forked from molecule-ai/molecule-core
Merge pull request #2205 from Molecule-AI/staging
staging → main: pipeline self-healing fixes (#2203 + #2204) — final manual bridge
This commit is contained in:
commit
5cba11b2fb
29
.github/workflows/auto-promote-staging.yml
vendored
29
.github/workflows/auto-promote-staging.yml
vendored
@ -61,13 +61,30 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Required gate workflow names. Must match the `name:` field
|
||||
# in the respective .github/workflows/*.yml files.
|
||||
# Required gate workflow files. Use file paths (relative to
|
||||
# .github/workflows/) rather than display names because:
|
||||
#
|
||||
# 1. `gh run list --workflow=<name>` is ambiguous when two
|
||||
# workflows have the same `name:` — observed 2026-04-28
|
||||
# with "CodeQL" matching both `codeql.yml` (explicit) and
|
||||
# GitHub's UI-configured Code-quality default setup
|
||||
# (internal "codeql"). gh CLI returns "could not resolve
|
||||
# to a unique workflow" → empty result → gate evaluated
|
||||
# as missing/none → auto-promote dead-locked despite all
|
||||
# checks actually passing.
|
||||
#
|
||||
# 2. File paths are the unique identifier for workflows;
|
||||
# `name:` is just a display string and can collide.
|
||||
#
|
||||
# When adding/removing a gate, update this list AND the
|
||||
# branch-protection required-checks list (which uses check-run
|
||||
# display names, not workflow names; the two are decoupled and
|
||||
# should be kept in sync manually).
|
||||
GATES=(
|
||||
"CI"
|
||||
"E2E Staging Canvas (Playwright)"
|
||||
"E2E API Smoke Test"
|
||||
"CodeQL"
|
||||
"ci.yml"
|
||||
"e2e-staging-canvas.yml"
|
||||
"e2e-api.yml"
|
||||
"codeql.yml"
|
||||
)
|
||||
|
||||
echo "head_sha=${HEAD_SHA}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
62
.github/workflows/e2e-api.yml
vendored
62
.github/workflows/e2e-api.yml
vendored
@ -1,27 +1,73 @@
|
||||
name: E2E API Smoke Test
|
||||
# Extracted from ci.yml so workflow-level concurrency can protect this job
|
||||
# from run-level cancellation (issue #458).
|
||||
#
|
||||
# Trigger model (changed 2026-04-28 — see auto-promote gap below):
|
||||
#
|
||||
# This workflow always FIRES on push/pull_request to staging+main, but
|
||||
# only does real work when paths under `workspace-server/`,
|
||||
# `tests/e2e/`, or this workflow file changed. The detect-changes job
|
||||
# uses dorny/paths-filter to decide; the e2e-api job runs only if
|
||||
# changes match. Otherwise the no-op job emits success so the workflow
|
||||
# always produces a `completed/success` run record.
|
||||
#
|
||||
# Why: auto-promote-staging.yml's gate-check (line 99) treats "workflow
|
||||
# didn't run" as failure, which dead-locked any platform-only or
|
||||
# test-only push to staging that didn't touch workspace-server paths.
|
||||
# Dropping the path filter on the trigger and gating real work
|
||||
# internally guarantees the workflow always emits a result that the
|
||||
# auto-promote chain can read. Same pattern applied to
|
||||
# e2e-staging-canvas.yml in the same PR.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, staging]
|
||||
paths:
|
||||
- 'workspace-server/**'
|
||||
- 'tests/e2e/**'
|
||||
- '.github/workflows/e2e-api.yml'
|
||||
pull_request:
|
||||
branches: [main, staging]
|
||||
paths:
|
||||
- 'workspace-server/**'
|
||||
- 'tests/e2e/**'
|
||||
- '.github/workflows/e2e-api.yml'
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: e2e-api-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
detect-changes:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
api: ${{ steps.decide.outputs.api }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dorny/paths-filter@v3
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
api:
|
||||
- 'workspace-server/**'
|
||||
- 'tests/e2e/**'
|
||||
- '.github/workflows/e2e-api.yml'
|
||||
- id: decide
|
||||
# Always run real work for manual dispatch — no diff context to
|
||||
# filter against and ops dispatching this expects the suite to
|
||||
# actually exercise the platform.
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
echo "api=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "api=${{ steps.filter.outputs.api }}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
no-op:
|
||||
needs: detect-changes
|
||||
if: needs.detect-changes.outputs.api != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
echo "No workspace-server / tests/e2e / workflow changes — E2E API gate satisfied without running tests."
|
||||
echo "::notice::E2E API Smoke Test no-op pass (paths filter excluded this commit)."
|
||||
|
||||
e2e-api:
|
||||
needs: detect-changes
|
||||
if: needs.detect-changes.outputs.api == 'true'
|
||||
name: E2E API Smoke Test
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
|
||||
53
.github/workflows/e2e-staging-canvas.yml
vendored
53
.github/workflows/e2e-staging-canvas.yml
vendored
@ -13,16 +13,23 @@ name: E2E Staging Canvas (Playwright)
|
||||
# workflow — mirrors what PR #1891 does for e2e-api.yml.
|
||||
|
||||
on:
|
||||
# Trigger model (changed 2026-04-28 — see auto-promote gap below):
|
||||
#
|
||||
# Always fires on push/pull_request; only does real work when canvas/
|
||||
# or this workflow file changed. The detect-changes job uses
|
||||
# dorny/paths-filter to decide; the playwright job runs only if
|
||||
# changes match. Otherwise no-op emits success so the workflow always
|
||||
# produces a `completed/success` run record.
|
||||
#
|
||||
# Why: auto-promote-staging.yml's gate-check (line 99) treats
|
||||
# "workflow didn't run" as failure, which dead-locked platform-only
|
||||
# pushes to staging. Dropping the trigger path filter and gating real
|
||||
# work internally guarantees a result the auto-promote chain can
|
||||
# read. Same pattern applied to e2e-api.yml in the same PR.
|
||||
push:
|
||||
branches: [main, staging]
|
||||
paths:
|
||||
- 'canvas/**'
|
||||
- '.github/workflows/e2e-staging-canvas.yml'
|
||||
pull_request:
|
||||
branches: [main, staging]
|
||||
paths:
|
||||
- 'canvas/**'
|
||||
- '.github/workflows/e2e-staging-canvas.yml'
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Weekly on Sunday 08:00 UTC — catches Chrome / Playwright / Next.js
|
||||
@ -34,7 +41,41 @@ concurrency:
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
detect-changes:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
canvas: ${{ steps.decide.outputs.canvas }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dorny/paths-filter@v3
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
canvas:
|
||||
- 'canvas/**'
|
||||
- '.github/workflows/e2e-staging-canvas.yml'
|
||||
- id: decide
|
||||
# Always run real tests for manual dispatch and the weekly cron —
|
||||
# both exist precisely to exercise the suite, regardless of diff.
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ] || [ "${{ github.event_name }}" = "schedule" ]; then
|
||||
echo "canvas=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "canvas=${{ steps.filter.outputs.canvas }}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
no-op:
|
||||
needs: detect-changes
|
||||
if: needs.detect-changes.outputs.canvas != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
echo "No canvas / workflow changes — E2E Staging Canvas gate satisfied without running tests."
|
||||
echo "::notice::E2E Staging Canvas no-op pass (paths filter excluded this commit)."
|
||||
|
||||
playwright:
|
||||
needs: detect-changes
|
||||
if: needs.detect-changes.outputs.canvas == 'true'
|
||||
name: Canvas tabs E2E
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 40
|
||||
|
||||
Loading…
Reference in New Issue
Block a user