mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-09 18:28:15 +01:00
Stop the pre-push check flagging real files whose names start with tmp or scratch (GST-1944) (#4177)
* Stop pregate flagging real files whose names start with tmp or scratch (GST-1944) Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * Make the stray-name test safe on case-insensitive disks and record the tmp-word tradeoff Review-Finding: p1/specialist-batched#1 reader=testing Review-Finding: p1/red-team#2 reader=red-team Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> * Describe the new scratch-name rule in the PREGATE_STRAYS troubleshooting entry Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com> --------- Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
199931029e
commit
b6155921a5
5 files changed
+37
-7
No files matched your search
@@ -0,0 +1,4 @@
|
||||
---
|
||||
important: blocker
|
||||
---
|
||||
- **pregate's `strays` check no longer flags real files whose names only start with `tmp` or `scratch`.** It treated `tmp` and `scratch` as name prefixes, so a real module such as `lib/server/disk-space/tmp-watch.js` failed with `PREGATE_STRAYS`, and `tmpfs-mount.js` or `scratchpad.ts` would have too. A branch can't allowlist its own strays, so nothing on the branch could clear it. `tmp` and `scratch` now count only as the whole name stem, optionally numbered: `tmp`, `tmp.js`, `tmp2.js`, `tmp_1.txt`, `TMP.js`, `scratch.md` and `scratch2.ts` are still flagged, and so is every `zz-*` name and editor leftover. The tradeoff: a stem followed by a word, such as `tmp-repro.ts` or `scratch_notes.md`, is no longer caught either, so name a scratch file `zz-*` to keep it flagged.
|
||||
+3
-1
@@ -220,7 +220,9 @@ Two stages with separate clocks, both printed:
|
||||
file is read whole from disk. A file over the size limit, or whose full diff
|
||||
does not parse, is scanned on its added lines alone, without that context.
|
||||
- `strays`: a new file at the repository root, a new top-level directory, or a
|
||||
scratch name (`zz-*`, `tmp*`, `scratch*`) or editor leftover (`*.orig`,
|
||||
scratch name (`zz-*`, or `tmp` or `scratch` as the whole name stem, optionally
|
||||
numbered: `tmp.js`, `tmp2.js`, `tmp_1.txt`, `scratch.md`, but not
|
||||
`tmp-watch.js`, `tmpfs-mount.js`, `scratchpad.ts` or `tmp-repro.ts`) or editor leftover (`*.orig`,
|
||||
`*.rej`, `*.swp`, `*.swo`, `*.bak`, `*.tmp`, `*~`, `.DS_Store`, `Thumbs.db`)
|
||||
anywhere.
|
||||
- `literals`: for every changed exported constant or named timeout/retry
|
||||
|
||||
@@ -4241,7 +4241,9 @@ anchored pattern and a reason ([docs/pregate.md](pregate.md#allowlist));
|
||||
### `PREGATE_STRAYS`
|
||||
|
||||
**Meaning.** A file was added at the repository root, in a new top-level
|
||||
directory, or under a scratch name (`zz-*`, `tmp*`, `scratch*`) or an editor
|
||||
directory, or under a scratch name (`zz-*`, or `tmp` or `scratch` as the whole
|
||||
name stem, optionally numbered: `tmp.js`, `tmp2.js`, `tmp_1.txt`, `scratch.md`,
|
||||
but not `tmp-watch.js`, `tmpfs-mount.js`, `scratchpad.ts` or `tmp-repro.ts`) or an editor
|
||||
leftover name (`*.orig`, `*.rej`, `*.swp`, `*.swo`, `*.bak`, `*.tmp`, `*~`,
|
||||
`.DS_Store`, `Thumbs.db`).
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/**
|
||||
* pregate check `strays` (tier 1, preflight): files the branch added at the
|
||||
* repository root, in a top-level directory the base branch does not have,
|
||||
* or anywhere under a scratch name (`zz-*`, `tmp*`, `scratch*`, editor
|
||||
* leftovers). Incident p0-4-scratch-script: a `zz-probe.sh` shipped in a
|
||||
* or anywhere under a scratch name (`zz-*`; `tmp` or `scratch` as the whole
|
||||
* stem, optionally numbered, so `tmp2.js` and `scratch_1.md` but not
|
||||
* `tmp-watch.js`; editor leftovers). Incident p0-4-scratch-script: a `zz-probe.sh` shipped in a
|
||||
* release PR because nothing looked at the file list.
|
||||
*/
|
||||
import { spawnSync } from 'node:child_process';
|
||||
@@ -12,7 +13,7 @@ import type { CheckDef, CheckResult, PregateContext } from '../types';
|
||||
|
||||
/** Conventional root files a repo adds without a declaration. */
|
||||
export const ROOT_OK = /^(?:README|LICENSE|LICENCE|NOTICE|CHANGELOG|CONTRIBUTING|CODE_OF_CONDUCT|SECURITY|AUTHORS|VERSION|Makefile|Dockerfile|Procfile|Gemfile|Rakefile|Cargo\.(?:toml|lock)|go\.(?:mod|sum)|package(?:-lock)?\.json|bun\.lockb?|pnpm-lock\.yaml|yarn\.lock|tsconfig[\w.-]*\.json|bunfig\.toml|pyproject\.toml|pubspec\.(?:yaml|lock)|analysis_options\.yaml|dart_test\.yaml|requirements[\w.-]*\.txt|setup\.(?:py|cfg)|\.[\w.-]+|[\w.-]+\.config\.[cm]?[jt]s|[\w.-]+\.md)$/i;
|
||||
export const STRAY_NAME = /^(?:zz-|tmp|scratch)|\.(?:orig|rej|swp|swo|bak|tmp)$|~$|^\.DS_Store$|^Thumbs\.db$/i;
|
||||
export const STRAY_NAME = /^(?:zz-|(?:tmp|scratch)\d*(?:[-_]\d+)?(?:\.|$))|\.(?:orig|rej|swp|swo|bak|tmp)$|~$|^\.DS_Store$|^Thumbs\.db$/i;
|
||||
|
||||
function run(ctx: PregateContext): CheckResult {
|
||||
const inputs = baseInputs(ctx);
|
||||
|
||||
@@ -20,6 +20,7 @@ import { DEFAULT_CONFIG, validateConfig } from '../lib/pregate/config';
|
||||
import { isDocsEmptyLane } from '../lib/pregate/docs-lane';
|
||||
import { buildGraph, testsFor } from '../lib/pregate/import-graph';
|
||||
import { CHECK_IDS } from '../lib/pregate/index';
|
||||
import { STRAY_NAME } from '../lib/pregate/checks/strays';
|
||||
import type { PregateContext } from '../lib/pregate/types';
|
||||
import { parseWorkflow } from '../lib/pregate/workflows';
|
||||
import { BASE_PREGATE, cleanup, commit, makeFixtureRepo, runBin, write, type FixtureRepo } from './helpers/pregate-fixture';
|
||||
@@ -536,15 +537,35 @@ describe('gstack-pregate (bin)', () => {
|
||||
const ok = pregate(repo, ['--stage', 'preflight', '--only', 'strays']);
|
||||
expect(ok.status).toBe(EXIT.ok);
|
||||
expect(ok.out).toMatch(/^preflight {2}strays {4}pass /m);
|
||||
commit(repo, { 'docs/zz-notes.md': '# n\n', 'lib/tmp-x.ts': 'export {};\n', 'test/scratch.py': 'pass\n', 'lib/util.js.orig': 'x\n' });
|
||||
commit(repo, { 'docs/zz-notes.md': '# n\n', 'lib/tmp.ts': 'export {};\n', 'test/scratch.py': 'pass\n', 'lib/util.js.orig': 'x\n' });
|
||||
const r = pregate(repo, ['--stage', 'preflight', '--only', 'strays']);
|
||||
expect(r.status).toBe(EXIT.fail);
|
||||
expect(r.out).toMatch(/^preflight {2}strays {4}fail .*4 stray file\(s\)/m);
|
||||
for (const f of ['docs/zz-notes.md', 'lib/tmp-x.ts', 'test/scratch.py', 'lib/util.js.orig']) expect(r.out).toContain(`strays: ${f}: scratch name (${f.split('/').pop()})`);
|
||||
for (const f of ['docs/zz-notes.md', 'lib/tmp.ts', 'test/scratch.py', 'lib/util.js.orig']) expect(r.out).toContain(`strays: ${f}: scratch name (${f.split('/').pop()})`);
|
||||
expect(r.out).not.toContain('probe.py: scratch name');
|
||||
expect(r.out).not.toContain('temporal-graph-shipped.test.ts: scratch name');
|
||||
});
|
||||
|
||||
// Value: protects=real modules whose names only start with tmp/scratch (tmp-watch.js, tmpfs-mount.js, scratchpad.ts) pass strays; fails_when=STRAY_NAME treats tmp or scratch as a bare prefix again
|
||||
// why_new=GST-1211 covers zz-*, probe.py and temporal-*, never a tmp- or scratch-prefixed real module (GST-1944, ALPH-74); seam=none
|
||||
test('GST-1944: tmp and scratch match as a whole stem only; tmp-watch.js, tmpfs-mount.js and scratchpad.ts are not scratch names', () => {
|
||||
for (const name of ['tmp-watch.js', 'tmpfs-mount.js', 'tmpl.ts', 'scratchpad.ts', 'scratch-card.tsx', 'tmp_cleanup.py', 'tmp-repro.ts', 'scratch-probe.sh']) expect([name, STRAY_NAME.test(name)]).toEqual([name, false]);
|
||||
for (const name of ['tmp', 'tmp.js', 'tmp2.js', 'tmp_1.txt', 'tmp-1.js', 'TMP.js', 'Tmp.md', 'scratch', 'scratch.md', 'scratch2.ts', 'scratch_3.py', 'SCRATCH.txt', 'zz-anything', 'zz-watch.js', 'notes.tmp', 'util.js.orig']) expect([name, STRAY_NAME.test(name)]).toEqual([name, true]);
|
||||
const repo = fixture({ pregate: { ...BASE_PREGATE, warn: [] } });
|
||||
commit(repo, { 'lib/server/disk-space/tmp-watch.js': 'module.exports = 1;\n', 'lib/server/disk-space/tmpfs-mount.js': 'module.exports = 2;\n', 'lib/scratchpad.js': 'module.exports = 3;\n' });
|
||||
const ok = pregate(repo, ['--stage', 'preflight', '--only', 'strays']);
|
||||
expect(ok.status).toBe(EXIT.ok);
|
||||
expect(ok.out).toMatch(/^preflight {2}strays {4}pass /m);
|
||||
commit(repo, { 'lib/tmp.js': 'x\n', 'lib/tmp2.js': 'x\n', 'lib/tmp_1.txt': 'x\n', 'docs/TMP.js': 'x\n', 'docs/scratch.md': 'x\n', 'lib/scratch2.ts': 'x\n', 'lib/zz-anything': 'x\n', 'lib/tmp': 'x\n' });
|
||||
const r = pregate(repo, ['--stage', 'preflight', '--only', 'strays']);
|
||||
expect(r.status).toBe(EXIT.fail);
|
||||
expect(r.out).toMatch(/^preflight {2}strays {4}fail .*8 stray file\(s\)/m);
|
||||
for (const f of ['lib/tmp.js', 'lib/tmp2.js', 'lib/tmp_1.txt', 'docs/TMP.js', 'docs/scratch.md', 'lib/scratch2.ts', 'lib/zz-anything', 'lib/tmp']) expect(r.out).toContain(`strays: ${f}: scratch name (${f.split('/').pop()})`);
|
||||
expect(r.out).not.toContain('tmp-watch.js: scratch name');
|
||||
expect(r.out).not.toContain('tmpfs-mount.js: scratch name');
|
||||
expect(r.out).not.toContain('scratchpad.js: scratch name');
|
||||
});
|
||||
|
||||
test('p0-4-heavy-old-constant: a nightly-only test still asserting the old literal fails literals with file:line', () => {
|
||||
const repo = fixture();
|
||||
commit(repo, { 'lib/retry.js': "exports.MAX_RETRIES = 3;\nexports.TIMEOUT_MS = 9000;\nexports.retry = (fn) => fn();\n" });
|
||||
|
||||
Reference in new issue
Block a user