ci(workflows): #2802 propagate detect-changes debug output + fail-open #2833

Merged
devops-engineer merged 3 commits from fix/2802-detect-changes-debug-output into main 2026-06-14 09:33:10 +00:00
7 changed files with 110 additions and 15 deletions
+22 -4
View File
@@ -80,6 +80,7 @@ jobs:
canvas: ${{ steps.check.outputs.canvas }}
python: ${{ steps.check.outputs.python }}
scripts: ${{ steps.check.outputs.scripts }}
debug: ${{ steps.check.outputs.debug }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
@@ -90,12 +91,23 @@ jobs:
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
PUSH_BEFORE: ${{ github.event.before }}
run: |
BASE_SHA="${PR_BASE_SHA:-$PUSH_BEFORE}"
python3 .gitea/scripts/detect-changes.py \
--profile ci \
--event-name "${{ github.event_name }}" \
--pr-base-sha "$PR_BASE_SHA" \
--base-ref "$PR_BASE_REF" \
--push-before "${GITHUB_EVENT_BEFORE:-$PUSH_BEFORE}"
--push-before "${GITHUB_EVENT_BEFORE:-$PUSH_BEFORE}" || {
# Script crash / uncaught error: fail open so every CI profile
# runs rather than silently no-oping a potentially-breaking PR.
echo "platform=true" >> "$GITHUB_OUTPUT"
echo "canvas=true" >> "$GITHUB_OUTPUT"
echo "python=true" >> "$GITHUB_OUTPUT"
echo "scripts=true" >> "$GITHUB_OUTPUT"
echo "debug=detect-script-error event=${{ github.event_name }} base=$BASE_SHA" >> "$GITHUB_OUTPUT"
exit 0
}
echo "debug=profile=ci event=${{ github.event_name }} base=$BASE_SHA" >> "$GITHUB_OUTPUT"
# Platform (Go) — Go build/vet/test/lint + coverage gates. The job always
# emits the required context, but expensive steps are path-scoped on every
@@ -126,7 +138,9 @@ jobs:
steps:
- if: ${{ needs.changes.outputs.platform != 'true' }}
working-directory: .
run: echo "No workspace-server/** changes — Platform (Go) gate satisfied without running Go build/test/lint."
run: |
echo "No workspace-server/** changes — Platform (Go) gate satisfied without running Go build/test/lint."
echo "::notice::detect-changes debug: ${{ needs.changes.outputs.debug }}"
- if: ${{ needs.changes.outputs.platform == 'true' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- if: ${{ needs.changes.outputs.platform == 'true' }}
@@ -303,7 +317,9 @@ jobs:
steps:
- if: ${{ needs.changes.outputs.canvas != 'true' }}
working-directory: .
run: echo "No canvas/** changes — Canvas (Next.js) gate satisfied without running npm build/test."
run: |
echo "No canvas/** changes — Canvas (Next.js) gate satisfied without running npm build/test."
echo "::notice::detect-changes debug: ${{ needs.changes.outputs.debug }}"
- if: ${{ needs.changes.outputs.canvas == 'true' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- if: ${{ needs.changes.outputs.canvas == 'true' }}
@@ -351,7 +367,9 @@ jobs:
continue-on-error: false
steps:
- if: ${{ needs.changes.outputs.scripts != 'true' }}
run: echo "No tests/e2e, scripts, or infra/scripts changes — Shellcheck gate satisfied without running script checks."
run: |
echo "No tests/e2e, scripts, or infra/scripts changes — Shellcheck gate satisfied without running script checks."
echo "::notice::detect-changes debug: ${{ needs.changes.outputs.debug }}"
- if: ${{ needs.changes.outputs.scripts == 'true' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- if: ${{ needs.changes.outputs.scripts == 'true' }}
+17 -3
View File
@@ -128,18 +128,31 @@ jobs:
continue-on-error: false
outputs:
api: ${{ steps.decide.outputs.api }}
debug: ${{ steps.decide.outputs.debug }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- id: decide
env:
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
PUSH_BEFORE: ${{ github.event.before }}
run: |
BASE_SHA="${PR_BASE_SHA:-$PUSH_BEFORE}"
python3 .gitea/scripts/detect-changes.py \
--profile e2e-api \
--event-name "${{ github.event_name }}" \
--pr-base-sha "${{ github.event.pull_request.base.sha }}" \
--base-ref "${{ github.event.pull_request.base.ref }}" \
--push-before "${GITHUB_EVENT_BEFORE:-${{ github.event.before }}}"
--pr-base-sha "$PR_BASE_SHA" \
--base-ref "$PR_BASE_REF" \
--push-before "${GITHUB_EVENT_BEFORE:-$PUSH_BEFORE}" || {
# Script crash / uncaught error: fail open so the E2E gate runs
# rather than silently no-oping a potentially-breaking PR.
echo "api=true" >> "$GITHUB_OUTPUT"
echo "debug=detect-script-error event=${{ github.event_name }} base=$BASE_SHA" >> "$GITHUB_OUTPUT"
exit 0
}
echo "debug=profile=e2e-api event=${{ github.event_name }} base=$BASE_SHA" >> "$GITHUB_OUTPUT"
# ONE job (no job-level `if:`) that always runs and reports under the
# required-check name `E2E API Smoke Test`. Real work is gated per-step
@@ -179,6 +192,7 @@ jobs:
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)."
echo "::notice::detect-changes debug: ${{ needs.detect-changes.outputs.debug }}"
- if: needs.detect-changes.outputs.api == 'true'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- if: needs.detect-changes.outputs.api == 'true'
+19 -1
View File
@@ -52,6 +52,7 @@ jobs:
continue-on-error: true
outputs:
chat: ${{ steps.decide.outputs.chat }}
debug: ${{ steps.decide.outputs.debug }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
@@ -63,6 +64,7 @@ jobs:
run: |
if [ "${{ github.event_name }}" = "schedule" ] || [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "chat=true" >> "$GITHUB_OUTPUT"
echo "debug=manual-trigger event=${{ github.event_name }}" >> "$GITHUB_OUTPUT"
exit 0
fi
BASE="${GITHUB_BASE_REF:-${{ github.event.before }}}"
@@ -71,6 +73,7 @@ jobs:
fi
if [ -z "$BASE" ] || echo "$BASE" | grep -qE '^0+$'; then
echo "chat=true" >> "$GITHUB_OUTPUT"
echo "debug=new-branch-fallback base=$BASE" >> "$GITHUB_OUTPUT"
exit 0
fi
if ! git cat-file -e "$BASE" 2>/dev/null; then
@@ -78,15 +81,19 @@ jobs:
fi
if ! git cat-file -e "$BASE" 2>/dev/null; then
echo "chat=true" >> "$GITHUB_OUTPUT"
echo "debug=base-missing-fallback base=$BASE" >> "$GITHUB_OUTPUT"
exit 0
fi
CHANGED=$(git diff --name-only "$BASE" HEAD)
CHANGED_FLAT=$(echo "$CHANGED" | tr '\n' ',')
if ! echo "$CHANGED" | grep -qE '^(canvas/|workspace-server/|\.gitea/workflows/e2e-chat\.yml$)'; then
echo "chat=false" >> "$GITHUB_OUTPUT"
echo "debug=no-matching-paths base=$BASE changed=$CHANGED_FLAT" >> "$GITHUB_OUTPUT"
exit 0
fi
if [ "${{ github.event_name }}" != "pull_request" ]; then
echo "chat=true" >> "$GITHUB_OUTPUT"
echo "debug=non-pr-run base=$BASE changed=$CHANGED_FLAT" >> "$GITHUB_OUTPUT"
exit 0
fi
@@ -95,13 +102,23 @@ jobs:
printf 'header = "Authorization: token %s"\n' "$GITEA_TOKEN" > "$authfile"
labels=$(curl -fsS -K "$authfile" \
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels" \
| python3 -c 'import json,sys; print("\n".join(label.get("name","") for label in json.load(sys.stdin)))')
| python3 -c 'import json,sys; print("\n".join(label.get("name","") for label in json.load(sys.stdin)))') || {
# Labels API unavailable: fail open so the E2E gate runs rather
# than silently no-oping a potentially-breaking PR.
rm -f "$authfile"
echo "chat=true" >> "$GITHUB_OUTPUT"
echo "debug=labels-api-unavailable pr=${{ github.event.pull_request.number }} base=$BASE changed=$CHANGED_FLAT" >> "$GITHUB_OUTPUT"
exit 0
}
rm -f "$authfile"
LABELS_FLAT=$(echo "$labels" | tr '\n' ',')
if printf '%s\n' "$labels" | grep -qx "$QUEUE_LABEL"; then
echo "chat=true" >> "$GITHUB_OUTPUT"
echo "debug=merge-queue-labeled base=$BASE changed=$CHANGED_FLAT" >> "$GITHUB_OUTPUT"
else
echo "PR is not in merge-queue; skipping heavy E2E Chat for normal PR path."
echo "chat=false" >> "$GITHUB_OUTPUT"
echo "debug=no-merge-queue-label base=$BASE changed=$CHANGED_FLAT labels=$LABELS_FLAT" >> "$GITHUB_OUTPUT"
fi
# bp-required: pending #1142 — new E2E check; add to branch protection after 3 green runs.
@@ -146,6 +163,7 @@ jobs:
run: |
echo "No canvas / workspace-server / workflow changes — E2E Chat gate satisfied without running tests."
echo "::notice::E2E Chat no-op pass (paths filter excluded this commit)."
echo "::notice::detect-changes debug: ${{ needs.detect-changes.outputs.debug }}"
- if: needs.detect-changes.outputs.chat == 'true'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+11 -1
View File
@@ -125,6 +125,7 @@ jobs:
continue-on-error: false
outputs:
peervis: ${{ steps.filter.outputs.peervis }}
debug: ${{ steps.filter.outputs.debug }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
@@ -137,12 +138,20 @@ jobs:
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
PUSH_BEFORE: ${{ github.event.before }}
run: |
BASE_SHA="${PR_BASE_SHA:-$PUSH_BEFORE}"
python3 .gitea/scripts/detect-changes.py \
--profile peer-visibility \
--event-name "${{ github.event_name }}" \
--pr-base-sha "$PR_BASE_SHA" \
--base-ref "$PR_BASE_REF" \
--push-before "${GITHUB_EVENT_BEFORE:-$PUSH_BEFORE}"
--push-before "${GITHUB_EVENT_BEFORE:-$PUSH_BEFORE}" || {
# Script crash / uncaught error: fail open so the E2E gate runs
# rather than silently no-oping a potentially-breaking PR.
echo "peervis=true" >> "$GITHUB_OUTPUT"
echo "debug=detect-script-error event=${{ github.event_name }} base=$BASE_SHA" >> "$GITHUB_OUTPUT"
exit 0
}
echo "debug=profile=peer-visibility event=${{ github.event_name }} base=$BASE_SHA" >> "$GITHUB_OUTPUT"
# THE required-check emitter. ONE always-running job (no job-level `if:`)
# named `E2E Peer Visibility`, so it posts EXACTLY ONE check run under the
@@ -208,6 +217,7 @@ jobs:
run: |
echo "No peer-visibility-relevant changes — E2E Peer Visibility gate satisfied without running the staging E2E."
echo "::notice::E2E Peer Visibility no-op pass (detect-changes profile peer-visibility excluded this push)."
echo "::notice::detect-changes debug: ${{ needs.changes.outputs.debug }}"
# --- push/dispatch/cron + relevant change: the REAL staging E2E ------
- name: Verify admin token present
+19 -1
View File
@@ -96,6 +96,7 @@ jobs:
continue-on-error: true
outputs:
canvas: ${{ steps.decide.outputs.canvas }}
debug: ${{ steps.decide.outputs.debug }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
@@ -109,6 +110,7 @@ jobs:
run: |
if [ "${{ github.event_name }}" = "schedule" ] || [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "canvas=true" >> "$GITHUB_OUTPUT"
echo "debug=manual-trigger event=${{ github.event_name }}" >> "$GITHUB_OUTPUT"
exit 0
fi
BASE="${GITHUB_BASE_REF:-${{ github.event.before }}}"
@@ -117,6 +119,7 @@ jobs:
fi
if [ -z "$BASE" ] || echo "$BASE" | grep -qE '^0+$'; then
echo "canvas=true" >> "$GITHUB_OUTPUT"
echo "debug=new-branch-fallback base=$BASE" >> "$GITHUB_OUTPUT"
exit 0
fi
if ! git cat-file -e "$BASE" 2>/dev/null; then
@@ -124,15 +127,19 @@ jobs:
fi
if ! git cat-file -e "$BASE" 2>/dev/null; then
echo "canvas=true" >> "$GITHUB_OUTPUT"
echo "debug=base-missing-fallback base=$BASE" >> "$GITHUB_OUTPUT"
exit 0
fi
CHANGED=$(git diff --name-only "$BASE" HEAD)
CHANGED_FLAT=$(echo "$CHANGED" | tr '\n' ',')
if ! echo "$CHANGED" | grep -qE '^(canvas/|\.gitea/workflows/e2e-staging-canvas\.yml$)'; then
echo "canvas=false" >> "$GITHUB_OUTPUT"
echo "debug=no-matching-paths base=$BASE changed=$CHANGED_FLAT" >> "$GITHUB_OUTPUT"
exit 0
fi
if [ "${{ github.event_name }}" != "pull_request" ]; then
echo "canvas=true" >> "$GITHUB_OUTPUT"
echo "debug=non-pr-run base=$BASE changed=$CHANGED_FLAT" >> "$GITHUB_OUTPUT"
exit 0
fi
@@ -141,13 +148,23 @@ jobs:
printf 'header = "Authorization: token %s"\n' "$GITEA_TOKEN" > "$authfile"
labels=$(curl -fsS -K "$authfile" \
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels" \
| python3 -c 'import json,sys; print("\n".join(label.get("name","") for label in json.load(sys.stdin)))')
| python3 -c 'import json,sys; print("\n".join(label.get("name","") for label in json.load(sys.stdin)))') || {
# Labels API unavailable: fail open so the E2E gate runs rather
# than silently no-oping a potentially-breaking PR.
rm -f "$authfile"
echo "canvas=true" >> "$GITHUB_OUTPUT"
echo "debug=labels-api-unavailable pr=${{ github.event.pull_request.number }} base=$BASE changed=$CHANGED_FLAT" >> "$GITHUB_OUTPUT"
exit 0
}
rm -f "$authfile"
LABELS_FLAT=$(echo "$labels" | tr '\n' ',')
if printf '%s\n' "$labels" | grep -qx "$QUEUE_LABEL"; then
echo "canvas=true" >> "$GITHUB_OUTPUT"
echo "debug=merge-queue-labeled base=$BASE changed=$CHANGED_FLAT" >> "$GITHUB_OUTPUT"
else
echo "PR is not in merge-queue; skipping heavy E2E Staging Canvas for normal PR path."
echo "canvas=false" >> "$GITHUB_OUTPUT"
echo "debug=no-merge-queue-label base=$BASE changed=$CHANGED_FLAT labels=$LABELS_FLAT" >> "$GITHUB_OUTPUT"
fi
# ONE job (no job-level `if:`) that always runs and reports under the
@@ -184,6 +201,7 @@ jobs:
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)."
echo "::notice::detect-changes debug: ${{ needs.detect-changes.outputs.debug }}"
- if: needs.detect-changes.outputs.canvas == 'true'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
@@ -93,6 +93,7 @@ jobs:
continue-on-error: false
outputs:
handlers: ${{ steps.filter.outputs.handlers }}
debug: ${{ steps.filter.outputs.debug }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
@@ -102,13 +103,25 @@ jobs:
# not present in the shallow checkout.
fetch-depth: 2
- id: filter
env:
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
PUSH_BEFORE: ${{ github.event.before }}
run: |
BASE_SHA="${PR_BASE_SHA:-$PUSH_BEFORE}"
python3 .gitea/scripts/detect-changes.py \
--profile handlers-postgres \
--event-name "${{ github.event_name }}" \
--pr-base-sha "${{ github.event.pull_request.base.sha }}" \
--base-ref "${{ github.event.pull_request.base.ref }}" \
--push-before "${GITHUB_EVENT_BEFORE:-}"
--pr-base-sha "$PR_BASE_SHA" \
--base-ref "$PR_BASE_REF" \
--push-before "${GITHUB_EVENT_BEFORE:-}" || {
# Script crash / uncaught error: fail open so the integration gate
# runs rather than silently no-oping a potentially-breaking PR.
echo "handlers=true" >> "$GITHUB_OUTPUT"
echo "debug=detect-script-error event=${{ github.event_name }} base=$BASE_SHA" >> "$GITHUB_OUTPUT"
exit 0
}
echo "debug=profile=handlers-postgres event=${{ github.event_name }} base=$BASE_SHA" >> "$GITHUB_OUTPUT"
# ONE job (no job-level `if:`) that always runs and reports under the
# required-check name `Handlers Postgres Integration`. Real work is gated
@@ -148,6 +161,7 @@ jobs:
run: |
echo "No handlers/migrations changes — Handlers Postgres Integration gate satisfied without running tests."
echo "::notice::Handlers Postgres Integration no-op pass (paths filter excluded this commit)."
echo "::notice::detect-changes debug: ${{ needs.detect-changes.outputs.debug }}"
- if: needs.detect-changes.outputs.handlers == 'true'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+5 -2
View File
@@ -74,6 +74,7 @@ jobs:
continue-on-error: true
outputs:
run: ${{ steps.decide.outputs.run }}
debug: ${{ steps.decide.outputs.debug }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
@@ -120,12 +121,13 @@ jobs:
| bash .gitea/scripts/push-commits-diff-files.py \
> .push-diff-files.txt 2>/dev/null || true
DIFF_FILES=$(cat .push-diff-files.txt 2>/dev/null || true)
DIFF_FILES_FLAT=$(echo "$DIFF_FILES" | tr '\n' ',')
if [ -n "$DIFF_FILES" ] && echo "$DIFF_FILES" | grep -qE '^workspace-server/|^canvas/|^tests/harness/|^.gitea/workflows/harness-replays\.yml$'; then
echo "run=true" >> "$GITHUB_OUTPUT"
else
echo "run=false" >> "$GITHUB_OUTPUT"
fi
echo "debug=push-files=$DIFF_FILES" >> "$GITHUB_OUTPUT"
echo "debug=push-files=$DIFF_FILES_FLAT" >> "$GITHUB_OUTPUT"
exit 0
else
# New branch or github.event.before unavailable — run everything.
@@ -148,8 +150,9 @@ jobs:
exit 0
}
DIFF_FILES=$(echo "$RESP" | bash .gitea/scripts/compare-api-diff-files.py 2>/dev/null || true)
DIFF_FILES_FLAT=$(echo "$DIFF_FILES" | tr '\n' ',')
echo "debug=diff-base=$BASE diff-files=$DIFF_FILES" >> "$GITHUB_OUTPUT"
echo "debug=diff-base=$BASE diff-files=$DIFF_FILES_FLAT" >> "$GITHUB_OUTPUT"
if echo "$DIFF_FILES" | grep -qE '^workspace-server/|^canvas/|^tests/harness/|^.gitea/workflows/harness-replays\.yml$'; then
echo "run=true" >> "$GITHUB_OUTPUT"