Powershell、Github Actions、环境变量踩坑

  1. 1. 没用的前言
  2. 2. Github Actions、Powershell与环境变量
  3. 3. 原因分析

没用的前言

最近做了一个AI安全会议的倒计时网站,核心思想类似MVVM:开发者维护一份人类可读的yml,网站则根据这些yml生成对应HTML。开发和维护都比较友好,构建也有脚本自动化

1
2
3
4
5
6
7
8
9
10
11
12
13
$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

唯一剩下的麻烦只有下部署了:

  1. 人肉拷贝dist文件夹到Github Pages的仓库
  2. commit
  3. 推送到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与环境变量

自动化部署的脚本原作者已经写了一份,我只要稍作修改即可。更具体一些,我需要做的事情如下:

  1. 更新git config user.name,以便上文中构建脚本$updated_by = git config user.name能够获得作者信息
  2. 以我的身份推送dist到origin

两者都可通过“环境变量”取得:

  1. 作者信息由github.actor环境变量给出
  2. Github secrets指出,Token由secrets.*环境变量给出

这简单,我马上在powershell中引入了这些变量

1
2
3
4
5
6
7
8
9
10
- 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,报错如下

1
2
*** Please tell me who you are.
fatal: unable to auto-detect email address

怀疑Setup Authors未成功执行,打印:

1
2
> Write-Host $env:github.authors
>

$env:github.authors是空的,怪不得git会报错
查文档,官方的语法是这样的

1
${{variable_name_here}}

虽然和powershell的语法完全不一样,但改了试试看吧

1
2
3
4
5
6
7
8
9
10
- 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的。

举个例子

1
2
3
4
5
6
7
- name: Deploy
run: |
...
git init
git commit -m ...
git push --force https://${{secrets.ACCESS_TOKEN}}@github.com/
...

Github Actions的运行引擎看到run字句,知道后面的内容应该被当作shell脚本被对待。接下来会根据runs-onshell选项调用特定的shell来执行脚本。但是在调用shell之前,它检查run字句的内容,若有
$的环境变量访问,则将这部分内容替换为实际值,结束后再交给shell运行。这个过程直接替换了脚本的内容,与shell的类型、访问环境变量的语法都无关

如果使用特定shell的写法(如$env:blah),则环境变量不会由运行引擎不会注入,这些环境变量shell自身也没有,当然是空了。