From 5d9a96d15c85019549511eaa65178f017b9385f1 Mon Sep 17 00:00:00 2001 From: Dennis Kim Date: Mon, 19 Oct 2026 14:09:21 -0400 Subject: [PATCH] ci: add Dependabot for actions and a weekly dependency check - .github/dependabot.yml: one grouped weekly PR against develop for the GitHub Actions the workflows use. No Cargo version-update PRs (each would run the full container CI; cargo deny already covers advisories), and the pinned devcontainer image stays hand-bumped because three files must match. - .github/workflows/scheduled-deps.yml: `scripts/check.sh deps` every Monday and on demand, so a new RustSec advisory surfaces without a push. Runs only once on the default branch (GitHub schedules from it). - ci_parity_guards: the scheduled workflow must run the devcontainer's pinned image and `check.sh deps`; fails on a drifted tag. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HRWwk1oVv9oLFxjb9cSiCm --- .github/dependabot.yml | 26 +++++++++++++ .github/workflows/scheduled-deps.yml | 34 ++++++++++++++++ crates/devflow-cli/tests/ci_parity_guards.rs | 41 ++++++++++++++++++++ 3 files changed, 101 insertions(+) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/scheduled-deps.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..08a3e65d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,26 @@ +# Dependabot version updates. +# +# Only the GitHub Actions the workflows use are kept current here, as one +# grouped weekly PR against `develop` (git flow: nothing lands on `main` +# except through a release). Cargo dependencies get no version-update PRs: +# each PR runs the full pinned-container CI, and advisories are already +# caught by `cargo deny` (ci.yml's `Dependency checks` job and the weekly +# .github/workflows/scheduled-deps.yml). +# +# The pinned devcontainer image is deliberately not managed here: it is +# repeated in .devcontainer/devcontainer.json, ci.yml and scheduled-deps.yml, +# which tests/ci_parity_guards.rs requires to match, so a bump in one file +# alone would fail CI. Bump it by hand in all of them at once. +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + target-branch: "develop" + schedule: + interval: "weekly" + groups: + github-actions: + patterns: + - "*" + commit-message: + prefix: "ci" diff --git a/.github/workflows/scheduled-deps.yml b/.github/workflows/scheduled-deps.yml new file mode 100644 index 00000000..22b2d501 --- /dev/null +++ b/.github/workflows/scheduled-deps.yml @@ -0,0 +1,34 @@ +# Weekly dependency checks, so a newly published RustSec advisory against a +# dependency nobody touched still turns something red. ci.yml's `Dependency +# checks` job runs the same `scripts/check.sh deps`, but only on push and PR. +# +# GitHub runs scheduled workflows from the default branch (`main`) only, so +# this takes effect once a release carries it there. `workflow_dispatch` runs +# it on demand from any branch. +# +# The image must stay identical to .devcontainer/devcontainer.json's +# (tests/ci_parity_guards.rs: scheduled_deps_workflow_runs_the_pinned_image). +name: Scheduled dependency checks + +on: + schedule: + - cron: "17 6 * * 1" + workflow_dispatch: + +permissions: + contents: read + +jobs: + deps: + name: Dependency checks (scheduled) + runs-on: ubuntu-24.04 + container: + image: mcr.microsoft.com/devcontainers/rust:2.0.13-1-bookworm + timeout-minutes: 30 + steps: + - uses: actions/checkout@v7 + - name: Trust the workspace + run: git config --global --add safe.directory "$GITHUB_WORKSPACE" + - name: Install the pinned dependency tools + run: scripts/install-dep-tools.sh + - run: scripts/check.sh deps diff --git a/crates/devflow-cli/tests/ci_parity_guards.rs b/crates/devflow-cli/tests/ci_parity_guards.rs index 6dcd55be..d74752f0 100644 --- a/crates/devflow-cli/tests/ci_parity_guards.rs +++ b/crates/devflow-cli/tests/ci_parity_guards.rs @@ -344,6 +344,47 @@ fn ci_workflow_runs_the_pinned_devcontainer_image() { } } +/// The weekly dependency workflow repeats ci.yml's `Dependency checks` job +/// outside the push/PR triggers, so it must run the same pinned image and the +/// same `scripts/check.sh deps`, on a schedule. Nothing else compares its +/// image with the devcontainer's, so without this a bump in the other two +/// files would leave it silently on the old image. +#[test] +fn scheduled_deps_workflow_runs_the_pinned_image() { + let root = repo_root(); + let workflow = read(&root.join(".github/workflows/scheduled-deps.yml")); + let devcontainer = read(&root.join(".devcontainer/devcontainer.json")); + let image = devcontainer + .lines() + .map(str::trim) + .find(|l| l.starts_with("\"image\"")) + .and_then(|l| l.split('"').nth(3)) + .expect("read \"image\" from devcontainer.json"); + + let lines = code_lines(&workflow); + let images: Vec<&str> = lines + .iter() + .filter_map(|l| l.trim().strip_prefix("image:")) + .map(str::trim) + .collect(); + assert_eq!( + images, + [image], + "scheduled-deps.yml must run exactly one container, the image \ + devcontainer.json declares" + ); + assert!( + lines + .iter() + .any(|l| l.trim() == "- run: scripts/check.sh deps"), + "scheduled-deps.yml must run `scripts/check.sh deps`" + ); + assert!( + lines.iter().any(|l| l.trim() == "schedule:"), + "scheduled-deps.yml must run on a schedule" + ); +} + /// `devflow test` is documented as the local mirror of CI's quality gates, /// so its clippy invocation must match the workflows' scope. It ran the /// narrow pre-Phase-17 form until this fix (17-REVIEW.md WR-10), which made