Skip to content

docs(learn): deploying from a CI/CD pipeline into Harper — best practices for private repos and registries - #594

Merged
Ethan-Arrowood merged 9 commits into
mainfrom
kris/ci-deploy-guide
Jul 27, 2026
Merged

docs(learn): deploying from a CI/CD pipeline into Harper — best practices for private repos and registries#594
Ethan-Arrowood merged 9 commits into
mainfrom
kris/ci-deploy-guide

Conversation

@kriszyp

@kriszypkriszyp commented Jul 17, 2026

Copy link
Copy Markdown
Member

Summary

Adds a Learn guide: “Deploying from a CI/CD Pipeline” (learn/developers/deploying-from-ci.mdx), covering the deploy-credentials capability that landed in harper#1797 — Reshape deploy_component registryAuth into a general-purpose credentials array and harper#1799 — Authenticate private git-reference deploys from an in-memory credential. Where PR #581 documents the reference shapes, this guide gives users the workflow: how to get from a GitHub repo, through a CI pipeline, into a Fabric cluster.

Stacked on #581 (kris/secrets-docs) — the guide links into the secrets store page and the credentials reference section that branch adds, so the base here is set to it. Merge #581 first, then retarget/merge this.

What the guide teaches

  • The core decision — git tag vs. registry artifact. Run-from-source apps (the common case) deploy directly from a semver git tag: no publish step, the repo is the artifact. Apps that need a build step publish a built artifact to a private registry (GitHub Packages in the examples) and deploy by version — the artifact CI tested is the artifact every node installs, and no build scripts run on database nodes (avoiding install_allow_scripts and its credential exposure). Private git-hosted dependencies also push toward the registry path (only the top-level clone is credentialed, by design).
  • Credentials — inline token as the primary flow. The workflows pass the token inline in credentials; Harper's auto-ingest (seal into hdb_secret under a derived name, strip before logging/replication, idempotent overwrite on redeploy) means there's no separate provisioning step and rotation is just updating the CI secret. Pre-provisioning via set_secret — or the Harper Studio UI — with a secret reference is presented as the alternative for keeping the GitHub token out of CI entirely.
  • Credential lifetime. The deploy credential outlives the deploy (new peers, rollbacks, re-installs resolve it later), so the guide explicitly warns against using the ephemeral Actions GITHUB_TOKEN as the deploy credential and calls for a durable fine-grained PAT (Contents: read) / read:packages token. The ephemeral GITHUB_TOKEN is still used where it belongs: npm publish inside the job.
  • Two complete GitHub Actions workflows (tag-triggered git-reference deploy; build → npm publish to GitHub Packages → deploy), with replicated: true + restart: "rolling" and deployment-record verification (get_deployment polling as a pipeline gate).
  • Operational notes: rollback = redeploy a pinned version (why #semver:vX beats #main), token rotation for both flows, git ≥ 2.31 / no-Windows constraints for git-host credentials, and the OSS-core-without-custody behavior.

Also in this PR

  • reference/components/applications.md: fixes install_allowInstallScriptsinstall_allow_scripts — the documented spelling never existed in harper source (verified against components/operationsValidation.js history).

Verification

  • Full docusaurus build passes locally (onBrokenLinks: throw); all cross-instance links use /reference/v5/... URL paths per learn-guide convention. The one broken-anchor warning is pre-existing on a release-notes page untouched here.
  • Behavior claims checked against harper main source: credentials validation schema, ingestCredentials/resolveCredentials (durable sealing + grant model + no-custody fallback), and the --ignore-scripts / install_allow_scripts gating from #1799.

🤖 Generated by Claude Fable 5 (an LLM) — please review accordingly.

kriszypand others added 6 commits July 13, 2026 11:24
…mponent registryAuth
Adds v5 reference documentation for the encrypted secrets store (#1550/#1554/
#1582) and the deploy_component private-registry auth path (#1717), none of
which was previously documented.
- reference/security/secrets.md (new): store model, custody (Pro) vs OSS core,
the two delivery tiers (process.env global vs scoped grants), the config.yaml
`env:` declaration block, the `import { secrets } from 'harper'` accessor,
full client-side `enc:v1:` envelope format + Node reference client, and the
threat model. Added to the Security sidebar.
- reference/operations-api/operations.md: new Secrets section (set_secret,
grant_secret, revoke_secret, list_secrets, delete_secret,
get_secrets_public_key) plus a registryAuth subsection under deploy_component.
- reference/components/javascript-environment.md: add `secrets` to the Harper
API globals list.
- reference/environment-variables/overview.md: cross-link to the secrets store
as the production alternative to a committed .env.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…584)
* style(operations-api): apply prettier table alignment
Pre-existing format:check violation on the kris/secrets-docs branch; the
repo-wide prettier gate must be clean for CI.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(security): document secrets change subscription and live scoped accessor
Documents harper#1787 (live secret change detection) on the new secrets
reference page:
- secrets.subscribe(name) — async iterable yielding the current value then
every change; shown as read-now + fire-and-forget background subscribe so
module load isn't blocked (the practical hot-swap-on-rotation pattern).
- Live scoped-tier accessor: a fresh secrets.NAME read reflects the latest
value; a destructure is now called out as a point-in-time copy.
- Reworked 'Healing after changes' into a per-tier 'How each tier sees a
change' table (scoped = live; global/process.env = reload-only) and
corrected the 'frozen' accessor description to the read-only live view,
with subscribe as a non-enumerable member.
Ships in v5.2.0 alongside the rest of the secrets store, so no differential
VersionBadge (the page is uniformly 5.2.0 surface).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(security): dedupe the subscribe example's startup rebuild
Address review on #584: secrets.subscribe() replays the current value
first, so guard on key change to skip the redundant client rebuild on
startup, and note that semantic inline.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(security): guard the subscribe example against unhandled rejections
Mirror the studio review fix (HarperFast/studio#1501): the fire-and-forget
subscribe loop is copy-paste code, so wrap it in try/catch and console.error
the failure so a stream error can't become an unhandled promise rejection.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs(security): lead with the live accessor; subscription is the exception
Per feedback: reading secrets.NAME (undestructured) returns the live value
on every read, so most components just use the secret where they need it —
e.g. per request inside a resource — and get the current value with no
subscription. Only a destructure takes a snapshot. Reframe subscribe() as
the case for long-lived objects built from a secret (client/pool/signer)
that must be rebuilt on rotation, and make the loader note's per-loader
boundary explicit (vm/compartment read live anywhere; native resolves only
during load).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…deploy auth
deploy_component's registryAuth field was renamed to a general-purpose
`credentials` array (harper#1797) that now carries both npm-registry
(`registry`) and git-host (`host`) credential entries; the git-over-HTTPS
path (harper#1792) serves the token to git from memory via a credential
helper. Update the operations reference and the secrets page accordingly,
including the derived secret-name conventions and a rename note.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Note that Harper Studio offers a graphical interface for managing secrets
(Dawson's suggestion) on both the Secrets page and the operations section.
- Clarify that a string env value is stored plaintext in config.yaml (VCS).
- Add a list_secrets response example.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…InstallScripts never existed)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…dentials, GitHub Actions
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kriszyp
kriszyp requested a review from a team as a code ownerJuly 17, 2026 15:50

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new guide on deploying Harper applications from a CI/CD pipeline, updates the sidebar configuration to include this new document, and renames the install_allowInstallScripts option to install_allow_scripts in the applications reference documentation. The review feedback highlights critical syntax issues in the provided GitHub Actions workflow examples, specifically regarding indented heredoc delimiters (EOF) which will cause bash execution failures. Additionally, it is recommended to adjust the Authorization header handling to support both Basic and Bearer tokens dynamically by storing the full header value in the HARPER_OPS_AUTH secret.

Comment threadlearn/developers/deploying-from-ci.mdx Outdated
Comment threadlearn/developers/deploying-from-ci.mdx
Comment threadlearn/developers/deploying-from-ci.mdx
@github-actions
github-actionsBot temporarily deployed to pr-594 July 17, 2026 15:53 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL:https://preview.harper-documentation.harperfabric.com/pr-594

This preview will update automatically when you push new commits.

…ention Studio UI for set_secret
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions
github-actionsBot temporarily deployed to pr-594 July 17, 2026 16:03 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL:https://preview.harper-documentation.harperfabric.com/pr-594

This preview will update automatically when you push new commits.

Comment threadlearn/developers/deploying-from-ci.mdx Outdated
…reference
CI's Format Check was failing on markdown table alignment and italic-marker
style in these two files.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions
github-actionsBot temporarily deployed to pr-594 July 18, 2026 17:46 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL:https://preview.harper-documentation.harperfabric.com/pr-594

This preview will update automatically when you push new commits.

…me typo
- HARPER_OPS_AUTH now documented (and used in the curl examples) as the
full Authorization header value, so a Bearer token works as well as
Basic — the hardcoded "Authorization: Basic $HARPER_OPS_AUTH" would
break for bearer-token users.
- Fix derived secret name example: deploy.my-app.git.github_com ->
deploy.my-app.git.github.com (deriveGitSecretName preserves dots).
Addresses review feedback from gemini-code-assist and cb1kenobi on
PR #594. The heredoc-EOF-indentation concern raised alongside the auth
header comments does not apply here: verified against a YAML parser
that the block-scalar's common-indentation stripping puts EOF at
column 0 in the actual generated script, since it shares curl's base
indent.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions
github-actionsBot temporarily deployed to pr-594 July 21, 2026 02:22 Inactive
@github-actions

Copy link
Copy Markdown

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL:https://preview.harper-documentation.harperfabric.com/pr-594

This preview will update automatically when you push new commits.

@cb1kenobicb1kenobi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@Ethan-ArrowoodEthan-Arrowood left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM on the content — accurate and security-conscious (least-privilege PATs, memory-only git tokens, log/replication stripping, the secret-reference alternative), and I confirmed the heredoc-EOF block is valid as written.

One logistical note: this is stacked on #581, so let's only merge once #581 lands and this retargets main.

sent with Claude Opus 4.8

Base automatically changed from kris/secrets-docs to mainJuly 27, 2026 14:30
@Ethan-Arrowood
Ethan-Arrowood merged commit d8d7ba4 into mainJul 27, 2026
7 checks passed
@Ethan-Arrowood
Ethan-Arrowood deleted the kris/ci-deploy-guide branch July 27, 2026 14:38
@github-actions

Copy link
Copy Markdown

🧹 Preview Cleanup

The preview deployment for this PR has been removed.

Sign up for freeto 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.

4 participants

@kriszyp@cb1kenobi@Ethan-Arrowood@dawsontoth