Github Actions: Reusable Workflow とジョブ名

Github Actions のあるワークフローから別ファイル(別リポジトリでも可)のワークフローを呼び出せる Reusable Workflow を触ったところ、不便というかどう対処するべきかわからない点があったのでメモとして残しておく。

ワークフローで定義したジョブ名と実行履歴としてのジョブ名

以下の callee.ymlcaller.yml を例に考える。

name: callee
on:
  workflow_call:
jobs:
  greet:
    runs-on: ubuntu-latest
    steps:
      - name: say-hello
        run: echo hello job name is $JOB
        env:
          JOB: ${{ github.job }}
name: caller
on:
  push
jobs:
  call-reusable:
    uses: org/repo/.github/workflows/callee.yml@main

callee の中ではジョブ名は greet と定義しており、環境変数 JOB の値も greet となる。しかし、GithubREST API GET /repos/:org/:repo/actions/runs/:runId/jobs で取得できる実際に実行されたジョブ一覧では違う名前となる。

{
  "jobs": [
    {
      "id": xxx,
      "run_id": 1663652585,
      ...
      "name": "call-reusable / greet", <- 名前が変わっている
      "steps": [
        {
          "name": "say-hello",
          ...
        }
      ],
      ...

この例では .jobs[0].namegreet ではなく call-reusable / greet となる。つまり、<caller> / <callee> のようなフォーマットに変換される。

実際に遭遇したこと

Slack 通知を行う 8398a7/action-slack を Reusable Workflow の中で使った際にジョブ名やジョブ実行時間が表示されない問題に遭遇した。

action-slack は自身のジョブ情報を得るために GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs にリクエストし、github.job と一致するジョブを探していた。しかし、前述の通りこの2つは異なる値になるため、検索に失敗していた。一応検索に用いるジョブ名は input で渡せば回避可能ではある。しかし、呼び出す側がいちいち自分のジョブ名を渡すのはあまりにも冗長でダルい。

ひとまず / ${this.jobName} という後方一致でも検索するように PR を出したところ無事マージされた。

ただし、この修正は完全とは言えない。同名のジョブを含む複数の Reusable Workflow を呼び出すと検索が上手くいかないだろう(レアケースだとは思うが……)。

どうあるべきか

Github Actions 側で以下のどちらかの対応が入ればマシになると思われる

  • 変換後のジョブ名を取得するための context が追加される(例えば ${{ github.realJob }}
  • 実行毎のジョブIDを取得するための context が追加される(例えば ${{ github.job_id }}
    • ジョブIDがわかれば GET /repos/{owner}/{repo}/actions/runs/{run_id}/jobs/{job_id} から一発でジョブ情報を引ける

現状は残念ながらどちらも対応されてない……と思われる。後者だと検索自体が不要になるため望ましい。今提供されているブツでもっとスマートな方法があればぜひ知りたいところ。

8398a7/action-slack の入力定義を修正する PR を出した

Github Actions で Slack 通知を行う 8398a7/action-slack の入力定義を修正する PR を出した & マージされた。

修正内容は入力パラメータの誤った必須指定を直すだけの簡単なもの。最近使い始めた ワークフローの YAML の補完・lint を行ってくれる VSCode 拡張に無駄に怒られるのが気になってしょうがなかった。マージ後すぐに最新版をリリースしてもらえたので、平穏な気持ちでワークフロー盆栽を行える日々を取り戻せた。

ちなみに required: true な入力パラメータを省略してアクションを使用したとしても、Github Actions 上で動かす分には問題は起きない。@actions/core*1getInputaction.yml 内の宣言は特に解釈せず、呼び出し時に required を改めて指定するようになっている(実態は特定の命名規則環境変数の値を取り出すだけ)。

import { getInput } from '@actions/core'

const myParam = getInput('myParam', { require: true })

action.yml 内の宣言はあくまでドキュメント用ということなんだろうか。せっかく宣言させるのだから、実行時に validate してくれてもいいのではと思った。

*1:JavaScript アクション用に公式が提供している npm パッケージ

Go の os.ProcessState からプロセスを終了させたシグナルを取得する

備忘録。Go の os.StartProcess()os/exec.Cmd で実行した外部プロセスがシグナルによって終了した場合に、そのシグナルを取得する方法について。Go のバージョンは1.16。

注: GOOS=linux or GOOS=darwin で動作すること、および GOOS=windows で動作しないことを確認済み。他の環境は不明。

続きを読む

ESLint ルールを TypeScript で書く

備忘録。ESLint のルールを含むプラグインを TypeScript で書く時のポイントについて。

プラグインの仕組み自体は公式ドキュメントに従いつつ、TypeScript でどう対応させるかについて述べる。

続きを読む

gh コマンドのシェル補完を強化する PR を出した

Github 公式 CLI である gh コマンドに出した PR がマージされた。

内容は gh issue list/gh pr list--state オプションの値をシェル補完できるようにするというもの。

--state オプションに open, closed といったキーワードを与えると、表示する issue/PR を選択できる。しかし opened, close のような typo が多発していたので、シェル補完をできるようにしていた。

ghgithub.com/spf13/cobra を使っているので、固定値のオプションならシェル補完の追加は簡単にできる

しかし、gh ではオプション値のシェル補完はこれまで無く、PR を出すにしても実装の汎用性がどれくらい求められるかが不安だった。が、よく調べたら1ヶ月以内に別のオプションの値を補完する PR が出ていた。

特に凝った汎用化もなく、しかも PR 作成者はコミッタだったので、心置きなく自分も便乗(?)して Issue/PR を出すことができた。レビューでも特に指摘をされることはなく(むしろフォーマット統一までしてもらった)、無事にマージされた。

OSS に初 PR を出す時は、こういう「空気を読む」ような所作に結構コストがかかる。考えすぎなのかもしれないが。