Skip to content

feat(harper-best-practices): deploy from CI with OIDC, and roll back by deployment_id - #119

Merged
dawsontoth merged 4 commits into
mainfrom
gen/deploying-oidc-and-deployment-id
Oct 14, 2026
Merged

dawsontoth merged 4 commits into
mainfrom
gen/deploying-oidc-and-deployment-id

Conversation

@dawsontoth

@dawsontoth dawsontoth commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

⊙ Problem

harper-best-practices taught deploys from before Harper 5.3: CI signed in with a stored username and password, and nothing mentioned the deploy workflow create-harper now scaffolds. Given only the skill, an agent on main writes a deploy workflow it can't authenticate, or keeps a refresh token in a GitHub secret.

💡 Solution

Deploy guidance is now two rules generated from documentation@81c1b0e. deploying-from-ci leads with harper deploy setup=true provider=github-actions (HarperFast/harper#3127), which sets up OIDC trusted publishing in one command, and keeps the hand-written policy for tag releases. deploying-to-harper-fabric covers restart modes, canary certification, staging, and going back by deployment_id. creating-harper-apps covers create-harper's scaffolded workflow and deploy:setup-ci (HarperFast/create-harper#147). Closes #117.

This is meant to merge before Harper 5.4.0, which ships the setup command, is published. Until then, the rules send earlier versions to the hand-written route, with commands for the scaffolded workflow.

⚖️ Alternatives

  • One wider deploy rule, as deploying-to-harper-fabric: deploy from CI with OIDC, and go back by deployment_id #117 proposed first: its input would be ~65KB, against ~31KB and ~35KB for the two halves, and regeneration compresses away more facts the larger the input.
  • Generating the bodies with npm run generate: there's no ANTHROPIC_API_KEY here, so they're hand-written to the generator's template with real input hashes, as you OK'd. sync:report lists both as current, and the next regeneration resamples them.
More for the reviewer

🔧 Changes

Reviewers flagged three points in the workflows the CI rule quotes from the docs: Path A's persisted checkout token, its unpinned harper install, and Path B building in the job that holds id-token: write, which create-harper's Next.js workflow also does. A fix here would be regenerated away, so HarperFast/documentation#731 and HarperFast/create-harper#151 fix them at the source, and the rule picks them up on the next sync. #731 drops npm install -g harper from the sourced sections, so the anchor is now npm install --global harper@^5.3, and Path A's quote matches #731's checkout and install. Validate passes whichever PR merges first.

✅ Verification

Agents given only the skill, on main and on this branch, answered three deploy requests. On this branch they ran the setup command (with workflow= for a deploy.yml), npm run deploy:setup-ci for a scaffolded project, and the hand-written policy for v* tags, storing no secrets. On main they wrote workflows with no way to authenticate. The setup command itself wasn't run, because 5.4.0 isn't published.

Agent answers, smoke test and checks
  • Agents. Sonnet agents, each told to read only a copy of the skill and answer three requests:

    Request Skill from main Skill from this branch
    "Set up automatic deploys to our Fabric cluster from GitHub Actions whenever we merge to main" (repository not from create-harper, workflow file deploy.yml) A workflow with id-token: write and no trust policy or deploy user ("details not in skill"); else a harper login --for-ci token kept as a GitHub secret harper deploy setup=true provider=github-actions project=my-app workflow=.github/workflows/deploy.yml, with json=true and the wait step in the job; no secrets
    "I just scaffolded this project with npm create harper@latest. How do I get it deploying to my Fabric cluster?" npm run deploy from the machine, optionally with CLI_TARGET_USERNAME/CLI_TARGET_PASSWORD in .env; doesn't know the project has a workflow Push to GitHub, run npm run deploy:setup-ci once (5.4.0), then merge to main; npm run deploy by hand, going back by deployment_id
    "We cut releases by pushing v* tags. Set up GitHub Actions to deploy each tag" A tag workflow running harper deploy ref=${{ github.ref_name }}, with authentication left open The hand-written role (with registration_info) and a workflow_path policy gated on the production environment, restricted to v* tags; Path A's workflow with its wait step
  • Live smoke test, on a throwaway Harper 5.3.1, of the hand-written route's commands (run against an earlier revision of the rules; the role now also lists get_deployment and registration_info):

    • add_role with an operations list, add_user, add_oidc_trust with claims (both a workflow_ref policy and a tag-release workflow_path one), list_oidc_trust, drop_oidc_trust, and alter_user active=false. After the last, list_oidc_trust reported invalid_reason: names inactive user 'ci-deploy'. An audience without a port was rejected as the rules say.
    • v1 and v2 deployed with restart=true each returned a deployment_id, list_deployments listed them, and harper deploy project=my-app deployment_id=<v1> restart=true served v1 again. A payload staged with activate=false left v1 serving until its id was activated, and restart with activate=false was refused.
    • harper get_job id=<restartJobId> reported IN_PROGRESS, then ERROR: single-node core can't run a rolling restart ("Replication not implemented"), as the guide says. A real OIDC exchange from GitHub and canary certification (5.4.0) were not exercised.
  • npm run validate passes: format, build, tests, both validators, and the relationship lint.

  • node scripts/generation/validate-generated.mjs --docs-path <documentation@81c1b0e> passes, fact retention and every must_cover anchor included, and npm run sync:report lists both deploy rules as current with 81c1b0e. It lists load-env as stale from unrelated docs changes; docs: regenerate rules from documentation@356a3bf #123 regenerates it.

🤖 Generated with Claude Code

Related PRs: #122 supersedes (its deploying-to-harper-fabric body, as with #121's before it), #120 independent
Complexity: medium

Deferred findings

  • 3ff0dc941e775055 nit maintainability — harper-best-practices/rules.manifest.yaml — New manifest comments restate docs or identifiers instead of a minimal reason — NOT FILED

Review-Coverage: authored=claude; ran=cursor-muse,gemini,codex,cursor-grok; adjudicated=domain; blocked=cursor-composer(no-receipt); declined=cursor-kimi,muse; rounds=7; full=3 @ 638e8a1

Review-Attention: study ~9m (decisions: do-less-alternative, fix-workflows-upstream, substring-anchors-for-yaml; raised: degraded review, open major) @ 638e8a1

gemini-code-assist[bot]

This comment was marked as resolved.

@dawsontoth
dawsontoth marked this pull request as ready for review October 8, 2026 20:52
@dawsontoth
dawsontoth requested a review from a team as a code owner October 8, 2026 20:52
@dawsontoth
dawsontoth force-pushed the gen/deploying-oidc-and-deployment-id branch 2 times, most recently from b3930d9 to 8bbfbbb Compare October 8, 2026 21:24
@dawsontoth
dawsontoth marked this pull request as draft October 12, 2026 13:39
dawsontoth and others added 3 commits October 14, 2026 13:00
…by deployment_id

Split the deploy guidance into two rules generated from the docs, against
documentation@e73e5ef (after HarperFast/documentation#711):

- deploying-to-harper-fabric covers a CLI deploy and what happens to the
  release afterwards: restart modes and canary certification, waiting on
  a rolling deploy's job on the node that received it, staging with
  activate=false, and going back to a kept release by its deployment_id
  instead of redeploying an older commit. Deploys replicate by default on
  Pro and Fabric.
- deploying-from-ci is new. It sources the rewritten CI guide: a
  deploy-only role and user, a trust policy gated on a GitHub
  environment, Path A's complete workflow with its get_job wait,
  private-source credentials, Path B, the deployment record, and
  diagnosing and revoking a policy.

As one rule, the sources would come to ~57KB, well over any other rule's
input; split, each is ~27-30KB. must_cover anchors pin the new facts,
including the workflow's checkout, CLI install, job wrapper and wait
loop.

The bodies are hand-written against the sources, following the
generator's prompt, and committed with the docs build's input hashes.

Part of #117.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…crets

creating-a-fabric-account-and-cluster told agents to put the cluster
username and password in .env or in GitHub Actions secrets. It now has
the CLI run harper login and set HARPER_CLI_TARGET, and sends CI to
deploying-from-ci, which stores no credential.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Regenerate the deploy rules against documentation@81c1b0e, which documents
`harper deploy setup=true provider=github-actions` (HarperFast/harper#3127,
HarperFast/documentation#722). deploying-from-ci now leads with that setup
and the four conditions under which a job's harper commands authenticate,
and keeps the hand-written role and policy for tag releases and
customization, with `registration_info` added to the role.
creating-harper-apps covers the deploy workflow create-harper 1.13.0
scaffolds (HarperFast/create-harper#147): deploy:setup-ci once, merge to
main to deploy, npm run deploy by hand, and going back by deployment_id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dawsontoth
dawsontoth force-pushed the gen/deploying-oidc-and-deployment-id branch from 221206c to beec766 Compare October 14, 2026 17:36
@dawsontoth
dawsontoth marked this pull request as ready for review October 14, 2026 17:47
…I install

The CI guide now installs harper@^5.3 and checks out with
persist-credentials: false (HarperFast/documentation companion PR), so
the 'npm install -g harper' anchor would no longer occur in the rule's
sources. Anchor the pinned install instead, and quote Path A's checkout
and install steps as the guide now writes them, so Validate passes
whichever of the two PRs merges first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dawsontoth
dawsontoth merged commit 5490f3f into main Oct 14, 2026
3 checks passed
@dawsontoth
dawsontoth deleted the gen/deploying-oidc-and-deployment-id branch October 14, 2026 20:55
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.15.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

deploying-to-harper-fabric: deploy from CI with OIDC, and go back by deployment_id

1 participant