Skip to content

Commit 7215f79

Browse files
committed
feat: switch action outputs to scope-json and debug plan mode
- make scope-json the primary execution handoff - reduce outputs to minimal gates plus debug-only plan-json - emit normalized custom surface outputs from scope data - refresh README, workflow coverage, and summary fixtures
1 parent e2fd263 commit 7215f79

8 files changed

Lines changed: 186 additions & 284 deletions

File tree

.github/workflows/test.yaml

Lines changed: 21 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -96,34 +96,24 @@ jobs:
9696
id: rail
9797
uses: ./
9898
with:
99-
mode: full
99+
mode: debug
100100
checksum: if-available
101101
since: HEAD~1
102102
working-directory: test-workspace
103103

104104
- name: Verify outputs
105105
run: |
106106
echo "=== Outputs ==="
107-
echo "count: ${{ steps.rail.outputs.count }}"
108-
echo "crates: ${{ steps.rail.outputs.crates }}"
109-
echo "matrix: ${{ steps.rail.outputs.matrix }}"
110-
echo "surfaces: ${{ steps.rail.outputs.surfaces }}"
111-
echo "trace: ${{ steps.rail.outputs.trace }}"
112-
echo "install-method: ${{ steps.rail.outputs.install-method }}"
113-
echo "cargo-rail-version: ${{ steps.rail.outputs.cargo-rail-version }}"
114-
115-
# Verify binary was downloaded (not compiled)
116-
METHOD="${{ steps.rail.outputs.install-method }}"
117-
[[ "$METHOD" == "binary" ]] || { echo "Expected binary install, got: $METHOD"; exit 1; }
118-
119-
# Verify count (should detect core + transitive deps api, cli)
120-
COUNT="${{ steps.rail.outputs.count }}"
121-
[[ "$COUNT" -ge 1 ]] || { echo "Expected at least 1 affected crate"; exit 1; }
122-
123-
# Verify matrix is valid JSON
124-
echo '${{ steps.rail.outputs.matrix }}' | jq . || { echo "matrix not valid JSON"; exit 1; }
125-
echo '${{ steps.rail.outputs.surfaces }}' | jq . || { echo "surfaces not valid JSON"; exit 1; }
126-
echo '${{ steps.rail.outputs.trace }}' | jq . || { echo "trace not valid JSON"; exit 1; }
107+
echo "build: ${{ steps.rail.outputs.build }}"
108+
echo "test: ${{ steps.rail.outputs.test }}"
109+
echo "scope-json: ${{ steps.rail.outputs.scope-json }}"
110+
echo "plan-json: ${{ steps.rail.outputs.plan-json }}"
111+
112+
[[ "${{ steps.rail.outputs.build }}" == "true" ]] || { echo "expected build=true"; exit 1; }
113+
[[ "${{ steps.rail.outputs.test }}" == "true" ]] || { echo "expected test=true"; exit 1; }
114+
echo '${{ steps.rail.outputs.scope-json }}' | jq . || { echo "scope-json not valid JSON"; exit 1; }
115+
echo '${{ steps.rail.outputs.plan-json }}' | jq . || { echo "plan-json not valid JSON"; exit 1; }
116+
[[ -n "${{ steps.rail.outputs.base-ref }}" ]] || { echo "base-ref missing"; exit 1; }
127117
128118
echo "Self-test passed!"
129119
@@ -146,29 +136,21 @@ jobs:
146136
id: rail
147137
uses: ./
148138
with:
149-
mode: full
139+
mode: minimal
150140
checksum: if-available
151141
since: HEAD~10
152142
working-directory: test-repo
153143

