Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions .claude/commands/composite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# Composite Actions — Rules & Conventions

Use these rules whenever creating or editing a composite action in `src/`.

## Before you create anything

**Step 1 — Check if it already exists in this repo**

Search `src/` before starting. If a composite already covers the same capability:

- Summarize what the existing composite does and which inputs it exposes
- Identify the gap between the existing behavior and the new requirement
- Propose an **adaptation plan** (add an input, extend steps, split into two) instead of creating a new file

**Step 2 — Check the GitHub Actions Marketplace first**

Before writing custom steps from scratch, search the [Marketplace](https://github.com/marketplace?type=actions) for an existing action that covers the need:

- Prefer a well-maintained marketplace action over custom shell scripting for non-trivial logic
- Wrap it in a composite if it needs input normalization or additional steps
- Pin to a specific tag or SHA — never `@main` or `@master`
- Document in the composite `README.md` why that action was chosen

Only implement from scratch when no suitable action exists or when existing ones don't meet security or customization requirements.

---

## Directory layout

Composite actions are grouped by capability inside `src/`:

```
src/
├── setup/ ← language runtime setup (Go, Node, etc.)
├── build/ ← build and artifact generation
├── test/ ← test execution and coverage
├── deploy/ ← deployment and release steps
└── config/ ← repository configuration management
```

Each composite lives in `src/<capability>/<name>/` with exactly two files:

```
src/config/labels-sync/
├── action.yml ← required
└── README.md ← required
```

## action.yml structure

```yaml
name: Human-readable name
description: One-line description.

inputs:
github-token:
description: GitHub token with required permissions
required: true
some-option:
description: What this option controls
required: false
default: "default-value"

runs:
using: composite
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Do the work
uses: some-owner/some-action@v1
with:
token: ${{ inputs.github-token }}
option: ${{ inputs.some-option }}
```

## Design rules

- **5–15 steps maximum** — split if larger
- **Single responsibility** — one composite, one capability
- Must not define jobs or call other workflows
- Must not contain pipeline control logic
- Never combine multiple language runtimes in the same composite

## Language-specific vs cross-language

Specialize by runtime when toolchains differ:

```
src/setup/setup-go/ ← Go toolchain, GOPATH, module cache
src/setup/setup-node/ ← Node.js, npm/yarn/pnpm, cache
src/build/build-go/ ← go build, cross-compilation
src/test/test-go/ ← go test, coverage upload
```

Cross-language composites stay language-agnostic:

```
src/build/docker-build/ ← any image
src/deploy/helm-deploy/ ← any chart
src/config/labels-sync/ ← any repo
```

## README.md requirements

1. Logo header — HTML table layout (logo left, `h1` title right)
2. Inputs table — `Input | Description | Required | Default`
3. Usage as composite step (full YAML)
4. Usage as reusable workflow (full YAML with `secrets: inherit`)
5. Required permissions block

### Usage example ref policy

Examples in README.md must never use `@main`. Use the correct ref for each context:

```yaml
# ✅ Testing — point to develop or feature branch
uses: LerianStudio/github-actions-shared-workflows/.github/workflows/labels-sync.yml@develop
uses: LerianStudio/github-actions-shared-workflows/.github/workflows/labels-sync.yml@feat/my-branch

# ✅ Production — always a pinned stable version
uses: LerianStudio/github-actions-shared-workflows/.github/workflows/labels-sync.yml@v1.2.3

# ❌ Never in examples
uses: LerianStudio/github-actions-shared-workflows/.github/workflows/labels-sync.yml@main
```

## After creating a new composite

- Update root `README.md` if the composite is meant to be used by external callers

### Labels checklist

Check `.github/labels.yml` for a label matching the composite's capability group. If it doesn't exist, add it:

```yaml
- name: <capability> # e.g. "infrastructure", "notifications"
color: "0075ca" # pick a distinct hex color
description: Changes to <capability> composite actions
```

After adding, run the `Sync Labels` workflow (`workflow_dispatch`) to create it in the repository.

### Dependabot checklist

For every third-party action used in the new composite (`uses: owner/action@vX`), check `.github/dependabot.yml`:

- If `owner/*` already matches an existing group → no change needed
- If not → add to the most appropriate group, or create a new one:

```yaml
new-tool-category:
patterns:
- "owner/new-action"
update-types:
- "minor"
- "patch"
```

Never add `LerianStudio/*` actions to dependabot — pinned to `@main` intentionally.
Loading