Skip to content

Commit 7b335ee

Browse files
Upload every distribution to robostack-<distro> on anaconda.org and prefix.dev
Instead of a mirror job (#54): the build uploads each package to anaconda.org (token ANACONDA_API_TOKEN, --force) and then to prefix.dev (trusted publishing), both robostack-<distro>; the builds read prefix.dev. Nothing goes to robostack-staging anymore: humble's channel is robostack-humble, and rolling and lyrical get their anaconda.org channels populated. channel_name and upload_target leave distro.yaml. anaconda.org goes first so that prefix.dev, which decides what is built, never has a package anaconda.org lacks; a rebuild replaces the anaconda.org file. The staging copy stays for noetic only (RoboStack/ros-noetic still uploads to robostack-staging). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 3648ac6 commit 7b335ee

16 files changed

Lines changed: 131 additions & 275 deletions

‎.github/workflows/copy-staging-packages.yaml‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
# humble and noetic upload to robostack-staging: copy their packages on to
2-
# robostack-humble / robostack-noetic (tools/copy_staging_packages.py). Moved here from
3-
# RoboStack/robostack.github.io. A job without its token secret is skipped.
1+
# noetic (RoboStack/ros-noetic) uploads to robostack-staging: copy its packages on to
2+
# robostack-noetic (tools/copy_staging_packages.py). Moved here from
3+
# RoboStack/robostack.github.io. The distributions of this repository upload to their
4+
# own channels directly (tools/robostack.py upload). Skipped without the token secret.
45
name: Copy staging packages
56

67
on:
@@ -18,7 +19,6 @@ jobs:
1819
matrix:
1920
include:
2021
- { distro: noetic, token: ROBOSTACK_NOETIC_ANACONDA_API_TOKEN }
21-
- { distro: humble, token: ROBOSTACK_HUMBLE_ANACONDA_API_TOKEN }
2222
name: copy ${{ matrix.distro }}
2323
runs-on: ubuntu-latest
2424
steps:

‎.github/workflows/mirror-to-anaconda.yaml‎

Lines changed: 0 additions & 53 deletions
This file was deleted.

‎README.md‎

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@ the [RoboStack documentation](https://robostack.github.io/GettingStarted.html).
66

77
| Distribution | Channel |
88
|---|---|
9-
| rolling | [robostack-rolling](https://prefix.dev/channels/robostack-rolling) |
10-
| lyrical | [robostack-lyrical](https://prefix.dev/channels/robostack-lyrical) |
11-
| jazzy | [robostack-jazzy](https://anaconda.org/robostack-jazzy) |
12-
| humble | [robostack-staging](https://anaconda.org/robostack-staging) |
9+
| rolling | robostack-rolling ([prefix.dev](https://prefix.dev/channels/robostack-rolling), [anaconda.org](https://anaconda.org/robostack-rolling)) |
10+
| lyrical | robostack-lyrical ([prefix.dev](https://prefix.dev/channels/robostack-lyrical), [anaconda.org](https://anaconda.org/robostack-lyrical)) |
11+
| jazzy | robostack-jazzy ([prefix.dev](https://prefix.dev/channels/robostack-jazzy), [anaconda.org](https://anaconda.org/robostack-jazzy)) |
12+
| humble | robostack-humble ([prefix.dev](https://prefix.dev/channels/robostack-humble), [anaconda.org](https://anaconda.org/robostack-humble)) |
13+
14+
Every distribution uploads the same packages to both: `-c robostack-<distro>` (anaconda.org)
15+
and `-c https://prefix.dev/robostack-<distro>` work alike.
1316

1417
Packages are named `ros2-<package>`, e.g. `ros2-desktop` or `ros2-rclcpp`; the
1518
distribution comes from the channel. The older names keep working: for every package
@@ -60,7 +63,7 @@ tools/robostack.py `pixi run rs ...`: every task, for one distribution o
6063
tools/maintenance.py checks and robostack-bot commands
6164
tools/import_distro.py (re)import a distribution from its own repository
6265
tools/*.py check_patches_clean_apply, check_dependency_compat, build_gap_report, ...
63-
tools/copy_staging_packages.py, mirror_to_anaconda.py channel maintenance (workflows below)
66+
tools/copy_staging_packages.py noetic's staging copy (see CI)
6467
.scripts/ staged build scripts (build_unix.sh, build_win.bat)
6568
.github/workflows/ testpr.yaml, main.yaml (staged build branches), bot.yaml, channel maintenance
6669
.claude/skills/ procedures for agents (debug a build, patches, versions/rebuilds, package selection)
@@ -120,18 +123,19 @@ label doesn't start one by itself. Nothing has to be reset before merging.
120123
- Each selected distribution is built on all five platforms, with its own build cache. The `check` job runs `pixi run rs check`.
121124
- **After a merge** (`main.yaml`): for every changed distribution and platform, the job regenerates the recipes and the staged build workflow, and pushes them to `buildbranch_<distro>_<platform>`.
122125
- Each build branch carries its workflow as `.github/workflows/build.yaml`, which runs `.scripts/build_*.sh` in `distros/<distro>/work`.
123-
- Those workflows build the packages and upload them to the distribution's channel.
126+
- Those workflows build the packages and upload them to the distribution's channels, `robostack-<distro>` on anaconda.org and then on prefix.dev (`pixi run rs <distro> upload`). The builds read prefix.dev.
124127
- **Repository variables:**
125128
- `ROBOSTACK_UPLOAD_CHANNEL`: upload to this prefix.dev channel instead (for example a test channel), or `none` to build without uploading. Use the canonical reference: `<namespace>/<channel>` for a channel that isn't the namespace's primary one (e.g. `tobias-fischer/robostack-distro-test`).
126-
- Upload credentials: prefix.dev channels use Repository Access (OIDC, no stored key). In the channel's *Settings > Repository Access*, authorize GitHub, this repository, workflow filename `build.yaml`, mode *Read/write*. There are no upload tokens: distributions whose channel is still on anaconda.org (`upload_target: anaconda`, read from there) can only upload to a prefix.dev channel set in `ROBOSTACK_UPLOAD_CHANNEL`.
129+
- Upload credentials:
130+
- prefix.dev channels use Repository Access (OIDC, no stored key). In the channel's *Settings > Repository Access*, authorize GitHub, this repository, workflow filename `build.yaml`, mode *Read/write*.
131+
- anaconda.org has no trusted publishing: the secret `ANACONDA_API_TOKEN` is a token of an account that can upload to every `robostack-<distro>` channel there.
132+
- With `ROBOSTACK_UPLOAD_CHANNEL` set, the uploads only go to that channel.
127133
- `ROBOSTACK_BOT_CLIENT_ID` (the App's Client ID, `Iv23…`) with the secret `ROBOSTACK_BOT_PRIVATE_KEY`: the robostack-bot GitHub App. It pushes the build branches (which contain workflow files) and opens bot PRs so that CI runs on them. `GHA_PAT` works as a fallback.
128134

129135
The app needs repository permissions Contents, Pull requests, Issues and Workflows (read and write), with its webhook inactive.
130136

131137
- **Channel maintenance:**
132-
- `copy-staging-packages.yaml` (hourly): copies humble's and noetic's packages from `robostack-staging` on to `robostack-humble` / `robostack-noetic` (`anaconda copy`). Secrets `ROBOSTACK_HUMBLE_ANACONDA_API_TOKEN`, `ROBOSTACK_NOETIC_ANACONDA_API_TOKEN`.
133-
- `mirror-to-anaconda.yaml` (started by hand for now, dry run by default): uploads what a prefix.dev channel has and its old anaconda.org channel doesn't (humble → `robostack-staging`, jazzy → `robostack-jazzy`). Secrets `ROBOSTACK_STAGING_ANACONDA_API_TOKEN`, `ROBOSTACK_JAZZY_ANACONDA_API_TOKEN`.
134-
- A job without its secret is skipped.
138+
- `copy-staging-packages.yaml` (hourly): noetic (RoboStack/ros-noetic) still uploads to `robostack-staging`; this copies its packages on to `robostack-noetic` (`anaconda copy`, secret `ROBOSTACK_NOETIC_ANACONDA_API_TOKEN`; skipped without it).
135139

136140
### robostack-bot
137141

‎distros/humble/distro.yaml‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Settings of ros-humble that differ from the other distributions
22
# (everything else is shared, see the README).
3-
channel_name: robostack-staging
4-
upload_target: anaconda
53
conda_forge_pinning_version: 2026.09.01.16.28.00
64
conda_forge_migrations: [giflib6, go_macos, gstreamer128, hdf52, libboost190, pybind11_abi11, urdfdom6,
75
vtk970]

‎distros/jazzy/distro.yaml‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Settings of ros-jazzy that differ from the other distributions
22
# (everything else is shared, see the README).
3-
channel_name: robostack-jazzy
4-
upload_target: anaconda
53
conda_forge_pinning_version: 2026.09.01.16.28.00
64
conda_forge_migrations: [giflib6, go_macos, gstreamer128, hdf52, libboost190, pybind11_abi11, urdfdom6,
75
vtk970]

‎distros/lyrical/distro.yaml‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Settings of ros-lyrical that differ from the other distributions
22
# (everything else is shared, see the README).
3-
channel_name: robostack-lyrical
4-
upload_target: prefix
53
conda_forge_pinning_version: 2026.10.09.13.11.31
64
conda_forge_migrations: [elfutils0196, giflib6, go_macos, gsl28, gstreamer128, hdf52, libboost190, libhwloc2150, proj99, urdfdom6]
75
pinning_overrides:

‎distros/rolling/distro.yaml‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
# Settings of ros-rolling that differ from the other distributions
22
# (everything else is shared, see the README).
3-
channel_name: robostack-rolling
4-
upload_target: prefix
53
conda_forge_pinning_version: 2026.09.01.16.28.00
64
conda_forge_migrations: [giflib6, go_macos, gstreamer128, hdf52, libboost190, pybind11_abi11, urdfdom6,
75
vtk970]

‎pixi.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pyyaml = "*"
2525
# Some git repos need git-lfs, see https://github.com/RoboStack/ros-jazzy/issues/118
2626
git-lfs = "*"
2727
pytest = ">=9.1.1,<10"
28-
# copy_staging_packages.py and mirror_to_anaconda.py (channel maintenance)
28+
# tools/copy_staging_packages.py (noetic: robostack-staging -> robostack-noetic)
2929
anaconda-client = ">=1.14.1,<2"
3030
niquests = ">=3.21.2,<4"
3131
py-rattler = ">=0.27.1,<0.28"

‎tools/abi_check.py‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -338,13 +338,9 @@ def channel_for(distro: str) -> list[str]:
338338
sys.path.insert(0, str(Path(__file__).parent))
339339
import robostack as rs
340340

341-
s = rs.settings(distro)
342-
name = s.get("channel_name", f"robostack-{distro}")
343341
upload = os.environ.get("ROBOSTACK_UPLOAD_CHANNEL", "").strip()
344342
extra = [f"https://repo.prefix.dev/{upload}"] if upload and upload != "none" else []
345-
if s.get("upload_target", "prefix") == "prefix":
346-
return extra + [f"https://repo.prefix.dev/{name}"]
347-
return extra + [f"https://conda.anaconda.org/{name}"]
343+
return extra + [f"https://repo.prefix.dev/{rs.channel_name(distro)}"]
348344

349345

350346
def download(channel: str, platform: str, filename: str, dest: Path) -> Path:

‎tools/copy_staging_packages.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
"""Copy a distribution's packages from robostack-staging to robostack-<distro> (anaconda.org).
22
3-
humble and noetic upload to robostack-staging; this copies every package of the given
4-
distribution built after a cutoff date that robostack-<distro> doesn't have yet, with
5-
`anaconda copy` (the token is read from ANACONDA_API_TOKEN). Moved here from
3+
noetic uploads to robostack-staging (humble did, too, before it moved here); this
4+
copies every package of the given distribution built after a cutoff date that
5+
robostack-<distro> doesn't have yet, with `anaconda copy` (the token is read from
6+
ANACONDA_API_TOKEN). Moved here from
67
RoboStack/robostack.github.io (scripts/copy-to-distro-specific-channel.py).
78
"""
89

0 commit comments

Comments
 (0)