Repository navigation
Deploying from CI: lead with OIDC, and correct the deploy reference where it disagrees with Harper #711
Description
Part of HarperFast/create-harper#143.
These are the gaps found while planning create-harper's deploy-on-merge workflow, checked against this repository at 2cfb813 and Harper main at be4009ca5 on 2026-10-06. Line numbers are from 2cfb813. No open issue or PR covers sections 1–3, 5 or 6. Some items were added or left by #707, #710 and #685, so they are recent.
1. The CI guide predates OIDC
learn/developers/deploying-from-ci.mdx was written in #594, before OIDC trusted publishing was documented in #637.
- Stored secrets. It authenticates with stored secrets, sent with curl (deploying-from-ci.mdx L91-107, deploying-from-ci.mdx L167-185): a super-user credential (
HARPER_OPS_AUTH) and GitHub tokens (GH_DEPLOY_TOKEN,GH_PACKAGES_TOKEN). - Tags only. It runs on
v*tags only (deploying-from-ci.mdx L80-82, deploying-from-ci.mdx L140-142). - Wrong version. It requires "Harper 5.2+" (deploying-from-ci.mdx L24), yet it describes canary certification (deploying-from-ci.mdx L114, deploying-from-ci.mdx L197, deploying-from-ci.mdx L222), which ships in 5.4.0. Date canary certification to 5.4.0, and add it to the 5.4 release notes #710 re-dated canary certification in
operations.md, but not here. - A wait step OIDC can't use. It waits for the rolling job with curl and
HARPER_OPS_AUTH(deploying-from-ci.mdx L199-220). Under OIDC the operation token never leaves the CLI, so this step can't be used.
What to change:
- Lead with OIDC, using one complete workflow that runs as written:
on,jobsandruns-on, a checkout, andnpm install -g harper;permissions: id-token: writeon the deploy job, plusenvironment;vars.HARPER_CLI_TARGET;harper deploy project=… restart=rolling json=true > deploy.json;- a wait that polls
harper get_job. Progress goes to stderr (bin/deployRenderer.ts), so stdout stays parseable.
- Next to the workflow, show the trust policy and the deploy-only role. The role needs
get_job(see section 2). - Explain how to write the policy for a tag-triggered workflow: pin
workflow_pathand gate onenvironment, sinceworkflow_refcan't pin a tag (operations.md L777). - Keep the curl paths as the alternative for other CI systems. Use
secretreferences instead of literal tokens, since a literaltokenneeds super user (operations.md L742). - Mark the canary text as 5.4.0+.
2. OIDC examples and roles
-
The two OIDC examples are fragments. Both
reference/cli/authentication.md(authentication.md L269-279) andoperations.md(operations.md L623-632) putenvironmentandstepsat the top level, with noon,jobsorruns-on, and no CLI install. The first is even labelled.github/workflows/deploy.yml. They also disagree with each other:by_ref=true restart=true replicated=trueagainstby_ref=truealone, which restarts nothing and so is never certified. Replace both with a link to the guide's workflow. -
The role and policy examples omit
get_job. These examples list operations without it:- the role example (operations.md L730-742):
["deploy_component","get_deployment"]; - the inline example (operations.md L688): the same list;
- the scoped policy (operations.md L711): adds
restart_service.
But the guide's wait step polls
get_job. An operations allowlist and a token's scope both refuse operations they don't list (utility/operation_authorization.ts,utility/operation_authorization.ts), so the wait step gets a 403. The jobs table's "Role Required: any" forget_job(operations.md L1912) hides this.restart_serviceisn't needed, because the rolling job is created internally. - the role example (operations.md L730-742):
-
The CLI overview still recommends the refresh token.
reference/cli/overview.mdcalls the refresh token "recommended for CI/CD" and doesn't mention workload identity (overview.md L161-168). That contradictsauthentication.md(authentication.md L55).
3. harper deploy and the CLI reference
- Say that
harper deploy restart=rollingexits 0 once the rolling job starts (commands.md L142), and give the CLI wait recipe. This stays true untilharper deploy restart=rollingexits 0 before the other nodes have taken the release harper#3058 ships. - Add
activate=falseanddeployment_id=toharper deploy's parameters (commands.md L135-165). Note thatrestartcan't be combined withactivate=false. - Fix where
replicatedis described as opt-in: commands.md L143, deploying-from-ci.mdx L113 andreference/components/applications.md(applications.md L348). On Harper Pro and Fabric, a deploy replicates unless you passreplicated: false. Core on its own doesn't replicate. Draft Add production reliability guides for Harper operators #671 rewritesapplications.mdandoperations.mdaround this. - Fix the version for
harper loginandharper logout, which are dated v5.0.0 (commands.md L260, commands.md L298). They shipped in v5.1.0, as authentication.md L74 says. - Fix the claim that
harper loginsetsHARPER_CLI_TARGETin.env(authentication.md L151-155, overview.md L177, cluster-creation-management.md L62). It only appends to a.envthat already exists and doesn't already set a target (bin/login.ts). commands.md L264 ("if it exists") is closest to right. - Fix the install command
npm i -g harperdb(overview.md L22). On npm that installs 4.7.39, which has no login, OIDC or by-reference deploys. Usenpm install -g harper, as the getting-started guide does.
4. applications.md → Remote Management
This is the source of the deploying-to-harper-fabric skill, so it is what agents learn from.
- It recommends
HARPER_CLI_USERNAMEandHARPER_CLI_PASSWORDfor CI/CD (applications.md L104-115). Point to workload identity instead. - It says "Roll back by deploying an older commit" (applications.md L184). Since 5.3.0, going back means activating the kept release's
deployment_id(Going back to a previous release). Keepref=<sha>as the way to deploy a particular commit.
5. Deployment records (operations.md)
-
deployment_idis a random UUID, not a content hash. operations.md L1208 calls it a "content hash", but each deploy gets a random UUID (components/deploymentRecorder.ts). The content hash ispayload_hash. -
list_deploymentshas no defaultlimit. operations.md L1179 says it defaults to 100, but leavinglimitout returns every row (components/deploymentOperations.ts). - The statuses are incomplete (operations.md L1211-1212):
loading,replicatingandrestartingoccur while a deploy runs, so filtering onpendingmisses deploys in flight.rolled_backandrollback_ofare never written. Going back writes a newsuccessrecord withactivated_from, which operations.md L1221 describes only for staged builds.- A stage whose peers fail returns an error, but its record stays
staged, witherrorset.
- Some fields are undocumented, and
erroris misdescribed.origin_node,restart_mode(immediate,rollingor null),credentials(references only) andpayload_blob_presentare returned but not documented.erroris described as a message (operations.md L1223), but it's an object:{ message, code, phase }. - The record and "what is deployed" disagree for rolling deploys. With
restart: 'rolling', the record sayssuccessbefore the other nodes take the release, and keeps saying it if one of them rejects the release. This stays true until A rolling deploy's record sayssuccesseven when another node rejects the release harper#3060 ships. Reconcile it with the sentence recommendinglist_deploymentsfor "what exactly is deployed right now". -
delete_deployment_payloadalso acceptsstaged. operations.md L1261 listssuccess,failedandrolled_back, and operations.md L959 already says a staged deployment works.
6. Streaming progress
- Document the SSE events. A streamed
deploy_componentsendsphase,install,peer,warning,payload_dropped,erroranddone, withdonecarrying{ result }. A replayed log can includetruncated.phasecan also bepending,successorstaged.- On 5.4,
loadbrackets the canary's decision, so a deploy that doesn't restart no longer emits it (operations.md L1167, commands.md L131).
- The live tail only follows a deploy running on the node that answers.
get_deployment's live tail (operations.md L1195) depends on this. Through a load balancer, it replays the log and returns, possibly with a status that isn't terminal.
Related
- deploying-to-harper-fabric: deploy from CI with OIDC, and go back by
deployment_idskills#117 regeneratesdeploying-to-harper-fabricfrom these pages. harper deploy restart=rollingexits 0 before the other nodes have taken the release harper#3058, Report which deployment is live on each node, and which releases each node keeps harper#3059, A rolling deploy's record sayssuccesseven when another node rejects the release harper#3060 and Record where a deploy came from: the commit, the CI run and the trust policy harper#3061 are Harper changes that some of these sentences will need to follow.- These issues and PRs overlap:
- Documentation: v5.1 release coverage #548, the v5.1 docs coverage umbrella, lists deployment tracking. Section 5 could sit under it.
- Add Harper deploy behavior #478 covers
harper deployon CI runners. - Rename CLI commands from harperdb to harper #399 covers renaming
harperdbcommands toharper. - Draft Add production reliability guides for Harper operators #671 covers the
replicateddefault, and adds a safe-deployments-and-rollback page that should usedeployment_idfor going back.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Activity
Lead the CI deploy guide with OIDC, and correct the deploy reference …
feat(harper-best-practices): regenerate the deploy rules from the rew…
feat(harper-best-practices): deploy from CI with OIDC, and roll back …
feat(harper-best-practices): deploy from CI with OIDC, and roll back …
feat(harper-best-practices): deploy from CI with OIDC, and roll back …
chore(release): 1.15.0 [skip ci]