Skip to content

ci(release): open a cloudhal-template PR after each release (#111) - #135

Merged
Madraka merged 1 commit into
mainfrom
chore/issue-111-template-sync
Oct 26, 2026
Merged

Madraka merged 1 commit into
mainfrom
chore/issue-111-template-sync

Conversation

@Madraka

@Madraka Madraka commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

What

Closes #111. cloudhal-template, the repository behind the Deploy to Cloudflare button, fell three releases behind. After every release a PR now opens there automatically, with its check attached. The template side is cloudhal-dev/cloudhal-template#2: Dependabot plus README changes.

  • release.yml → template job (after a successful publish) calls the new template-sync.yml. That workflow can also be run by hand (Actions › Template sync, version x.y.z). It:
    1. Checks out the public template without any token and runs scripts/template-sync.ts. The script copies src/, public/, astro.config.mjs and tsconfig.json from the blog starter that @cloudhal/cli@<version> ships, which is exactly what cloudhal init copies. It moves @cloudhal/* to ^<version> and keeps template-specific files. It fails closed on package.json fields it has no rule for, and running it twice changes nothing.
    2. Runs --lock, which refreshes package-lock.json with every @cloudhal/* pinned to exactly <version> and checked. No package code runs in this step.
    3. Installs a copy with npm ci and runs cloudhal deploy --dry-run with WORKERS_CI=1. This happens before any write token exists.
    4. Creates a GitHub App token, pushes cloudhal/v<version>, and opens or updates the PR. Lookups are owner-qualified, so a fork's PR with the same branch name is never picked up.
    5. Posts the dry-run result as the PR's cloudhal/template-check commit status, closes older cloudhal/v* PRs as superseded, and fails the run if the dry run failed.
  • Without the App the job only logs a notice.
  • CONTRIBUTING.md:
    • Step 5, "After the release": the template, cloudhal.com (Dependabot; minor versions wait for a person) and try.cloudhal.com (by hand).
    • Corrected re-run advice.
    • Manual releases now also need Template sync to be run.
    • The frozen-theme rule for renderer changes.
  • docs/guides/deploy-button.md: how the template and copies stay current.

Why no workflow in the template

The button copies the template with Cloudflare's GitHub App, and Cloudflare's docs do not say whether that copy may contain .github/workflows/. GitHub refuses workflow files pushed by an App without the workflows permission. Putting the check in the template could therefore break the button for everyone, so the check runs here and reports as a status instead.

Owner setup (one time) for the job to run

  1. Create a GitHub App in the cloudhal-dev organization: github.com/organizations/cloudhal-dev/settings/apps/new.
    • Name, for example cloudhal-release-sync. Untick Webhook › Active.
    • Repository permissions: Contents Read and write, Pull requests Read and write, Commit statuses Read and write. Metadata is read-only and added automatically. Grant nothing else, and do not grant Workflows.
    • "Only on this account".
  2. Copy the Client ID (starts with Iv) and generate a private key (.pem).
  3. Install App › cloudhal-dev › Only select repositories › cloudhal-template. Do not install it on cloudhal.
  4. In cloudhal-dev/cloudhal › Settings › Secrets and variables › Actions:
    • variable TEMPLATE_SYNC_APP_CLIENT_ID = the Client ID. This is the on/off switch.
    • secret TEMPLATE_SYNC_APP_PRIVATE_KEY = the whole .pem. Delete the local file afterwards.
  5. First run: Actions › Template sync › Run workflow › 0.6.1. This should open chore: Cloudhal 0.6.1 and the 0.6.1 starter theme on cloudhal-template with a green cloudhal/template-check. That sync should only change tokens.css and the four ranges, plus the lockfile.
  6. Optional: a ruleset on cloudhal-template main requiring a PR and the cloudhal/template-check status.

Verification (local)

  • packages/cli template-sync.test.ts (19 tests, offline, temp dirs) and release-plan.test.ts (5) pass.
  • CLI typecheck, Biome, pnpm size:check pass. node scripts/publish-ci.ts --plan → publish=false version=0.6.1.
  • Both workflows parse.
  • Every uses: is pinned to a full SHA. create-github-app-token is v3.3.0, 64ab729a…. checkout and setup-node reuse the SHAs already in release.yml.
  • On a fresh clone of the template, for 0.6.1:
    • --check reports the pending change.
    • The sync changes tokens.css and four @cloudhal/* ranges.
    • --lock changes the 12 @cloudhal/* lock entries (plus two in-range transitive packages).
    • A second sync, --check and --lock change nothing.
    • npm ci passes, and WORKERS_CI=1 npx cloudhal deploy --dry-run prints "Dry run OK".
  • Refusals tested: a workspace starter, a downgrade, and malformed versions.
  • Not verified here: the end-to-end Actions run. It needs the App (owner setup above).

Checklist

  • pnpm check and cargo test --workspace pass locally. I ran the pieces that cover this change: scripts, their tests, docs and workflows; there is no package or Rust change.
  • Contract change? No.
  • User-visible change in a published package? No. Scripts, workflows and docs only, so no changeset.
  • Commits are signed off (git commit -s, DCO)
  • Docs / AGENTS.md updated if behaviour or commands changed: CONTRIBUTING.md and deploy-button.md.

Closes #111

🤖 Generated with Claude Code

cloudhal-template, the Deploy to Cloudflare button's repository, drifted
three releases behind. A new template job in release.yml (after a
successful publish) calls template-sync.yml, also runnable by hand for a
version npm has:

- scripts/template-sync.ts copies src/, public/, astro.config.mjs and
  tsconfig.json from the blog starter that @cloudhal/cli@<version> ships
  (what `cloudhal init` copies), moves @cloudhal/* to ^<version>, fails
  closed on starter package.json fields it has no rule for, and is
  idempotent; --lock pins every @cloudhal/* in the lockfile to exactly
  <version> without running package code.
- A copy of the synced template is installed with npm ci and deployed
  dry with WORKERS_CI=1 before any write token exists; the result is the
  PR's cloudhal/template-check commit status. The template keeps no
  workflow files: whether the button's copy may contain them is not
  documented.
- A GitHub App token (TEMPLATE_SYNC_APP_CLIENT_ID variable,
  TEMPLATE_SYNC_APP_PRIVATE_KEY secret; contents, pull requests and
  commit statuses on cloudhal-template only) pushes cloudhal/v<version>,
  opens or updates the PR (never a fork's), and closes older ones as
  superseded. Without the App the job logs a notice and does nothing.

CONTRIBUTING.md gets the after-the-release checklist (template,
cloudhal.com, try.cloudhal.com), corrected re-run and manual-release
notes, and the frozen-theme rule for renderer changes; the deploy-button
guide explains how the template stays current. onNpm moves to
release-plan.ts for both scripts.

Refs #111

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Madraka <8898640+Madraka@users.noreply.github.com>
@Madraka
Madraka enabled auto-merge October 26, 2026 09:01
@Madraka
Madraka merged commit de4ade0 into main Oct 26, 2026
5 checks passed
@Madraka
Madraka deleted the chore/issue-111-template-sync branch October 26, 2026 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Template and themes drift behind releases: keep cloudhal-template and frozen theme copies current

1 participant