Skip to content

Commit 1203e59

Browse files
authored
Merge branch 'main' into fix/session-init-timeout-contract
2 parents 83498f3 + be58588 commit 1203e59

240 files changed

Lines changed: 17538 additions & 2693 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actionlint.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ self-hosted-runner:
22
labels:
33
- 'ecs-qwen'
44
- 'ecs-win'
5-
- 'ecs-update-sg'
6-
- 'ecs-update-64c'
75
- 'ecs-update-hk-1'
86
- 'ecs-update-hk-2'
97
- 'ecs-update-hk-3'
8+
- 'ecs-update-hk-4'
9+
- 'ecs-update-hk-5'
1010

1111
config-variables: null
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import assert from 'node:assert/strict';
2+
import { spawnSync } from 'node:child_process';
3+
import {
4+
chmodSync,
5+
mkdtempSync,
6+
readFileSync,
7+
rmSync,
8+
writeFileSync,
9+
} from 'node:fs';
10+
import { tmpdir } from 'node:os';
11+
import { dirname, join } from 'node:path';
12+
import { describe, it } from 'node:test';
13+
import { fileURLToPath } from 'node:url';
14+
import { parse } from 'yaml';
15+
16+
const workflowPath = join(
17+
dirname(fileURLToPath(import.meta.url)),
18+
'..',
19+
'workflows',
20+
'ci.yml',
21+
);
22+
const testSteps = parse(readFileSync(workflowPath, 'utf8')).jobs.test.steps;
23+
24+
function step(name) {
25+
const value = testSteps.find((candidate) => candidate.name === name);
26+
assert.ok(value, `missing ${name} step`);
27+
return value;
28+
}
29+
30+
describe('ci.yml disk-pressure evidence', () => {
31+
it('starts sampling before npm ci and preserves those samples for upload', () => {
32+
const install = step('Install dependencies').run;
33+
const npmCi = install.indexOf('npm ci');
34+
35+
assert.match(
36+
install,
37+
/DISK_SAMPLES="\$\{RUNNER_TEMP\}\/disk-pressure-samples\.log"/,
38+
);
39+
assert.ok(npmCi > install.indexOf('DFSAMPLE '));
40+
assert.match(install, /\( while sleep 10; do sample_disk; done \) &/);
41+
assert.ok(npmCi > install.indexOf('( while sleep 10'));
42+
assert.match(install, /trap .*SAMPLER_PID.* EXIT/);
43+
44+
const tests = step('Run tests and generate reports').run;
45+
assert.match(
46+
tests,
47+
/DISK_SAMPLES="\$\{RUNNER_TEMP\}\/disk-pressure-samples\.log"\nif \[ ! -s "\$DISK_SAMPLES" \]; then\n {2}echo "DISKCONTEXT .*" > "\$DISK_SAMPLES" 2>\/dev\/null \|\| true\nfi/,
48+
);
49+
assert.ok(tests.indexOf('export TMPDIR=') > tests.indexOf('DISK_SAMPLES='));
50+
51+
const sampleFormat = (script) => {
52+
const match = script.match(
53+
/sample="DFSAMPLE .*\/proc\/meminfo 2>\/dev\/null(?: \|\| true)?\)\]"/,
54+
);
55+
assert.ok(match);
56+
return match[0]
57+
.replaceAll('${RUNNER_TEMP:-/tmp}', '${TMPDIR}')
58+
.replace(
59+
' /proc/meminfo 2>/dev/null || true)]',
60+
' /proc/meminfo 2>/dev/null)]',
61+
);
62+
};
63+
const headerLine = (script) =>
64+
script
65+
.split('\n')
66+
.find((line) => line.trimStart().startsWith('echo "DISKCONTEXT '))
67+
?.trim();
68+
assert.equal(headerLine(install), headerLine(tests));
69+
assert.equal(sampleFormat(install), sampleFormat(tests));
70+
71+
const upload = step('Upload disk-pressure samples');
72+
assert.equal(upload.if, '${{ failure() }}');
73+
assert.equal(upload.with['if-no-files-found'], 'ignore');
74+
assert.equal(
75+
upload.with.path,
76+
'${{ runner.temp }}/disk-pressure-samples.log',
77+
);
78+
});
79+
80+
it('keeps install failure status while writing the pre-install sample', () => {
81+
const root = mkdtempSync(join(tmpdir(), 'ci-disk-pressure-'));
82+
const npm = join(root, 'npm');
83+
writeFileSync(npm, '#!/usr/bin/env bash\nexit 42\n');
84+
chmodSync(npm, 0o755);
85+
86+
try {
87+
const result = spawnSync(
88+
'bash',
89+
['-e', '-o', 'pipefail', '-c', step('Install dependencies').run],
90+
{
91+
encoding: 'utf8',
92+
timeout: 30_000,
93+
env: {
94+
...process.env,
95+
PATH: `${root}:${process.env.PATH}`,
96+
RUNNER_TEMP: root,
97+
},
98+
},
99+
);
100+
101+
assert.equal(result.error, undefined);
102+
assert.equal(
103+
result.status,
104+
42,
105+
`signal: ${result.signal}\nerror: ${result.error}\nstdout: ${result.stdout}\nstderr: ${result.stderr}`,
106+
);
107+
const samples = readFileSync(
108+
join(root, 'disk-pressure-samples.log'),
109+
'utf8',
110+
);
111+
assert.match(samples, /^DISKCONTEXT /m);
112+
assert.match(samples, /^DFSAMPLE /m);
113+
} finally {
114+
rmSync(root, { recursive: true, force: true });
115+
}
116+
});
117+
});

.github/scripts/ci-runner-routing.test.mjs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -574,15 +574,19 @@ describe('e2e.yml e2e-test-linux runner routing', () => {
574574
assert.match(job.steps[heal].run, /chown -R .* "\$GITHUB_WORKSPACE"/);
575575
assert.match(job.steps[heal].run, /chmod -R u\+rwX/);
576576
assert.ok(heal < checkout, 'the heal must precede the checkout');
577-
// Dangling-only prune at the end: always(), docker leg, pool only —
578-
// and never a form that could remove tagged images other jobs use.
577+
// Cleanup at the end: always(), docker leg, pool only. Tagged cleanup is
578+
// restricted to old workflow-owned images; the general cleanup remains
579+
// dangling-only so it cannot remove images from unrelated jobs.
579580
assert.ok(prune !== -1, 'the dangling prune must exist');
580581
assert.match(job.steps[prune].if, /always\(\)/);
581582
assert.match(job.steps[prune].if, /sandbox:docker/);
582583
assert.match(job.steps[prune].if, /runner\.environment == 'self-hosted'/);
584+
assert.match(
585+
job.steps[prune].run,
586+
/docker image prune --all --force --filter 'label=org\.qwen-code\.ci\.sandbox=true' --filter 'until=24h'/,
587+
);
583588
assert.match(job.steps[prune].run, /docker image prune --force/);
584589
assert.match(job.steps[prune].run, /until=24h/);
585-
assert.doesNotMatch(job.steps[prune].run, /--all|-a\b/);
586590
// A failing prune must stay diagnosable: surface a warning instead of a
587591
// silent `|| true`, and keep the daemon's error out of /dev/null.
588592
assert.match(job.steps[prune].run, /\|\| echo "::warning::/);

0 commit comments

Comments
 (0)