Skip to content

Commit 43ac2fc

Browse files
committed
Fail smoke summary if any provider fails
1 parent cf9fe77 commit 43ac2fc

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 }}
@@ -162,21 +166,37 @@ jobs:
162166
MATOMO_LOG_FILE: ${{ env.MATOMO_DIR }}/tmp/logs/matomo.log
163167
PHP_SERVER_LOG_FILE: ${{ env.MATOMO_DIR }}/tmp/logs/php-server.log
164168

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

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

217237
- name: Codex MCP smoke suite
238+
id: smoke_suite
239+
continue-on-error: true
218240
run: ./.github/scripts/mcp-smoke/run-codex-smoke.sh
219241
env:
220242
OPENAI_APIKEY: ${{ secrets.OPENAI_APIKEY }}
@@ -227,21 +249,37 @@ jobs:
227249
MATOMO_LOG_FILE: ${{ env.MATOMO_DIR }}/tmp/logs/matomo.log
228250
PHP_SERVER_LOG_FILE: ${{ env.MATOMO_DIR }}/tmp/logs/php-server.log
229251

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

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

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

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

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

0 commit comments

Comments
 (0)