Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions doc/changelog/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]

### 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.
- Upgrade `template/` subtree to [v0.10.0-rc2](https://github.com/ycpss91255-docker/template/releases/tag/v0.10.0-rc2). Bundles:
- **Compose `runtime` service** auto-emitted by `setup.sh` when Dockerfile declares `FROM … AS runtime` (closes template #108). `./run.sh -t runtime` no longer errors with "no such service".
- **`run.sh` arg realignment** (closes template #118, BREAKING): target is now `-t/--target` flag (default `devel`); positional args become CMD passthrough (empty → Dockerfile CMD, non-empty → override); `-d + cmd` → exit 2 error. `./run.sh` bare unchanged (devel bash). Migration inside this repo: `./run.sh runtime` now written as `./run.sh -t runtime` (auto-runs `parameter_bridge` attached). `./run.sh -t runtime bash` drops into runtime shell for debug.
- **arm64 test-tools** hotfix — `Dockerfile.test-tools` `ARG TARGETARCH=amd64` default used to shadow BuildKit's auto-inject (moby/buildkit#3403), so `:v0.9.13` / `:v0.10.0-rc1` GHCR arm64 variants shipped x86_64 shellcheck / hadolint. v0.10.0-rc2 drops the default; arm64 binaries are now genuinely aarch64 (verified via `docker cp` + `file`).
- Intermediate releases (v0.9.11/12/13, v0.10.0-rc1) are superseded; this PR pins `main.yaml` directly to `@v0.10.0-rc2`.
- Pin `main.yaml` reusable workflows to [`@v0.10.0-rc2`](https://github.com/ycpss91255-docker/template/releases/tag/v0.10.0-rc2).
- 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.
Expand Down
7 changes: 7 additions & 0 deletions template/.github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 5
46 changes: 23 additions & 23 deletions template/.github/workflows/build-worker.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,7 @@ jobs:
fi

- name: Set up Docker Buildx
# docker-container driver is required even on single-platform
# builds now: the downstream Dockerfile's `test` stage
# references `test-tools:local` via `COPY --from=`, and with
# docker-container the tag built in the previous buildx step
# stays in the same builder's internal store, which subsequent
# build-push-action steps can resolve. The legacy `docker`
# driver stores images in the host daemon, which isn't
# accessible from a matrix job's buildx container.
uses: docker/setup-buildx-action@v3
with:
driver: docker-container

- name: Generate .env
run: |
Expand All @@ -143,21 +133,30 @@ jobs:
EOF
mkdir -p /tmp/workspace

- name: Build test-tools image
# Must use buildx (not plain `docker build`) so `test-tools:local`
# lands in buildx's internal image store — subsequent build
# steps on the same builder resolve `COPY --from=test-tools:local`
# from there. docker-container's builder container doesn't see
# host daemon images.
uses: docker/build-push-action@v6
with:
context: .
file: template/dockerfile/Dockerfile.test-tools
tags: test-tools:local
platforms: ${{ matrix.platform }}
push: false
- name: Resolve template version for test-tools image
# The downstream repo's main.yaml pins this workflow via
# uses: ycpss91255-docker/template/.github/workflows/build-worker.yaml@vX.Y.Z
# GITHUB_WORKFLOW_REF exposes that full ref at runtime. Parse
# out the tag so we can pin the test-tools GHCR image to the
# matching template release (prevents version skew between the
# workflow logic and the test-tools contract it assumes).
id: tplver
shell: bash
run: |
ref="${GITHUB_WORKFLOW_REF##*@}"
case "${ref}" in
refs/tags/v*) ver="${ref##refs/tags/}" ;;
*) ver="latest" ;;
esac
printf 'image=ghcr.io/ycpss91255-docker/test-tools:%s\n' "${ver}" >> "${GITHUB_OUTPUT}"

- name: Build test stage (includes smoke tests)
# The downstream Dockerfile consumes TEST_TOOLS_IMAGE as the
# source of `COPY --from=${TEST_TOOLS_IMAGE}`; buildx auto-pulls
# the image from GHCR on `COPY --from=<name:tag>` when the tag
# is not present locally, so no explicit docker-pull step is
# needed here. Public visibility of the GHCR package means
# anonymous pull works, keeping the build-args simple.
uses: docker/build-push-action@v6
with:
context: .
Expand All @@ -170,6 +169,7 @@ jobs:
UID=1000
GID=1000
HARDWARE=${{ matrix.hardware }}
TEST_TOOLS_IMAGE=${{ steps.tplver.outputs.image }}
${{ inputs.build_args }}

- name: Build devel stage
Expand Down
73 changes: 73 additions & 0 deletions template/.github/workflows/release-test-tools.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Release test-tools image to GHCR

# Multi-arch (linux/amd64 + linux/arm64) build of
# template/dockerfile/Dockerfile.test-tools, pushed to
# ghcr.io/ycpss91255-docker/test-tools tagged with the release version
# and :latest. Downstream repo Dockerfiles consume this via
# `ARG TEST_TOOLS_IMAGE=ghcr.io/ycpss91255-docker/test-tools:<ver>`,
# avoiding the cross-step image-store isolation that sank the previous
# `test-tools:local` approach (v0.9.11 pre-D migration).
#
# Triggers:
# push of a vX.Y.Z tag -> pushes :<tag> and :latest
# workflow_dispatch -> manual bootstrap; pushes only :latest
#
# Needs packages: write to push to GHCR under the org namespace.

on:
push:
tags:
- 'v*'
workflow_dispatch:

permissions:
contents: read
packages: write

jobs:
release-test-tools:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Resolve tags
id: tags
shell: bash
run: |
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
ver="${GITHUB_REF##refs/tags/}"
printf 'tags=ghcr.io/ycpss91255-docker/test-tools:%s,ghcr.io/ycpss91255-docker/test-tools:latest\n' "${ver}" >> "${GITHUB_OUTPUT}"
else
printf 'tags=ghcr.io/ycpss91255-docker/test-tools:latest\n' >> "${GITHUB_OUTPUT}"
fi

- name: Set up QEMU
# Needed for the arm64 leg; amd64 alone could skip it, but the
# QEMU setup is a no-op on native arch so we keep the workflow
# simple with a single builder.
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push multi-arch test-tools image
# This workflow runs inside the template repo, not a downstream
# consumer, so the Dockerfile lives at `dockerfile/...`, not
# `template/dockerfile/...` (the latter is only the subtree path
# downstream repos see and is what build-worker.yaml uses since
# that workflow executes in the downstream's checkout).
uses: docker/build-push-action@v6
with:
context: .
file: dockerfile/Dockerfile.test-tools
platforms: linux/amd64,linux/arm64
tags: ${{ steps.tags.outputs.tags }}
push: true
2 changes: 1 addition & 1 deletion template/.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.9.11
v0.10.0-rc2
38 changes: 35 additions & 3 deletions template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,16 @@ Notes:
- `test` is always built from `devel`, so runtime assertions inside
`test/smoke/<repo>_env.bats` see the same binaries / files a user would
find after `docker run ... <repo>:devel`.
- `Dockerfile.test-tools` builds a separate `test-tools:local` image (not
part of the stage chain above) that the `test` stage copies bats /
shellcheck / hadolint binaries from via `COPY --from=test-tools:local`.
- `Dockerfile.test-tools` builds the lint/test tool bundle (bats + shellcheck +
hadolint). The downstream `test` stage consumes it through an `ARG
TEST_TOOLS_IMAGE` build arg — defaults to `test-tools:local` (matches the
local `./build.sh` flow that builds `Dockerfile.test-tools` into the host
Docker daemon). CI overrides it to
`ghcr.io/ycpss91255-docker/test-tools:vX.Y.Z` (pre-built multi-arch image
pushed by `.github/workflows/release-test-tools.yaml` on every tag) so
buildx pulls the arch-correct binaries over the wire instead of rebuilding
them per run, and sidesteps the cross-step image-store isolation that
`docker-container` buildx drivers enforce.

### Smoke test helpers (for downstream repos)

Expand Down Expand Up @@ -289,6 +296,31 @@ make upgrade
./template/upgrade.sh v0.3.0
```

`upgrade.sh` handles the full cycle in one go: `git subtree pull --squash`,
post-pull integrity check (rolls back on destructive FF), `./template/init.sh`
to resync root symlinks, and `sed` of `.github/workflows/main.yaml`'s
`build-worker.yaml@vX.Y.Z` / `release-worker.yaml@vX.Y.Z` references. Don't
subtree pull by hand — the sed + init steps are easy to forget.

#### Automated version bumps (optional)

Downstream repos can let Dependabot open PRs whenever a new `template` tag
ships. Add `.github/dependabot.yml`:

```yaml
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
```

Dependabot notices the `uses: ycpss91255-docker/template/...@vX.Y.Z` refs in
`main.yaml`, compares against the template's latest tag, and files a PR. You
still run `./template/upgrade.sh vX.Y.Z` locally to sync the subtree itself —
Dependabot only bumps the workflow refs.

## CI Reusable Workflows

Repos replace local `build-worker.yaml` / `release-worker.yaml` with calls to this repo's reusable workflows:
Expand Down
49 changes: 49 additions & 0 deletions template/doc/changelog/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [v0.10.0-rc2] - 2026-04-24

Second release candidate. Ships the arm64 test-tools hotfix that v0.10.0-rc1 / v0.9.13 both missed — **strongly recommended** over rc1 for any downstream repo enabling the arm64 build matrix.

### Fixed
- **`Dockerfile.test-tools` `ARG TARGETARCH=amd64` default shadowed BuildKit's per-platform auto-inject** ([moby/buildkit#3403](https://github.com/moby/buildkit/issues/3403)). Every multi-arch build published via `release-test-tools.yaml` (v0.9.13, v0.10.0-rc1) therefore fell back to `amd64` and shipped x86_64 `shellcheck` / `hadolint` binaries inside the arm64 image variant. Symptom downstream: `shellcheck: Exec format error` on arm64 CI (ros1_bridge PR #27 first surfaced it). Fix: declare `ARG TARGETARCH` without default so BuildKit's injected value drives the `case` branch. Regression test added: `Dockerfile.test-tools ARG TARGETARCH has no default value`. Requires a new tag + `release-test-tools.yaml` re-run to reissue `:v0.10.0-rc2` + `:latest` on GHCR.

## [v0.10.0-rc1] - 2026-04-24

Release candidate for v0.10.0. BREAKING: `run.sh` arg semantics realigned.
Validate on `ros1_bridge` (`./run.sh -t runtime` attaches to bridge logs,
`./run.sh -t runtime bash` drops into runtime shell) + at least one
GUI-using env repo before promoting to v0.10.0.

### Added
- **`runtime` compose service auto-emission (closes #108)**. `setup.sh` now detects a `FROM <base> AS runtime` stage in the sibling Dockerfile and emits a paired `runtime` service that `extends: { service: devel }` (inherits volumes / env / network / GPU / caps), overrides `build.target`, `image` (`:runtime` tag), `container_name` (`<name>-runtime`), and flips `stdin_open: false` / `tty: false` for headless auto-run. Gated by `profiles: [runtime]` so plain `compose up` still scopes to `devel`; `compose run runtime` / `compose up runtime` (and `./run.sh -t runtime`) target it explicitly. Repos without an `AS runtime` stage get no emission (no broken service entry).

### Changed
- **BREAKING: `./run.sh` arg semantics aligned with `docker run <image> [cmd]` (closes #118).**
- Target is now the explicit `-t TARGET` / `--target TARGET` flag (default `devel`).
- Positional args after options are the CMD to run inside the container, mirroring `exec.sh`. Empty CMD → Dockerfile CMD runs (`devel` = `bash`, `runtime` = its auto-run service). Non-empty CMD → overrides Dockerfile CMD.
- `-d` + CMD → error (exit 2) with a pointer to `./exec.sh` for the detached-container cmd case; `-d` alone is unchanged (`compose up -d TARGET`).
- Migration: `./run.sh runtime` → `./run.sh -t runtime`. `./run.sh test` → `./run.sh -t test`. Plain `./run.sh` still drops into devel bash (unchanged UX).

## [v0.9.13] - 2026-04-24

### Added
- **`.github/workflows/release-test-tools.yaml`** — on every tag push (and manual `workflow_dispatch`), builds multi-arch (amd64 + arm64) `Dockerfile.test-tools` and publishes to `ghcr.io/ycpss91255-docker/test-tools:<tag>` + `:latest`. First release triggered by this tag; package visibility should be set to public on first push so downstream Dockerfiles can pull anonymously.
- **`TEST_TOOLS_IMAGE` build-arg** in `Dockerfile.example` — defaults to `test-tools:local` (preserves the local `./build.sh` flow that builds `Dockerfile.test-tools` into the host daemon). Override in CI to `ghcr.io/ycpss91255-docker/test-tools:vX.Y.Z` so buildx pulls the arch-correct pre-built image over the wire.

### Changed
- **BREAKING for downstream repos adopting v0.9.13+ workflows**: `build-worker.yaml` no longer builds `test-tools:local` in-job. Instead it parses the template version from `GITHUB_WORKFLOW_REF` and passes `TEST_TOOLS_IMAGE=ghcr.io/ycpss91255-docker/test-tools:<template-ver>` as a build-arg to the test stage. Downstream Dockerfiles must add `ARG TEST_TOOLS_IMAGE="test-tools:local"` + `FROM ${TEST_TOOLS_IMAGE} AS test-tools-stage` + `COPY --from=test-tools-stage` (the previous `COPY --from=test-tools:local` literal stops working once repos bump their `main.yaml` `@tag` to `v0.9.13`). Existing repos pinned to `@v0.9.12` or earlier remain unaffected until they upgrade.
- `Dockerfile.example` test stage restructured: new `FROM ${TEST_TOOLS_IMAGE} AS test-tools-stage` alias, 4 `COPY --from=test-tools:local` → `COPY --from=test-tools-stage`, top-level comment updated.

### Fixed
- **CI `COPY --from=test-tools:local` no longer fails with `pull access denied` on downstream repos** (follow-up to v0.9.12 `load: true` attempt, which turned out not to share images between buildx steps — [docker/build-push-action#581](https://github.com/docker/build-push-action/issues/581)). GHCR-backed approach sidesteps the cross-step image-store isolation entirely.
- **`release-test-tools.yaml` Dockerfile path** — was wrongly written as `template/dockerfile/Dockerfile.test-tools` (the downstream subtree path); in the template repo itself the file is at `dockerfile/Dockerfile.test-tools`. Regression test added to assert no subtree-prefixed path leaks back in.

## [v0.9.12] - 2026-04-24

### Added
- `.github/dependabot.yml` — weekly `github-actions` ecosystem scan so template's own consumed actions (`actions/checkout`, `docker/*`, etc.) stay current without manual audits.

### Changed
- README "Updating" section (4 languages) clarifies that `./template/upgrade.sh` already automates subtree pull + integrity check + `init.sh` resync + `main.yaml` `@vX.Y.Z` sed; hand-rolling `git subtree pull` is discouraged since the sed + init steps are easy to forget. Adds a Dependabot snippet downstream repos can drop into their `.github/dependabot.yml` so template version bumps surface as PRs automatically (Dependabot handles workflow refs only; subtree still needs `upgrade.sh`).

### Fixed
- **`build-worker.yaml` test-tools build now uses `load: true`.** Without it, `docker/build-push-action@v6` with `push: false` discards the built image, so subsequent `COPY --from=test-tools:local` in the downstream Dockerfile can't resolve the tag. buildx then falls back to registry pull → `docker.io/library/test-tools:local: pull access denied` → CI fail. Surfaced when `ros1_bridge` became the first downstream repo to adopt `test-tools:local` post-v0.9.11 (issue #106 migration PR). Added `test/unit/template_spec.bats` regression test asserting the `load: true` flag is present.

## [v0.9.11] - 2026-04-24

### Fixed
Expand Down
22 changes: 18 additions & 4 deletions template/doc/readme/README.ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,7 @@ flowchart LR
- `test` は常に `devel` を継承するため、`test/smoke/<repo>_env.bats` の
runtime assertion が確認するバイナリやファイルは、ユーザーが
`docker run ... <repo>:devel` で目にするものと一致します。
- `Dockerfile.test-tools` は別途 `test-tools:local` image をビルドし
(上記ステージ連鎖には含まれません)、`test` ステージが
`COPY --from=test-tools:local` で bats / shellcheck / hadolint
バイナリを取り込みます。
- `Dockerfile.test-tools` は lint/test ツールセット(bats + shellcheck + hadolint)をビルドします。ダウンストリームの `test` ステージは `ARG TEST_TOOLS_IMAGE` build arg で参照します — デフォルト `test-tools:local`(ローカル `./build.sh` フロー、`Dockerfile.test-tools` を host Docker daemon に load)。CI では `ghcr.io/ycpss91255-docker/test-tools:vX.Y.Z`(`.github/workflows/release-test-tools.yaml` がタグ push ごとに publish するマルチアーキ image)で override し、buildx が registry からアーキ対応の bats / shellcheck / hadolint binary を直接 pull します。`docker-container` buildx driver の step 間 image store 分離問題を回避。

### Smoke test ヘルパー(ダウンストリーム repo 用)

Expand Down Expand Up @@ -299,6 +296,23 @@ make upgrade
./template/upgrade.sh v0.3.0
```

`upgrade.sh` は一度に完結します:`git subtree pull --squash`、post-pull 整合性チェック(destructive FF を検出したら自動 rollback)、`./template/init.sh` による root symlinks の再同期、そして `.github/workflows/main.yaml` 内の `build-worker.yaml@vX.Y.Z` / `release-worker.yaml@vX.Y.Z` を sed で更新します。手動で `git subtree pull` しないでください — sed と init の手順を忘れがちです。

#### 自動バージョン更新(任意)

ダウンストリーム repo は、`template` の新しい tag が出るたびに Dependabot が PR を立てるよう設定できます。`.github/dependabot.yml` を追加します:

```yaml
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
```

Dependabot は `main.yaml` 内の `uses: ycpss91255-docker/template/...@vX.Y.Z` ref を見て、template の最新 tag と照合して PR を出します。subtree 自体は引き続きローカルで `./template/upgrade.sh vX.Y.Z` を実行する必要があります — Dependabot が扱うのは workflow ref のみです。

## CI Reusable Workflows

各 repo のローカル `build-worker.yaml` / `release-worker.yaml` を、本 repo の reusable workflows 呼び出しに置き換えます:
Expand Down
Loading
Loading