From 022465eb0c3fb2aaf5b05e4af98424d181d5a3bd Mon Sep 17 00:00:00 2001 From: cyc Date: Fri, 24 Apr 2026 11:16:42 +0800 Subject: [PATCH 1/3] fix: migrate Dockerfile lint stages to test-tools:local (#106) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Inline bats-src / bats-extensions / lint-tools stages had hardcoded linux.x86_64 / Linux-x86_64 download URLs. On arm64 hosts (Jetson, Graviton) they pulled unusable binaries; the `test` stage then exited at `shellcheck -S warning /lint/*.sh`. `./build.sh devel` still worked because devel doesn't need lint tools, but `./build.sh test` and the CI `docker-build` check broke on arm64. Template's `Dockerfile.test-tools` builds an arch-aware shellcheck + hadolint + bats bundle (keyed off BuildKit's TARGETARCH). `./build.sh` and `build-worker.yaml` already build `test-tools:local` before the main build, so consumers just COPY from it. Delete 19 lines of inline stages; switch 4 COPY --from=... lines to --from=test-tools:local; net -17 lines. bats-extensions COPY dropped because test-tools:local bundles bats-support / bats-assert under /usr/lib/bats. Verified: ./build.sh --no-env test on amd64 — 28/28 smoke tests pass. --- Dockerfile | 34 +++++++--------------------------- doc/changelog/CHANGELOG.md | 1 + 2 files changed, 8 insertions(+), 27 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3dee7b4..2bb1673 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,25 +1,5 @@ ARG IMAGE="ros:foxy-ros-base-focal" -############################## test tool sources ############################## -FROM bats/bats:latest AS bats-src - -FROM alpine:latest AS bats-extensions -RUN apk add --no-cache git && \ - git clone --depth 1 -b v0.3.0 \ - https://github.com/bats-core/bats-support /bats/bats-support && \ - git clone --depth 1 -b v2.1.0 \ - https://github.com/bats-core/bats-assert /bats/bats-assert - -FROM alpine:latest AS lint-tools -RUN apk add --no-cache curl xz && \ - curl -fsSL \ - https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.x86_64.tar.xz \ - | tar -xJ -C /tmp && \ - mv /tmp/shellcheck-v0.10.0/shellcheck /usr/local/bin/shellcheck && \ - curl -fsSL -o /usr/local/bin/hadolint \ - https://github.com/hadolint/hadolint/releases/download/v2.12.0/hadolint-Linux-x86_64 && \ - chmod +x /usr/local/bin/hadolint - ############################## devel ############################## FROM ${IMAGE} AS devel @@ -80,9 +60,9 @@ CMD ["ros2", "run", "ros1_bridge", "parameter_bridge"] ############################## test (ephemeral) ############################## FROM devel AS test -# Install lint tools -COPY --from=lint-tools /usr/local/bin/shellcheck /usr/local/bin/shellcheck -COPY --from=lint-tools /usr/local/bin/hadolint /usr/local/bin/hadolint +# Lint tools (from pre-built test-tools image built by build.sh) +COPY --from=test-tools:local /usr/local/bin/shellcheck /usr/local/bin/shellcheck +COPY --from=test-tools:local /usr/local/bin/hadolint /usr/local/bin/hadolint # Lint: ShellCheck (.sh) + Hadolint (Dockerfile) COPY .hadolint.yaml /lint/.hadolint.yaml @@ -93,10 +73,10 @@ COPY script/*.sh /lint/ RUN shellcheck -S warning /lint/*.sh RUN cd /lint && hadolint Dockerfile -# Install bats -COPY --from=bats-src /opt/bats /opt/bats -COPY --from=bats-src /usr/lib/bats /usr/lib/bats -COPY --from=bats-extensions /bats /usr/lib/bats +# Bats + extensions (from pre-built test-tools image; bats-support / bats-assert +# are bundled into /usr/lib/bats, no separate stage needed) +COPY --from=test-tools:local /opt/bats /opt/bats +COPY --from=test-tools:local /usr/lib/bats /usr/lib/bats RUN ln -sf /opt/bats/bin/bats /usr/local/bin/bats ENV BATS_LIB_PATH="/usr/lib/bats" diff --git a/doc/changelog/CHANGELOG.md b/doc/changelog/CHANGELOG.md index 54c9c2a..e8c99cc 100644 --- a/doc/changelog/CHANGELOG.md +++ b/doc/changelog/CHANGELOG.md @@ -23,6 +23,7 @@ versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - `COPY config/ /config/` from Dockerfile and the `config directory exists` smoke test — the `/config/` directory was never read at runtime (entrypoint only loads `/bridge.yaml`). `config/*.yaml` files remain in the repo as reference examples and can still be consumed via `--build-arg BRIDGE_FILE=config/.yaml`. ### Fixed +- **arm64 / Jetson `./build.sh test` failure (template issue #106).** Dockerfile's inline `bats-src` / `bats-extensions` / `lint-tools` stages had hardcoded `linux.x86_64` / `Linux-x86_64` download URLs, so on arm64 hosts they pulled unusable binaries and the `test` stage exited at `shellcheck -S warning /lint/*.sh`. Migrated to template's pre-built arch-aware `test-tools:local` image (`template/dockerfile/Dockerfile.test-tools` keys off `TARGETARCH`): 3 inline stages deleted, 4 `COPY --from=...` lines switched to `--from=test-tools:local`, net ~17 lines removed. `./build.sh` / `build-worker.yaml` already build `test-tools:local` before the main build. - Restore `.env.example` (removed during APT-mirror refactor) so `setup.sh`'s IMAGE_NAME detection has its documented fallback. ## [v1.4.1] - 2026-03-25 From c3f71d4dfea0cc8bf92edceee0ae86df19b78cc6 Mon Sep 17 00:00:00 2001 From: cyc Date: Fri, 24 Apr 2026 13:13:12 +0800 Subject: [PATCH 2/3] ci: bump main.yaml @tag to v0.9.12 for build-worker load:true fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v0.9.11's build-worker.yaml had a latent bug (discarded test-tools image, docker.io pull fail). v0.9.12 ships the load:true fix — this is the first PR exercising the test-tools:local pattern downstream, so must pin to v0.9.12. template/ subtree stays at v0.9.11 locally (CI uses the remote @tag, not the subtree); a full subtree upgrade to v0.9.12 can follow in a separate PR. --- .github/workflows/main.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 8c74b30..69dcbcd 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -10,7 +10,7 @@ on: jobs: call-docker-build: - uses: ycpss91255-docker/template/.github/workflows/build-worker.yaml@v0.9.11 + uses: ycpss91255-docker/template/.github/workflows/build-worker.yaml@v0.9.12 with: image_name: ros1_bridge build_runtime: true @@ -18,6 +18,6 @@ jobs: call-release: needs: call-docker-build if: startsWith(github.ref, 'refs/tags/') - uses: ycpss91255-docker/template/.github/workflows/release-worker.yaml@v0.9.11 + uses: ycpss91255-docker/template/.github/workflows/release-worker.yaml@v0.9.12 with: archive_name_prefix: ros1_bridge From fc0b0b3a9c504e7f29459e469fd035903af54525 Mon Sep 17 00:00:00 2001 From: cyc Date: Fri, 24 Apr 2026 15:03:04 +0800 Subject: [PATCH 3/3] fix: adopt D plan TEST_TOOLS_IMAGE ARG + bump @v0.9.13 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v0.9.12's load:true attempt didn't actually share images between buildx steps (docker/build-push-action#581). Template v0.9.13 ships D plan: test-tools is published to ghcr.io/ycpss91255-docker/test-tools: per release, and build-worker.yaml passes the GHCR tag via TEST_TOOLS_IMAGE build-arg instead of building test-tools:local in-job. Dockerfile changes: - Top-level ARG TEST_TOOLS_IMAGE="test-tools:local" default keeps local ./build.sh flow unchanged (builds Dockerfile.test-tools into host Docker daemon). - New FROM ${TEST_TOOLS_IMAGE} AS test-tools-stage alias. - 4 COPY --from=test-tools:local switched to --from=test-tools-stage. main.yaml: @v0.9.12 → @v0.9.13 so build-worker passes the resolved GHCR tag for this build. Verified locally: ./build.sh --no-env test on amd64 — 28/28 smoke tests pass, build succeeds with the default test-tools:local ARG. --- .github/workflows/main.yaml | 4 ++-- Dockerfile | 16 +++++++++++----- doc/changelog/CHANGELOG.md | 3 ++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 69dcbcd..3ccbb9e 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -10,7 +10,7 @@ on: jobs: call-docker-build: - uses: ycpss91255-docker/template/.github/workflows/build-worker.yaml@v0.9.12 + uses: ycpss91255-docker/template/.github/workflows/build-worker.yaml@v0.9.13 with: image_name: ros1_bridge build_runtime: true @@ -18,6 +18,6 @@ jobs: call-release: needs: call-docker-build if: startsWith(github.ref, 'refs/tags/') - uses: ycpss91255-docker/template/.github/workflows/release-worker.yaml@v0.9.12 + uses: ycpss91255-docker/template/.github/workflows/release-worker.yaml@v0.9.13 with: archive_name_prefix: ros1_bridge diff --git a/Dockerfile b/Dockerfile index 2bb1673..4001cf7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,5 @@ ARG IMAGE="ros:foxy-ros-base-focal" +ARG TEST_TOOLS_IMAGE="test-tools:local" ############################## devel ############################## FROM ${IMAGE} AS devel @@ -58,11 +59,16 @@ ENTRYPOINT ["/entrypoint.sh"] CMD ["ros2", "run", "ros1_bridge", "parameter_bridge"] ############################## test (ephemeral) ############################## +# Resolves to test-tools:local (local ./build.sh builds Dockerfile.test-tools +# into the host Docker daemon) or ghcr.io/ycpss91255-docker/test-tools:vX.Y.Z +# (CI passes the matching template tag via --build-arg TEST_TOOLS_IMAGE=...). +FROM ${TEST_TOOLS_IMAGE} AS test-tools-stage + FROM devel AS test -# Lint tools (from pre-built test-tools image built by build.sh) -COPY --from=test-tools:local /usr/local/bin/shellcheck /usr/local/bin/shellcheck -COPY --from=test-tools:local /usr/local/bin/hadolint /usr/local/bin/hadolint +# Lint tools (from pre-built test-tools image; see TEST_TOOLS_IMAGE at top) +COPY --from=test-tools-stage /usr/local/bin/shellcheck /usr/local/bin/shellcheck +COPY --from=test-tools-stage /usr/local/bin/hadolint /usr/local/bin/hadolint # Lint: ShellCheck (.sh) + Hadolint (Dockerfile) COPY .hadolint.yaml /lint/.hadolint.yaml @@ -75,8 +81,8 @@ RUN cd /lint && hadolint Dockerfile # Bats + extensions (from pre-built test-tools image; bats-support / bats-assert # are bundled into /usr/lib/bats, no separate stage needed) -COPY --from=test-tools:local /opt/bats /opt/bats -COPY --from=test-tools:local /usr/lib/bats /usr/lib/bats +COPY --from=test-tools-stage /opt/bats /opt/bats +COPY --from=test-tools-stage /usr/lib/bats /usr/lib/bats RUN ln -sf /opt/bats/bin/bats /usr/local/bin/bats ENV BATS_LIB_PATH="/usr/lib/bats" diff --git a/doc/changelog/CHANGELOG.md b/doc/changelog/CHANGELOG.md index e8c99cc..32cfa21 100644 --- a/doc/changelog/CHANGELOG.md +++ b/doc/changelog/CHANGELOG.md @@ -9,6 +9,7 @@ versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Changed - Upgrade `template/` subtree to [v0.9.11](https://github.com/ycpss91255-docker/template/releases/tag/v0.9.11). Brings arm64-native CI (multi-arch matrix on `ubuntu-24.04-arm`), Jetson auto-detect for `[deploy] runtime` / `[build] network` (no more manual `network = host` workaround on Jetson), `_sanitize_lang` i18n, `_lib.sh` / `i18n.sh` dedupe, and `upgrade.sh` destructive fast-forward guards. +- Pin `main.yaml` reusable workflows to [`@v0.9.13`](https://github.com/ycpss91255-docker/template/releases/tag/v0.9.13) — picks up the GHCR test-tools migration (D plan, closes template #106) and the associated `build-worker.yaml` fix. Required because this PR's Dockerfile adopts the `ARG TEST_TOOLS_IMAGE` pattern that v0.9.13 introduced. - Rebuild `devel` stage from `ros:foxy-ros-base-focal` (multi-arch) plus the ROS 1 snapshot apt repo instead of the amd64-only `osrf/ros:foxy-ros1-bridge`. Enables Jetson (arm64) support. - `ENV ROS1_DISTRO=noetic` / `ENV ROS2_DISTRO=foxy` now baked into the image so downstream scripts can reference the distro names without hardcoding. - Test stage lint target uses `COPY script/*.sh /lint/` (glob) to pick up new scripts automatically. @@ -23,7 +24,7 @@ versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - `COPY config/ /config/` from Dockerfile and the `config directory exists` smoke test — the `/config/` directory was never read at runtime (entrypoint only loads `/bridge.yaml`). `config/*.yaml` files remain in the repo as reference examples and can still be consumed via `--build-arg BRIDGE_FILE=config/.yaml`. ### Fixed -- **arm64 / Jetson `./build.sh test` failure (template issue #106).** Dockerfile's inline `bats-src` / `bats-extensions` / `lint-tools` stages had hardcoded `linux.x86_64` / `Linux-x86_64` download URLs, so on arm64 hosts they pulled unusable binaries and the `test` stage exited at `shellcheck -S warning /lint/*.sh`. Migrated to template's pre-built arch-aware `test-tools:local` image (`template/dockerfile/Dockerfile.test-tools` keys off `TARGETARCH`): 3 inline stages deleted, 4 `COPY --from=...` lines switched to `--from=test-tools:local`, net ~17 lines removed. `./build.sh` / `build-worker.yaml` already build `test-tools:local` before the main build. +- **arm64 / Jetson `./build.sh test` failure (closes template #106).** Dockerfile's inline `bats-src` / `bats-extensions` / `lint-tools` stages had hardcoded `linux.x86_64` / `Linux-x86_64` download URLs, so on arm64 hosts they pulled unusable binaries and the `test` stage exited at `shellcheck -S warning /lint/*.sh`. Migrated to template's arch-aware pre-built test-tools image (v0.9.13 D plan): top-level `ARG TEST_TOOLS_IMAGE="test-tools:local"` default keeps local `./build.sh` flow unchanged (builds `Dockerfile.test-tools` into host Docker daemon); CI overrides to `ghcr.io/ycpss91255-docker/test-tools:v0.9.13` via `GITHUB_WORKFLOW_REF` parsing in `build-worker.yaml`. New `FROM ${TEST_TOOLS_IMAGE} AS test-tools-stage` alias; 4 `COPY --from=test-tools:local` → `--from=test-tools-stage`. 3 inline stages deleted, net ~15 lines removed. - Restore `.env.example` (removed during APT-mirror refactor) so `setup.sh`'s IMAGE_NAME detection has its documented fallback. ## [v1.4.1] - 2026-03-25