Skip to content

Task #1664: cargo cache save를 trusted branch로 제한 #2696

Task #1664: cargo cache save를 trusted branch로 제한

Task #1664: cargo cache save를 trusted branch로 제한 #2696

Workflow file for this run

name: CI
on:
push:
branches: [main, devel]
tags: ['v*']
paths-ignore:
- 'mydocs/**'
- 'docs/**'
- 'samples/**'
- 'assets/**'
- '*.md'
- 'LICENSE'
- '.github/ISSUE_TEMPLATE/**'
- '.github/FUNDING.yml'
- '.github/CODE_OF_CONDUCT.md'
- '.github/SECURITY.md'
- '.github/pull_request_template.md'
- '.github/dependabot.yml'
- 'rhwp-logo.*'
pull_request:
branches: [main, devel]
paths-ignore:
- 'docs/**'
- 'samples/**'
- 'assets/**'
- '*.md'
- 'LICENSE'
- '.github/ISSUE_TEMPLATE/**'
- '.github/FUNDING.yml'
- '.github/CODE_OF_CONDUCT.md'
- '.github/SECURITY.md'
- '.github/pull_request_template.md'
- '.github/dependabot.yml'
- 'rhwp-logo.*'
workflow_dispatch:
env:
CARGO_TERM_COLOR: always
# [Task #1192 F] 같은 PR 에 새 push 가 오면 진행 중 run 을 취소해 중복 실행 제거.
# cancel-in-progress 는 PR 이벤트에서만 활성화 — devel/main push 머지 검증 run 은 보존.
concurrency:
group: ci-${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
preflight:
name: CI preflight
runs-on: ubuntu-latest
permissions:
contents: read
checks: read
pull-requests: read
outputs:
fast_pass: ${{ steps.detect.outputs.fast_pass || 'false' }}
reason: ${{ steps.detect.outputs.reason || 'preflight-unavailable' }}
candidate_sha: ${{ steps.detect.outputs.candidate_sha || '' }}
steps:
- name: Detect mydocs-only fast pass
id: detect
continue-on-error: true
uses: actions/github-script@v8
with:
script: |
const allowedConclusions = new Set(['success', 'skipped', 'neutral']);
const { owner, repo } = context.repo;
function setResult(fastPass, reason, candidateSha = '') {
core.setOutput('fast_pass', fastPass ? 'true' : 'false');
core.setOutput('reason', reason);
core.setOutput('candidate_sha', candidateSha);
core.info(`fast_pass=${fastPass} reason=${reason} candidate_sha=${candidateSha}`);
}
function isAllowedMydocsPath(filename) {
return filename.startsWith('mydocs/');
}
function latestRun(runs) {
return runs
.slice()
.sort((a, b) => {
const bTime = Date.parse(b.completed_at || b.started_at || b.created_at || 0);
const aTime = Date.parse(a.completed_at || a.started_at || a.created_at || 0);
return bTime - aTime;
})[0];
}
try {
if (context.eventName !== 'pull_request') {
setResult(false, 'not-pull-request');
return;
}
const pr = context.payload.pull_request;
const commits = await github.paginate(github.rest.pulls.listCommits, {
owner,
repo,
pull_number: pr.number,
per_page: 100,
});
if (commits.length === 0) {
setResult(false, 'no-pr-commits');
return;
}
let trailingMydocsOnlyCommits = 0;
let candidateSha = '';
for (let index = commits.length - 1; index >= 0; index -= 1) {
const sha = commits[index].sha;
const { data: commit } = await github.rest.repos.getCommit({
owner,
repo,
ref: sha,
});
const files = commit.files || [];
// The commit endpoint may truncate very large file lists. Fall back to full CI.
if (files.length === 0 || files.length >= 300) {
setResult(false, `unusable-file-list:${sha}`);
return;
}
const mydocsOnly = files.every((file) => isAllowedMydocsPath(file.filename));
if (mydocsOnly) {
if ((commit.parents || []).length !== 1) {
setResult(false, `mydocs-only-merge-commit:${sha}`);
return;
}
trailingMydocsOnlyCommits += 1;
continue;
}
candidateSha = sha;
break;
}
if (trailingMydocsOnlyCommits === 0) {
setResult(false, 'no-trailing-mydocs-commits');
return;
}
if (!candidateSha) {
candidateSha = pr.base.sha;
core.info(`all PR commits are under mydocs; using base SHA ${candidateSha}`);
setResult(true, 'all-mydocs-no-code-impact', candidateSha);
return;
}
const checkRuns = await github.paginate(github.rest.checks.listForRef, {
owner,
repo,
ref: candidateSha,
per_page: 100,
});
const buildRun = latestRun(checkRuns.filter((run) => (
run.name === 'Build & Test'
&& run.app?.slug === 'github-actions'
)));
if (!buildRun) {
setResult(false, `missing-build-and-test:${candidateSha}`, candidateSha);
return;
}
if (buildRun.status !== 'completed') {
setResult(false, `build-and-test-not-completed:${buildRun.status}`, candidateSha);
return;
}
if (!allowedConclusions.has(buildRun.conclusion)) {
setResult(false, `build-and-test-not-green:${buildRun.conclusion}`, candidateSha);
return;
}
setResult(true, `build-and-test-green:${buildRun.conclusion}`, candidateSha);
} catch (error) {
core.warning(`CI preflight failed; running full CI. ${error.message}`);
setResult(false, 'preflight-error');
}
build-and-test:
name: Build & Test
runs-on: ubuntu-latest
needs: preflight
if: ${{ always() && needs.preflight.outputs.fast_pass != 'true' }}
permissions:
contents: read
steps:
- uses: actions/checkout@v5
# [Task #1109 / #1192 C] ubuntu-latest runner 의 미사용 사전 설치 toolchain 제거하여
# 테스트 빌드 시 디스크 한도 초과를 줄인다.
# [#1192] 캐시 정상 작동 확인 후 "크고 빠른" 항목(android/dotnet)만 남기고 축소.
# 느린 docker prune --all / apt clean / ghc / CodeQL 정리는 제거. df -h 로 여유 확인.
- name: Free disk space (remove unused pre-installed toolchains)
run: |
sudo rm -rf /usr/local/lib/android
sudo rm -rf /usr/share/dotnet
df -h
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: 1.93.1
components: clippy, rustfmt
targets: wasm32-unknown-unknown
- name: Restore cargo registry & build cache
id: cargo_cache_restore
uses: actions/cache/restore@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Format check
run: cargo fmt --all -- --check
- name: Build
run: cargo build --release --verbose
# [Task #1192 A] canvas_layer_tree_matches_legacy* 는 feature gate 없는 lib 테스트로
# 아래 "Run lib tests"에 이미 포함된다. 별도 step 은 순수 중복이라 제거.
# (native-skia 테스트는 default feature 가 아니므로 전용 step 을 유지한다.)
- name: Check WASM target
run: cargo check --target wasm32-unknown-unknown --lib
- name: Install native Skia runtime packages
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
fonts-dejavu-core \
libfontconfig1-dev \
libfreetype6-dev
- name: Native Skia tests
run: cargo test --release --features native-skia skia --lib --verbose
- name: Run lib tests
run: cargo test --release --lib --verbose
- name: Run integration tests
run: cargo test --profile release-test --tests --verbose
- name: Clippy
run: cargo clippy -- -D warnings
- name: Save cargo registry & build cache
if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/devel' || github.ref == 'refs/heads/main') && steps.cargo_cache_restore.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
wasm-build:
name: WASM Build
runs-on: ubuntu-latest
permissions:
contents: read
if: github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/checkout@v5
# [Task #1109 / #1192 C] wasm-build job 도 build-and-test 와 동일 축소 패턴.
# "크고 빠른" 항목(android/dotnet)만 제거. df -h 로 여유 확인.
- name: Free disk space (remove unused pre-installed toolchains)
run: |
sudo rm -rf /usr/local/lib/android
sudo rm -rf /usr/share/dotnet
df -h
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
toolchain: 1.93.1
targets: wasm32-unknown-unknown
- name: Install wasm-pack
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
- name: Cache cargo registry & build
uses: actions/cache@v5
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-wasm-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-wasm-
- name: Build WASM
run: wasm-pack build --target web --release
- name: Upload WASM artifacts
uses: actions/upload-artifact@v4
with:
name: rhwp-wasm-pkg
path: pkg/
retention-days: 30