Skip to content

ci: run the suite weekly against re-resolved dependencies - #116

Merged
Shashankss1205 merged 2 commits into
mainfrom
ci/weekly-upstream-drift
Sep 25, 2026
Merged

Shashankss1205 merged 2 commits into
mainfrom
ci/weekly-upstream-drift

Conversation

@Shashankss1205

@Shashankss1205 Shashankss1205 commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Every trigger on ci.yml was caused by someone pushing, so the suite only ever ran against the versions uv.lock pins. That is correct for a pull request and wrong as the only signal: a langgraph minor that breaks the runtime stays invisible here until a user on a fresh pip install grapharc hits it.

That is the standing complaint in #103 — every extra but mcp is unbounded, and the lockfile hides what the next major would do. With six weeks between commits there is currently no signal at all.

What this adds

  • A Monday 06:00 UTC schedule trigger.
  • One upstream-drift job that runs uv lock --upgrade to re-resolve every range from scratch, then syncs and runs the suite against the newest versions pyproject.toml's constraints allow.

Two deliberate choices

Gated to schedule and workflow_dispatch. On pull requests this would turn a contributor's branch red for an upstream release that branch did not cause. A PR has to be judged against the lockfile it ships.

The re-resolved lockfile diff is printed whether or not the suite then passes. A green run against moved dependencies is the useful half — it is the evidence needed to widen a range or drop a pin, which is what #103 actually asks for.

Noted in a comment on the trigger: GitHub disables a scheduled workflow after 60 days without repository activity, so a long quiet spell stops these runs rather than failing them.

Verification

ci.yml parses; the five jobs are lint, live-marker-guard, test, upstream-drift, build, and the cron expression round-trips. Full suite green locally on 3.14.7 — 2151 passed, 13 live deselected.

🤖 Generated with Claude Code


Follow-up commit: the job now reports where someone will see it

As first written this job had the flaw it exists to fix, one level up: it would detect upstream breakage and tell nobody. A scheduled run has no pull request to turn red and no author to notify.

This repository has already paid for exactly that. pages.yml failed on two consecutive pushes in August and the failures sat unnoticed for the better part of two months, while the published site served a version six releases behind. A weekly job in a repository that goes quiet for weeks is the same shape.

So a failure now opens an issue, or comments on the open one if there already is one — reused rather than re-opened, because an unattended weekly job that files a fresh issue every Monday is a second way of being ignored. Matched on title rather than a label, so it needs no label to exist first.

The body tells a reader what they need: that this is not any branch's fault, that every other job resolves against uv.lock while this one does not, that the remedy is an upstream fix or a narrower range in pyproject.toml (#103), and that the run log's lockfile diff names what moved.

issues: write is added at the job level, which replaces rather than extends the workflow's permissions, so contents: read is repeated there.

Verification

A reporting step that only runs on a failing Monday months from now is not something to take on trust, so I extracted the step's script out of the parsed YAML and ran it against a stubbed gh:

  • the heredoc dedents correctly out of the block scalar, and the escaped backticks survive as literals rather than being command-substituted;
  • $RUN_URL expands;
  • with no open issue it calls issue create; with one open it calls issue comment and never issue create.

Every trigger on this workflow was caused by someone pushing, so the suite
only ever ran against the versions `uv.lock` pins. That is the right thing
for a pull request and the wrong thing as the only signal: a `langgraph`
minor that breaks the runtime is invisible here until a user on a fresh
install hits it. Issue #103 is the standing form of the complaint -- the
extras are unbounded and the lockfile hides what the next major would do.

Adds a Monday cron and one job that re-resolves every range from scratch
(`uv lock --upgrade`) and runs the suite against the newest versions
pyproject.toml's constraints allow. The job is gated to `schedule` and
`workflow_dispatch`: on pull requests it would turn someone's branch red
for an upstream release that branch did not cause.

The re-resolved lockfile diff is printed whether or not the suite passes,
because a green run against moved dependencies is the evidence needed to
widen a range or drop a pin.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… tab

The job as first written had the flaw it was built to fix, one level up: it
would detect upstream breakage and then tell nobody. A scheduled run has no
pull request to turn red and no author to notify, and this repository has
already paid for exactly that -- `pages.yml` failed on two consecutive
pushes and sat unnoticed for the better part of two months, while the
published site served a version six releases behind. A weekly job in a
repository that goes quiet for weeks is the same shape.

So a failure now opens an issue, or comments on the open one if there is
already one. Reused rather than re-opened: an unattended weekly job that
files a fresh issue every Monday is a second way of being ignored. Matched
on title rather than a label, so it needs no label to exist first.

The body says what a reader needs and not more: that this is not any
branch's fault, that every other job resolves against `uv.lock` while this
one does not, that the remedy is an upstream fix or a narrower range in
pyproject.toml (#103), and that the run log's lockfile diff names what
moved.

`issues: write` is added at the job level, which replaces rather than
extends the workflow's permissions, so `contents: read` is repeated there.

Verified by extracting the step's script from the parsed YAML and running it
against a stubbed `gh`: the heredoc dedents correctly out of the block
scalar, the escaped backticks survive as literals, `$RUN_URL` expands, and
the two paths do what they claim -- create when no issue is open, comment
when one is, with no duplicate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Shashankss1205
Shashankss1205 merged commit 05be13c into main Sep 25, 2026
7 checks passed
@Shashankss1205
Shashankss1205 deleted the ci/weekly-upstream-drift branch September 25, 2026 19:35
Shashankss1205 added a commit that referenced this pull request Sep 26, 2026
…#129)

Closes #103. #116 already covered most of what that issue asked for -- a weekly
resolve that ignores `uv.lock`, reporting to the issue tracker, not gating pull
requests. What it did not cover is the criterion's other half: importing every
subpackage from the *built wheel*.

The distinction is the one #101 was: `mcp>=1.2` resolved to 2.0.0 for anyone
installing fresh, `mcp.server.fastmcp` had gone, and `grapharc[mcp]` was broken
on arrival while every locked job stayed green. A suite run from the source tree
does not see a packaging break that only shows in an installed wheel -- a
subpackage dropped from the build, or an extra whose new major moves a module
the package imports at import time.

The walk moves out of `ci.yml`'s heredoc into `scripts/wheel_import_walk.py`,
because two jobs now need exactly this check and two copies would drift apart.
Same logic, two parameters: which checkout to compare against, and the prefix
the import must come from. `scripts/` holds no `grapharc` package, so running it
by path does not put the checkout on `sys.path` -- the property the old `cd /tmp`
was there for, kept and now asserted with a message rather than a bare
`assert`.

Verified by running it for real rather than reasoning about it, and it earned
its keep immediately: against the wheel then sitting in `dist/` it reported
`grapharc.examples.plan_research` missing -- correctly, because that wheel was
built before #115 merged. Rebuilt, it walks 132 modules clean.

Deliberately **not** done: putting a ceiling on the eight unbounded extras. The
issue asks for a decision on that and argues a bound should be "a ceiling with a
reason attached, not a reflex" -- so adding eight of them at once is the reflex
it warns against, and it would refuse users upgrades that are fine. Detection is
what this closes; the policy is left open.

Verified: 2214 selected, 13 deselected, ruff clean; the sdist's required-files
and secret-leak checks still pass with `scripts/` added.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.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