chore: harden runner setup
This commit is contained in:
parent
bc773950c0
commit
0f4391e2ab
@ -31,6 +31,7 @@
|
||||
"clean": "rimraf dist",
|
||||
"dev": "tsc -w -p tsconfig.build.json",
|
||||
"prepublishOnly": "pnpm check && pnpm test && pnpm build",
|
||||
"docs:list": "pnpm exec tsx scripts/docs-list.ts",
|
||||
"mcporter:list": "pnpm exec tsx src/cli.ts list",
|
||||
"mcporter:call": "pnpm exec tsx src/cli.ts call"
|
||||
},
|
||||
@ -50,6 +51,7 @@
|
||||
"@types/express": "^5.0.5",
|
||||
"@types/node": "^24.10.0",
|
||||
"@typescript/native-preview": "7.0.0-dev.20251104.1",
|
||||
"bun-types": "^1.3.2",
|
||||
"express": "^5.1.0",
|
||||
"oxlint": "^1.25.0",
|
||||
"oxlint-tsgolint": "^0.5.0",
|
||||
|
||||
25
pnpm-lock.yaml
generated
25
pnpm-lock.yaml
generated
@ -48,6 +48,9 @@ importers:
|
||||
'@typescript/native-preview':
|
||||
specifier: 7.0.0-dev.20251104.1
|
||||
version: 7.0.0-dev.20251104.1
|
||||
bun-types:
|
||||
specifier: ^1.3.2
|
||||
version: 1.3.2(@types/react@19.2.2)
|
||||
express:
|
||||
specifier: ^5.1.0
|
||||
version: 5.1.0
|
||||
@ -631,6 +634,9 @@ packages:
|
||||
'@types/range-parser@1.2.7':
|
||||
resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==}
|
||||
|
||||
'@types/react@19.2.2':
|
||||
resolution: {integrity: sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==}
|
||||
|
||||
'@types/send@0.17.6':
|
||||
resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==}
|
||||
|
||||
@ -752,6 +758,11 @@ packages:
|
||||
resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
bun-types@1.3.2:
|
||||
resolution: {integrity: sha512-i/Gln4tbzKNuxP70OWhJRZz1MRfvqExowP7U6JKoI8cntFrtxg7RJK3jvz7wQW54UuvNC8tbKHHri5fy74FVqg==}
|
||||
peerDependencies:
|
||||
'@types/react': ^19
|
||||
|
||||
bytes@3.1.2:
|
||||
resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@ -815,6 +826,9 @@ packages:
|
||||
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
|
||||
engines: {node: '>= 8'}
|
||||
|
||||
csstype@3.1.3:
|
||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||
|
||||
debug@4.4.3:
|
||||
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
|
||||
engines: {node: '>=6.0'}
|
||||
@ -1819,6 +1833,10 @@ snapshots:
|
||||
|
||||
'@types/range-parser@1.2.7': {}
|
||||
|
||||
'@types/react@19.2.2':
|
||||
dependencies:
|
||||
csstype: 3.1.3
|
||||
|
||||
'@types/send@0.17.6':
|
||||
dependencies:
|
||||
'@types/mime': 1.3.5
|
||||
@ -1948,6 +1966,11 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
bun-types@1.3.2(@types/react@19.2.2):
|
||||
dependencies:
|
||||
'@types/node': 24.10.0
|
||||
'@types/react': 19.2.2
|
||||
|
||||
bytes@3.1.2: {}
|
||||
|
||||
call-bind-apply-helpers@1.0.2:
|
||||
@ -1999,6 +2022,8 @@ snapshots:
|
||||
shebang-command: 2.0.0
|
||||
which: 2.0.2
|
||||
|
||||
csstype@3.1.3: {}
|
||||
|
||||
debug@4.4.3:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
@ -15,7 +15,9 @@ function walkMarkdownFiles(dir: string, base: string = dir): string[] {
|
||||
const entries = readdirSync(dir, { withFileTypes: true });
|
||||
const files: string[] = [];
|
||||
for (const entry of entries) {
|
||||
if (entry.name.startsWith('.')) continue;
|
||||
if (entry.name.startsWith('.')) {
|
||||
continue;
|
||||
}
|
||||
const fullPath = join(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
if (EXCLUDED_DIRS.has(entry.name)) {
|
||||
|
||||
@ -56,6 +56,9 @@ export function findGitSubcommand(commandArgs: string[]): GitCommandInfo | null
|
||||
|
||||
while (index < commandArgs.length) {
|
||||
const token = commandArgs[index];
|
||||
if (token === undefined) {
|
||||
break;
|
||||
}
|
||||
if (token === '--') {
|
||||
const next = commandArgs[index + 1];
|
||||
return next ? { name: next, index: index + 1 } : null;
|
||||
@ -83,6 +86,9 @@ export function determineGitWorkdir(baseDir: string, gitArgs: string[], command:
|
||||
|
||||
while (index < limit) {
|
||||
const token = gitArgs[index];
|
||||
if (token === undefined) {
|
||||
break;
|
||||
}
|
||||
if (token === '-C') {
|
||||
const next = gitArgs[index + 1];
|
||||
if (next) {
|
||||
|
||||
@ -156,13 +156,23 @@ function shouldExtendTimeout(commandArgs: string[]): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
const [first, ...rest] = tokens;
|
||||
const first = tokens[0];
|
||||
if (!first) {
|
||||
return false;
|
||||
}
|
||||
const rest = tokens.slice(1);
|
||||
|
||||
if (first === 'pnpm') {
|
||||
if (rest.length === 0) {
|
||||
return false;
|
||||
}
|
||||
const subcommand = rest[0];
|
||||
if (!subcommand) {
|
||||
return false;
|
||||
}
|
||||
if (!subcommand) {
|
||||
return false;
|
||||
}
|
||||
if (subcommand === 'run') {
|
||||
const script = rest[1];
|
||||
if (!script) {
|
||||
@ -218,13 +228,20 @@ function shouldUseLintTimeout(commandArgs: string[]): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
const [first, ...rest] = tokens;
|
||||
const first = tokens[0];
|
||||
if (!first) {
|
||||
return false;
|
||||
}
|
||||
const rest = tokens.slice(1);
|
||||
|
||||
if (first === 'pnpm') {
|
||||
if (rest.length === 0) {
|
||||
return false;
|
||||
}
|
||||
const subcommand = rest[0];
|
||||
if (!subcommand) {
|
||||
return false;
|
||||
}
|
||||
if (subcommand === 'run') {
|
||||
const script = rest[1];
|
||||
return typeof script === 'string' && script.startsWith('lint');
|
||||
@ -257,7 +274,11 @@ function isSingleTestInvocation(commandArgs: string[]): boolean {
|
||||
}
|
||||
}
|
||||
|
||||
const [first, ...rest] = tokens;
|
||||
const first = tokens[0];
|
||||
if (!first) {
|
||||
return false;
|
||||
}
|
||||
const rest = tokens.slice(1);
|
||||
if (first === 'pnpm') {
|
||||
if (rest[0] === 'test:file') {
|
||||
return true;
|
||||
@ -293,6 +314,9 @@ function tokenReferencesIntegrationTest(token: string): boolean {
|
||||
function referencesIntegrationSpec(tokens: string[]): boolean {
|
||||
for (let index = 0; index < tokens.length; index += 1) {
|
||||
const token = tokens[index];
|
||||
if (!token) {
|
||||
continue;
|
||||
}
|
||||
if (token === '--run' || token === '--include') {
|
||||
const next = tokens[index + 1];
|
||||
if (next && tokenReferencesIntegrationTest(next)) {
|
||||
@ -316,13 +340,34 @@ function matchesScriptKeyword(script: string, keywords: readonly string[]): bool
|
||||
function stripWrappersAndAssignments(args: string[]): string[] {
|
||||
const tokens = [...args];
|
||||
|
||||
while (tokens.length > 0 && isEnvAssignment(tokens[0])) {
|
||||
while (tokens.length > 0) {
|
||||
const candidate = tokens[0];
|
||||
if (!candidate) {
|
||||
break;
|
||||
}
|
||||
if (!isEnvAssignment(candidate)) {
|
||||
break;
|
||||
}
|
||||
tokens.shift();
|
||||
}
|
||||
|
||||
while (tokens.length > 0 && WRAPPER_COMMANDS.has(tokens[0])) {
|
||||
while (tokens.length > 0) {
|
||||
const wrapper = tokens[0];
|
||||
if (!wrapper) {
|
||||
break;
|
||||
}
|
||||
if (!WRAPPER_COMMANDS.has(wrapper)) {
|
||||
break;
|
||||
}
|
||||
tokens.shift();
|
||||
while (tokens.length > 0 && isEnvAssignment(tokens[0])) {
|
||||
while (tokens.length > 0) {
|
||||
const assignment = tokens[0];
|
||||
if (!assignment) {
|
||||
break;
|
||||
}
|
||||
if (!isEnvAssignment(assignment)) {
|
||||
break;
|
||||
}
|
||||
tokens.shift();
|
||||
}
|
||||
}
|
||||
@ -344,6 +389,9 @@ function isTestRunnerSuiteInvocation(tokens: string[], suite: string): boolean {
|
||||
const normalizedSuite = suite.toLowerCase();
|
||||
for (let index = 0; index < tokens.length; index += 1) {
|
||||
const token = tokens[index];
|
||||
if (!token) {
|
||||
continue;
|
||||
}
|
||||
const normalizedToken = token.replace(/^[./\\]+/, '');
|
||||
if (normalizedToken === 'scripts/test-runner.ts' || normalizedToken.endsWith('/scripts/test-runner.ts')) {
|
||||
const suiteToken = tokens[index + 1]?.toLowerCase();
|
||||
@ -363,7 +411,11 @@ function shouldUseLongTimeout(commandArgs: string[]): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
const [first, ...rest] = tokens;
|
||||
const first = tokens[0];
|
||||
if (!first) {
|
||||
return false;
|
||||
}
|
||||
const rest = tokens.slice(1);
|
||||
const matches = (token: string): boolean => matchesScriptKeyword(token, LONG_SCRIPT_KEYWORDS);
|
||||
|
||||
if (first === 'pnpm') {
|
||||
@ -371,6 +423,9 @@ function shouldUseLongTimeout(commandArgs: string[]): boolean {
|
||||
return false;
|
||||
}
|
||||
const subcommand = rest[0];
|
||||
if (!subcommand) {
|
||||
return false;
|
||||
}
|
||||
if (subcommand === 'run') {
|
||||
const script = rest[1];
|
||||
if (script && matches(script)) {
|
||||
@ -506,19 +561,22 @@ function buildExecutionParams(commandArgs: string[]): { command: string; args: s
|
||||
for (const token of commandArgs) {
|
||||
if (!commandStarted && isEnvAssignment(token)) {
|
||||
const [key, ...rest] = token.split('=');
|
||||
env[key] = rest.join('=');
|
||||
if (key) {
|
||||
env[key] = rest.join('=');
|
||||
}
|
||||
continue;
|
||||
}
|
||||
commandStarted = true;
|
||||
args.push(token);
|
||||
}
|
||||
|
||||
if (args.length === 0) {
|
||||
if (args.length === 0 || !args[0]) {
|
||||
printUsage('Missing command to execute.');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
return { command: args[0], args: args.slice(1), env };
|
||||
const [command, ...restArgs] = args;
|
||||
return { command, args: restArgs, env };
|
||||
}
|
||||
|
||||
// Forwards termination signals to the child and returns an unregister hook.
|
||||
@ -818,7 +876,7 @@ async function buildFindDeletePlan(findArgs: string[], workspaceDir: string): Pr
|
||||
process.exit(exitCode);
|
||||
}
|
||||
|
||||
const matches = stdoutBuf.split('\0').filter((entry) => entry.length > 0);
|
||||
const matches = stdoutBuf.split('\0').filter((entry: string) => entry.length > 0);
|
||||
if (matches.length === 0) {
|
||||
return { paths: [] };
|
||||
}
|
||||
@ -853,6 +911,9 @@ function parseRmArguments(argv: string[]): { targets: string[]; force: boolean;
|
||||
let index = 1;
|
||||
while (index < argv.length) {
|
||||
const token = argv[index];
|
||||
if (token === undefined) {
|
||||
break;
|
||||
}
|
||||
if (!treatAsTarget && token === '--') {
|
||||
treatAsTarget = true;
|
||||
index += 1;
|
||||
@ -894,6 +955,9 @@ function parseGitRmArguments(argv: string[], command: GitCommandInfo): GitRmPlan
|
||||
let index = command.index + 1;
|
||||
while (index < argv.length) {
|
||||
const token = argv[index];
|
||||
if (token === undefined) {
|
||||
break;
|
||||
}
|
||||
if (!treatAsPath && token === '--') {
|
||||
treatAsPath = true;
|
||||
index += 1;
|
||||
@ -1002,7 +1066,7 @@ async function movePathsToTrash(
|
||||
stdout: 'ignore',
|
||||
stderr: 'pipe',
|
||||
});
|
||||
const [exitCode, stderrText] = await Promise.all([proc.exited, proc.stderr?.text() ?? Promise.resolve('')]);
|
||||
const [exitCode, stderrText] = await Promise.all([proc.exited, readProcessStream(proc.stderr)]);
|
||||
if (exitCode === 0) {
|
||||
return { missing, errors: [] };
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"noEmit": true,
|
||||
"types": ["node"]
|
||||
"types": ["node", "bun-types"]
|
||||
},
|
||||
"include": ["src", "tests", "scripts", "docs"]
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user