Skip to content

Commit 6c5832e

Browse files
Daily conda-forge pinning PRs that rebuild only what changed pins affect (#16)
See #16. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent cde63fd commit 6c5832e

12 files changed

Lines changed: 360 additions & 106 deletions

File tree

‎.claude/skills/robostack-versions/SKILL.md‎

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ description: Update ROS package versions (rosdistro snapshot) and conda-forge pi
77

88
robostack-bot does the routine part: `update-rosdistro-snapshot` (daily, when a new
99
rosdistro sync is tagged) and
10-
`update-conda-forge-pinning` (weekly, or on request) open PRs that already contain the
11-
bumps below. Do it by hand when the bot fails or something extra is needed.
10+
`update-conda-forge-pinning` (daily, when the pinning version or the usable migrations
11+
change, or on request) open PRs that already contain the bumps below. Do it by hand when the bot fails or something extra is needed.
1212

1313
## What is pinned where
1414

@@ -50,7 +50,8 @@ pixi run rs <d> create-snapshot
5050
## Update the conda-forge pinning
5151

5252
```bash
53-
pixi run rs update-pinning # = bot command, for all distributions that follow shared/
53+
pixi run rs <d> update-pinning # = bot command: latest pinning + rebuild plan for <d>
54+
pixi run rs update-pinning # the same for every distribution
5455
pixi run rs <d> render-pinning # after editing shared/pinning or distro.yaml
5556
pixi run rs <d> check-deps # solve all non-ROS deps + mutex constraints, nothing built
5657
```
@@ -65,9 +66,36 @@ pixi run rs <d> check-deps # solve all non-ROS deps + mutex constraints
6566
Exit code 1 means something conflicts. Status of migrations:
6667
https://conda-forge.org/status/.
6768

69+
`check-deps` takes the requirements of every selected package from vinca (`--source
70+
recipes` uses `recipes/` instead, which with skip-existing only holds unbuilt packages).
71+
72+
### What the pinning PR rebuilds
73+
74+
`update-pinning` moves the distribution's pinning (its own `distro.yaml` version, or
75+
the shared one it follows) forward and compares the old and new
76+
`conda_build_config.yaml` with `vinca-rebuild-plan`: packages with a changed pin among their build or
77+
host requirements, plus everything that depends on them (host or run, transitively),
78+
are rebuilt; the rest keep their published builds.
79+
80+
- **Partial rebuild** (the usual case): those packages get `build_number` = highest
81+
released build + 1 in `distros/<d>/pkg_additional_info.yaml`, and when the mutex
82+
`run_constraints` changed, the mutex gets a new build at the same version
83+
(`mutex_package.build_number`), so all other published packages stay installable.
84+
- **Full rebuild** (more than half of the packages affected): the bump below.
85+
86+
The PR lists the packages and why, the migrations used / waiting for our dependencies'
87+
feedstocks, and a linux-64 `check-deps` result; it is labelled `dependency-conflict`
88+
when the new pins can't be installed together.
89+
90+
```bash
91+
pixi run vinca-rebuild-plan --old <old cbc> --new distros/<d>/conda_build_config.yaml \
92+
--vinca-dir distros/<d>/work # the plan by hand (after `rs <d> prepare`)
93+
```
94+
6895
## Rebuild bump (full rebuild)
6996

70-
When the snapshot or the pins change, everything is rebuilt:
97+
When the snapshot changes (or a pinning change affects most packages), everything is
98+
rebuilt:
7199

72100
1. `build_number` in `distros/<d>/vinca.yaml` = the highest build number of the
73101
distribution's released packages + 1, so every package gets a new build.

‎.github/ISSUE_TEMPLATE/3_robostack_bot.yaml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ body:
1414
| `add-package` | anyone | Add ROS packages to the shared package selection (built by every distribution that has them); the PR lists what will be built. A maintainer reviews and merges it. |
1515
| `update-rosdistro-snapshot` | maintainers | Refresh `rosdistro_snapshot.yaml` to the latest rosdistro sync (master for rolling) and bump the build number (highest released + 1, per-package build numbers removed) and mutex: a full rebuild. The PR lists the version bumps. Runs daily when a new sync is tagged. |
1616
| `find-stale-packages` | maintainers | List published packages built against pins that no longer match, with the build-number snippet to rebuild them. Replies only. |
17-
| `update-conda-forge-pinning` | maintainers | Move the shared conda-forge pinning to the latest version; re-renders `conda_build_config.yaml` and bumps the build number and mutex of the distributions whose pins changed. Runs weekly. |
17+
| `update-conda-forge-pinning` | maintainers | Move the distribution's conda-forge pinning to the latest version, with the migrations that are done for its dependencies; rebuilds only the packages that use a changed pin and what depends on them (a full rebuild when that is most of them). The PR lists the packages, the migrations and a dependency check. Runs daily. |
1818
- type: dropdown
1919
id: command
2020
attributes:
@@ -32,7 +32,7 @@ body:
3232
id: distributions
3333
attributes:
3434
label: Distributions
35-
description: "`all`: every distribution (for add-package: every one that has the package). Ignored by update-conda-forge-pinning."
35+
description: "`all`: every distribution (for add-package: every one that has the package)."
3636
multiple: true
3737
options: [all, rolling, lyrical, jazzy, humble]
3838
default: 0

