From 921f95a33ff93e79c77766a1493308c418cf740e Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 6 Oct 2026 14:49:14 +0000 Subject: [PATCH 1/2] One-button releases with the SDK's release workflow Actions > Release > Run workflow (patch / minor / major) bumps the version, writes the changelog, tags, releases and tells the registry. CI validates against Ervisio v0.6.2. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01YBUx1d4niJfMeuwPGpikuu --- .github/workflows/ci.yml | 2 +- .github/workflows/release.yml | 92 +++++++++-------------------------- package.json | 3 +- scripts/sync-version.mjs | 14 ++++++ 4 files changed, 40 insertions(+), 71 deletions(-) create mode 100644 scripts/sync-version.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 32d2e7c..9c893c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ permissions: contents: read env: - ERVISIO_REF: v0.5.0 + ERVISIO_REF: v0.6.2 jobs: build: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1798f7e..b05fbda 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,79 +1,33 @@ -# Publishes a release when a version tag is pushed: -# -# git tag -a v1.1.0 -m "1.1.0" && git push origin v1.1.0 -# -# The tag must equal the version in plugin/manifest.json and package.json. -# Assets: -.tar.gz (one top folder /, unsigned manifest) and -# -.tar.gz.sha256. The Ervisio plugin registry (Ervisio/plugins) -# picks the release up, reviews it, signs it with the Ervisio team key and -# lists it in the marketplace. No secrets are needed here. +# Release: Actions > Release > Run workflow, choose patch, minor or major +# (and optionally type the release notes). The version, CHANGELOG.md, the tag +# and the GitHub release are done for you, then the Ervisio registry is told; +# a version that asks for no new permissions is in the marketplace minutes +# later. Pushing a vX.Y.Z tag yourself still works. +# The steps live in Ervisio/plugin-sdk (.github/workflows/plugin-release.yml). name: Release on: + workflow_dispatch: + inputs: + bump: + description: 'Which part of the version goes up' + type: choice + options: [patch, minor, major] + default: patch + notes: + description: 'Release notes (empty: the commit subjects since the last release)' + type: string + required: false push: tags: ['v*.*.*'] permissions: - contents: read - -env: - ERVISIO_REF: v0.5.0 + contents: write jobs: release: - runs-on: ubuntu-24.04 - permissions: - contents: write - env: - TAG: ${{ github.ref_name }} - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 24 - - name: Install - run: if [ -f package-lock.json ]; then npm ci; else npm install; fi - - name: Version is the same everywhere - run: npm run check - - name: Build - run: npm run build - - name: Pack (checks tag = manifest version = package.json version) - run: npm run pack - - uses: actions/checkout@v4 - with: - repository: Ervisio/ervisio - ref: ${{ env.ERVISIO_REF }} - path: .ervisio-core - - uses: actions/setup-go@v5 - with: - go-version-file: .ervisio-core/server/go.mod - cache: false - - name: Validate the manifest (Ervisio's own checks, throwaway key) - run: | - (cd .ervisio-core/server && CGO_ENABLED=0 go build -o "$RUNNER_TEMP/plugin-sign" ./internal/modules/plugins/cmd/plugin-sign) - id="$(node -p "require('./plugin/manifest.json').id")" - version="$(node -p "require('./plugin/manifest.json').version")" - echo "ID=$id" >> "$GITHUB_ENV"; echo "VERSION=$version" >> "$GITHUB_ENV" - (cd dist && sha256sum -c "$id-$version.tar.gz.sha256") - V="$RUNNER_TEMP/validate"; mkdir -p "$V" - tar -xzf "dist/$id-$version.tar.gz" -C "$V" - test "$(ls "$V")" = "$id" - if [ -n "$(find "$V" ! -type f ! -type d)" ]; then echo "links or special files in the tarball"; exit 1; fi - pub="$("$RUNNER_TEMP/plugin-sign" -genkey "$RUNNER_TEMP/throwaway.key" | sed -n 's/^public key: //p')" - "$RUNNER_TEMP/plugin-sign" -key "$RUNNER_TEMP/throwaway.key" "$V/$id" - "$RUNNER_TEMP/plugin-sign" -verify -pub "$pub" "$V/$id" - rm -f "$RUNNER_TEMP/throwaway.key" - - name: Release notes (CHANGELOG.md section of this version) - run: | - notes="$RUNNER_TEMP/notes.md" - awk -v v="$VERSION" ' - /^## / { if (p) exit; h=$0; sub(/^## +\[?v?/, "", h); gsub(/\]/, " ", h); split(h, a, /[ \t(]+/); if (a[1] == v) { p=1; next } } - p { print }' CHANGELOG.md > "$notes" - if ! grep -q '[^[:space:]]' "$notes"; then echo "::error::CHANGELOG.md has no section for $VERSION"; exit 1; fi - cat "$notes" - - name: Publish - env: - GH_TOKEN: ${{ github.token }} - run: | - gh release create "$TAG" --verify-tag --title "$ID $VERSION" --notes-file "$RUNNER_TEMP/notes.md" \ - "dist/$ID-$VERSION.tar.gz" "dist/$ID-$VERSION.tar.gz.sha256" + uses: Ervisio/plugin-sdk/.github/workflows/plugin-release.yml@main + with: + bump: ${{ github.event_name == 'workflow_dispatch' && inputs.bump || '' }} + notes: ${{ inputs.notes }} + secrets: inherit diff --git a/package.json b/package.json index 4335672..4c82d7e 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "test:engine": "PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tests/engine -p 'test_*.py'", "test:connect": "PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s tests/connect -p 'test_*.py'", "check": "node scripts/check-release.mjs && python3 -B scripts/gen-tools-doc.py --check", - "docs": "python3 -B scripts/gen-tools-doc.py" + "docs": "python3 -B scripts/gen-tools-doc.py", + "version": "node scripts/sync-version.mjs" }, "devDependencies": { "@ervisio/plugin-sdk": "github:Ervisio/plugin-sdk#v0.2.0", diff --git a/scripts/sync-version.mjs b/scripts/sync-version.mjs new file mode 100644 index 0000000..a1dc13a --- /dev/null +++ b/scripts/sync-version.mjs @@ -0,0 +1,14 @@ +// Writes the package version into the engine and the connector; run by +// `npm version` (the "version" script), which the release workflow uses. +import { readFileSync, writeFileSync } from 'node:fs'; + +const v = process.env.npm_package_version || JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version; +const edit = (p, re, line) => { + const u = new URL(`../${p}`, import.meta.url); + const s = readFileSync(u, 'utf8'); + if (!re.test(s)) throw new Error(`${p}: no version line`); + writeFileSync(u, s.replace(re, line)); +}; +edit('plugin/engine/ervisio_ai/__init__.py', /__version__\s*=\s*"[^"]+"/, `__version__ = "${v}"`); +edit('plugin/connect/ervisio-ai-connect.py', /^VERSION\s*=\s*"[^"]+"/m, `VERSION = "${v}"`); +console.log(`version ${v} written to the engine and the connector`); From a20f57620f08b1678425bcd0fff78eca4fed8e01 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 6 Oct 2026 14:49:31 +0000 Subject: [PATCH 2/2] README: one-button releases Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01YBUx1d4niJfMeuwPGpikuu --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c2c7e8a..8042b7b 100644 --- a/README.md +++ b/README.md @@ -214,12 +214,11 @@ More in [docs/architecture.md](docs/architecture.md). ## Releasing -1. Set the version in `plugin/manifest.json`, `package.json`, `plugin/engine/ervisio_ai/__init__.py` and - `plugin/connect/ervisio-ai-connect.py`, and add a `## X.Y.Z` section to `CHANGELOG.md` (`npm run check` verifies all of it). -2. Commit, then `git tag -a vX.Y.Z -m "X.Y.Z" && git push origin vX.Y.Z`. -3. The release workflow builds, validates the manifest with Ervisio's validator, and publishes `ai-X.Y.Z.tar.gz` and `.sha256`. -4. The [Ervisio plugin registry](https://github.com/Ervisio/plugins) picks up the release, signs it, and lists it in the - marketplace catalog. +On GitHub: **Actions › Release › Run workflow**, choose `patch`, `minor` or `major`, optionally type the release notes +(empty: the commit subjects since the last release), and run it. The workflow bumps the version, writes the +`CHANGELOG.md` section, tags, builds, validates and releases, then tells the Ervisio registry: an update that asks for +no new permissions is in the marketplace a few minutes later. The steps live in +[Ervisio/plugin-sdk](https://github.com/Ervisio/plugin-sdk/blob/main/docs/publishing.md). ## License