t28.dev

GitHub Actions のカスタムシェルで zx を実行して shell から逃げる

2024/9/25
Tech

Github Actions で シェルスクリプトを書く機会がどんどん増えた結果、「書くときも、読むときも、辛すぎ…」ってなった🥺

処理の流れを把握するためにかなり細かく変数を定義したり、ロジック以外の文法に関する補足までコメントに書きまくることで、 やっと後で読み返しても困らない (辛くないとは言っていない) 状態になるのはあまりにも不便。 一番慣れている言語 (JavaScript) で書けた方が絶対良いので…書く!!

シェルスクリプトに慣れろよ!っていう話は置いておいちゃう

カスタムシェル

GitHub Actions は shell キーワードで内部で実行されるコマンドを制御することが出来る。

デフォルトだと bash -e {0} が実行される。 公式ドキュメントの説明が見つけられないけれど、 {0}run キーワードに記述したスクリプトが書き込まれた一時ファイルのパスが入ることが 👇️ のような step で分かる。

ref: Display executed script file name step

steps:
  - name: Display executed script file name
    run: echo "$0"
# /home/runner/work/_temp/e45dc7a6-bed6-437b-9414-87a0d70764e2.sh が出力される

shell キーワードに任意のコマンドを設定する (カスタムシェル)ことで、 run キーワードの処理のために内部で実行されるシェルコマンドを変更することが出来る。

ドキュメントの例だと、perl を実行している。

steps:
  - name: Display the environment variables and their values
    shell: perl {0}
    run: |
      print %ENV

カスタムシェルで Node.js を実行する

ubuntu-latest ランナーでは Node.js が最初からインストールされているので、shell キーワードで node コマンドを実行すれば run キーワード内で直接 JavaScript を書くことが出来る!

- name: Run with Node.js
  shell: node {0}
  run: |
    console.log(process.env);

# {
#   VCPKG_INSTALLATION_ROOT: '/usr/local/share/vcpkg',
#   GOROOT_1_22_X64: '/opt/hostedtoolcache/go/1.22.7/x64',
#   (略)

カスタムシェルで zx を実行する

GitHub Actions 内でシェルを書くときはファイルシステムにアクセスしたり、他のコマンドを実行したりすることが多いので、 素の Node.js ではなく zx に実行してもらいたみが深い。

- name: Run zx
  shell: npx zx {0}
  run: |
    const branch = await $`git branch --show-current`
    echo`Current branch is ${branch}.`

# Current branch is main.

気になったこと

シンタックスハイライト

シェルスクリプトでも同じだけれど、YAML のブロックコンテンツに JavaScript を書くとシンタックスハイライトが効かない。 エディターによってはいい感じになるのかな?と調べてみた。

IDEA

標準の機能として提供されていた、さすがだ -> 言語インジェクション

VS Code

拡張機能があった -> YAML Embedded Languages

IDEA と mark が違うけど…🥺

npx で zx を毎回ダウンロードしている

速度の観点では大したことない (多分) けれど、実行の度に npx が zx をダウンロードしていることが気になっていたら、 同じことを考えている人がいたactions/setup-node で “npm のキャッシュ” をキャッシュするために、 キャッシュのキーとして package-lock.json の代わりにワークフローのファイルを使っている。

真似してやってみた。

- uses: actions/setup-node@v4
  with:
    node-version: "22"
    cache: "npm"
    cache-dependency-path: ".github/workflows/shell.yml"

1回目:

setup-node 時にキャッシュがないので、

npm cache is not found

npx 実行時にダウンロードするよ〜って言われる。

npm warn exec The following package was not found and will be installed: [email protected]
Current branch is main.

2回目:

キャッシュが見つかったみたい!

Cache restored successfully

キャッシュがあるので npx がダウンロードしたログを出していない ✌️

Current branch is main.

キャッシュする場合は、zx のバージョンも指定した方が良さそう。

- name: Run zx
  shell: npx [email protected] {0}
  run: |
    const branch = await $`git branch --show-current`
    echo`Current branch is ${branch}.`