From 27948346b4a37a201712c3d51eb9870199d87616 Mon Sep 17 00:00:00 2001 From: ReachableCEO Date: Wed, 29 Oct 2025 08:26:35 -0500 Subject: [PATCH] feat(toolbox): update toolbox configuration and scripts - Update collab/TSYSDevStack-toolbox-prompt.md with latest guidelines - Update output/PROMPT with improved instructions for AI collaboration - Update output/toolbox-base/PROMPT with enhanced development guidelines - Update output/toolbox-base/README.md with current documentation - Update output/toolbox-base/build.sh with improved build process - Update output/toolbox-base/docker-compose.yml with refined service definitions - Update output/toolbox-base/run.sh with enhanced runtime configuration - Add output/toolbox-base/release.sh for release management processes These changes improve the developer workspace experience and ensure consistent tooling across the TSYSDevStack project. --- .../collab/TSYSDevStack-toolbox-prompt.md | 2 +- ToolboxStack/output/PROMPT | 2 + ToolboxStack/output/toolbox-base/PROMPT | 8 +- ToolboxStack/output/toolbox-base/README.md | 15 +++- ToolboxStack/output/toolbox-base/build.sh | 24 ++++- .../output/toolbox-base/docker-compose.yml | 2 +- ToolboxStack/output/toolbox-base/release.sh | 90 +++++++++++++++++++ ToolboxStack/output/toolbox-base/run.sh | 1 + 8 files changed, 134 insertions(+), 10 deletions(-) create mode 100755 ToolboxStack/output/toolbox-base/release.sh diff --git a/ToolboxStack/collab/TSYSDevStack-toolbox-prompt.md b/ToolboxStack/collab/TSYSDevStack-toolbox-prompt.md index 46d201c..cd80632 100644 --- a/ToolboxStack/collab/TSYSDevStack-toolbox-prompt.md +++ b/ToolboxStack/collab/TSYSDevStack-toolbox-prompt.md @@ -25,7 +25,7 @@ The TSYSDevStack consists of four categories: - mise - zsh / oh-my-zsh / completions / - -- See `output/PROMPT` for shared toolbox contributor guidance, `output/toolbox-base/PROMPT` for the image-specific snapshot, and `output/NewToolbox.sh` for bootstrapping new toolboxes from the template (edit each toolbox's `SEED` once to set goals, then load its PROMPT when starting work). +- See `output/PROMPT` for shared toolbox contributor guidance, `output/toolbox-base/PROMPT` for the image-specific snapshot, and `output/NewToolbox.sh` for bootstrapping new toolboxes from the template (edit each toolbox's `SEED` once to set goals, then load its PROMPT when starting work). Toolbox images follow a `dev` → `release-current` → `vX.Y.Z` tagging scheme; use `build.sh` for local iteration and `release.sh ` (clean tree) to promote builds (details in README). ## toolbox-gis ## toolbox-weather diff --git a/ToolboxStack/output/PROMPT b/ToolboxStack/output/PROMPT index cc1bee9..b684660 100644 --- a/ToolboxStack/output/PROMPT +++ b/ToolboxStack/output/PROMPT @@ -6,6 +6,8 @@ Global toolbox guidance: - Keep aqua/mise usage consistent across the family; prefer aqua-managed CLIs and mise-managed runtimes. - Reference toolbox-template when bootstrapping a new toolbox. Copy the directory, rename it, and replace {{toolbox_name}} placeholders in compose/devcontainer. - Each toolbox maintains a `SEED` file to seed the initial goals—edit it once before kicking off work, then rely on the toolbox PROMPT for ongoing updates (which begins by reading SEED). +- Default build workflow: `./build.sh` produces a `:dev` tag; `./release.sh ` (clean git tree required) rebuilds and pushes `:dev`, `:release-current`, and `v` (use `--dry-run`/`--allow-dirty` to rehearse). +- Downstream Dockerfiles should inherit from `:release-current` by default; pin to version tags when reproducibility matters. Commit discipline: - Craft atomic commits with clear intent; do not mix unrelated changes. diff --git a/ToolboxStack/output/toolbox-base/PROMPT b/ToolboxStack/output/toolbox-base/PROMPT index 1cd94d2..ef79167 100644 --- a/ToolboxStack/output/toolbox-base/PROMPT +++ b/ToolboxStack/output/toolbox-base/PROMPT @@ -12,14 +12,14 @@ Current state: - mise handles language/tool runtimes; activation wired into zsh, bash, and fish. - docker-compose.yml runs container with host UID/GID, `sleep infinity`, and docker socket mount; run via run.sh/build.sh. Host directories `~/.local/share/mise` and `~/.cache/mise` are mounted for persistent runtimes. - Devcontainer config ( .devcontainer/devcontainer.json ) references the compose service. -- Documentation: README.md (tooling inventory & workflow) and this PROMPT must stay current, and both should stay aligned with the shared guidance in ../PROMPT. README also notes that build.sh now uses docker buildx with a local cache directory. +- Documentation: README.md (tooling inventory & workflow) and this PROMPT must stay current, and both should stay aligned with the shared guidance in ../PROMPT. README also notes that build.sh now uses docker buildx with a local cache directory and documents the `dev` → `release-current` → semantic tagging workflow. Collaboration guidelines: 1. Default to non-destructive operations; respect existing scripts run.sh/build.sh. -2. Any tooling changes require updating README.md (inventory) and this prompt summary, rebuilding via ./build.sh, then committing (Conventional Commits, atomic diffs) and pushing after a successful build per ../PROMPT. +2. Any tooling changes require updating README.md (inventory) and this prompt summary, rebuilding via `./build.sh` (local dev tag), then committing (Conventional Commits, atomic diffs) and pushing after a successful build per ../PROMPT. Use `./release.sh ` (clean git tree required; `--dry-run`/`--allow-dirty` only for rehearsal) to promote to `release-current` + semantic tag. 3. Keep configurations reproducible: prefer aqua/mise for new CLI/runtimes over apt unless prerequisites. -4. Mention verification steps (build/test) after changes. -5. Maintain UID/GID mapping and non-root execution. +4. Mention verification steps (build/test) after changes and note which tag was built/pushed. +5. Downstream consumers should inherit from `:release-current` (or a pinned semantic tag); maintain UID/GID mapping and non-root execution. Active focus: - Extend toolbox-base as a "daily driver" dev container while preserving reproducibility and documentation. diff --git a/ToolboxStack/output/toolbox-base/README.md b/ToolboxStack/output/toolbox-base/README.md index ab47cc9..9dfd829 100644 --- a/ToolboxStack/output/toolbox-base/README.md +++ b/ToolboxStack/output/toolbox-base/README.md @@ -6,16 +6,16 @@ Daily-driver development container for ToolboxStack work. It provides a reproduc ## 🚀 Quick Start -1. **Build the image** +1. **Build the image (local dev tag)** ```bash ./build.sh ``` - > Uses `docker buildx` with a local cache at `.build-cache/` for faster rebuilds. + > Builds and tags the image as `tsysdevstack-toolboxstack-toolbox-base:dev`. Uses `docker buildx` with a local cache at `.build-cache/` for faster rebuilds. 2. **Start the container** ```bash ./run.sh up ``` - > Mise runtimes persist to your host in `~/.local/share/mise` and `~/.cache/mise` so language/tool downloads are shared across projects. + > Defaults to the `release-current` tag; override with `TOOLBOX_IMAGE_OVERRIDE=...` when testing other tags. Mise runtimes persist to your host in `~/.local/share/mise` and `~/.cache/mise` so language/tool downloads are shared across projects. 3. **Attach to a shell** ```bash docker exec -it tsysdevstack-toolboxstack-toolbox-base zsh @@ -30,6 +30,15 @@ The compose service mounts the current repo to `/workspace` (read/write) and run --- +## 🏷️ Image Tagging & Releases + +- `./build.sh` (no overrides) ⇒ builds `:dev` for active development. +- `./release.sh ` ⇒ rebuilds, retags, and pushes `:dev`, `:release-current`, and `v` (e.g., `./release.sh 0.2.0`). Requires a clean git tree. +- Add `--dry-run` to rehearse the release without pushing (optionally `--allow-dirty` for experimentation only). +- Downstream Dockerfiles should inherit from `tsysdevstack-toolboxstack-toolbox-base:release-current` (or pin to a semantic tag for reproducibility). + +--- + ## 🧩 Tooling Inventory | Category | Tooling | Notes | diff --git a/ToolboxStack/output/toolbox-base/build.sh b/ToolboxStack/output/toolbox-base/build.sh index 664df94..63616c0 100755 --- a/ToolboxStack/output/toolbox-base/build.sh +++ b/ToolboxStack/output/toolbox-base/build.sh @@ -11,8 +11,13 @@ USERNAME="${USERNAME_OVERRIDE:-toolbox}" TEA_VERSION="${TEA_VERSION_OVERRIDE:-0.11.1}" BUILDER_NAME="${BUILDER_NAME:-tsysdevstack-toolboxstack-builder}" CACHE_DIR="${SCRIPT_DIR}/.build-cache" +TAG="${TAG_OVERRIDE:-dev}" +RELEASE_TAG="${RELEASE_TAG_OVERRIDE:-release-current}" +VERSION_TAG="${VERSION_TAG_OVERRIDE:-}" +PUSH="${PUSH_OVERRIDE:-false}" echo "Building ${IMAGE_NAME} with UID=${USER_ID} GID=${GROUP_ID} USERNAME=${USERNAME}" +echo "Primary tag: ${TAG}" if ! docker buildx inspect "${BUILDER_NAME}" >/dev/null 2>&1; then docker buildx create --driver docker-container --name "${BUILDER_NAME}" --use >/dev/null @@ -32,5 +37,22 @@ docker buildx build \ --build-arg TEA_VERSION="${TEA_VERSION}" \ --cache-from "type=local,src=${CACHE_DIR}" \ --cache-to "type=local,dest=${CACHE_DIR},mode=max" \ - --tag "${IMAGE_NAME}" \ + --tag "${IMAGE_NAME}:${TAG}" \ "${SCRIPT_DIR}" + +if [[ "${PUSH}" == "true" ]]; then + echo "Pushing ${IMAGE_NAME}:${TAG}" + docker push "${IMAGE_NAME}:${TAG}" + + if [[ "${TAG}" == "dev" && -n "${VERSION_TAG}" ]]; then + docker tag "${IMAGE_NAME}:${TAG}" "${IMAGE_NAME}:${VERSION_TAG}" + echo "Pushing ${IMAGE_NAME}:${VERSION_TAG}" + docker push "${IMAGE_NAME}:${VERSION_TAG}" + fi + + if [[ "${TAG}" == "dev" ]]; then + docker tag "${IMAGE_NAME}:${TAG}" "${IMAGE_NAME}:${RELEASE_TAG}" + echo "Pushing ${IMAGE_NAME}:${RELEASE_TAG}" + docker push "${IMAGE_NAME}:${RELEASE_TAG}" + fi +fi diff --git a/ToolboxStack/output/toolbox-base/docker-compose.yml b/ToolboxStack/output/toolbox-base/docker-compose.yml index 667cbab..761fa51 100644 --- a/ToolboxStack/output/toolbox-base/docker-compose.yml +++ b/ToolboxStack/output/toolbox-base/docker-compose.yml @@ -1,7 +1,7 @@ services: toolbox-base: container_name: tsysdevstack-toolboxstack-toolbox-base - image: tsysdevstack-toolboxstack-toolbox-base + image: ${TOOLBOX_IMAGE:-tsysdevstack-toolboxstack-toolbox-base:release-current} build: context: . args: diff --git a/ToolboxStack/output/toolbox-base/release.sh b/ToolboxStack/output/toolbox-base/release.sh new file mode 100755 index 0000000..0f3eaa3 --- /dev/null +++ b/ToolboxStack/output/toolbox-base/release.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash + +set -euo pipefail + +usage() { + cat <<'EOU' +Usage: ./release.sh [--dry-run] [--allow-dirty] + +Examples: + ./release.sh 0.2.0 + ./release.sh --dry-run 0.2.0 + +This script rebuilds the toolbox-base image, tags it as: + - tsysdevstack-toolboxstack-toolbox-base:dev + - tsysdevstack-toolboxstack-toolbox-base:release-current + - tsysdevstack-toolboxstack-toolbox-base:v + +When run without --dry-run it pushes all three tags. +EOU +} + +DRY_RUN=false +ALLOW_DIRTY=false +VERSION="" + +while (( $# > 0 )); do + case "$1" in + --dry-run) + DRY_RUN=true + shift + ;; + --allow-dirty) + ALLOW_DIRTY=true + shift + ;; + -h|--help) + usage + exit 0 + ;; + -*) + echo "Unknown option: $1" >&2 + usage + exit 1 + ;; + *) + VERSION="$1" + shift + ;; + esac +done + +if [[ -z "${VERSION}" ]]; then + echo "Error: semantic version is required." >&2 + usage + exit 1 +fi + +if [[ "${VERSION}" =~ ^v?([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then + SEMVER="v${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.${BASH_REMATCH[3]}" +else + echo "Error: version must be semantic (e.g., 0.2.0 or v0.2.0)." >&2 + exit 1 +fi + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}" && git rev-parse --show-toplevel 2>/dev/null || true)" + +if [[ -n "${REPO_ROOT}" && "${ALLOW_DIRTY}" != "true" ]]; then + if ! git -C "${REPO_ROOT}" diff --quiet --ignore-submodules --exit-code; then + echo "Error: git working tree has uncommitted changes. Please commit or stash before releasing." >&2 + exit 1 + fi +elif [[ -z "${REPO_ROOT}" ]]; then + echo "Warning: unable to resolve git repository root; skipping clean tree check." >&2 +fi + +echo "Preparing release for ${SEMVER}" +echo " dry-run: ${DRY_RUN}" +echo " allow-dirty: ${ALLOW_DIRTY}" + +if [[ "${DRY_RUN}" == "true" ]]; then + VERSION_TAG_OVERRIDE="${SEMVER}" PUSH_OVERRIDE=false "${SCRIPT_DIR}/build.sh" + echo "[dry-run] Skipped pushing tags." +else + VERSION_TAG_OVERRIDE="${SEMVER}" PUSH_OVERRIDE=true "${SCRIPT_DIR}/build.sh" + echo "Release ${SEMVER} pushed as:" + echo " - tsysdevstack-toolboxstack-toolbox-base:dev" + echo " - tsysdevstack-toolboxstack-toolbox-base:release-current" + echo " - tsysdevstack-toolboxstack-toolbox-base:${SEMVER}" +fi diff --git a/ToolboxStack/output/toolbox-base/run.sh b/ToolboxStack/output/toolbox-base/run.sh index c36bb2d..57f8998 100755 --- a/ToolboxStack/output/toolbox-base/run.sh +++ b/ToolboxStack/output/toolbox-base/run.sh @@ -8,6 +8,7 @@ COMPOSE_FILE="${SCRIPT_DIR}/docker-compose.yml" export LOCAL_UID="${USER_ID_OVERRIDE:-$(id -u)}" export LOCAL_GID="${GROUP_ID_OVERRIDE:-$(id -g)}" export LOCAL_USERNAME="${USERNAME_OVERRIDE:-toolbox}" +export TOOLBOX_IMAGE="${TOOLBOX_IMAGE_OVERRIDE:-tsysdevstack-toolboxstack-toolbox-base:release-current}" if [[ ! -f "${COMPOSE_FILE}" ]]; then echo "Error: docker-compose.yml not found at ${COMPOSE_FILE}" >&2