@andwhy/e2e-pipeline 0.12.1 → 0.12.2
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@andwhy/e2e-pipeline",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.2",
|
|
4
4
|
"description": "Scaffolds the full e2e testing pipeline: agent-assisted Playwright tests, CI runs against Vercel previews, and Checkly monitors that follow production deploys",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -43,6 +43,12 @@ negotiable:
|
|
|
43
43
|
workflow reads your outcome from it after you finish, and destroying it
|
|
44
44
|
turns your entire run into an unexplained failure. No `rm -rf`, no
|
|
45
45
|
`git clean`. Only add files to it.
|
|
46
|
+
6. **Runtime is metered — stop the moment the classification is certain.**
|
|
47
|
+
You run under a hard 35-minute step timeout, and every minute is paid CI
|
|
48
|
+
and API time. Run the narrowest thing that answers the current question,
|
|
49
|
+
never the full suite, and never re-run a test whose answer you already
|
|
50
|
+
have. If the deadline nears, write an honest partial outcome instead of
|
|
51
|
+
pushing on — a run killed by the timeout reports nothing.
|
|
46
52
|
|
|
47
53
|
## Procedure
|
|
48
54
|
|
|
@@ -60,17 +66,20 @@ run "wasn't real".
|
|
|
60
66
|
|
|
61
67
|
### 2. Reproduce
|
|
62
68
|
|
|
63
|
-
|
|
69
|
+
Identify the narrowest reproduction: the failing spec and test named by
|
|
70
|
+
`result.json` when present; without a result file, the spec files belonging
|
|
71
|
+
to the failing check. Run that once against production, stopping at the
|
|
72
|
+
first failure:
|
|
64
73
|
|
|
65
74
|
```bash
|
|
66
|
-
BASE_URL=<production-url> pnpm playwright test <failing-spec> --project=Chrome
|
|
75
|
+
BASE_URL=<production-url> pnpm playwright test <failing-spec> --project=Chrome --max-failures=1
|
|
67
76
|
```
|
|
68
77
|
|
|
69
78
|
- **Fails** → continue to triage.
|
|
70
|
-
- **Passes** →
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
79
|
+
- **Passes** → classification `not-reproducible`. Write the outcome and stop
|
|
80
|
+
immediately — no repeat runs, no wider investigation. Checkly saw it fail
|
|
81
|
+
and it passes now, so the blip was transient; a genuinely unstable test
|
|
82
|
+
will alert again, and that repetition is the signal a human acts on.
|
|
74
83
|
|
|
75
84
|
### 3. Triage — before any edit
|
|
76
85
|
|
|
@@ -84,9 +93,10 @@ the live page:
|
|
|
84
93
|
behavior hides an outage.
|
|
85
94
|
- **The test is flaky.** The outcome works, but the test fails
|
|
86
95
|
intermittently — races, missing waits for dynamic content, animation
|
|
87
|
-
timing, order-dependent assertions.
|
|
88
|
-
|
|
89
|
-
|
|
96
|
+
timing, order-dependent assertions. When the trace alone doesn't settle
|
|
97
|
+
it, repeating the one failing test is the only permitted repeat run.
|
|
98
|
+
Classification `flaky` — proceed to step 4 and fix the root cause per the
|
|
99
|
+
robustness rules; blanket timeout increases are not a fix.
|
|
90
100
|
- **The test is stale.** Production changed legitimately (new markup, changed
|
|
91
101
|
copy, moved element) and the test's selectors or assertions no longer
|
|
92
102
|
describe it, while the actual user outcome still works. Classification
|
|
@@ -113,10 +123,11 @@ that make the test robust.
|
|
|
113
123
|
|
|
114
124
|
### 5. Verify
|
|
115
125
|
|
|
116
|
-
- **Test-only fixes:** re-run the spec against production until green —
|
|
117
|
-
flaky fix, prove stability with `--repeat-each=5
|
|
118
|
-
|
|
119
|
-
|
|
126
|
+
- **Test-only fixes:** re-run the fixed spec against production until green —
|
|
127
|
+
for a flaky fix, prove stability with `--repeat-each=5` on that one spec,
|
|
128
|
+
not a single pass. Do not run the full suite (override 6): the heal PR gets
|
|
129
|
+
its own `pr-playwright-tests` preview run, and that is where collateral
|
|
130
|
+
damage surfaces. Validate the fixed spec on Checkly's infrastructure:
|
|
120
131
|
|
|
121
132
|
```bash
|
|
122
133
|
pnpm checkly pw-test --env BASE_URL="<production-url>" -- <failing-spec>
|
|
@@ -165,36 +165,55 @@ jobs:
|
|
|
165
165
|
npm install -g @anthropic-ai/claude-code@2
|
|
166
166
|
# Transcript lives OUTSIDE .checkly-heal so it survives whatever the
|
|
167
167
|
# agent does to its working directory, and outside the repo tree so
|
|
168
|
-
# the diff guard never counts it.
|
|
168
|
+
# the diff guard never counts it. stream-json writes each event as it
|
|
169
|
+
# happens — a run killed by the timeout still leaves the full history
|
|
170
|
+
# (plain json buffers everything and a kill leaves an empty file).
|
|
169
171
|
claude -p "$(cat .github/prompts/checkly-heal.md)" \
|
|
170
172
|
--model claude-opus-5 \
|
|
171
173
|
--allowedTools "Bash,Read,Edit,Write,Glob,Grep" \
|
|
172
174
|
--permission-mode dontAsk \
|
|
173
175
|
--max-turns 150 \
|
|
174
|
-
--output-format json \
|
|
175
|
-
> /tmp/checkly-heal-agent-output.json || echo "claude exited non-zero: $?"
|
|
176
|
+
--output-format stream-json --verbose \
|
|
177
|
+
> /tmp/checkly-heal-agent-output.json || echo "claude exited non-zero: $?" | tee -a "$GITHUB_STEP_SUMMARY"
|
|
178
|
+
# Diagnostics go to the job log AND the summary: the log is readable
|
|
179
|
+
# over the API, the summary only in the browser.
|
|
176
180
|
{
|
|
177
181
|
echo "### Agent step diagnostics"
|
|
178
182
|
echo '```'
|
|
179
183
|
ls -la .checkly-heal 2>&1 || echo ".checkly-heal missing"
|
|
180
184
|
tail -c 2000 /tmp/checkly-heal-agent-output.json 2>/dev/null || echo "no agent output"
|
|
181
185
|
echo '```'
|
|
182
|
-
}
|
|
186
|
+
} | tee -a "$GITHUB_STEP_SUMMARY"
|
|
183
187
|
|
|
184
188
|
# The guard is deterministic on purpose: the PR path requires an outcome
|
|
185
189
|
# file claiming a fix AND a diff clear of protected paths. App-source
|
|
186
190
|
# changes (test hooks) are allowed but derived from the diff, not the
|
|
187
191
|
# agent's claim, and flagged downstream. Everything else — protected
|
|
188
192
|
# paths, missing outcome, other classifications — escalates.
|
|
193
|
+
# always(): a killed agent step (timeout, cancel) must still produce a
|
|
194
|
+
# classification, or Slack reports an unexplained failure.
|
|
189
195
|
- name: Read the outcome and guard the diff
|
|
190
|
-
if: steps.guard.outputs.mode == 'heal'
|
|
196
|
+
if: always() && steps.guard.outputs.mode == 'heal'
|
|
191
197
|
id: outcome
|
|
198
|
+
env:
|
|
199
|
+
AGENT_CONCLUSION: ${{ steps.agent.conclusion }}
|
|
192
200
|
run: |
|
|
193
201
|
classification="agent-failed"
|
|
194
202
|
summary="The heal agent did not produce an outcome."
|
|
195
|
-
if [ -f .checkly-heal/outcome.json ] && jq -e . .checkly-heal/outcome.json > /dev/null 2>&1; then
|
|
203
|
+
if [ "$AGENT_CONCLUSION" = "success" ] && [ -f .checkly-heal/outcome.json ] && jq -e . .checkly-heal/outcome.json > /dev/null 2>&1; then
|
|
196
204
|
classification=$(jq -r '.classification // "agent-failed"' .checkly-heal/outcome.json)
|
|
197
205
|
summary=$(jq -r '.summary // ""' .checkly-heal/outcome.json)
|
|
206
|
+
else
|
|
207
|
+
# No trustworthy outcome — say WHY, so the Slack message diagnoses
|
|
208
|
+
# itself. An outcome written before a kill is unverified: escalate
|
|
209
|
+
# rather than open a PR for it.
|
|
210
|
+
if [ "$AGENT_CONCLUSION" = "skipped" ]; then
|
|
211
|
+
summary="The heal agent never ran — a setup step failed before it."
|
|
212
|
+
elif [ "$AGENT_CONCLUSION" != "success" ]; then
|
|
213
|
+
summary="The heal agent was killed before finishing (step conclusion: ${AGENT_CONCLUSION:-unknown} — usually the 35-minute timeout)."
|
|
214
|
+
fi
|
|
215
|
+
agent_error=$(jq -r 'select(.is_error == true) | .result // empty' /tmp/checkly-heal-agent-output.json 2>/dev/null | head -c 300)
|
|
216
|
+
[ -n "$agent_error" ] && summary="$summary Agent error: $agent_error"
|
|
198
217
|
fi
|
|
199
218
|
|
|
200
219
|
files=$(git status --porcelain | awk '{print $NF}' | grep -v "^\.checkly-heal/" || true)
|
|
@@ -332,5 +351,8 @@ jobs:
|
|
|
332
351
|
path: |
|
|
333
352
|
.checkly-heal/
|
|
334
353
|
/tmp/checkly-heal-agent-output.json
|
|
354
|
+
# .checkly-heal is a dot-directory; without this it is silently
|
|
355
|
+
# excluded and the debug artifact loses context/outcome/result.
|
|
356
|
+
include-hidden-files: true
|
|
335
357
|
if-no-files-found: ignore
|
|
336
358
|
retention-days: 14
|