|
1 | | -# /publish-astro — Publish @run402/astro to npm |
| 1 | +# /publish-astro — Publish @run402/astro to npm via OIDC |
2 | 2 |
|
3 | | -Publish the `@run402/astro` Astro integration package from `astro/` in this repo. Unlike `@run402/sdk`, `run402` CLI, and `run402-mcp` (which lockstep via `/publish`), `@run402/astro` has its own versioning cadence because it's a framework adapter, not part of the core SDK release train. |
| 3 | +Trigger the canonical publish pipeline at `.github/workflows/publish-astro.yml`. The workflow handles version bump, smoke test, npm publish (via OIDC Trusted Publisher — no stored tokens), commit-back, tag, and GitHub release. This skill is your local-machine wrapper around `gh workflow run`. |
4 | 4 |
|
5 | | -> **`@run402/functions` is published from the private gateway monorepo** (`kychee-com/run402-private` via `/publish-functions`). This skill is only for `@run402/astro`. |
| 5 | +> **Why CI-driven not local-publish:** `@run402/astro` uses npm's Trusted Publisher OIDC federation. The npm package's settings page lists this repository, branch, and workflow filename as a trusted publisher. Any publish attempted from anywhere else (a developer laptop, a fork, a different workflow file) fails the npm-side claim check. The whole point of OIDC is to remove the "do you have a token" question — only this workflow file running on main can publish. |
| 6 | +> |
| 7 | +> **One bootstrap exception:** v0.1.0 was published manually with an OTP-elevated automation token because npm requires the package to exist before a Trusted Publisher can be configured. That bootstrap is done and never repeats; from 0.1.1 onwards, all publishes go through this skill → this workflow. |
6 | 8 |
|
7 | | -Stop on any failure. Do NOT skip checks. |
| 9 | +> **`@run402/functions` is published from a different repo** (`kychee-com/run402-private` via `/publish-functions`). This skill is only for `@run402/astro`. |
| 10 | +> |
| 11 | +> **`run402-mcp`, `run402` CLI, and `@run402/sdk`** ship via `/publish` (lockstep). This skill is independent of that release train. |
8 | 12 |
|
9 | | -## When to publish |
| 13 | +Stop on any failure. Do NOT skip checks. |
10 | 14 |
|
11 | | -- New `<Image>` component prop, integration option, or behavior change → publish |
12 | | -- Bug fix to the resolver / scanner / uploader / picture-builder → publish patch |
13 | | -- Compat fix for a new Astro major version → publish minor (after testing against the new major) |
14 | | -- Documentation-only README fix → publish at your discretion (no functional change) |
| 15 | +## Pre-flight (local, before triggering the workflow) |
15 | 16 |
|
16 | | -The package has **no runtime relationship with the gateway** — there is no equivalent of `@run402/functions`'s "gateway redeploy alone propagates the fix." A consumer must bump their `@run402/astro` dependency to see any change. |
| 17 | +These run on your machine to catch obvious problems before the workflow burns Actions minutes: |
17 | 18 |
|
18 | | -## Pre-publish checks |
| 19 | +1. **On `main`, in sync with `origin/main`.** `git rev-parse --abbrev-ref HEAD` must be `main`. `git fetch origin main && git rev-list --count HEAD..origin/main` must be `0`. If not, stop and tell the user. The workflow itself enforces `if: github.ref == 'refs/heads/main'`, but catching the mismatch locally avoids a wasted run. |
| 20 | +2. **Working tree clean** (`git status`). Uncommitted changes don't go to the workflow — they'd be invisible to the publish. If the user has work in flight that they want included in the publish, commit + push it first. |
| 21 | +3. **Unit tests pass:** `npm test --workspace=astro`. Expect ~50 tests, 0 failures. The workflow re-runs these but a local pre-check gives fast feedback. |
| 22 | +4. **Type-check clean:** `npx tsc --noEmit -p astro`. Empty output = clean. |
| 23 | +5. **Confirm npm Trusted Publisher is configured.** Open https://www.npmjs.com/package/@run402/astro/access in a browser and confirm the "Trusted Publishers" section lists this repo + workflow. If the section is empty, the publish step will fail with 401 — stop and ask the user to configure it before proceeding (org `kychee-com`, repo `run402`, workflow filename `publish-astro.yml`, no environment). |
19 | 24 |
|
20 | | -1. **On main, in sync with origin/main.** `git rev-parse --abbrev-ref HEAD` must be `main`. `git fetch origin main && git rev-list --count HEAD..origin/main` must be `0`. If not, stop and tell the user. |
21 | | -2. **Working tree clean** (`git status`). Stop if not. |
22 | | -3. **Unit tests pass:** `npm test --workspace=astro`. Expect 50+ tests, 0 failures. |
23 | | -4. **Type-check clean:** `npx tsc --noEmit -p astro`. No output = clean. |
24 | | -5. **Build the package:** `npm run build --workspace=astro`. Confirms `dist/` is current. |
| 25 | +If any local check fails, stop and tell the user. |
25 | 26 |
|
26 | | -If any step fails, stop and tell the user. |
| 27 | +## Choose the bump kind |
27 | 28 |
|
28 | | -## Version bump |
| 29 | +Ask the user: **patch, minor, or major.** |
29 | 30 |
|
30 | | -1. Ask the user: **patch, minor, or major.** |
31 | | - - Patch (`0.1.0 → 0.1.1`): bug fix, no surface change. |
32 | | - - Minor (`0.1.0 → 0.2.0`): new prop, new integration option, or new optional behavior. Backwards-compatible. |
33 | | - - Major (`0.1.0 → 1.0.0` or `1.0.0 → 2.0.0`): breaking prop change, removed option, or behavior change that requires consumer code changes. v0.x → v1.x is the "stable surface" promotion. |
34 | | -2. Read current version from `astro/package.json`. |
35 | | -3. Compute target: apply bump kind. Apply directly to `astro/package.json` (use Edit, not `npm version` — `npm version` from inside a workspace can have surprising lockfile behavior). |
36 | | -4. `npm install --package-lock-only` from repo root to sync `package-lock.json`. |
| 31 | +- **Patch** (`0.1.0 → 0.1.1`): bug fix, no surface change. Example: blurhash decoder crash on edge case, error message wording. |
| 32 | +- **Minor** (`0.1.0 → 0.2.0`): new prop, new integration option, or new optional behavior. Backwards-compatible. Example: new `placeholder="dominantColor"` mode, support for AVIF variants when they ship in v1.50. |
| 33 | +- **Major** (`0.x → 1.0` or `1.x → 2.0`): breaking prop change, removed option, or behavior change that requires consumer code changes. Example: removing `priority` in favor of `fetchpriority`, changing the variant URL format. Reserve `1.0` for the "stable surface" promotion when the prop API is locked. |
37 | 34 |
|
38 | | -## Tarball smoke test |
| 35 | +## Trigger the workflow |
39 | 36 |
|
40 | | -`npm test` runs against source, not the packed tarball. Pack it and verify the entry points resolve: |
| 37 | +The workflow does ALL the publish work — version bump, smoke test, npm publish, commit-back to main, tag, GitHub release. You just trigger it: |
41 | 38 |
|
42 | 39 | ``` |
43 | | -SMOKE=/tmp/smoke-astro-<new_version> && rm -rf $SMOKE && mkdir $SMOKE |
44 | | -(cd astro && npm pack --pack-destination $SMOKE) |
45 | | -mkdir $SMOKE/astro && tar xzf $SMOKE/run402-astro-<new_version>.tgz -C $SMOKE/astro |
46 | | -(cd $SMOKE/astro/package && npm install --omit=dev --before=9999-12-31) |
47 | | -node -e "import('$SMOKE/astro/package/dist/index.js').then(m => console.log('OK', typeof m.run402)).catch(e => { console.error('FAIL', e.message); process.exit(1) })" |
| 40 | +gh workflow run publish-astro.yml -F bump=<patch|minor|major> -R kychee-com/run402 |
48 | 41 | ``` |
49 | 42 |
|
50 | | -Expect `OK function`. The script exits non-zero on any failure. |
51 | | - |
52 | | -**Also verify the .astro component file ships:** |
| 43 | +For a dry-run that builds + smoke-tests without publishing (useful when validating a workflow change): |
53 | 44 |
|
54 | 45 | ``` |
55 | | -ls $SMOKE/astro/package/src/Image.astro |
| 46 | +gh workflow run publish-astro.yml -F bump=patch -F dry_run=true -R kychee-com/run402 |
56 | 47 | ``` |
57 | 48 |
|
58 | | -Must print the path. If the file is missing, the `files` allowlist in `package.json` is broken — do not publish. |
| 49 | +The dry run still bumps the local version on the runner and packs the tarball, but skips the publish + commit + tag + release steps. Useful for "does the bumped version pack right?" testing. |
| 50 | + |
| 51 | +## Watch the workflow |
59 | 52 |
|
60 | | -**Also verify the tarball does NOT include source `.ts` files:** |
| 53 | +Find the run ID and watch: |
61 | 54 |
|
62 | 55 | ``` |
63 | | -find $SMOKE/astro/package -name "*.ts" -not -name "*.d.ts" | head |
| 56 | +RUN_ID=$(gh run list -w publish-astro.yml -R kychee-com/run402 --limit 1 --json databaseId --jq '.[0].databaseId') |
| 57 | +gh run watch "$RUN_ID" -R kychee-com/run402 --exit-status |
64 | 58 | ``` |
65 | 59 |
|
66 | | -Should print nothing (only `.d.ts` types ship). Source `.ts` files in the tarball means `files` allowlist is wrong. |
| 60 | +`--exit-status` makes the watch command exit non-zero if the workflow fails — useful for chaining into a verification step. |
67 | 61 |
|
68 | | -**About `--before=9999-12-31`:** if the user's global npm has a `before` date pinned (supply-chain mitigation), the scratch install needs this flag to bypass it for `/tmp` installs. Do **not** suggest removing the global config. |
| 62 | +## Verify post-publish |
69 | 63 |
|
70 | | -## Commit and publish |
| 64 | +After the workflow completes successfully: |
71 | 65 |
|
72 | | -1. Stage and commit the version bump: |
| 66 | +1. **Verify the new version is live:** |
73 | 67 | ``` |
74 | | - git add astro/package.json package-lock.json |
75 | | - git commit -m "chore(astro): bump @run402/astro to v<new_version>" |
| 68 | + curl -sS "https://registry.npmjs.org/@run402/astro/<new_version>" | jq -r .version |
76 | 69 | ``` |
77 | | -2. Publish: |
78 | | - ``` |
79 | | - cd astro && npm publish --access public |
80 | | - ``` |
81 | | - The `publishConfig.access: public` field is set in `package.json`, so the explicit flag is redundant but harmless. The tarball contains `dist/`, `src/Image.astro`, and `README.md` only (per the `files` allowlist; `node_modules`, tests, and `*.test.*` are excluded). |
| 70 | + The user's local npm may have a `--before` date pin set as a supply-chain mitigation that filters out newly-published packages from `npm view`. Use direct `curl` to confirm registry state. If the user wants to see it via `npm view`, they need `--before=9999-12-31` (do NOT suggest changing their global config). |
82 | 71 |
|
83 | | -## Post-publish |
84 | | - |
85 | | -1. `git push` to push the version bump commit. |
86 | | -2. Create a git tag: |
87 | | - ``` |
88 | | - git tag v<new_version>-astro && git push --tags |
| 72 | +2. **Confirm provenance attestation:** |
89 | 73 | ``` |
90 | | - Use the `-astro` suffix because the other public-repo packages (`run402-mcp`, `run402`, `@run402/sdk`) have their own tag scheme; this clarifies which package the tag belongs to. |
91 | | -3. Create a GitHub release (public repo): |
| 74 | + curl -sS "https://registry.npmjs.org/@run402/astro/<new_version>" | jq '.dist.attestations' |
92 | 75 | ``` |
93 | | - gh release create v<new_version>-astro -R kychee-com/run402 --notes "..." |
94 | | - ``` |
95 | | - Write a human-readable summary naming user-facing changes. Don't rely on auto-generated notes. |
96 | | -4. **Verify live on npm:** |
97 | | - ``` |
98 | | - npm view @run402/astro@<new_version> version |
99 | | - ``` |
100 | | - Should print the new version. May take up to a minute to propagate. |
101 | | -5. **Update `documentation.md`** if the prop surface or integration options changed. The doc serves as the canonical reference for the public repo. Commit + push. |
102 | | -6. **Update `llms-full.txt` in the private repo** (`kychee-com/run402-private` at `site/llms-full.txt`) if the Astro integration section needs to point at a new version or document a new feature. The site at https://run402.com/llms-full.txt is regenerated from there; trigger a redeploy after the update: |
103 | | - ``` |
104 | | - gh workflow run deploy-site.yml -R kychee-com/run402-private |
105 | | - ``` |
106 | | -7. Print a summary: |
| 76 | + Should return a non-null object. If null, OIDC didn't kick in and the publish silently fell back to anonymous — investigate. |
| 77 | + |
| 78 | +3. **Print summary** for the user: |
107 | 79 | - Published version |
108 | | - - npm URL: `https://www.npmjs.com/package/@run402/astro` |
109 | | - - GitHub release URL |
| 80 | + - npm URL: `https://www.npmjs.com/package/@run402/astro/v/<new_version>` |
| 81 | + - Workflow run URL |
| 82 | + - GitHub release URL: `https://github.com/kychee-com/run402/releases/tag/v<new_version>-astro` |
110 | 83 |
|
111 | 84 | ## What this skill does NOT do |
112 | 85 |
|
113 | | -- Does NOT bump `mcp`, `cli`, or `sdk`. Those lockstep via `/publish`. |
114 | | -- Does NOT bump `@run402/functions`. That lives in the private gateway monorepo and ships via `/publish-functions` there. |
115 | | -- Does NOT trigger any gateway redeploy. There is no gateway-side dependency on this package. |
116 | | -- Does NOT migrate consumer projects. After publishing, consumers (Kychon, etc.) update their `@run402/astro` dependency on their own cadence. |
| 86 | +- Does NOT publish locally via `npm publish`. The Trusted Publisher OIDC trust ONLY accepts publishes from THIS workflow file on `main`. Attempting a local publish would fail the npm-side claim check (or succeed only if the user has an unrelated bypass-2FA token, which defeats the whole point). |
| 87 | +- Does NOT bump `mcp`, `cli`, `sdk` — those lockstep via `/publish`. |
| 88 | +- Does NOT bump `@run402/functions` — that lives in the private gateway monorepo. |
| 89 | +- Does NOT pull a release branch — the workflow operates on `main` directly. Use a feature branch for the code change, merge to main, then run this skill. |
| 90 | +- Does NOT prompt for an OTP or token. If you ever see the workflow asking for one, the Trusted Publisher config drifted — fix the npm-side config rather than reverting to token auth. |
| 91 | + |
| 92 | +## Troubleshooting |
| 93 | + |
| 94 | +- **Workflow fails at `Publish to npm` with 401 or 403:** Trusted Publisher config doesn't match. Check the npm package access page — org / repo / workflow filename must exactly match this workflow's metadata. |
| 95 | +- **Workflow fails at `Commit version bump` with permission denied:** Repo Settings → Actions → General → Workflow permissions → must be "Read and write." The default GITHUB_TOKEN's permissions are read-only unless this is flipped. |
| 96 | +- **Workflow fails at `Tarball smoke test` after a successful publish-in-progress:** the tarball was generated incorrectly. Recover by manually patching `astro/package.json` to bump the version back (workflow had already bumped locally on the runner but not committed) and re-run. The npm-side already-published version blocks re-publish, which is the safety net. |
| 97 | +- **`npm view` returns 404 right after a successful publish:** almost always the user's `--before` date pin filtering, not a real propagation issue. Confirm with the direct `curl` against `registry.npmjs.org`. |
0 commit comments