bigpowers 2.34.1 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.pi/package.json +2 -2
- package/.pi/prompts/deploy.md +53 -28
- package/.pi/prompts/develop-tdd.md +5 -80
- package/.pi/prompts/migrate-spec.md +273 -197
- package/.pi/prompts/publish-package.md +125 -67
- package/.pi/prompts/release-branch.md +85 -69
- package/.pi/prompts/security-review.md +323 -0
- package/.pi/prompts/smoke-test.md +98 -58
- package/.pi/prompts/using-bigpowers.md +2 -2
- package/.pi/prompts/validate-contracts.md +169 -54
- package/.pi/prompts/wire-ci.md +147 -89
- package/.pi/skills/deploy/SKILL.md +53 -28
- package/.pi/skills/develop-tdd/SKILL.md +5 -80
- package/.pi/skills/migrate-spec/SKILL.md +273 -197
- package/.pi/skills/publish-package/SKILL.md +125 -67
- package/.pi/skills/release-branch/SKILL.md +85 -69
- package/.pi/skills/security-review/SKILL.md +324 -0
- package/.pi/skills/smoke-test/SKILL.md +98 -58
- package/.pi/skills/using-bigpowers/SKILL.md +2 -2
- package/.pi/skills/validate-contracts/SKILL.md +169 -54
- package/.pi/skills/wire-ci/SKILL.md +147 -89
- package/CHANGELOG.md +14 -0
- package/README.md +4 -4
- package/SKILL-INDEX.md +2 -2
- package/deploy/REFERENCE.md +82 -0
- package/deploy/SKILL.md +3 -63
- package/develop-tdd/SKILL.md +5 -80
- package/migrate-spec/REFERENCE.md +268 -0
- package/migrate-spec/SKILL.md +5 -199
- package/package.json +2 -2
- package/publish-package/REFERENCE.md +239 -0
- package/publish-package/SKILL.md +8 -192
- package/release-branch/REFERENCE.md +83 -0
- package/release-branch/SKILL.md +2 -69
- package/scripts/generate-reference-tables.sh +1 -0
- package/scripts/sync-skills.sh +4 -1
- package/security-review/REFERENCE-confidence-rubric.md +85 -0
- package/security-review/REFERENCE-false-positives.md +68 -0
- package/security-review/REFERENCE-vuln-categories.md +103 -0
- package/security-review/SKILL.md +63 -0
- package/skills-lock.json +14 -9
- package/smoke-test/REFERENCE.md +162 -0
- package/smoke-test/SKILL.md +5 -130
- package/using-bigpowers/SKILL.md +2 -2
- package/validate-contracts/REFERENCE.md +183 -0
- package/validate-contracts/SKILL.md +6 -77
- package/wire-ci/REFERENCE.md +257 -0
- package/wire-ci/SKILL.md +8 -210
|
@@ -32,6 +32,112 @@ If no manifest is found, prompt the user to specify the type or pass `--type <np
|
|
|
32
32
|
Before attempting any publish, run all applicable checks:
|
|
33
33
|
|
|
34
34
|
**npm (`package.json`):**
|
|
35
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
36
|
+
|
|
37
|
+
**crates.io (`Cargo.toml`):**
|
|
38
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
39
|
+
|
|
40
|
+
**PyPI (`setup.py` / `pyproject.toml`):**
|
|
41
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
42
|
+
|
|
43
|
+
### 3. Run publish
|
|
44
|
+
|
|
45
|
+
After all prerequisite checks pass, run the registry-specific command:
|
|
46
|
+
|
|
47
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
48
|
+
|
|
49
|
+
### 4. Verify publish success
|
|
50
|
+
|
|
51
|
+
After publish, confirm the version appears on the registry:
|
|
52
|
+
|
|
53
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
54
|
+
|
|
55
|
+
### 5. Error handling
|
|
56
|
+
|
|
57
|
+
On failure, surface actionable hints:
|
|
58
|
+
|
|
59
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
60
|
+
|
|
61
|
+
### 6. Dry-run mode (`--dry-run`)
|
|
62
|
+
|
|
63
|
+
Run `--dry-run` to verify all prerequisites without actually publishing:
|
|
64
|
+
|
|
65
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
66
|
+
|
|
67
|
+
### 7. Dry-run mode per registry
|
|
68
|
+
|
|
69
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
70
|
+
|
|
71
|
+
## Verify
|
|
72
|
+
|
|
73
|
+
→ verify: `test -f publish-package/SKILL.md && echo "OK: skill file exists" || echo "FAIL: no skill file"`
|
|
74
|
+
→ verify: `grep -q "name: publish-package" publish-package/SKILL.md && echo "OK: frontmatter" || echo "FAIL: frontmatter"`
|
|
75
|
+
→ verify: `grep -ci "npm\|crates.io\|pypi\|publish\|registry" publish-package/SKILL.md | awk '{if($1>=4) print "OK: semantics"; else print "FAIL: missing"}'`
|
|
76
|
+
→ verify: `grep -q "publish-package" SKILL-INDEX.md && echo "OK: in SKILL-INDEX" || echo "FAIL: not indexed"`
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
# Publish Package — Reference
|
|
81
|
+
|
|
82
|
+
## Options
|
|
83
|
+
|
|
84
|
+
| Flag | Description |
|
|
85
|
+
|------|-------------|
|
|
86
|
+
| `--dry-run` | Verify prerequisites and show publish command without executing |
|
|
87
|
+
| `--registry <type>` | Force registry type (skip auto-detection) |
|
|
88
|
+
| `--otp <code>` | One-time password for npm 2FA |
|
|
89
|
+
| `--no-verify` | Skip prerequisite checks (use with caution) |
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Examples
|
|
95
|
+
|
|
96
|
+
### Publish an npm package
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Verify first
|
|
100
|
+
publish-package --dry-run
|
|
101
|
+
|
|
102
|
+
# Publish
|
|
103
|
+
publish-package
|
|
104
|
+
|
|
105
|
+
# Output:
|
|
106
|
+
# [npm] Publishing my-package v0.4.0...
|
|
107
|
+
# OK: npm publish confirmed (my-package@0.4.0 on registry)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Publish a Rust crate
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
export CARGO_REGISTRY_TOKEN=<token>
|
|
114
|
+
publish-package --dry-run
|
|
115
|
+
publish-package
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Missing token scenario
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
$ publish-package
|
|
122
|
+
FAIL: NPM_TOKEN not set. Set via: export NPM_TOKEN=<token> or add to .npmrc
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Integration with release-branch
|
|
129
|
+
|
|
130
|
+
When wired into `release-branch`, add a step after git push:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
6a. Run publish-package to publish to package registries
|
|
134
|
+
→ verify: publish-package --dry-run && publish-package
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Reference block 1
|
|
140
|
+
|
|
35
141
|
```bash
|
|
36
142
|
# Check auth token exists
|
|
37
143
|
if [ -z "${NPM_TOKEN:-}" ]; then
|
|
@@ -69,7 +175,10 @@ if [ -f CHANGELOG.md ]; then
|
|
|
69
175
|
fi
|
|
70
176
|
```
|
|
71
177
|
|
|
72
|
-
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Reference block 2
|
|
181
|
+
|
|
73
182
|
```bash
|
|
74
183
|
# Check auth token exists
|
|
75
184
|
if [ -z "${CARGO_REGISTRY_TOKEN:-}" ]; then
|
|
@@ -88,7 +197,10 @@ if cargo search "$CRATE_NAME" 2>/dev/null | grep -q "^${CRATE_NAME}.*\"$CURRENT_
|
|
|
88
197
|
fi
|
|
89
198
|
```
|
|
90
199
|
|
|
91
|
-
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Reference block 3
|
|
203
|
+
|
|
92
204
|
```bash
|
|
93
205
|
# Check auth token exists
|
|
94
206
|
if [ -z "${TWINE_PASSWORD:-}" ] && [ -z "${POETRY_PYPI_TOKEN_PYPI:-}" ]; then
|
|
@@ -104,9 +216,9 @@ if [ ! -d dist ] || [ -z "$(ls dist/*.whl 2>/dev/null)" ]; then
|
|
|
104
216
|
fi
|
|
105
217
|
```
|
|
106
218
|
|
|
107
|
-
|
|
219
|
+
---
|
|
108
220
|
|
|
109
|
-
|
|
221
|
+
## Reference block 4
|
|
110
222
|
|
|
111
223
|
```bash
|
|
112
224
|
# npm
|
|
@@ -122,9 +234,9 @@ python -m twine upload dist/* # or: poetry publish
|
|
|
122
234
|
brew bump-formula-pr --url=<tarball-url> <formula-name>
|
|
123
235
|
```
|
|
124
236
|
|
|
125
|
-
|
|
237
|
+
---
|
|
126
238
|
|
|
127
|
-
|
|
239
|
+
## Reference block 5
|
|
128
240
|
|
|
129
241
|
```bash
|
|
130
242
|
# npm
|
|
@@ -137,9 +249,9 @@ cargo search "$CRATE_NAME" 2>/dev/null | grep -q "^${CRATE_NAME}.*\"$CURRENT_VER
|
|
|
137
249
|
pip index versions "$PACKAGE_NAME" 2>/dev/null | grep -q "$CURRENT_VER" && echo "OK: PyPI publish confirmed"
|
|
138
250
|
```
|
|
139
251
|
|
|
140
|
-
|
|
252
|
+
---
|
|
141
253
|
|
|
142
|
-
|
|
254
|
+
## Reference block 6
|
|
143
255
|
|
|
144
256
|
```bash
|
|
145
257
|
# Generic failure handler
|
|
@@ -172,9 +284,9 @@ if [ $? -ne 0 ]; then
|
|
|
172
284
|
fi
|
|
173
285
|
```
|
|
174
286
|
|
|
175
|
-
|
|
287
|
+
---
|
|
176
288
|
|
|
177
|
-
|
|
289
|
+
## Reference block 7
|
|
178
290
|
|
|
179
291
|
```bash
|
|
180
292
|
# Example output
|
|
@@ -190,7 +302,9 @@ $ publish-package --dry-run
|
|
|
190
302
|
[DRY-RUN] Exiting without publishing.
|
|
191
303
|
```
|
|
192
304
|
|
|
193
|
-
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## Reference block 8
|
|
194
308
|
|
|
195
309
|
```bash
|
|
196
310
|
# npm dry-run
|
|
@@ -202,59 +316,3 @@ cargo package --list 2>/dev/null
|
|
|
202
316
|
# PyPI dry-run
|
|
203
317
|
python -m twine upload --repository testpypi dist/* # test.pypi.org
|
|
204
318
|
```
|
|
205
|
-
|
|
206
|
-
## Options
|
|
207
|
-
|
|
208
|
-
| Flag | Description |
|
|
209
|
-
|------|-------------|
|
|
210
|
-
| `--dry-run` | Verify prerequisites and show publish command without executing |
|
|
211
|
-
| `--registry <type>` | Force registry type (skip auto-detection) |
|
|
212
|
-
| `--otp <code>` | One-time password for npm 2FA |
|
|
213
|
-
| `--no-verify` | Skip prerequisite checks (use with caution) |
|
|
214
|
-
|
|
215
|
-
## Examples
|
|
216
|
-
|
|
217
|
-
### Publish an npm package
|
|
218
|
-
|
|
219
|
-
```bash
|
|
220
|
-
# Verify first
|
|
221
|
-
publish-package --dry-run
|
|
222
|
-
|
|
223
|
-
# Publish
|
|
224
|
-
publish-package
|
|
225
|
-
|
|
226
|
-
# Output:
|
|
227
|
-
# [npm] Publishing my-package v0.4.0...
|
|
228
|
-
# OK: npm publish confirmed (my-package@0.4.0 on registry)
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### Publish a Rust crate
|
|
232
|
-
|
|
233
|
-
```bash
|
|
234
|
-
export CARGO_REGISTRY_TOKEN=<token>
|
|
235
|
-
publish-package --dry-run
|
|
236
|
-
publish-package
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### Missing token scenario
|
|
240
|
-
|
|
241
|
-
```bash
|
|
242
|
-
$ publish-package
|
|
243
|
-
FAIL: NPM_TOKEN not set. Set via: export NPM_TOKEN=<token> or add to .npmrc
|
|
244
|
-
```
|
|
245
|
-
|
|
246
|
-
## Integration with release-branch
|
|
247
|
-
|
|
248
|
-
When wired into `release-branch`, add a step after git push:
|
|
249
|
-
|
|
250
|
-
```
|
|
251
|
-
6a. Run publish-package to publish to package registries
|
|
252
|
-
→ verify: publish-package --dry-run && publish-package
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
## Verify
|
|
256
|
-
|
|
257
|
-
→ verify: `test -f publish-package/SKILL.md && echo "OK: skill file exists" || echo "FAIL: no skill file"`
|
|
258
|
-
→ verify: `grep -q "name: publish-package" publish-package/SKILL.md && echo "OK: frontmatter" || echo "FAIL: frontmatter"`
|
|
259
|
-
→ verify: `grep -ci "npm\|crates.io\|pypi\|publish\|registry" publish-package/SKILL.md | awk '{if($1>=4) print "OK: semantics"; else print "FAIL: missing"}'`
|
|
260
|
-
→ verify: `grep -q "publish-package" SKILL-INDEX.md && echo "OK: in SKILL-INDEX" || echo "FAIL: not indexed"`
|
|
@@ -62,29 +62,7 @@ bash scripts/land-branch.sh <task-slug> "feat(scope): description"
|
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
**Path B — `scripts/land-branch.sh` missing (fallback):**
|
|
65
|
-
|
|
66
|
-
# Fallback: manual squash-merge when land-branch.sh is absent
|
|
67
|
-
FEATURE_BRANCH=<task-slug>
|
|
68
|
-
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo main)
|
|
69
|
-
|
|
70
|
-
# Ensure we're on the feature branch
|
|
71
|
-
if [ "$(git branch --show-current)" != "$FEATURE_BRANCH" ]; then
|
|
72
|
-
git checkout "$FEATURE_BRANCH"
|
|
73
|
-
fi
|
|
74
|
-
|
|
75
|
-
# Checkout default branch and update
|
|
76
|
-
git checkout "$DEFAULT_BRANCH"
|
|
77
|
-
git pull --rebase origin "$DEFAULT_BRANCH" 2>/dev/null || git pull origin "$DEFAULT_BRANCH"
|
|
78
|
-
|
|
79
|
-
# Squash-merge the feature branch
|
|
80
|
-
git merge --no-ff "$FEATURE_BRANCH" -m "<conventional-commit-message>"
|
|
81
|
-
|
|
82
|
-
# Push
|
|
83
|
-
git push origin "$DEFAULT_BRANCH"
|
|
84
|
-
|
|
85
|
-
# Clean up local feature branch
|
|
86
|
-
git branch -d "$FEATURE_BRANCH"
|
|
87
|
-
```
|
|
65
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
88
66
|
|
|
89
67
|
**Report which path was taken.** Print exactly:
|
|
90
68
|
- `"used land-branch.sh"` if Path A
|
|
@@ -116,41 +94,7 @@ mv specs/epics/eNN-slug specs/epics/archive/
|
|
|
116
94
|
|
|
117
95
|
After push (solo-local step 5 or team-pr step 7), verify the CI workflow completes successfully:
|
|
118
96
|
|
|
119
|
-
|
|
120
|
-
echo "==> Polling CI for main branch..."
|
|
121
|
-
TIMEOUT=600 # 10 minutes
|
|
122
|
-
INTERVAL=30 # poll every 30 seconds
|
|
123
|
-
ELAPSED=0
|
|
124
|
-
|
|
125
|
-
while [ $ELAPSED -lt $TIMEOUT ]; do
|
|
126
|
-
CI_JSON=$(gh run list --limit 1 --branch main --workflow CI --json status,conclusion,headSha,databaseId 2>/dev/null)
|
|
127
|
-
CI_STATUS=$(echo "$CI_JSON" | jq -r '.[0].status // "unknown"')
|
|
128
|
-
CI_CONCLUSION=$(echo "$CI_JSON" | jq -r '.[0].conclusion // ""')
|
|
129
|
-
CI_SHA=$(echo "$CI_JSON" | jq -r '.[0].headSha // ""')
|
|
130
|
-
CI_ID=$(echo "$CI_JSON" | jq -r '.[0].databaseId // ""')
|
|
131
|
-
|
|
132
|
-
if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "success" ]; then
|
|
133
|
-
echo "OK: CI passed for $(git rev-parse --short HEAD)"
|
|
134
|
-
bp-yaml-set.sh specs/state.yaml release.ci_verified true 2>/dev/null || \
|
|
135
|
-
echo " (bp-yaml-set not available — manually set release.ci_verified: true in state.yaml)"
|
|
136
|
-
break
|
|
137
|
-
fi
|
|
138
|
-
|
|
139
|
-
if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "failure" ]; then
|
|
140
|
-
echo "FAIL: CI failed for $(git rev-parse --short HEAD)"
|
|
141
|
-
echo " Run URL: https://github.com/$(gh repo view --json nameWithOwner -q .nameWithOwner)/actions/runs/$CI_ID"
|
|
142
|
-
echo " Handoff to fix-bug with the failure URL above."
|
|
143
|
-
return 1
|
|
144
|
-
fi
|
|
145
|
-
|
|
146
|
-
sleep $INTERVAL
|
|
147
|
-
ELAPSED=$((ELAPSED + INTERVAL))
|
|
148
|
-
echo " Waiting... (${ELAPSED}s / ${TIMEOUT}s)"
|
|
149
|
-
done
|
|
150
|
-
|
|
151
|
-
echo "FAIL: CI did not complete within ${TIMEOUT}s timeout"
|
|
152
|
-
return 1
|
|
153
|
-
```
|
|
97
|
+
See [REFERENCE.md](REFERENCE.md)
|
|
154
98
|
|
|
155
99
|
- [ ] CI workflow passes after push
|
|
156
100
|
- [ ] `release.ci_verified: true` documented in state.yaml
|
|
@@ -176,21 +120,12 @@ git checkout main && git status && pwd
|
|
|
176
120
|
|
|
177
121
|
Report: "Branch released. Integrate mode: <solo-local|team-pr>. cwd: $(pwd) on $(git branch --show-current)."
|
|
178
122
|
|
|
179
|
-
## Solo-local fallback detail
|
|
180
|
-
|
|
181
|
-
The fallback sequence (Path B above) handles the "remote has moved" case with `git pull --rebase`. Use when `scripts/land-branch.sh` is absent.
|
|
182
|
-
|
|
183
|
-
**Acceptance:** When fallback runs, main is updated, feature branch is deleted locally, and output states `"used fallback merge (land-branch.sh not found)"`.
|
|
184
|
-
|
|
185
|
-
## Handoff
|
|
186
|
-
|
|
187
|
-
Gate: READY -> next: survey-context
|
|
188
|
-
Writes: state.yaml handoff.next_skill = survey-context
|
|
189
|
-
|
|
190
123
|
---
|
|
191
124
|
|
|
192
125
|
# Release Branch — Reference
|
|
193
126
|
|
|
127
|
+
# Release Branch — Reference
|
|
128
|
+
|
|
194
129
|
## PR body template (team-pr mode)
|
|
195
130
|
|
|
196
131
|
```bash
|
|
@@ -244,3 +179,84 @@ After landing the branch, record delivery metrics for this story:
|
|
|
244
179
|
cycle_minutes: 90
|
|
245
180
|
bcp_per_hour: 2.0
|
|
246
181
|
```
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Solo-local fallback detail
|
|
186
|
+
|
|
187
|
+
The fallback sequence (Path B above) handles the "remote has moved" case with `git pull --rebase`. Use when `scripts/land-branch.sh` is absent.
|
|
188
|
+
|
|
189
|
+
**Acceptance:** When fallback runs, main is updated, feature branch is deleted locally, and output states `"used fallback merge (land-branch.sh not found)"`.
|
|
190
|
+
|
|
191
|
+
## Handoff
|
|
192
|
+
|
|
193
|
+
Gate: READY -> next: survey-context
|
|
194
|
+
Writes: state.yaml handoff.next_skill = survey-context
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Reference block 1
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Fallback: manual squash-merge when land-branch.sh is absent
|
|
202
|
+
FEATURE_BRANCH=<task-slug>
|
|
203
|
+
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@' || echo main)
|
|
204
|
+
|
|
205
|
+
# Ensure we're on the feature branch
|
|
206
|
+
if [ "$(git branch --show-current)" != "$FEATURE_BRANCH" ]; then
|
|
207
|
+
git checkout "$FEATURE_BRANCH"
|
|
208
|
+
fi
|
|
209
|
+
|
|
210
|
+
# Checkout default branch and update
|
|
211
|
+
git checkout "$DEFAULT_BRANCH"
|
|
212
|
+
git pull --rebase origin "$DEFAULT_BRANCH" 2>/dev/null || git pull origin "$DEFAULT_BRANCH"
|
|
213
|
+
|
|
214
|
+
# Squash-merge the feature branch
|
|
215
|
+
git merge --no-ff "$FEATURE_BRANCH" -m "<conventional-commit-message>"
|
|
216
|
+
|
|
217
|
+
# Push
|
|
218
|
+
git push origin "$DEFAULT_BRANCH"
|
|
219
|
+
|
|
220
|
+
# Clean up local feature branch
|
|
221
|
+
git branch -d "$FEATURE_BRANCH"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Reference block 2
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
echo "==> Polling CI for main branch..."
|
|
230
|
+
TIMEOUT=600 # 10 minutes
|
|
231
|
+
INTERVAL=30 # poll every 30 seconds
|
|
232
|
+
ELAPSED=0
|
|
233
|
+
|
|
234
|
+
while [ $ELAPSED -lt $TIMEOUT ]; do
|
|
235
|
+
CI_JSON=$(gh run list --limit 1 --branch main --workflow CI --json status,conclusion,headSha,databaseId 2>/dev/null)
|
|
236
|
+
CI_STATUS=$(echo "$CI_JSON" | jq -r '.[0].status // "unknown"')
|
|
237
|
+
CI_CONCLUSION=$(echo "$CI_JSON" | jq -r '.[0].conclusion // ""')
|
|
238
|
+
CI_SHA=$(echo "$CI_JSON" | jq -r '.[0].headSha // ""')
|
|
239
|
+
CI_ID=$(echo "$CI_JSON" | jq -r '.[0].databaseId // ""')
|
|
240
|
+
|
|
241
|
+
if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "success" ]; then
|
|
242
|
+
echo "OK: CI passed for $(git rev-parse --short HEAD)"
|
|
243
|
+
bp-yaml-set.sh specs/state.yaml release.ci_verified true 2>/dev/null || \
|
|
244
|
+
echo " (bp-yaml-set not available — manually set release.ci_verified: true in state.yaml)"
|
|
245
|
+
break
|
|
246
|
+
fi
|
|
247
|
+
|
|
248
|
+
if [ "$CI_STATUS" = "completed" ] && [ "$CI_CONCLUSION" = "failure" ]; then
|
|
249
|
+
echo "FAIL: CI failed for $(git rev-parse --short HEAD)"
|
|
250
|
+
echo " Run URL: https://github.com/$(gh repo view --json nameWithOwner -q .nameWithOwner)/actions/runs/$CI_ID"
|
|
251
|
+
echo " Handoff to fix-bug with the failure URL above."
|
|
252
|
+
return 1
|
|
253
|
+
fi
|
|
254
|
+
|
|
255
|
+
sleep $INTERVAL
|
|
256
|
+
ELAPSED=$((ELAPSED + INTERVAL))
|
|
257
|
+
echo " Waiting... (${ELAPSED}s / ${TIMEOUT}s)"
|
|
258
|
+
done
|
|
259
|
+
|
|
260
|
+
echo "FAIL: CI did not complete within ${TIMEOUT}s timeout"
|
|
261
|
+
return 1
|
|
262
|
+
```
|