我的工作流程如下所示:
name: Site - Build and Deploy FTP
on:
push:
branches: main
paths:
- 'src/Site/Site/**'
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/[email protected]
- name: Setup .NET Core
uses: actions/setup-dotnet@v4
with:
dotnet-version: '6.0.x'
include-prerelease: true
- name: Install dependencies
working-directory: src/Site/Site
run: dotnet restore
- name: Build with dotnet
working-directory: src/Site/Site
run: dotnet build --configuration Release
- name: Publish
working-directory: src/Site/Site
run: dotnet publish -c Release -o ${{env.DOTNET_ROOT}}/myapp
#substitute production appsettings entries to temp json file
- name: App Settings Variable Substitution
shell: bash
run: |
cat ${{env.DOTNET_ROOT}}/myapp/appsettings.json | jq --arg my_secret ${{secrets.SQL_CONNECTION_STRING}} --arg email_secret ${{secrets.EMAIL_PASSWORD}} '.Config.SiteDb = $my_secret | .Config.EmailPassword = $email_secret' > newfile.json
直到两周前它才开始在替代应用程序设置步骤上失败。奇怪的是我没有改变工作流程中的任何内容。另外,我对项目的另一部分有一个几乎相同的工作流程,每次都会成功(.yml 文件中的唯一区别是它在不同的项目上运行,并从自己的 appsettings.json 文件中替换出不同的设置。)它将失败并显示 127 错误代码,但 cat 命令会将 appsettings.json 文件写入控制台,因此它可以正确找到该文件,因此它一定是 jq 命令有问题。
我尝试删除 --arg 选项和替换过滤器,并将其替换为“jq '.'”,并且成功了。然后,我尝试执行“jq '.Config.SiteDb = 5 | .Config.EmailPassword = 9'”,结果成功了。所以看起来 --arg 的某些东西弄乱了这个特定的跑步者?
当您在 Github Actions 的 shell 脚本中展开这样的变量时,它们会被 shell 完全解释,就像您输入了这些字符一样。
#substitute production appsettings entries to temp json file
- name: App Settings Variable Substitution
shell: bash
run: |
cat ${{env.DOTNET_ROOT}}/myapp/appsettings.json | jq --arg my_secret ${{secrets.SQL_CONNECTION_STRING}} --arg email_secret ${{secrets.EMAIL_PASSWORD}} '.Config.SiteDb = $my_secret | .Config.EmailPassword = $email_secret' > newfile.json
这意味着变量中可能被 shell 解释的任何字符都会导致问题:
>
和 <
可能被视为重定向。|
可以被视为管道步骤。您的示例的行为会有所不同,具体取决于密码中恰好包含哪些字符。
如果你可以保证字符串不包含单引号和换行符,你可以用单引号括起来。
在大多数情况下,更好的选择是引入环境变量。所以,尝试这样的事情:
#substitute production appsettings entries to temp json file
- name: App Settings Variable Substitution
shell: bash
run: |
cat ${{env.DOTNET_ROOT}}/myapp/appsettings.json | jq --arg my_secret "$SQL_CONNECTION_STRING" --arg email_secret "$EMAIL_PASSWORD" '.Config.SiteDb = $my_secret | .Config.EmailPassword = $email_secret' > newfile.json
env:
SQL_CONNECTION_STRING: ${{secrets.SQL_CONNECTION_STRING}}
EMAIL_PASSWORD: ${{secrets.EMAIL_PASSWORD}}
这次,扩展是由 shell 完成的,而不是由 GHA 完成的,因此它不会将字符串的内容重新解释为 shell 字符。
这样做的一个缺点是环境变量对于 shell 中启动的每个进程都是可见的。如果这是不可接受的,您可以使用 bash 的
export -n VARIABLENAME
来启动脚本,从环境中删除这些变量,同时将它们保留为 shell 变量。