Repository navigation
feat: ecosystem-wide [compat] pruning workflow - #95
Merged
Merged
Conversation
Stdlib-only Julia scripts that find the [compat] specifiers no supported Julia version ever selects across the control-toolbox ecosystem, and prove that dropping them changes no resolved manifest (control-toolbox/OptimalControl.jl#986). - collect.jl: audited versions = joint resolution; files read from the registered tree - envs.jl: joint env + test and docs env of every package, owner pinned - resolve.jl: baseline, or prunes simulated by per-environment compat intersection - classify.jl: prune / keep / blocked / idle per multi-specifier entry - validate.jl: rejects prunes that change a manifest, names the blockers - audit.jl: one registry snapshot, every Julia version, validation until stable Phases A and B of the plan; the workflow, the report and the publishing come next. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- edit.jl: rewrites one [compat] value in place on checkouts of the default branches (layout, quoting and comments kept, result re-parsed); outcome edited / already / drift per prune. Edits are re-applied to the current branch, never copied from the collected files: copying reverted CTSolvers' version line in the dry run. - report.jl: deterministic Markdown body of the tracking issue, with a hidden marker. - resolution calls Pkg.Operations.resolve_versions! directly: Pkg.resolve downloads every source and artifact, and offline mode restricts to installed versions. - every script is split into functions and a main guard; gh and the resolver are injectable. - tests split per script, with fakes (gh, simulator), golden files, a non-regression snapshot of the real 2026-10-15 audit, and opt-in integration tests (real resolutions, scripts run as commands, fake gh on PATH): 297 pass on Julia 1.10, 1.12, 1.13. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- compat-prune.yml: reusable workflow, read-only `audit` job for now: juliaup with the audited Julia versions, General + ct-registry (public, over HTTPS), script tests, the audit, the prunes applied to fresh checkouts of the default branches, report in the job summary (with the diff), `compat-prune` artifact. `dry_run` defaults to true. - compat-prune-tests.yml: when the scripts or the workflows change, the test suite on Julia 1.10, 1.12, 1.13 (integration included), then a dry-run audit through the reusable workflow at the PR head. A full local audit now takes 145 s (eight packages, 17 environments, three Julia versions): 42 prunes accepted, 0 rejected, 2 blocked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ocots
added a commit
to control-toolbox/OptimalControl.jl
that referenced
this pull request
Oct 15, 2026
Caller of CTActions' compat-prune workflow (control-toolbox/CTActions#95), monthly and on demand. Dry run on every trigger until the publishing job is enabled. Part of #986. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
Author
Progress: phases C and D donePhase C — report, edits, tests (36bef06)
Phase D — workflows (37cc299)
Next
|
…issue) - publish.jl: idempotent publication. The tracking issue is found by its hidden marker (open or closed), its body rewritten, reopened when something is to prune and closed when nothing is left, never created twice. Each repository has one bot-owned branch ct/compat-prune rebuilt from its default branch, pushed only when its content changes; its PR is updated or created, and closed (branch deleted) when nothing is left. - report.jl: PR body (entries of the repository, links to the issue and the run). - checkout.sh: shallow clones of the default branches, shared by both jobs. - compat-prune.yml: `publish` job, skipped on dry runs, the only writer, with a token of the organization's GitHub App (CT_APP_CLIENT_ID, CT_APP_PRIVATE_KEY); fails early and clearly when the secrets are missing. actionlint flags `client-id` of create-github-app-token@v3 from outdated metadata: v3 takes `client-id`. - test_publish.jl: a stateful fake GitHub and real local git origins replay four runs (create; rerun changes nothing; after the merge everything is closed; a new prune reopens the same issue). 336 tests pass on Julia 1.10, 1.12, 1.13. Not run live: the GitHub App does not exist yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`sort` on Pairs compares the values as well (`isless(::Pair)` evaluates both sides), and the index values are dicts: the dry run of 8808247 failed there. Sorted by name only; COMPAT_PRUNE_GIT_BASE lets the new integration test clone from local repositories. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WORKFLOWS.md §3.1: catalog row and how the monthly prune works (what is audited, what is pruned, what is reported, idempotence, dry run, local run, caller); §3.2: the self-test; §4: OptimalControl's CompatPrune; §5: CT_APP_CLIENT_ID / CT_APP_PRIVATE_KEY. README: catalog row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
Author
Progress: phases E and F done (8808247, 156b806, cc32a54)Phase E — publication
A bug the dry run caught
Phase F — documentation
State
|
ocots
marked this pull request as ready for review
October 15, 2026 21:37
…dit record The prune is the organization's, never a package's: the monthly run moves from an OptimalControl caller to compat-prune-monthly.yml in CTActions (cron + workflow_dispatch, dry run on every trigger until the GitHub App exists), and the tracking issue lives in CTActions (new input `tracking_repo`, default control-toolbox/CTActions). The tracking issue now opens with the record of the audit: environments resolved per Julia version (and which failed), multi-specifier entries examined with one status each (prune, rejected, blocked, keep, idle, withheld), registry snapshot (General tree, ct-registry commit), and, folded, the entries left as they are with why. audit.jl is split into registry_snapshot / coverage / summarize, tested (test_audit.jl, report golden, integration). 366 tests pass on Julia 1.10, 1.12, 1.13. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WORKFLOWS.md: compat-prune leaves §3.1 (no package calls it) for §3.2 (workflows that live in CTActions), with compat-prune-monthly.yml, the tracking issue in CTActions and the audit record; §4 no longer lists a CompatPrune caller in OptimalControl; §5 secrets moved to the monthly workflow. README: from the reusable table to the scheduled one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Member
Author
The prune runs from CTActions; the audit record is in the issue (4b5aa65, bd46094)The prune is the organization's, never a package's, so nothing lives in OptimalControl any more.
The tracking issue now opens with an Audit section:
In the self-test run: 17/17 environments on 1.10, 1.12 and 1.13; 45 entries examined, with 42 prunes, 2 blocked and 1 kept (CTParser's
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements control-toolbox/OptimalControl.jl#986: the organization's monthly
[compat]prune. It finds the specifiers that no supported Julia version selects across the CT* ecosystem, proves that dropping them leaves every resolved manifest unchanged, and maintains one PR per affected repository plus one tracking issue in CTActions. Blockers (an entry's newest specifier is never selected) are reported, without PR. Everything lives in CTActions; no package carries a caller (OptimalControl.jl#990 was closed for that reason). Plan: control-toolbox/OptimalControl.jl#986 (comment).Contents
.github/workflows/compat-prune.ymlauditjob: read-only, report and diff in the job summary,compat-pruneartifact.publishjob: the only writer, skipped on dry runs, uses a GitHub App token.github/workflows/compat-prune-monthly.ymlworkflow_dispatch(dry_run). Dry run on every trigger until the GitHub App exists.github/workflows/compat-prune-tests.ymlscripts/compat-prune/audit.jljulia +<v>), validation repeated until stablecollect.jl,envs.jlresolve.jl,classify.jl,validate.jlresolve_versions!: nothing downloaded or installed). Classification: prune / keep / blocked / idle / withheld. Prunes are simulated by intersecting compat in each environment where they apply, and rejected if any manifest movesedit.jl,checkout.sh[compat]line rewritten in place on fresh checkouts of the default branches. Outcome per prune: edited / already / driftreport.jl,publish.jlct/compat-prune, push only when the content changes, PRs updated or closed, the issue reopened and never recreatedscripts/compat-prune/test/gh, the simulator and GitHub. Golden files. A non-regression snapshot of the real 2026-10-15 audit. Integration tests (real resolutions, scripts run as commands, fakeghonPATH, local git origins)docs/WORKFLOWS.md,README.mdChecks
CTBase = "0.29, 0.30": both lanes in use).0.7from CTSolvers'CUDSSis rejected, because OptimalControl's tests and docs select it.Before the first live run (maintainer)
CT_APP_CLIENT_IDandCT_APP_PRIVATE_KEY, as organization secrets or CTActions secrets.workflow_dispatchonly lists workflows that are onmain.Compat prune (monthly)from the Actions tab of CTActions withdry_run: false. Then switch the schedule to publishing, a one-line change incompat-prune-monthly.yml.force_latest_compatible_version=auto(ci: restore force_latest_compatible_version=auto, skip it on Julia 1.10 #93), notfalse; the workflow lives in CTActions.🤖 Generated with Claude Code