mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-14 02:42:24 +03:00
The hosted 7 GB runner cannot build release/v3.8.51 in any profile: `Build App` (build.yml, push on every branch, full `build:release`) died in 19 of the last 30 runs — the branch tip included — with "The runner has received a shutdown signal" ~8 min into `next build`, swapfile and all; the advisory quality.yml build failed on 8/8 recent fork PRs with the same recipe; and `DAST smoke (PR)`'s backend-only build died ~7 min in before the server even started, hidden as a permanently red continue-on-error check. Together they painted every PR into release/** red with zero signal and, on build.yml, produced an artefact nothing downloads. - build.yml: workflow_dispatch only. The bundle is validated where a build fits — ci.yml `Build` on the self-hosted omni-build pool after every merge to main, and nightly-release-green.yml on the same pool for release/**. - dast-smoke.yml: pull_request into main only (plus workflow_dispatch to smoke a release branch by hand); main's tree still builds on the hosted runner in ~5.5 min. - quality.yml: the fork-only rationale of `Build (advisory)` updated to say why own-origin PRs no longer get a hosted build either. Behaviour unchanged. check:workflows --ratchet: 194 zizmor findings, baseline 194. check-workflows and backend-only-smoke-workflows suites pass. Trade-off stated in the PR: own-origin PRs into release/** lose a pre-merge build that was not succeeding anyway; the nightly rail files a base-red issue within a day if a merge breaks the build.
99 lines
4.5 KiB
YAML
99 lines
4.5 KiB
YAML
name: DAST smoke (PR)
|
|
# PRs into main only since #11946. The job's "Build CLI bundle" step is a backend-only
|
|
# `next build`; on the hosted 7 GB runner it fits main's tree (~5.5 min) but dies on
|
|
# release/v3.8.51 (VM shutdown ~7 min in, before the server even starts), and because the
|
|
# job is continue-on-error the result was a permanently red advisory check on every
|
|
# release PR — noise, not signal. DAST coverage for release/** lives on the nightly rail
|
|
# (nightly-schemathesis.yml, nightly-llm-security.yml); dispatch this workflow by hand
|
|
# to smoke a release branch on demand.
|
|
on:
|
|
workflow_dispatch:
|
|
pull_request:
|
|
branches: ["main"]
|
|
# Runner-cost guard (#8084): the CLI-bundle build alone is 6-11min; a docs-only PR
|
|
# cannot change DAST behavior, so skip the whole workflow for pure docs/markdown
|
|
# changes. Any code path in the diff still runs the full smoke.
|
|
paths-ignore:
|
|
- "docs/**"
|
|
- "**/*.md"
|
|
permissions:
|
|
contents: read
|
|
|
|
# Superseded runs on the same PR must not stack 25-minute advisory builds
|
|
# (force-push storms were holding 2-3 runners each). Same group rule as quality.yml.
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref }}
|
|
cancel-in-progress: true
|
|
jobs:
|
|
dast-smoke:
|
|
runs-on: ubuntu-latest
|
|
# ADVISORY while this new gate matures (repo convention: advisory -> blocking).
|
|
# Flip to blocking (remove continue-on-error) once it's proven stable across a few PRs.
|
|
continue-on-error: true
|
|
# Build CLI bundle alone varies 6-11min on GitHub-hosted runners (3 consecutive
|
|
# timeouts observed on 2026-07-14 with the old 12min cap killing schemathesis
|
|
# mid-run) — 25min leaves real headroom for the actual DAST steps.
|
|
timeout-minutes: 25
|
|
env:
|
|
JWT_SECRET: ci-build-secret-with-sufficient-length-for-validation
|
|
API_KEY_SECRET: ci-api-key-secret-with-sufficient-length-aaaa
|
|
steps:
|
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
with:
|
|
persist-credentials: false
|
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
|
with:
|
|
node-version: "24"
|
|
cache: npm
|
|
- uses: ./.github/actions/npm-ci-retry
|
|
- name: Build CLI bundle
|
|
env:
|
|
OMNIROUTE_BUILD_BACKEND_ONLY: "1"
|
|
run: npm run build:cli
|
|
- name: Start OmniRoute
|
|
env:
|
|
PORT: "20128"
|
|
INJECTION_GUARD_MODE: block
|
|
REQUIRE_API_KEY: "false"
|
|
run: |
|
|
node dist/server.js > server.log 2>&1 &
|
|
echo $! > server.pid
|
|
for _ in $(seq 1 30); do
|
|
if curl -sf http://localhost:20128/api/monitoring/health >/dev/null; then echo up; break; fi
|
|
sleep 2
|
|
done
|
|
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
with:
|
|
python-version: "3.12"
|
|
- run: pip install schemathesis
|
|
- name: Schemathesis smoke (high-risk endpoints, blocking)
|
|
run: |
|
|
# /api/auth/oidc/* is a BROWSER redirect flow (302 to the IdP, 302 back to
|
|
# /login?oidc_error=... on every failure), not a REST endpoint: Schemathesis reads
|
|
# those 302s as "the API accepted a schema-violating request" and the configured-off
|
|
# 400 as "rejected a schema-compliant request". Documenting the flow in the spec is
|
|
# still right (operators need it); fuzzing it is not what this smoke is for.
|
|
# /api/auth/login has brute-force rate limiting: repeated failed logins return 429,
|
|
# which Schemathesis flags as rejection of schema-compliant requests.
|
|
schemathesis run docs/openapi.yaml --url http://localhost:20128 \
|
|
--include-path-regex '^/v1/(chat/completions|models)$|^/api/(auth|keys)' \
|
|
--exclude-path-regex '^/api/auth/(oidc/|login)' \
|
|
--max-examples 8 --workers 4 --checks all --max-response-time 30 \
|
|
--request-timeout 20 --suppress-health-check all --no-color
|
|
- name: Install promptfoo
|
|
run: npm install -g promptfoo@0.122.0
|
|
- name: promptfoo injection-guard (blocking)
|
|
env:
|
|
OMNIROUTE_URL: http://localhost:20128
|
|
OMNIROUTE_API_KEY: not-needed-blocked-before-upstream
|
|
run: promptfoo eval -c promptfooconfig.yaml --no-cache
|
|
- name: Stop server
|
|
if: always()
|
|
run: kill "$(cat server.pid)" || true
|
|
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
if: always()
|
|
with:
|
|
name: dast-smoke-logs
|
|
path: server.log
|
|
retention-days: 7
|