Skip to content

Commit 7403cd6

Browse files
committed
chore: add GitHub Actions agent instructions and skills
1 parent f0f6c4c commit 7403cd6

2 files changed

Lines changed: 434 additions & 0 deletions

File tree

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
---
2+
applyTo: ".github/workflows/**"
3+
---
4+
5+
# GitHub Actions — instructions for Copilot coding agent
6+
7+
> **Skill reference:** for the full best-practices guide, action-pinning decision table, composite action patterns and PR comment strategies read `.github/skills/github-actions.md` first.
8+
9+
Follow these steps when creating or modifying GitHub Actions workflows in this repository.
10+
11+
## 1. File conventions
12+
13+
- All workflow files use the **`.yaml`** extension (not `.yml`).
14+
- File names use **kebab-case**: `a11y.yaml`, `lighthouse.yaml`, `docs.yaml`.
15+
- Every workflow must start with a block comment explaining its purpose, triggers and strategy.
16+
17+
## 2. Pinning third-party actions
18+
19+
**Every third-party action (anything not `actions/*` from GitHub itself) MUST be pinned
20+
to an exact commit SHA, never to a tag or a branch.**
21+
22+
```yaml
23+
# ✅ correct — SHA-pinned with tag comment
24+
uses: owner/repo@<40-char-sha> # v1.2.3
25+
26+
# ❌ wrong — mutable tag
27+
uses: owner/repo@v1
28+
29+
# ❌ wrong — branch (can be force-pushed)
30+
uses: owner/repo@main
31+
```
32+
33+
To resolve a tag to its commit SHA:
34+
35+
```bash
36+
git ls-remote https://github.com/<owner>/<repo>.git refs/tags/<tag> refs/tags/<tag>^{}
37+
# The ^{} peeled SHA (second line, if present) is the actual commit. Use that one.
38+
```
39+
40+
Add a comment `# v1.2.3` to the right of the hash so the version is human-readable.
41+
42+
**First-party GitHub actions** (`actions/checkout`, `actions/upload-artifact`, etc.) should
43+
also be pinned. Always resolve the latest released tag before using any action.
44+
45+
## 3. Coordinated version upgrades
46+
47+
When bumping an action version, update **every workflow file** that uses it in the same commit.
48+
Actions that appear in multiple workflows (e.g. `actions/checkout`, `oven-sh/setup-bun`) must
49+
always reference **the same commit SHA** across all files. Use `grep` to find all usages before
50+
opening a PR.
51+
52+
```bash
53+
grep -r "oven-sh/setup-bun" .github/workflows/
54+
```
55+
56+
## 4. DRY — composite action for shared steps
57+
58+
If two or more workflows share identical steps (e.g. starting a preview server, waiting for it
59+
to be ready), extract them into a **composite action** under `.github/actions/<name>/action.yml`.
60+
61+
```yaml
62+
# In a workflow:
63+
- name: Start VitePress preview server
64+
uses: ./.github/actions/start-preview-server
65+
```
66+
67+
The composite action must declare all inputs with defaults and document each one. Never
68+
duplicate multi-step shell sequences across workflows.
69+
70+
## 5. PR comment reports
71+
72+
Every workflow that produces a structured report (audit scores, coverage, test results) **must**:
73+
74+
1. Generate a formatted Markdown summary (table preferred).
75+
2. Post it as a **sticky PR comment** using
76+
`marocchino/sticky-pull-request-comment@<sha> # v2.9.4` with a unique `header:` value
77+
so the comment is updated (not duplicated) on each push to the PR.
78+
3. Use `actions/github-script` to build the comment body when the data comes from JSON files
79+
produced by the workflow (avoids shelling out to `jq` / Python).
80+
81+
```yaml
82+
- name: Generate scores comment
83+
id: comment-body
84+
if: github.event_name == 'pull_request'
85+
uses: actions/github-script@<sha> # v7
86+
with:
87+
result-encoding: string
88+
script: |
89+
// ... parse JSON, build Markdown table, return body
90+
91+
- name: Post / update comment on PR
92+
if: github.event_name == 'pull_request'
93+
uses: marocchino/sticky-pull-request-comment@<sha> # v2.9.4
94+
with:
95+
header: <unique-identifier>
96+
message: ${{ steps.comment-body.outputs.result }}
97+
```
98+
99+
## 6. Minimum required permissions
100+
101+
Set `permissions: contents: read` at the **workflow level** as the default.
102+
Override to `write` **at the job level** only for the exact permissions needed:
103+
104+
```yaml
105+
permissions:
106+
contents: read # workflow-level default (principle of least privilege)
107+
108+
jobs:
109+
audit:
110+
permissions:
111+
contents: read
112+
pull-requests: write # needed only to post the PR comment
113+
```
114+
115+
## 7. Concurrency
116+
117+
Every workflow that produces side-effects (deploy, comment, upload) must define a
118+
`concurrency` block to cancel stale runs:
119+
120+
```yaml
121+
concurrency:
122+
group: <workflow-name>-${{ github.ref }}
123+
cancel-in-progress: true
124+
```
125+
126+
## 8. Validation checklist before opening a PR
127+
128+
```bash
129+
# Lint all workflow files locally (requires actionlint):
130+
actionlint .github/workflows/*.yaml .github/actions/**/*.yml
131+
132+
# Confirm every action is pinned:
133+
grep -rn "uses:" .github/workflows/ | grep -v "@[a-f0-9]\{40\}"
134+
# → must return nothing
135+
```
136+
137+
Also verify:
138+
139+
- [ ] All `.yml` workflow files have been renamed to `.yaml`
140+
- [ ] Every new third-party action has a `# vX.Y.Z` comment after its SHA
141+
- [ ] New reusable composite actions are under `.github/actions/<name>/action.yml`
142+
- [ ] The workflow self-references the correct filename (e.g. in `paths:`)
143+
- [ ] `pull-requests: write` is set only on jobs that post comments
144+
- [ ] No `bunx` in workflow `run:` steps — use binaries from `node_modules/.bin/` or
145+
scripts defined in `package.json` via `bun run <script>`

0 commit comments

Comments
 (0)