mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-07-10 01:29:17 +00:00
ci: stabilize actionlint on self-hosted runners (#6113)
This commit is contained in:
parent
15d30ddc64
commit
1287ac10ca
3 changed files with 109 additions and 8 deletions
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
|
|
@ -128,14 +128,15 @@ jobs:
|
|||
# instant the branch is pushed) instead of github.ref. github.ref is the
|
||||
# merge ref (refs/pull/N/merge), which GitHub rebuilds asynchronously and
|
||||
# can serve stale for minutes after a push, repeatedly flaking this gate.
|
||||
# The merge queue (integration_cli on merge_group) validates the merged
|
||||
# result. Non-PR events keep github.ref.
|
||||
# Merge queue refs are ephemeral; check out the event head SHA directly so
|
||||
# slow hosted runners do not fail after the queue branch is removed.
|
||||
# Non-PR/non-queue events keep github.ref.
|
||||
- name: 'Checkout'
|
||||
id: 'checkout'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
uses: 'actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd' # v6.0.2
|
||||
with:
|
||||
ref: "${{ github.event.inputs.branch_ref || (github.event_name == 'pull_request' && format('refs/pull/{0}/head', github.event.pull_request.number)) || github.ref }}"
|
||||
ref: "${{ github.event.inputs.branch_ref || (github.event_name == 'pull_request' && format('refs/pull/{0}/head', github.event.pull_request.number)) || (github.event_name == 'merge_group' && github.event.merge_group.head_sha) || github.ref }}"
|
||||
# Shallow: nothing here walks git history (the verify guard below checks
|
||||
# head.sha == HEAD, schema/tests touch only the working tree). On the
|
||||
# in-repo ECS runner a full-history clone is the heaviest transfer and
|
||||
|
|
@ -318,14 +319,14 @@ jobs:
|
|||
permissions:
|
||||
contents: 'read'
|
||||
steps:
|
||||
# See the Ubuntu gate's checkout: on PRs use the immutable refs/pull/N/head
|
||||
# to avoid merge-ref rebuild lag; other events keep github.ref.
|
||||
# See the Ubuntu gate's checkout: PRs use the immutable refs/pull/N/head
|
||||
# and merge queue uses the event head SHA.
|
||||
- name: 'Checkout'
|
||||
id: 'checkout'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
uses: 'actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd' # v6.0.2
|
||||
with:
|
||||
ref: "${{ github.event.inputs.branch_ref || (github.event_name == 'pull_request' && format('refs/pull/{0}/head', github.event.pull_request.number)) || github.ref }}"
|
||||
ref: "${{ github.event.inputs.branch_ref || (github.event_name == 'pull_request' && format('refs/pull/{0}/head', github.event.pull_request.number)) || (github.event_name == 'merge_group' && github.event.merge_group.head_sha) || github.ref }}"
|
||||
|
||||
- name: 'Set up Node.js 22.x'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
|
|
@ -380,7 +381,7 @@ jobs:
|
|||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
uses: 'actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd' # v6.0.2
|
||||
with:
|
||||
ref: "${{ github.event.inputs.branch_ref || (github.event_name == 'pull_request' && format('refs/pull/{0}/head', github.event.pull_request.number)) || github.ref }}"
|
||||
ref: "${{ github.event.inputs.branch_ref || (github.event_name == 'pull_request' && format('refs/pull/{0}/head', github.event.pull_request.number)) || (github.event_name == 'merge_group' && github.event.merge_group.head_sha) || github.ref }}"
|
||||
|
||||
- name: 'Set up Node.js 22.x'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
|
|
@ -495,6 +496,7 @@ jobs:
|
|||
- name: 'Checkout'
|
||||
uses: 'actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd' # v6.0.2
|
||||
with:
|
||||
ref: "${{ github.event.inputs.branch_ref || (github.event_name == 'merge_group' && github.event.merge_group.head_sha) || github.ref }}"
|
||||
# Shallow, mirroring the Ubuntu gate: nothing here walks git history,
|
||||
# and a full-history clone is the heaviest transfer on the ECS runner.
|
||||
fetch-depth: 1
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
import { execSync } from 'node:child_process';
|
||||
import { createHash } from 'node:crypto';
|
||||
import { mkdirSync, rmSync } from 'node:fs';
|
||||
import { tmpdir } from 'node:os';
|
||||
import { join } from 'node:path';
|
||||
|
|
@ -15,7 +16,37 @@ const ACTIONLINT_VERSION = '1.7.12';
|
|||
const SHELLCHECK_VERSION = '0.11.0';
|
||||
const YAMLLINT_VERSION = '1.35.1';
|
||||
|
||||
const TEMP_DIR = join(tmpdir(), 'qwen-code-linters');
|
||||
function sanitizePathPart(value) {
|
||||
return value.replace(/[^A-Za-z0-9._-]/g, '_');
|
||||
}
|
||||
|
||||
export function getLinterTempDir({
|
||||
cwd = process.cwd(),
|
||||
env = process.env,
|
||||
} = {}) {
|
||||
const baseDir = env.RUNNER_TEMP || tmpdir();
|
||||
const runId = env.GITHUB_RUN_ID;
|
||||
|
||||
if (runId) {
|
||||
return join(
|
||||
baseDir,
|
||||
'qwen-code-linters',
|
||||
[
|
||||
sanitizePathPart(runId),
|
||||
sanitizePathPart(env.GITHUB_RUN_ATTEMPT || '1'),
|
||||
sanitizePathPart(env.GITHUB_JOB || 'job'),
|
||||
].join('-'),
|
||||
);
|
||||
}
|
||||
|
||||
const workspaceHash = createHash('sha256')
|
||||
.update(cwd)
|
||||
.digest('hex')
|
||||
.slice(0, 16);
|
||||
return join(baseDir, 'qwen-code-linters', `local-${workspaceHash}`);
|
||||
}
|
||||
|
||||
const TEMP_DIR = getLinterTempDir();
|
||||
|
||||
function getPlatformArch() {
|
||||
const platform = process.platform;
|
||||
|
|
@ -65,6 +96,7 @@ const LINTERS = {
|
|||
run: `
|
||||
actionlint \
|
||||
-color \
|
||||
-shellcheck= \
|
||||
-ignore 'SC2002:' \
|
||||
-ignore 'SC2016:' \
|
||||
-ignore 'SC2129:' \
|
||||
|
|
|
|||
67
scripts/tests/lint.test.js
Normal file
67
scripts/tests/lint.test.js
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright 2025 Qwen Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
|
||||
describe('getLinterTempDir', () => {
|
||||
const originalArgv = process.argv;
|
||||
|
||||
beforeEach(() => {
|
||||
process.argv = ['node', 'scripts/lint.js', '--test-import'];
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.argv = originalArgv;
|
||||
});
|
||||
|
||||
it('isolates GitHub Actions linter installs by run and job', async () => {
|
||||
const { getLinterTempDir } = await import('../lint.js');
|
||||
|
||||
const first = getLinterTempDir({
|
||||
cwd: '/runner/_work/qwen-code/qwen-code',
|
||||
env: {
|
||||
RUNNER_TEMP: '/runner/_work/_temp',
|
||||
GITHUB_RUN_ID: '28501834362',
|
||||
GITHUB_RUN_ATTEMPT: '1',
|
||||
GITHUB_JOB: 'test',
|
||||
},
|
||||
});
|
||||
const second = getLinterTempDir({
|
||||
cwd: '/runner/_work/qwen-code/qwen-code',
|
||||
env: {
|
||||
RUNNER_TEMP: '/runner/_work/_temp',
|
||||
GITHUB_RUN_ID: '28501834363',
|
||||
GITHUB_RUN_ATTEMPT: '1',
|
||||
GITHUB_JOB: 'integration_cli',
|
||||
},
|
||||
});
|
||||
|
||||
expect(first).toBe(
|
||||
'/runner/_work/_temp/qwen-code-linters/28501834362-1-test',
|
||||
);
|
||||
expect(second).toBe(
|
||||
'/runner/_work/_temp/qwen-code-linters/28501834363-1-integration_cli',
|
||||
);
|
||||
expect(first).not.toBe(second);
|
||||
});
|
||||
|
||||
it('isolates local linter installs by workspace', async () => {
|
||||
const { getLinterTempDir } = await import('../lint.js');
|
||||
|
||||
const first = getLinterTempDir({
|
||||
cwd: '/tmp/qwen-code-a',
|
||||
env: {},
|
||||
});
|
||||
const second = getLinterTempDir({
|
||||
cwd: '/tmp/qwen-code-b',
|
||||
env: {},
|
||||
});
|
||||
|
||||
expect(first).toMatch(/\/qwen-code-linters\/local-[a-f0-9]{16}$/);
|
||||
expect(second).toMatch(/\/qwen-code-linters\/local-[a-f0-9]{16}$/);
|
||||
expect(first).not.toBe(second);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue