Skip to content

Commit ccecb21

Browse files
committed
Fail smoke summary if any provider fails
1 parent 5ea255c commit ccecb21

2 files changed

Lines changed: 98 additions & 10 deletions

File tree

.github/scripts/mcp-smoke/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,6 @@ This harness powers `.github/workflows/mcp-ai-smoke.yml`.
4545
- Claude defaults to the generic `sonnet` alias, with `claude_model` still available in `workflow_dispatch` for pinned-model overrides.
4646
- Gemini, Codex, and Claude run in separate CI jobs with isolated Matomo environments and log files.
4747
- Provider jobs share a local composite action for the common Matomo/bootstrap sequence.
48-
- The workflow is intentionally report-first/non-blocking for internal prototype usage.
49-
- The workflow uploads one artifact per provider job and builds a combined summary from the downloaded per-provider `results.json` files.
48+
- The workflow is intentionally report-first: provider jobs continue far enough to upload artifacts and append per-provider summaries even when an individual smoke run fails.
49+
- The final workflow status is driven by explicit per-provider outcomes emitted by the workflow jobs, not by GitHub's masked `needs.<job>.result` values for `continue-on-error` jobs.
50+
- The workflow uploads one artifact per provider job, and detailed case-level diagnostics remain in each provider's `results.json` artifact bundle.

.github/workflows/mcp-ai-smoke.yml

Lines changed: 95 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,8 @@ jobs:
112112
needs: preflight
113113
if: needs.preflight.outputs.has_gemini == 'true'
114114
continue-on-error: true
115+
outputs:
116+
provider_outcome: ${{ steps.set_provider_outcome.outputs.provider_outcome }}
115117
timeout-minutes: 30
116118
services:
117119
mysql:
@@ -150,6 +152,8 @@ jobs:
150152
run: npm install -g @google/gemini-cli
151153

152154
- name: Gemini MCP smoke suite
155+
id: smoke_suite
156+
continue-on-error: true
153157
run: ./.github/scripts/mcp-smoke/run-gemini-smoke.sh
154158
env:
155159
GEMINI_APIKEY: ${{ secrets.GEMINI_APIKEY }}
@@ -163,21 +167,37 @@ jobs:
163167
MATOMO_LOG_FILE: ${{ env.MATOMO_DIR }}/tmp/logs/matomo.log
164168
PHP_SERVER_LOG_FILE: ${{ env.MATOMO_DIR }}/tmp/logs/php-server.log
165169

170+
- name: Set Gemini provider outcome
171+
id: set_provider_outcome
172+
if: always()
173+
run: |
174+
provider_outcome="success"
175+
176+
if [ "${{ job.status }}" != "success" ] || [ "${{ steps.smoke_suite.outcome }}" = "failure" ]; then
177+
provider_outcome="failure"
178+
elif [ "${{ steps.smoke_suite.outcome }}" = "cancelled" ]; then
179+
provider_outcome="cancelled"
180+
fi
181+
182+
echo "provider_outcome=${provider_outcome}" >> "$GITHUB_OUTPUT"
183+
166184
- name: Finalize Gemini smoke job
167185
if: always()
168186
uses: ./.github/actions/finalize-mcp-smoke-job
169187
with:
170188
provider_label: Gemini
171189
artifact_dir: ${{ github.workspace }}/.github/scripts/mcp-smoke/artifacts/gemini
172190
artifact_name: mcp-ai-smoke-gemini
173-
job_status: ${{ job.status }}
191+
job_status: ${{ steps.set_provider_outcome.outputs.provider_outcome }}
174192

175193
smoke_codex:
176194
name: Codex smoke
177195
runs-on: ubuntu-24.04
178196
needs: preflight
179197
if: needs.preflight.outputs.has_codex == 'true'
180198
continue-on-error: true
199+
outputs:
200+
provider_outcome: ${{ steps.set_provider_outcome.outputs.provider_outcome }}
181201
timeout-minutes: 30
182202
services:
183203
mysql:
@@ -216,6 +236,8 @@ jobs:
216236
run: npm install -g @openai/codex
217237

218238
- name: Codex MCP smoke suite
239+
id: smoke_suite
240+
continue-on-error: true
219241
run: ./.github/scripts/mcp-smoke/run-codex-smoke.sh
220242
env:
221243
OPENAI_APIKEY: ${{ secrets.OPENAI_APIKEY }}
@@ -228,21 +250,37 @@ jobs:
228250
MATOMO_LOG_FILE: ${{ env.MATOMO_DIR }}/tmp/logs/matomo.log
229251
PHP_SERVER_LOG_FILE: ${{ env.MATOMO_DIR }}/tmp/logs/php-server.log
230252

253+
- name: Set Codex provider outcome
254+
id: set_provider_outcome
255+
if: always()
256+
run: |
257+
provider_outcome="success"
258+
259+
if [ "${{ job.status }}" != "success" ] || [ "${{ steps.smoke_suite.outcome }}" = "failure" ]; then
260+
provider_outcome="failure"
261+
elif [ "${{ steps.smoke_suite.outcome }}" = "cancelled" ]; then
262+
provider_outcome="cancelled"
263+
fi
264+
265+
echo "provider_outcome=${provider_outcome}" >> "$GITHUB_OUTPUT"
266+
231267
- name: Finalize Codex smoke job
232268
if: always()
233269
uses: ./.github/actions/finalize-mcp-smoke-job
234270
with:
235271
provider_label: Codex
236272
artifact_dir: ${{ github.workspace }}/.github/scripts/mcp-smoke/artifacts/codex
237273
artifact_name: mcp-ai-smoke-codex
238-
job_status: ${{ job.status }}
274+
job_status: ${{ steps.set_provider_outcome.outputs.provider_outcome }}
239275

