diff --git a/.github/workflows/reusable_edge_build.yml b/.github/workflows/reusable_edge_build.yml index 668eba4..c0fe83e 100644 --- a/.github/workflows/reusable_edge_build.yml +++ b/.github/workflows/reusable_edge_build.yml @@ -101,6 +101,7 @@ jobs: package: ${{ matrix.package.package }} ros_distro: ${{ matrix.ros_distro }} version_suffix: ${{ matrix.package.suffix }} + archive_channels: edge stable runner: ${{ inputs.runner }} continue_on_failure: true diff --git a/.github/workflows/reusable_release_build.yml b/.github/workflows/reusable_release_build.yml index 96d852e..2fbc736 100644 --- a/.github/workflows/reusable_release_build.yml +++ b/.github/workflows/reusable_release_build.yml @@ -46,6 +46,10 @@ on: description: 'Appended to the version in package.xml, e.g. "+git20261027153012.ab12cd3" for a build of main' default: '' type: string + archive_channels: + description: 'Archive channels whose packages the build depends on, e.g. "edge stable" for a build of main' + default: 'stable' + type: string workflow_call: inputs: repository: @@ -86,6 +90,11 @@ on: default: '' required: false type: string + archive_channels: + description: 'Archive channels whose packages the build depends on, e.g. "edge stable" for a build of main' + default: 'stable' + required: false + type: string outputs: artifact: description: 'Artifact name without its architecture: one artifact per architecture built, -' @@ -114,6 +123,22 @@ jobs: ref: v1 path: .devtools + # Dependencies on packages already published resolve from the archive the ARCHIVE_URL + # organization variable names, trusted by its key's fingerprint. + - name: Fetch the archive key + if: vars.ARCHIVE_URL != '' + env: + ARCHIVE_URL: ${{ vars.ARCHIVE_URL }} + FPR: ${{ vars.ARCHIVE_KEY_FINGERPRINT }} + run: | + [ -n "$FPR" ] || { echo "::error::ARCHIVE_URL is set without ARCHIVE_KEY_FINGERPRINT"; exit 1; } + mkdir -p "$RUNNER_TEMP/keys" + key="$RUNNER_TEMP/keys/duatic-archive.gpg" + curl -fsSL "${ARCHIVE_URL%/}/duatic-archive.gpg" -o "$key" + fprs="$(gpg --show-keys --with-colons "$key" | awk -F: '/^pub/{p=1; next} p && /^fpr/{print $10; p=0}')" + [ "$fprs" = "$FPR" ] \ + || { echo "::error::the archive key is ${fprs:-unreadable}, not $FPR" | tr "\n" " "; exit 1; } + - name: Build the package into a .deb id: build continue-on-error: ${{ inputs.continue_on_failure }} @@ -123,12 +148,20 @@ jobs: ROS_DISTRO_TARGET: ${{ inputs.ros_distro }} ARCH: ${{ matrix.arch }} SUFFIX: ${{ inputs.version_suffix }} + ARCHIVE_URL: ${{ vars.ARCHIVE_URL }} + ARCHIVE_CHANNELS: ${{ inputs.archive_channels }} run: | mkdir -p "$RUNNER_TEMP/out" + archive=() + if [ -n "$ARCHIVE_URL" ]; then + archive=(-e ARCHIVE_URL="$ARCHIVE_URL" -e ARCHIVE_CHANNELS="$ARCHIVE_CHANNELS" + -e ARCHIVE_KEYRING=/keys/duatic-archive.gpg -v "$RUNNER_TEMP/keys:/keys:ro") + fi docker run --rm -i --platform "linux/$ARCH" \ -e HOST_UID="$(id -u)" -e HOST_GID="$(id -g)" \ -e ROS_DISTRO="$ROS_DISTRO_TARGET" \ -e DEB_VERSION_SUFFIX="$SUFFIX" \ + "${archive[@]}" \ -v "$PWD/src:/src" \ -v "$PWD/.devtools/packaging/builder:/builder" \ -v "$RUNNER_TEMP/out:/out" \ diff --git a/README.md b/README.md index 797c1a6..e90d3d4 100644 --- a/README.md +++ b/README.md @@ -314,10 +314,12 @@ symbols and, when the package declares ``, its source tar It takes a tag to check out and the package to build inside it, and a `version_suffix` appended to the `package.xml` version for a build of main. The package is named explicitly, whether the tag is a `/` tag, a repo-wide `v` tag or a commit, so the build does not need to -guess it from the tag's shape. It is not wired into any repository yet: a -package's dependencies on other packages in the org resolve only from the builder's local -repository, so a build stops at the first such dependency. Signing and publishing belong to the -archive host. +guess it from the tag's shape. A dependency on a package already published resolves from the +archive the organization variable `ARCHIVE_URL` names, read from the channels in +`archive_channels`: `stable` for a release, `edge stable` for a build of main, so a dependency +without a build of main comes from its release. The archive's key is fetched from it and used only +when its fingerprint is `ARCHIVE_KEY_FINGERPRINT`. Without `ARCHIVE_URL` the build resolves no +such dependency and fails at the first one. Signing and publishing belong to the archive host. **`reusable_release_publish.yml`** takes one of those artifacts and publishes it into a signed archive root, by delivering it to the publish host and calling `duatic_devtools`' archive tooling there. The @@ -418,6 +420,7 @@ And in `ci.yml`, beside the orchestrator, for either mode: | `repository` | build | no | the caller | `owner/name` of the repository holding the tag, for a dispatch from elsewhere. | | `ros_distro` | build | no | `jazzy` | Distro to build for. The Ubuntu base is not an input; it's derived from this instead. | | `version_suffix` | build | no | | Appended to the `package.xml` version, starting with `+` or `~`. The build fails if the `.deb` does not carry it. | +| `archive_channels` | build | no | `stable` | Archive channels the build's dependencies are read from, e.g. `edge stable`. | | `channel` | publish | no | `stable` | Archive channel to publish into: `stable` or `edge`. | | `runner` | prepare, prepare-repo, tag, repo-tag, build | no | `ubuntu-latest` | Runner label(s), e.g. `self-hosted`. |