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
2 changes: 1 addition & 1 deletion .github/workflows/template-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Template sync
# Keeps cloudhal-dev/cloudhal-template, the repository the Deploy to Cloudflare button copies
# (docs/guides/deploy-button.md), on the latest release (issue #111). release.yml calls this after
# a successful npm publish; to re-sync by hand, run Actions › Template sync › Run workflow with a
# version npm has.
# version npm has, or scripts/template-sync.ts from a checkout (CONTRIBUTING.md, Releasing).
# scripts/template-sync.ts copies src/, public/, astro.config.mjs and tsconfig.json from the blog
# starter `@cloudhal/cli@<version>` ships and moves @cloudhal/* to ^<version>; the lockfile is
# refreshed with every @cloudhal/* at exactly <version>, without running package code; then one PR
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ All publishable packages (`@cloudhal/*` and `create-cloudhal`) share one version
3. **Approval.** The merge starts the `publish` job, which waits for the `npm-publish` environment's approval (the maintainer, with 2FA). Approve it in the run's page on GitHub.
4. **Publish.** `scripts/publish-ci.ts` checks the build, packs every package and installs the tarballs from scratch with npm (`scripts/smoke-pack.ts`), publishes exactly those tarballs with npm trusted publishing (OIDC, with provenance), waits until npm serves all of them, then creates the `vX.Y.Z` tag and the GitHub Release from the changelogs.
5. **After the release.** Bring the rest along:
- **cloudhal-template** (the Deploy to Cloudflare button): the workflow's `template` job (`.github/workflows/template-sync.yml`) opens `chore: Cloudhal X.Y.Z and the X.Y.Z starter theme` from `cloudhal/vX.Y.Z`, with `src/`, `public/`, `astro.config.mjs` and `tsconfig.json` from the published starter, `@cloudhal/*` at `^X.Y.Z` and a lockfile that installs exactly `X.Y.Z`. Merge it once its `cloudhal/template-check` status is green: the same run installs a copy of the synced template with `npm ci` and runs `cloudhal deploy --dry-run` with `WORKERS_CI=1`. To sync again, run Actions › Template sync › Run workflow. Without the `TEMPLATE_SYNC_APP_CLIENT_ID` variable and the `TEMPLATE_SYNC_APP_PRIVATE_KEY` secret (a GitHub App installed on cloudhal-template only, with Contents, Pull requests and Commit statuses write) the job only logs a notice; Dependabot's `@cloudhal/*` PR on the template is the fallback, and it brings dependencies only, no theme.
- **cloudhal-template** (the Deploy to Cloudflare button): the workflow's `template` job (`.github/workflows/template-sync.yml`) opens `chore: Cloudhal X.Y.Z and the X.Y.Z starter theme` from `cloudhal/vX.Y.Z`, with `src/`, `public/`, `astro.config.mjs` and `tsconfig.json` from the published starter, `@cloudhal/*` at `^X.Y.Z` and a lockfile that installs exactly `X.Y.Z`. Merge it once its `cloudhal/template-check` status is green: the same run installs a copy of the synced template with `npm ci` and runs `cloudhal deploy --dry-run` with `WORKERS_CI=1`. To sync again, run Actions › Template sync › Run workflow. Without the `TEMPLATE_SYNC_APP_CLIENT_ID` variable and the `TEMPLATE_SYNC_APP_PRIVATE_KEY` secret (a GitHub App installed on cloudhal-template only, with Contents, Pull requests and Commit statuses write) the job only logs a notice. Then sync by hand from a checkout: clone cloudhal-template next to this repository, run `node scripts/template-sync.ts --template ../cloudhal-template --version X.Y.Z --summary pr-body.md` and then the same command with `--lock` in place of `--summary` (Node 24, no `pnpm install` needed), check a copy of the template (`npm ci`, then `WORKERS_CI=1 npx cloudhal deploy --dry-run`), commit on `cloudhal/vX.Y.Z`, push, open the PR with the title above and `pr-body.md` as its body, and post the `cloudhal/template-check` status on its head commit (`gh api -X POST repos/cloudhal-dev/cloudhal-template/statuses/<sha> -f state=success -f context=cloudhal/template-check -f description='npm ci and cloudhal deploy --dry-run (WORKERS_CI=1) passed, run by hand'`). Dependabot's `@cloudhal/*` PR on the template is no substitute: it moves dependencies only, no theme, and it fails to install whenever the starter's own pins moved with the release (0.6.3 moved astro to 7.4.7 for the `^7.4.0` peer range, so Dependabot's `^0.6.1` PR hit ERESOLVE); close it as superseded by the sync PR.
- **cloudhal.com**: Dependabot opens the `@cloudhal/*` PR the next morning (06:00 Europe/Istanbul). A patch release merges itself after its check; a minor bump waits for a person.
- **try.cloudhal.com** (`cloudhal-dev/try`): by hand. Bump its exact `@cloudhal/*` pins, then `pnpm install` and `pnpm run deploy`.
- **The Docker image** (`ghcr.io/cloudhal-dev/cloudhal`, [self-host guide](docs/guides/self-host.md)): the workflow's `docker` job (`.github/workflows/docker.yml`) builds it from the npm release and pushes `X.Y.Z`, `X.Y` and `latest` for linux/amd64 and linux/arm64, with an SBOM, provenance and a smoke test. The image never carries a version of its own: one release, one version everywhere. To rebuild a version (a base-image fix) run Actions › Docker image › Run workflow with it; that re-tags `X.Y.Z` and `X.Y` and leaves `latest` alone. `edge` is built nightly from `main`.
Expand Down
8 changes: 8 additions & 0 deletions packages/cli/test/template-sync.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,14 @@ describe("PR body", () => {
expect(body).toContain("Do not push to this branch");
});

