ci: limit final memory repair to requested regressions #74
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Port memory successor | ||
| on: | ||
| pull_request: | ||
| types: [opened, synchronize, reopened] | ||
| permissions: | ||
| contents: write | ||
| jobs: | ||
| port: | ||
| if: github.event.pull_request.head.repo.full_name == github.repository && github.event.pull_request.head.ref == 'feat/memory-guard-observability-dev' | ||
| runs-on: ubuntu-22.04 | ||
| timeout-minutes: 45 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| ref: feat/memory-guard-observability-dev | ||
| fetch-depth: 0 | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
| - name: Check one-shot trigger | ||
| id: gate | ||
| shell: bash | ||
| run: | | ||
| if [ -f .github/trigger/memory-final-review ]; then | ||
| echo "run=true" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "run=false" >> "$GITHUB_OUTPUT" | ||
| fi | ||
| - uses: oven-sh/setup-bun@v2 | ||
| if: steps.gate.outputs.run == 'true' | ||
| with: | ||
| bun-version: '1.3.14' | ||
| - name: Add direct Windows accounting regressions | ||
| if: steps.gate.outputs.run == 'true' | ||
| shell: bash | ||
| run: | | ||
| python3 - <<'PY' | ||
| from pathlib import Path | ||
| path = Path('packages/coding-agent/test/tools/resource-gc-redteam.test.ts') | ||
| text = path.read_text() | ||
| settings_import = 'import { Settings } from "../../src/config/settings";\n' | ||
| limit_import = 'import { resolveEffectiveMemoryLimit } from "../../src/runtime/memory-limit";\n' | ||
| if limit_import not in text: | ||
| if settings_import not in text: | ||
| raise SystemExit('settings import anchor missing') | ||
| text = text.replace(settings_import, settings_import + limit_import, 1) | ||
| import_anchor = '\t__resetResourceGcForTest,\n' | ||
| seam = '\t__sampleWindowsJobMemoryForTest,\n\t__selectMemoryPressureDomainForTest,\n' | ||
| if '__sampleWindowsJobMemoryForTest' not in text: | ||
| if import_anchor not in text: | ||
| raise SystemExit('resource-gc import anchor missing') | ||
| text = text.replace(import_anchor, import_anchor + seam, 1) | ||
| marker = '\tit("never evicts ownerless tabs under RSS pressure and warns once", async () => {' | ||
| tests = r'''\tit("keeps uncapped Windows Job commit charge separate from physical RAM", () => { | ||
| \t\tconst gib = 1024 ** 3; | ||
| \t\tconst hostBytes = 16 * gib; | ||
| \t\tconst parentBytes = 2 * gib; | ||
| \t\tconst snapshot = __sampleWindowsJobMemoryForTest(hostBytes, parentBytes, { | ||
| \t\t\tkind: "job_snapshot", | ||
| \t\t\tplatform: "win32", | ||
| \t\t\tisInJob: true, | ||
| \t\t\tjobMemoryUsedBytes: String(20 * gib), | ||
| \t\t\tpeakJobMemoryUsedBytes: String(21 * gib), | ||
| \t\t\tprocessPrivateUsageBytes: String(20 * gib), | ||
| \t\t\tprocessWorkingSetBytes: String(parentBytes), | ||
| \t\t\tpeakProcessWorkingSetBytes: String(3 * gib), | ||
| \t\t}); | ||
| \t\texpect(snapshot).not.toBeNull(); | ||
| \t\texpect(snapshot?.parentBytes).toBe(parentBytes); | ||
| \t\texpect(snapshot?.domains).toContainEqual({ | ||
| \t\t\thardCapBytes: Number.MAX_SAFE_INTEGER, | ||
| \t\t\ttotalUsageBytes: 20 * gib, | ||
| \t\t\tsource: "windows_job", | ||
| \t\t}); | ||
| \t\texpect(snapshot?.domains).toContainEqual({ | ||
| \t\t\thardCapBytes: hostBytes, | ||
| \t\t\ttotalUsageBytes: parentBytes, | ||
| \t\t\tsource: "windows_process_job_limit", | ||
| \t\t}); | ||
| \t}); | ||
| \tit("does not clamp a Windows commit-domain policy cap to physical RAM", () => { | ||
| \t\tconst gib = 1024 ** 3; | ||
| \t\tconst hostBytes = 16 * gib; | ||
| \t\tconst policyLimitBytes = 24 * gib; | ||
| \t\tconst snapshot = __sampleWindowsJobMemoryForTest(hostBytes, 2 * gib, { | ||
| \t\t\tkind: "job_snapshot", | ||
| \t\t\tplatform: "win32", | ||
| \t\t\tisInJob: true, | ||
| \t\t\tjobMemoryUsedBytes: String(20 * gib), | ||
| \t\t\tpeakJobMemoryUsedBytes: String(21 * gib), | ||
| \t\t\tprocessPrivateUsageBytes: String(20 * gib), | ||
| \t\t\tprocessWorkingSetBytes: String(2 * gib), | ||
| \t\t\tpeakProcessWorkingSetBytes: String(3 * gib), | ||
| \t\t}); | ||
| \t\texpect(snapshot).not.toBeNull(); | ||
| \t\tconst pressure = __selectMemoryPressureDomainForTest(snapshot!, policyLimitBytes); | ||
| \t\tconst limit = resolveEffectiveMemoryLimit({ | ||
| \t\t\thardCapBytes: pressure.hardCapBytes, | ||
| \t\t\tpolicyLimitBytes, | ||
| \t\t}); | ||
| \t\texpect(pressure.source).toBe("windows_job"); | ||
| \t\texpect(limit.effectiveBytes).toBe(policyLimitBytes); | ||
| \t\texpect(limit.effectiveBytes).toBeGreaterThan(hostBytes); | ||
| \t\tconst usageRatio = pressure.totalUsageBytes / limit.effectiveBytes!; | ||
| \t\texpect(usageRatio).toBeCloseTo(20 / 24, 8); | ||
| \t\texpect(usageRatio).toBeLessThan(1); | ||
| \t}); | ||
| ''' | ||
| if 'keeps uncapped Windows Job commit charge separate from physical RAM' not in text: | ||
| if text.count(marker) != 1: | ||
| raise SystemExit('test insertion anchor missing') | ||
| text = text.replace(marker, tests + marker, 1) | ||
| path.write_text(text) | ||
| PY | ||
| - name: Restore generated native declarations | ||
| if: steps.gate.outputs.run == 'true' | ||
| run: | | ||
| bun packages/natives/scripts/gen-enums.ts | ||
| cp packages/natives/native/index.d.ts /tmp/index.generated.d.ts | ||
| cp packages/natives/native/index.js /tmp/index.generated.js | ||
| bun packages/natives/scripts/gen-enums.ts | ||
| cmp /tmp/index.generated.d.ts packages/natives/native/index.d.ts | ||
| cmp /tmp/index.generated.js packages/natives/native/index.js | ||
| grep -F "macOS computer-use controller." packages/natives/native/index.d.ts | ||
| - name: Install, format, and verify | ||
| if: steps.gate.outputs.run == 'true' | ||
| run: | | ||
| bun install --frozen-lockfile | ||
| bunx biome check --write packages/coding-agent/test/tools/resource-gc-redteam.test.ts | ||
| bun test --timeout 30000 \ | ||
| packages/coding-agent/test/runtime/memory-limit.test.ts \ | ||
| packages/coding-agent/test/runtime/memory-domain.test.ts \ | ||
| packages/coding-agent/test/runtime/memory-guard.test.ts \ | ||
| packages/coding-agent/test/tools/resource-gc.test.ts \ | ||
| packages/coding-agent/test/tools/resource-gc-redteam.test.ts \ | ||
| packages/coding-agent/test/gjc-runtime/linux-proc.test.ts \ | ||
| packages/coding-agent/test/cli-memory-guard-native-smoke.test.ts \ | ||
| packages/natives/test/memory-guard-native.test.ts \ | ||
| packages/natives/test/memory-guard-build-wiring.test.ts | ||
| bun --cwd=packages/coding-agent run check | ||
| bun --cwd=packages/natives run check | ||
| - name: Publish verified clean successor | ||
| if: steps.gate.outputs.run == 'true' | ||
| shell: bash | ||
| run: | | ||
| git config user.name 'twoimo' | ||
| git config user.email '32544727+twoimo@users.noreply.github.com' | ||
| git fetch --no-tags upstream dev || { | ||
| git remote add upstream https://github.com/Yeachan-Heo/gajae-code.git || true | ||
| git fetch --no-tags upstream dev | ||
| } | ||
| git reset --soft upstream/dev | ||
| rm -f .github/workflows/memory-final-self-repair.yml .github/trigger/memory-final-review | ||
| git add -A | ||
| git commit -m 'feat(coding-agent): add cross-platform memory pressure observability' | ||
| git push --force origin HEAD:feat/memory-guard-observability-dev | ||