mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-07-09 17:19:02 +00:00
ci: add lightweight PR profiles (#6186)
* ci: add lightweight PR profiles * fix(ci): harden lightweight profile classification * fix(ci): harden lightweight profile edge cases * fix(ci): report classifier invocation failures * fix(ci): tighten docs-only path matching * ci: restrict light profiles to same-repo PRs --------- Co-authored-by: Shaojin Wen <shaojin.wensj@alibaba-inc.com>
This commit is contained in:
parent
e743f0e2e0
commit
183ad54b11
3 changed files with 287 additions and 25 deletions
102
.github/scripts/ci/classify-profile.mjs
vendored
Normal file
102
.github/scripts/ci/classify-profile.mjs
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#!/usr/bin/env node
|
||||
import { readFileSync } from 'node:fs';
|
||||
|
||||
export const CI_PROFILES = {
|
||||
DOCS_ONLY: 'docs_only',
|
||||
GITHUB_CI_ONLY: 'github_ci_only',
|
||||
FULL: 'full',
|
||||
};
|
||||
|
||||
export const GITHUB_CI_ONLY_FILES = new Set([
|
||||
'.github/scripts/pr-safety-precheck.mjs',
|
||||
'.github/scripts/pr-safety-precheck.test.mjs',
|
||||
'.github/workflows/qwen-pr-safety-precheck.yml',
|
||||
]);
|
||||
|
||||
function isDocsOnlyFile(file) {
|
||||
const normalized = file.replace(/\\/g, '/');
|
||||
return (
|
||||
/^docs\/.+\.(?:md|mdx)$/i.test(normalized) ||
|
||||
/^(?:README|CHANGELOG|CONTRIBUTING|CODE_OF_CONDUCT|SECURITY|SUPPORT|LICENSE|NOTICE)(?:\.[^/]*)?$/i.test(
|
||||
normalized,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function classifyPath(file) {
|
||||
if (isDocsOnlyFile(file)) return CI_PROFILES.DOCS_ONLY;
|
||||
if (GITHUB_CI_ONLY_FILES.has(file)) return CI_PROFILES.GITHUB_CI_ONLY;
|
||||
return CI_PROFILES.FULL;
|
||||
}
|
||||
|
||||
function classifyFileEntry(entry) {
|
||||
if (typeof entry === 'string') return classifyPath(entry);
|
||||
|
||||
const filename = entry?.filename;
|
||||
if (!filename) return CI_PROFILES.FULL;
|
||||
|
||||
const profile = classifyPath(filename);
|
||||
if (entry.status !== 'renamed') return profile;
|
||||
|
||||
const previousProfile = entry.previous_filename
|
||||
? classifyPath(entry.previous_filename)
|
||||
: CI_PROFILES.FULL;
|
||||
return previousProfile === profile ? profile : CI_PROFILES.FULL;
|
||||
}
|
||||
|
||||
export function classifyChangedFiles(files) {
|
||||
const changedFiles = files.filter(Boolean);
|
||||
if (changedFiles.length === 0) return CI_PROFILES.FULL;
|
||||
|
||||
if (
|
||||
changedFiles.every(
|
||||
(entry) => classifyFileEntry(entry) === CI_PROFILES.DOCS_ONLY,
|
||||
)
|
||||
) {
|
||||
return CI_PROFILES.DOCS_ONLY;
|
||||
}
|
||||
|
||||
if (
|
||||
changedFiles.every(
|
||||
(entry) => classifyFileEntry(entry) === CI_PROFILES.GITHUB_CI_ONLY,
|
||||
)
|
||||
) {
|
||||
return CI_PROFILES.GITHUB_CI_ONLY;
|
||||
}
|
||||
|
||||
return CI_PROFILES.FULL;
|
||||
}
|
||||
|
||||
function parseChangedFiles(text) {
|
||||
return text
|
||||
.split(/\r?\n/)
|
||||
.filter(Boolean)
|
||||
.map((line) => {
|
||||
try {
|
||||
return JSON.parse(line);
|
||||
} catch {
|
||||
return line;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function main() {
|
||||
const filePath = process.argv[2];
|
||||
if (!filePath) {
|
||||
console.log(CI_PROFILES.FULL);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const files = parseChangedFiles(readFileSync(filePath, 'utf8'));
|
||||
console.log(classifyChangedFiles(files));
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : String(err);
|
||||
console.error(`::warning::Failed to read changed files: ${message}`);
|
||||
console.log(CI_PROFILES.FULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
main();
|
||||
}
|
||||
116
.github/scripts/ci/classify-profile.test.mjs
vendored
Normal file
116
.github/scripts/ci/classify-profile.test.mjs
vendored
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import {
|
||||
GITHUB_CI_ONLY_FILES,
|
||||
classifyChangedFiles,
|
||||
} from './classify-profile.mjs';
|
||||
|
||||
test('uses docs_only for markdown-only changes', () => {
|
||||
assert.equal(
|
||||
classifyChangedFiles(['README.md', 'docs/usage.md', '.qwen/design/foo.md']),
|
||||
'full',
|
||||
);
|
||||
assert.equal(
|
||||
classifyChangedFiles(['README.md', 'docs/usage.md']),
|
||||
'docs_only',
|
||||
);
|
||||
});
|
||||
|
||||
test('uses docs_only for uppercase and extensionless docs', () => {
|
||||
assert.equal(
|
||||
classifyChangedFiles(['README.MD', 'docs/guide.MDX', 'LICENSE', 'README']),
|
||||
'docs_only',
|
||||
);
|
||||
});
|
||||
|
||||
test('falls back to full for root docs names used as directories', () => {
|
||||
assert.equal(classifyChangedFiles(['README.md/evil.ts']), 'full');
|
||||
assert.equal(classifyChangedFiles(['LICENSE.txt/src/index.ts']), 'full');
|
||||
});
|
||||
|
||||
test('uses github_ci_only for the allowed GitHub CI helper files', () => {
|
||||
assert.equal(
|
||||
classifyChangedFiles([...GITHUB_CI_ONLY_FILES]),
|
||||
'github_ci_only',
|
||||
);
|
||||
});
|
||||
|
||||
test('uses github_ci_only for each allowed GitHub CI helper file', () => {
|
||||
for (const file of GITHUB_CI_ONLY_FILES) {
|
||||
assert.equal(classifyChangedFiles([file]), 'github_ci_only');
|
||||
}
|
||||
});
|
||||
|
||||
test('falls back to full for case-mismatched GitHub CI helper paths', () => {
|
||||
assert.equal(
|
||||
classifyChangedFiles(['.GITHUB/SCRIPTS/PR-SAFETY-PRECHECK.MJS']),
|
||||
'full',
|
||||
);
|
||||
});
|
||||
|
||||
test('classifies renamed files using both old and new paths', () => {
|
||||
assert.equal(
|
||||
classifyChangedFiles([
|
||||
{
|
||||
filename: 'docs/new.md',
|
||||
previous_filename: 'packages/core/src/runtime.ts',
|
||||
status: 'renamed',
|
||||
},
|
||||
]),
|
||||
'full',
|
||||
);
|
||||
assert.equal(
|
||||
classifyChangedFiles([
|
||||
{
|
||||
filename: 'docs/new.md',
|
||||
previous_filename: 'docs/old.md',
|
||||
status: 'renamed',
|
||||
},
|
||||
]),
|
||||
'docs_only',
|
||||
);
|
||||
});
|
||||
|
||||
test('falls back to full when changed files are unavailable', () => {
|
||||
assert.equal(classifyChangedFiles([]), 'full');
|
||||
assert.equal(classifyChangedFiles(['', null, undefined]), 'full');
|
||||
});
|
||||
|
||||
test('falls back to full for source or mixed changes', () => {
|
||||
assert.equal(
|
||||
classifyChangedFiles(['README.md', 'packages/cli/src/index.ts']),
|
||||
'full',
|
||||
);
|
||||
assert.equal(
|
||||
classifyChangedFiles([
|
||||
'README.md',
|
||||
'.github/scripts/pr-safety-precheck.mjs',
|
||||
]),
|
||||
'full',
|
||||
);
|
||||
});
|
||||
|
||||
test('falls back to full for main CI workflow changes', () => {
|
||||
assert.equal(classifyChangedFiles(['.github/workflows/ci.yml']), 'full');
|
||||
assert.equal(classifyChangedFiles(['.github/workflows/codeql.yml']), 'full');
|
||||
});
|
||||
|
||||
test('falls back to full for classifier changes', () => {
|
||||
assert.equal(
|
||||
classifyChangedFiles(['.github/scripts/ci/classify-profile.mjs']),
|
||||
'full',
|
||||
);
|
||||
assert.equal(
|
||||
classifyChangedFiles(['.github/scripts/ci/classify-profile.test.mjs']),
|
||||
'full',
|
||||
);
|
||||
});
|
||||
|
||||
test('falls back to full for runtime markdown assets and instruction files', () => {
|
||||
assert.equal(
|
||||
classifyChangedFiles(['packages/core/src/skills/bundled/foo/SKILL.md']),
|
||||
'full',
|
||||
);
|
||||
assert.equal(classifyChangedFiles(['AGENTS.md']), 'full');
|
||||
});
|
||||
94
.github/workflows/ci.yml
vendored
94
.github/workflows/ci.yml
vendored
|
|
@ -119,6 +119,8 @@ jobs:
|
|||
if: "${{ !cancelled() && github.event_name != 'push' }}"
|
||||
runs-on: '${{ fromJSON(needs.classify_pr.outputs.ubuntu_runner || ''["ubuntu-latest"]'') }}'
|
||||
timeout-minutes: 60
|
||||
outputs:
|
||||
ci_profile: '${{ steps.ci_profile.outputs.ci_profile }}'
|
||||
permissions:
|
||||
contents: 'read'
|
||||
checks: 'write'
|
||||
|
|
@ -158,9 +160,50 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
|
||||
- name: 'Classify CI profile'
|
||||
id: 'ci_profile'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
env:
|
||||
GH_TOKEN: '${{ github.token }}'
|
||||
PR_NUMBER: "${{ github.event_name == 'pull_request' && github.event.pull_request.number || '' }}"
|
||||
IS_SAME_REPO_PR: "${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository }}"
|
||||
run: |-
|
||||
profile=full
|
||||
if [[ "${GITHUB_EVENT_NAME}" == "pull_request" && -n "${PR_NUMBER}" ]]; then
|
||||
if [[ "${IS_SAME_REPO_PR}" == "true" ]]; then
|
||||
changed_files="${RUNNER_TEMP}/changed-files.jsonl"
|
||||
if gh api --paginate "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}/files" --jq '.[] | {filename, status, previous_filename}' > "${changed_files}"; then
|
||||
if ! profile="$(node .github/scripts/ci/classify-profile.mjs "${changed_files}")"; then
|
||||
echo "::error::CI profile classifier exited non-zero; running full CI."
|
||||
profile=full
|
||||
fi
|
||||
else
|
||||
echo "::warning::Unable to list PR changed files; running full CI."
|
||||
fi
|
||||
else
|
||||
echo "Fork PR detected; running full CI."
|
||||
fi
|
||||
fi
|
||||
echo "ci_profile=${profile}" >> "${GITHUB_OUTPUT}"
|
||||
echo "Selected CI profile: ${profile}"
|
||||
|
||||
- name: 'Docs-only CI'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'docs_only' }}"
|
||||
run: 'echo "Docs-only change; full CI skipped."'
|
||||
|
||||
- name: 'GitHub CI helper checks'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'github_ci_only' }}"
|
||||
timeout-minutes: 5
|
||||
run: |-
|
||||
# Keep this path dependency-free; script formatting is checked when those files hit full CI.
|
||||
node scripts/lint.js --setup
|
||||
node scripts/lint.js --actionlint
|
||||
node scripts/lint.js --yamllint
|
||||
node --test .github/scripts/pr-safety-precheck.test.mjs .github/scripts/ci/classify-profile.test.mjs
|
||||
|
||||
# Self-hosted can't reach nodejs.org reliably; reuse the machine's Node.
|
||||
- name: 'Set up Node.js 22.x (hosted)'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && runner.environment == 'github-hosted' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' && runner.environment == 'github-hosted' }}"
|
||||
uses: 'actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e' # v6.4.0
|
||||
with:
|
||||
node-version: '22.x'
|
||||
|
|
@ -169,7 +212,7 @@ jobs:
|
|||
registry-url: 'https://registry.npmjs.org/'
|
||||
|
||||
- name: 'Use pre-installed Node.js (self-hosted)'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && runner.environment == 'self-hosted' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' && runner.environment == 'self-hosted' }}"
|
||||
run: |-
|
||||
if ! command -v node >/dev/null 2>&1; then
|
||||
echo "::error::Node.js is not on PATH for this self-hosted runner. Provision Node 22.x or set the MAINTAINER_ECS_RUNNER_DISABLED repository variable to 'true' to route PRs back to hosted runners."
|
||||
|
|
@ -181,7 +224,7 @@ jobs:
|
|||
fi
|
||||
|
||||
- name: 'Configure persistent npm cache (self-hosted)'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && runner.environment == 'self-hosted' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' && runner.environment == 'self-hosted' }}"
|
||||
run: |-
|
||||
cache_dir="${HOME}/.cache/qwen-code/npm"
|
||||
mkdir -p "${cache_dir}"
|
||||
|
|
@ -190,7 +233,7 @@ jobs:
|
|||
du -sh "${cache_dir}" 2>/dev/null || true
|
||||
|
||||
- name: 'Configure npm for rate limiting'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: |-
|
||||
npm config set fetch-retry-mintimeout 20000
|
||||
npm config set fetch-retry-maxtimeout 120000
|
||||
|
|
@ -198,68 +241,68 @@ jobs:
|
|||
npm config set fetch-timeout 300000
|
||||
|
||||
- name: 'Install dependencies'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: |-
|
||||
npm ci --prefer-offline --no-audit --progress=false
|
||||
|
||||
- name: 'Report npm cache usage (self-hosted)'
|
||||
if: "${{ always() && needs.classify_pr.outputs.skip_ci != 'true' && runner.environment == 'self-hosted' }}"
|
||||
if: "${{ always() && needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' && runner.environment == 'self-hosted' }}"
|
||||
run: |-
|
||||
cache_dir="${NPM_CONFIG_CACHE:-$(npm config get cache)}"
|
||||
echo "npm cache: ${cache_dir}"
|
||||
du -sh "${cache_dir}" 2>/dev/null || true
|
||||
|
||||
- name: 'Audit critical runtime dependencies'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: 'npm run audit:runtime:critical'
|
||||
|
||||
- name: 'Check lockfile'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: 'npm run check:lockfile'
|
||||
|
||||
- name: 'Check desktop workspace isolation'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: 'npm run check:desktop-isolation'
|
||||
|
||||
- name: 'Install linters'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: 'node scripts/lint.js --setup'
|
||||
|
||||
- name: 'Run ESLint'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: 'node scripts/lint.js --eslint'
|
||||
|
||||
- name: 'Run actionlint'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
timeout-minutes: 5
|
||||
run: 'node scripts/lint.js --actionlint'
|
||||
|
||||
- name: 'Run shellcheck'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: 'node scripts/lint.js --shellcheck'
|
||||
|
||||
- name: 'Run yamllint'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: 'node scripts/lint.js --yamllint'
|
||||
|
||||
- name: 'Run Prettier'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: 'node scripts/lint.js --prettier'
|
||||
|
||||
- name: 'Run sensitive keyword linter'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: 'node scripts/lint.js --sensitive-keywords'
|
||||
|
||||
- name: 'Run i18n check'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: 'npm run check-i18n'
|
||||
|
||||
- name: 'Generate settings schema'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: 'npm run generate:settings-schema'
|
||||
|
||||
- name: 'Check settings schema is up-to-date'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: |-
|
||||
if [[ -n $(git status --porcelain packages/vscode-ide-companion/schemas/settings.schema.json) ]]; then
|
||||
echo "Error: settings.schema.json is out of date."
|
||||
|
|
@ -274,12 +317,12 @@ jobs:
|
|||
# npm run test:ci only, so they intentionally do not repeat this
|
||||
# platform-independent bundle closure check.
|
||||
- name: 'Check serve fast-path bundle closure'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
run: 'npm run check:serve-fast-path-bundle'
|
||||
|
||||
- name: 'Run tests and generate reports'
|
||||
id: 'unit_tests'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
env:
|
||||
NO_COLOR: true
|
||||
HOME: '${{ runner.temp }}/qwen-ci-home'
|
||||
|
|
@ -294,12 +337,12 @@ jobs:
|
|||
npm run test:ci
|
||||
|
||||
- name: 'Run no-AK integration smoke tests'
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && github.event_name == 'pull_request' }}"
|
||||
if: "${{ needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' && github.event_name == 'pull_request' }}"
|
||||
run: 'npm run test:integration:no-ak:sandbox:none'
|
||||
|
||||
- name: 'Publish Test Report (for non-forks)'
|
||||
if: |-
|
||||
${{ always() && needs.classify_pr.outputs.skip_ci != 'true' && steps.unit_tests.outcome != 'skipped' && (github.event.pull_request.head.repo.full_name == github.repository) }}
|
||||
${{ always() && needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' && steps.unit_tests.outcome != 'skipped' && (github.event.pull_request.head.repo.full_name == github.repository) }}
|
||||
uses: 'dorny/test-reporter@a43b3a5f7366b97d083190328d2c652e1a8b6aa2' # ratchet:dorny/test-reporter@v3
|
||||
with:
|
||||
name: 'Test Results (ubuntu-latest, Node 22.x)'
|
||||
|
|
@ -309,14 +352,14 @@ jobs:
|
|||
|
||||
- name: 'Upload Test Results Artifact (for forks)'
|
||||
if: |-
|
||||
${{ always() && needs.classify_pr.outputs.skip_ci != 'true' && (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }}
|
||||
${{ always() && needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' && (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }}
|
||||
uses: 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a' # v7.0.1
|
||||
with:
|
||||
name: 'test-results-fork-22.x-ubuntu-latest'
|
||||
path: 'packages/*/junit.xml'
|
||||
|
||||
- name: 'Upload coverage reports'
|
||||
if: "${{ always() && needs.classify_pr.outputs.skip_ci != 'true' }}"
|
||||
if: "${{ always() && needs.classify_pr.outputs.skip_ci != 'true' && steps.ci_profile.outputs.ci_profile == 'full' }}"
|
||||
uses: 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a' # v7.0.1
|
||||
with:
|
||||
name: 'coverage-reports-22.x-ubuntu-latest'
|
||||
|
|
@ -450,6 +493,7 @@ jobs:
|
|||
${{
|
||||
!cancelled() &&
|
||||
needs.classify_pr.outputs.skip_ci != 'true' &&
|
||||
needs.test.outputs.ci_profile == 'full' &&
|
||||
github.event_name == 'pull_request' &&
|
||||
github.event.pull_request.head.repo.full_name == github.repository
|
||||
}}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue