Reusable GitHub Actions for Gforce-Innovation-Kft: TypeScript actions (a portable
core + thin adapters), composite actions, and callable workflows for
Salesforce CI/CD. Reference them from any repo in the org.
TypeScript action: Gforce-Innovation-Kft/shared-github-actions/.github/actions/<name>@v2
Composite action: Gforce-Innovation-Kft/shared-github-actions/.github/actions/<name>@v2
Reusable workflow: Gforce-Innovation-Kft/shared-github-actions/.github/workflows/reusable-<name>.yml@v2
See Versioning for how to pin (@v2, @v2.0.0, or a full
commit SHA — avoid @main in production callers).
Naming (ADR 0002): actions are
<domain>-<object>-<verb> (sf-package-create, aws-secret-get,
github-branch-sync); workflows you may call are prefixed reusable-, and
anything unprefixed is this repo's own CI.
Pin
@v2for everything below.v1is frozen at the pre-rename layout and contains onlyget-aws-secret,create-release-pr,sync-branches,sf-delta-package,sf-find-tests,sf-jwt-login,sf-org-login, plus the unprefixedsalesforce-code-analyzer.yml,sf-pr-validate.ymlandsf-release.yml. Everything else on this page — thesf-package-*actions,sf-org-scratch-create,sf-ops-callback, the dispatcher — does not exist at@v1at all, so a@v1ref to one of those fails to resolve.
New here? docs/pipeline-map.md is the whole system
on one page: flow diagrams of the four layers, the Salesforce dispatch chain, and
what is still missing. The same content as sortable tables:
docs/sf-cicd-pipeline-map.xlsx.
Thin Node20 entry points over a strict, class-based singleton architecture in
gforce-gha-src/. Each ships a committed dist/index.js. Full input/output
lists live in each action.yml; runnable callers are in examples/.
Synchronize one branch into another: fast-forward when possible, else a server-side merge, else open a "sync" pull request on conflict.
- Key inputs:
source-branch,target-branch,strategy(auto|fast-forward|merge, defaultauto),dry-run(defaulttrue),github-token(default${{ github.token }}). - Key outputs:
synced,action,result-sha,pull-request-number,pull-request-url,ahead-by,behind-by,reason. - Permissions:
contents: write(moves the target ref / merges) +pull-requests: write(opens the sync PR on conflict).
Create or update a release pull request between two branches, with a templated title/body, labels, and reviewers.
- Key inputs:
source-branch,target-branch,release-version*,title,body-template({{version}}/{{source}}/{{target}}/{{commits}}/{{files}}),draft(defaultfalse),labels,reviewers,dry-run(defaulttrue),github-token(default${{ github.token }}). - Key outputs:
pull-request-number,pull-request-url,created,updated. - Permissions:
contents: read(compare only) +pull-requests: write.
dry-rundefaults totrueon both actions — a caller must explicitly opt in to mutating state.
Select the Apex test classes relevant to a delta package.xml — naming-convention
matches plus a reference scan of test classes in the source tree.
- Key inputs:
package-xml*,source-dir(defaultforce-app),test-suffixes(defaultTest,_Test,Tests),github-token(default${{ github.token }}— this action makes no GitHub API calls; the input exists only for the shared runtime). - Key outputs:
tests,test-count,has-apex. - Permissions: none (no GitHub API calls).
aws-secret-get— fetch a secret from AWS Secrets Manager via OIDC role assumption; JSON fields are exported as env vars (reference them as${{ env.FIELD }}, not step outputs). Requiresid-token: write+contents: read.sf-org-login— authenticate to a Salesforce org, either from an SFDX auth URL held in a GitHub secret (auth-method: auth-url, the default, no cloud dependency) or via the JWT bearer flow with credentials from AWS Secrets Manager (auth-method: jwt, needsid-token: write+aws-role-arn). Outputsorg-id,username,instance-url,access-token(masked); cleans up every credential file in anif: always()step. Replaces the formersf-jwt-login— see CLAUDE.md.sf-source-delta— generate a deltapackage.xmlbetween two git refs with sfdx-git-delta. Inputsfrom-ref*,to-ref,output-dir,source-dir,generate-delta; outputspackage-path,has-changes,component-count. Requires afetch-depth: 0checkout.sf-org-scratch-create— create a scratch org, refusing to start when the Dev Hub has no capacity (bothActiveScratchOrgsandDailyScratchOrgsare checked). Does not delete the org — composite actions cannot register apost:step, so pair it with your ownif: always()sf org delete scratch.sf-package-create— build one 2GP package version: Dev Hub headroom preflight,sf package version create, andPackage2VersionCreateRequestErrorevidence on failure. Outputspackage-name,version-id(04t),version-number. Needs onlycontents: read— the provenance tag is pushed byreusable-sf-package-release.yml, not here.sf-package-promote— promote a04tto released. Refuses a version built with--skip-validationunlessallow-unvalidated; an already-released version is success, not failure. Outputsstatus,version-number.sf-package-install— install one04tinto a target org, polling to a terminal state. Preflights the org so an already-installed version is success; surfaces Salesforce's own install errors on failure. Outputsstatus,install-request-id.sf-ops-callback— report a dispatched operation's terminal status back into Salesforce, keyed by the requester's correlation id.dry-run: truerenders the payload without posting.
-
reusable-sf-ops-dispatch.yml— L3, the single external entry point for Salesforce-initiated operations (create-version,promote,install). Validates the request, routes it to exactly one L2/L1 path, and reports the terminal status back throughsf-ops-callback. An operation that matches no route fails the run instead of showing green. See ADR 0001 and docs/consuming-sf-dispatch.md. -
reusable-sf-package-release.yml— L2, the 2GP release pipeline:validate(the only job that spends a scratch org — skip it withrun-validate: false) →package(sf-package-create, then push the annotatedpkg/<package>/<versionNumber>provenance tag) →release(cut the GitHub Release; runs even when validation was skipped). Jobs are ordered by cost, not dependency: a tree that does not compile spends zero of the 6/day validated package creates. Outputsversion-id(04t),version-number,git-tag. Secrets:sfdx-auth-url(required, Dev Hub),scratch-org-auth-url(optional — validate in an existing org and keep it, for debugging the flow). Caller needscontents: write. -
reusable-sf-code-analyze.yml— run Salesforce Code Analyzer with quality gates; posts PR comments. Caller needspull-requests: write,contents: read,actions: read. -
reusable-sf-pr-validate.yml— PR code health:jestrunsnpm testwhen the consumer'spackage.jsonhas atestscript (skips with a notice otherwise);scratch-orgcreates a 1-day scratch org fromconfig/scratch-orgs/ci.json, deploys, assigns permission sets, runsRunLocalTestswith coverage, uploads results, always deletes the org. Secret:sfdx-auth-url. Caller needscontents: read. See docs/consuming-sf-cicd.md. -
reusable-sf-release.yml— one workflow, two phases: onpull_request, a delta package +sf-apex-test-select-selected Apex tests, check-only deploy against the target org, and ansf-release-<run>handoff artifact; onpushto main (orworkflow_dispatch), behind the caller's environment gate, quick-deploys the validated request (fallback: delta → full;full-deploy: trueforces the full path). Secret:sfdx-auth-url. Caller needscontents: read,actions: read. See docs/consuming-sf-cicd.md.
Docker moved out.
docker-build-test-push.ymlnow lives insf-docker-imagesas.github/workflows/reusable-docker-image-build.yml, alongside its only consumer. See ADR 0002, decision 3. This repository covers Salesforce, GitHub, and AWS.
Workflows without the reusable- prefix are this repo's own CI: ci.yml
(quality + smoke), ci-sf-ops-dispatch-smoke.yml (routes all three dispatcher
operations with dry-run: true), catalog-refresh.yml (weekly consumer rescan,
opens a PR on drift), and release.yml (tag → Release + floating major tag).
Releases follow semver, published as git tags with a floating major tag:
| Pin | Example | Behavior |
|---|---|---|
| Major tag | @v2 |
Recommended. Moves with every non-breaking release; you get fixes automatically. |
| Exact tag | @v2.0.0 |
Immutable; bump manually. |
| Commit SHA | @93cb6ef… |
Strictest supply-chain pin; pair with Dependabot to stay current. |
@main |
— | Development only. Unreleased, may break at any time. |
Pushing a vX.Y.Z tag triggers release.yml,
which creates the GitHub Release and force-moves the vX major tag. Breaking
changes bump the major (callers on the old @v1 are unaffected until they move
to @v2).
v2.0.0 is the breaking release: it renames every action and workflow per
ADR 0002. Migrating from @v1 means
changing the paths in your uses: lines, not just the tag — the mapping table is
in decisions 1 and 2 of that ADR.
The release procedure for maintainers is in CONTRIBUTING.md. It has a manual step: a major bump must rewrite the reusable workflows' own self-references to the new tag before tagging.
Development happens on main. develop was merged and deleted on 2026-08-06 —
open PRs against main.
npm-workspaces monorepo:
gforce-gha-src/ # ALL TypeScript implementation (single source of truth):
# actions/<name>/ (Orchestrator + Validator singletons),
# clients/github/ (sub-clients + facade), services/,
# libraries/salesforce/, selectors, utils, __tests__/
.github/actions/<name> # action.yml + entry index.ts + committed esbuild dist/index.js
.github/actions/aws-secret-get # composite actions
.github/workflows # CI + reusable workflows
.github/scripts # build-usage-catalog.sh (regenerates docs/usage-catalog.*)
examples/ # runnable caller workflows
docs/ # architecture + authoring guides + pipeline map
docs/adr/ # architecture decision records
.agents/skills/ # vendored agent skills (symlinked into .claude/skills/)
skills-lock.json # content hashes for the vendored skills
See docs/architecture.md for the layering and
docs/typescript-action-authoring.md for
how to add the next action.
npm ci # install workspaces (Node 20+)
npm run all # format:check + lint + typecheck + bundle + test + dist:verify
npm run test:all # all workspace tests (95% coverage gate, 100% actual)
npm run bundle:all # rebuild every action's dist/index.js (esbuild)
npm run typecheck:all # tsc --noEmit across workspacesRun npm run all and ensure it passes before opening a PR. A pre-commit hook
rebuilds and re-stages action bundles; CI's dist:verify fails on a stale bundle.
- Reference actions/workflows by release tag (
@v2,@v2.0.0) — see Versioning; never@mainin production. - Third-party actions are pinned to the floating major tag (
actions/checkout@v7,aws-actions/configure-aws-credentials@v6); Dependabot opens a PR when a new major appears. Patch and minor fixes arrive without a commit here — which is the point, and also the trade-off: a tag is mutable, so this trusts the action's publisher not to move it. Use a SHA instead for anything security-critical. - Commit prefixes:
Add:,Fix:,Update:,Docs:,Test:,Refactor:. - Composite actions use
using: "composite"withshell: bash; always clean up secrets in anif: always()step.
MIT