GitHub Actions环境变量

2020年4月29日


GitHub Actions有多种环境变量:workflow环境的变量、job环境的变量、step环境的变量,以及每台电脑都有的操作系统的环境变量、shell环境变量。在GitHub Actions文档中,workflow环境的变量、job环境的变量、step环境的变量的英文为env,我将其不正规地称为“大环境变量”;操作系统的环境变量、shell环境变量的英文为environment variables

因为https://help.github.com/cn/actions/reference/workflow-syntax-for-github-actions翻译不完全,本文多采用英文术语或参考《GitHub Actions 入门教程》的翻译。

操作系统的环境变量是Windows命令提示符用的cd /d %appdata%、Linux bash用的echo $whatever里面的变量。在GitHub Actions,除了访问操作系统定义的常见环境变量,action和你自己还可以定义新的环境变量。定义环境变量的方法跟在正常操作系统里一模一样。

jobs:
  build:
    runs-on: ubuntu-18.04
    steps:
    - run: |
        x=1
        y=2
        echo $x+$y

代码定义了两个bash环境变量(“(Bash is) The default shell on non-Windows platforms[1]),然后把它们相加。输出值是1+2,因为我们没有进行算术运算(算术运算需要((x+y))[2])。代码的运行结果在https://github.com/gqqnbig/github-actions-demo/runs/631610823#step:2:6

“Each step runs in its own process in the runner environment”[3],所以上一个步骤设置的shell环境变量不能带到下一个步骤使用。《Using environment variables》提到工作流命令set-env可以提升环境变量到大环境变量。

jobs:
  build:
    runs-on: ubuntu-18.04
    steps:
    - name: 设置shell环境变量
      run: |
        x=1
        y=2
        echo $x+$y
        echo "::set-env name=z::$x+$y"
    - name: 读取上一步的环境变量
      run: |
        echo $z

代码有两个步骤,且为了方便区分,我添加了name键(在YAML,冒号前那个东西叫做键(key[4])。如果不用name,GitHub会用run的第一行作为name。从 https://github.com/gqqnbig/github-actions-demo/runs/631732869#step:3:6 可以看到,步骤“读取上一步的环境变量”成功读取了上一步设置的变量z。

有时候需要有条件地执行某些步骤,参考《Workflow syntax for GitHub Actions》得知step下可以写if语句。

steps:
- name: 设置shell环境变量
  run: |
    x=1
    y=2
    let z=x+y
    echo "::set-env name=z::$z"
- name: 条件执行1
  if: env.z > 2
  run: |
    echo $z
- name: 条件执行2
  if: env.z > 3
  run: |
    echo $z

代码定义了三个步骤,第一步设置shell环境变量,并把它提升为大环境变量。第二、三步测试该大环境变量,进行条件执行。从日志https://github.com/gqqnbig/github-actions-demo/runs/631759950可以看到,条件执行1执行了,条件执行2(我猜因为不满足if语句)被跳过。

实例挑战

GitHub Actions除了可以像上面这样手动编写语句,还可以调用别人写好的语句。别人写好的语句,类似类库,叫做GitHub Action,注意没有s,简称action。就像类库方法,action一般会接受参数,用with键传入。

例1

最著名的action应该是checkout,一般用来检出本仓库代码。它还可以检出别人的代码,用with.repository指定。

steps:
- name: 选择项目
  run: |
	# 不能用let index=(RANDOM % 4)
	# 如果右值是0,那么let的退出码就是1,bash就直接终止了。
	index=$((RANDOM % 4))
	arr=(github-actions-demo advanced-play-search uMatrixCleaner)
	targetRepo=${arr[index]}
	if [[ ${targetRepo} ]]; then
	  echo "将会检出${targetRepo}"
	  echo "::set-env name=targetRepo::$targetRepo"
	else
	  echo "没有选中任何项目"
	fi
- name: 检出项目
  if: ${{ env.targetRepo }}
  uses: actions/checkout@v2.1.0
  with:
	repository: gqqnbig/${{ env.targetRepo }}
	path: targetRepo
- name: 检查日志
  if: ${{ env.targetRepo }}
  run: |
	cd ${GITHUB_WORKSPACE}/targetRepo
	git log -1
:随机检出一个仓库

代码有三个步骤。步骤一读取bash变量RANDOM获得一个[0,3]范围的随机数,选择要检出哪个仓库,并把环境变量targetRepo的值通过工作流命令set-env设置为大环境变量env.targetRepo的值。步骤二先检查大环境变量targetRepo,若不为空,则传递给actions/checkoutrepository参数。

代码的其中一次执行日志可见https://github.com/gqqnbig/github-actions-demo/runs/632003219

代码同时显示了,GitHub Actions目前不支持伪代码的想法;每个需要条件执行的步骤必须自带if键。

if(xxx) {
  步骤1
  步骤2
}
else {
  步骤3
  步骤4
}

例2

Using environment variables》列出了不少环境变量,如GITHUB_WORKSPACE是GitHub Actions的工作目录。这篇文章的标题已经提醒了我们,文章里列出的都是环境变量,不是大环境变量

参考资料

  1. . Workflow syntax for GitHub Actions. . [2020-04-29].
  2. . GNU Bash Reference Manual. . [2020-04-29].
  3. . Workflow syntax for GitHub Actions. . [2020-04-29].
  4. . YAML Ain’t Markup Language (YAML™) Version 1.2. . 2009-10-01 [2020-04-29].