mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-27 06:53:11 +08:00
The gate waited 90 x 30s = 45 min for CodeQL to finish on the PR head. That
is shorter than CodeQL actually takes on this repository, so the gate has
been failing runs that had not failed.
Measured on PR #1426, head 7b72652a: the CodeQL SAST workflow completed with
conclusion=success at 17:46:05, having started at 15:41:44 -- 124 minutes.
The gate step ran 16:52:58 to 17:38:44 and reported "BLOCKED: CodeQL timeout"
7 minutes and 21 seconds before the scan it was waiting for succeeded.
Two open contributor pull requests are red from exactly this: #1426 and
#1769, both with CodeQL completed=success on their head and every other
check green.
Three further PRs (#1703, #1741, #1742) are also red on codeql-gate alone,
but from a different cause: the CodeQL run on their head is
completed=cancelled, so the gate saw a non-success conclusion and correctly
exited 1 without waiting. This change does not help those and is not
intended to; they need a fresh scan, most likely having been superseded by
concurrency cancel-in-progress in codeql.yml.
300 x 30s = 150 min covers the measured 124 min with margin. The job already
declares timeout-minutes: 240, so the wait still cannot outlive its own job.
No trigger, permission or gating change: codeql-gate blocks exactly what it
blocked before, and a genuine CodeQL failure still exits 1 immediately rather
than waiting out the budget. Only the absence of a verdict waits longer.
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
93 lines
4.1 KiB
YAML
93 lines
4.1 KiB
YAML
# Reusable: security-static + CodeQL gate.
|
|
# Runs independently from lint/test/build — does not block the main pipeline.
|
|
# Affects overall workflow success status.
|
|
name: Security Gate
|
|
|
|
on:
|
|
workflow_call: {}
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
security-static:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 5
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
- name: "Layer 1: Static allow-list audit"
|
|
run: scripts/security-audit.sh
|
|
- name: "Layer 6: UI security audit"
|
|
run: scripts/security-ui.sh
|
|
- name: "Layer 8: Vendored dependency integrity"
|
|
run: scripts/security-vendored.sh
|
|
|
|
license-gate:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 240
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
- name: Install ScanCode Toolkit
|
|
run: pipx install scancode-toolkit
|
|
- name: "Gate self-test (a planted violation must be detected)"
|
|
run: scripts/license-gate.sh --selftest
|
|
- name: "License compliance gate (one finding fails)"
|
|
run: scripts/license-gate.sh
|
|
- name: "License provenance audit (byte-identity vs upstream)"
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: scripts/audit-license-provenance.py
|
|
|
|
codeql-gate:
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 240
|
|
steps:
|
|
- name: Wait for CodeQL on current commit (max 150 min)
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
# On pull_request events github.sha is the synthetic merge commit;
|
|
# CodeQL runs are recorded against the PR head SHA.
|
|
CURRENT_SHA="${{ github.event.pull_request.head.sha || github.sha }}"
|
|
echo "Waiting for CodeQL to complete on $CURRENT_SHA..."
|
|
# 300 attempts x 30s = 150 min. The previous budget was 90 x 30s = 45 min,
|
|
# which is shorter than CodeQL actually takes on this repository: a measured
|
|
# run on PR #1426 (head 7b72652a) completed with conclusion=success after
|
|
# 124 min, 7 minutes AFTER this gate had already given up. That marked at
|
|
# least five contributor PRs red for a scan that passed. The job's own
|
|
# timeout-minutes is 240, so 150 still leaves headroom.
|
|
for attempt in $(seq 1 300); do
|
|
LATEST=$(gh api "repos/${{ github.repository }}/actions/workflows/codeql.yml/runs?head_sha=$CURRENT_SHA&per_page=1" \
|
|
--jq '.workflow_runs[] | "\(.conclusion) \(.status)"' 2>/dev/null | head -1 || echo "")
|
|
if [ -z "$LATEST" ]; then
|
|
echo " $attempt/300: no run yet..."; sleep 30; continue
|
|
fi
|
|
CONCLUSION=$(echo "$LATEST" | cut -d' ' -f1)
|
|
STATUS=$(echo "$LATEST" | cut -d' ' -f2)
|
|
if [ "$STATUS" = "completed" ] && [ "$CONCLUSION" = "success" ]; then
|
|
echo "=== CodeQL passed ==="; exit 0
|
|
elif [ "$STATUS" = "completed" ]; then
|
|
echo "BLOCKED: CodeQL $CONCLUSION"; exit 1
|
|
fi
|
|
echo " $attempt/300: $STATUS..."; sleep 30
|
|
done
|
|
echo "BLOCKED: CodeQL timeout"; exit 1
|
|
|
|
- name: Check for open code scanning alerts
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
echo "Waiting 60s for alert API to settle..."
|
|
sleep 60
|
|
ALERTS=$(gh api 'repos/${{ github.repository }}/code-scanning/alerts?state=open' --jq 'length' 2>/dev/null || echo "0")
|
|
sleep 15
|
|
ALERTS2=$(gh api 'repos/${{ github.repository }}/code-scanning/alerts?state=open' --jq 'length' 2>/dev/null || echo "0")
|
|
[ "$ALERTS" -lt "$ALERTS2" ] && ALERTS=$ALERTS2
|
|
if [ "$ALERTS" -gt 0 ]; then
|
|
echo "BLOCKED: $ALERTS open alert(s)"
|
|
gh api 'repos/${{ github.repository }}/code-scanning/alerts?state=open' \
|
|
--jq '.[] | " #\(.number) [\(.rule.security_severity_level // .rule.severity)] \(.rule.id) — \(.most_recent_instance.location.path):\(.most_recent_instance.location.start_line)"' 2>/dev/null || true
|
|
exit 1
|
|
fi
|
|
echo "=== CodeQL gate passed (0 alerts) ==="
|