Repository navigation
fix(org-deploy): move the marker with curl, not gh - #28
Merged
Merged
Conversation
The simplification pass replaced a full bare clone with `gh api` — one ref update instead of downloading the whole history. Correct instinct, wrong tool: the sf-ci container has no GitHub CLI, so the step died with `gh: command not found` after a successful deployment. curl is in the image, so the round-trip saving survives. PATCH first and treat 422/404 as "create it", rather than probing for existence and paying a second call. Also gives the failure a consequence the reader can act on: the deploy succeeded, so the next delta recomputes from the old base and redeploys these components — noisy, not dangerous. Caught by running the pipeline; the checksum script, the single-traversal digest, the relocated env-config export and the template-count invariant all passed in the same run.
9 tasks done
gambe94
added a commit
that referenced
this pull request
Aug 14, 2026
…30) * Docs: point CLAUDE.md at docs/ and install the L2 AI layer CLAUDE.md duplicated docs/pipeline-map.md and docs/architecture.md inline. Replaced with summaries plus links; the docs were already the better source. Verified every fact in the removed text against the two routed docs before cutting it - nothing was dropped, it was already covered there. Adds the gforce-github-actions skill (lockfile) and the gha-workflow-author agent, and AGENTS.md as a symlink for cross-vendor coverage. Also fixes two pre-existing defects in docs/ surfaced by reviewing the new skill, since it now routes every session straight to these files: - docs/consuming-sf-cicd.md still pointed at the frozen v1 release tag and told readers to copy examples/sf-pr-validate.yml and examples/sf-release.yml, filenames that do not exist post-rename (they are reusable-sf-pr-validate.yml and reusable-sf-release.yml now). Its sibling consuming-sf-dispatch.md was updated to v2 during the rename; this one was missed. Fixed both. - docs/claude-actions-reference.md was missing entries for six assets added in PR #27 and PR #28: sf-artifact-build, sf-artifact-deploy, sf-env-config-apply, reusable-sf-org-deploy, smoke-sf-artifact, and smoke-sf-org-login. Added an entry for each, sourced from each asset's own action.yml / workflow file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Fix: correct false claim in 069f926 and four review findings 069f926's message claimed "nothing was dropped" when CLAUDE.md's TypeScript- actions text was cut. That claim was inaccurate: the removed text named ApexTestSelectionService and package.xml parsing as the substance of libraries/salesforce, and neither appeared anywhere under docs/ - architecture.md described that directory only generically. Restored the detail to docs/architecture.md (the doc that owns code layering), not back into CLAUDE.md, which is already near its 150-line budget. Also: - docs/consuming-sf-cicd.md: the @v1 fix in 069f926 was incomplete. Lines 9, 18, 52 and 55 still used the pre-rename short names sf-pr-validate.yml / sf-release.yml while the real files, examples/README.md, and this doc's own link targets all use reusable-sf-pr-validate.yml / reusable-sf-release.yml - line 52 was self-contradictory within one link. Completed the rename throughout; re-read the file end to end afterward and found no remaining v1 references, no dead paths, and no contradiction with consuming-sf-dispatch.md. - docs/claude-actions-reference.md: sf-artifact-build's head-commit entry claimed a default of GITHUB_SHA; the action.yml declares default: "" with the $GITHUB_SHA fallback applied in the script body at runtime. Corrected. - docs/claude-actions-reference.md: the smoke-sf-artifact.yml entry called reject-validate-without-tests "a fifth job" while conflating it with the workflow's five-property header comment. The workflow has 4 jobs (build-artifact covers properties 1/3/4, unset-replacement-fails covers 2, reject-tampered-artifact covers 5); reject-validate-without-tests is the 4th job, sitting outside the five-property enumeration. Reworded. - docs/claude-actions-reference.md: the note flagging that sf-org-login predates PR #16's credential-source: github-env input lived only at the end of the smoke-sf-org-login.yml entry (~line 396), 280 lines from the stale sf-org-login entry itself (~line 115) where an editor would actually need it. Added a one-line pointer at the sf-org-login entry; left the existing note in place. The underlying staleness is still out of scope. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * docs: name the actual token tooling, drop graphify graphify was uninstalled on 2026-08-14; CLAUDE.md still told every session it was available, and omitted rtk, which is the thing actually compressing Bash output through a PreToolUse hook. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Add: github-app-token, a fail-closed replacement for cross-repo PATs `secrets.GITHUB_TOKEN` cannot reach another repository, so every cross-repo job in the fleet reached for a personal access token instead. Two are in service today — `E2E_DISPATCH_TOKEN` in sf-docker-images and `CATALOG_SCAN_TOKEN` here. A PAT is the worst credential available for the job: it belongs to a person, it has account-wide scope, it never expires on its own, and it dies with the account. An App installation token is better on all four counts, but only if it is actually scoped. `actions/create-github-app-token` is generous in two directions at once — omit `repositories` and the token reaches every repo in the installation; omit every `permission-*` and it inherits every permission the App holds. Do both and the replacement for an over-broad PAT is an over-broad token that merely expires sooner. So this action refuses to mint until the caller has named the repositories AND named the permissions. `allow-broad-scope: true` is the deliberate opt-out, and it logs a warning saying so. Also validated here, because each failure is otherwise diagnosed from a bare 401/404 in a later step: - neither client-id nor app-id set (an unshared org variable arrives as an empty string, indistinguishable from never passing one) - a private key without its PEM armour - an empty private key `client-id` is preferred; upstream deprecated the numeric `app-id` in v3, and both are accepted so a caller can migrate without a flag day. Three CI smoke steps pin the guards. They run with a throwaway key and no App credentials at all, which is the point — the two scope rejections would otherwise SUCCEED and hand back a working, over-broad token. Verified locally across 11 input combinations before wiring: every reject case rejects, every scoped case passes, and `allow-broad-scope` still opens the door. Registered with Dependabot per the authoring convention — the action carries a third-party `uses:`, and composite directories are not covered by "/". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
sf-ci has no gh CLI. curl keeps the single-round-trip win.