QVAC-22630 chore: release @qvac/model-fit 0.6.0 #5108
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: Security baseline | |
| # Canonical security baseline (TruffleHog secret scan + CodeQL static analysis) | |
| # rolled out to Tier-1 repos per QVAC-21550. This is a thin caller that | |
| # delegates to the org's reusable workflow (authored under QVAC-19055); its | |
| # inputs and behavior are documented in | |
| # tetherto/qvac-actions/docs/security-baseline.md. | |
| # | |
| # Uses plain `pull_request` (never `pull_request_target`): fork PRs run with a | |
| # read-only token and no secrets, and this baseline needs none of the | |
| # privileged context (`codeql-upload: never` below), so the "pwn request" | |
| # surface of `pull_request_target` buys nothing here. | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| schedule: | |
| # Weekly full scan (QVAC-19056 rollout). Mondays 07:00 UTC; crons are | |
| # staggered across weekdays per repo to spread scheduled-run load. | |
| - cron: "0 7 * * 1" | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| baseline: | |
| # Pinned to the 0.1.0 tag's immutable commit SHA per the org freeze-and-pin | |
| # convention for reusable workflows (never `@main`). | |
| uses: tetherto/qvac-actions/.github/workflows/public-reusable-security.yml@bbb0740e2a16b94371c7439e0e06945c5b68e759 # 0.3.0 | |
| permissions: | |
| contents: read | |
| security-events: write | |
| pull-requests: write | |
| actions: read | |
| with: | |
| # Explicit language list: CodeQL autodetect frequently misses C/C++ in | |
| # mixed repos, so we name every scanned surface (JS/TS + Python + C/C++). | |
| languages: c-cpp,javascript-typescript,python | |
| severity-threshold: high | |
| # qvac uses GitHub "Default setup" for code scanning, which rejects SARIF | |
| # from advanced workflows. Skip the upload here; the severity gate and | |
| # TruffleHog still run (SARIF is written locally for the gate to read). | |
| codeql-upload: never | |
| # Buildless C/C++ extraction (no compilation / submodule checkout), so the | |
| # scan doesn't need qvac's clang/vcpkg/bare-make toolchain. Uniform with | |
| # the Tier-1 C/C++ callers; requires qvac-actions >= 0.2.0. | |
| codeql-build-mode: none | |
| # Repo-local CI trust-policy regression tests (fork CI hardening). Kept here | |
| # instead of a dedicated workflow so the coverage rides along with the security | |
| # baseline that already runs on every PR. | |
| # Runs UNPRIVILEGED only (plain pull_request, contents: read, no secrets) — | |
| # never move this under pull_request_target. NOTE: this job is repo-local and | |
| # NOT part of the org reusable baseline above; preserve it across any org | |
| # sync of this caller file. | |
| policy-tests: | |
| name: policy-tests | |
| runs-on: ubuntu-latest | |
| # The job's own work is ~10s; the budget exists almost entirely to absorb | |
| # checkout latency, which is not ours to control — the same --depth=1 fetch | |
| # of this repo has been observed at both 7s and 97s. A cap this close to | |
| # external variance buys nothing and turns a slow morning into a red main. | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| # Reads the changed-file list from the pull request files API. | |
| pull-requests: read | |
| steps: | |
| - name: Checkout PR code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 6.0.2 | |
| with: | |
| # Default shallow fetch: the changed-file list comes from the PR files | |
| # API below, so this job needs no history beyond the checked-out tree. | |
| persist-credentials: false | |
| - name: Set up Node.js | |
| uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # 6.3.0 | |
| with: | |
| node-version: 20 | |
| - name: Run trust-policy tests | |
| run: >- | |
| node --test | |
| .github/scripts/test/ci-trust-policy.test.mjs | |
| .github/scripts/test/prebuild-status.test.mjs | |
| # The co-load inventory drifts when the SDK swaps an addon, not when the | |
| # co-load package changes, so this has to run on every PR rather than | |
| # behind the co-load label. It only reads files (no npm install), and a | |
| # stale inventory makes the co-load gate report on an addon the SDK no | |
| # longer ships. | |
| - name: Run co-load addon inventory tests | |
| run: >- | |
| node --test | |
| packages/ggml-coload-smoke/test/addons.unit.test.js | |
| # The trust-policy suite asserts on workflow *text*, so it stays green even | |
| # when an edit destroys a job graph. on-merge-*/on-publish-* never run on a | |
| # PR, and pull_request_target workflows load from the base branch, so this | |
| # is the only place a PR parses its own edited workflows. Only files this PR | |
| # changes are linted — no repo-wide baseline file. | |
| - name: Collect changed workflow files | |
| id: changed-workflows | |
| if: github.event_name == 'pull_request' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| REPO: ${{ github.repository }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| run: | | |
| set -euo pipefail | |
| # The PR files API is the exact changed set, so this needs no local | |
| # history and the checkout stays shallow. The previous `git diff | |
| # base...head` required fetch-depth: 0, whose blob backfill stalled the | |
| # checkout for ~2 minutes of this job's 5-minute budget on push runs. | |
| # It also read a `base.sha` that GitHub leaves stale, which inflated the | |
| # scope with files the PR never touched. | |
| # | |
| # `status != removed` drops deletions: actionlint aborts its entire run | |
| # (reporting nothing at all) if any path on its command line is missing, | |
| # so a PR that deletes a workflow would otherwise lint nothing and pass. | |
| gh api "repos/${REPO}/pulls/${PR_NUMBER}/files" --paginate \ | |
| --jq '.[] | select(.status != "removed") | .filename' \ | |
| > "$RUNNER_TEMP/changed-all.txt" | |
| # The endpoint hard-caps at 3000 files. Truncation would silently shrink | |
| # the lint scope, so refuse to report a pass we cannot stand behind. | |
| if [ "$(wc -l < "$RUNNER_TEMP/changed-all.txt" | tr -d ' ')" -ge 3000 ]; then | |
| echo "::error title=PR too large to scope automatically::The pull request files API truncates at 3000 files; run actionlint over the changed workflows manually." | |
| exit 1 | |
| fi | |
| # grep, not rg: ripgrep is not installed on GitHub-hosted runners, and | |
| # a blanket `|| true` turned that `command not found` into count=0 — | |
| # the gate reported success while linting nothing. grep exits 1 for | |
| # "no matches" (fine) and >1 for a real failure (must not be silent). | |
| set +e | |
| grep -E '^\.github/(workflows|actions)/.*\.ya?ml$' \ | |
| "$RUNNER_TEMP/changed-all.txt" > "$RUNNER_TEMP/changed-workflows.txt" | |
| filter_status=$? | |
| set -e | |
| if [ "$filter_status" -gt 1 ]; then | |
| echo "::error title=Could not determine changed workflow files::grep exited ${filter_status}" | |
| exit 1 | |
| fi | |
| count=$(wc -l < "$RUNNER_TEMP/changed-workflows.txt" | tr -d ' ') | |
| echo "count=${count}" >> "$GITHUB_OUTPUT" | |
| echo "actionlint scope: ${count} changed workflow/action file(s)" | |
| # `.cursor/rules/no-remote-code-execution.mdc` forbids fetching a remote | |
| # artefact and executing it. actionlint ships no first-party action, so the | |
| # release tarball is pinned to a digest here and verified before extraction — | |
| # a retagged or tampered release fails the checksum and never runs. | |
| # To bump: update both ACTIONLINT_VERSION and ACTIONLINT_SHA256 from | |
| # https://github.com/rhysd/actionlint/releases (actionlint_<ver>_checksums.txt). | |
| - name: Install actionlint | |
| if: github.event_name == 'pull_request' && steps.changed-workflows.outputs.count != '0' | |
| env: | |
| ACTIONLINT_VERSION: 1.7.12 | |
| ACTIONLINT_SHA256: 8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8 | |
| run: | | |
| set -euo pipefail | |
| curl -sSfL -o "$RUNNER_TEMP/actionlint.tgz" \ | |
| "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" | |
| echo "${ACTIONLINT_SHA256} ${RUNNER_TEMP}/actionlint.tgz" | sha256sum --check --strict | |
| tar -xzf "$RUNNER_TEMP/actionlint.tgz" -C "$RUNNER_TEMP" actionlint | |
| - name: Lint changed workflows with actionlint | |
| if: github.event_name == 'pull_request' && steps.changed-workflows.outputs.count != '0' | |
| run: | | |
| set -euo pipefail | |
| mapfile -t files < "$RUNNER_TEMP/changed-workflows.txt" | |
| # actionlint exits 1 when it reports findings; lint-workflows.mjs decides pass/fail. | |
| "$RUNNER_TEMP/actionlint" -oneline -shellcheck= -pyflakes= "${files[@]}" \ | |
| > "$RUNNER_TEMP/actionlint.txt" || true | |
| node .github/scripts/lint-workflows.mjs --input "$RUNNER_TEMP/actionlint.txt" | |
| # The whole fork trust model collapses to fail-open if the fork-ci | |
| # environment loses its required reviewers or is deleted (GitHub silently | |
| # recreates it unprotected on next use). Checked on push/schedule/dispatch | |
| # rather than per-PR: fork PR tokens cannot read environment settings, so | |
| # gating PRs on this would fail for exactly the PRs it is meant to protect. | |
| # Exit 1 means the protection actually drifted (hard fail). Any other | |
| # non-zero means the check could not run — GITHUB_TOKEN has no dedicated | |
| # `environments` permission scope, so a read denial must not be reported | |
| # as drift. | |
| - name: Verify fork-ci environment protection | |
| if: github.event_name != 'pull_request' | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set +e | |
| node .github/scripts/verify-fork-ci-environment.mjs | |
| status=$? | |
| set -e | |
| if [ "$status" -eq 1 ]; then | |
| echo "::error title=fork-ci environment protection drifted::External fork PRs may run without human approval." | |
| exit 1 | |
| fi | |
| if [ "$status" -ne 0 ]; then | |
| echo "::warning title=Could not verify fork-ci environment::Exit ${status}; GITHUB_TOKEN may lack environment read access. Run .github/scripts/verify-fork-ci-environment.mjs locally with an admin token." | |
| fi |