Skip to content

ci: Add cargo to dependabot so openjd-rs releases open their own PR - #336

Open
leongdl wants to merge 1 commit into
OpenJobDescription:mainlinefrom
leongdl:ci/dependabot-cargo
Open

ci: Add cargo to dependabot so openjd-rs releases open their own PR#336
leongdl wants to merge 1 commit into
OpenJobDescription:mainlinefrom
leongdl:ci/dependabot-cargo

Conversation

@leongdl

@leongdl leongdl commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Dependabot watches pip and github-actions but not cargo, so a new openjd-expr /
openjd-model / openjd-sessions release is only noticed when somebody goes looking.
#335 is the worked
example: the crates published, and picking them up was a manual chase for pins, Cargo.lock, and
THIRD-PARTY-LICENSES.txt. This makes that arrive as a PR on its own.

Loosening the version requirements would not have helped

Worth stating because it is the obvious alternative. The requirements are already permissive
enough — openjd-model = "0.5.2" is ^0.5.2, so >=0.5.2, <0.6.0, and a 0.5.3 satisfies it
without an edit. Cargo.lock is what actually pins the build, and it is committed and is what CI
resolves from. So a patch pickup needs a cargo update and a commit no matter how loose the
requirement string is, and a * requirement would buy nothing while giving up the reproducibility
the lock exists for.

Why patch-only grouping, unlike the pip entry

Bump Lands as
openjd-model 0.5.2 -> 0.5.3 grouped, one PR with any other patch bumps
openjd-expr 0.3.0 -> 0.4.0 its own PR

Every crate here is pre-1.0, and cargo treats a minor bump of a 0.x crate as breaking. That is not
theoretical: openjd-expr 0.4.0 carried a [**breaking**] coercion change, and openjd-model
0.5.2 changed the job-side StepScript wire format. Those deserve their own CI run and their own
review rather than riding along with a patch. The pip entry groups minor and patch together
because its dependencies are 1.0+, where minor is additive.

The one manual step this leaves

scripts/check_third_party_licenses.sh fails on a Cargo.lock change alone, so that check will be
red on every cargo PR until the file is regenerated [measured — a lock-only diff of the three
openjd versions failed the check]. The follow-up is one command pushed to the dependabot branch:

scripts/check_third_party_licenses.sh --update

(Alternate, if you would rather it be zero-touch) a scheduled workflow that runs
cargo update -p openjd-expr -p openjd-model -p openjd-sessions, regenerates the license file, and
opens the PR itself. That removes the manual step and scopes updates to the three crates that
matter, at the cost of ~40 lines of workflow YAML and a token with PR-write permission. I went with
dependabot because it matches what this repo already does; happy to switch if you prefer the
workflow.

Testing

Config parses as YAML and declares all three ecosystems; the cargo entry's directory: "/" is
where Cargo.toml and Cargo.lock actually live, with rust-bindings picked up as a workspace
member. I cannot run dependabot itself, so the schedule and grouping behaviour are unverified
until it runs on Monday.

Signed-off-by: David Leong <leongdl@amazon.com>
@leongdl
leongdl requested a review from a team as a code owner August 22, 2026 01:47
Comment thread .github/dependabot.yml
update-types:
- "minor"
- "patch"
- package-ecosystem: "cargo"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enabling the cargo ecosystem will make every Dependabot Rust PR fail CI, because Dependabot updates Cargo.lock but cannot regenerate THIRD-PARTY-LICENSES.txt.

The third_party_licenses job in .github/workflows/rust_quality.yml runs scripts/check_third_party_licenses.sh, which renders the Rust section from Cargo.lock via cargo about generate and then hard-fails on any diff:

if ! diff -u "$OUTPUT_FILE" "$generated"; then
  ...
  exit 1
fi

The committed file embeds exact crate versions (** tokio; version 1.53.1, ** memchr; version 2.8.3, ...), so a bump of any crate — including a transitive patch bump inside the cargo-patch group — changes the rendered output and trips the check. There is no path for a bot-authored PR to fix this on its own, so cargo Dependabot PRs will land permanently red and need a manual scripts/check_third_party_licenses.sh --update commit pushed onto each one.

Worth deciding up front which way to go, e.g.:

  • add a job (or a Dependabot-triggered workflow with contents: write) that runs --update and commits back to the Dependabot branch, or
  • make the license check advisory / non-blocking for dependabot[bot]-authored PRs, or
  • accept the manual step and document it.

Note this is specific to cargo: the existing pip group only bumps requirements-*.txt (dev/test), which the script does not include since it resolves Python deps from the installed wheel's runtime closure.

Comment thread .github/dependabot.yml
# group and so each get their own individual PR, because every crate this
# package depends on is pre-1.0: for a 0.x crate cargo treats a minor bump
# as breaking, so openjd-expr 0.3 -> 0.4 deserves its own review rather
# than riding along with a patch.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stated goal — "openjd-expr 0.3 -> 0.4 deserves its own review rather than riding along with a patch" — is defeated by .github/workflows/auto_approve.yml, which approves any PR authored by dependabot[bot] with no filtering on update type:

if: ${{ github.actor == 'dependabot[bot]' }}
steps:
  - uses: dependabot/fetch-metadata@v3
    id: metadata
  - run: gh pr review --approve "$PR_URL"

So the isolated-PR-per-minor-bump split buys separation but not review: a 0.3 -> 0.4 bump of openjd-expr/openjd-model/openjd-sessions — the crates that actually carry the API surface this package binds to — arrives pre-approved. That is the highest-risk update class this config can produce, and it is exactly the one that gets waved through.

fetch-metadata is already wired up (id: metadata) but its outputs are unused, so gating is cheap, e.g. restrict auto-approve to patch bumps:

if: steps.metadata.outputs.update-type == 'version-update:semver-patch'

(That is a change to auto_approve.yml, not this file, but it is this PR that makes it load-bearing for Rust deps.)

Comment thread .github/dependabot.yml
prefix: "chore(deps):"
# Patch bumps are combined into a single PR. Minor bumps do not match this
# group and so each get their own individual PR, because every crate this
# package depends on is pre-1.0: for a 0.x crate cargo treats a minor bump

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"every crate this package depends on is pre-1.0" is not accurate, and it is the premise the grouping choice rests on. Per rust-bindings/Cargo.toml:

crate req pre-1.0?
openjd-expr 0.3.0 yes
openjd-model 0.5.0 yes
openjd-sessions 0.5.0 yes
pyo3 0.29 yes
pyo3-log 0.13 yes
pyo3-stub-gen 0.22 yes
log 0.4 yes
windows 0.62 yes
tokio 1 no
uuid 1 no
serde_json 1 no

For the three 1.x crates a minor bump is explicitly non-breaking under cargo's semver rules, so the "0.x minor == breaking, so isolate it" rationale does not apply to them — yet they are excluded from cargo-patch and will each open a standalone PR (tokio 1.53 -> 1.54, etc.) for a compatible update. Combined with transitive deps in Cargo.lock, that is a fair amount of avoidable PR churn.

If the intent is "isolate only the genuinely-breaking 0.x minors", consider adding a second group that sweeps up the 1.x minors, e.g.:

groups:
  cargo-patch:
    patterns: ["*"]
    update-types: ["patch"]
  cargo-stable-minor:
    patterns: ["tokio", "uuid", "serde_json"]
    update-types: ["minor"]

Otherwise the comment should just be corrected to say most deps are pre-1.0 and the per-PR split is being accepted for all minors for simplicity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant