From fa749414fcab366401093824cfca18edc148c4d9 Mon Sep 17 00:00:00 2001 From: samuelburnham <45365069+samuelburnham@users.noreply.github.com> Date: Sat, 15 Aug 2026 08:45:42 -0400 Subject: [PATCH 1/4] ci: Update repo-sync workflow --- .github/workflows/repo-sync.yml | 37 ++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/.github/workflows/repo-sync.yml b/.github/workflows/repo-sync.yml index 8590677..9a6bb12 100644 --- a/.github/workflows/repo-sync.yml +++ b/.github/workflows/repo-sync.yml @@ -7,27 +7,36 @@ on: repository: required: true type: string - source-branch: - required: false - default: 'main' - type: string - dest-branch: - required: false + # `gh repo sync` takes a single branch name, so the upstream and the + # mirror must share it. + branch: + required: false default: 'main' type: string + secrets: + TOKEN_APP_ID: + required: true + TOKEN_APP_PRIVATE_KEY: + required: true + +# `secrets.GITHUB_TOKEN` cannot carry the `workflow` scope, so it is rejected +# whenever an upstream commit touches `.github/workflows/**`. A GitHub App +# installation token with Workflows: write can push those commits. +permissions: {} jobs: repo-sync: name: Sync changes from upstream runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/create-github-app-token@v3 + id: generate-token with: - persist-credentials: false + app-id: ${{ secrets.TOKEN_APP_ID }} + private-key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} + # `github.repository` is the caller's repo, not this one, and the token is + # scoped to it by default. - name: repo-sync - uses: repo-sync/github-sync@v2 - with: - source_repo: "https://github.com/${{ inputs.repository }}.git" - source_branch: "${{ inputs.source-branch }}" - destination_branch: "${{ inputs.dest-branch }}" - github_token: ${{ secrets.GITHUB_TOKEN }} + run: gh repo sync ${{ github.repository }} --source ${{ inputs.repository }} --branch ${{ inputs.branch }} --force + env: + GH_TOKEN: ${{ steps.generate-token.outputs.token }} From 9f720f60c5cb6bf7a7b6e00eb0723bacf3f3815a Mon Sep 17 00:00:00 2001 From: samuelburnham <45365069+samuelburnham@users.noreply.github.com> Date: Mon, 24 Aug 2026 11:19:50 -0400 Subject: [PATCH 2/4] ci: Lint workflows, drop bench plotter and downstream-compiles crates Add an `actionlint` + `zizmor` composite action and a `lint.yml` that runs it over this repo, with config for the org's self-hosted runner labels and for the zizmor rules that don't apply here. Fix what those linters found: - Move `github.event.*` interpolations into `env:` in `bench-pr-comment.yml` and `gpu-bench.yml` so untrusted input can't be injected into `run:`. - Migrate the deprecated `tibdex/github-app-token` to `actions/create-github-app-token` in `typos.yml`, and request explicit token permissions there and in `repo-sync.yml`. - Quote the `FILE_PATHS` assignment in `typos.yml`. - Drop `if $(...)` command substitution in `lints.yml`. - Remove the `type:` key from a composite action input, which Actions does not support. Remove the `benchmark-plotter` and `check-downstream-compiles` crates along with their only consumers, `bench-deploy.yml`, `ci.yml`, and the `check-downstream-compiles` action. Give Dependabot a 7-day cooldown before opening update PRs. --- .github/actionlint.yaml | 5 + .../check-downstream-compiles/action.yml | 52 ---- .github/actions/gpu-setup/action.yml | 1 - .github/actions/lint-workflows/action.yml | 35 +++ .github/dependabot.yml | 4 +- .github/workflows/actions-lint.yml | 24 ++ .github/workflows/bench-deploy.yml | 139 ----------- .github/workflows/bench-pr-comment.yml | 4 +- .github/workflows/ci.yml | 48 ---- .github/workflows/gpu-bench.yml | 4 +- .github/workflows/lints.yml | 2 +- .github/workflows/repo-sync.yml | 2 + .github/workflows/typos.yml | 10 +- .github/zizmor.yml | 14 ++ crates/benchmark-plotter/Cargo.toml | 21 -- crates/benchmark-plotter/build.rs | 8 - crates/benchmark-plotter/rust-toolchain.toml | 4 - crates/benchmark-plotter/src/json.rs | 147 ----------- crates/benchmark-plotter/src/main.rs | 114 --------- crates/benchmark-plotter/src/plot.rs | 235 ------------------ .../.cargo/config.toml | 50 ---- crates/check-downstream-compiles/Cargo.toml | 12 - crates/check-downstream-compiles/src/main.rs | 189 -------------- 23 files changed, 96 insertions(+), 1028 deletions(-) create mode 100644 .github/actionlint.yaml delete mode 100644 .github/actions/check-downstream-compiles/action.yml create mode 100644 .github/actions/lint-workflows/action.yml create mode 100644 .github/workflows/actions-lint.yml delete mode 100644 .github/workflows/bench-deploy.yml delete mode 100644 .github/workflows/ci.yml create mode 100644 .github/zizmor.yml delete mode 100644 crates/benchmark-plotter/Cargo.toml delete mode 100644 crates/benchmark-plotter/build.rs delete mode 100644 crates/benchmark-plotter/rust-toolchain.toml delete mode 100644 crates/benchmark-plotter/src/json.rs delete mode 100644 crates/benchmark-plotter/src/main.rs delete mode 100644 crates/benchmark-plotter/src/plot.rs delete mode 100644 crates/check-downstream-compiles/.cargo/config.toml delete mode 100644 crates/check-downstream-compiles/Cargo.toml delete mode 100644 crates/check-downstream-compiles/src/main.rs diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml new file mode 100644 index 0000000..7a9720b --- /dev/null +++ b/.github/actionlint.yaml @@ -0,0 +1,5 @@ +# Labels of the org's self-hosted runners, which actionlint cannot know about. +self-hosted-runner: + labels: + - gpu-bench + - gpu-ci diff --git a/.github/actions/check-downstream-compiles/action.yml b/.github/actions/check-downstream-compiles/action.yml deleted file mode 100644 index 0c94c03..0000000 --- a/.github/actions/check-downstream-compiles/action.yml +++ /dev/null @@ -1,52 +0,0 @@ -# Default use case: run on `pull_request` and check the changes don't break a downstream crate -name: Check downstream compiles - -description: Patch dependent crate with upstream changes and check it builds - -inputs: - # Path to the upstream repo relative to `${{ github.workspace }}` - upstream-path: - description: 'path to upstream repo' - required: true - type: string - # Path to the downstream repo relative to `${{ github.workspace }}` - downstream-path: - description: 'Path to upstream repo' - required: true - type: string - # `[patch.]`, defaults to HTTPS URL from upstream caller repo - patch-type: - description: 'Patch with HTTPS, SSH, or crates.io' - required: false - default: 'https' - type: string - features: - description: 'Features to check in addition to the default' - required: false - type: string - -runs: - using: "composite" - steps: - - name: Set env - run: | - if [[ ! -z "${{ inputs.features }}" ]]; then - FEATURES="--features ${{ inputs.features }}" - else - FEATURES="" - fi - echo "FEATURES=$FEATURES" | tee -a $GITHUB_ENV - shell: bash - # Assumes at least one dependency in the current workspace is used by the downstream crate - - name: Patch Cargo.toml files in the downstream repo with all uses of the upstream-repo - shell: bash - working-directory: ${{ github.workspace }}/ci-workflows/crates/check-downstream-compiles - run: | - cargo run -- --upstream ${{ github.workspace }}/${{ inputs.upstream-path }} --downstream ${{ github.workspace }}/${{ inputs.downstream-path }} --repo ${{ github.repository }} --patch-type ${{ inputs.patch-type }} - env: - RUST_LOG: "debug" - - name: Check downstream types don't break spectacularly - shell: bash - working-directory: ${{ github.workspace }}/${{ inputs.downstream-path }} - run: | - cargo check --workspace --all-targets ${{ env.FEATURES }} diff --git a/.github/actions/gpu-setup/action.yml b/.github/actions/gpu-setup/action.yml index 884f235..3566d1d 100644 --- a/.github/actions/gpu-setup/action.yml +++ b/.github/actions/gpu-setup/action.yml @@ -8,7 +8,6 @@ inputs: description: 'cuda or opencl' required: false default: 'cuda' - type: string runs: using: "composite" diff --git a/.github/actions/lint-workflows/action.yml b/.github/actions/lint-workflows/action.yml new file mode 100644 index 0000000..78c151e --- /dev/null +++ b/.github/actions/lint-workflows/action.yml @@ -0,0 +1,35 @@ +# Assumes the repo under test is already checked out. +name: Lint workflows + +description: Run actionlint and zizmor over a repo's workflows and composite actions + +inputs: + # actionlint pipes every `run:` block through shellcheck, whose info- and + # style-level findings are mostly noise in workflow scripts. + shellcheck-severity: + description: 'Minimum shellcheck severity actionlint reports: error, warning, info, or style' + required: false + default: 'warning' + # Left empty, zizmor discovers `.github/zizmor.yml` in the repo being linted. + zizmor-config: + description: 'Path to a zizmor config file' + required: false + zizmor-advisory: + description: 'Report zizmor findings without failing the job' + required: false + default: 'true' + +runs: + using: composite + steps: + - uses: raven-actions/actionlint@v2 + env: + SHELLCHECK_OPTS: -S ${{ inputs.shellcheck-severity }} + - uses: zizmorcore/zizmor-action@v0.6.2 + continue-on-error: ${{ inputs.zizmor-advisory == 'true' }} + with: + config: ${{ inputs.zizmor-config }} + # Mutually exclusive with `annotations`; the Security tab needs + # `security-events: write` from the calling job. + advanced-security: false + annotations: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 120c689..a1203f0 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,4 +3,6 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: - interval: "weekly" \ No newline at end of file + interval: "weekly" + cooldown: + default-days: 7 \ No newline at end of file diff --git a/.github/workflows/actions-lint.yml b/.github/workflows/actions-lint.yml new file mode 100644 index 0000000..a08d943 --- /dev/null +++ b/.github/workflows/actions-lint.yml @@ -0,0 +1,24 @@ +# Lints this repo's own workflows and composite actions +name: Lint + +on: + push: + branches: main + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + lint: + name: Lint workflows + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - uses: ./.github/actions/lint-workflows diff --git a/.github/workflows/bench-deploy.yml b/.github/workflows/bench-deploy.yml deleted file mode 100644 index 3a7a4f4..0000000 --- a/.github/workflows/bench-deploy.yml +++ /dev/null @@ -1,139 +0,0 @@ -# Intended to run on the `push` trigger -# Pre-requisites -# - `gh-pages` branch with Pages deployment set up -# - Ideally some HTML to link to the reports, e.g. https://argumentcomputer.github.io/ci-lab/ -# - Self-hosted runner attached to the caller repo with `gpu-bench` and `gh-pages` tags -# - `justfile` with a `gpu-bench-ci` recipe that outputs `-.json` -name: Deploy GPU benchmark from default branch - -on: - workflow_call: - inputs: - # Leave as default for lurk-rs, input `ARECIBO` for arecibo - env-prefix: - required: false - default: 'LURK' - type: string - # List of prerequisite Ubuntu packages, separated by whitespace - packages: - required: false - type: string - -jobs: - benchmark: - name: Bench and deploy - runs-on: [self-hosted, gpu-bench, gh-pages] - steps: - - uses: actions/checkout@v4 - with: - repository: argumentcomputer/ci-workflows - - uses: ./.github/actions/gpu-setup - with: - gpu-framework: 'cuda' - - uses: ./.github/actions/ci-env - - uses: ./.github/actions/install-deps - if: inputs.packages != '' - with: - packages: "${{ inputs.packages }}" - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - - uses: taiki-e/install-action@v2 - with: - tool: just@1.22.0 - # Run benchmarks and deploy - - name: Get old benchmarks - uses: actions/checkout@v4 - with: - ref: gh-pages - path: gh-pages - - name: Install criterion - run: cargo install cargo-criterion - - name: Copy old benchmarks locally for comparison - run: | - mkdir -p target gh-pages/benchmarks/criterion - cp -r gh-pages/benchmarks/criterion target - # Make sure to set repo-specific env vars in the `justfile`/`bench.env`, e.g. `LURK_RC` - - name: Set env vars - run: | - echo "COMMIT=$(git rev-parse --short HEAD)" | tee -a $GITHUB_ENV - echo "${{ inputs.env-prefix }}_BENCH_OUTPUT=gh-pages" | tee -a $GITHUB_ENV - - name: Run benchmarks - run: | - just gpu-bench-ci fibonacci - mv fibonacci-${{ env.COMMIT }}.json .. - working-directory: ${{ github.workspace }}/benches - # If no plot data found, unzip all historical bench results to re-create the plots - - name: Check for existing plot data - run: | - if [ ! -f "plot-data.json" ]; then - shopt -s nullglob # Make glob patterns that match no files expand to a null string - tarballs=(./*.tar.gz) - if (( ${#tarballs[@]} )); then - cat "${tarballs[@]}" | tar -xvzf - -i - else - echo "No tarballs found for extraction." - fi - shopt -u nullglob # Disable nullglob option - fi - # TODO: This should probably be in a subdirectory or Cargo workspace - # Saves the plot data to be deployed - - name: Generate historical performance plot - run: | - cargo run - mkdir -p history - mv -f plot-data.json history - # TODO: Prettify labels for easier viewing - # Compress the benchmark file and metadata for later analysis - - name: Compress artifacts - run: | - echo $LABELS > labels.md - tar -cvzf fibonacci-${{ env.COMMIT }}.tar.gz Cargo.lock fibonacci-${{ env.COMMIT }}.json labels.md - mv -f fibonacci-${{ env.COMMIT }}.tar.gz history - working-directory: ${{ github.workspace }} - # TODO: Arguably the HTML template should be a pre-requisite - - name: Prepare HTML plots page - run: | - if [[ ! -f plots.html ]]; then - html=$(cat << EOF - - - - - - - - - EOF - ) - echo "$html" > plots.html - fi - - shopt -s nullglob # Prevent errors if no matching files are found - - for FILE in `ls *.png | sort -g`; do - if [[ -f $FILE ]]; then # Check if it's a regular file - IMAGE="\"Benchmark" - echo $IMAGE - sed -i "/<\/body>/i\\$IMAGE" plots.html - fi - done - - mv -f *.png plots.html history - - name: Deploy latest benchmark report - uses: peaceiris/actions-gh-pages@v4 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./target/criterion - destination_dir: benchmarks/criterion - - name: Deploy benchmark history - uses: peaceiris/actions-gh-pages@v4 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - publish_dir: ./history - destination_dir: benchmarks/history - keep_files: true diff --git a/.github/workflows/bench-pr-comment.yml b/.github/workflows/bench-pr-comment.yml index 3b431c2..fa6cb8e 100644 --- a/.github/workflows/bench-pr-comment.yml +++ b/.github/workflows/bench-pr-comment.yml @@ -76,9 +76,11 @@ jobs: echo "EOF" >> $GITHUB_OUTPUT - name: Parse PR comment body id: bench-params + env: + COMMENT_BODY: ${{ github.event.comment.body }} run: | # Parse `issue_comment` body - printf '${{ github.event.comment.body }}' > comment.txt + printf '%s' "$COMMENT_BODY" > comment.txt BENCH_COMMAND=$(head -n 1 comment.txt) echo "$BENCH_COMMAND" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 9ae90a3..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: CI Tests - -on: - push: - branches: main - pull_request: - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - test: - name: CI Test Suite - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - repository: argumentcomputer/ci-workflows - - uses: ./.github/actions/ci-env - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - - uses: taiki-e/install-action@nextest - - name: Run tests - run: cargo nextest run - working-directory: ${{ github.workspace }}/crates/check-downstream-compiles - - clippy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - repository: argumentcomputer/ci-workflows - - uses: ./.github/actions/ci-env - - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - - name: Check Rustfmt Code Style - run: cargo fmt --all --check - working-directory: ${{ github.workspace }}/crates/check-downstream-compiles - - name: check *everything* compiles - run: cargo check --all-targets --all-features --all --examples --tests --benches - working-directory: ${{ github.workspace }}/crates/check-downstream-compiles - # See '.cargo/config' for list of enabled/disabled clippy lints - - name: Check clippy warnings - run: cargo xclippy -D warnings - working-directory: ${{ github.workspace }}/crates/check-downstream-compiles diff --git a/.github/workflows/gpu-bench.yml b/.github/workflows/gpu-bench.yml index 4885be0..2b17da0 100644 --- a/.github/workflows/gpu-bench.yml +++ b/.github/workflows/gpu-bench.yml @@ -125,8 +125,10 @@ jobs: continue-on-error: true # Not possible to use ${{ github.event.number }} with the `merge_group` trigger - name: Get PR number from merge branch + env: + HEAD_REF: ${{ github.event.merge_group.head_ref }} run: | - echo "PR_NUMBER=$(echo ${{ github.event.merge_group.head_ref }} | sed -e 's/.*pr-\(.*\)-.*/\1/')" | tee -a $GITHUB_ENV + echo "PR_NUMBER=$(echo "$HEAD_REF" | sed -e 's/.*pr-\(.*\)-.*/\1/')" | tee -a $GITHUB_ENV - name: Create file for issue if: steps.regression-check.outcome == 'failure' run: | diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index 26787a3..adee252 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -45,7 +45,7 @@ jobs: fi - name: Check clippy warnings run: | - if $(cargo --list|grep -q xclippy); then + if cargo --list | grep -q xclippy; then cargo xclippy -Dwarnings else cargo clippy -Dwarnings diff --git a/.github/workflows/repo-sync.yml b/.github/workflows/repo-sync.yml index 9a6bb12..ae19146 100644 --- a/.github/workflows/repo-sync.yml +++ b/.github/workflows/repo-sync.yml @@ -34,6 +34,8 @@ jobs: with: app-id: ${{ secrets.TOKEN_APP_ID }} private-key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} + permission-contents: write + permission-workflows: write # `github.repository` is the caller's repo, not this one, and the token is # scoped to it by default. - name: repo-sync diff --git a/.github/workflows/typos.yml b/.github/workflows/typos.yml index 8a46f3d..c324b6b 100644 --- a/.github/workflows/typos.yml +++ b/.github/workflows/typos.yml @@ -46,14 +46,16 @@ jobs: if: steps.typo-check.outputs.typos == 'true' id: file-types run: | - FILE_PATHS=:!*\_body.md,$(git status --porcelain | awk -F. '{OFS=""; print "**/*."$NF}' | sort -u | paste -sd,) + FILE_PATHS=":!*\_body.md,$(git status --porcelain | awk -F. '{OFS=""; print "**/*."$NF}' | sort -u | paste -sd,)" echo "paths=$FILE_PATHS" | tee -a $GITHUB_OUTPUT - - uses: tibdex/github-app-token@v2 + - uses: actions/create-github-app-token@v3 if: steps.typo-check.outputs.typos == 'true' id: generate-token with: - app_id: ${{ secrets.TOKEN_APP_ID }} - private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} + app-id: ${{ secrets.TOKEN_APP_ID }} + private-key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} + permission-contents: write + permission-pull-requests: write - name: Create pull request uses: peter-evans/create-pull-request@v7 if: steps.typo-check.outputs.typos == 'true' diff --git a/.github/zizmor.yml b/.github/zizmor.yml new file mode 100644 index 0000000..72a2bc7 --- /dev/null +++ b/.github/zizmor.yml @@ -0,0 +1,14 @@ +rules: + # Every action here is version-pinned and tracked by Dependabot; hash-pinning + # is a posture this org has not adopted. + unpinned-uses: + disable: true + template-injection: + # These expand caller-supplied `inputs.*`, not attacker-supplied data. A + # caller that can set them can already write arbitrary steps of its own. + ignore: + - bench-pr-comment.yml + - gpu-ci-cuda.yml + - gpu-ci-opencl.yml + - repo-sync.yml + - unused-deps.yml diff --git a/crates/benchmark-plotter/Cargo.toml b/crates/benchmark-plotter/Cargo.toml deleted file mode 100644 index 3931797..0000000 --- a/crates/benchmark-plotter/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[package] -name = "benchmark-plotter" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -anyhow = "1.0" -# chrono version is pinned to be compatible with plotters `build_cartesian_2d` API -chrono = { version = "=0.4.20", features = ["clock", "serde"] } -plotters = "0.3.5" -serde = { version = "1.0.195", features = ["derive"] } -serde_json = "1.0.111" - -[dev-dependencies] -criterion = "0.4" -anyhow = "1.0" - -[build-dependencies] -vergen = { version = "8", features = ["build", "git", "gitcl"] } diff --git a/crates/benchmark-plotter/build.rs b/crates/benchmark-plotter/build.rs deleted file mode 100644 index 35aa44a..0000000 --- a/crates/benchmark-plotter/build.rs +++ /dev/null @@ -1,8 +0,0 @@ -use std::error::Error; -use vergen::EmitBuilder; - -fn main() -> Result<(), Box> { - // Emit the instructions - EmitBuilder::builder().all_git().emit()?; - Ok(()) -} diff --git a/crates/benchmark-plotter/rust-toolchain.toml b/crates/benchmark-plotter/rust-toolchain.toml deleted file mode 100644 index 0fe01f0..0000000 --- a/crates/benchmark-plotter/rust-toolchain.toml +++ /dev/null @@ -1,4 +0,0 @@ -[toolchain] -channel = "1.75.0" -targets = [ "wasm32-unknown-unknown" ] -profile = "default" diff --git a/crates/benchmark-plotter/src/json.rs b/crates/benchmark-plotter/src/json.rs deleted file mode 100644 index 1389560..0000000 --- a/crates/benchmark-plotter/src/json.rs +++ /dev/null @@ -1,147 +0,0 @@ -use core::fmt; -use std::io::Read; -use std::{fs::File, path::Path}; - -use serde::Deserialize; -use serde_json::de::{StrRead, StreamDeserializer}; -use serde_json::{Deserializer, Error, Value}; - -#[derive(Debug, Deserialize)] -pub struct BenchData { - pub id: BenchId, - #[serde(rename = "typical")] - pub result: BenchResult, -} - -#[derive(Debug)] -pub struct BenchId { - pub group_name: String, - pub bench_name: String, - pub params: String, -} - -// Assumes three `String` elements in a Criterion bench ID: // -// E.g. `Fibonacci-num=10/28db40f-2024-01-30T19:07:04-05:00/rc=100` -// Errors if a different format is found -impl<'de> Deserialize<'de> for BenchId { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - let id = s.split('/').collect::>(); - if id.len() != 3 { - Err(serde::de::Error::custom("Expected 3 bench ID elements")) - } else { - let bench_name = id[1].replace('_', ":"); - Ok(BenchId { - group_name: id[0].to_owned(), - // Criterion converts `:` to `_` in the timestamp as the former is valid JSON syntax, - // so we convert `_` back to `:` when deserializing - bench_name, - params: id[2].to_owned(), - }) - } - } -} - -#[derive(Debug, Deserialize)] -pub struct BenchResult { - #[serde(rename = "estimate")] - pub time: f64, -} - -// Deserializes the benchmark JSON file into structured data for plotting -pub fn read_json_from_file>(path: P) -> Result, Error> { - let mut file = File::open(path).unwrap(); - let mut s = String::new(); - file.read_to_string(&mut s).unwrap(); - - let mut data = vec![]; - for result in ResilientStreamDeserializer::::new(&s).flatten() { - data.push(result); - } - Ok(data) -} - -// The following code is taken from https://users.rust-lang.org/t/step-past-errors-in-serde-json-streamdeserializer/84228/10 -// The `ResilientStreamDeserializer` is a workaround to enable a `StreamDeserializer` to continue parsing when it encounters -// a deserialization type error or invalid JSON. See https://github.com/serde-rs/json/issues/70 for discussion -#[derive(Debug)] -pub struct JsonError { - error: Error, - value: Option, // Some(_) if JSON was syntactically valid -} - -impl fmt::Display for JsonError { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(formatter, "{}", self.error)?; - - if let Some(value) = self.value.as_ref() { - write!(formatter, ", value: {}", value)?; - } - - Ok(()) - } -} - -impl std::error::Error for JsonError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - Some(&self.error) - } -} - -pub struct ResilientStreamDeserializer<'de, T> { - json: &'de str, - stream: StreamDeserializer<'de, StrRead<'de>, T>, - last_ok_pos: usize, -} - -impl<'de, T> ResilientStreamDeserializer<'de, T> -where - T: Deserialize<'de>, -{ - pub fn new(json: &'de str) -> Self { - let stream = Deserializer::from_str(json).into_iter(); - let last_ok_pos = 0; - - ResilientStreamDeserializer { - json, - stream, - last_ok_pos, - } - } -} - -impl<'de, T> Iterator for ResilientStreamDeserializer<'de, T> -where - T: Deserialize<'de>, -{ - type Item = Result; - - fn next(&mut self) -> Option { - match self.stream.next()? { - Ok(value) => { - self.last_ok_pos = self.stream.byte_offset(); - Some(Ok(value)) - } - Err(error) => { - // If an error happened, check whether it's a type error, i.e. - // whether the next thing in the stream was at least valid JSON. - // If so, return it as a dynamically-typed `Value` and skip it. - let err_json = &self.json[self.last_ok_pos..]; - let mut err_stream = Deserializer::from_str(err_json).into_iter::(); - let value = err_stream.next()?.ok(); - let next_pos = if value.is_some() { - self.last_ok_pos + err_stream.byte_offset() - } else { - self.json.len() // when JSON has a syntax error, prevent infinite stream of errors - }; - self.json = &self.json[next_pos..]; - self.stream = Deserializer::from_str(self.json).into_iter(); - self.last_ok_pos = 0; - Some(Err(JsonError { error, value })) - } - } - } -} diff --git a/crates/benchmark-plotter/src/main.rs b/crates/benchmark-plotter/src/main.rs deleted file mode 100644 index 6a8d8df..0000000 --- a/crates/benchmark-plotter/src/main.rs +++ /dev/null @@ -1,114 +0,0 @@ -mod json; -mod plot; - -use std::{ - io::{self, Read, Write}, - path::PathBuf, -}; - -use anyhow::anyhow; -use json::read_json_from_file; - -use crate::plot::{generate_plots, Plots}; - -// TODO: Switch to camino -// Gets all JSON paths in the current directory, optionally ending in a given suffix -// E.g. if `suffix` is `abc1234.json` it will return "*abc1234.json" -fn get_json_paths(suffix: Option<&str>) -> std::io::Result> { - let suffix = suffix.unwrap_or(".json"); - let entries = std::fs::read_dir(".")? - .flatten() - .filter_map(|e| { - let ext = e.path(); - if ext.to_str()?.ends_with(suffix) { - Some(ext) - } else { - None - } - }) - .collect::>(); - Ok(entries) -} - -// Benchmark files to plot, e.g. `LURK_BENCH_FILES=fibonacci-abc1234,fibonacci-def5678` -fn bench_files_env() -> anyhow::Result> { - std::env::var("LURK_BENCH_FILES") - .map_err(|e| anyhow!("Benchmark files env var isn't set: {e}")) - .and_then(|commits| { - let vec: anyhow::Result> = commits - .split(',') - .map(|sha| { - sha.parse::() - .map_err(|e| anyhow!("Failed to parse Git commit string: {e}")) - }) - .collect(); - vec - }) -} - -// Deserializes JSON file into `Plots` type -fn read_plots_from_file() -> Result { - let path = std::path::Path::new("plot-data.json"); - - let mut file = std::fs::File::open(path)?; - - let mut s = String::new(); - file.read_to_string(&mut s)?; - - let plots: Plots = serde_json::from_str(&s)?; - - Ok(plots) -} - -// Serializes `Plots` type into file -fn write_plots_to_file(plot_data: &Plots) -> Result<(), io::Error> { - let path = std::path::Path::new("plot-data.json"); - - let mut file = std::fs::File::create(path)?; - - let json_data = serde_json::to_string(&plot_data)?; - - file.write_all(json_data.as_bytes()) -} - -fn main() { - // If existing plot data is found on disk, only read and add benchmark files specified by `LURK_BENCH_FILES` - // Data is stored in a `HashMap` so duplicates are ignored - let (mut plots, bench_files) = { - if let Ok(plots) = read_plots_from_file() { - // The user should know which files they just benchmarked and want to add to the plot - // Otherwise defaults to all files containing the current Git commit - let bench_files = bench_files_env().map_or_else( - |_| { - let mut short_sha = env!("VERGEN_GIT_SHA").to_owned(); - short_sha.truncate(7); - get_json_paths(Some(&format!("{}.json", short_sha))) - .expect("Failed to read JSON paths") - }, - |files| { - files - .iter() - .map(|file| PathBuf::from(format!("{}.json", file))) - .collect() - }, - ); - (plots, bench_files) - } - // If no plot data exists, read all `JSON` files in the current directory and save to disk - else { - let paths = get_json_paths(None).expect("Failed to read JSON paths"); - (Plots::new(), paths) - } - }; - println!("Adding bench files to plot: {:?}", bench_files); - let mut bench_data = vec![]; - for file in bench_files { - let mut data = read_json_from_file(file).expect("JSON serde error"); - bench_data.append(&mut data); - } - plots.add_data(&bench_data); - - // Write to disk - write_plots_to_file(&plots).expect("Failed to write `Plots` to `plot-data.json`"); - generate_plots(&plots).unwrap(); -} diff --git a/crates/benchmark-plotter/src/plot.rs b/crates/benchmark-plotter/src/plot.rs deleted file mode 100644 index f9ab23f..0000000 --- a/crates/benchmark-plotter/src/plot.rs +++ /dev/null @@ -1,235 +0,0 @@ -use plotters::prelude::*; - -use chrono::{serde::ts_seconds, DateTime, Duration, Utc}; -use serde::{Deserialize, Serialize}; - -use std::{collections::HashMap, error::Error}; - -use crate::json::BenchData; - -// TODO: Figure out how to include the commit hash as a label on the point or X-axis -pub fn generate_plots(data: &Plots) -> Result<(), Box> { - for plot in data.0.iter() { - let out_file_name = format!("./{}.png", plot.0); - let root = BitMapBackend::new(&out_file_name, (1024, 768)).into_drawing_area(); - root.fill(&WHITE)?; - - let mut chart = ChartBuilder::on(&root) - .margin(10) - .caption(plot.0, ("sans-serif", 40)) - .set_label_area_size(LabelAreaPosition::Left, 60) - .set_label_area_size(LabelAreaPosition::Bottom, 40) - .build_cartesian_2d( - // Add one day buffer before and after - plot.1 - .x_axis - .min - .checked_sub_signed(Duration::days(1)) - .expect("DateTime underflow") - ..plot - .1 - .x_axis - .max - .checked_add_signed(Duration::days(1)) - .expect("DateTime overflow"), - // Add 0.2 ns buffer before and after (not rigorous, based on a priori knowledge of Y axis units & values) - plot.1.y_axis.min - 0.2f64..plot.1.y_axis.max + 0.2f64, - )?; - - chart - .configure_mesh() - .disable_x_mesh() - .disable_y_mesh() - .x_labels(10) - .max_light_lines(4) - .x_desc("Commit Date") - .y_desc("Time (ns)") - .draw()?; - - // Draws the lines of benchmark data points, one line/color per set of bench ID params e.g. `rc=100` - for (i, line) in plot.1.lines.iter().enumerate() { - // Draw lines between each point - chart - .draw_series(LineSeries::new( - line.1.iter().map(|p| (p.x, p.y)), - Palette99::pick(i), - ))? - .label(line.0) - // TODO: Move the legend out of the plot area - .legend(move |(x, y)| { - Rectangle::new( - [(x - 5, y - 5), (x + 5, y + 5)], - Palette99::pick(i).filled(), - ) - }); - - // Draw dots on each point - chart.draw_series( - line.1 - .iter() - .map(|p| Circle::new((p.x, p.y), 3, Palette99::pick(i).filled())), - )?; - chart - .configure_series_labels() - .background_style(WHITE) - .border_style(BLACK) - .draw()?; - } - - // To avoid the IO failure being ignored silently, we manually call the present function - root.present().expect("Unable to write result to file"); - println!("Result has been saved to {}", out_file_name); - } - - Ok(()) -} - -// Convert - to a `DateTime` object, discarding `short-sha` -fn str_to_datetime(input: &str) -> Result, Box> { - // Removes the first 8 chars (assuming UTF8) for the `short-sha` and trailing '-' - let datetime: &str = input.split_at(8).1; - - DateTime::parse_from_rfc3339(datetime).map_or_else( - |e| Err(format!("Failed to parse string into `DateTime`: {}", e).into()), - |dt| Ok(dt.with_timezone(&Utc)), - ) -} - -// Plots of benchmark results over time/Git history. This data structure is persistent between runs, -// saved to disk in `plot-data.json`, and is meant to be append-only to preserve historical results. -// -// Note: -// Plots are separated by benchmark input e.g. `Fibonacci-num-100`. It doesn't reveal much -// information to view multiple benchmark input results on the same graph (e.g. fib-10 and fib-20), -// since they are expected to be different. Instead, we group different benchmark parameters -// (e.g. `rc` value) onto the same graph to compare/contrast their impact on performance. -#[derive(Debug, Serialize, Deserialize)] -pub struct Plots(HashMap); - -impl Plots { - pub fn new() -> Self { - Self(HashMap::new()) - } - - // Converts a list of deserialized Criterion benchmark results into a plotting-friendly format, - // and adds the data to the `Plots` struct. - pub fn add_data(&mut self, bench_data: &Vec) { - for bench in bench_data { - let commit_date = str_to_datetime(&bench.id.bench_name).expect("Timestamp parse error"); - let point = Point { - x: commit_date, - y: bench.result.time, - }; - - if self.0.get(&bench.id.group_name).is_none() { - self.0.insert(bench.id.group_name.to_owned(), Plot::new()); - } - let plot = self.0.get_mut(&bench.id.group_name).unwrap(); - - plot.x_axis.set_min_max(commit_date); - plot.y_axis.set_min_max(point.y); - - if plot.lines.get(&bench.id.params).is_none() { - plot.lines.insert(bench.id.params.to_owned(), vec![]); - } - plot.lines.get_mut(&bench.id.params).unwrap().push(point); - } - // Sort each data point in each line for each plot - for plot in self.0.iter_mut() { - for line in plot.1.lines.iter_mut() { - line.1.sort_by(|a, b| a.partial_cmp(b).unwrap()); - } - } - } -} - -// The data type for a plot: contains the range of X and Y values, and the line(s) to be drawn -#[derive(Debug, Serialize, Deserialize)] -pub struct Plot { - x_axis: XAxisRange, - y_axis: YAxisRange, - lines: HashMap>, -} - -impl Plot { - pub fn new() -> Self { - Self { - x_axis: XAxisRange::default(), - y_axis: YAxisRange::default(), - lines: HashMap::new(), - } - } -} - -// Historical benchmark result, showing the performance at a given Git commit -#[derive(Debug, Serialize, Deserialize, PartialEq, PartialOrd)] -pub struct Point { - // Commit timestamp associated with benchmark - x: DateTime, - // Benchmark time (avg.) - y: f64, -} - -// Min. and max. X axis values for a given plot -#[derive(Debug, Serialize, Deserialize)] -pub struct XAxisRange { - #[serde(with = "ts_seconds")] - min: DateTime, - #[serde(with = "ts_seconds")] - max: DateTime, -} - -// Starts with flipped min/max so they can be set by `Point` values as they are encountered -impl Default for XAxisRange { - fn default() -> Self { - Self { - min: Utc::now(), - max: chrono::DateTime::::MIN_UTC, - } - } -} - -// Min. and max. Y axis values for a given plot -#[derive(Debug, Serialize, Deserialize)] -pub struct YAxisRange { - min: f64, - max: f64, -} - -// Starts with flipped min/max so they can be set by `Point` values as they are encountered -impl Default for YAxisRange { - fn default() -> Self { - Self { - min: f64::MAX, - max: f64::MIN, - } - } -} - -// Checks if input is < the current min and/or > current max -// If so, sets input as the new min and/or max respectively -trait MinMax { - fn set_min_max(&mut self, value: T); -} - -impl MinMax> for XAxisRange { - fn set_min_max(&mut self, value: DateTime) { - if value < self.min { - self.min = value - } - if value > self.max { - self.max = value - } - } -} - -impl MinMax for YAxisRange { - fn set_min_max(&mut self, value: f64) { - if value < self.min { - self.min = value - } - if value > self.max { - self.max = value - } - } -} diff --git a/crates/check-downstream-compiles/.cargo/config.toml b/crates/check-downstream-compiles/.cargo/config.toml deleted file mode 100644 index 0e515fd..0000000 --- a/crates/check-downstream-compiles/.cargo/config.toml +++ /dev/null @@ -1,50 +0,0 @@ -[alias] -# Collection of project wide clippy lints. This is done via an alias because -# clippy doesn't currently allow for specifiying project-wide lints in a -# configuration file. This is a similar workaround to the ones presented here: -# -xclippy = [ - "clippy", "--workspace", "--all-targets", "--all-features", "--", - "-Wclippy::all", - "-Wclippy::cast_lossless", - "-Wclippy::checked_conversions", - "-Wclippy::dbg_macro", - "-Wclippy::disallowed_methods", - "-Wclippy::derive_partial_eq_without_eq", - "-Wclippy::enum_glob_use", - "-Wclippy::explicit_into_iter_loop", - "-Wclippy::fallible_impl_from", - "-Wclippy::filter_map_next", - "-Wclippy::flat_map_option", - "-Wclippy::from_iter_instead_of_collect", - "-Wclippy::implicit_clone", - "-Wclippy::inefficient_to_string", - "-Wclippy::invalid_upcast_comparisons", - "-Wclippy::large_stack_arrays", - "-Wclippy::large_types_passed_by_value", - "-Wclippy::macro_use_imports", - "-Wclippy::manual_assert", - "-Wclippy::manual_ok_or", - "-Wclippy::map_flatten", - "-Wclippy::map_unwrap_or", - "-Wclippy::match_same_arms", - "-Wclippy::match_wild_err_arm", - "-Wclippy::missing_const_for_fn", - "-Wclippy::needless_borrow", - "-Wclippy::needless_continue", - "-Wclippy::needless_for_each", - "-Wclippy::needless_pass_by_value", - "-Wclippy::option_option", - "-Wclippy::same_functions_in_if_condition", - "-Wclippy::single_match_else", - "-Wclippy::trait_duplication_in_bounds", - "-Wclippy::unnecessary_wraps", - "-Wclippy::unnested_or_patterns", - "-Wnonstandard_style", - "-Wrust_2018_idioms", - "-Wtrivial_numeric_casts", - "-Wunused_lifetimes", - "-Wunreachable_pub", - "-Wtrivial_numeric_casts", - "-Wunused_qualifications", -] diff --git a/crates/check-downstream-compiles/Cargo.toml b/crates/check-downstream-compiles/Cargo.toml deleted file mode 100644 index 870b51b..0000000 --- a/crates/check-downstream-compiles/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "check-downstream-compiles" -version = "0.1.0" -edition = "2021" - -[dependencies] -camino = "1.1.7" -clap = { version = "4.5.13", features = ["derive"] } -env_logger = "0.11.5" -log = "0.4.22" -toml_edit = "0.22.20" -walkdir = "2.5.0" diff --git a/crates/check-downstream-compiles/src/main.rs b/crates/check-downstream-compiles/src/main.rs deleted file mode 100644 index 46b591e..0000000 --- a/crates/check-downstream-compiles/src/main.rs +++ /dev/null @@ -1,189 +0,0 @@ -use std::collections::BTreeMap; -use std::fs; - -use camino::Utf8PathBuf; -use clap::{Parser, ValueEnum}; -use log::debug; -use toml_edit::{value, DocumentMut, Item, Table}; -use walkdir::WalkDir; - -/// CLI to patch a downstream repo and check it compiles -#[derive(Parser, Debug)] -#[command(version, about, long_about = None)] -struct Args { - /// Path to upstream crate - #[arg(long)] - upstream: String, - - /// Path to downstream crate - #[arg(long)] - downstream: String, - - /// The type of patch in `[patch.]` - #[arg(long, value_enum, default_value_t = PatchType::default())] - patch_type: PatchType, - - /// The org/repo name to be patched via GitHub URL, e.g. argumentcomputer/sphinx - #[arg(long)] - repo: String, -} - -#[derive(Debug, Clone, Default, ValueEnum)] -enum PatchType { - // TODO - CratesIO, - Ssh, - #[default] - Https, -} - -fn main() { - env_logger::init(); - let args = Args::parse(); - - let mut upstream_packages: BTreeMap = BTreeMap::new(); - - // Get all the upstream crates and their paths - for entry in WalkDir::new(args.upstream) - .into_iter() - .filter_map(|e| e.ok()) - { - let path = entry.path(); - if let Some(file_name) = path.file_name() { - if file_name == "Cargo.toml" { - let dir = path.parent().expect("No parent for Cargo.toml"); - let cargo_toml_content = fs::read_to_string(path).expect("FS err"); - let doc = cargo_toml_content - .parse::() - .expect("Parse err"); - if let Some(package) = doc.get("package") { - if let Some(name) = package.get("name") { - let dep_name = name.as_str().unwrap().to_string(); - upstream_packages.insert( - dep_name, - Utf8PathBuf::from_path_buf(dir.to_owned()).unwrap(), - ); - } - } - } - } - } - - let mut downstream_packages: BTreeMap = BTreeMap::new(); - - // Get all the upstream crates that are used in the downstream repo - for entry in WalkDir::new(&args.downstream) - .into_iter() - .filter_map(|e| e.ok()) - { - let path = entry.path(); - if let Some(file_name) = path.file_name() { - if file_name == "Cargo.toml" { - let cargo_toml_content = fs::read_to_string(path).expect("FS err"); - let doc = cargo_toml_content - .parse::() - .expect("Parse err"); - - if let Some(Item::Table(workspace_table)) = doc.get("workspace") { - if let Some(Item::Table(dep_table)) = workspace_table.get("dependencies") { - get_downstream_deps( - dep_table, - &upstream_packages, - &mut downstream_packages, - ); - } - } - if let Some(Item::Table(dep_table)) = doc.get("dependencies") { - get_downstream_deps(dep_table, &upstream_packages, &mut downstream_packages); - } - } - } - } - - debug!("downstream packages: {downstream_packages:?}"); - - let patch_str = patch_string(&args.patch_type, &args.repo); - - // Patch each downstream crate with the upstream crates - // Iterate through each crate in the downstream workspace - // Read each Cargo.toml file into toml_edit - // Write the patches for each patch in downstream_packages - for entry in WalkDir::new(&args.downstream) - .into_iter() - .filter_map(|e| e.ok()) - { - let path = entry.path(); - if let Some(file_name) = path.file_name() { - if file_name == "Cargo.toml" { - let cargo_toml_content = fs::read_to_string(path).expect("FS err"); - let mut doc = cargo_toml_content - .parse::() - .expect("Parse err"); - - // Ensure [patch.] table exists, create it if it doesn't - if let Some(Item::Table(patch)) = doc.get_mut("patch") { - if let Some(Item::Table(patch_table)) = patch.get_mut(&patch_str) { - // Add entries to the existing [patch.] table - for (pkg, dir) in downstream_packages.iter() { - add_patch(patch_table, pkg, dir.as_str()); - } - } else { - // Create the [patch.] table and add entries - let mut patch_table = Table::new(); - for (pkg, dir) in downstream_packages.iter() { - add_patch(&mut patch_table, pkg, dir.as_str()); - } - patch[&patch_str] = Item::Table(patch_table); - } - } else { - // Create the [patch] table, then the [patch.] table and add entries - let mut patch = Table::new(); - patch.set_implicit(true); - let mut patch_table = Table::new(); - for (pkg, dir) in downstream_packages.iter() { - add_patch(&mut patch_table, pkg, dir.as_str()); - } - patch[&patch_str] = Item::Table(patch_table); - doc["patch"] = Item::Table(patch); - } - - debug!("File: {path:?}\n{doc}"); - - fs::write(path, doc.to_string()).expect("Failed to write"); - } - } - } -} - -fn get_downstream_deps( - deps: &Table, - upstream_packages: &BTreeMap, - downstream_packages: &mut BTreeMap, -) { - for (dep_name, dep_value) in deps.iter() { - if let Some(table) = dep_value.as_inline_table() { - if table.get("git").is_some() { - if let Some(dir) = upstream_packages.get(dep_name) { - downstream_packages.insert(dep_name.to_owned(), dir.clone()); - } - } - } - } -} - -// TODO: Clean this up with a From/Display impl -fn patch_string(patch_type: &PatchType, repo: &str) -> String { - match patch_type { - PatchType::CratesIO => String::from("crates-io"), - PatchType::Ssh => format!("ssh://git@github.com/{repo}"), - PatchType::Https => format!("https://github.com/{repo}"), - } -} - -fn add_patch(patch_table: &mut Table, dep: &str, path: &str) { - patch_table[dep]["path"] = value(path); - patch_table[dep] - .as_inline_table_mut() - .unwrap() //_or_else(|| bail!("Failed to get mutable table for {dep}")) - .fmt(); -} From 426861b844be8c383028d43750b912a2fbcf171a Mon Sep 17 00:00:00 2001 From: samuelburnham <45365069+samuelburnham@users.noreply.github.com> Date: Mon, 24 Aug 2026 12:13:13 -0400 Subject: [PATCH 3/4] ci: Fix zizmor findings across workflows and composite actions The new lint job surfaced ~200 findings in workflows and actions that predate it. Fix them rather than suppress them: - Move `inputs.*`, `env.*`, and `github.*` interpolations out of `run:` blocks and into `env:`, so untrusted values reach the shell as variables instead of being spliced into the script. Where a value is read back from `$GITHUB_ENV` it becomes a plain shell variable, and `github.sha`/`github.repository` use the runner's own `GITHUB_*` vars. - Set `persist-credentials: false` on checkouts that don't push. The primary checkout in `gpu-bench.yml` keeps its credentials, since `git-auto-commit-action` pushes with them; every other push path authenticates with an explicit token. - Annotate the remaining findings inline with a rationale: `GITHUB_ENV` writes that pass state between steps of a composite action, and `ncipollo/release-action`, whose `allowUpdates` behavior `gh release` does not provide. `continue-on-error` is silently ignored on composite action steps, so zizmor could never have been advisory as its input claimed. Drop the `zizmor-advisory` input and document that findings fail the caller. Rename `lint.yml` to `actions-lint.yml` to distinguish this repo's own workflow lint from the reusable `lints.yml` that consumers call. --- .github/actions/ci-env/action.yml | 5 +- .github/actions/gpu-setup/action.yml | 9 ++- .github/actions/install-deps/action.yml | 4 +- .github/actions/lint-workflows/action.yml | 8 +-- .github/actions/release-pr/action.yml | 86 ++++++++++++++--------- .github/actions/rust-version/action.yml | 30 +++++--- .github/actions/tag-release/action.yml | 32 ++++++--- .github/workflows/bench-pr-comment.yml | 23 ++++-- .github/workflows/check-lurk-compiles.yml | 4 ++ .github/workflows/codecov.yml | 2 + .github/workflows/docs.yml | 3 + .github/workflows/gpu-bench.yml | 37 ++++++---- .github/workflows/gpu-ci-cuda.yml | 6 +- .github/workflows/gpu-ci-opencl.yml | 6 +- .github/workflows/licenses-audits.yml | 2 + .github/workflows/links-check.yml | 2 + .github/workflows/lints.yml | 3 + .github/workflows/msrv.yml | 3 + .github/workflows/repo-sync.yml | 4 +- .github/workflows/rust-version-check.yml | 3 + .github/workflows/typos.yml | 2 + .github/workflows/unused-deps.yml | 7 +- .github/workflows/wasm.yml | 3 + .github/zizmor.yml | 9 --- 24 files changed, 200 insertions(+), 93 deletions(-) diff --git a/.github/actions/ci-env/action.yml b/.github/actions/ci-env/action.yml index 03ddc50..a577a08 100644 --- a/.github/actions/ci-env/action.yml +++ b/.github/actions/ci-env/action.yml @@ -5,7 +5,10 @@ description: Set Rust env vars runs: using: "composite" steps: - - run: | + # `cargo` and `rustc` read these from the environment, so they must be + # exported for the caller's later steps rather than passed as step outputs. + # Every value written here is a literal. + - run: | # zizmor: ignore[github-env] echo "CARGO_TERM_COLOR=always" | tee -a $GITHUB_ENV # Disable incremental compilation. diff --git a/.github/actions/gpu-setup/action.yml b/.github/actions/gpu-setup/action.yml index 3566d1d..689dee8 100644 --- a/.github/actions/gpu-setup/action.yml +++ b/.github/actions/gpu-setup/action.yml @@ -20,7 +20,12 @@ runs: - run: nvcc --version shell: bash - name: Set env vars - run: | + env: + GPU_FRAMEWORK: ${{ inputs.gpu-framework }} + # `ec-gpu` reads `EC_GPU_*` from the environment at build time, so these + # have to be exported rather than passed as step outputs. Every value + # below is a literal or comes from `nvidia-smi` on the runner itself. + run: | # zizmor: ignore[github-env] echo "GPU_NAME=$(nvidia-smi --query-gpu=gpu_name --format=csv,noheader,nounits | tail -n1)" | tee -a $GITHUB_ENV # The `compute`/`sm` number corresponds to the Nvidia GPU architecture (e.g. Ampere, Ada) # In order to use any GPU with this action, we want this to be configurable @@ -28,7 +33,7 @@ runs: CUDA_ARCH=$(nvidia-smi --query-gpu=compute_cap --format=csv,noheader | sed 's/\.//g') echo "EC_GPU_CUDA_NVCC_ARGS=--fatbin --gpu-architecture=sm_$CUDA_ARCH --generate-code=arch=compute_$CUDA_ARCH,code=sm_$CUDA_ARCH" | tee -a $GITHUB_ENV echo "CUDA_ARCH=$CUDA_ARCH" | tee -a $GITHUB_ENV - if [ "${{ inputs.gpu-framework }}" = "cuda" ]; + if [ "$GPU_FRAMEWORK" = "cuda" ]; then echo "EC_GPU_FRAMEWORK=cuda" | tee -a $GITHUB_ENV else diff --git a/.github/actions/install-deps/action.yml b/.github/actions/install-deps/action.yml index 105fac2..2132925 100644 --- a/.github/actions/install-deps/action.yml +++ b/.github/actions/install-deps/action.yml @@ -10,5 +10,7 @@ inputs: runs: using: "composite" steps: - - run: sudo apt-get update && sudo apt-get install -y ${{ inputs.packages }} + - run: sudo apt-get update && sudo apt-get install -y ${INPUTS_PACKAGES} shell: bash + env: + INPUTS_PACKAGES: ${{ inputs.packages }} diff --git a/.github/actions/lint-workflows/action.yml b/.github/actions/lint-workflows/action.yml index 78c151e..9f9c8c5 100644 --- a/.github/actions/lint-workflows/action.yml +++ b/.github/actions/lint-workflows/action.yml @@ -14,10 +14,6 @@ inputs: zizmor-config: description: 'Path to a zizmor config file' required: false - zizmor-advisory: - description: 'Report zizmor findings without failing the job' - required: false - default: 'true' runs: using: composite @@ -25,8 +21,10 @@ runs: - uses: raven-actions/actionlint@v2 env: SHELLCHECK_OPTS: -S ${{ inputs.shellcheck-severity }} + # Note that `continue-on-error` is silently ignored on composite action + # steps, so any zizmor finding fails the calling job. Suppress findings + # that don't apply via `.github/zizmor.yml` or `# zizmor: ignore` comments. - uses: zizmorcore/zizmor-action@v0.6.2 - continue-on-error: ${{ inputs.zizmor-advisory == 'true' }} with: config: ${{ inputs.zizmor-config }} # Mutually exclusive with `annotations`; the Security tab needs diff --git a/.github/actions/release-pr/action.yml b/.github/actions/release-pr/action.yml index 49bb091..1bed6b1 100644 --- a/.github/actions/release-pr/action.yml +++ b/.github/actions/release-pr/action.yml @@ -61,8 +61,12 @@ runs: # Discards patch version for a major or minor release. Patches are reserved for the `patch` `release-type`, # as they update the existing release branch rather than creating a new one - name: Validate version - run: | - echo "Validating input version ${{ inputs.version }}..." + # Composite actions cannot declare outputs from a step that later steps + # read as plain shell variables, so version state crosses steps via + # `GITHUB_ENV`. Everything written below is derived from `inputs.version` + # only after it has matched the SemVer regex. + run: | # zizmor: ignore[github-env] + echo "Validating input version ${INPUTS_VERSION}..." # Regex from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string D='0|[1-9][0-9]*' @@ -70,7 +74,7 @@ runs: MW='[0-9a-zA-Z-]+' SEMVER_REGEX="^($D)\.($D)\.($D)(-(($D|$PW)(\.($D|$PW))*))?(\+($MW(\.$MW)*))?$" - if [[ "${{ inputs.version }}" =~ $SEMVER_REGEX ]]; then + if [[ "${INPUTS_VERSION}" =~ $SEMVER_REGEX ]]; then # Extract major, minor, patch versions and anything after the patch (e.g., pre-release or build metadata) MAJOR="${BASH_REMATCH[1]}" MINOR="${BASH_REMATCH[2]}" @@ -78,7 +82,7 @@ runs: EXTRA="${BASH_REMATCH[4]}" # Pre-release or build metadata (if present) # Error if the patch version is greater than 0 for a release - if [[ "${{ inputs.release-type }}" != "patch" ]]; then + if [[ "${INPUTS_RELEASE_TYPE}" != "patch" ]]; then if [[ "$PATCH" -gt 0 ]]; then echo "Error: Patch version must be 0 for a major/minor release, but found $PATCH." exit 1 @@ -90,25 +94,28 @@ runs: fi fi - echo "Version ${{ inputs.version }} is valid." + echo "Version ${INPUTS_VERSION} is valid." # Construct BRANCH_VERSION as MAJOR.MINOR + EXTRA (retain pre-release and build metadata) BRANCH_VERSION="${MAJOR}.${MINOR}${EXTRA}" echo "Branch version: $BRANCH_VERSION" - if [[ "${{ inputs.release-type }}" == "major" ]]; then + if [[ "${INPUTS_RELEASE_TYPE}" == "major" ]]; then echo "PRIOR_VERSION=$(( MAJOR - 1 ))" | tee -a $GITHUB_ENV - elif [[ "${{ inputs.release-type }}" == "minor" ]]; then + elif [[ "${INPUTS_RELEASE_TYPE}" == "minor" ]]; then echo "PRIOR_VERSION=${MAJOR}" | tee -a $GITHUB_ENV fi else - echo "Version ${{ inputs.version }} is not valid SemVer. Aborting..." + echo "Version ${INPUTS_VERSION} is not valid SemVer. Aborting..." exit 1 fi echo "BRANCH_VERSION=$BRANCH_VERSION" | tee -a $GITHUB_ENV - echo "CRATE_VERSION=${{ inputs.version }}" | tee -a $GITHUB_ENV + echo "CRATE_VERSION=${INPUTS_VERSION}" | tee -a $GITHUB_ENV shell: bash + env: + INPUTS_VERSION: ${{ inputs.version }} + INPUTS_RELEASE_TYPE: ${{ inputs.release-type }} # Always checks out an existing release branch (if existent) as the base for the release PR. Maintainers are expected to # cherry-pick the desired changes from the default branch and push to the temporary `release-pr--v-v "$OLD_VERSION" ]]; then - sed -i "s/version = \"$OLD_VERSION\"/version = \"${{ env.CRATE_VERSION }}\"/" Cargo.toml + if [[ "${CRATE_VERSION}" > "$OLD_VERSION" ]]; then + sed -i "s/version = \"$OLD_VERSION\"/version = \"${CRATE_VERSION}\"/" Cargo.toml else echo "New version is not greater than the current version for $1. Aborting..." exit 1 fi - cd ${{ github.workspace }}/${{ inputs.path }} + cd ${{ github.workspace }}/${INPUTS_PATH} } while IFS= read -r path; do @@ -211,27 +225,33 @@ runs: git diff working-directory: ${{ github.workspace }}/${{ inputs.path }} shell: bash + env: + INPUTS_MORE_CRATES: ${{ inputs.more-crates }} + INPUTS_PATH: ${{ inputs.path }} - name: Create pull request description run: | REPO=$( echo "${{ github.repository }}" | awk -F'/' '{ print $2 }') - if [[ -n "${{ inputs.tag-prefix }}" ]]; then - TAG="${{ inputs.tag-prefix }}-v${{ env.CRATE_VERSION }}" + if [[ -n "${INPUTS_TAG_PREFIX}" ]]; then + TAG="${INPUTS_TAG_PREFIX}-v${CRATE_VERSION}" else - TAG="v${{ env.CRATE_VERSION }}" + TAG="v${CRATE_VERSION}" fi - if [[ -n "${{ inputs.path }}" ]]; then - NAME="$REPO/${{ inputs.path }}" + if [[ -n "${INPUTS_PATH}" ]]; then + NAME="$REPO/${INPUTS_PATH}" else NAME="$REPO" fi - printf '%s\n' "This is an automated release PR for \`$NAME\` version \`${{ env.CRATE_VERSION }}\`. + printf '%s\n' "This is an automated release PR for \`$NAME\` version \`${CRATE_VERSION}\`. On merge, this will trigger the [release publish workflow](${{ github.server_url }}/${{ github.repository }}/actions/workflows/tag-release.yml), which will upload a new GitHub release with tag \`$TAG\`. [Workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" > body.md shell: bash + env: + INPUTS_TAG_PREFIX: ${{ inputs.tag-prefix }} + INPUTS_PATH: ${{ inputs.path }} # TODO: Also open PR to `dev` to bump version if this is the latest release - name: Create release PR diff --git a/.github/actions/rust-version/action.yml b/.github/actions/rust-version/action.yml index 285f444..3d4e053 100644 --- a/.github/actions/rust-version/action.yml +++ b/.github/actions/rust-version/action.yml @@ -29,12 +29,14 @@ outputs: runs: using: "composite" - steps: + steps: - name: Parse `rust-toolchain.toml` shell: bash id: current-rust + env: + TOOLCHAIN: ${{ inputs.toolchain }} run: | - if [[ "${{ inputs.toolchain }}" == "nightly" ]]; then + if [[ "$TOOLCHAIN" == "nightly" ]]; then version=$(rustup show | grep rustc | awk -F'[()]| ' '{ print $(NF-1) }') else version=$(rustup show | grep rustc | awk '{ printf $2 }') @@ -44,9 +46,11 @@ runs: - name: Get latest `${{ inputs.toolchain }}` Rust release id: latest-rust shell: bash + env: + TOOLCHAIN: ${{ inputs.toolchain }} run: | - if [[ "${{ inputs.toolchain }}" == "nightly" ]]; then - version=$(rustup check | grep ${{ inputs.toolchain }} | awk -F'[()]| ' '{print $(NF-1)}') + if [[ "$TOOLCHAIN" == "nightly" ]]; then + version=$(rustup check | grep "$TOOLCHAIN" | awk -F'[()]| ' '{print $(NF-1)}') else version=$(rustup check | grep stable | awk '{print $(NF-2)}') fi @@ -54,24 +58,32 @@ runs: - name: Compare Rust versions id: compare-versions shell: bash + env: + CURRENT_VERSION: ${{ steps.current-rust.outputs.version }} + LATEST_VERSION: ${{ steps.latest-rust.outputs.version }} run: | - if [[ $(printf '%s\n' "${{ steps.current-rust.outputs.version }}" "${{ steps.latest-rust.outputs.version }}" | sort -V | head -n 1) != "${{ steps.latest-rust.outputs.version }}" ]]; then + if [[ $(printf '%s\n' "$CURRENT_VERSION" "$LATEST_VERSION" | sort -V | head -n 1) != "$LATEST_VERSION" ]]; then echo "outdated=true" | tee -a $GITHUB_OUTPUT fi working-directory: ${{ github.workspace }}/${{ inputs.workdir }} - name: Update `Cargo.toml` if: steps.compare-versions.outputs.outdated == 'true' shell: bash + env: + TOOLCHAIN: ${{ inputs.toolchain }} + LATEST_VERSION: ${{ steps.latest-rust.outputs.version }} run: | - if [[ "${{ inputs.toolchain }}" == "nightly" ]]; then - sed -i 's/channel = .*/channel = "nightly-${{ steps.latest-rust.outputs.version }}"/' rust-toolchain.toml + if [[ "$TOOLCHAIN" == "nightly" ]]; then + sed -i "s/channel = .*/channel = \"nightly-$LATEST_VERSION\"/" rust-toolchain.toml else - sed -i 's/channel = .*/channel = "${{ steps.latest-rust.outputs.version }}"/' rust-toolchain.toml + sed -i "s/channel = .*/channel = \"$LATEST_VERSION\"/" rust-toolchain.toml fi echo "Outdated Rust, updating" cat rust-toolchain.toml working-directory: ${{ github.workspace }}/${{ inputs.workdir }} - name: Clean up shell: bash + env: + WORKSPACE: ${{ github.workspace }} run: | - rm -rf ${{ github.workspace }}/ci-workflows + rm -rf "$WORKSPACE/ci-workflows" diff --git a/.github/actions/tag-release/action.yml b/.github/actions/tag-release/action.yml index 58dd3e2..d348ef7 100644 --- a/.github/actions/tag-release/action.yml +++ b/.github/actions/tag-release/action.yml @@ -32,33 +32,39 @@ runs: steps: - name: Get release tag id: get-tag - run: | - if [[ -n "${{ inputs.tag-prefix }}" ]]; then - TAG_PREFIX="${{ inputs.tag-prefix }}-v" + # `TAG_PREFIX` is consumed as a shell variable by the next step, which a + # step output cannot provide. Its value is the caller's literal prefix. + run: | # zizmor: ignore[github-env] + if [[ -n "${INPUTS_TAG_PREFIX}" ]]; then + TAG_PREFIX="${INPUTS_TAG_PREFIX}-v" else TAG_PREFIX="" fi - RELEASE_TAG=${TAG_PREFIX}${{ inputs.version }} + RELEASE_TAG=${TAG_PREFIX}${INPUTS_VERSION} - git tag -a $RELEASE_TAG -m "$RELEASE_TAG" origin/${{ inputs.release-branch }} + git tag -a $RELEASE_TAG -m "$RELEASE_TAG" origin/${INPUTS_RELEASE_BRANCH} git push origin $RELEASE_TAG --follow-tags echo "release-tag=$RELEASE_TAG" | tee -a "$GITHUB_OUTPUT" echo "TAG_PREFIX=$TAG_PREFIX" | tee -a "$GITHUB_ENV" shell: bash + env: + INPUTS_TAG_PREFIX: ${{ inputs.tag-prefix }} + INPUTS_VERSION: ${{ inputs.version }} + INPUTS_RELEASE_BRANCH: ${{ inputs.release-branch }} - name: Get latest release reference id: get-latest-release run: | set +o pipefail - NEW_MAJOR_VERSION=$(echo "${{ inputs.version }}" | cut -d '.' -f 1) + NEW_MAJOR_VERSION=$(echo "${INPUTS_VERSION}" | cut -d '.' -f 1) # Get the latest release version from the repository - LATEST_RELEASE=$(gh release list --repo ${{ github.repository }} --limit 100 | grep -Ei "${{ env.TAG_PREFIX }}" | head -n 1 | awk '{ print $1 }') + LATEST_RELEASE=$(gh release list --repo ${{ github.repository }} --limit 100 | grep -Ei "${TAG_PREFIX}" | head -n 1 | awk '{ print $1 }') - if [[ -n "${{ env.TAG_PREFIX }}" ]]; then - LATEST_MAJOR_VERSION=$(echo "$LATEST_RELEASE" | awk -F"${{ env.TAG_PREFIX }}" '{print $2}' | cut -d '.' -f 1) + if [[ -n "${TAG_PREFIX}" ]]; then + LATEST_MAJOR_VERSION=$(echo "$LATEST_RELEASE" | awk -F"${TAG_PREFIX}" '{print $2}' | cut -d '.' -f 1) else LATEST_MAJOR_VERSION=$(echo "$LATEST_RELEASE" | cut -d '.' -f 1) fi @@ -74,7 +80,7 @@ runs: # Get the latest release within the same major version range LATEST_RELEASE=$(gh release list --repo ${{ github.repository }} --limit 100 \ - | grep -E "${{ env.TAG_PREFIX }}${SEMVER_REGEX}" \ + | grep -E "${TAG_PREFIX}${SEMVER_REGEX}" \ | head -n 1) fi @@ -85,6 +91,7 @@ runs: echo "latest-release=$LATEST_RELEASE" | tee -a "$GITHUB_OUTPUT" env: GH_TOKEN: ${{ github.token }} + INPUTS_VERSION: ${{ inputs.version }} shell: bash # TODO: Add an automatic labeler for PRs based on title/commit prefix @@ -101,7 +108,10 @@ runs: GITHUB_TOKEN: ${{ github.token }} - name: Create Release - uses: ncipollo/release-action@v1 + # `gh release` has no equivalent of `allowUpdates`, which re-releases an + # existing tag rather than failing. Replacing this would mean + # hand-rolling create-or-update logic in a release-critical path. + uses: ncipollo/release-action@v1 # zizmor: ignore[superfluous-actions] with: body: ${{ steps.github-release.outputs.changelog }} tag: ${{ steps.get-tag.outputs.release-tag }} diff --git a/.github/workflows/bench-pr-comment.yml b/.github/workflows/bench-pr-comment.yml index fa6cb8e..e795d3b 100644 --- a/.github/workflows/bench-pr-comment.yml +++ b/.github/workflows/bench-pr-comment.yml @@ -67,17 +67,20 @@ jobs: id: format-runner run: | # Parse `default-runner` if it's a list of strings (e.g. `"self-hosted,gpu-bench") - RUNNER=$(echo ${{ inputs.default-runner }} | awk -F"," -v q=\" '{for (i=0; i> $GITHUB_OUTPUT echo "$RUNNER" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT + env: + INPUTS_DEFAULT_RUNNER: ${{ inputs.default-runner }} - name: Parse PR comment body id: bench-params env: COMMENT_BODY: ${{ github.event.comment.body }} + INPUTS_DEFAULT_BENCHES: ${{ inputs.default-benches }} run: | # Parse `issue_comment` body printf '%s' "$COMMENT_BODY" > comment.txt @@ -88,7 +91,7 @@ jobs: BENCHES=$(echo $BENCH_COMMAND | awk -v q=\" '{for (i=1; i<=NF; i++) {if ($i ~ /^--bench/) {print q$(i+1)q","}}}') if [[ -z $BENCHES ]]; then # Add quotes to each default bench name in comma-separated list for `fromJSON` parsing - BENCHES=$(echo ${{ inputs.default-benches }} | awk -F"," -v q=\" '{for (i=0; i> $GITHUB_OUTPUT # Get the list of features to run on each benchmark FEATURES=$(echo $BENCH_COMMAND | awk '{for (i=1; i<=NF; i++) {if ($i ~ /^--features/) {print $(i+1) }}}') - if [[ ${{ env.GPU_BENCHMARK }} = 'true' || $(echo $FEATURES | grep -s cuda) ]]; then + if [[ ${GPU_BENCHMARK} = 'true' || $(echo $FEATURES | grep -s cuda) ]]; then echo "cuda=true" | tee -a $GITHUB_OUTPUT COMMAND="gpu-benchmark" # Add the "cuda" feature if not already specified @@ -126,20 +129,28 @@ jobs: # When using the `cuda` feature, several GPU-related env vars are set by the `gpu-setup` action below. # Thus there is no need to set them here. These inputs are mainly for benchmark parameters such as `LURK_RC` - name: Set env vars + env: + DEFAULT_ENV: ${{ inputs.default-env }} + COMMENT_ENV: ${{ needs.setup.outputs.env-vars }} run: | # Trims newlines that may arise from `$GITHUB_OUTPUT` - for var in ${{ inputs.default-env }} + # Both lists are deliberately unquoted so they word-split into + # individual `NAME=VALUE` pairs. + # shellcheck disable=SC2086 + for var in $DEFAULT_ENV do echo "$(echo $var | tr -d '\n')" | tee -a $GITHUB_ENV done # Overrides default env vars with those specified in the `issue_comment` input if identically named - for var in ${{ needs.setup.outputs.env-vars }} + # shellcheck disable=SC2086 + for var in $COMMENT_ENV do echo "$(echo $var | tr -d '\n')" | tee -a $GITHUB_ENV done - uses: actions/checkout@v4 with: repository: argumentcomputer/ci-workflows + persist-credentials: false - uses: ./.github/actions/gpu-setup if: ${{ needs.setup.outputs.cuda }} with: @@ -153,6 +164,8 @@ jobs: - uses: xt0rted/pull-request-comment-branch@v2 id: comment-branch - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Checkout PR branch run: gh pr checkout $PR_NUMBER env: diff --git a/.github/workflows/check-lurk-compiles.yml b/.github/workflows/check-lurk-compiles.yml index e7a24ba..c3f7d03 100644 --- a/.github/workflows/check-lurk-compiles.yml +++ b/.github/workflows/check-lurk-compiles.yml @@ -20,17 +20,21 @@ jobs: - uses: actions/checkout@v4 with: repository: argumentcomputer/ci-workflows + persist-credentials: false - uses: ./.github/actions/ci-env - uses: ./.github/actions/install-deps if: inputs.packages != '' with: packages: "${{ inputs.packages }}" - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: actions/checkout@v4 with: repository: argumentcomputer/lurk-rs path: ./lurk-rs submodules: recursive + persist-credentials: false - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: Patch Cargo.toml diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 3a8fff8..329aaa5 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -22,6 +22,7 @@ jobs: - uses: actions/checkout@v4 with: repository: argumentcomputer/ci-workflows + persist-credentials: false - uses: ./.github/actions/ci-env - uses: ./.github/actions/install-deps if: inputs.packages != '' @@ -30,6 +31,7 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive + persist-credentials: false - uses: dtolnay/rust-toolchain@stable with: components: llvm-tools-preview diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 0976dda..a919490 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -11,8 +11,11 @@ jobs: - uses: actions/checkout@v4 with: repository: argumentcomputer/ci-workflows + persist-credentials: false - uses: ./.github/actions/ci-env - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: dtolnay/rust-toolchain@stable - name: Generate documentation env: diff --git a/.github/workflows/gpu-bench.yml b/.github/workflows/gpu-bench.yml index 2b17da0..8bd5736 100644 --- a/.github/workflows/gpu-bench.yml +++ b/.github/workflows/gpu-bench.yml @@ -23,6 +23,7 @@ jobs: - uses: actions/checkout@v4 with: repository: argumentcomputer/ci-workflows + persist-credentials: false - uses: ./.github/actions/gpu-setup with: gpu-framework: 'cuda' @@ -31,7 +32,9 @@ jobs: if: inputs.packages != '' with: packages: "${{ inputs.packages }}" - - uses: actions/checkout@v4 + # `git-auto-commit-action` below pushes to `gh-pages` with the credentials + # this checkout persists, so they cannot be disabled here. + - uses: actions/checkout@v4 # zizmor: ignore[artipacked] # Install dependencies - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 @@ -53,13 +56,14 @@ jobs: with: ref: gh-pages path: gh-pages + persist-credentials: false - name: Check for cached bench result id: cached-bench run: | - if [ -f "${{ env.BASE_COMMIT }}-${{ env.GPU_ID }}.json" ] + if [ -f "$BASE_COMMIT-$GPU_ID.json" ] then echo "cached=true" | tee -a $GITHUB_OUTPUT - cp ${{ env.BASE_COMMIT }}-${{ env.GPU_ID }}.json ../${{ env.BASE_COMMIT }}.json + cp "$BASE_COMMIT-$GPU_ID.json" "../$BASE_COMMIT.json" else echo "cached=false" | tee -a $GITHUB_OUTPUT fi @@ -70,13 +74,14 @@ jobs: with: ref: ${{ github.base_ref }} path: ${{ github.base_ref }} + persist-credentials: false - name: Run GPU bench on base branch if: steps.cached-bench.outputs.cached == 'false' run: | # Run benchmark - cargo criterion --features "cuda" --message-format=json > ${{ env.BASE_COMMIT }}.json + cargo criterion --features "cuda" --message-format=json > "$BASE_COMMIT.json" # Copy bench output to PR branch - cp ${{ env.BASE_COMMIT }}.json .. + cp "$BASE_COMMIT.json" .. working-directory: ${{ github.workspace }}/${{ github.base_ref }} - name: Run GPU bench on PR branch run: | @@ -94,15 +99,18 @@ jobs: TOTAL_RAM=$(grep MemTotal /proc/meminfo | awk '{$2=$2/(1024^2); print int($2), "GB RAM";}') # Use conditionals to ensure that only non-empty variables are inserted - [[ ! -z "${{ env.GPU_NAME }}" ]] && sed -i "/^\"\"\"$/i ${{ env.GPU_NAME }}" tables.toml + [[ ! -z "$GPU_NAME" ]] && sed -i "/^\"\"\"$/i $GPU_NAME" tables.toml [[ ! -z "$CPU_MODEL" ]] && sed -i "/^\"\"\"$/i $CPU_MODEL" tables.toml [[ ! -z "$NUM_VCPUS" ]] && sed -i "/^\"\"\"$/i $NUM_VCPUs" tables.toml [[ ! -z "$TOTAL_RAM" ]] && sed -i "/^\"\"\"$/i $TOTAL_RAM" tables.toml - sed -i "/^\"\"\"$/i Workflow run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" tables.toml + sed -i "/^\"\"\"$/i Workflow run: $GITHUB_SERVER_URL/$REPO/actions/runs/$RUN_ID" tables.toml working-directory: ${{ github.workspace }} + env: + REPO: ${{ github.repository }} + RUN_ID: ${{ github.run_id }} # Create a `criterion-table` and write in commit comment - name: Run `criterion-table` - run: cat ${{ env.BASE_COMMIT }}.json ${{ github.sha }}.json | criterion-table > BENCHMARKS.md + run: cat "$BASE_COMMIT.json" "$GITHUB_SHA.json" | criterion-table > BENCHMARKS.md - name: Write bench on commit comment uses: peter-evans/commit-comment@v3 with: @@ -132,9 +140,12 @@ jobs: - name: Create file for issue if: steps.regression-check.outcome == 'failure' run: | - printf '%s\n' "Regression >= 10% found during merge for PR #${{ env.PR_NUMBER }} - Commit: ${{ github.sha }} - Workflow run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" > ./_body.md + printf '%s\n' "Regression >= 10% found during merge for PR #$PR_NUMBER + Commit: $GITHUB_SHA + Workflow run: $GITHUB_SERVER_URL/$REPO/actions/runs/$RUN_ID" > ./_body.md + env: + REPO: ${{ github.repository }} + RUN_ID: ${{ github.run_id }} - name: Open issue on regression if: steps.regression-check.outcome == 'failure' uses: peter-evans/create-issue-from-file@v5 @@ -146,8 +157,8 @@ jobs: automated issue - name: Remove old base bench run: | - rm ${{ env.BASE_COMMIT }}.json - mv ${{ github.sha }}.json ${{ github.sha }}-${{ env.GPU_ID }}.json + rm "$BASE_COMMIT.json" + mv "$GITHUB_SHA.json" "$GITHUB_SHA-$GPU_ID.json" working-directory: ${{ github.workspace }} - name: Commit bench result to `gh-pages` branch if no regression if: steps.regression-check.outcome != 'failure' diff --git a/.github/workflows/gpu-ci-cuda.yml b/.github/workflows/gpu-ci-cuda.yml index e5f1254..0fae71f 100644 --- a/.github/workflows/gpu-ci-cuda.yml +++ b/.github/workflows/gpu-ci-cuda.yml @@ -28,6 +28,7 @@ jobs: - uses: actions/checkout@v4 with: repository: argumentcomputer/ci-workflows + persist-credentials: false - uses: ./.github/actions/gpu-setup with: gpu-framework: 'cuda' @@ -39,9 +40,12 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive + persist-credentials: false - uses: dtolnay/rust-toolchain@stable - uses: taiki-e/install-action@nextest - uses: Swatinem/rust-cache@v2 - name: CUDA tests + env: + FEATURES: ${{ inputs.features }} run: | - cargo nextest run --profile ci --cargo-profile dev-ci --features "cuda,${{ inputs.features }}" + cargo nextest run --profile ci --cargo-profile dev-ci --features "cuda,$FEATURES" diff --git a/.github/workflows/gpu-ci-opencl.yml b/.github/workflows/gpu-ci-opencl.yml index b1a3c9f..cb5809c 100644 --- a/.github/workflows/gpu-ci-opencl.yml +++ b/.github/workflows/gpu-ci-opencl.yml @@ -28,6 +28,7 @@ jobs: - uses: actions/checkout@v4 with: repository: argumentcomputer/ci-workflows + persist-credentials: false - uses: ./.github/actions/gpu-setup with: gpu-framework: 'opencl' @@ -39,9 +40,12 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive + persist-credentials: false - uses: dtolnay/rust-toolchain@stable - uses: taiki-e/install-action@nextest - uses: Swatinem/rust-cache@v2 - name: OpenCL tests + env: + FEATURES: ${{ inputs.features }} run: | - cargo nextest run --profile ci --cargo-profile dev-ci --features "cuda,opencl,${{ inputs.features }}" + cargo nextest run --profile ci --cargo-profile dev-ci --features "cuda,opencl,$FEATURES" diff --git a/.github/workflows/licenses-audits.yml b/.github/workflows/licenses-audits.yml index 017c78a..5d89259 100644 --- a/.github/workflows/licenses-audits.yml +++ b/.github/workflows/licenses-audits.yml @@ -10,4 +10,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: EmbarkStudios/cargo-deny-action@v1 diff --git a/.github/workflows/links-check.yml b/.github/workflows/links-check.yml index cc4f71a..1f0fdc7 100644 --- a/.github/workflows/links-check.yml +++ b/.github/workflows/links-check.yml @@ -18,6 +18,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + persist-credentials: false - name: Link Checker uses: lycheeverse/lychee-action@v2.0.2 with: diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index adee252..2e4149a 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -22,12 +22,15 @@ jobs: - uses: actions/checkout@v4 with: repository: argumentcomputer/ci-workflows + persist-credentials: false - uses: ./.github/actions/ci-env - uses: ./.github/actions/install-deps if: inputs.packages != '' with: packages: "${{ inputs.packages }}" - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: dtolnay/rust-toolchain@stable with: components: rustfmt, clippy diff --git a/.github/workflows/msrv.yml b/.github/workflows/msrv.yml index 041db11..5f537ac 100644 --- a/.github/workflows/msrv.yml +++ b/.github/workflows/msrv.yml @@ -18,12 +18,15 @@ jobs: - uses: actions/checkout@v4 with: repository: argumentcomputer/ci-workflows + persist-credentials: false - uses: ./.github/actions/ci-env - uses: ./.github/actions/install-deps if: inputs.packages != '' with: packages: "${{ inputs.packages }}" - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: Install cargo-msrv diff --git a/.github/workflows/repo-sync.yml b/.github/workflows/repo-sync.yml index ae19146..d89de06 100644 --- a/.github/workflows/repo-sync.yml +++ b/.github/workflows/repo-sync.yml @@ -39,6 +39,8 @@ jobs: # `github.repository` is the caller's repo, not this one, and the token is # scoped to it by default. - name: repo-sync - run: gh repo sync ${{ github.repository }} --source ${{ inputs.repository }} --branch ${{ inputs.branch }} --force + run: gh repo sync ${{ github.repository }} --source ${INPUTS_REPOSITORY} --branch ${INPUTS_BRANCH} --force env: GH_TOKEN: ${{ steps.generate-token.outputs.token }} + INPUTS_REPOSITORY: ${{ inputs.repository }} + INPUTS_BRANCH: ${{ inputs.branch }} diff --git a/.github/workflows/rust-version-check.yml b/.github/workflows/rust-version-check.yml index d4ca586..0520897 100644 --- a/.github/workflows/rust-version-check.yml +++ b/.github/workflows/rust-version-check.yml @@ -12,12 +12,15 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Check out `ci-workflows` uses: actions/checkout@v4 with: repository: argumentcomputer/ci-workflows path: ci-workflows + persist-credentials: false - name: Set up Rust uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/typos.yml b/.github/workflows/typos.yml index c324b6b..34ea3ca 100644 --- a/.github/workflows/typos.yml +++ b/.github/workflows/typos.yml @@ -12,6 +12,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: Install typos binary diff --git a/.github/workflows/unused-deps.yml b/.github/workflows/unused-deps.yml index ba542ac..46a1961 100644 --- a/.github/workflows/unused-deps.yml +++ b/.github/workflows/unused-deps.yml @@ -25,10 +25,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: actions/checkout@v4 with: repository: argumentcomputer/ci-workflows path: ci-workflows + persist-credentials: false - uses: ./ci-workflows/.github/actions/install-deps if: inputs.packages != '' with: @@ -40,7 +43,9 @@ jobs: # opt to use the stable toolchain specified via the 'rust-toolchain' file # and instead enable nightly features via 'RUSTC_BOOTSTRAP' - name: run cargo-udeps - run: RUSTC_BOOTSTRAP=1 cargo udeps --workspace --all-targets --features "${{ inputs.features }}" + run: RUSTC_BOOTSTRAP=1 cargo udeps --workspace --all-targets --features "${INPUTS_FEATURES}" + env: + INPUTS_FEATURES: ${{ inputs.features }} - uses: JasonEtco/create-an-issue@v2 if: ${{ failure() }} env: diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index 4badd42..13f0ede 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -14,12 +14,15 @@ jobs: - uses: actions/checkout@v4 with: repository: argumentcomputer/ci-workflows + persist-credentials: false - uses: ./.github/actions/ci-env - uses: ./.github/actions/install-deps if: inputs.packages != '' with: packages: "${{ inputs.packages }}" - uses: actions/checkout@v4 + with: + persist-credentials: false - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - run: rustup target add wasm32-unknown-unknown diff --git a/.github/zizmor.yml b/.github/zizmor.yml index 72a2bc7..41a93d1 100644 --- a/.github/zizmor.yml +++ b/.github/zizmor.yml @@ -3,12 +3,3 @@ rules: # is a posture this org has not adopted. unpinned-uses: disable: true - template-injection: - # These expand caller-supplied `inputs.*`, not attacker-supplied data. A - # caller that can set them can already write arbitrary steps of its own. - ignore: - - bench-pr-comment.yml - - gpu-ci-cuda.yml - - gpu-ci-opencl.yml - - repo-sync.yml - - unused-deps.yml From b0b3e505fb1fa21fd1c32de957f58c47387b49ae Mon Sep 17 00:00:00 2001 From: samuelburnham <45365069+samuelburnham@users.noreply.github.com> Date: Mon, 24 Aug 2026 12:23:20 -0400 Subject: [PATCH 4/4] build(deps): Update all actions to their latest major versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Supersedes the open Dependabot PRs, several of which had themselves gone stale — lychee is now on 2.9.0 rather than the 2.2.0 in #85, and codecov on v7 rather than the v5 in #83. actions/checkout v4 -> v7 codecov/codecov-action v4 -> v7 EmbarkStudios/cargo-deny-action v1 -> v2 lycheeverse/lychee-action v2.0.2 -> v2.9.0 mikepenz/release-changelog-builder-action v5 -> v6 peter-evans/commit-comment v3 -> v4 peter-evans/create-issue-from-file v5 -> v6 peter-evans/create-or-update-comment v4 -> v5 peter-evans/create-pull-request v7 -> v8 stefanzweifel/git-auto-commit-action v5 -> v7 xt0rted/pull-request-comment-branch v2 -> v3 Most of these majors are Node 24 runtime moves, which need Actions Runner v2.327.1 or later on the self-hosted GPU runners. Every input still passed was checked against the new version's `action.yml`. Fix the link checker's failure path while bumping it: lychee stopped exporting `lychee_exit_code` to the environment in v2, so the condition guarding the issue-opening step has been reading an unset variable — and never firing — since the action moved to v2.0.2. Read the exit code from the step output instead. --- .github/actions/release-pr/action.yml | 2 +- .github/actions/tag-release/action.yml | 2 +- .github/workflows/actions-lint.yml | 2 +- .github/workflows/bench-pr-comment.yml | 10 +++++----- .github/workflows/check-lurk-compiles.yml | 6 +++--- .github/workflows/codecov.yml | 6 +++--- .github/workflows/docs.yml | 4 ++-- .github/workflows/gpu-bench.yml | 14 +++++++------- .github/workflows/gpu-ci-cuda.yml | 4 ++-- .github/workflows/gpu-ci-opencl.yml | 4 ++-- .github/workflows/licenses-audits.yml | 4 ++-- .github/workflows/links-check.yml | 11 +++++++---- .github/workflows/lints.yml | 4 ++-- .github/workflows/msrv.yml | 4 ++-- .github/workflows/rust-version-check.yml | 4 ++-- .github/workflows/typos.yml | 4 ++-- .github/workflows/unused-deps.yml | 4 ++-- .github/workflows/wasm.yml | 4 ++-- 18 files changed, 48 insertions(+), 45 deletions(-) diff --git a/.github/actions/release-pr/action.yml b/.github/actions/release-pr/action.yml index 1bed6b1..9e5b5a8 100644 --- a/.github/actions/release-pr/action.yml +++ b/.github/actions/release-pr/action.yml @@ -255,7 +255,7 @@ runs: # TODO: Also open PR to `dev` to bump version if this is the latest release - name: Create release PR - uses: peter-evans/create-pull-request@v7 + uses: peter-evans/create-pull-request@v8 with: token: ${{ inputs.token }} add-paths: | diff --git a/.github/actions/tag-release/action.yml b/.github/actions/tag-release/action.yml index d348ef7..de629bf 100644 --- a/.github/actions/tag-release/action.yml +++ b/.github/actions/tag-release/action.yml @@ -97,7 +97,7 @@ runs: # TODO: Add an automatic labeler for PRs based on title/commit prefix - name: Build Changelog id: github-release - uses: mikepenz/release-changelog-builder-action@v5 + uses: mikepenz/release-changelog-builder-action@v6 with: mode: "COMMIT" configuration: ${{ inputs.changelog-config-file }} diff --git a/.github/workflows/actions-lint.yml b/.github/workflows/actions-lint.yml index a08d943..f5b2513 100644 --- a/.github/workflows/actions-lint.yml +++ b/.github/workflows/actions-lint.yml @@ -18,7 +18,7 @@ jobs: name: Lint workflows runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: persist-credentials: false - uses: ./.github/actions/lint-workflows diff --git a/.github/workflows/bench-pr-comment.yml b/.github/workflows/bench-pr-comment.yml index e795d3b..590187d 100644 --- a/.github/workflows/bench-pr-comment.yml +++ b/.github/workflows/bench-pr-comment.yml @@ -147,7 +147,7 @@ jobs: do echo "$(echo $var | tr -d '\n')" | tee -a $GITHUB_ENV done - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: repository: argumentcomputer/ci-workflows persist-credentials: false @@ -161,9 +161,9 @@ jobs: with: packages: "${{ inputs.packages }}" # Get base branch of the PR - - uses: xt0rted/pull-request-comment-branch@v2 + - uses: xt0rted/pull-request-comment-branch@v3 id: comment-branch - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: persist-credentials: false - name: Checkout PR branch @@ -187,7 +187,7 @@ jobs: branchName: ${{ steps.comment-branch.outputs.base_ref }} - name: Comment on successful run if: success() - uses: peter-evans/create-or-update-comment@v4 + uses: peter-evans/create-or-update-comment@v5 with: issue-number: ${{ github.event.issue.number }} body: | @@ -197,7 +197,7 @@ jobs: - name: Comment on failing run if: failure() - uses: peter-evans/create-or-update-comment@v4 + uses: peter-evans/create-or-update-comment@v5 with: issue-number: ${{ github.event.issue.number }} body: | diff --git a/.github/workflows/check-lurk-compiles.yml b/.github/workflows/check-lurk-compiles.yml index c3f7d03..d50794f 100644 --- a/.github/workflows/check-lurk-compiles.yml +++ b/.github/workflows/check-lurk-compiles.yml @@ -17,7 +17,7 @@ jobs: if: github.event_name == 'pull_request' runs-on: ${{ inputs.runner }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: repository: argumentcomputer/ci-workflows persist-credentials: false @@ -26,10 +26,10 @@ jobs: if: inputs.packages != '' with: packages: "${{ inputs.packages }}" - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: persist-credentials: false - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: repository: argumentcomputer/lurk-rs path: ./lurk-rs diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 329aaa5..89e315d 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: true steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: repository: argumentcomputer/ci-workflows persist-credentials: false @@ -28,7 +28,7 @@ jobs: if: inputs.packages != '' with: packages: "${{ inputs.packages }}" - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: submodules: recursive persist-credentials: false @@ -46,6 +46,6 @@ jobs: - name: Collect coverage data run: cargo llvm-cov nextest --lcov --output-path lcov.info --profile ci --release --workspace - name: Upload coverage data to codecov - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v7 with: files: lcov.info diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index a919490..9e826ad 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -8,12 +8,12 @@ jobs: name: Generate crate documentation runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: repository: argumentcomputer/ci-workflows persist-credentials: false - uses: ./.github/actions/ci-env - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: persist-credentials: false - uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/gpu-bench.yml b/.github/workflows/gpu-bench.yml index 8bd5736..539bce6 100644 --- a/.github/workflows/gpu-bench.yml +++ b/.github/workflows/gpu-bench.yml @@ -20,7 +20,7 @@ jobs: runs-on: [self-hosted, gpu-bench] steps: # Set up GPU - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: repository: argumentcomputer/ci-workflows persist-credentials: false @@ -34,7 +34,7 @@ jobs: packages: "${{ inputs.packages }}" # `git-auto-commit-action` below pushes to `gh-pages` with the credentials # this checkout persists, so they cannot be disabled here. - - uses: actions/checkout@v4 # zizmor: ignore[artipacked] + - uses: actions/checkout@v7 # zizmor: ignore[artipacked] # Install dependencies - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 @@ -52,7 +52,7 @@ jobs: echo "GPU_ID=$(echo $GPU_NAME | awk '{ print $NF }')" | tee -a $GITHUB_ENV # Checkout gh-pages to check for cached bench result - name: Checkout gh-pages - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: ref: gh-pages path: gh-pages @@ -69,7 +69,7 @@ jobs: fi working-directory: ${{ github.workspace }}/gh-pages # Checkout base branch for comparative bench - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 if: steps.cached-bench.outputs.cached == 'false' with: ref: ${{ github.base_ref }} @@ -112,7 +112,7 @@ jobs: - name: Run `criterion-table` run: cat "$BASE_COMMIT.json" "$GITHUB_SHA.json" | criterion-table > BENCHMARKS.md - name: Write bench on commit comment - uses: peter-evans/commit-comment@v3 + uses: peter-evans/commit-comment@v4 with: body-path: BENCHMARKS.md # Check for a slowdown >= 10%. If so, open an issue but don't block merge @@ -148,7 +148,7 @@ jobs: RUN_ID: ${{ github.run_id }} - name: Open issue on regression if: steps.regression-check.outcome == 'failure' - uses: peter-evans/create-issue-from-file@v5 + uses: peter-evans/create-issue-from-file@v6 with: title: ':rotating_light: Performance regression detected for PR #${{ env.PR_NUMBER }}' content-filepath: ./_body.md @@ -162,7 +162,7 @@ jobs: working-directory: ${{ github.workspace }} - name: Commit bench result to `gh-pages` branch if no regression if: steps.regression-check.outcome != 'failure' - uses: stefanzweifel/git-auto-commit-action@v5 + uses: stefanzweifel/git-auto-commit-action@v7 with: branch: gh-pages commit_message: '[automated] GPU Benchmark from PR #${{ env.PR_NUMBER }}' diff --git a/.github/workflows/gpu-ci-cuda.yml b/.github/workflows/gpu-ci-cuda.yml index 0fae71f..8deae4e 100644 --- a/.github/workflows/gpu-ci-cuda.yml +++ b/.github/workflows/gpu-ci-cuda.yml @@ -25,7 +25,7 @@ jobs: if: github.event_name != 'pull_request' || github.event.action == 'enqueued' runs-on: [self-hosted, gpu-ci] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: repository: argumentcomputer/ci-workflows persist-credentials: false @@ -37,7 +37,7 @@ jobs: if: inputs.packages != '' with: packages: "${{ inputs.packages }}" - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: submodules: recursive persist-credentials: false diff --git a/.github/workflows/gpu-ci-opencl.yml b/.github/workflows/gpu-ci-opencl.yml index cb5809c..2c3e69c 100644 --- a/.github/workflows/gpu-ci-opencl.yml +++ b/.github/workflows/gpu-ci-opencl.yml @@ -25,7 +25,7 @@ jobs: if: github.event_name != 'pull_request' || github.event.action == 'enqueued' runs-on: [self-hosted, gpu-ci] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: repository: argumentcomputer/ci-workflows persist-credentials: false @@ -37,7 +37,7 @@ jobs: if: inputs.packages != '' with: packages: "${{ inputs.packages }}" - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: submodules: recursive persist-credentials: false diff --git a/.github/workflows/licenses-audits.yml b/.github/workflows/licenses-audits.yml index 5d89259..54d13bd 100644 --- a/.github/workflows/licenses-audits.yml +++ b/.github/workflows/licenses-audits.yml @@ -9,7 +9,7 @@ jobs: name: cargo-deny (advisories, licenses, bans, ...) runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: persist-credentials: false - - uses: EmbarkStudios/cargo-deny-action@v1 + - uses: EmbarkStudios/cargo-deny-action@v2 diff --git a/.github/workflows/links-check.yml b/.github/workflows/links-check.yml index 1f0fdc7..0572139 100644 --- a/.github/workflows/links-check.yml +++ b/.github/workflows/links-check.yml @@ -17,18 +17,21 @@ jobs: linkChecker: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: persist-credentials: false - name: Link Checker - uses: lycheeverse/lychee-action@v2.0.2 + id: lychee + uses: lycheeverse/lychee-action@v2.9.0 with: fail: ${{ inputs.fail-fast }} env: GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + # lychee stopped exporting `lychee_exit_code` to the environment in v2; + # the exit code is only available as a step output. - name: Open issue on failure if `fail-fast` input is false - if: env.lychee_exit_code != 0 && inputs.fail-fast != true - uses: peter-evans/create-issue-from-file@v5 + if: steps.lychee.outputs.exit_code != 0 && inputs.fail-fast != true + uses: peter-evans/create-issue-from-file@v6 with: title: Link Checker Report content-filepath: ./lychee/out.md diff --git a/.github/workflows/lints.yml b/.github/workflows/lints.yml index 2e4149a..c382359 100644 --- a/.github/workflows/lints.yml +++ b/.github/workflows/lints.yml @@ -19,7 +19,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: repository: argumentcomputer/ci-workflows persist-credentials: false @@ -28,7 +28,7 @@ jobs: if: inputs.packages != '' with: packages: "${{ inputs.packages }}" - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: persist-credentials: false - uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/msrv.yml b/.github/workflows/msrv.yml index 5f537ac..b8a0391 100644 --- a/.github/workflows/msrv.yml +++ b/.github/workflows/msrv.yml @@ -15,7 +15,7 @@ jobs: msrv: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: repository: argumentcomputer/ci-workflows persist-credentials: false @@ -24,7 +24,7 @@ jobs: if: inputs.packages != '' with: packages: "${{ inputs.packages }}" - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: persist-credentials: false - uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/rust-version-check.yml b/.github/workflows/rust-version-check.yml index 0520897..039b17b 100644 --- a/.github/workflows/rust-version-check.yml +++ b/.github/workflows/rust-version-check.yml @@ -11,12 +11,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: persist-credentials: false - name: Check out `ci-workflows` - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: repository: argumentcomputer/ci-workflows path: ci-workflows diff --git a/.github/workflows/typos.yml b/.github/workflows/typos.yml index 34ea3ca..cc035a5 100644 --- a/.github/workflows/typos.yml +++ b/.github/workflows/typos.yml @@ -11,7 +11,7 @@ jobs: typo-check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: persist-credentials: false - uses: dtolnay/rust-toolchain@stable @@ -59,7 +59,7 @@ jobs: permission-contents: write permission-pull-requests: write - name: Create pull request - uses: peter-evans/create-pull-request@v7 + uses: peter-evans/create-pull-request@v8 if: steps.typo-check.outputs.typos == 'true' with: token: ${{ steps.generate-token.outputs.token }} diff --git a/.github/workflows/unused-deps.yml b/.github/workflows/unused-deps.yml index 46a1961..9518f1e 100644 --- a/.github/workflows/unused-deps.yml +++ b/.github/workflows/unused-deps.yml @@ -24,10 +24,10 @@ jobs: unused-dependencies: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: persist-credentials: false - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: repository: argumentcomputer/ci-workflows path: ci-workflows diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index 13f0ede..cfedb25 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -11,7 +11,7 @@ jobs: wasm-build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: repository: argumentcomputer/ci-workflows persist-credentials: false @@ -20,7 +20,7 @@ jobs: if: inputs.packages != '' with: packages: "${{ inputs.packages }}" - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 with: persist-credentials: false - uses: dtolnay/rust-toolchain@stable