ci: Add cargo to dependabot so openjd-rs releases open their own PR - #336
ci: Add cargo to dependabot so openjd-rs releases open their own PR#336leongdl wants to merge 1 commit into
Conversation
Signed-off-by: David Leong <leongdl@amazon.com>
| update-types: | ||
| - "minor" | ||
| - "patch" | ||
| - package-ecosystem: "cargo" |
There was a problem hiding this comment.
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
fiThe 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--updateand 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.
| # 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. |
There was a problem hiding this comment.
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.)
| 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 |
There was a problem hiding this comment.
"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.
Dependabot watches
pipandgithub-actionsbut notcargo, so a newopenjd-expr/openjd-model/openjd-sessionsrelease 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, andTHIRD-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 itwithout an edit.
Cargo.lockis what actually pins the build, and it is committed and is what CIresolves from. So a patch pickup needs a
cargo updateand a commit no matter how loose therequirement string is, and a
*requirement would buy nothing while giving up the reproducibilitythe lock exists for.
Why patch-only grouping, unlike the pip entry
openjd-model0.5.2 -> 0.5.3openjd-expr0.3.0 -> 0.4.0Every crate here is pre-1.0, and cargo treats a minor bump of a 0.x crate as breaking. That is not
theoretical:
openjd-expr0.4.0 carried a[**breaking**]coercion change, andopenjd-model0.5.2 changed the job-side
StepScriptwire format. Those deserve their own CI run and their ownreview rather than riding along with a patch. The
pipentry groups minor and patch togetherbecause its dependencies are 1.0+, where minor is additive.
The one manual step this leaves
scripts/check_third_party_licenses.shfails on aCargo.lockchange alone, so that check will bered 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:
(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, andopens 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
cargoentry'sdirectory: "/"iswhere
Cargo.tomlandCargo.lockactually live, withrust-bindingspicked up as a workspacemember. I cannot run dependabot itself, so the schedule and grouping behaviour are unverified
until it runs on Monday.