154144
- name: Verify outputs
155145
run: |
156146
echo "=== Outputs ==="
157-
echo "count: ${{ steps.rail.outputs.count }}"
158-
echo "crates: ${{ steps.rail.outputs.crates }}"
159-
echo "matrix: ${{ steps.rail.outputs.matrix }}"
160-
echo "active-surfaces: ${{ steps.rail.outputs.active-surfaces }}"
161-
echo "files: ${{ steps.rail.outputs.files }}"
162-
echo "plan-json: ${{ steps.rail.outputs.plan-json }}"
147+
echo "scope-json: ${{ steps.rail.outputs.scope-json }}"
148+
echo "build: ${{ steps.rail.outputs.build }}"
149+
echo "test: ${{ steps.rail.outputs.test }}"
163150
164-
# Verify count is a number
165-
[[ "${{ steps.rail.outputs.count }}" =~ ^[0-9]+$ ]] || { echo "count not a number"; exit 1; }
166-
167-
# Verify matrix is valid JSON
168-
echo '${{ steps.rail.outputs.matrix }}' | jq . || { echo "matrix not valid JSON"; exit 1; }
169-
echo '${{ steps.rail.outputs.active-surfaces }}' | jq . || { echo "active-surfaces not valid JSON"; exit 1; }
170-
echo '${{ steps.rail.outputs.files }}' | jq . || { echo "files not valid JSON"; exit 1; }
171-
echo '${{ steps.rail.outputs.plan-json }}' | jq . || { echo "plan-json not valid JSON"; exit 1; }
151+
echo '${{ steps.rail.outputs.scope-json }}' | jq . || { echo "scope-json not valid JSON"; exit 1; }
152+
[[ -n "${{ steps.rail.outputs.base-ref }}" ]] || { echo "base-ref missing"; exit 1; }
153+
[[ -z "${{ steps.rail.outputs.plan-json }}" ]] || { echo "plan-json should be empty in minimal mode"; exit 1; }
172154
173155
echo "Monorepo test passed!"
174156
@@ -193,7 +175,7 @@ jobs:
193175
id: rail
194176
uses: ./
195177
with:
196-
mode: full
178+
mode: minimal
197179
checksum: if-available
198180
since: HEAD~5
199181
working-directory: test-repo
@@ -202,13 +184,6 @@ jobs:
202184
shell: bash
203185
run: |
204186
echo "Platform: ${{ matrix.os }}"
205-
echo "Count: ${{ steps.rail.outputs.count }}"
206-
echo "Install method: ${{ steps.rail.outputs.install-method }}"
207-
208-
# Verify binary download worked
209-
[[ "${{ steps.rail.outputs.install-method }}" == "binary" ]] || {
210-
echo "Warning: Expected binary install on ${{ matrix.os }}"
211-
}
212-
213-
[[ -n "${{ steps.rail.outputs.count }}" ]] || exit 1
187+
echo "Scope JSON: ${{ steps.rail.outputs.scope-json }}"
188+
echo '${{ steps.rail.outputs.scope-json }}' | jq . >/dev/null || exit 1
214189
echo "Platform test passed!"

README.md

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
# cargo-rail-action
22

