fix(ci): skip the duplicate prepare build in the daemon E2E lane (#14884)

* fix(ci): skip the duplicate prepare build in the daemon E2E lane (#14870)

Co-authored-by: Qwen-Coder <[email protected]>

* test(ci): pin the daemon E2E prepare-skip premises (Refs #14870)

* test(ci): keep the daemon E2E step commands pinned (Refs #14870)

* test(ci): pin the daemon E2E step and its install warning (#14870)

---------

Co-authored-by: Qwen-Coder <[email protected]>
Co-authored-by: Qwen Autofix <[email protected]>
Co-authored-by: qwen-code-dev-bot <[email protected]>
This commit is contained in:
authored and GitHub committed 2026-10-22 12:19:59 +00:00
1 parent 7773fa313a
commit 06e59666df
2 files changed
+78 -10

No files matched your search

+1 -1
View File
@@ -1969,7 +1969,7 @@ jobs:
for attempt in 1 2 3; do
if corepack pnpm install --frozen-lockfile --prefer-offline --reporter=append-only; then
if [[ "${attempt}" != "1" ]]; then
echo "::warning::corepack pnpm install failed $((attempt - 1)) time(s) before the retry absorbed it — this step also runs prepare's build, so check the failure class before counting it toward #11726."
echo "::warning::corepack pnpm install failed $((attempt - 1)) time(s) before the retry absorbed it — this step skips prepare's build, so check the failure class before counting it toward #11726."
fi
break
fi
+77 -9
View File
@@ -100,13 +100,37 @@ describe('SDK Java self-hosted workflow guards', () => {
(s) => s.name === 'Install Node.js dependencies',
);
expect(install.env?.QWEN_SKIP_PREPARE).toBe('1');
expect(steps.map((s) => s.name).indexOf('Build Qwen Code')).toBeGreaterThan(
steps.map((s) => s.name).indexOf('Install Node.js dependencies'),
);
});
it.each([
['.github/workflows/sdk-java.yml', 'daemon-e2e'],
['.github/workflows/release-sdk-java.yml', 'release'],
])('%s %s pins the explicit Build/Bundle/Run steps', (file, jobName) => {
const steps = parse(readFileSync(file, 'utf8')).jobs[jobName].steps;
const names = steps.map((s) => s.name);
expect(names.indexOf('Build Qwen Code')).toBeGreaterThan(
names.indexOf('Install Node.js dependencies'),
);
expect(names.indexOf('Bundle Qwen Code')).toBeGreaterThan(
names.indexOf('Build Qwen Code'),
);
let previous = -1;
for (const [name, run] of [
['Build Qwen Code', 'npm run build'],
['Bundle Qwen Code', 'npm run bundle'],
['Run Java daemon E2E', 'npx tsx scripts/run-java-daemon-sdk-e2e.ts'],
]) {
const index = names.indexOf(name);
expect(index, `${jobName}: ${name}`).toBeGreaterThan(previous);
previous = index;
expect(steps[index].run, name).toBe(run);
expect(steps[index]['continue-on-error'], name).toBeUndefined();
expect(steps[index].if, name).toBeUndefined();
}
});
it('keeps the pinned build steps pointed at files that exist', () => {
const scripts = JSON.parse(readFileSync('package.json', 'utf8')).scripts;
expect(existsSync('scripts/run-java-daemon-sdk-e2e.ts')).toBe(true);
expect(scripts.build).toBeTruthy();
expect(scripts.bundle).toBeTruthy();
});
it('serializes latency-sensitive tests on each physical ECS host', () => {
@@ -1485,15 +1509,30 @@ describe('setup-java Maven cache stays on hosted runners', () => {
// and qwen-autofix.yml already absorb (#11726); the heap class is capped in
// pnpm-workspace.yaml, and a retry only offers it a quieter host. Pin the
// recipe on every install so a new bare step fails here instead of on main.
// Each attempt re-runs prepare's build (~4m32s observed), not just backoff.
// For the five installs that do not set QWEN_SKIP_PREPARE, each attempt
// re-runs prepare's build (~4m32s observed), not just backoff; daemon-e2e
// skips the build and only runs `npm run generate` on each attempt.
// Scope is sdk-java.yml: release-sdk-java.yml's install is a bare one-liner
// with no retry loop or prepare skip, so these assertions do not describe it;
// its explicit Build/Bundle/Run steps are pinned separately above.
describe('SDK Java install-transient retry', () => {
const installs = Object.entries(parse(workflow).jobs).flatMap(
// Mirrors scripts/prepare.js, which skips on '1' or 'true' case-insensitively;
// Actions merges workflow/job env into the step environment.
const installSkipsPrepare = (step, inheritedEnv = {}) =>
['1', 'true'].includes(
String(
{ ...inheritedEnv, ...step.env }.QWEN_SKIP_PREPARE ?? '',
).toLowerCase(),
);
const parsedWorkflow = parse(workflow);
const installs = Object.entries(parsedWorkflow.jobs).flatMap(
([jobName, job]) =>
(job.steps ?? [])
.filter(
(s) => typeof s.run === 'string' && s.run.includes('pnpm install'),
)
.map((s) => [jobName, s]),
.map((s) => [jobName, s, { ...parsedWorkflow.env, ...job.env }]),
);
it('finds every install step', () => {
@@ -1507,6 +1546,35 @@ describe('SDK Java install-transient retry', () => {
]);
});
it.each(installs)(
"%s install warning matches the step's prepare behaviour",
(jobName, step, inheritedEnv) => {
const skips = installSkipsPrepare(step, inheritedEnv);
expect(step.run, jobName).toMatch(
new RegExp(
'::warning::[^\\n]*' +
(skips
? "this step skips prepare's build"
: "this step also runs prepare's build"),
),
);
},
);
it('classifies prepare-skip spellings the way scripts/prepare.js does', () => {
for (const value of ['1', 'true', 'TRUE', 1]) {
expect(installSkipsPrepare({ env: { QWEN_SKIP_PREPARE: value } })).toBe(
true,
);
expect(installSkipsPrepare({}, { QWEN_SKIP_PREPARE: value })).toBe(true);
}
for (const value of [undefined, '', '0', 'false']) {
expect(installSkipsPrepare({ env: { QWEN_SKIP_PREPARE: value } })).toBe(
false,
);
}
});
it.each(installs)('%s retries a transient install', (jobName, step) => {
for (const fragment of [
'for attempt in 1 2 3; do',