Skip to content

Latest commit

 

History

History
151 lines (116 loc) · 8.67 KB

File metadata and controls

151 lines (116 loc) · 8.67 KB

CLAUDE.md

Guidance for Claude Code in this repository.

Repository Overview

Reusable GitHub Actions for Gforce-Innovation-Kft: TypeScript actions (strict, class-based singleton architecture, single shared source tree), composite actions, and callable workflows for Salesforce CI/CD pipelines.

Per-asset reference (inputs/outputs/permissions + per-asset traps for every action and workflow): docs/claude-actions-reference.mdread the entry for any asset before changing it. The action.yml / workflow file is the contract; the reference carries the rationale the YAML cannot.

Naming convention

Recorded in ADR 0002. Two rules:

  • Actions are <domain>-<object>-<verb>, domain ∈ sf · aws · github · git. So sf-package-create, aws-secret-get. Never verb-first.
  • Workflows with workflow_call are reusable-<domain>-<name>.yml; unprefixed workflows are this repo's own CI. (GitHub forbids subdirectories under .github/workflows/, so the name is the only separator.)

Branching

Single branch: main. develop was merged and deleted on 2026-08-06 — nothing in this repo may reference @develop.

Before you change ANY action or workflow: check the usage catalog

Everything here is consumed by other repositories — a change is never local. docs/usage-catalog.md lists every known consumer of every asset (repo, file, pinned ref); machine-readable twin in docs/usage-catalog.json.

Required before renaming/removing an input, output, or file, and before changing a default:

  1. Read the catalog entry for the asset. Note each consumer's pinned ref@main breaks on merge; @v1/@v2 is insulated until that tag moves.
  2. Zero consumers shown → confirm with the human (the scan sees default branches in this org only).
  3. Regenerate after renames/new consumers: ./.github/scripts/build-usage-catalog.sh (needs gh + jq); CI refreshes weekly. Regenerate on main right after a rename.
  4. A changed default is a breaking change when the old behaviour was load-bearing (e.g. container-user: root → 1001 waits on sf-docker-images v3.0.0).

