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
4 changes: 2 additions & 2 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:

jobs:
call-docker-build:
uses: ycpss91255-docker/template/.github/workflows/build-worker.yaml@v0.10.0-rc2
uses: ycpss91255-docker/template/.github/workflows/build-worker.yaml@v0.10.0
with:
image_name: ros1_bridge
build_runtime: true
Expand All @@ -19,6 +19,6 @@ jobs:
call-release:
needs: call-docker-build
if: startsWith(github.ref, 'refs/tags/')
uses: ycpss91255-docker/template/.github/workflows/release-worker.yaml@v0.10.0-rc2
uses: ycpss91255-docker/template/.github/workflows/release-worker.yaml@v0.10.0
with:
archive_name_prefix: ros1_bridge
10 changes: 6 additions & 4 deletions doc/changelog/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]

### Changed
- Upgrade `template/` subtree to [v0.10.0-rc2](https://github.com/ycpss91255-docker/template/releases/tag/v0.10.0-rc2). Bundles:
- Upgrade `template/` subtree to [v0.10.0](https://github.com/ycpss91255-docker/template/releases/tag/v0.10.0). 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).
- **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`).
- **`--reset-conf` flag on `build.sh`** (closes template #124) — restores `setup.conf` to the template default in one step, backing up the existing `setup.conf` → `setup.conf.bak` and `.env` → `.env.bak` first. `-y` / `--yes` skips the confirmation prompt.
- **`upgrade.sh` sed regex fix** (closes template #61) — handles semver pre-release tags so future RC upgrades stop producing `-rcN-rcM` double suffixes.
- Intermediate releases (v0.9.11 through v0.10.0-rc2) are superseded; this PR pins `main.yaml` directly to `@v0.10.0`.
- Pin `main.yaml` reusable workflows to [`@v0.10.0`](https://github.com/ycpss91255-docker/template/releases/tag/v0.10.0).
- 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
2 changes: 1 addition & 1 deletion template/.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.10.0-rc2
v0.10.0
26 changes: 26 additions & 0 deletions template/doc/changelog/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

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

First stable minor bump post-v0.9.x. Cuts the rc2 feature work + two fixes. **Recommended upgrade path** for all downstream repos (rc1 / rc2 supersede everything earlier, see rc1/rc2 notes below for the full run-phase UX realignment + arm64 test-tools hotfix).

### Added
- **`--reset-conf` flag** on `build.sh` (closes #124). Overwrites `setup.conf` with the template default, backing up the previous `setup.conf` → `setup.conf.bak` and `.env` → `.env.bak` first. Interactive confirmation prompt; `-y` / `--yes` skips it. Internally delegates to the new `./template/init.sh --gen-conf --force` backend. Triggers a `setup.sh` rerun afterward so `.env` + `compose.yaml` regenerate from the fresh conf.
- `./template/init.sh --gen-conf --force` — backend for the above. Without `--force`, `--gen-conf` still refuses to clobber an existing `setup.conf` (unchanged default).
- New-repo `.gitignore` template gains `setup.conf.bak` and `.env.bak` entries so the reset backups never get committed by accident.

### Fixed
- **`upgrade.sh` main.yaml sed regex now handles semver pre-release tags** (closes #61). The prior `[0-9.]*` character class stopped at the first `-`, so upgrading from an existing RC tag (e.g. `v0.10.0-rc1` → `-rc2`) left the old `-rcN` suffix in place and produced `@v0.10.0-rc2-rc1`. First surfaced when ros1_bridge ran `./template/upgrade.sh v0.10.0-rc2` from `@v0.9.13`. Regex now anchored on full semver shape (`\d+\.\d+\.\d+(-[0-9A-Za-z.-]+)?`). Two regression tests added covering RC → RC and RC → stable transitions.

### Release summary

Cumulative highlights from rc1 + rc2 rolled up here for discoverability:

- **Run-phase UX realignment (BREAKING, from rc1, closes #118)**: `./run.sh` target now moves behind explicit `-t/--target`; positional args become CMD passthrough matching `docker run <image> [cmd]`. Migration: `./run.sh runtime` → `./run.sh -t runtime`; plain `./run.sh` unchanged.
- **Compose `runtime` service auto-emission (from rc1, closes #108)**: `setup.sh` detects `FROM … AS runtime` in the Dockerfile and emits a paired service extending `devel`, so `./run.sh -t runtime` actually works.
- **arm64 `test-tools` binaries are now genuinely aarch64 (from rc2)**: `Dockerfile.test-tools` `ARG TARGETARCH=amd64` default used to shadow BuildKit's auto-inject (moby/buildkit#3403), shipping x86_64 shellcheck / hadolint inside the arm64 image. v0.10.0-rc2+ drops the default; multi-arch GHCR `:v0.10.0` variants carry the right binaries per arch.

Downstream repos upgrading from v0.9.x straight to v0.10.0 should:

1. `./template/upgrade.sh v0.10.0`
2. Dockerfile: adopt `ARG TEST_TOOLS_IMAGE="test-tools:local"` + `FROM ${TEST_TOOLS_IMAGE} AS test-tools-stage` + `COPY --from=test-tools-stage` (see `template/dockerfile/Dockerfile.example`).
3. Audit any `./run.sh <target>` call sites and rewrite as `./run.sh -t <target>`.

## [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.
Expand Down
10 changes: 6 additions & 4 deletions template/doc/test/TEST.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TEST.md

Template self-tests: **675 tests** total (632 unit + 43 integration).
Template self-tests: **685 tests** total (642 unit + 43 integration).

## Test Files

Expand Down Expand Up @@ -92,7 +92,7 @@ a canned response; exercised with `TUI_STUB_RESPONSE` / `TUI_STUB_EXIT`.
| `_tui_checklist` (passes `--separate-output`) | 1 |
| `_tui_msgbox` / `_tui_yesno` (correct flags, propagates exit code) | 2 |

### test/unit/build_sh_spec.bats (32)
### test/unit/build_sh_spec.bats (35)

Unit tests for `build.sh` argument handling and control flow. Uses a
sandbox tree mirroring the expected layout (build.sh + `template/` subtree
Expand Down Expand Up @@ -188,7 +188,7 @@ conditional GPU deploy block + GUI env/volumes + extra volumes from
| `runtime detection is robust against weird whitespace` | regex tolerance |
| `runtime detection ignores non-runtime stage names` | strict match |

### test/unit/template_spec.bats (116)
### test/unit/template_spec.bats (118)

| Test | Description |
|------|-------------|
Expand Down Expand Up @@ -288,6 +288,8 @@ conditional GPU deploy block + GUI env/volumes + extra volumes from
| `upgrade.sh --gen-conf delegates to init.sh --gen-conf` | Delegation |
| `upgrade.sh --help mentions --gen-conf` | Help text |
| `upgrade.sh updates main.yaml @tag without clobbering release-worker.yaml` | sed regression |
| `upgrade.sh main.yaml sed handles semver pre-release tags (RC → RC)` | `-rcN-rcN` regression |
| `upgrade.sh main.yaml sed handles stable → stable + RC → stable transitions` | RC → stable cleanup |
| `build-worker.yaml: no legacy in-job test-tools build step` | v0.9.13 GHCR migration |
| `build-worker.yaml: resolves template version from GITHUB_WORKFLOW_REF` | GHCR tag resolution |
| `build-worker.yaml: test build passes TEST_TOOLS_IMAGE build-arg` | build-arg wiring |
Expand Down Expand Up @@ -344,7 +346,7 @@ conditional GPU deploy block + GUI env/volumes + extra volumes from
| `_run_shellcheck: picks up every .sh file in script/docker/` | `find` covers new scripts |
| `_run_shellcheck: exits non-zero when shellcheck fails on any script` | Strict-mode propagation |

### test/unit/init_spec.bats (13)
### test/unit/init_spec.bats (18)

Unit coverage for `init.sh` helpers that previous rounds exercised only
through the Level-1 integration test. Complements
Expand Down
36 changes: 30 additions & 6 deletions template/init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,14 @@ jobs:
YAML
_log " Created .github/workflows/main.yaml"

# .gitignore (compose.yaml + .env are setup.sh-generated artifacts)
# .gitignore (compose.yaml + .env are setup.sh-generated artifacts;
# *.bak siblings are written by `./template/init.sh --gen-conf --force`
# on a reset-conf, see #124 / issue #60 — keep them local-only.)
cat > .gitignore <<'GIT'
.env
.env.bak
compose.yaml
setup.conf.bak
coverage/
.Dockerfile.generated
GIT
Expand Down Expand Up @@ -278,13 +282,28 @@ _init_existing_repo() {
_gen_setup_conf() {
local _src="${TEMPLATE_DIR}/setup.conf"
local _dst="${REPO_ROOT}/setup.conf"
local _force="${1:-false}"
if [[ ! -f "${_src}" ]]; then
_error "Template setup.conf not found at ${_src}"
fi
if [[ -f "${_dst}" ]]; then
_error "setup.conf already exists at ${_dst}. Remove it first or edit directly."
if [[ "${_force}" != "true" ]]; then
_error "setup.conf already exists at ${_dst}. Remove it first or edit directly."
fi
# --force path: back up the existing conf (and .env, since a reset
# will regenerate it from the new conf baseline) to *.bak siblings
# before overwriting. `.gitignore` ignores these so they never get
# committed by accident.
local _bak="${_dst}.bak"
cp -f "${_dst}" "${_bak}"
_log "Backed up existing setup.conf → ${_bak}"
if [[ -f "${REPO_ROOT}/.env" ]]; then
local _env_bak="${REPO_ROOT}/.env.bak"
cp -f "${REPO_ROOT}/.env" "${_env_bak}"
_log "Backed up existing .env → ${_env_bak}"
fi
fi
cp "${_src}" "${_dst}"
cp -f "${_src}" "${_dst}"
_log "Created ${_dst}"
_log "Edit it to customize runtime settings for this repo."
}
Expand All @@ -310,7 +329,7 @@ _error() { printf "[init] ERROR: %s\n" "$*" >&2; exit 1; }
main() {
if [[ "${1:-}" =~ ^(-h|--help)$ ]]; then
cat >&2 <<'EOF'
Usage: ./template/init.sh [--gen-conf]
Usage: ./template/init.sh [--gen-conf [--force]]

Initialize a repo with template. Auto-detects:
- Has Dockerfile → create symlinks, then run setup.sh
Expand All @@ -322,7 +341,10 @@ Options:
--gen-conf Copy template/setup.conf to <repo>/setup.conf so the
user can override any section (image / build / deploy /
gui / network / volumes). Refuses to overwrite an
existing per-repo setup.conf.
existing per-repo setup.conf unless --force is given.
--force With --gen-conf: overwrite existing setup.conf,
backing up the previous setup.conf to setup.conf.bak
and .env to .env.bak first.

Run from the repo root after:
git subtree add --prefix=template \
Expand All @@ -334,7 +356,9 @@ EOF
cd "${REPO_ROOT}"

if [[ "${1:-}" == "--gen-conf" ]]; then
_gen_setup_conf
local _force=false
[[ "${2:-}" == "--force" ]] && _force=true
_gen_setup_conf "${_force}"
return 0
fi

Expand Down
66 changes: 62 additions & 4 deletions template/script/docker/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,15 @@ usage() {
case "${_LANG}" in
zh-TW)
cat >&2 <<'EOF'
用法: ./build.sh [-h] [-s|--setup] [--no-cache] [--clean-tools] [--dry-run] [--lang <en|zh-TW|zh-CN|ja>] [TARGET]
用法: ./build.sh [-h] [-s|--setup] [--reset-conf] [-y|--yes] [--no-cache] [--clean-tools] [--dry-run] [--lang <en|zh-TW|zh-CN|ja>] [TARGET]

選項:
-h, --help 顯示此說明
-s, --setup 強制重跑 setup.sh 重新生成 .env + compose.yaml
(預設:.env 不存在時自動 bootstrap;存在時僅印 drift warning)
--reset-conf 用 template 預設值覆蓋 setup.conf(先備份到 setup.conf.bak
+ .env.bak;需確認,可用 -y 跳過)。之後會自動重跑 setup。
-y, --yes 略過 --reset-conf 的互動確認
--no-cache 強制不使用 cache 重建
--clean-tools build 結束後移除 test-tools:local image(預設保留以加速下次 build)
--dry-run 只印出將執行的 docker 指令,不實際執行
Expand All @@ -68,12 +71,15 @@ EOF
;;
zh-CN)
cat >&2 <<'EOF'
用法: ./build.sh [-h] [-s|--setup] [--no-cache] [--clean-tools] [--dry-run] [--lang <en|zh-TW|zh-CN|ja>] [TARGET]
用法: ./build.sh [-h] [-s|--setup] [--reset-conf] [-y|--yes] [--no-cache] [--clean-tools] [--dry-run] [--lang <en|zh-TW|zh-CN|ja>] [TARGET]

选项:
-h, --help 显示此说明
-s, --setup 强制重跑 setup.sh 重新生成 .env + compose.yaml
(默认:.env 不存在时自动 bootstrap;存在时仅打印 drift warning)
--reset-conf 用 template 默认值覆盖 setup.conf(先备份到 setup.conf.bak
+ .env.bak;需确认,可用 -y 跳过)。之后会自动重跑 setup。
-y, --yes 跳过 --reset-conf 的交互确认
--no-cache 强制不使用 cache 重建
--clean-tools build 结束后移除 test-tools:local image(默认保留以加速下次 build)
--dry-run 只打印将执行的 docker 命令,不实际执行
Expand All @@ -87,12 +93,16 @@ EOF
;;
ja)
cat >&2 <<'EOF'
使用法: ./build.sh [-h] [-s|--setup] [--no-cache] [--clean-tools] [--dry-run] [--lang <en|zh-TW|zh-CN|ja>] [TARGET]
使用法: ./build.sh [-h] [-s|--setup] [--reset-conf] [-y|--yes] [--no-cache] [--clean-tools] [--dry-run] [--lang <en|zh-TW|zh-CN|ja>] [TARGET]

オプション:
-h, --help このヘルプを表示
-s, --setup setup.sh を強制実行して .env + compose.yaml を再生成
(デフォルト:.env が無ければ自動 bootstrap、あれば drift warning のみ)
--reset-conf setup.conf をテンプレのデフォルトで上書き(setup.conf.bak
+ .env.bak にバックアップ;確認プロンプト、-y でスキップ)。
その後 setup を再実行。
-y, --yes --reset-conf の確認プロンプトをスキップ
--no-cache キャッシュを使わず強制リビルド
--clean-tools build 終了後に test-tools:local image を削除(デフォルトは保持)
--dry-run 実行される docker コマンドを表示するのみ(実行はしない)
Expand All @@ -106,12 +116,18 @@ EOF
;;
*)
cat >&2 <<'EOF'
Usage: ./build.sh [-h] [-s|--setup] [--no-cache] [--clean-tools] [--dry-run] [--lang <en|zh-TW|zh-CN|ja>] [TARGET]
Usage: ./build.sh [-h] [-s|--setup] [--reset-conf] [-y|--yes] [--no-cache] [--clean-tools] [--dry-run] [--lang <en|zh-TW|zh-CN|ja>] [TARGET]

Options:
-h, --help Show this help
-s, --setup Force rerun setup.sh to regenerate .env + compose.yaml
(default: auto-bootstrap if .env missing; warn on drift if present)
--reset-conf Overwrite setup.conf with template defaults (backs up the
existing setup.conf → setup.conf.bak and .env → .env.bak
first). Prompts for confirmation; pass -y to skip. Triggers
a setup.sh rerun afterward so .env + compose.yaml follow
the fresh conf.
-y, --yes Skip the --reset-conf confirmation prompt
--no-cache Force rebuild without cache
--clean-tools Remove test-tools:local image after build (default: keep for faster next build)
--dry-run Print the docker commands that would run, but do not execute
Expand All @@ -129,6 +145,8 @@ EOF

main() {
local RUN_SETUP=false
local RESET_CONF=false
local ASSUME_YES=false
local NO_CACHE=false
local CLEAN_TOOLS=false
local TARGET="devel"
Expand All @@ -143,6 +161,14 @@ main() {
RUN_SETUP=true
shift
;;
--reset-conf)
RESET_CONF=true
shift
;;
-y|--yes)
ASSUME_YES=true
shift
;;
--no-cache)
NO_CACHE=true
shift
Expand All @@ -168,6 +194,38 @@ main() {
done
export DRY_RUN

# --reset-conf: delegate to init.sh --gen-conf --force. Confirms unless
# -y/--yes is passed. Backs up the existing setup.conf + .env to
# *.bak siblings (git-ignored) before overwriting, so the reset is
# recoverable. Runs before the normal bootstrap/drift flow below so
# subsequent setup.sh invocation regenerates .env + compose.yaml from
# the fresh conf.
if [[ "${RESET_CONF}" == true ]]; then
local _conf="${FILE_PATH}/setup.conf"
local _env="${FILE_PATH}/.env"
if [[ -f "${_conf}" || -f "${_env}" ]]; then
if [[ "${ASSUME_YES}" != true && "${DRY_RUN}" != true ]]; then
printf "[build] --reset-conf will overwrite:\n" >&2
[[ -f "${_conf}" ]] && printf " %s (backup → %s.bak)\n" "${_conf}" "${_conf}" >&2
[[ -f "${_env}" ]] && printf " %s (backup → %s.bak)\n" "${_env}" "${_env}" >&2
printf "[build] proceed? [y/N] " >&2
local _reply
read -r _reply
case "${_reply}" in
y|Y|yes|YES) ;;
*) printf "[build] aborted.\n" >&2; exit 1 ;;
esac
fi
fi
if [[ "${DRY_RUN}" == true ]]; then
printf "[dry-run] %s/template/init.sh --gen-conf --force\n" "${FILE_PATH}"
else
bash "${FILE_PATH}/template/init.sh" --gen-conf --force
fi
# Force a fresh setup.sh run so .env + compose.yaml follow the new conf.
RUN_SETUP=true
fi

local _setup="${FILE_PATH}/template/script/docker/setup.sh"
local _tui="${FILE_PATH}/setup_tui.sh"

Expand Down
31 changes: 31 additions & 0 deletions template/test/unit/build_sh_spec.bats
Original file line number Diff line number Diff line change
Expand Up @@ -501,3 +501,34 @@ EOS
assert_failure
assert_output --partial "エラー"
}

# ════════════════════════════════════════════════════════════════════
# --reset-conf flag (issue #60 / #124)
# ════════════════════════════════════════════════════════════════════

@test "build.sh --reset-conf --yes --dry-run prints init.sh --gen-conf --force cmd" {
# -y skips the interactive prompt; --dry-run makes the init.sh call
# a printf instead of an exec so we can assert it without sandbox
# side effects.
echo "old" > "${SANDBOX}/setup.conf"
run bash "${SANDBOX}/build.sh" --reset-conf --yes --dry-run
assert_success
assert_output --partial "[dry-run]"
assert_output --partial "template/init.sh --gen-conf --force"
}

@test "build.sh --reset-conf is mentioned in usage help" {
run bash "${SANDBOX}/build.sh" --help
assert_success
assert_output --partial "--reset-conf"
assert_output --partial "setup.conf.bak"
}

@test "build.sh --reset-conf with no existing setup.conf / .env skips prompt" {
# Nothing to overwrite → no confirmation needed, --dry-run just prints
# the init.sh call and exits cleanly.
rm -f "${SANDBOX}/setup.conf" "${SANDBOX}/.env"
run bash "${SANDBOX}/build.sh" --reset-conf --dry-run
assert_success
refute_output --partial "proceed?"
}
Loading
Loading