docs(deploy): by-reference deploys, sealed credentials, CI token auth (draft) - #616
Conversation
Builds on the two-phase deploy docs (#599) to cover the rest of the deploy-by-reference workflow. reference/components/applications.md - "Deploying by Reference" — `harper deploy by_ref=true`, `ref=`, `credential=`. Explains why a reference pins to a resolved SHA rather than the tag or branch name typed: peers resolve the package independently, so a tag that moves mid-deploy could otherwise leave nodes running different code. Notes that the cluster clones the pushed remote, and that by-reference means the cluster builds from source — so an app whose build can't run on the node should stay on payload deploys. - "Provisioning a Deploy Credential" — `harper deploy setup=true`, the client-side sealing flow, and that reverting to the previous version needs no credential at all. reference/cli/authentication.md - Documents HARPER_CLI_REFRESH_TOKEN / HARPER_CLI_OPERATION_TOKEN and adds "Token credentials for CI/CD", so the CI guidance is no longer "put an admin password in your pipeline". Covers precedence, in-memory-only refresh, and token lifetimes (1d / 30d defaults). - Warns that a user holds only ONE valid refresh token at a time: issuing a new one invalidates the last, so a routine local `harper login` silently breaks a pipeline using the same account. Hence the recommendation to give CI its own user. (Verified against security/tokenAuthentication.ts, which stores a single hashed refresh_token per user record.) reference/cli/commands.md - `harper login --for-ci`, including the stdout/stderr split that makes `| gh secret set --env-file -` work without displaying the token. reference/security/secrets.md - Points the existing private-source deploy credentials section at the CLI flow that automates it. Documents HarperFast/harper#1850, #1851, and #1876. Verified every anchor link in the changed files resolves (16 checked). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🚀 Preview DeploymentYour preview deployment is ready! 🔗 Preview URL: https://preview.harper-documentation.harperfabric.com/pr-616 This preview will update automatically when you push new commits. |
There was a problem hiding this comment.
Code Review
This pull request updates the Harper CLI documentation to introduce features added in v5.2.0, including token-based credentials for CI/CD pipelines via harper login --for-ci, deploying components by git reference, and provisioning deploy credentials securely using client-side encryption. The review feedback correctly points out that the GitHub CLI (gh) does not support the --env-file flag used in the documentation examples, and provides a shell loop alternative to set multiple secrets from the command output.
| # Set both GitHub Actions secrets in one command — the token is never displayed | ||
| harper login --for-ci | gh secret set --env-file - |
There was a problem hiding this comment.
The gh secret set command in the GitHub CLI does not support a --env-file flag. To set multiple secrets from an environment file, you typically need to loop over the file's contents in your shell script or use a custom gh extension.
Consider providing a standard shell loop or pointing to the correct syntax for setting individual secrets.
| # Set both GitHub Actions secrets in one command — the token is never displayed | |
| harper login --for-ci | gh secret set --env-file - | |
| # Set GitHub Actions secrets by looping over the env-file output | |
| harper login --for-ci | while read -r line; do gh secret set "${line%%=*}" -b "${line#*=}"; done |
There was a problem hiding this comment.
Not applying this one — gh secret set --env-file does exist, and - for stdin works. Verified on gh version 2.92.0:
$ gh secret set --help | grep env-file
-f, --env-file file Load secret names and values from a dotenv-formatted file
$ printf 'FOO=bar\nBAZ=qux\n' | gh secret set --env-file - --repo HarperFast/does-not-exist-xyz
failed to fetch public key: HTTP 404: Not Found (…/does-not-exist-xyz/actions/secrets/public-key)
The second command consumed stdin and got as far as the API call — it failed on the deliberately nonexistent repo, not on reading the file. A rejected - would have failed earlier with a file error.
Worth adding that the suggested loop would be a downgrade for this specific use: gh secret set NAME -b "$VALUE" puts the token in the process's argument list, where it's visible to ps for the life of the call and may land in shell history. Keeping the token on stdin and never in argv is precisely why --for-ci writes a dotenv block rather than printing a value to copy.
🤖 Reviewed by Claude Code
| # Set both GitHub Actions secrets in one command | ||
| harper login --for-ci | gh secret set --env-file - |
There was a problem hiding this comment.
The gh secret set command in the GitHub CLI does not support a --env-file flag. To set multiple secrets from an environment file, you typically need to loop over the file's contents in your shell script or use a custom gh extension.
Consider providing a standard shell loop or pointing to the correct syntax for setting individual secrets.
| # Set both GitHub Actions secrets in one command | |
| harper login --for-ci | gh secret set --env-file - | |
| # Set GitHub Actions secrets by looping over the env-file output | |
| harper login --for-ci | while read -r line; do gh secret set "${line%%=*}" -b "${line#*=}"; done |
There was a problem hiding this comment.
Not applying this one — gh secret set --env-file does exist, and - for stdin works. Verified on gh version 2.92.0:
$ gh secret set --help | grep env-file
-f, --env-file file Load secret names and values from a dotenv-formatted file
$ printf 'FOO=bar\nBAZ=qux\n' | gh secret set --env-file - --repo HarperFast/does-not-exist-xyz
failed to fetch public key: HTTP 404: Not Found (…/does-not-exist-xyz/actions/secrets/public-key)
The second command consumed stdin and got as far as the API call — it failed on the deliberately nonexistent repo, not on reading the file. A rejected - would have failed earlier with a file error.
Worth adding that the suggested loop would be a downgrade for this specific use: gh secret set NAME -b "$VALUE" puts the token in the process's argument list, where it's visible to ps for the life of the call and may land in shell history. Keeping the token on stdin and never in argv is precisely why --for-ci writes a dotenv block rather than printing a value to copy.
🤖 Reviewed by Claude Code
🧹 Preview CleanupThe preview deployment for this PR has been removed. |
#599 documents the two-phase deploy and
revert_component. This covers the rest of the deploy-by-reference workflow — how you point a cluster at a commit, how it authenticates to a private source, and how CI authenticates to the cluster.Documents harper#1850 (
by_ref), harper#1851 (deploy setup), and harper#1876 (CI token auth).add_ssh_key generate=true(harper-pro#594) is already covered by #599.What this adds
reference/components/applications.mdDeploying by Reference —
harper deploy by_ref=true, plusref=andcredential=. Leads with why: omittingpackageuploads an anonymous snapshot with no record of which commit it came from, so it can't be reproduced or stepped back from.Two things I made sure to call out explicitly, because both are quiet correctness traps:
Provisioning a Deploy Credential —
harper deploy setup=true: the client-side sealing flow, that the plaintext never reaches the operations API, that it needs custody (Pro/Fabric), and that reverting to the previous version needs no credential at all (it reuses the retained build rather than re-fetching).reference/cli/authentication.mdAdds
HARPER_CLI_REFRESH_TOKEN/HARPER_CLI_OPERATION_TOKENto the supported variables, and a Token credentials for CI/CD section — so the CI recommendation is no longer "put an admin password in your pipeline". Covers precedence, the in-memory-only refresh, and token lifetimes (1d/30ddefaults).create_authentication_tokensoverwrites a single hashedrefresh_tokenon the user record (security/tokenAuthentication.ts), so issuing a new one invalidates the last — meaning a routine localharper loginsilently breaks a pipeline authenticating as the same account. The docs now recommend giving CI its own user, which also scopes its permissions and makes revocation independent.reference/cli/commands.mdharper login --for-ci, including the stdout/stderr split that makesharper login --for-ci | gh secret set --env-file -work without ever displaying the token.reference/security/secrets.mdVerification
prettier --checkclean on all four files.Notes for review
v5.2.0to match docs(deploy): two-phase deploy_component, revert_component, stage/activate CLI (draft) #599's placeholder — worth confirming both against the actual shipping release before merge.reference_versioned_docs/version-v4/(v5 feature), consistent with docs(deploy): two-phase deploy_component, revert_component, stage/activate CLI (draft) #599.--for-ciflag replaced an earlier interactive prompt in harper#1876; if that design shifts again,commands.mdand the CI/CD section are the two places to update.Related — deploy-by-reference effort
HarperFast/documentation#599— two-phase deploy docs (this PR's base)HarperFast/harper#1849— two-phase stage/activate +revert_componentHarperFast/harper#1850—harper deploy by_ref=trueHarperFast/harper#1851—harper deploy setup=trueHarperFast/harper#1876— CI token auth +harper login --for-ciHarperFast/harper-pro#594—add_ssh_key generate=trueHarperFast/create-harper#118— scaffolds this whole flow🤖 Generated with Claude Code