feat: deploy-by-reference via native harper CLI (prototype / draft) - #118
feat: deploy-by-reference via native harper CLI (prototype / draft)#118dawsontoth wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the deployment process across multiple project templates to deploy "by reference" using the native harper CLI. It adds a new GitHub Actions workflow (deploy.yaml), updates package.json scripts to include deploy and deploy:setup, and updates the documentation in README.md files. Feedback on these changes highlights that the template-early-hints template was only partially updated, missing changes to its package.json and README.md. Additionally, installing the harper CLI globally in the workflow without a version pin could introduce breaking changes in the future, and the duplication of the deploy.yaml file across all template directories should be addressed by dynamically copying it from a centralized location.
217a381 to
161efc2
Compare
Templates deploy by *reference* (the Harper cluster clones a pinned commit over SSH) with no per-project scripts: deploy -> `harper deploy by_ref=true restart=true replicated=true`, deploy:setup -> `harper deploy setup=true`. Centralized GitHub Actions workflow (.github/workflows/deploy.yaml — also fixes the singular workflow/ -> workflows/ path bug so GitHub runs it); tag+dispatch triggered. .env carries only CLI_TARGET (creds via harper login / CI secrets). README deployment sections rewritten around the reference model. End-state assuming native CLI support has landed: harper#1777 (by_ref), harper#1778 (deploy setup), harper-pro#570 (add_ssh_key generate). Tracks create-harper#117. DRAFT until those release. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…rly-hints Pin the workflow's global install to `harper@^5.2.0` (the 5.2 line where deploy-by-reference lands; blocks a breaking 6.x bump) instead of unpinned latest. Exclude template-early-hints (a legacy harperdb EdgeWorker example, not published via npm create harper) from the deploy migration: remove the stray _github workflow it got via fan-out, and filter _github out of applySharedTemplates for it so it isn't re-added (it keeps every other shared file). The per-template deploy.yaml duplication is intentional (templates-shared/README.md: shared files are committed into each template for discoverability + wholesale-copy scaffolding), so it's left as-is. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Aligns the scaffold with where the deploy design landed (harper#1799 in-memory git-host credential + client-side-sealed durable tokens) instead of SSH deploy keys: deploy -> `harper deploy by_ref=true credential=github.com ...` (git+https ref + a sealed-token credential reference the cluster resolves at clone time; public repos drop credential=github.com). deploy:setup -> `harper deploy setup=true` seals a durable GitHub/npm token locally with the cluster's public key and stores only ciphertext. README rewritten around the sealed-token flow; the workflow no longer handles any token itself. Depends on harper#1777 (by_ref git+https + credential), harper#1778 (deploy setup), harper#1799. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Follows main's Next.js templates and harper#1876's CI credential flow. Next.js stays on deploy-by-payload, deliberately. By-reference means the cluster clones the repo and builds on the node, which Next.js can't do: `.next` is gitignored, so a git reference carries no build output, and an on-cluster build currently fails outright (Turbopack crashes in a Harper worker thread, HarperFast/nextjs#57; a webpack build overruns the component-load timeout, HarperFast/nextjs#58). They keep `next build && harper deploy_component .` until those land. `applySharedTemplates.js` records why they're absent from the fan-out, so their omission reads as a decision rather than an oversight. They do get the `_github/workflow/` → `_github/workflows/` fix this PR makes everywhere else — GitHub only runs workflows from the plural directory, so the one they shipped never triggered — plus their own payload-deploy workflow with the same auth wiring. CI now authenticates with a token instead of a password. The workflows consume HARPER_CLI_TARGET + HARPER_CLI_REFRESH_TOKEN (harper#1876) rather than HARPER_CLI_USERNAME/HARPER_CLI_PASSWORD, and the docs point at the pipe that sets both without the token ever reaching the screen or shell history: harper login --for-ci | gh secret set --env-file - template.test.js asserts the deploy model per template, with the payload-based ones as an explicit allow-list — a newly added template fails the by-reference assertions until it's either wired up or added there with a reason, so it can't silently opt out. Verified by flipping the list: exactly the two Next.js templates fail, confirming the assertions actually run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6199d28 to
f352445
Compare
|
Rebased onto 1. Next.js templates landed on main, and they can't use deploy-by-reference. By-reference means the cluster clones the repo and builds on the node. Next.js can't do that today: So they stay on deploy-by-payload ( They do get the 2. CI auth moved from password to token (harper#1876). The workflows now take harper login --for-ci | gh secret set --env-file -Testing. Worth flagging:
|
kriszyp
left a comment
There was a problem hiding this comment.
This looks good. I kinda did two GPT reviews, which is probably a bit excessive, but hopefully helpful:
Overall, this is well aligned with the deployment guidance. The immutable-SHA reference model, cluster-stored clone credential, token-based CI authentication, and payload exception for Next.js all look right. It effectively implements the newer workflow from documentation#616 rather than documentation#594’s lower-level curl examples.
I have two changes before approval:
The generated commands use restart=true with replicated=true. Documentation#594 recommends restart=rolling for cluster deployments and reserves restart=true for single-node/dev use. Since the scaffolded workflow targets Fabric clusters, can we default its deployment to restart=rolling, or document why an immediate cluster-wide restart is intended?
The READMEs describe HARPER_CLI_REFRESH_TOKEN as long-lived but omit two operational constraints: CI should use a dedicated user because issuing another refresh token invalidates the existing one, and the default refresh-token lifetime is 30 days. Please add a short warning so generated pipelines do not unexpectedly break after a local login or token expiry.
The PR description also needs refreshing: it still mentions SSH, password-based CI authentication, and the superseded dependency PR numbers, while the implementation now uses git+HTTPS, sealed tokens, and harper#1850/#1851/#1876.
Finally, this should remain blocked until harper#1850 and harper#1851 land in a released CLI. The current CI proves the templates generate correctly, but it cannot exercise those unreleased commands.
🤖 Reviewed with GPT 5.6
| - name: Set up Node.js | ||
| uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0 | ||
| with: | ||
| cache: 'npm' |
There was a problem hiding this comment.
This now makes the previously inert workflow run, but it is hard-coded to npm even though create-harper detects and installs with pnpm, Yarn, Bun, and Deno too. For example, a project created with pnpm create harper commits pnpm-lock.yaml, so setup-node's npm cache cannot resolve a package lock and the following npm ci fails; the tag workflow never reaches tests or deploy. Please generate the cache/install/run setup from the detected package manager (and apply the equivalent fix to both standalone Next.js workflows), or deliberately generate an npm lockfile and document npm-only CI. Please also exercise at least one non-npm user agent in the scaffold test so this path cannot regress.
What this shows
The end-state of the deploy-by-reference switch (create-harper#117): scaffolded projects deploy by reference (the Harper cluster clones a pinned commit over SSH) with no per-project scripts.
package.json:deploy→harper deploy by_ref=true restart=true replicated=true;deploy:setup→harper deploy setup=true..github/workflows/deploy.yaml— also fixes a latent bug: templates shipped a singular_github/workflow/that GitHub never runs; nowworkflows/(plural). Tag- and dispatch-triggered..envcarries onlyCLI_TARGET; credentials come fromharper login(local) or GitHub Actions secretsCLI_TARGET/HARPER_CLI_USERNAME/HARPER_CLI_PASSWORD(CI).Relationship to the ships-today version
The interim version that works with the currently released CLI carries
scripts/deploy.mjs+scripts/setup-deploy.mjs(the logic lives in the project until the CLI can do it natively). It's on branchclaude/harper-deployment-path-dd2495. This PR is the same feature with those scripts folded into the CLI.Blocked on (must release first)
harper deploy by_ref=true— deploy by git reference harper#1777 —harper deploy by_ref=true(prototyped, branchclaude/deploy-by-ref-flag)harper deploy --setup— one-command deploy-key provisioning harper#1778 —harper deploy setup=truegenerate: trueharper-pro#570 —add_ssh_key generate=true(drafted, branchclaude/add-ssh-key-generate)Tracks create-harper#117. Rollback: HarperFast/harper#641.
Notes
deploy:setupspelling (setup=truevs--setupvs a dedicatedharper add-deploy-key) is TBD per harper#1778; this PR usessetup=trueto match the CLI'skey=valuearg model.npm test(213 tests) green;dprint+oxlintclean.🤖 Generated with Claude Code
Related — deploy-by-reference effort
HarperFast/harper#1849— two-phase stage/activate +revert_componentHarperFast/harper#1850—harper deploy by_ref=true(deploy by git reference)HarperFast/harper#1851—harper deploy setup=true(client-side sealed deploy credential)HarperFast/harper#1876— CI token auth +harper login --for-ciHarperFast/harper-pro#594—add_ssh_key generate=true(cluster-side keygen)HarperFast/create-harper#118— scaffolds this flowHarperFast/documentation#599— two-phase deploy docsHarperFast/documentation#616— by-reference / sealed-credential / CI-auth docs