3-
> GitHub Action wrapper for `cargo rail plan -f github`.
3+
> GitHub Action wrapper for planner gates and `scope-json`.
44
55
[![Test](https://github.com/loadingalias/cargo-rail-action/actions/workflows/test.yaml/badge.svg)](https://github.com/loadingalias/cargo-rail-action/actions/workflows/test.yaml) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
66

77
## What It Does
88

9-
- Runs `cargo rail plan ... -f github`.
10-
- Publishes planner outputs for job gating.
9+
- Runs `cargo rail plan` in planner-owned GitHub transport mode.
10+
- Publishes planner gates and `scope-json` for job gating.
1111
- Keeps CI behavior aligned with local `plan` + `run` workflows.
1212

13-
Minimum planner contract: `cargo-rail >= 0.10.0`.
13+
Minimum planner contract: `cargo-rail >= 0.10.12`.
1414

1515
## Quick Start
1616

@@ -29,11 +29,26 @@ jobs:
2929
- uses: loadingalias/cargo-rail-action@v3
3030
id: rail
3131
with:
32-
version: "0.10.8"
32+
version: "0.10.12"
3333

3434
- name: Run targeted tests
3535
if: steps.rail.outputs.test == 'true'
36-
run: cargo rail run --since "${{ steps.rail.outputs.base-ref }}" --profile ci
36+
env:
37+
SCOPE_JSON: ${{ steps.rail.outputs.scope-json }}
38+
run: |
39+
MODE=$(echo "$SCOPE_JSON" | jq -r '.mode')
40+
if [ "$MODE" = "workspace" ]; then
41+
cargo nextest run --workspace
42+
elif [ "$MODE" = "crates" ]; then
43+
mapfile -t CRATES < <(echo "$SCOPE_JSON" | jq -r '.crates[]')
44+
ARGS=()
45+
for crate in "${CRATES[@]}"; do
46+
ARGS+=(-p "$crate")
47+
done
48+
cargo nextest run "${ARGS[@]}"
49+
else
50+
echo "planner enabled test surface, but no package-scoped work was selected"
51+
fi
3752
3853
- name: Run docs pipeline
3954
if: steps.rail.outputs.docs == 'true'
@@ -47,13 +62,13 @@ Use the stable major tag `@v3`, or pin a commit SHA for maximum reproducibility.
4762

4863
| Input | Default | Description |
4964
|---|---|---|
50-
| `version` | `0.10.8` | `cargo-rail` version to install (use `latest` only if you intentionally want floating upgrades) |
65+
| `version` | `0.10.12` | `cargo-rail` version to install (use `latest` only if you intentionally want floating upgrades) |
5166
| `checksum` | `required` | `required`, `if-available`, or `off` |
5267
| `since` | auto | Git ref for planner comparison |
53-
| `args` | `""` | Extra planner args (see below) |
68+
| `args` | `""` | Extra planner args except `-f`/`--format`, `--json`, and `-o`/`--output` |
5469
| `working-directory` | `.` | Workspace directory |
5570
| `token` | `${{ github.token }}` | Token for release download API |
56-
| `mode` | `minimal` | `minimal` (recommended) or `full` |
71+
| `mode` | `minimal` | `minimal` (recommended) or `debug` |
5772

5873
**Optional `args` examples:**
5974

@@ -63,11 +78,6 @@ Use the stable major tag `@v3`, or pin a commit SHA for maximum reproducibility.
6378
with:
6479
args: '--explain'
6580
66-
# Custom format (default is github for this action)
67-
- uses: loadingalias/cargo-rail-action@v3
68-
with:
69-
args: '-f json'
70-
7181
# Use different comparison ref
7282
- uses: loadingalias/cargo-rail-action@v3
7383
with:
@@ -92,8 +102,8 @@ Use the stable major tag `@v3`, or pin a commit SHA for maximum reproducibility.
92102
- Composable: combine gates (`if: steps.rail.outputs.build == 'true' || steps.rail.outputs.infra == 'true'`)
93103

94104
**Modes** control what outputs are published:
95-
- `minimal` (default): only gates, matrix, base-ref, plan-json — optimized for modern workflows
96-
- `full`: includes all minimal outputs plus legacy compatibility fields (counts, file lists, etc.)
105+
- `minimal` (default): gates, `scope-json`, `base-ref`, and per-custom-surface booleans
106+
- `debug`: minimal outputs plus `plan-json`
97107

98108
### Minimal mode (default)
99109

@@ -104,32 +114,34 @@ Use the stable major tag `@v3`, or pin a commit SHA for maximum reproducibility.
104114
| `bench` | `true`/`false` | Gate benchmark jobs — set when changes affect performance tests |
105115
| `docs` | `true`/`false` | Gate docs jobs — set for doc comments, README, markdown changes |
106116
| `infra` | `true`/`false` | Gate infra jobs — set for CI config, scripts, toolchain changes |
107-
| `matrix` | JSON | `strategy.matrix` for dynamic job matrices (crate-level parallelism) |
117+
| `scope-json` | JSON | Compact execution-scope payload emitted by `cargo-rail` |
108118
| `base-ref` | string | Git ref for downstream `run` calls (`--since "${{ steps.rail.outputs.base-ref }}"`) |
109-
| `plan-json` | JSON | Full deterministic planner output (all surfaces, crates, files, metadata) |
110-
111-
### Full mode (`mode: full`)
119+
| `custom_<name>` | `true`/`false` | Custom surface gates, with punctuation normalized to `_` |
112120

113-
Includes all minimal outputs plus additional fields for compatibility and debugging.
121+
### Debug mode (`mode: debug`)
114122

115-
**When to use full mode:**
116-
- Migrating from legacy workflows that parse file lists or crate counts
117-
- Debugging plan decisions (use `trace` output)
118-
- Building custom CI logic that needs raw file/crate lists
119-
120-
**Additional outputs in full mode:**
123+
Includes all minimal outputs plus the full planner contract.
121124

122125
| Output | Type | Description |
123126
|---|---|---|
124-
| `count` | number | Total number of affected crates (for logging/metrics) |
125-
| `crates` | string | Space-separated list of affected crate names |
126-
| `files` | JSON | JSON array of changed workspace-relative file paths |
127-
| `surfaces` | JSON | JSON object of surface decisions (`enabled` + `reasons`) |
128-
| `trace` | JSON | Detailed trace of plan decisions (why each surface enabled/disabled) |
129-
| `install-method` | string | Installation source (`cached`, `binary`, `binstall`, `cargo-install`) |
130-
| `cargo-rail-version` | string | Installed `cargo-rail` version |
131-
132-
**Note:** Most workflows should use `minimal` mode. The `plan-json` output contains all plan data in structured form — use `jq` to extract what you need rather than relying on legacy string outputs.
127+
| `plan-json` | JSON | Full deterministic planner contract for debugging and deep inspection |
128+
129+
**Note:** Most workflows should use `minimal` mode. `scope-json` is the execution handoff; use it for package selection in scripts and jobs. `plan-json` is forensic/debug output only.
130+
131+
Example:
132+
133+
```yaml
134+
- name: Show targeted crates
135+
run: echo '${{ steps.rail.outputs.scope-json }}' | jq -r '.crates[]'
136+
```
137+
138+
Custom surfaces are exported as `custom_<name>` outputs. Example:
139+
140+
```yaml
141+
- name: Run benchmark suite
142+
if: steps.rail.outputs.custom_benchmarks == 'true'
143+
run: cargo bench --workspace
144+
```
133145

134146
## Security and Runtime
135147

0 commit comments

Comments
 (0)