Github Actions手習い
ERROR: invalid tag "/ritalin/duckdb-extract-placeholder:main": invalid reference format
Error: buildx failed with: ERROR: invalid tag "/ritalin/duckdb-extract-placeholder:main": invalid reference format
ってなった。前途多難。
直しつつ毎度プッシュするのは辛いなぁって思ってたら、ローカルで試せるnektos /act
なるものがあるらしい。
dockerくん使わなくなっててサービス止めてたわ。うっかりうっかり
Error: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
docker起動し直して、ローカルレポジトリのルートでact
叩いたら少し進展した。
なんかエラーが出た。
##[error]Parameter token or opts.auth is required
Github Action
が自動で引き渡すトークンを指定しなきゃらしい
引数で渡せるとおあるのでこれを試してみる
そのまえに、gh
持ってなかったから、こいつの初期設定から。
$ gh issue list
To get started with GitHub CLI, please run: gh auth login
まずログインね
gh auth login
対話モードになるので指示に従って進める。
Fine-grained personal access tokens使うようにしたらgit pushできなくなったお
ChatGPT先生曰く、今までは自動切り替えでうまくやってくれてたのかもって
トークンの自動切り替え(Token auto-rotation):
GitHubはセキュリティを強化するため、古い認証トークン(classic personal access token)を自動的に新しいタイプのトークン(Fine-grained personal access token)に切り替える仕組みを導入している場合があります。これにより、以前は classic personal access token を使っていた場合でも、GitHubが自動的に新しいタイプのトークンを使うように設定されている可能性があります。
APIキー取得のためだけに一切の権限なしでFine-grained personal access tokens
作ったもんだから、自動切り替えが働かなくなったかもって。
とりあえず、Fine-grained personal access tokens
のRepository permissions
の設定が、
Read access to metadata
Read and Write access to code, commit statuses, pull requests, and workflows
となるようスコープを付与したら、push
はできた。
有効期限がどう影響するかは様子見で。
再開
act -s GITHUB_TOKEN="$(gh auth token)"
予定通り(?)のエラーが表示された。
しょうもないミスだった。
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
と指定しているが、REGISTRYを設定してなかった。
そりゃだめだ。
alpineのapkが失敗する・・・
RUN echo "@edge-community https://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories
RUN apk add --no-cache zig@edge-community~=0.13.0
結局、Dockerfile
に書くのやめて、Actions
のyml
にベタ書きしたら通った。
しょうもない記述ミスで難儀はしたが・・・
-
sudo apt update
してなかったとか
落ち穂拾い
異なるプラットホーム向けのビルド
jobs:
build:
name: Build on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: [14.x, 16.x]
# (snip)
のように、matrix
として記述する。(CharGPT先生より)
タスクのサブコマンドもマトリックスにしたい
追記すれば良い
# (snip)
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
node-version: [14.x, 16.x]
+ command: [test, build]
# (snip)
step:
- name: Run npm command
run: npm run ${{ matrix.command }}
異なるプラットホームで異なるパッケージマネージャーを使いたい
プラットホームをマトリックスとして記述した上で、各step
ディレクティブ、if
でレクティブを使って書き分ける。
# (snip)
step:
- name: Install dependencies on Ubuntu
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y some-linux-package
- name: Install dependencies on macOS
if: runner.os == 'macOS'
run: |
brew update
brew install some-macos-package
- name: Install dependencies on Windows
if: runner.os == 'Windows'
run: |
choco install some-windows-package
# (snip)
ビルドジョブの最後でアップロード
# OSごとにアーティファクトをアップロード
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: ${{ matrix.os }}-build-artifacts-${{ matrix.node-version }}
path: ./dist/${{ runner.os }}/ # OSごとに適切なパスを指定
リリースジョブで各アーティファクトをダウンロード
release:
name: Create Release
runs-on: ubuntu-latest
needs: build
steps:
- name: Checkout code
uses: actions/checkout@v2
# OSごとにアーティファクトをダウンロード
- name: Download artifacts
uses: actions/download-artifact@v2
with:
name: ubuntu-latest-build-artifacts-14.x # ビルドしたプラットホームとバージョン
path: ./dist/ubuntu-latest/ # ダウンロード先のパスを指定
# (snip)
ダウンロードしたアーティファクト使ってリリース
# ダウンロードしたアーティファクトを使用してリリースを作成する手順を追加
- name: Create GitHub Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: false
aptでインストールしたパッケージの確認
- パス - dpkg -L <PACKAGE>
- 利用可能バージョン - apt-cache showpkg <PACKAGE>
wgetで持ってきて、unzipして配置してた時の名残
- name: Install libduckdb
run: |
mkdir /tmp/duckdb
sudo mkdir -p /usr/local/duckdb/lib
sudo mkdir -p /usr/local/duckdb/include
wget -nv -O /tmp/duckdk.zip https://github.com/duckdb/duckdb/releases/download/v1.0.0/libduckdb-linux-amd64.zip
unzip /tmp/duckdk.zip -d /tmp/duckdb
echo "check duckdb include (from)"
ls -ld /tmp/duckdb/*
sudo mv /tmp/duckdb/lib* /usr/local/duckdb/lib/
sudo mv /tmp/duckdb/*.h /tmp/duckdb/*/*.hpp /usr/local/duckdb/include/
nektos /actでローカルでビルドしたdockerイメージをruns-onとして使用する
actのCLI引数として、-P <NAME>=<IMAGE>
を指定する
ここで
- NAME -
run-on
に指定する名称。例えばubuntu-latest
- IMAGE -
docker build
で指定したイメージ名
ただし-P
オプションはrun-on
にしか作用しない。
Actions
はubuntu
固定のため、現実問題を解決しない。
ビルドしたイメージの使用を強制する(dockerhub
からpull
しない)のならpull=false
も併せて指定も有効。
-
pull=false
オプションはcontainer
セクションにも反映される。
dockerのマルチステージビルドの勘所
- 1st stage: パッケージマネージャによる依存パッケージの構成
- 2st stage: build構成(confihure)とbuildの実行(
cmake --build
) - 3rd stage: build成果物のインストール(
cmake --install
) - last stage:
3rd stage
の成果物から新しいイメージを作る
dockerの特定のステージのキャッシュを無効化
任意のステージで
-
ARG CACHE_BUST=1
のようなダミーの引数を割り当てる -
docker --build-arg CACHE_BUST=$(date +%s) ...
のように実行するたびに値を指定する
毎度引数の値が変更されることでキャッシュを無効化したのと同様の効果を得られる。
docker buildで実行中のログを出す
docker build --progress=plain ...
nektos/act 下でcontainerセクションのシミュレーションでエラー
mkdir /host_mnt/Users/xxxx/.docker/run/docker.sock: operation not supported
のようなエラーが出た場合の対処
-
docker context ls
でソケットを確認する -
desktop-linux *
のendpoint
からunix://
を除いたパスで、/var/run/docker.sock
のシンボリックリンクを作る
sudo ln -s /var/run/docker.sock <desktop-linux *のendpoint>
see aldo: https://outatime.dev/notes/using-act-to-run-github-actions-locally/
クロスプラットホームのビルド
単純なケースではmatrix
を使うのが楽
プラットホーム間で依存パッケージのABIが異なる場合、matrix
では面倒。
素直にプラットホームごとにジョブを分けたほうがいい。
分け方は
- 1つの構成ファイルに両方のジョブを定義する
- プラットホームごとに構成ファイルを用意する
いずれの場合も独立に別プロセスで並行してビルドが実行される。
mlugg/setup-zigでエラー
以下のメッセージが出た場合
Error: Path Validation Error: Path(s) specified in the action for caching do(es) not exist, hence no cache is being saved.
use-cache: false
を付与すると解決するとのこと
see also: https://github.com/mlugg/setup-zig/issues/8#issuecomment-2255600521
dockerのマルチステージビルドのキャッシュされたステージに入りたい
そのままでは無理
docker build --target <ステージ名> -t <イメージ名> .
とすると、キャッシュしたステージをエクスポートでくる。
あとはコンテナ起動して入るだけ。
docker run -it <イメージ名> /bin/bash
nektos/actでcontainerセクションを使用する
環境変数はcontainer.env
にまとめておくとスッキリする。
起動は以下
act -P ubuntu-latest=ghcr.io/catthehacker/ubuntu:act-latest -s GITHUB_TOKEN="$(gh auth token)"
マルチステージビルドで前ステージでインストールしたパッケージを次ステージにコピーする
homebrew
(linuxbrew
)はインストールしたパッケージを/<PREFIX>/Celler/<PACKAGE>/<VERSION>
にインストールし、/<PREFIX>/opt/<PACKAGE>
にシンボリックリンクを作成する。
次ステージで
COPY from=prev_stage /<PREFIX>/opt/<PACKAGE>/. /path/to/<PACKAGE>
とできれば、バージョンを意識する必要がなくなるため楽できるのだが、
シンボリックリンクはシンボリックリンクのままコピーしてしまうため、このままでは想定通りに動かない。
回避策として、前ステージでrsync
を使用して/<PREFIX>/opt/<PACKAGE>
のシンボリックリンクを解決してしまう方法が挙げられる。
どうせ前ステージで捨ててしまうので上書きてしまっても、さして影響はないという考え。
# 一旦シンボリックリンクを解決しつつtmpにコピー
RUN rsync -aL /<PREFIX>/opt/<PACKAGE> /tmp/
# 書き戻す
RUN rsync -a --delete /tmp<PACKAGE> /<PREFIX>/opt
コピーする際は、依存パッケージも同様の作業を行うこと(ビルドの際にリンクエラーになる)
タグからバージョンを抽出
例えばv1.2.3
というタグを付与したとする。
ここから1.2.3
を抽出したいというケース。
name: Extract version
id: extract_version
run: |
VERSION = ${GITHUB_REF#refs/tags/v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
ここで、${GITHUB_REF#refs/tags/v}
はシェルスクリプトの機能で、#
以降の文字列を除去して返す物。
GITHUT_OUTPUT
環境変数に割り当てられたファイルパスにリダイレクトすると、後続のステップで
${{ steps.extract_version.outputs.version }}
で取得できる。
ジョブ間で環境変数を引き継ぐ
ただし$GITHUB_OUTPUT
はジョブごとにリセットされるため、この方法でだけでは別ジョブに引き継げない。
回避策として、
- 環境変数を別ファイルにリダイレクト
-
actions/upload-artifact
でアップロード - 別ジョブで、
actions/download-artifact
で展開 -
source
コマンドでファイルを読み、環境変数としてロード -
$GITHUB_OUTPUT
にリダイレクト
これで、${{ steps.extract_version.outputs.version }}
を介して値が読める
#1
echo "version=$VERSION" | tee other-info.txt $GITHUB_OUTPUT > /dev/null
#2
uses: actions/upload-artifact
name: other-info
path: other-info.txt
#3
uses: actions/download-artifact
name: other-info
path: other-info.txt
#4
source other-info/other-info.txt
#5
echo "version=$version" >> $GITHUB_OUTPUT
nektos/actで特定ワークフローの特定ジョブを実行する
- ワークフローの指定
-
-W <PATH>
で指定する - ヘルプには
path to workflow file(s) (default "./.github/workflows/")
とあり、一見ルートフォルダを指定するオプションのようにみえるが、ワークフローファイルのパスも指定できる模様
-
- ジョブの指定
-
-j <JOB>
で指定する
-
例:
act -W foo.yaml -j build ...
nektos/actでリリース成果物生成のシミュレーション
リリース成果物を作成する際、actions/upload-artifact
とactions/download-artifact
を使うことになるが、保存先がクラウドのストレージに向かっているためそのままではシミュレーションできない。
その際、--artifact-server-path <PATH>
オプションを指定することで、保存先を変更できる
参照:
nektos/actでリリースタグを指定したシミュレーション
nektos/act
はカレンとブランチでシミュレーションを走らせるため、$GITHUB_REF
にはrefs/heads/main
のようになる。
これではタグからバージョンを抽出するようなことができなくなる。
回避策として、nektos/act
のenv
オプションで強制的に差し替える
act --env GITHUB_REF=refs/tags/v1.2.3 ...
nektos/actでのactions/upload-artifact@v4に関するバグ
ctions/upload-artifact@v4
でアップロードするファイルサイズが8MB
を超えるとチェックサムを正しく計算できなくなるバグが存在する。
v0.2.64
で存在を確認。
現在は修正されており、v0.2.69
では問題なくアップロードできることを確認している。