From be690cf1a07fc0b2a2cb7736563759153fec864c Mon Sep 17 00:00:00 2001 From: Masakuni Kato <7091+mackato@users.noreply.github.com> Date: Wed, 3 Jun 2026 22:32:49 +0900 Subject: [PATCH] =?UTF-8?q?ghas-setup:=20=E6=97=A2=E5=AD=98=20config=20loo?= =?UTF-8?q?kup=20=E3=81=AE=20--slurp+--jq=20=E4=BD=B5=E7=94=A8=E3=82=A8?= =?UTF-8?q?=E3=83=A9=E3=83=BC=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gh api は `--slurp` を `--jq` と併用できず("the --slurp option is not supported with --jq or --template")、本適用の冪等 lookup が実行時に失敗して いた。--slurp をやめ、--paginate でページごとに --jq を適用して一致 id を出し、 複数行になっても先頭行のみ採用する(head パイプを使わないため SIGPIPE + pipefail での誤失敗も起きない)。 bats の gh スタブが実 gh のフラグ制約を再現しておらず見逃したため、スタブ側で `--slurp` + `--jq` 併用を非 0 終了として再現し、同種 regression を検知できる ようにした。 Co-Authored-By: Claude Opus 4.8 --- devbox.lock | 96 +++++++++++++++++++++++++++ pkgs/ghas-setup/ghas-setup | 13 ++-- pkgs/ghas-setup/tests/ghas-setup.bats | 22 ++++-- 3 files changed, 121 insertions(+), 10 deletions(-) diff --git a/devbox.lock b/devbox.lock index 5e86c61..3c374e7 100644 --- a/devbox.lock +++ b/devbox.lock @@ -97,6 +97,54 @@ } } }, + "gh@2": { + "last_modified": "2026-05-21T08:15:18Z", + "resolved": "github:NixOS/nixpkgs/4a29d733e8a7d5b824c3d8c958a946a9867b3eb2#gh", + "source": "devbox-search", + "version": "2.92.0", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/2wapk3dm2magc0lq8rx8yd5pam3xlacw-gh-2.92.0", + "default": true + } + ], + "store_path": "/nix/store/2wapk3dm2magc0lq8rx8yd5pam3xlacw-gh-2.92.0" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/63sx2manc3ny8l4zzppcvz9292vi3044-gh-2.92.0", + "default": true + } + ], + "store_path": "/nix/store/63sx2manc3ny8l4zzppcvz9292vi3044-gh-2.92.0" + }, + "x86_64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/arfkhrr2bcmdrg6ncgnk6vaqx6qfv3vl-gh-2.92.0", + "default": true + } + ], + "store_path": "/nix/store/arfkhrr2bcmdrg6ncgnk6vaqx6qfv3vl-gh-2.92.0" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/d0r9xzcpv8xcjds6z1w03wyqi6iv30af-gh-2.92.0", + "default": true + } + ], + "store_path": "/nix/store/d0r9xzcpv8xcjds6z1w03wyqi6iv30af-gh-2.92.0" + } + } + }, "git@2": { "last_modified": "2026-05-21T08:15:18Z", "resolved": "github:NixOS/nixpkgs/4a29d733e8a7d5b824c3d8c958a946a9867b3eb2#git", @@ -496,6 +544,54 @@ "store_path": "/nix/store/v5wmprihi3ywkh9ksdvwgiixrxj29r66-statix-0-unstable-2026-05-14" } } + }, + "yq-go@4": { + "last_modified": "2026-05-21T08:15:18Z", + "resolved": "github:NixOS/nixpkgs/4a29d733e8a7d5b824c3d8c958a946a9867b3eb2#yq-go", + "source": "devbox-search", + "version": "4.53.2", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/ffkx6855qiv6004asmckjqwcq6dvc32q-yq-go-4.53.2", + "default": true + } + ], + "store_path": "/nix/store/ffkx6855qiv6004asmckjqwcq6dvc32q-yq-go-4.53.2" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/3hsajqhhm8m9nx306jh09m1qz4idwmxk-yq-go-4.53.2", + "default": true + } + ], + "store_path": "/nix/store/3hsajqhhm8m9nx306jh09m1qz4idwmxk-yq-go-4.53.2" + }, + "x86_64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/mh9wimc8ddgqag0ma18izcd08bkldk1a-yq-go-4.53.2", + "default": true + } + ], + "store_path": "/nix/store/mh9wimc8ddgqag0ma18izcd08bkldk1a-yq-go-4.53.2" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/pibhm258wp416plqdaxym4z6lis8ksla-yq-go-4.53.2", + "default": true + } + ], + "store_path": "/nix/store/pibhm258wp416plqdaxym4z6lis8ksla-yq-go-4.53.2" + } + } } } } diff --git a/pkgs/ghas-setup/ghas-setup b/pkgs/ghas-setup/ghas-setup index 78369fd..aa5dff9 100755 --- a/pkgs/ghas-setup/ghas-setup +++ b/pkgs/ghas-setup/ghas-setup @@ -108,12 +108,13 @@ gh auth status -h github.com 2>&1 | grep -q "admin:org" || { echo "==> $ORG org の code security configuration を有効化します" # 既存 configuration を name で lookup(冪等化のため)。configuration が 30 件(既定 per_page)を -# 超えても取りこぼさないよう --paginate で全件取得する。--slurp で全ページを 1 つの配列にまとめ、 -# jq 側で最初の一致 id を取り出す(`| head -n1` だと pagination 途中で stdout が閉じ、gh が SIGPIPE -# で非 0 終了して set -o pipefail がスクリプト全体を落としうるため使わない)。 -# name は config 由来の文字列なので jq 式に直埋めせず env 経由で渡す(" や \ を含んでも壊れない)。 -CONFIG_ID=$(GHAS_CONFIG_NAME="$CONFIG_NAME" gh api --paginate --slurp "/orgs/$ORG/code-security/configurations" \ - --jq '[.[][] | select(.name == env.GHAS_CONFIG_NAME) | .id] | .[0] // ""') +# 超えても取りこぼさないよう --paginate で全ページ取得し、--jq をページごとに適用して一致 id を出す +# (--slurp は --jq と併用不可なため使わない)。出力は `head` でパイプ切断せずコマンド置換で全量 +# 受け取り、複数行になっても先頭行のみ採用する(パイプ切断による SIGPIPE + set -o pipefail での +# 誤失敗を避ける)。name は config 由来なので jq 式に直埋めせず env 経由で渡す(" や \ でも壊れない)。 +CONFIG_ID=$(GHAS_CONFIG_NAME="$CONFIG_NAME" gh api --paginate "/orgs/$ORG/code-security/configurations" \ + --jq '.[] | select(.name == env.GHAS_CONFIG_NAME) | .id') +CONFIG_ID=${CONFIG_ID%%$'\n'*} if [ -z "$CONFIG_ID" ]; then echo " - configuration を新規作成: $CONFIG_NAME" diff --git a/pkgs/ghas-setup/tests/ghas-setup.bats b/pkgs/ghas-setup/tests/ghas-setup.bats index 3f20e45..0a0e28f 100644 --- a/pkgs/ghas-setup/tests/ghas-setup.bats +++ b/pkgs/ghas-setup/tests/ghas-setup.bats @@ -42,10 +42,12 @@ EOF } # gh をスタブする。呼び出し引数を $GH_LOG に記録し、種別ごとに想定 stdout を返す: -# - auth status : "admin:org" を出力(scope 判定の grep 用)/ exit 0 -# - api(--slurp あり) : 既存 lookup。$1(""=新規, それ以外=既存 id)を返す +# - auth status : "admin:org" を出力(scope 判定の grep 用)/ exit 0 +# - api(--paginate=lookup) : 既存 lookup。$1(""=新規, それ以外=既存 id)を返す # - api(POST で末尾が /configurations): 新規作成。固定 id 123 を返す -# - その他 api : 読み戻し等。{} を返す +# - その他 api : 読み戻し等。{} を返す +# 併せて実 gh の制約「--slurp は --jq と併用不可」を再現し、両指定なら非 0 終了する +# (この組み合わせの regression を検知するため)。 make_gh_stub() { STUB_DIR="$BASE/stubbin" GH_LOG="$BASE/gh-calls.log" @@ -58,7 +60,19 @@ echo "\$*" >> "$GH_LOG" case "\$1" in auth) echo "admin:org"; exit 0 ;; api) - for a in "\$@"; do [ "\$a" = "--slurp" ] && { printf '%s' "$1"; exit 0; }; done + has_slurp=0; has_jq=0; has_paginate=0 + for a in "\$@"; do + case "\$a" in + --slurp) has_slurp=1 ;; + --jq|-q) has_jq=1 ;; + --paginate) has_paginate=1 ;; + esac + done + if [ "\$has_slurp" = 1 ] && [ "\$has_jq" = 1 ]; then + echo "the \`--slurp\` option is not supported with \`--jq\` or \`--template\`" >&2 + exit 1 + fi + [ "\$has_paginate" = 1 ] && { printf '%s' "$1"; exit 0; } case "\$*" in *"--method POST"*"/code-security/configurations "*) printf '123'; exit 0 ;; esac