Skip to content

Commit 5b3cc5c

Browse files
author
test
committed
Merge remote-tracking branch 'origin/main' into fix/scoped-cache-acquisitions
2 parents 8de1ea1 + eac13af commit 5b3cc5c

2 files changed

Lines changed: 105 additions & 0 deletions

File tree

scripts/hooks/pre-push

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@
55

66
set -e
77

8+
# Git exports repository-local environment variables to hooks. Clear them so
9+
# child processes can discover or create repositories outside this worktree.
10+
if ! git_local_env_vars="$(git rev-parse --local-env-vars)"; then
11+
echo "Failed to discover repository-local Git environment variables." >&2
12+
exit 1
13+
fi
14+
15+
while IFS= read -r git_var; do
16+
if [[ -n "$git_var" ]]; then
17+
unset "$git_var"
18+
fi
19+
done <<< "$git_local_env_vars"
20+
821
echo "Running pre-push quality gates..."
922

1023
echo "→ Linting..."
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { describe, expect, it } from 'vitest';
2+
import {
3+
chmodSync,
4+
existsSync,
5+
mkdirSync,
6+
mkdtempSync,
7+
readFileSync,
8+
rmSync,
9+
writeFileSync,
10+
} from 'node:fs';
11+
import { spawnSync } from 'node:child_process';
12+
import os from 'node:os';
13+
import path from 'node:path';
14+
import { fileURLToPath } from 'node:url';
15+
16+
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../');
17+
const hookPath = path.join(repoRoot, 'scripts/hooks/pre-push');
18+
19+
describe('pre-push hook', () => {
20+
it('clears repository-local Git variables before invoking quality gates', () => {
21+
const fixture = createFixture({ gitExitCode: 0 });
22+
23+
try {
24+
const result = runHook(fixture);
25+
26+
expect(result.status).toBe(0);
27+
expect(readFileSync(fixture.logPath, 'utf8').trim().split('\n')).toEqual([
28+
'unset|unset|run lint',
29+
'unset|unset|test',
30+
]);
31+
} finally {
32+
fixture.cleanup();
33+
}
34+
});
35+
36+
it('fails closed before quality gates when Git variable discovery fails', () => {
37+
const fixture = createFixture({ gitExitCode: 42 });
38+
39+
try {
40+
const result = runHook(fixture);
41+
42+
expect(result.status).not.toBe(0);
43+
expect(result.stderr).toContain('Failed to discover repository-local Git environment variables.');
44+
expect(existsSync(fixture.logPath)).toBe(false);
45+
} finally {
46+
fixture.cleanup();
47+
}
48+
});
49+
});
50+
51+
function createFixture({ gitExitCode }) {
52+
const root = mkdtempSync(path.join(os.tmpdir(), 'git-cas-pre-push-'));
53+
const binPath = path.join(root, 'bin');
54+
const logPath = path.join(root, 'pnpm.log');
55+
const gitPath = path.join(binPath, 'git');
56+
const pnpmPath = path.join(binPath, 'pnpm');
57+
58+
writeExecutable(
59+
gitPath,
60+
`#!/usr/bin/env bash\nif [[ ${gitExitCode} -ne 0 ]]; then exit ${gitExitCode}; fi\nprintf 'GIT_DIR\\nGIT_WORK_TREE\\n'\n`,
61+
);
62+
writeExecutable(
63+
pnpmPath,
64+
`#!/usr/bin/env bash\nprintf '%s|%s|%s\\n' "\${GIT_DIR-unset}" "\${GIT_WORK_TREE-unset}" "$*" >> "$HOOK_LOG"\n`,
65+
);
66+
67+
return {
68+
binPath,
69+
logPath,
70+
cleanup: () => rmSync(root, { recursive: true, force: true }),
71+
};
72+
}
73+
74+
function runHook(fixture) {
75+
return spawnSync('bash', [hookPath], {
76+
cwd: repoRoot,
77+
encoding: 'utf8',
78+
env: {
79+
...process.env,
80+
PATH: `${fixture.binPath}:${process.env.PATH}`,
81+
GIT_DIR: '/contaminating/repository',
82+
GIT_WORK_TREE: '/contaminating/worktree',
83+
HOOK_LOG: fixture.logPath,
84+
},
85+
});
86+
}
87+
88+
function writeExecutable(filePath, source) {
89+
mkdirSync(path.dirname(filePath), { recursive: true });
90+
writeFileSync(filePath, source);
91+
chmodSync(filePath, 0o755);
92+
}

0 commit comments

Comments
 (0)