From 249695114e96b9caa0bf398cfb5f7b3565383e04 Mon Sep 17 00:00:00 2001 From: Joe Esquibel Date: Fri, 28 Aug 2026 15:02:12 -0400 Subject: [PATCH] ci: stop the docs-auto-update treadmill from exhausting free CI budgets main takes ~40 pushes/day and ~70% of them are `docs: auto-update` bot commits (~21/day from the LLM brief alone -- it embeds a timestamp so it always diffs, and its PR auto-merges, which is itself another push). Two mirrors of the same full-precision galaxyscope run fired on every one of those pushes: - gitgalaxy.yml's `full-report` job (SARIF/SBOM/LLM brief). Moved from per-push to a daily schedule + workflow_dispatch. The brief is an orientation doc and the SARIF feed is a dashboard -- daily is plenty. The real per-PR malware gate is the unchanged PRE-GATE jobs. - azure-pipelines.yml. main pushes there ~40x/day exhausted the Azure DevOps org's free Microsoft-hosted minute grant, so every run failed with "no free minutes remaining" -- a permanent red X on every main commit. Now triggers on `v*` tags + a weekly heartbeat only (~5 runs/month), keeping it as a "still green on Azure" reference. Also shallow-checkout (the audit reads the working tree, not history). Follow-ups: make the LLM brief itself stable (drop the volatile timestamp/duration/commit lines) so most scheduled runs are no-ops; and on the Azure side, disable the pipeline or request the free-parallelism grant to green the historical commits. Co-Authored-By: Claude Sonnet 5 --- .github/workflows/gitgalaxy.yml | 51 +++++++++++++++++---------------- azure-pipelines.yml | 41 +++++++++++++++++--------- 2 files changed, 55 insertions(+), 37 deletions(-) diff --git a/.github/workflows/gitgalaxy.yml b/.github/workflows/gitgalaxy.yml index ee7e1b6dd..8f9afe01a 100644 --- a/.github/workflows/gitgalaxy.yml +++ b/.github/workflows/gitgalaxy.yml @@ -4,14 +4,19 @@ on: pull_request: branches: [main] paths-ignore: ["docs/**"] - push: - branches: [main] - # Manual re-fire for the post-gate (SARIF/SBOM/LLM brief) without needing a - # new commit -- added after push-to-main events silently stopped creating - # runs for ~4.5h on 2026-08-06 (GitHub recorded the PushEvents; no run was - # ever created for this workflow or muninn.yml). Root cause unconfirmed - # (suspected Actions run-creation throttling from this repo's push volume, - # see the LLM-brief auto-merge loop below); this is the recovery lever. + # The post-gate (SARIF / SBOM / LLM brief) used to run on every push to main. + # With the docs-auto-update bots merging ~40x/day (see the LLM-brief loop + # below), that meant ~40 full-precision galaxyscope runs/day here AND ~40 + # runs/day on the mirrored azure-pipelines.yml / bitbucket-pipelines.yml, + # which instantly exhausts their free hosted-CI minute grants. The brief is + # an orientation doc and the SARIF feed is a dashboard -- neither needs to be + # fresher than daily. So the post-gate now runs on a schedule instead. + schedule: + - cron: "17 5 * * *" # daily, 05:17 UTC + # Manual re-fire for the post-gate without waiting for the schedule -- also + # the recovery lever from 2026-08-06, when push-to-main events silently + # stopped creating runs for ~4.5h (suspected Actions run-creation throttling + # from this repo's push volume, the same volume this schedule change cuts). workflow_dispatch: permissions: @@ -65,25 +70,23 @@ jobs: version: local # ============================================================ - # POST-GATE — runs only once code is on main (merge or direct - # push). One galaxyscope pass produces all 6 outputs; we route - # 3 of them and let the rest live only in the ephemeral runner. - # --fail-on-malware stays on here too, as a safety net in case - # branch protection is ever bypassed. + # POST-GATE — one galaxyscope pass produces all 6 outputs; we route 3 of + # them (SARIF -> Security tab, SBOM + self-scan DB -> artifacts, LLM brief + # -> committed doc) and let the rest live only in the ephemeral runner. + # --fail-on-malware stays on here too, as a safety net in case branch + # protection is ever bypassed. # - # The LLM brief embeds a Timestamp/Scan Duration/Git Commit in its own - # content (llm_recorder.py), so it always differs from the last commit - # even with zero real code changes -- and merging the bot's own PR is - # itself a push to main. Without the second half of this condition, that - # is a genuine infinite loop: this confirmed live on 2026-07-25, landing - # 13 junk commits in ~13 minutes before being caught and disabled. Skip - # regenerating when the triggering push IS the bot's own previous merge. + # Runs on a daily schedule (or manual dispatch), NOT per-push: the LLM brief + # embeds a Timestamp/Scan Duration/Git Commit (llm_recorder.py) so it always + # produces a diff, its PR auto-merges, and that merge is itself a push -- + # a per-push trigger made this a treadmill (~21 brief commits/day; a + # confirmed 13-commits-in-13-minutes runaway on 2026-07-25) that also + # exhausted the mirrored Azure/Bitbucket free CI minutes. A daily brief is + # plenty for an orientation doc, and a daily SARIF refresh is plenty for a + # dashboard. The real per-PR malware gate is the PRE-GATE jobs above. # ============================================================ full-report: - if: | - (github.event_name == 'push' && - !startsWith(github.event.head_commit.message, 'docs: auto-update LLM architectural brief')) || - github.event_name == 'workflow_dispatch' + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' name: Full Report (SARIF, SBOM, LLM Brief) runs-on: ubuntu-latest permissions: diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 25ce7f2f9..ef3698ccc 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,21 +1,35 @@ # GitGalaxy Enterprise Security Scanner # Integration: Azure DevOps Pipelines +# Triggers on release tags + a weekly heartbeat only -- NOT on every push to +# main. main takes ~40 pushes/day (the docs-auto-update bots in +# gitgalaxy.yml), and one full-precision galaxyscope run per push instantly +# exhausts this Azure DevOps org's free Microsoft-hosted minute grant, leaving +# every run failing with "no free minutes remaining" -- a permanent red X on +# every main commit for a scan GitHub Actions' gitgalaxy.yml already does for +# free. Tag + weekly keeps this pipeline alive as a "still green on Azure" +# reference for people who find the project via Azure, at ~5 runs/month. +# +# To fully green the historical commits, also disable/delete this pipeline in +# Azure DevOps (Pipelines -> squid-protocol.gitgalaxy -> Settings) or request +# the free-parallelism grant at https://aka.ms/azpipelines-parallelism-request +# for the (public) project. trigger: - branches: - include: - - main tags: include: - v* -# No `pr:` trigger on purpose: this pipeline previously ran on every GitHub PR -# via the Azure Pipelines GitHub App's default PR-validation behavior (which -# fires whenever `pr:` is unset), burning the org's Microsoft-hosted free -# minutes across every PR in addition to `trigger:`'s push/tag runs. It's -# also redundant -- GitHub Actions' gitgalaxy.yml already runs the same -# --fail-on-malware scan on every PR for free. `pr: none` restricts this -# pipeline to `trigger:`'s push-to-main/tag-push cases only. +schedules: + - cron: "0 6 * * 1" # Mondays 06:00 UTC + displayName: Weekly backup heartbeat scan + branches: + include: + - main + always: true + +# `pr: none`: no PR-validation runs. Redundant with gitgalaxy.yml's per-PR +# --fail-on-malware gate, and it used to fire on every GitHub PR via the Azure +# Pipelines GitHub App's default behavior when `pr:` is unset. pr: none variables: @@ -52,10 +66,11 @@ stages: pip install "gitgalaxy[yaml]" networkx tiktoken xgboost pandas numpy displayName: 'Install GitGalaxy & Heavy Physics Engines' - # 2. NOW pull the potentially untrusted code onto the runner + # 2. NOW pull the potentially untrusted code onto the runner. Shallow: the + # spectral audit reads the working tree, not git history. - checkout: self - fetchDepth: 0 - displayName: 'Checkout Repository (Full Depth)' + fetchDepth: 1 + displayName: 'Checkout Repository' # 3. Execute the scan (No package managers allowed down here) - script: |