Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 38 additions & 14 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
name: Release

on:
push:
tags:
- 'v*'
workflow_dispatch:

env:
NODE_VERSION: 20

jobs:
release:
name: Release
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Verify main branch
run: |
if [[ "${{ github.ref_name }}" != "main" ]]; then
echo "Release can only be done on the main branch."
exit 1
fi

- name: Checkout project
uses: actions/checkout@v4

- name: Install Node.js
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
node-version: ${{ env.NODE_VERSION }}

- name: Install dependencies
run: npm install
Expand All @@ -25,14 +35,28 @@ jobs:
run: npm run build
Comment on lines 26 to 35
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow uses npm install/npm run build even though the repo is bun-first (bun.lock + README/.agents docs). This means the release build can ignore the lockfile and produce non-reproducible artifacts. Consider setting up bun in this workflow and using bun install --frozen-lockfile + bun run build (or bun run package if that's the intended release artifact).

Copilot uses AI. Check for mistakes.

- name: Sign plugin
working-directory: dist
run: |
if [[ -z "${{ secrets.PRIVATE_KEY }}" ]]; then
echo "Set an ed25519 key as PRIVATE_KEY in GitHub Action secret to sign."
exit 1
fi
echo "${{ secrets.PRIVATE_KEY }}" > private_key.pem
openssl pkeyutl -sign -inkey private_key.pem -out plugin_package.zip.sig -rawin -in plugin_package.zip
rm private_key.pem
Comment on lines +45 to +46
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The private key file is removed only on the happy path. If openssl pkeyutl fails, the rm private_key.pem line won’t run and the key can remain in the workspace for subsequent steps. Consider using a trap (as the previous version did) to ensure cleanup on failure, and/or running the signing step in a subshell that always deletes the file.

Suggested change
openssl pkeyutl -sign -inkey private_key.pem -out plugin_package.zip.sig -rawin -in plugin_package.zip
rm private_key.pem
trap 'rm -f private_key.pem' EXIT
openssl pkeyutl -sign -inkey private_key.pem -out plugin_package.zip.sig -rawin -in plugin_package.zip

Copilot uses AI. Check for mistakes.

- name: Check version
id: meta
working-directory: dist
run: |
trap 'rm private.pem' EXIT
echo "${{ secrets.PRIVATE_KEY }}" > private.pem
openssl pkeyutl -sign -inkey private.pem -out plugin_package.zip.sig -rawin -in dist/plugin_package.zip
VERSION=$(unzip -p plugin_package.zip manifest.json | jq -r .version)
echo "version=${VERSION}" >> $GITHUB_OUTPUT
Copy link

Copilot AI Feb 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jq -r .version will output the literal string null (exit code 0) if the manifest is missing a version field, which would then be used as the Git tag. Add validation that VERSION is non-empty and not null (and optionally matches the expected semver format) before writing it to $GITHUB_OUTPUT.

Suggested change
echo "version=${VERSION}" >> $GITHUB_OUTPUT
if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then
echo "Error: manifest.json is missing a valid 'version' field."
exit 1
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"

Copilot uses AI. Check for mistakes.

- name: Create Release
uses: softprops/action-gh-release@v2
- name: Create release
uses: caido/action-release@v1
with:
files: |
dist/plugin_package.zip
plugin_package.zip.sig
tag: ${{ steps.meta.outputs.version }}
commit: ${{ github.sha }}
body: 'Release ${{ steps.meta.outputs.version }}'
artifacts: 'dist/plugin_package.zip,dist/plugin_package.zip.sig'
immutableCreate: true
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ bun run package

1. Bump `version` in both `package.json` and `manifest.json`.
2. Commit and push to `main`.
3. Tag and push: `git tag v1.2.x && git push origin v1.2.x`.
4. GitHub Actions builds, signs, and publishes the release.
3. Go to **Actions** > **Release** > **Run workflow** (on `main` branch).
4. GitHub Actions builds, signs, and publishes an immutable release tagged with the version from `manifest.json`.

## Credits

Expand Down