it("says who opened it: the workflow run, or a hand run of the script", () => {
const byHand = prBody({ ops: [], from: "0.6.0", to: "0.6.3" });
expect(byHand).toContain("Opened by hand with `scripts/template-sync.ts`");
expect(byHand).toContain("whoever synced by hand installed a copy of this branch");
expect(byHand).not.toContain("release workflow");
expect(byHand).toContain("None: dependencies and the lockfile only.");
});

it("caps each path list at 50", () => {
const ops = Array.from({ length: 60 }, (_, i) =>
write(`src/f${String(i).padStart(2, "0")}.css`),
Expand Down
11 changes: 7 additions & 4 deletions scripts/template-pr.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/**
* The text of the cloudhal-template PR that scripts/template-sync.ts writes for
* .github/workflows/template-sync.yml (issue #111): what moved, what to read, what must pass.
* .github/workflows/template-sync.yml, or for a hand run of the script (issue #111): what moved,
* what to read, what must pass, and who opened it.
* A pure function over scripts/template-plan.ts's operations; Node built-ins only.
*/
import type { DepChange, SyncOp } from "./template-plan.ts";
Expand All @@ -11,7 +12,7 @@ export interface PrBodyOptions {
readonly from: string | undefined;
readonly to: string;
readonly deps?: readonly DepChange[] | undefined;
/** The workflow run that opened the PR. */
/** The workflow run that opened the PR; undefined when the script ran by hand. */
readonly runUrl?: string | undefined;
}

Expand Down Expand Up @@ -69,9 +70,11 @@ export function prBody(o: PrBodyOptions): string {
"",
"### Before merging",
"",
"The `cloudhal/template-check` status must be green: the Template sync run installed a copy of this branch with `npm ci` and ran `cloudhal deploy --dry-run` with `WORKERS_CI=1`. Merging changes what the Deploy to Cloudflare button deploys from now on; sites created earlier keep their theme.",
`The \`cloudhal/template-check\` status must be green: ${o.runUrl ? "the Template sync run" : "whoever synced by hand"} installed a copy of this branch with \`npm ci\` and ran \`cloudhal deploy --dry-run\` with \`WORKERS_CI=1\`. Merging changes what the Deploy to Cloudflare button deploys from now on; sites created earlier keep their theme.`,
"",
`Opened by the Cloudhal release workflow${o.runUrl ? ` ([run](${o.runUrl}))` : ""}. Do not push to this branch: a re-run of Template sync rebuilds it from \`main\` and replaces it.`,
o.runUrl
? `Opened by the Cloudhal release workflow ([run](${o.runUrl})). Do not push to this branch: a re-run of Template sync rebuilds it from \`main\` and replaces it.`
: "Opened by hand with `scripts/template-sync.ts` (CONTRIBUTING.md, Releasing), not by the Template sync workflow. Do not push to this branch: a run of Template sync rebuilds it from `main` and replaces it.",
"",
].join("\n");
}
3 changes: 2 additions & 1 deletion scripts/template-sync.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/**
* Moves cloudhal-template (the Deploy to Cloudflare button) to a Cloudhal release, issue #111.
* .github/workflows/template-sync.yml runs it after each npm publish, then refreshes the
* lockfile and opens the PR; scripts/template-plan.ts has the rules.
* lockfile and opens the PR; scripts/template-plan.ts has the rules. Without the workflow's
* GitHub App it runs by hand from a checkout, the same two commands (CONTRIBUTING.md, Releasing).
*
* node scripts/template-sync.ts --template <dir> --version <x.y.z>
* [--starter <dir>] [--wait <seconds>] [--summary <file>] [--check] [--allow-downgrade]
Expand Down
Loading