Skip to content

Commit 9b8b8f6

Browse files
kraenhansenclaude
andauthored
docs: instruct Claude Code to attach CI labels when opening PRs (#436)
* docs: instruct Claude Code to attach CI labels when opening PRs .github/workflows/check.yml's pull_request trigger fires only on opened, synchronize and reopened — not labeled. Several jobs are gated on labels being present in that triggering event's payload (host, Apple 🍎, Android 🤖, MacOS 💻, Ferric 🦀, weak-node-api), so a label attached after PR creation (the only way the create_pull_request MCP tool allows, since it has no labels parameter) never actually triggers those jobs without a follow-up push. Adds .claude/CLAUDE.md documenting the label -> job mapping and the attach-then-push-again workflow, prompted by PR #434 needing labels added and retriggered after the fact. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DaK9eAAF5G8wj6UT8VekAm * docs: correct the host label name to "Host 🏡" The label table and example condition used plain "host", copied from .github/workflows/check.yml's host-cpp-tests job at the time. That job's condition was itself wrong — the repository's real label is "Host 🏡" (see issues #428/#420/#412) — confirmed and fixed on #434's branch. Update this doc to match, and note that a label condition needs to be checked against the real, existing label rather than trusted at face value. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DaK9eAAF5G8wj6UT8VekAm --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 37e8081 commit 9b8b8f6

1 file changed

Lines changed: 63 additions & 0 deletions

File tree

‎.claude/CLAUDE.md‎

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# CLAUDE.md (`.claude/`)
2+
3+
Guidance specific to Claude Code sessions that open pull requests against this
4+
repository (including automated/scheduled sessions). See the root `CLAUDE.md`
5+
and `AGENTS.md` for everything else.
6+
7+
## Attach CI labels when you open a PR
8+
9+
`.github/workflows/check.yml`'s `pull_request` trigger only fires on
10+
`opened`, `synchronize` and `reopened` — **not** `labeled`. Several of its
11+
jobs are gated behind a label check evaluated against that triggering
12+
event's payload, e.g.:
13+
14+
```yaml
15+
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/next' || contains(github.event.pull_request.labels.*.name, 'Host 🏡')
16+
```
17+
18+
A label added after the PR is already open does nothing on its own — there
19+
is no new `opened`/`synchronize`/`reopened` event for the workflow to
20+
re-evaluate against, so the gated job silently never runs, and that gap is
21+
easy to miss since the Check run still shows green (the job wasn't
22+
skipped-and-failed, it just never triggered).
23+
24+
The label name in the `if:` condition has to match a real, currently-existing
25+
GitHub label exactly (name and emoji). `host-cpp-tests` checked for a label
26+
literally named `host` for a while, when the repository's real label was
27+
`Host 🏡` — the condition never matched anything anyone would actually apply,
28+
so the job silently only ran on pushes to `main`/`next`. Confirm the label
29+
exists (e.g. via the GitHub MCP `get_label` tool) before trusting a condition
30+
or table like the one below.
31+
32+
The `create_pull_request` GitHub MCP tool has no `labels` parameter, so
33+
labels can only be attached in a follow-up call after the PR exists — which
34+
is exactly the case above. **Whenever you open a PR here:**
35+
36+
1. Decide which of the labels below apply, based on what the diff touches.
37+
2. Attach them immediately after creating the PR (e.g. `issue_write` with
38+
`method: "update"`, or the equivalent `gh pr edit --add-label`).
39+
3. Push one more commit to the branch — even a trivial or `--allow-empty`
40+
one — so a `synchronize` event fires and the gated jobs actually run with
41+
the labels now present. Labeling without this step means the relevant CI
42+
never runs before merge.
43+
44+
## Label → job map
45+
46+
| Label | Gated job(s) | Attach when the diff touches |
47+
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
48+
| `Host 🏡` | Host C++ tests | `packages/host/cpp/`, `packages/host/android/CMakeLists.txt`, the generated injector, or anything in `packages/weak-node-api` that the host links against |
49+
| `Apple 🍎` | iOS test app build/run | iOS/macOS/tvOS/visionOS build config, XCFrameworks, Cocoapods, Xcode project files, or any change to Node-API behavior addons rely on (buffers, fatal-error handling, etc.) that device tests would catch |
50+
| `Android 🤖` | Android test app build/run (self-hosted runner; currently label-gated even on `main`/`next`, see the `if:` comment in `check.yml` — check whether that's still true before relying on it) | Gradle, NDK, Android SDK, `.android.node` packaging, or the same cross-platform Node-API behavior changes as above |
51+
| `MacOS 💻` | macOS test app | `react-native-macos`-specific code paths |
52+
| `Ferric 🦀` | Ferric Apple triplets build | `packages/ferric`, `packages/ferric-example`, or anything napi-rs/Cargo related |
53+
| `weak-node-api` | weak-node-api tests | `packages/weak-node-api` |
54+
55+
A PR can need more than one label — e.g. a change to `RuntimeNodeApi.cpp`
56+
that alters buffer semantics warrants `Host 🏡` plus `Apple 🍎` and
57+
`Android 🤖`, since the actual behavior change can only be verified on a
58+
real device.
59+
60+
When in doubt, prefer attaching a label and letting the job run (mirroring
61+
what the label's own description says on GitHub) over guessing it isn't
62+
needed — a job that runs and passes costs a bit of CI time; a real device
63+
regression that ships because the label was skipped costs much more.

0 commit comments

Comments
 (0)