240276
smoke_claude:
241277
name: Claude smoke
242278
runs-on: ubuntu-24.04
243279
needs: preflight
244280
if: needs.preflight.outputs.has_claude == 'true'
245281
continue-on-error: true
282+
outputs:
283+
provider_outcome: ${{ steps.set_provider_outcome.outputs.provider_outcome }}
246284
timeout-minutes: 30
247285
services:
248286
mysql:
@@ -281,6 +319,8 @@ jobs:
281319
run: npm install -g @anthropic-ai/claude-code
282320

283321
- name: Claude MCP smoke suite
322+
id: smoke_suite
323+
continue-on-error: true
284324
run: ./.github/scripts/mcp-smoke/run-claude-smoke.sh
285325
env:
286326
ANTHROPIC_API_KEY: ${{ secrets.CLAUDE_APIKEY }}
@@ -293,20 +333,34 @@ jobs:
293333
MATOMO_LOG_FILE: ${{ env.MATOMO_DIR }}/tmp/logs/matomo.log
294334
PHP_SERVER_LOG_FILE: ${{ env.MATOMO_DIR }}/tmp/logs/php-server.log
295335

336+
- name: Set Claude provider outcome
337+
id: set_provider_outcome
338+
if: always()
339+
run: |
340+
provider_outcome="success"
341+
342+
if [ "${{ job.status }}" != "success" ] || [ "${{ steps.smoke_suite.outcome }}" = "failure" ]; then
343+
provider_outcome="failure"
344+
elif [ "${{ steps.smoke_suite.outcome }}" = "cancelled" ]; then
345+
provider_outcome="cancelled"
346+
fi
347+
348+
echo "provider_outcome=${provider_outcome}" >> "$GITHUB_OUTPUT"
349+
296350
- name: Finalize Claude smoke job
297351
if: always()
298352
uses: ./.github/actions/finalize-mcp-smoke-job
299353
with:
300354
provider_label: Claude
301355
artifact_dir: ${{ github.workspace }}/.github/scripts/mcp-smoke/artifacts/claude
302356
artifact_name: mcp-ai-smoke-claude
303-
job_status: ${{ job.status }}
357+
job_status: ${{ steps.set_provider_outcome.outputs.provider_outcome }}
304358

305359
summary:
306360
name: Final status
307361
runs-on: ubuntu-24.04
308362
needs: [preflight, smoke_gemini, smoke_codex, smoke_claude]
309-
if: always()
363+
if: needs.preflight.outputs.should_run == 'true'
310364
steps:
311365
- name: Final status summary
312366
run: |
@@ -318,9 +372,42 @@ jobs:
318372
echo "- Codex available: ${{ needs.preflight.outputs.has_codex }}"
319373
echo "- Claude available: ${{ needs.preflight.outputs.has_claude }}"
320374
echo "- reason: ${{ needs.preflight.outputs.reason }}"
321-
echo "- Gemini job result: ${{ needs.smoke_gemini.result || 'skipped' }}"
322-
echo "- Codex job result: ${{ needs.smoke_codex.result || 'skipped' }}"
323-
echo "- Claude job result: ${{ needs.smoke_claude.result || 'skipped' }}"
375+
echo "- Gemini provider outcome: ${{ needs.preflight.outputs.has_gemini == 'true' && needs.smoke_gemini.outputs.provider_outcome || 'skipped' }}"
376+
echo "- Codex provider outcome: ${{ needs.preflight.outputs.has_codex == 'true' && needs.smoke_codex.outputs.provider_outcome || 'skipped' }}"
377+
echo "- Claude provider outcome: ${{ needs.preflight.outputs.has_claude == 'true' && needs.smoke_claude.outputs.provider_outcome || 'skipped' }}"
324378
echo
325-
echo "Prototype smoke is intentionally non-blocking."
379+
echo "Detailed per-case results remain in the individual provider jobs and uploaded artifacts."
326380
} >> "$GITHUB_STEP_SUMMARY"
381+
382+
- name: Evaluate overall result
383+
run: |
384+
set -euo pipefail
385+
386+
gemini_result="${{ needs.preflight.outputs.has_gemini == 'true' && needs.smoke_gemini.outputs.provider_outcome || 'skipped' }}"
387+
codex_result="${{ needs.preflight.outputs.has_codex == 'true' && needs.smoke_codex.outputs.provider_outcome || 'skipped' }}"
388+
claude_result="${{ needs.preflight.outputs.has_claude == 'true' && needs.smoke_claude.outputs.provider_outcome || 'skipped' }}"
389+
390+
ran_providers=0
391+
failed_providers=0
392+
393+
for result in "$gemini_result" "$codex_result" "$claude_result"; do
394+
if [ "$result" != "skipped" ]; then
395+
ran_providers=$((ran_providers + 1))
396+
fi
397+
398+
if [ "$result" != "success" ] && [ "$result" != "skipped" ]; then
399+
failed_providers=$((failed_providers + 1))
400+
fi
401+
done
402+
403+
if [ "$ran_providers" -eq 0 ]; then
404+
echo "No provider jobs ran."
405+
exit 0
406+
fi
407+
408+
if [ "$failed_providers" -gt 0 ]; then
409+
echo "$failed_providers provider job(s) failed."
410+
exit 1
411+
fi
412+
413+
echo "All provider jobs succeeded."

0 commit comments

Comments
 (0)