Skip to content

Commit 02b473c

Browse files
wishbornclaude
andcommitted
CI: sign official plugins with the reusable genie signer action
Add .github/workflows/sign.yml. On push to main under plugins/** (or manual dispatch) it signs each plugin's genie-plugin.json via the reusable composite action Renaissance-Analytics/genie/.github/actions/sign-genie-plugin@main, passing signing-key: secrets.GENIE_PLUGIN_SIGNING_KEY (the org Ed25519 private key — contributors never handle it) and guarding with expect-key-id set to the official Genie Official keyId. The action signs one manifest per call, so the plugin dirs are signed in sequential steps in a single job (shared checkout → clean fast-forward pushes) with the action's default commit+push publish flow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent ef0654c commit 02b473c

1 file changed

Lines changed: 53 additions & 0 deletions

File tree

.github/workflows/sign.yml

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Sign the marketplace's official plugins in CI.
2+
#
3+
# The signing key is the `GENIE_PLUGIN_SIGNING_KEY` ORG secret — the Ed25519
4+
# PRIVATE key for "Genie Official" (keyId
5+
# ed25519-bHc2Rt62EgjmpE5Fd7-QsJeNi36BsAwckJ4bEyx4BCE). It lives ONLY in GitHub;
6+
# contributors never handle it. This workflow feeds it to the reusable signer
7+
# action on genie `main`, which signs each plugin's genie-plugin.json (writing
8+
# publisher.keyId + integrity + a detached Ed25519 signature) and commits the
9+
# signed manifest back to `main`. Genie verifies that signature against its
10+
# bundled trust root at install time. See genie's docs/plugin-signing.md.
11+
name: Sign plugins
12+
13+
on:
14+
# Sign whenever a plugin's source changes on the publish branch…
15+
push:
16+
branches: [main]
17+
paths:
18+
- 'plugins/**'
19+
# …and allow a manual re-sign (e.g. after rotating the key).
20+
workflow_dispatch:
21+
22+
permissions:
23+
# The signer commits + pushes the signed manifests back to main.
24+
contents: write
25+
26+
jobs:
27+
sign:
28+
runs-on: ubuntu-latest
29+
steps:
30+
- uses: actions/checkout@v4
31+
32+
# The action signs ONE manifest per call, so we invoke it once per plugin
33+
# dir. These run sequentially in a single job sharing one checkout, so each
34+
# commit advances local HEAD and the next push is a clean fast-forward —
35+
# unlike separate matrix jobs, which would each check out the trigger SHA
36+
# and collide on push. Ed25519 signing is deterministic, so a re-triggered
37+
# run re-signs to identical bytes → the action's "nothing to commit"
38+
# no-op → no push → no loop.
39+
- name: Sign presentation
40+
uses: Renaissance-Analytics/genie/.github/actions/sign-genie-plugin@main
41+
with:
42+
signing-key: ${{ secrets.GENIE_PLUGIN_SIGNING_KEY }}
43+
plugin-dir: plugins/presentation
44+
# Guard: refuse to sign unless the secret derives to the official key.
45+
expect-key-id: ed25519-bHc2Rt62EgjmpE5Fd7-QsJeNi36BsAwckJ4bEyx4BCE
46+
# commit: 'true' (default) — commit + push the signed genie-plugin.json.
47+
48+
- name: Sign spreadsheet
49+
uses: Renaissance-Analytics/genie/.github/actions/sign-genie-plugin@main
50+
with:
51+
signing-key: ${{ secrets.GENIE_PLUGIN_SIGNING_KEY }}
52+
plugin-dir: plugins/spreadsheet
53+
expect-key-id: ed25519-bHc2Rt62EgjmpE5Fd7-QsJeNi36BsAwckJ4bEyx4BCE

0 commit comments

Comments
 (0)