From ebb862e20e4cc6fe57653fa4b12901a204e7b007 Mon Sep 17 00:00:00 2001 From: Asgeir Frimannsson Date: Thu, 16 Jul 2026 19:44:19 +0800 Subject: [PATCH 1/2] fix: install both CLI archive namings (kapi_ and 1.2.0's kapi-cli_) + prerelease canary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 1.2.0 release packaging (scripts/package-cli.sh in neokapi/neokapi) renamed the CLI archive kapi___. → kapi-cli__…, mirroring the Homebrew naming. Every 1.2.0 RC already publishes the new name, so the moment 1.2.0 stable ships, this action's download step would 404 for every consumer workflow. Resolve the archive name from checksums.txt — the release's own asset manifest — preferring kapi-cli_ and falling back to kapi_, so both eras install (verified locally against v1.1.0 and v1.2.0-rc9). Also add a daily schedule to the test workflow plus a prerelease canary job that installs the newest vX.Y.Z-* CLI prerelease: release-packaging changes land on RCs first, so this class of breakage now fails here weeks before it can reach a stable release. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01NBoxTTZe69Nyssa6QSMxFK --- .github/workflows/test.yml | 53 ++++++++++++++++++++++++++++++++++++++ scripts/download-verify.sh | 30 ++++++++++++++++++--- 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 80abfdb..1c7ec3d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,6 +5,13 @@ on: branches: [main] pull_request: branches: [main] + # Daily canary: the action installs from neokapi/neokapi releases, so it can + # break without a commit here (a renamed release asset did exactly that for + # 1.2.0). The schedule catches that class of breakage; the prerelease job + # below catches it while it is still an RC. + schedule: + - cron: "17 5 * * *" + workflow_dispatch: jobs: test-latest: @@ -77,6 +84,52 @@ jobs: echo "Expected: ${EXPECTED}, Actual: ${ACTUAL}" test "${EXPECTED}" = "${ACTUAL}" + # Canary against the newest CLI prerelease. Release packaging changes land + # on RCs first (the kapi_ → kapi-cli_ archive rename shipped on 1.2.0-rc1), + # so installing the newest prerelease here fails weeks before the same + # breakage would reach a stable release and every consumer workflow. + test-prerelease: + name: "Prerelease canary" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Resolve newest CLI prerelease + id: prerelease + shell: bash + env: + GH_TOKEN: ${{ secrets.NEOKAPI_GITHUB_TOKEN }} + # Same tag discipline as resolve-version.sh: only vX.Y.Z-… CLI tags, + # never plugin/app tags (check-v…, asr-v…, bowrain-v…). + run: | + VERSION=$( + gh api "repos/neokapi/neokapi/releases?per_page=100" --paginate \ + --jq '.[] | select(.draft == false and .prerelease == true) | .tag_name' | + grep -E '^v[0-9]+\.[0-9]+\.[0-9]+-' | + sed 's/^v//' | + sort -V | + tail -n 1 + ) || true + if [ -z "${VERSION}" ]; then + echo "No CLI prerelease found — nothing to canary." + else + echo "Newest CLI prerelease: ${VERSION}" + fi + echo "version=${VERSION}" >> "$GITHUB_OUTPUT" + + - name: Setup kapi (prerelease) + if: steps.prerelease.outputs.version != '' + id: setup + uses: ./ + with: + token: ${{ secrets.NEOKAPI_GITHUB_TOKEN }} + version: ${{ steps.prerelease.outputs.version }} + + - name: Verify kapi is on PATH + if: steps.prerelease.outputs.version != '' + shell: bash + run: kapi version + test-cache: name: "Cache hit (${{ matrix.os }})" runs-on: ${{ matrix.os }} diff --git a/scripts/download-verify.sh b/scripts/download-verify.sh index 92fba5e..5d4b76f 100755 --- a/scripts/download-verify.sh +++ b/scripts/download-verify.sh @@ -13,21 +13,43 @@ ARCH="${3:?}" EXT="${4:?}" DEST="${5:?}" -ARCHIVE="kapi_${VERSION}_${OS}_${ARCH}.${EXT}" TAG="v${VERSION}" TMPDIR=$(mktemp -d) trap 'rm -rf "${TMPDIR}"' EXIT +# The CLI archive was renamed for 1.2.0: kapi___. became +# kapi-cli___. (scripts/package-cli.sh mirrors the +# Homebrew naming, where the CLI toolchain is kapi-cli). Resolve the actual +# name from checksums.txt — the release's own asset manifest — so the action +# installs both eras: 1.1.0 and earlier ship kapi_, 1.2.0-rc1 and later ship +# kapi-cli_. +echo "Fetching checksums.txt from release ${TAG}..." +gh release download "${TAG}" \ + --repo neokapi/neokapi \ + --pattern "checksums.txt" \ + --dir "${TMPDIR}" + +cd "${TMPDIR}" +ARCHIVE="" +for candidate in "kapi-cli_${VERSION}_${OS}_${ARCH}.${EXT}" "kapi_${VERSION}_${OS}_${ARCH}.${EXT}"; do + if awk -v name="${candidate}" '$2 == name { found = 1 } END { exit !found }' checksums.txt; then + ARCHIVE="${candidate}" + break + fi +done +if [ -z "${ARCHIVE}" ]; then + echo "::error::Release ${TAG} has neither kapi-cli_${VERSION}_${OS}_${ARCH}.${EXT} nor kapi_${VERSION}_${OS}_${ARCH}.${EXT} in checksums.txt" >&2 + exit 1 +fi + echo "Downloading ${ARCHIVE} from release ${TAG}..." gh release download "${TAG}" \ --repo neokapi/neokapi \ --pattern "${ARCHIVE}" \ - --pattern "checksums.txt" \ --dir "${TMPDIR}" # Verify checksum -cd "${TMPDIR}" -EXPECTED=$(grep "${ARCHIVE}" checksums.txt | awk '{print $1}') +EXPECTED=$(awk -v name="${ARCHIVE}" '$2 == name { print $1 }' checksums.txt) if [ -z "${EXPECTED}" ]; then echo "::error::Archive ${ARCHIVE} not found in checksums.txt" >&2 exit 1 From fce1b1c226551b00a27cf7a86a68a194d8ff034d Mon Sep 17 00:00:00 2001 From: Asgeir Frimannsson Date: Thu, 16 Jul 2026 20:44:32 +0800 Subject: [PATCH 2/2] feat: install the bowrain plugin by default, and fix the plugin ref docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The plugins input now defaults to 'bowrain' so server-connected projects work out of the box; pass '' to install nothing. Along the way: the documented example ref 'kapi-bowrain' never worked — the registry names the plugin 'bowrain' (kapi plugins install does an exact index lookup; 'kapi-bowrain' errors "not in registry"), verified against the live registry. Plugin install was previously not covered by this repo's CI, so the broken example went unnoticed; with the new default, every test job now exercises it. The install step strips a 'kapi-' prefix so the binary-name spelling installs too. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01NBoxTTZe69Nyssa6QSMxFK --- README.md | 12 +++++++----- action.yml | 16 ++++++++++++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4e6db16..63ea06b 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ GitHub Action for installing the [kapi CLI](https://github.com/neokapi/neokapi) in CI workflows. -Downloads the correct binary for the runner platform, verifies SHA-256 checksums, caches between runs, and optionally installs kapi plugins (such as the bowrain plugin, `kapi-bowrain`) and configures server authentication. +Downloads the correct binary for the runner platform, verifies SHA-256 checksums, caches between runs, installs kapi plugins (the bowrain plugin by default), and configures server authentication. ## Usage @@ -33,13 +33,15 @@ steps: - run: kapi run ``` -### With the bowrain plugin and server auth +### With server auth + +The bowrain plugin is installed by default, so a server-connected project only +needs credentials: ```yaml steps: - uses: neokapi/setup-kapi@v1 with: - plugins: kapi-bowrain auth-token: ${{ secrets.BOWRAIN_AUTH_TOKEN }} server: https://your.bowrain.server @@ -54,7 +56,7 @@ steps: |-------|-------------|---------|----------| | `version` | Kapi CLI version (e.g. `1.1.0`), or `latest` for the newest stable CLI release | `latest` | No | | `token` | GitHub token for release downloads and API rate limits | `${{ github.token }}` | No | -| `plugins` | Newline- or comma-separated plugin refs to install (e.g. `kapi-bowrain`) | — | No | +| `plugins` | Newline- or comma-separated plugin refs to install, as the registry names them (`bowrain`, `okapi-bridge`; a `kapi-` prefix is stripped). Pass `''` to install nothing | `bowrain` | No | | `auth-token` | Bowrain server JWT, exported as `BOWRAIN_AUTH_TOKEN` | — | No | | `server` | Bowrain server URL, exported as `BOWRAIN_SERVER_URL` | — | No | @@ -72,7 +74,7 @@ steps: 3. **Download + verify** (on cache miss) — downloads the archive and `checksums.txt` from the GitHub release, verifies the SHA-256 checksum, and extracts the binary. 4. **Add to PATH** — makes `kapi` available to all subsequent steps. 5. **Configure auth** (optional) — exports `BOWRAIN_AUTH_TOKEN`/`BOWRAIN_SERVER_URL` when `auth-token` is set. -6. **Install plugins** (optional) — installs each ref in `plugins` via `kapi plugins install`, cached keyed on the plugin set + OS + arch. +6. **Install plugins** — installs each ref in `plugins` (default: `bowrain`) via `kapi plugins install`, cached keyed on the plugin set + OS + arch. Refs use the registry names; a `kapi-` binary prefix is stripped (`kapi-bowrain` → `bowrain`). ## Caching diff --git a/action.yml b/action.yml index 146fe5e..9583b12 100644 --- a/action.yml +++ b/action.yml @@ -14,9 +14,14 @@ inputs: required: false default: ${{ github.token }} plugins: - description: "Newline- or comma-separated plugin refs to install (e.g. 'kapi-bowrain')" + description: >- + Newline- or comma-separated plugin refs to install, as the registry + names them (e.g. 'bowrain', 'okapi-bridge'). The 'kapi-' binary prefix + is accepted and stripped ('kapi-bowrain' → 'bowrain'). Defaults to + 'bowrain' so server-connected projects work out of the box; pass '' to + install nothing. required: false - default: "" + default: "bowrain" auth-token: description: "Bowrain server JWT auth token (exported as BOWRAIN_AUTH_TOKEN)" required: false @@ -151,8 +156,11 @@ runs: env: INPUT_PLUGINS: ${{ inputs.plugins }} run: | - # Normalize: replace commas with newlines, trim whitespace, skip empty lines - PLUGINS=$(echo "${INPUT_PLUGINS}" | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | grep -v '^$') + # Normalize: replace commas with newlines, trim whitespace, skip empty + # lines, and strip the 'kapi-' binary prefix — the registry names the + # plugin 'bowrain' while its binary and archives are 'kapi-bowrain', + # so both spellings should install. + PLUGINS=$(echo "${INPUT_PLUGINS}" | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//;s/^kapi-//' | grep -v '^$') while IFS= read -r plugin; do echo "Installing plugin: ${plugin}" kapi plugins install "${plugin}"