没用的前言
最近做了一个AI安全会议的倒计时网站,核心思想类似MVVM:开发者维护一份人类可读的yml,网站则根据这些yml生成对应HTML。开发和维护都比较友好,构建也有脚本自动化
$dest_dir = './public'
$dest_dir = Join-Path $dest_dir 'conference'
New-Item -Type dir $dest_dir -Force
Copy-Item -Path './conference/types.yml' -Destination (Join-Path $dest_dir 'types.yml') -Force
$all_yml = Get-Content './conference/*/*.yml' -Encoding UTF8
Set-Content -Path (Join-Path $dest_dir 'allconf.yml') $all_yml -Encoding UTF8 -Force
$updated_by = git config user.name
$updated_by = $updated_by.trim()
$last_updated = Get-ChildItem -Path(Join-Path $dest_dir 'allconf.yml') | select LastWriteTimeUtc
$content = "$($last_updated.LastWriteTimeUtc),$($updated_by)"
Set-Content -Path (Join-Path $dest_dir 'last_updated.json') $content -Encoding UTF8 -Force
Write-Host $content
唯一剩下的麻烦只有下部署了:
- 人肉拷贝
dist文件夹到Github Pages的仓库 - commit
- 推送到origin
虽说这也不麻烦,但在全自动化的Pipeline中这需要人力的过程显得那么格格不入。正好Github Actions提供了可编程的接口,强迫症患者终于有救了:
Automate, customize, and execute your software development workflows right in your repository with GitHub Actions. You can discover, create, and share actions to perform any job you’d like, including CI/CD, and combine actions in a completely customized workflow.
Github Actions、Powershell与环境变量
自动化部署的脚本原作者已经写了一份,我只要稍作修改即可。更具体一些,我需要做的事情如下:
- 更新
git config user.name,以便上文中构建脚本$updated_by = git config user.name能够获得作者信息 - 以我的身份推送
dist到origin
两者都可通过“环境变量”取得:
- 作者信息由
github.actor环境变量给出 - Github secrets指出,Token由
secrets.*环境变量给出
这简单,我马上在powershell中引入了这些变量
- name: Setup Authors
run: |
git config --global user.name $env:github.actor
- name: Deploy
run: |
...
git init
git commit -m ...
git push --force https://${env:secrets.ACCESS_TOKEN}@github.com/
...
然而事与愿违,Github Actions挂在Deploy,报错如下
*** Please tell me who you are.
fatal: unable to auto-detect email address
怀疑Setup Authors未成功执行,打印:
> Write-Host $env:github.authors
>
$env:github.authors是空的,怪不得git会报错
查文档,官方的语法是这样的
${{variable_name_here}}
虽然和powershell的语法完全不一样,但改了试试看吧
- name: Setup Authors
run: |
git config --global user.name ${{github.actor}}
- name: Deploy
run: |
...
git init
git commit -m ...
git push --force https://${{secrets.ACCESS_TOKEN}}@github.com/
...
修改后运行,成功
这是咋回事?
原因分析
一番瞎猜后,我认为官方文档里提到的“环境变量”和powershell的“环境变量”并非是同一回事。即,官方文档里的“环境变量”是针对github actions的。
举个例子
- name: Deploy
run: |
...
git init
git commit -m ...
git push --force https://${{secrets.ACCESS_TOKEN}}@github.com/
...
Github Actions的运行引擎看到run字句,知道后面的内容应该被当作shell脚本被对待。接下来会根据runs-on和shell选项调用特定的shell来执行脚本。但是在调用shell之前,它检查run字句的内容,若有
${{variable_name_here}}的环境变量访问,则将这部分内容替换为实际值,结束后再交给shell运行。这个过程直接替换了脚本的内容,与shell的类型、访问环境变量的语法都无关
如果使用特定shell的写法(如$env:blah),则环境变量不会由运行引擎不会注入,这些环境变量shell自身也没有,当然是空了。