‎.github/workflows/bot.yaml‎

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
#
33
# - daily: a snapshot PR for every distribution with a new rosdistro sync (the ROS
44
# release team tags each sync, e.g. jazzy/2026-10-05; `rosdistro_sync: manual` in
5-
# distro.yaml opts out, like rolling); Mondays also the shared conda-forge pinning.
5+
# distro.yaml opts out, like rolling), and a conda-forge pinning PR when there's a new
6+
# pinning version or a migration became usable (only packages using a changed pin, and
7+
# what depends on them, are rebuilt; the PR is labelled dependency-conflict when the
8+
# new pins can't be installed together).
69
# - on demand (owners, members and collaborators):
710
# Actions > robostack-bot > Run workflow, an issue from the "robostack-bot command"
811
# template, or a comment: @robostack-bot <command> [<distro>]
912
# commands: update-rosdistro-snapshot [<distro>...|all] | find-stale-packages [<distro>...|all] |
10-
# update-conda-forge-pinning | add-package <pkg>... [<distro>...]
13+
# update-conda-forge-pinning [<distro>...|all] | add-package <pkg>... [<distro>...]
1114
# - package requests (the "Package request" issue form or `@robostack-bot add-package`,
1215
# from anyone): the bot opens a PR that adds the packages; maintainers review it.
1316
# Every other command is for owners, members and collaborators.
@@ -72,10 +75,8 @@ jobs:
7275
run: |
7376
case "$EVENT" in
7477
schedule)
75-
jobs=$(pixi run -q rs rosdistro-syncs)
76-
if [ "$(date -u +%u)" = 1 ]; then
77-
jobs=$(echo "$jobs" | python3 -c 'import json,sys; print(json.dumps(json.load(sys.stdin) + [{"command":"update-conda-forge-pinning","distro":"","args":"","preview":False}]))')
78-
fi ;;
78+
# rosdistro syncs, and the conda-forge pinning of every distribution
79+
jobs=$(pixi run -q rs rosdistro-syncs | python3 -c 'import json,sys; print(json.dumps(json.load(sys.stdin) + [{"command":"update-conda-forge-pinning","distro":d,"args":"","preview":False} for d in sys.argv[1:]]))' $(ls distros)) ;;
7980
workflow_dispatch) # only people with write access can dispatch
8081
jobs=$(ROBOSTACK_BOT_BODY="@robostack-bot $COMMAND $PACKAGES $DISTRO" ROBOSTACK_BOT_ASSOCIATION=OWNER pixi run -q rs parse-command) ;;
8182
*)
@@ -132,7 +133,7 @@ jobs:
132133
pixi run rs add-package $ARGS "${extra[@]}" --summary "$RUNNER_TEMP/summary.md" ;;
133134
update-rosdistro-snapshot) pixi run rs "$DISTRO" update-snapshot --summary "$RUNNER_TEMP/summary.md" ;;
134135
find-stale-packages) pixi run rs "$DISTRO" find-stale --summary "$RUNNER_TEMP/summary.md" ;;
135-
update-conda-forge-pinning) pixi run rs update-pinning --summary "$RUNNER_TEMP/summary.md" ;;
136+
update-conda-forge-pinning) pixi run rs "$DISTRO" update-pinning --summary "$RUNNER_TEMP/summary.md" ;;
136137
esac
137138
status=$?
138139
cat "$RUNNER_TEMP/summary.md" >> "$GITHUB_STEP_SUMMARY" 2>/dev/null
@@ -153,7 +154,9 @@ jobs:
153154
commit-message: ${{ steps.bot.outputs.title }}
154155
title: ${{ steps.bot.outputs.title }}
155156
body-path: ${{ runner.temp }}/summary.md
156-
labels: robostack-bot
157+
labels: |
158+
robostack-bot
159+
${{ steps.bot.outputs.labels }}
157160
- name: Reply on the issue / pull request
158161
if: always() && (github.event_name == 'issue_comment' || github.event_name == 'issues')
159162
env:

