73415cd2dc
* ci: pass ref context through env in release tag step zizmor flagged the "Resolve target tag" step in release.yml for template-injection: github.event_name / github.ref / github.ref_name were interpolated directly into the shell script. On a tag push the tag name is attacker-influenceable, so a crafted tag could inject commands. Move all three context values into the step env and reference them as shell variables instead. Verified with zizmor 1.16.3: template-injection findings on release.yml drop from 2 to 0. * ci: accept release.yml build caches via zizmor config The release pipeline restores Swatinem/rust-cache and actions/setup-node caches as a deliberate optimisation. zizmor flags all eight under cache-poisoning because release.yml publishes to crates.io / PyPI / npm. The caches are maintainer-controlled and the restore speedup is kept on purpose, so accept the finding via a zizmor config ignore for release.yml rather than running cache-free release builds. (Six of the eight are actions/setup-node, reported at Low confidence.) Adds .github/zizmor.yml; release.yml now reports 0 high findings. * ci: drop persisted checkout credentials on read-only jobs zizmor's artipacked audit flags every actions/checkout that keeps the default persisted credential: the token is written to the runner's .git/config, where it can leak if a later step packs .git into an uploaded artifact, or be read by another step in the same job. Set persist-credentials: false on the 20 checkouts whose jobs never push or authenticate to git (build/test/clippy/msrv/coverage/supply-chain/ fuzz/python/wasm/node in ci.yml, plus bench.yml, codeql.yml, the seven release.yml build/publish jobs, and sync-metadata.yml). The publish and release jobs authenticate to crates.io / npm / PyPI / the GitHub API with their own tokens, not persisted git credentials, so this is safe. sync-about.yml genuinely pushes the indicator-count fix-up to the PR branch, so it keeps its credential and is accepted via .github/zizmor.yml. zizmor artipacked for the repo drops to 0 (0 high, 0 medium remaining).
120 lines
4.7 KiB
YAML
120 lines
4.7 KiB
YAML
name: Cross-library benchmark
|
||
|
||
# Audit finding R10: previously the cross-library benchmark ran on every push
|
||
# and every pull-request to `main`, adding 5–10 minutes of build + bench time
|
||
# per CI run with no consumer of the resulting artefact. The benchmark is now
|
||
# scheduled (nightly at 03:00 UTC) and on-demand via `workflow_dispatch`. The
|
||
# CI pipeline proper (.github/workflows/ci.yml) still verifies build / tests /
|
||
# lints on every push and pull-request.
|
||
on:
|
||
schedule:
|
||
# Nightly at 03:00 UTC. Pick a slot well away from common European /
|
||
# American working-hours pushes to keep this off the critical path.
|
||
- cron: "0 3 * * *"
|
||
workflow_dispatch:
|
||
inputs:
|
||
size:
|
||
description: "Number of bars per indicator (default 20000)"
|
||
required: false
|
||
default: "20000"
|
||
iterations:
|
||
description: "Batch iterations per indicator (default 10)"
|
||
required: false
|
||
default: "10"
|
||
|
||
# Least-privilege default for the auto-injected GITHUB_TOKEN. The single job
|
||
# only builds and uploads an artifact (upload-artifact uses the artifact
|
||
# storage API, not the contents scope), so it never needs repo write (OpenSSF
|
||
# Scorecard: Token-Permissions).
|
||
permissions:
|
||
contents: read
|
||
|
||
env:
|
||
CARGO_TERM_COLOR: always
|
||
# Network-flake resilience: retry transient registry/DNS failures at the tool
|
||
# level so a blip fetching crates.io / PyPI inside any build step (cargo,
|
||
# maturin, pip) retries automatically instead of failing the job. Cargo treats
|
||
# "couldn't resolve host" / connect / timeout as spurious and retries with
|
||
# backoff; 10 attempts ride out a transient DNS blip on a runner.
|
||
CARGO_NET_RETRY: "10"
|
||
CARGO_NET_GIT_FETCH_WITH_CLI: "true"
|
||
npm_config_fetch_retries: "5"
|
||
npm_config_fetch_retry_maxtimeout: "120000"
|
||
PIP_RETRIES: "5"
|
||
PIP_DEFAULT_TIMEOUT: "120"
|
||
|
||
jobs:
|
||
cross-library-bench:
|
||
name: Cross-library benchmark report
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||
with:
|
||
persist-credentials: false
|
||
|
||
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable branch, 2026-03-27
|
||
|
||
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
|
||
continue-on-error: true # cache is an optimisation; never block on a stuck/slow restore
|
||
timeout-minutes: 6
|
||
|
||
- name: Set up Python
|
||
id: setup_python
|
||
continue-on-error: true
|
||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||
with:
|
||
python-version: "3.11"
|
||
cache: pip
|
||
cache-dependency-path: .github/requirements/bench.txt
|
||
|
||
- name: Wait before Python retry
|
||
if: steps.setup_python.outcome == 'failure'
|
||
shell: bash
|
||
run: |
|
||
echo "::warning::setup-python failed (likely CDN flake), waiting 30s before retry..."
|
||
sleep 30
|
||
|
||
- name: Set up Python (retry)
|
||
if: steps.setup_python.outcome == 'failure'
|
||
uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
|
||
with:
|
||
python-version: "3.11"
|
||
cache: pip
|
||
cache-dependency-path: .github/requirements/bench.txt
|
||
|
||
- name: Install Python deps + peer libs
|
||
run: |
|
||
python -m pip install --upgrade pip
|
||
# Hash-locked deps (OpenSSF Scorecard PinnedDependencies). bench.yml
|
||
# runs on a single Python version (3.11), so one lock file suffices.
|
||
python -m pip install --require-hashes -r .github/requirements/bench.txt
|
||
|
||
- name: Build Wickra wheel
|
||
working-directory: bindings/python
|
||
run: maturin build --release --out dist
|
||
|
||
- name: Install Wickra wheel
|
||
working-directory: bindings/python
|
||
run: python -m pip install --find-links dist --force-reinstall wickra
|
||
|
||
- name: Run cross-library benchmark
|
||
working-directory: bindings/python
|
||
# workflow_dispatch inputs are untrusted; pass them through the
|
||
# environment and quote them rather than interpolating into the shell
|
||
# command (OpenSSF Scorecard: Dangerous-Workflow).
|
||
env:
|
||
BENCH_SIZE: ${{ github.event.inputs.size || '20000' }}
|
||
BENCH_ITERATIONS: ${{ github.event.inputs.iterations || '10' }}
|
||
run: |
|
||
python -m benchmarks.compare_libraries \
|
||
--size "$BENCH_SIZE" \
|
||
--iterations "$BENCH_ITERATIONS" \
|
||
--streaming-window 5000 --streaming-iterations 2 \
|
||
| tee benchmark.txt
|
||
|
||
- name: Upload report
|
||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||
with:
|
||
name: cross-library-bench
|
||
path: bindings/python/benchmark.txt
|