Skip to content

deps

deps #4

Workflow file for this run

# Weekly `cargo update` PR — the other half of committing Cargo.lock
# (blog.rust-lang.org/2023/08/29/committing-lockfiles): the committed lock pins
# every build, and this job keeps that pin from fossilizing. It refreshes both
# lockfiles (the root workspace and the docling-py bindings workspace), tests
# the workspace against the latest compatible dependency versions right here
# (the post's "run cargo update as part of a scheduled CI job"), and opens a
# PR with the diff. CI on that PR (fmt/clippy, test --locked, msrv) is the
# merge gate — a dependency that breaks the build or raises the MSRV floor
# shows up red on the PR instead of as a release-day surprise.
name: deps
on:
schedule:
- cron: "17 4 * * 1" # Mondays 04:17 UTC
workflow_dispatch:
permissions:
contents: write # push the deps/cargo-update branch
pull-requests: write # open/refresh the update PR
jobs:
# Weekly known-CVE scan of the committed lockfiles. Runs unconditionally
# (not gated on a lockfile change): an advisory can be published against a
# version we already pin, so the value is auditing the *current* tree every
# week, independent of whether `cargo update` moved anything. A finding fails
# the job — the scheduled-run failure is the alarm, same philosophy as the
# in-job test below.
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust (stable)
run: |
rustup toolchain install stable --profile minimal
rustup default stable
- uses: actions/cache@v4
with:
path: |
~/.cargo/bin
~/.cargo/registry/index
~/.cargo/registry/cache
key: ${{ runner.os }}-cargo-audit-bin
- name: Install cargo-audit
# --locked: cargo-audit's own deps have raised the MSRV past stable's
# floor before; pin to its committed lockfile to install reliably.
run: cargo install cargo-audit --locked
- name: Audit both lockfiles
# Known-accepted advisories are ignored by ID so the job fails only on
# NEW findings (an unfiltered audit would go red every week on the
# residual and get tuned out). Keep this list in sync with the
# "Known residual" section of docs/SECURITY.md; drop an entry the week
# its upstream fix lands so a regression can't hide behind the ignore.
# RUSTSEC-2026-0194 / -0195: quick-xml DoS, reachable only via
# calamine's transitive 0.31 pin (XLSX). Our direct quick-xml is
# >=0.41 (patched). Remove when calamine bumps quick-xml.
run: |
IGNORES="--ignore RUSTSEC-2026-0194 --ignore RUSTSEC-2026-0195"
echo "::group::root workspace"
cargo audit $IGNORES
echo "::endgroup::"
echo "::group::docling-py workspace"
cargo audit $IGNORES --file crates/docling-py/Cargo.lock
echo "::endgroup::"
cargo-update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
# Push with the admin PAT when it's configured: branches pushed with
# the default GITHUB_TOKEN don't trigger workflows, so the update PR
# would sit there with no CI verdict.
token: ${{ secrets.RELEASE_PAT || github.token }}
- name: Install Rust (stable)
run: |
rustup toolchain install stable --profile minimal
rustup default stable
- uses: actions/cache@v4
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
target
key: ${{ runner.os }}-cargo-deps-update-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-deps-update-
- name: cargo update (both workspaces)
id: update
run: |
{ cargo update
cargo update --manifest-path crates/docling-py/Cargo.toml
} 2>&1 | tee /tmp/update.log
if git diff --quiet -- Cargo.lock crates/docling-py/Cargo.lock; then
echo "Lockfiles already at the latest compatible versions."
echo "changed=false" >> "$GITHUB_OUTPUT"
else
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
# Test against the fresh resolution in-job, not only on the PR: this red
# is the scheduled "latest deps broke us" alarm even if the PR's own CI
# never runs (e.g. RELEASE_PAT missing).
- name: Test with updated dependencies
if: steps.update.outputs.changed == 'true'
run: cargo test --workspace --locked
- name: Open / refresh the update PR
if: steps.update.outputs.changed == 'true'
env:
GH_TOKEN: ${{ secrets.RELEASE_PAT || github.token }}
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git checkout -B deps/cargo-update
git add Cargo.lock crates/docling-py/Cargo.lock
git commit -m "chore(deps): weekly cargo update"
# Rebase onto master as of *now*, not as of job start: GitHub diffs a
# new branch against the current default branch, and if master gained
# a .github/workflows/ change while this job ran, the push would be
# rejected as a workflow update the token may not be allowed to make.
# (The RELEASE_PAT still needs the `workflow` scope for the weeks
# when the previous deps/cargo-update branch predates a workflow
# change on master — the force-push then legitimately rewrites it.)
git fetch origin master
git rebase origin/master
git push --force -u origin deps/cargo-update
{
echo "Scheduled \`cargo update\` of both committed lockfiles;"
echo "the workspace test suite passed against the new resolution."
echo
echo "<details><summary>cargo update log</summary>"
echo
echo '```'
head -c 60000 /tmp/update.log
echo '```'
echo
echo "</details>"
} > /tmp/pr-body.md
# One rolling PR: force-pushing the branch refreshes an open PR in
# place; create only when none is open.
if [ -z "$(gh pr list --head deps/cargo-update --state open --json number --jq '.[].number')" ]; then
gh pr create \
--title "chore(deps): weekly cargo update" \
--body-file /tmp/pr-body.md
else
gh pr edit deps/cargo-update --body-file /tmp/pr-body.md
fi