Skip to content

ci(dependabot): the caps Dependabot was supposed to respect, the gate that asked the wrong question, and a test that measured the scheduler - #121

Merged
wshallwshall merged 10 commits into
mainfrom
claude/github-actions-workflow-4ac072
Aug 1, 2026
Merged

ci(dependabot): the caps Dependabot was supposed to respect, the gate that asked the wrong question, and a test that measured the scheduler#121
wshallwshall merged 10 commits into
mainfrom
claude/github-actions-workflow-4ac072

Conversation

@wshallwshall

Copy link
Copy Markdown
Collaborator

Triage of the red CI legs plus an end-to-end Dependabot audit. Six commits, one layer each.

The main-branch red (test_run_load_end_to_end_no_loss) is not here — #115 fixed that and has merged.

What was failing

Failure Cause
Dependabot #66: 8 FHIR ImportErrors (windows-2022) + 868 ruff findings (ubuntu) the uv ecosystem had no ignore:, so Dependabot widened both deliberate caps
test_coord_lock "expected exactly 1 winner, got 2" (windows-2025, run 30672004091) the test, not the lock — a winner count measures the scheduler

The caps were worse than decorative

Dependabot rewrites a declared upper bound rather than respecting it. PR #66 widened
annotated-types<0.8<0.9 (both declaration sites) and ruff>=0.4,<0.16<0.17, and the
lock resync then propagated 0.8.0/0.16.0 into constraints.lock — so ci.yml's --constraint
pinned CI to the broken versions. python-deps groups on *, so the two of them red the whole
batch and hold every benign bump hostage.

The npm ecosystem has carried exactly this pattern since #649/#877; uv never got it.

Accepted trade-off, recorded inline: a Dependabot ignore suppresses the SECURITY track for the
named range too (update-types is version-only and cannot express a range). Detection is untouched —
the required pip-audit -r requirements.lock runs on every PR and a daily cron, so a withheld fix
reds a merge-blocking gate within ~24h and a human lifts the pyproject cap, which is the real ceiling
either way.

The GHSA gate asked about the wrong versions

fetch-metadata's scalar previous-version is the first dependency's even on a grouped PR —
output.ts:27 reads firstDependency?.prevVersion, verified at the pinned SHA 25dd0e34 (v3.1.0).
The gate applied it to every name in the group, so a five-dep PR asked about four versions the PR does
not touch. That fails permissively: advisory ranges are mostly open at the bottom, so a low
first-dep version confirms almost anything. Demonstrated on the real shape — a group of aiohttp 3.9.0

  • Pillow 10.2.0 queries pillow@3.9.0, a 2016 release, and returns a confirmation.

Switched to updated-dependencies-json, which carries a per-dependency prevVersion, and closed a
fail-open case that came with it: update_metadata.ts:101 falls back to an empty prevVersion for
index > 0, and an unknown previous version must deny rather than skip on a gate whose contract is to
fail closed.

Verified by executing the step against a stubbed advisories endpoint: each dep queried at its own
version; no-advisory, empty-prevVersion, malformed-metadata and version-track all deny. The old loop
was run against the same input first, to confirm the test can see the defect.

A zizmor bump never ran zizmor