Reference pattern

  • Actions: Gforce-Innovation-Kft/shared-github-actions/.github/actions/<name>@v2
  • Workflows: Gforce-Innovation-Kft/shared-github-actions/.github/workflows/reusable-<name>.yml@v2
  • v2 carries the ADR 0002 names; v1 is frozen pre-rename — anything added since 404s at @v1. Re-point consumers to @v2 when they migrate.
  • Self-references inside reusable workflows must be absolute (a ./ ref resolves against the CALLER's repo). All are pinned to floating @v2; moving them to @vX+1 is a release step (ADR 0002, decision 6) — never point them at a branch.

Pipeline layers (L1–L4)

System map: docs/pipeline-map.md (mermaid — editing the diagrams is how to specify a change). Code layering inside a TypeScript action is a separate thing: docs/architecture.md.

Layer Lives in Contract
L1 .github/actions/<name>/ One SF/CLI operation. No routing, no context.
L2 reusable-sf-*.yml (workflow_call) Composes L1 into a business pipeline. Typed inputs/outputs, explicit secrets:.
L3 reusable-sf-ops-dispatch.yml Single external entry point for Salesforce. Validates, routes to one path, reports back.
L4 consumer repos Thin uses: callers. Not here.

Rules: L1 never calls L1 (routing belongs in L2/L3); L3 inlines no Salesforce logic; no pass-through layers; nesting caps at 4 and L4→L3→L2→action spends three. Composite actions have no secrets context — secrets arrive as inputs.

TypeScript actions (strict singleton architecture)

All implementation lives in gforce-gha-src/ — the only .ts outside it is each action's entry point (.github/actions/<name>/index.ts: getInput → Orchestrator.execute → setOutput, zero logic, committed esbuild dist/index.js).

Layout: actions/<name> (Orchestrator + Validator singletons) · clients/github (sub-clients + GitHubClient facade, one thin wrapper per endpoint) · services (business workflows + sanctioned runner-API wrappers) · libraries/salesforce (ApexTestSelectionService, selectors, package.xml parsing) · {types,utils,__tests__}.

Every class is a singleton (getInstance/resetInstance); one shared Octokit; services only touch the facade. Errors are throw-based, caught in the entry; expected outcomes are typed values. Tests: method_scenario_expectedResult, Given/When/Then, mock at the singleton boundary, 95% coverage gate.

Adding an action: docs/typescript-action-authoring.md; rationale in docs/architecture.md. Before any PR: npm run all (format + lint + typecheck + bundle + test + dist:verify) must pass.

Authoring conventions

  • Reusable workflows: workflow_call with typed inputs/outputs. Composite actions: .github/actions/<name>/action.yml, using: "composite", every shell step shell: bash.
  • Commit prefixes: Add: Fix: Update: Docs: Test: Refactor:.
  • Clean up credentials in an if: always() step.
  • Third-party actions pin to the floating major tag (actions/checkout@v7) — never @main, never mixed styles. Security-critical or unknown publishers: pin the SHA and say why in a comment.
  • Dependabot directories: must list every action directory containing a uses: (today: aws-secret-get, sf-org-login) — a new composite with a third-party uses: must be added or it goes unwatched.

Internal CI traps (details in the per-asset reference)

  • ci-sf-ops-dispatch-smoke.yml must grant the widest permissions any dispatcher job requests (contents: write) even for dry runs — GitHub validates the whole call graph up front, and a startup_failure produces NO check run (looks like passing).
  • catalog-refresh.yml: the catalog is generated — never hand-edit.
  • release.yml: a major bump is two steps — rewrite self-references to @vX+1 first, then tag (CONTRIBUTING.md).

Skills & AI tooling

Eight repo-scoped skills are committed. They live in .agents/skills/, are symlinked into .claude/skills/, and are pinned by content hash in skills-lock.json. All are vendored from upstream — do not hand-edit a vendored SKILL.md; the next update overwrites it and the hash stops matching.

npx skills check is not read-only — despite the name it fetches upstream and rewrites the SKILL.md files and skills-lock.json in place, so it dirties the working tree. Run it deliberately, on its own branch, and review the diff and the changed hashes as a real content change; never run it mid-PR expecting a report.

Invoke the relevant one when the task matches:

Skill Upstream Use when
github-actions-docs xixu-me/skills Authoring or editing a workflow / action.yml — keeps YAML aligned with current GitHub Actions syntax (composite, reusable, TypeScript action patterns). The default for most work in this repo.
github-actions-templates wshobson/agents Scaffolding a new workflow from a known-good shape, rather than editing an existing one.
code-review mattpocock/skills Reviewing the TypeScript under gforce-gha-src/ for quality and correctness.
requesting-code-review obra/superpowers Preparing a change for review, before opening the PR.
receiving-code-review obra/superpowers Responding to review feedback on a PR.
dx-org-manage forcedotcom/sf-skills Running scratch-org or snapshot operations against a real org by hand — reproducing what sf-org-scratch-create and the validate job do, when debugging why they fail.
dx-org-permission-set-assign forcedotcom/sf-skills Assigning permission sets to org users — the step reusable-sf-pr-validate performs inside its scratch org.
dx-pkg-post-install-configure forcedotcom/sf-skills Post-install configuration of a managed package — what a consumer does after sf-package-install lands a version.

The three dx-* skills execute SF CLI operations against a live org. They are here because this repo's composite actions wrap those same commands, so the skills are how you reproduce a failing pipeline step interactively. They are not a way to change pipeline behaviour: an action's behaviour lives in its action.yml.

Global tooling available in every session: lean-ctx (prefer ctx_* MCP tools for reads/search/shell — token-compressed), superpowers process skills, and graphify (no graph built for this repo).