From 6987022063167e0494bbe90495b7751e6186bcd9 Mon Sep 17 00:00:00 2001 From: Pal Lakatos-Toth Date: Tue, 23 Jun 2026 14:40:56 +0200 Subject: [PATCH 1/2] fix(cli): read --version from package.json; bump 0.1.1; surface npm publish failures - kars --version was hardcoded to 0.1.0-alpha.1 and drifted from the published package version. Read it from package.json via createRequire so it can never drift again (works in both dist/ and src/). - Bump @kars-runtime/cli to 0.1.1. The manually-published 0.1.0 lacked a README and provenance and npm forbids overwriting it; 0.1.1 lets CI publish a complete, provenance-signed version via OIDC. - Harden the release workflow npm-publish step: pre-check for an existing version (skip cleanly) and emit a loud ::warning:: annotation on a genuine publish failure, so a 'green but did not publish' outcome is visible in the run summary instead of being silently swallowed by continue-on-error. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/release-public-interim.yml | 19 +++++++++++++++++-- cli/package-lock.json | 4 ++-- cli/package.json | 2 +- cli/src/cli.ts | 6 +++++- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release-public-interim.yml b/.github/workflows/release-public-interim.yml index 7cee6d095..9e895d2cc 100644 --- a/.github/workflows/release-public-interim.yml +++ b/.github/workflows/release-public-interim.yml @@ -770,11 +770,26 @@ jobs: run: npm install -g npm@latest - name: Publish @kars-runtime/cli to npmjs (OIDC trusted publishing) if: ${{ !contains(env.VERSION, 'interim') }} + # Non-fatal so a missing trusted-publisher config can't break the whole + # release, BUT a genuine failure (or already-published version) emits a + # loud ::warning:: annotation so a "green but didn't publish" outcome is + # visible in the run summary instead of being silently swallowed. continue-on-error: true working-directory: cli run: | - echo "Publishing @kars-runtime/cli@$(node -p "require('./package.json').version") via OIDC trusted publishing…" - npm publish --provenance --access public + PKG="$(node -p "require('./package.json').name")" + VER="$(node -p "require('./package.json').version")" + if npm view "${PKG}@${VER}" version >/dev/null 2>&1; then + echo "::warning title=npm publish skipped::${PKG}@${VER} already exists on npm — bump cli/package.json version to publish a new release." + echo "Nothing to publish; ${PKG}@${VER} is already on the registry." + exit 0 + fi + echo "Publishing ${PKG}@${VER} via OIDC trusted publishing…" + if ! npm publish --provenance --access public; then + echo "::warning title=npm publish failed::${PKG}@${VER} did NOT publish. Check the OIDC trusted-publisher config on npmjs (Azure/kars → release-public-interim.yml) and the log above." + exit 1 + fi + echo "Published ${PKG}@${VER} with provenance." - name: Upload CLI tarball uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v4 diff --git a/cli/package-lock.json b/cli/package-lock.json index 19547821f..7f4bbfca9 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -1,12 +1,12 @@ { "name": "@kars-runtime/cli", - "version": "0.1.0", + "version": "0.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@kars-runtime/cli", - "version": "0.1.0", + "version": "0.1.1", "license": "MIT", "dependencies": { "@azure/identity": "^4.0.0", diff --git a/cli/package.json b/cli/package.json index 5b9a3bcc9..b115facd5 100644 --- a/cli/package.json +++ b/cli/package.json @@ -1,6 +1,6 @@ { "name": "@kars-runtime/cli", - "version": "0.1.0", + "version": "0.1.1", "description": "Enterprise-grade runtime for running OpenClaw AI assistants safely on Azure", "license": "MIT", "repository": { diff --git a/cli/src/cli.ts b/cli/src/cli.ts index a5cf05642..c12fd16b7 100644 --- a/cli/src/cli.ts +++ b/cli/src/cli.ts @@ -2,6 +2,10 @@ // Licensed under the MIT License. import { Command } from "commander"; +import { createRequire } from "node:module"; + +const require = createRequire(import.meta.url); +const { version: CLI_VERSION } = require("../package.json") as { version: string }; import { upCommand } from "./commands/up.js"; import { devCommand } from "./commands/dev.js"; import { addCommand } from "./commands/add.js"; @@ -43,7 +47,7 @@ export function createCli(): Command { .description( "Run AI agents safely on Azure. One command to go from zero to production." ) - .version("0.1.0-alpha.1"); + .version(CLI_VERSION); // Lifecycle program.addCommand(upCommand()); From b4ccf952576a7cbf1ee53605e5f1f5199fc45a72 Mon Sep 17 00:00:00 2001 From: Pal Lakatos-Toth Date: Tue, 23 Jun 2026 15:04:34 +0200 Subject: [PATCH 2/2] ci: stop legacy release.yml + image-sign-sbom.yml from auto-firing on v* tags Both legacy workflows triggered on the same clean v[0-9]+.[0-9]+.[0-9]+ tags as the new release-public-interim.yml (the single public release pipeline), causing guaranteed failures on every public tag: - image-sign-sbom.yml targets karsacr.azurecr.io and fails on azure/docker-login with 'Input required: username' because the ACR_USERNAME/ACR_PASSWORD secrets don't exist (MCR not onboarded yet). - release.yml creates a bare GitHub Release for the tag, colliding with the richer signed release that release-public-interim.yml creates for the same tag. Make both dispatch-only so they no longer auto-fire on v* tags. Public release images are signed via keyless cosign on GHCR in the canonical pipeline; image-sign-sbom.yml can be dispatched manually once ACR creds are provisioned. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/image-sign-sbom.yml | 18 ++++++------------ .github/workflows/release.yml | 13 +++++-------- 2 files changed, 11 insertions(+), 20 deletions(-) diff --git a/.github/workflows/image-sign-sbom.yml b/.github/workflows/image-sign-sbom.yml index e94bc9f24..4e3893d8d 100644 --- a/.github/workflows/image-sign-sbom.yml +++ b/.github/workflows/image-sign-sbom.yml @@ -1,18 +1,12 @@ name: Image Build, Sign & SBOM on: - push: - # Only fire for public-release tags (strict semver). Internal / - # preview tags (v*-internal*, v*-preview*) go through - # release-internal.yml which uses private GHCR — no ACR creds needed. - # This workflow targets karsacr.azurecr.io which requires ACR_USERNAME - # /ACR_PASSWORD secrets that won't exist until MCR namespace is - # onboarded. - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - - 'v[0-9]+.[0-9]+.[0-9]+-alpha*' - - 'v[0-9]+.[0-9]+.[0-9]+-beta*' - - 'v[0-9]+.[0-9]+.[0-9]+-rc*' + # ACR-based signing path for karsacr.azurecr.io. It requires ACR_USERNAME + # /ACR_PASSWORD secrets that do NOT exist until the MCR namespace is + # onboarded, so auto-firing on v* tags only produces a guaranteed + # "Input required: username" failure on azure/docker-login. Public + # releases are signed via release-public-interim.yml (keyless cosign on + # GHCR). Keep this dispatch-only until ACR creds are provisioned. workflow_dispatch: inputs: version: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7e6577519..70e85e3ef 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,14 +1,11 @@ name: Release on: - push: - # Only fire for public-release tags (semver). Internal/preview tags - # use release-internal.yml which produces wall-off artefacts. - tags: - - 'v[0-9]+.[0-9]+.[0-9]+' - - 'v[0-9]+.[0-9]+.[0-9]+-alpha*' - - 'v[0-9]+.[0-9]+.[0-9]+-beta*' - - 'v[0-9]+.[0-9]+.[0-9]+-rc*' + # Superseded by release-public-interim.yml, which is now the single public + # release pipeline (multi-arch GHCR images + signed GitHub Release + npm). + # Kept dispatch-only so the old CI+release path stays available if ever + # needed, but it no longer auto-fires on v* tags and races the new pipeline. + workflow_dispatch: permissions: contents: read