‎README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ of a distribution uses `full_rebuild: true` there. A new build number goes into
127127
| `add-package <pkg>... [<distro>...]` | anyone | Adds ROS packages to the shared selection in `shared/vinca.yaml`, in sorted position; every distribution that has them builds them. Opens a PR listing, for the given (default: every) distribution, what will be built on linux-64 (and what is already published as a dependency). Valid ROS package names only, at most 10 per request. |
128128
| `update-rosdistro-snapshot [<distro>... \| all]` | maintainers | Snapshots the distribution's latest rosdistro sync (the release team's tag, e.g. `jazzy/2026-10-05`, recorded as `rosdistro_sync` in `distro.yaml`; rosdistro master for `rosdistro_sync: manual`, like rolling), then sets `build_number` to the highest build of the distribution's released packages + 1, bumps the mutex minor version and removes all per-package build numbers: a full rebuild. The PR links the sync's announcement and lists the version bumps. Runs daily for distributions with a new sync. |
129129
| `find-stale-packages [<distro>... \| all]` | maintainers | Published packages built against pins that no longer match, with the build-number snippet to rebuild them. Replies only. |
130-
| `update-conda-forge-pinning` | maintainers | Moves `shared/pinning/conda_forge.yaml` to the latest conda-forge pinning (migrations selected for the dependencies of all distributions) and re-renders the distributions that follow it. Those whose pins changed get the same build number and mutex bump, and their mutex `run_constraints` of the form `<pkg> <version>.*` follow the new pins. Runs weekly. |
130+
| `update-conda-forge-pinning [<distro>... \| all]` | maintainers | Moves the distribution's conda-forge pinning (`conda_forge_pinning_version` / `conda_forge_migrations` in `distro.yaml`, or `shared/pinning/conda_forge.yaml` for distributions that follow it) to the latest version, with the migrations that are done for the distribution's dependencies, and re-renders `conda_build_config.yaml`. Only packages that use a changed pin, and everything depending on them, are rebuilt (per-package build numbers, a new build of the mutex at the same version); more than half affected means a full rebuild. Mutex `run_constraints` of the form `<pkg> <version>.*` follow the new pins. The PR lists the rebuilt packages, the migrations used and those waiting for feedstocks, and the dependency check; it is labelled `dependency-conflict` when the pins can't be installed together. Runs daily, one PR per distribution. |
131131

132132
There are three ways to trigger a command:
133133
- a *Package request* or *robostack-bot command* issue;

‎distros/humble/ci.yaml‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,4 @@ full_rebuild: false
2323
#
2424
# Remember that dependents are not rebuilt automatically: evict them as well if
2525
# they must pick up the change.
26-
evict_cache:
27-
# built from ROS sources under the conda-forge names before shared/vinca.yaml
28-
# skipped them; the conda-forge packages must be used instead
29-
- cpp-expected
30-
- sophus
26+
evict_cache: []

‎distros/jazzy/ci.yaml‎

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,4 @@ full_rebuild: false
2323
#
2424
# Remember that dependents are not rebuilt automatically: evict them as well if
2525
# they must pick up the change.
26-
evict_cache:
27-
# built from ROS sources under the conda-forge names before shared/vinca.yaml
28-
# skipped them; the conda-forge packages must be used instead
29-
- cpp-expected
30-
- sophus
31-
# empty win-64 build from a cancelled run
32-
- rmw_fastrtps_shared_cpp
26+
evict_cache: []

‎distros/lyrical/ci.yaml‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,4 @@ full_rebuild: false
2323
#
2424
# Remember that dependents are not rebuilt automatically: evict them as well if
2525
# they must pick up the change.
26-
evict_cache:
27-
- ros_image_to_qimage # rebuilt with Qt6
28-
- openvdb_vendor # rebuilt with the OpenVDB module path fix
29-
- nlohmann_json_schema_validator_vendor # rebuilt with exported symbols on Windows
26+
evict_cache: []

‎pixi.lock‎

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎pixi.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ git = "*"
3434
[pypi-dependencies]
3535
# One vinca for all distributions.
3636
# Tobias-Fischer/vinca robostack-integration (RoboStack/vinca#162 + extends, test selectors, gha fix) until merged upstream
37-
vinca = { git = "https://github.com/Tobias-Fischer/vinca.git", rev = "ed3493cb303e571fd78dd8812869e5b44726acb0" }
37+
vinca = { git = "https://github.com/Tobias-Fischer/vinca.git", rev = "b5c524bfc06221d8f9345ad851f7d4d9fd9b79b6" }
3838
# For local development, temporarily use (and regenerate pixi.lock):
3939
# vinca = { path = "../vinca", editable = true }
4040

0 commit comments

Comments
 (0)