Task #1664: cargo cache save를 trusted branch로 제한 #2696
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |