From 54b71acbd75ddf116fc6b6d0dc132f526060ed53 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Tue, 7 Jul 2026 21:56:36 +0900 Subject: [PATCH] perf(strix): skip scans on doc/image-only diffs and cap job at 60m Runner-queue starvation across the org: every doc-only, image-only, or empty re-trigger PR/push spawned a fresh ~120-min Strix scan, blocking all PR merges behind runner contention. Two security-preserving throughput fixes: 1. paths-ignore on push and pull_request_target for changes whose ENTIRE diff is non-executable documentation/image assets (*.md, *.rst, *.markdown, raster images, LICENSE, .github/ISSUE_TEMPLATE). A code security scanner has nothing to analyze in such a diff. Conservative: no source, no *.txt, no *.svg (can embed script), no CODEOWNERS, no build/workflow files. GitHub requires EVERY changed file to match, so any code/config/build/workflow change still scans. The weekly full-tree schedule (no path filter) backstops protected branches, and the merge scheduler still forces same-head evidence via workflow_dispatch (which paths-ignore does not affect) before merging managed PRs. 2. Cap the strix job at 60m (was 120m). The scan step is already hard-bounded to 30 min (timeout-minutes: 30 + STRIX_TOTAL_TIMEOUT=1800) and all other steps are quick/self-bounded; 120 only ever bit hung runs. 60m clears the realistic worst case with margin and is fail-closed. The head.sha concurrency / cancel-in-progress security design (which deliberately does NOT cancel in-progress scans on new commits) is unchanged. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01RjGVapDZ3k7V7zKYk16P4C --- .github/workflows/strix.yml | 56 ++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/.github/workflows/strix.yml b/.github/workflows/strix.yml index 9214c44f..071927b7 100644 --- a/.github/workflows/strix.yml +++ b/.github/workflows/strix.yml @@ -3,8 +3,55 @@ name: Strix Security Scan on: push: branches: [main, develop, master] + # Skip scans for changes that touch ONLY non-executable documentation and + # image assets. A change whose entire diff is these paths has no source, + # build, config, or workflow logic for a code security scanner to analyze, + # so skipping it loses no coverage while freeing shared runner capacity. + # Conservative by design: only file EXTENSIONS/paths that can never contain + # executable logic are listed (no source, no *.txt, no *.svg, no CODEOWNERS, + # no build scripts). A diff touching even one non-listed file still scans. + # The weekly full-tree schedule below re-scans protected branches with no + # path filter, backstopping every path. + paths-ignore: + - '**/*.md' + - '**/*.markdown' + - '**/*.rst' + - '**/*.png' + - '**/*.jpg' + - '**/*.jpeg' + - '**/*.gif' + - '**/*.webp' + - '**/*.bmp' + - '**/*.ico' + - 'LICENSE' + - 'LICENSE.*' + - 'COPYING' + - '.github/ISSUE_TEMPLATE/**' pull_request_target: types: [opened, synchronize, reopened, ready_for_review, closed] + # Same conservative doc/image-only skip for PR scans. GitHub evaluates these + # path filters against the PR's full base..head diff, so a PR is skipped only + # when EVERY changed file is a non-executable doc/image asset; any code, + # config, build, or workflow change still triggers the scan. The head.sha + # concurrency design (below) is unchanged. For PRs the merge scheduler + # manages, same-head Strix evidence is still forced at merge time via + # workflow_dispatch (which paths-ignore does not affect), so merged code + # never loses evidence. + paths-ignore: + - '**/*.md' + - '**/*.markdown' + - '**/*.rst' + - '**/*.png' + - '**/*.jpg' + - '**/*.jpeg' + - '**/*.gif' + - '**/*.webp' + - '**/*.bmp' + - '**/*.ico' + - 'LICENSE' + - 'LICENSE.*' + - 'COPYING' + - '.github/ISSUE_TEMPLATE/**' schedule: # Weekly scan on protected branches (Mondays at 03:00 UTC). - cron: '0 3 * * 1' @@ -61,7 +108,14 @@ jobs: strix: if: github.event_name != 'pull_request_target' || github.event.action != 'closed' - timeout-minutes: 120 + # The scan itself is hard-bounded to 30 min (the "Run Strix (quick)" step + # has timeout-minutes: 30 and exports STRIX_TOTAL_TIMEOUT_SECONDS=1800), and + # every other step is quick or self-bounded (self-test is 2 min). A healthy + # run finishes well under 50 min. The 120 cap only ever bit HUNG runs (e.g. + # a network stall in pip/git with no per-step timeout); 60 min still clears + # the realistic worst case with margin while freeing a stuck runner in half + # the time. Fail-closed: hitting the cap fails the run, never passes it. + timeout-minutes: 60 runs-on: ubuntu-latest env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true