mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-10 03:27:59 +00:00
fix(ci): gate evolution runs on runner readiness (#2785)
Prevent paid scheduled work until host survival protections and the proven three-worker rollout are explicitly in place. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
990a3b680a
commit
b7e621df4c
2 changed files with 42 additions and 9 deletions
33
.github/workflows/gitnexus-skill-evolution.yml
vendored
33
.github/workflows/gitnexus-skill-evolution.yml
vendored
|
|
@ -41,7 +41,8 @@
|
|||
# most weekly. Revisit if run frequency increases or the threat model
|
||||
# changes; stopping already bounds the exposure window to the job's own
|
||||
# runtime on 1 day out of 7.
|
||||
# [ ] Stop the runner box from restarting services under a running job. A run
|
||||
# [ ] Install and verify the runner survival policy below before enabling
|
||||
# scheduled runs. A run
|
||||
# spans ~15h and apt-daily-upgrade.timer fires daily (~06:34), so every
|
||||
# scheduled run crosses it. On 2026-08-02 unattended-upgrades upgraded
|
||||
# openssl at 07:54:02 and needrestart restarted the Actions runner five
|
||||
|
|
@ -58,14 +59,13 @@
|
|||
# uploads, and a promotion (if any) opens a well-formed PR. Run
|
||||
# 29907431284 (2026-07-22) went green end to end in 14h45m and reached a
|
||||
# gate decision (`insufficient_evidence`, no promotion).
|
||||
# [x] Set the repository variable GITNEXUS_EVOLUTION_ENABLED=true. Roll back
|
||||
# the scheduled lane by setting it to false. workflow_dispatch always runs
|
||||
# the full benchmark loop regardless and bills real API usage on
|
||||
# GITNEXUS_BENCH_AUTH_TOKEN.
|
||||
# [ ] After resizing the runner, prove a manual workers=3 run has zero excluded
|
||||
# runs and does not stretch the 48-minute serial mean toward the session
|
||||
# ceiling; then set GITNEXUS_EVOLUTION_WORKERS=3 for scheduled runs. Leave
|
||||
# it unset or set it to 1 for the serial fallback and immediate rollback.
|
||||
# ceiling; then set GITNEXUS_EVOLUTION_WORKERS=3 and
|
||||
# GITNEXUS_EVOLUTION_ENABLED=true for scheduled runs. Scheduled runs
|
||||
# require both values, so leaving workers unset/1 is an immediate rollback;
|
||||
# workflow_dispatch remains available for the proof and bills real API
|
||||
# usage on GITNEXUS_BENCH_AUTH_TOKEN.
|
||||
name: GitNexus skill evolution
|
||||
|
||||
on:
|
||||
|
|
@ -121,7 +121,10 @@ jobs:
|
|||
github.repository == 'abhigyanpatwari/GitNexus' &&
|
||||
(
|
||||
github.event_name == 'workflow_dispatch' ||
|
||||
vars.GITNEXUS_EVOLUTION_ENABLED == 'true'
|
||||
(
|
||||
vars.GITNEXUS_EVOLUTION_ENABLED == 'true' &&
|
||||
vars.GITNEXUS_EVOLUTION_WORKERS == '3'
|
||||
)
|
||||
)
|
||||
runs-on: [self-hosted, linux, x64, gitnexus-evolution]
|
||||
# Gate promotion runs on a protected Environment. An admin must attach a
|
||||
|
|
@ -164,6 +167,20 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
|
||||
- name: Verify runner survival policy
|
||||
run: |
|
||||
set -euo pipefail
|
||||
needrestart_policy=/etc/needrestart/conf.d/90-gitnexus-evolution.conf
|
||||
if [[ ! -r "${needrestart_policy}" ]] || ! grep -Fqx '$nrconf{restart} = '\''l'\'';' "${needrestart_policy}"; then
|
||||
echo "::error::${needrestart_policy} must contain: \$nrconf{restart} = 'l';"
|
||||
exit 1
|
||||
fi
|
||||
oom_score_adjustment="$(</proc/self/oom_score_adj)"
|
||||
if (( oom_score_adjustment > -900 )); then
|
||||
echo "::error::Runner.Worker descendants require OOMScoreAdjust=-900 or stronger; effective value is ${oom_score_adjustment}."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ const workflowDocument = load(workflow) as {
|
|||
{
|
||||
environment?: unknown;
|
||||
env?: Record<string, string>;
|
||||
if?: unknown;
|
||||
'timeout-minutes'?: unknown;
|
||||
steps?: Array<{
|
||||
name?: string;
|
||||
|
|
@ -407,6 +408,21 @@ exit 1`);
|
|||
expect(mint?.with).not.toHaveProperty('app-id');
|
||||
});
|
||||
|
||||
it('keeps scheduled runs off until the three-worker proof is explicitly enabled', () => {
|
||||
const condition = String(evolveJob?.if);
|
||||
expect(condition).toContain("github.event_name == 'workflow_dispatch'");
|
||||
expect(condition).toContain("vars.GITNEXUS_EVOLUTION_ENABLED == 'true'");
|
||||
expect(condition).toContain("vars.GITNEXUS_EVOLUTION_WORKERS == '3'");
|
||||
});
|
||||
|
||||
it('fails before paid work when runner survival protections are ineffective', () => {
|
||||
const preflight = stepRun('Verify runner survival policy');
|
||||
expect(preflight).toContain('/etc/needrestart/conf.d/90-gitnexus-evolution.conf');
|
||||
expect(preflight).toContain("$nrconf{restart} = 'l';");
|
||||
expect(preflight).toContain('/proc/self/oom_score_adj');
|
||||
expect(preflight).toContain('oom_score_adjustment > -900');
|
||||
});
|
||||
|
||||
it('labels the upload-artifact pin with its real version', () => {
|
||||
expect(workflow).toContain(
|
||||
'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1',
|
||||
|
|
@ -456,7 +472,7 @@ exit 1`);
|
|||
expect(workflow).toContain('RELEASE_APP_ID');
|
||||
expect(workflow).toContain('RELEASE_APP_PRIVATE_KEY');
|
||||
expect(workflow).toContain('gitnexus-evolution');
|
||||
expect(workflow).toContain('[x] Set the repository variable GITNEXUS_EVOLUTION_ENABLED=true');
|
||||
expect(workflow).toContain('GITNEXUS_EVOLUTION_ENABLED=true for scheduled runs');
|
||||
expect(workflow).toContain('GITNEXUS_EVOLUTION_WORKERS');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue