Skip to content

QVAC-22630 chore: release @qvac/model-fit 0.6.0 #5108

QVAC-22630 chore: release @qvac/model-fit 0.6.0

QVAC-22630 chore: release @qvac/model-fit 0.6.0 #5108

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