Dependabotの作ったPRがSecretsにアクセスできないためにことごとく失敗していたのを修正しました。
SecretsにアクセスできないのはKeeping your GitHub Actions and workflows secure: Preventing pwn requestsで説明されているようにセキュリティ向上のためです。workflow_run
イベントでCheckを回すとワークフロー定義は常にデフォルトブランチのものが使われるため、PRでワークフローファイルが悪意を持って変更されてもマージしなければ悪影響を受けません。ので今後、基本的にはSecretsを必要とするワークフローはworkflow_run
イベントで回すことになります。
上記securitylab.github.comの記事で色々説明されていますが、わりと限定的なユースケースについて述べているので、ここでは自分のケースで必要だった知見についてまとめます。
actions/checkout ではrefプロパティを指定する
ソースコードをチェックアウトする場合、どのrefをチェックアウトするのかを明示的に示す必要があります。何も指定しない状態ではデフォルトブランチをチェックアウトしてしまうため、PRで変更する内容をテストできません。
on: workflow_run: workflows: - build types: - completed jobs: integration-test: runs-on: ubuntu-latest if: github.event.workflow_run.conclusion == 'success' steps: - uses: actions/checkout@v2 with: ref: ${{ github.event.workflow_run.head_sha }}
Pull RequestのChecksを登録する際もshaを指定する
この「何もしなければデフォルトブランチの最新refが対象になる」のが曲者です。例えばChecksに結果を反映する際も、明示的にshaを指定する必要があります。
- uses: LouisBrunner/checks-action@v1.1.2 if: always() with: token: ${{ secrets.GITHUB_TOKEN }} name: integration-test sha: ${{ github.event.workflow_run.head_sha }} conclusion: ${{ job.status }} details_url : https://github.com/${{github.repository}}/actions/runs/${{github.run_id}}
Secretsなしでもテストできるようにする
すべてのテストをworkflow_run
の方に寄せても良いですが、Secretsなしでも実行できる単体テストや静的解析はpull_request
で実行してしまったほうが良いかもしれません。
その場合は、./gradlew build
や npm run all
がSecretsなしでも正常ステータスコードで完了する必要があります。
JUnitならassumptionsでTokenがあるか確認して無ければテスト実行をスキップすればいいでしょう。Jestではうまい方法が見つからなかったので、Tokenの有無でtest
とtest.skip
を呼び分けることにしました。
const token = process.env.GITHUB_TOKEN || '' const integrationTest = token ? test : test.skip integrationTest('fork() does nothing if the forked repo already exists', async () => { ... })