zizmor's pinned version arrives from ci/locks/ci-scanners.lock (installed at zizmor.yml:53) —
outside the .github/** paths filter. PR #66 bumps zizmor 1.5.2 → 1.28.0 and ran 33 check contexts,
not one of them zizmor, so a 23-minor jump against a deliberately clean baseline would first have been
adjudicated by the 06:00 cron, against main, after merge.

The coord_lock test measured the scheduler

The lock is correct. The barrier releases the cohort together, but each process then runs
Enter-CoordLock's own prologue — a git rev-parse spawn at lock.ps1:47 — before its deadline is
set at lock.ps1:56, and nothing synchronizes that. A winner count tolerates only
hold - timeout = 500 ms of that skew, against a measured 645–2134 ms. A straggler arriving after the
winner released acquires legitimately and is counted as a violation; hold intervals in five
multi-winner rounds were measured strictly disjoint.

Not a flake. Under 40 CPU burners on a 20-core box:

result
old winner-count assertion 0/6 pass (2–3 winners)
new occupancy assertion 6/6 pass
new assertion vs a no-op stubbed lock fails, 7 simultaneous holders

It now asserts occupancy — a CreateNew sentinel taken under the lock, the same atomic test-and-set
the lock itself uses, with no reference to a clock. Cost: hold_ms 1500 → 8000 for a ~3.3x margin over
the measured skew, so the test's floor wall-time is ~9 s.

Also

  • Four plain-pip install -e legs (benchmark ×3, selfhosted-win2025-sql) had no --constraint, so
    they would have adopted the same breaking versions. freethread-smoke stays unconstrained on
    purpose and now says why — pinning GIL-build versions there can send pip to a source build and the
    canary stops measuring free-threading.
  • Settles the config's own UNVERIFIED question: the uv ecosystem does reach PEP 735
    [dependency-groups] (PR build(deps): bump the python-deps group across 1 directory with 5 updates #66 bumped zizmor inside ci-scanners). Scoped to what the evidence
    supports — at least ci-scanners, routine track only.
  • Three cap comments described a uv pip install CI no longer runs, and offered "once CI installs from
    the hashed lock" as an exit condition that would not retire the cap.
  • Adds a 5-day cooldown to github-actions — the one ecosystem where auto-merge demonstrably fires,
    and where a compromised release runs inside CI with the job's token. SHA-pinning stops tag mutation,
    not a malicious new release.

Verification

ruff format --check ., ruff check . clean. mypy is unchanged by this branch — it touches no file
under messagefoundry/. Full pytest running at time of writing; tests/test_coord_lock.py,
tests/test_dependabot_automerge_guardrails.py and tests/test_required_contexts.py pass, and every
run: block in the edited workflows was bash-syntax-checked and actionlint-clean.

No lock file is touched, so DEP-1 is unaffected.

CI-only, cannot be proven locally: the ignore: taking effect (falsifiable on the next uv PR —
annotated-types and ruff must be absent from the pyproject diff entirely, and constraints.lock
must still read annotated-types==0.7.0 / ruff==0.15.22); the GHSA loop, which only runs on a
Dependabot-authored PR; zizmor 1.28.0 against the clean baseline.

Follow-up for the owner

PR #66 needs @dependabot recreate after this merges — Dependabot reads config from the default
branch, so the ignore rules must land first. Not a plain close, and not rebase-and-hand-revert (a human
push makes dependabot-lock-resync.yml skip; its gate requires triggering_actor == 'dependabot[bot]').
The recreated PR carries fastapi + prometheus-client + zizmor and needs a manual merge — fastapi is
deny-listed.

Open questions left alone deliberately: the hvac prose/spec mismatch (pyproject.toml:167-169
documents a 2.x hold that hvac>=2.3.0 does not encode — the fix needs uv lock); pre-emptive ignores
for pydicom/pynetdicom/webauthn (recommend skipping — no 4.x exists, and an ignore on webauthn would
suppress its security track for no present benefit); and ide-security PRs hitting the GHSA loop with
ecosystem=pip hardcoded, which is pre-existing and fails closed.

No ADR or BACKLOG number was consumed.

🤖 Generated with Claude Code

…respect

Dependabot rewrites a declared upper bound rather than respecting it, so a
load-bearing cap in pyproject.toml is decorative unless it is restated as an
ignore range here. PR #66 widened `annotated-types<0.8` -> `<0.9` (both
declaration sites) and `ruff>=0.4,<0.16` -> `<0.17`; the lock resync then
propagated 0.8.0/0.16.0 into constraints.lock, so ci.yml's `--constraint`
pinned CI *to* the broken versions — 8 FHIR ImportErrors on windows-2022 and
868 ruff findings on ubuntu. `python-deps` groups on `*`, so the two of them
red the whole batch and hold every benign bump in it hostage.

The ignore entries suppress the security track for the named RANGE too;
that is accepted and recorded inline, because detection does not depend on
Dependabot — the required `pip-audit -r requirements.lock` gate reds within
~24h and a human lifts the pyproject cap, which is the real ceiling either way.

Also corrects two comments the evidence retired: the header still claimed no
committed lockfile exists, and the PEP 735 question is settled — PR #66 bumped
`zizmor` inside `[dependency-groups].ci-scanners`, so the uv ecosystem does
reach it.
…er runs

Both annotated-types and ruff caps said "CI installs with a FRESH resolve
(uv pip install -e ...)" in the present tense. It does not: every uv install
in ci.yml, quality-advisory.yml and dast.yml passes `--constraint
constraints.lock`. That mattered for more than tidiness — it framed the cap as
a CI workaround with "or once CI installs from the hashed lock" as an exit
condition, which is wrong in both directions. The cap bounds the RESOLVER, and
the lock carries whatever the resolver already chose, so installing from the
lock would not retire it; meanwhile it is also what bounds every resolve CI
never sees (an end user's `pip install messagefoundry[fhir]`, the local dev
venv, dispatch-only legs).

The fhir extra additionally claimed the cap "lives here rather than in
[project.dependencies]" while an identical cap sat 67 lines above it.

Stops restating the ruff finding count: 626, ~525 and 868 were three numbers
for one fact at two different scopes. States it once, as a bound, dated.

No version specifier changed and no lock is touched — comments only.
The paths filter listed only `.github/**`, but zizmor's own pinned version
lives in pyproject.toml's [dependency-groups].ci-scanners and reaches the
install step through ci/locks/ci-scanners.lock — outside the filter. So PR #66,
which bumps zizmor 1.5.2 -> 1.28.0, ran 33 check contexts and not one of them
was zizmor: a 23-minor jump against a deliberately clean baseline would have
been adjudicated by the 06:00 cron, against main, after merge.

Adds the lock to the filter and corrects the header, whose "a Python / docs /
test PR cannot change its result" is precisely what a lock-only bump disproves.
The lock also carries bandit and pip-audit, so their bumps now trigger this
workflow too (~1 billed min) — arguably correct, since bandit is the other
clean-baseline gate.

Also states the filter once: three docs restated its contents verbatim, which
is three things to forget when it changes. They now point at the workflow.
fetch-metadata's scalar `previous-version` is the FIRST dependency's, even on a
grouped PR — output.ts:27 reads `firstDependency?.prevVersion` (verified at the
pinned SHA 25dd0e34, v3.1.0). The gate applied it to every name in the group, so
on a five-dep PR it asked about four versions the PR does not touch. That fails
in the PERMISSIVE direction: advisory ranges are mostly open at the bottom, so a
low first-dep version confirms almost anything. Demonstrated on the real shape —
a group of aiohttp 3.9.0 + Pillow 10.2.0 queries `pillow@3.9.0` (a 2016 release)
and returns a confirmation.

Switches to `updated-dependencies-json`, which carries a per-dependency
prevVersion, and closes a fail-open case the scalar never had: update_metadata.ts:101
falls back to an EMPTY prevVersion for index > 0, and an unknown previous version
must deny rather than skip on a gate whose contract is to fail closed.

Verified by executing the step against a stubbed advisories endpoint: each dep is
queried at its own version; no-advisory, empty-prevVersion, malformed-metadata and
version-track all deny. The old loop was run against the same input first, to
confirm the test can see the defect.

Also adds a 5-day cooldown to github-actions — the one ecosystem where auto-merge
demonstrably fires, and the one where a compromised release runs inside CI with
the job's token. SHA-pinning stops tag mutation, not a malicious new release.

And scopes the IN SCOPE header, which read as though uv routinely auto-merges;
in practice `patterns: ["*"]` plus the deny-list makes it review-by-default.
…mutual exclusion

The lock is correct. `test_only_one_of_eight_concurrent_claimants_wins` counted
winners, which measures the scheduler: the barrier releases the cohort together,
but each process then runs Enter-CoordLock's own prologue — a `git rev-parse`
spawn at lock.ps1:47 — before its deadline is set at lock.ps1:56, and nothing
synchronizes that. A winner count tolerates only (hold - timeout) = 500 ms of
that skew. So a straggler that arrives after the winner released acquires
legitimately and is counted as a violation.

That is what failed on windows-2025 in run 30672004091, and it is not a flake:
under 40 CPU burners on a 20-core box the old assertion fails 6/6 (2-3 winners),
the new one passes 6/6.

Asserts occupancy instead — a CreateNew sentinel taken under the lock, the same
atomic test-and-set the lock itself uses, with no reference to a clock. Validated
both directions: with Enter-CoordLock stubbed to a no-op it fails with 7
simultaneous holders, so the assertion can see the defect class it claims to
exclude.

Cost: hold_ms 1500 -> 8000 to keep a ~3.3x margin over the measured skew, so this
test's floor wall-time is ~9 s.
Every uv install in ci.yml, quality-advisory.yml and dast.yml passes
`--constraint constraints.lock`; the four plain-pip legs did not, so they
re-resolved from pyproject's `>=` floors and would have adopted ruff 0.16.0 and
annotated-types 0.8.0 on the day those shipped, exactly as PR #66 did. A
benchmark leg is the worst place for that — a silent dependency change reads as
a performance regression.

freethread-smoke stays unconstrained on purpose and now says so. The lock
records what resolved for the GIL build; pinning it there can leave a dep with
no cp314t wheel at that version and send pip to a source build, so the canary
would stop measuring free-threading and start measuring the lock.
@wshallwshall
wshallwshall enabled auto-merge (squash) August 1, 2026 14:00
@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Merged main in and picked up one commit that is not mine in spirit.

The first CI pass failed tests/test_backlog_status_check.py — and it was not this branch. BACKLOG
#320, filed on main at 13:26 (30701716567), used > 📋 **Filed 2026-08-01, not started.**. The
status gate accepts five glyphs (✅ / ⛔ / 🪦 closed, 🔢 / 🚧 open) and 📋 is not one, so the item
read as declaring no status.

main was already red for this — both the ubuntu and windows-2022 legs — and every PR opened since
inherits it through the merge ref. Verified no other PR or branch carries a fix: #118 is the same
session's related harness work and references #320 but does not touch the banner.

Fixed as 07c91713: 📋 → 🚧, wording unchanged, still exactly one banner on the item. Anyone reviewing
this PR should know that commit fixes a defect from a different session's work; it is here because it
had to be, not because it belongs to the Dependabot topic.

Also merged origin/main (the PR was BEHIND). No conflicts.

@wshallwshall

Copy link
Copy Markdown
Collaborator Author

Correction to my previous comment — the BACKLOG #320 fix has been split out to #122.

Commit 07c91713 is no longer on this branch (force-pushed with lease; the commit is preserved on
backlog-320-banner-glyph). This PR is back to a single topic: the Dependabot caps, the GHSA gate, the
zizmor paths filter, and the coord_lock test.

Consequence, stated plainly: this PR will stay red on
tests/test_backlog_status_check.py::test_the_real_backlog_satisfies_the_invariant until #122 merges.
That failure is main's, not this branch's — it reproduces on origin/main at
run 30701716567. Merge #122
first and this goes green without another change here.

The origin/main merge (d22d6f97) stays — this PR was BEHIND and needed it regardless.

The earlier "state it once, link to it" edit replaced the restated filter
contents with "(see `zizmor.yml`)" at four sites — but every one of those lines
already has zizmor.yml as its subject, so the pointer was circular. CI.md:147
was the worst: "`zizmor.yml` (which is already paths-filtered (see
`zizmor.yml`))".

Drops the pointer instead. The subject is already named, so plain
"paths-filtered" states the fact without restating its contents, which is what
the rule was after.
@wshallwshall
wshallwshall merged commit 2a6649f into main Aug 1, 2026
37 checks passed
@wshallwshall
wshallwshall deleted the claude/github-actions-workflow-4ac072 branch August 1, 2026 16:00
wshallwshall added a commit that referenced this pull request Aug 2, 2026
…d pin the premises (#130)

* build(deps): bump the python-deps group across 1 directory with 3 updates

Bumps the python-deps group with 3 updates in the / directory: [fastapi](https://github.com/fastapi/fastapi), [prometheus-client](https://github.com/prometheus/client_python) and [zizmor](https://github.com/zizmorcore/zizmor).


Updates `fastapi` from 0.139.2 to 0.140.4
- [Release notes](https://github.com/fastapi/fastapi/releases)
- [Commits](fastapi/fastapi@0.139.2...0.140.4)

Updates `prometheus-client` from 0.25.0 to 0.26.0
- [Release notes](https://github.com/prometheus/client_python/releases)
- [Commits](prometheus/client_python@v0.25.0...v0.26.0)

Updates `zizmor` from 1.5.2 to 1.28.0
- [Release notes](https://github.com/zizmorcore/zizmor/releases)
- [Changelog](https://github.com/zizmorcore/zizmor/blob/main/docs/release-notes.md)
- [Commits](zizmorcore/zizmor@v1.5.2...v1.28.0)

---
updated-dependencies:
- dependency-name: fastapi
  dependency-version: 0.140.4
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python-deps
- dependency-name: prometheus-client
  dependency-version: 0.26.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: python-deps
- dependency-name: zizmor
  dependency-version: 1.28.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: python-deps
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore(deps): resync exported lock files (DEP-1)

* fix(ci): label the setup-node pins v7.0.0 — the SHA has been v7 since 2026-07-26

Three pins read `actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6`
while that SHA is what `refs/tags/v7` AND `refs/tags/v7.0.0` point at — verified
against the upstream refs API, not inferred from the lint. So the repo has been
running setup-node v7 for a week with a comment asserting v6.

This RATIFIES a major already in force; it is not a cosmetic label fix. v7 is
green on both `ide build` legs and on the required `npm-audit` job, and reverting
to the v6 line would be worse, not safer: v6 carries fast-xml-parser 5.9.3, which
sits inside GHSA-8r6m-32jq-jx6q, while v7.0.0's 5.7.2 is in no open advisory
range.

The SHA is unchanged. Only the comment moves, and all three move together —
one Dependabot change introduced them and they must not drift apart.

Surfaced by zizmor 1.28.0's ref-version-mismatch audit, which could not run
before #121 put ci/locks/ci-scanners.lock in the zizmor paths filter.

* ci(zizmor): retire the dead ignore entry and the claims that rotted with it

The config header calls every entry "a REVIEWED, justified non-finding", which
makes a stale one worse than noise — it reads as a reviewed risk that is actually
unexamined. Five had rotted, each verified against the tree rather than taken
from the lint:

  * `release-sync-check.yml` is ignored under artipacked, but that workflow was
    deleted in 59fbc93 (2026-07-26). An entry naming a file that cannot produce
    a finding is dead config presenting as coverage.
  * "The jobs below do not push" — `dependabot-lock-resync.yml` is in that list
    and pushes at line 160. The carve-out two lines below already says so.
  * "release.yml sets persist-credentials: false on both checkouts" — it has
    three (73, 371, 498), all false. The claim is right and the count is a
    liability, so the count goes.
  * "cla.yml ... does check out" — cla.yml has zero checkouts. The comparison it
    was drawing still holds on a different axis (third-party code vs none), so
    that is what it now says.
  * "See the SECURITY note in cla.yml" — cla.yml contains no such note. A
    security justification whose only citation does not resolve.

Adds tests/test_zizmor_config_hygiene.py so the first one cannot recur: every
ignore entry must name a live workflow. Validated both directions — it passes on
this tree and fails when the deleted entry is put back. It also prints what it
scanned, so a run that silently covered nothing is distinguishable from a pass.

* ci(zizmor): record bot-conditions on the resync gate as a justified non-finding

zizmor 1.28.0 reports `github.triggering_actor == 'dependabot[bot]'` at
dependabot-lock-resync.yml:76 as a spoofable bot actor check. The observation is
correct and the gate is still FAIL-CLOSED, because that expression is the second
half of a conjunction:

    github.event.pull_request.user.login == 'dependabot[bot]'
    && github.triggering_actor == 'dependabot[bot]'

Clause 1 is the immutable PR author — the exact context this audit recommends as
the replacement. A conjunction only narrows, so spoofing the actor can make the
job SKIP, never run, and skipping is safe: DEP-1 lock sync is independently
enforced by security.yml's pip-audit job, a required context on an unfiltered
trigger. zizmor itself agrees enough to report at MEDIUM confidence, treating
`And` as non-dominating.

So this is suppressed, line-anchored, not fixed — and PR #121's description
needs no correction: it claimed a human push makes the job skip, which is the
fail-closed direction, while this audit is about a check wrongly passing.

Two things the suppression does NOT rely on prose for:

  * tests/test_dep1_lock_resync_lockstep.py now pins the premise — clause 1
    present, conjoined, no `||`. Validated by mutation: flipping `&&` to `||` and
    deleting clause 1 each turn it red. Without this the suppression would be an
    assertion about a shape nothing enforces.
  * The comment records that zizmor's auto-fix for this audit is classified SAFE,
    so a bare `zizmor --fix` would apply it silently — substituting clause 1 for
    clause 2, collapsing the condition to `A && A` and deleting the self-trigger
    skip, with every check still green.

* ci(zizmor): accept the archived CLA action as a dated residual (ADR 0034)

zizmor 1.28.0's archived-uses audit is right: contributor-assistant/github-action
is archived upstream (API archived: true, last push 2026-03-23) and v2.6.1 is the
final release. Our pin equals that tag's commit exactly, so there is no later
patch to move to. Recorded as an accepted residual, not waved away as a false
positive.

The SHA pin closes tampering — a bundled JS action's SHA fully determines the
bytes that run — but not the axis the audit names: a flaw already at that SHA
will never be fixed.

Not replaced now, deliberately. `cla` is a required status context AND is the
job's own conclusion, so a broken step blocks every contribution; and because
pull_request_target/issue_comment workflows run only from the default branch, a
replacement cannot be exercised on the PR that makes it — it would land on main
untested with approvals at 0 and auto-merge armed.

The forcing function is not this lint: action.yml declares `runs.using: node20`
at the pin and at the archived HEAD, so an archived repo can never re-declare
node24 and GitHub's fall-2026 Node20 removal decides it. The suppression is dated
and says to re-check before then, rather than being open-ended.

The ADR amendment records a contingency candidate with its provenance checked
rather than asserted: iainmcgin/cla-github-action is real, Apache-2.0, unarchived
— and its v3.2.0 is an ANNOTATED tag, so the ref resolves to a tag object, not the
commit. The commit `uses:` must pin was dereferenced and confirmed. Pinning the
tag-object SHA would be the same mismatch class fixed two commits ago.

* ci: hand the setup-node label fix to the timeout PR to clear the collision gate

Drops this branch's one-line ci.yml hunk (`# v6` -> `# v7.0.0` at :301). The
change is not abandoned — the "Stuck CIs" session is carrying it in the same
commit as the W22/W25 timeout raise.

Why: the collision gate keys on a branch's DIFF against main, not on whether a
session is actively editing. Standing down verbally did not clear it; while this
branch carried any ci.yml hunk, `ci.yml` read as in-flight and the timeout edit
was refused. That mattered because #130 is itself running against the 26:00 cap
the timeout fix raises — so a timeout on this PR would have trapped the fix for
the timeout behind a PR that died of it.

Known consequence, accepted: until that commit reaches main, zizmor reports
ref-version-mismatch on ci.yml:301 again — measured, 1 medium, exit 13 — so this
PR's zizmor check is RED in the interim. It clears when main carries the label
fix and this branch merges it. The other two sites (security.yml:159, :189) keep
their fix here.

Side benefit: #130 is now purely "adopt a scanner and adjudicate its findings",
which is the topic separation this PR argued for.

* Revert "ci: hand the setup-node label fix to the timeout PR to clear the collision gate"

This reverts dcccf9d. The handover did not complete: #131 landed the W22/W25
timeout raise but does NOT touch setup-node, so nothing else carries the
`# v6` -> `# v7.0.0` label.

Taking it back is now urgent rather than tidy. zizmor is deliberately NOT a
required context, so a red zizmor cannot block #130 — and #130 has auto-merge
armed. Left as-is, this PR would have landed zizmor 1.28.0 on main together with
an unfixed ref-version-mismatch, redding the 06:00 cron that nothing alerts on
(nightly-notice.yml watches CI only). That is precisely the outcome this PR
exists to prevent, arriving through the PR that prevents it.

The reason for handing it over is gone: the collision gate keys on a branch's
diff, and #131's ci.yml edit is already committed and pushed, so re-adding this
hunk cannot block it.

Restores one comment. SHA unchanged; the pin has resolved to v7.0.0 since
2026-07-26.

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant