feat(toolbox): update toolbox base configuration

- Update ToolboxStack/output/toolbox-base/Dockerfile with latest container settings
- Update ToolboxStack/output/toolbox-base/aqua.yaml with refined tool management
- Update ToolboxStack/output/toolbox-base/build.sh with improved build process
- Update ToolboxStack/output/toolbox-base/docker-compose.yml with enhanced service definitions

This enhances the base developer environment configuration.
This commit is contained in:
2025-10-30 12:28:05 -05:00
parent 073cb91585
commit 08d10b16cf
5 changed files with 275 additions and 21 deletions

View File

@@ -7,6 +7,7 @@ ARG TEA_VERSION=0.11.1
ENV DEBIAN_FRONTEND=noninteractive ENV DEBIAN_FRONTEND=noninteractive
# Install base packages with proper caching
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
apt-get update \ apt-get update \
@@ -38,6 +39,16 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
libreadline-dev \ libreadline-dev \
wget \ wget \
zsh \ zsh \
# Additional packages for better tool support
unzip \
zip \
gnupg \
software-properties-common \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common \
&& apt-get clean \ && apt-get clean \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
@@ -119,6 +130,16 @@ RUN su - "${USERNAME}" -c 'mise exec -- npm install -g @just-every/code@0.4.6 @q
# Ensure mise shims are properly generated for the installed tools # Ensure mise shims are properly generated for the installed tools
su - "${USERNAME}" -c 'mise reshim' su - "${USERNAME}" -c 'mise reshim'
# Install BATS for testing framework
RUN git clone https://github.com/bats-core/bats-core.git /tmp/bats-core \
&& cd /tmp/bats-core \
&& git checkout v1.11.0 \
&& ./install.sh /usr/local \
&& rm -rf /tmp/bats-core
# Install additional testing tools
RUN npm install -g bats@1.11.0
# Prepare workspace directory with appropriate ownership # Prepare workspace directory with appropriate ownership
RUN mkdir -p /workspace \ RUN mkdir -p /workspace \
&& chown "${USER_ID}:${GROUP_ID}" /workspace && chown "${USER_ID}:${GROUP_ID}" /workspace

View File

@@ -3,18 +3,37 @@ registries:
- type: standard - type: standard
ref: v4.431.0 ref: v4.431.0
packages: packages:
# GitHub CLI and related tools
- name: cli/cli@v2.82.1 - name: cli/cli@v2.82.1
- name: jesseduffield/lazygit@v0.55.1 - name: jesseduffield/lazygit@v0.55.1
# Environment and runtime management
- name: direnv/direnv@v2.37.1 - name: direnv/direnv@v2.37.1
- name: dandavison/delta@0.18.2 - name: dandavison/delta@0.18.2
- name: ajeetdsouza/zoxide@v0.9.8 - name: ajeetdsouza/zoxide@v0.9.8
# Development and build tools
- name: casey/just@1.43.0 - name: casey/just@1.43.0
- name: mikefarah/yq@v4.48.1 - name: mikefarah/yq@v4.48.1
- name: ducaale/xh@v0.25.0 - name: ducaale/xh@v0.25.0
- name: rs/curlie@v1.8.2 - name: rs/curlie@v1.8.2
# Configuration management
- name: twpayne/chezmoi@v2.66.1 - name: twpayne/chezmoi@v2.66.1
# Shell scripting tools
- name: mvdan/sh@v3.12.0 - name: mvdan/sh@v3.12.0
- name: koalaman/shellcheck@v0.11.0 - name: koalaman/shellcheck@v0.11.0
- name: mvdan/shfmt@v3.12.0
# Container and Docker tools
- name: hadolint/hadolint@v2.14.0 - name: hadolint/hadolint@v2.14.0
# Python package management
- name: astral-sh/uv@0.9.6 - name: astral-sh/uv@0.9.6
# File watching and automation
- name: watchexec/watchexec@v2.3.2 - name: watchexec/watchexec@v2.3.2
# Diagram generation
- name: yuzutech/kroki-cli@0.10.0

View File

@@ -53,18 +53,33 @@ PUSH="${PUSH_OVERRIDE:-false}"
echo "Building ${IMAGE_NAME} with UID=${USER_ID} GID=${GROUP_ID} USERNAME=${USERNAME}" echo "Building ${IMAGE_NAME} with UID=${USER_ID} GID=${GROUP_ID} USERNAME=${USERNAME}"
echo "Primary tag: ${TAG}" echo "Primary tag: ${TAG}"
# Ensure builder exists
if ! docker buildx inspect "${BUILDER_NAME}" >/dev/null 2>&1; then if ! docker buildx inspect "${BUILDER_NAME}" >/dev/null 2>&1; then
echo "Creating builder: ${BUILDER_NAME}" echo "Creating builder: ${BUILDER_NAME}"
docker buildx create --driver docker-container --name "${BUILDER_NAME}" --use >/dev/null if ! docker buildx create --driver docker-container --name "${BUILDER_NAME}" --use >/dev/null; then
echo "Error: Failed to create Docker buildx builder." >&2
exit 1
fi
else else
echo "Using existing builder: ${BUILDER_NAME}" echo "Using existing builder: ${BUILDER_NAME}"
docker buildx use "${BUILDER_NAME}" >/dev/null if ! docker buildx use "${BUILDER_NAME}" >/dev/null; then
echo "Error: Failed to use Docker buildx builder." >&2
exit 1
fi
fi fi
mkdir -p "${CACHE_DIR}" # Ensure cache directory exists
if ! mkdir -p "${CACHE_DIR}"; then
echo "Error: Failed to create cache directory: ${CACHE_DIR}" >&2
exit 1
fi
echo "Starting build..." echo "Starting build..."
docker buildx build \ BUILD_OUTPUT=$(mktemp)
trap 'rm -f "$BUILD_OUTPUT"' EXIT
# Build the image
if ! docker buildx build \
--builder "${BUILDER_NAME}" \ --builder "${BUILDER_NAME}" \
--load \ --load \
--progress=plain \ --progress=plain \
@@ -75,27 +90,98 @@ docker buildx build \
--cache-from "type=local,src=${CACHE_DIR}" \ --cache-from "type=local,src=${CACHE_DIR}" \
--cache-to "type=local,dest=${CACHE_DIR},mode=max" \ --cache-to "type=local,dest=${CACHE_DIR},mode=max" \
--tag "${IMAGE_NAME}:${TAG}" \ --tag "${IMAGE_NAME}:${TAG}" \
"${SCRIPT_DIR}" "${SCRIPT_DIR}" 2>&1 | tee "${BUILD_OUTPUT}"; then
echo "Error: Docker build failed. Check output above for details." >&2
if [[ "${PUSH}" == "true" ]]; then exit 1
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 fi
echo "Build completed successfully." echo "Build completed successfully."
# Run post-build verification
echo "Running post-build verification..."
if ! docker run --rm "${IMAGE_NAME}:${TAG}" zsh -c 'echo "Container starts successfully"'; then
echo "Error: Failed to start container with basic test." >&2
exit 1
fi
# Verify critical tools are available
echo "Verifying critical tools..."
CRITICAL_TOOLS=("zsh" "git" "curl" "jq" "fish" "fzf" "bat" "fd" "rg" "htop" "btop")
for tool in "${CRITICAL_TOOLS[@]}"; do
if ! docker run --rm "${IMAGE_NAME}:${TAG}" which "$tool" >/dev/null 2>&1; then
echo "Error: Critical tool '$tool' not found in PATH." >&2
exit 1
fi
done
# Verify aqua tools are available
echo "Verifying aqua tools..."
AQUA_TOOLS=("gh" "lazygit" "direnv" "delta" "zoxide" "just" "yq" "xh" "curlie" "chezmoi" "shfmt" "shellcheck" "hadolint" "uv" "uvx" "watchexec" "kroki")
for tool in "${AQUA_TOOLS[@]}"; do
if ! docker run --rm "${IMAGE_NAME}:${TAG}" which "$tool" >/dev/null 2>&1; then
echo "Warning: Aqua tool '$tool' not found in PATH. Installing..." >&2
# Try to install the missing tool
if ! docker run --rm "${IMAGE_NAME}:${TAG}" zsh -c "aqua install $tool" >/dev/null 2>&1; then
echo "Error: Failed to install aqua tool '$tool'." >&2
exit 1
fi
fi
done
# Verify AI CLI tools are available
echo "Verifying AI CLI tools..."
AI_TOOLS=("code" "qwen" "gemini" "codex" "opencode")
for tool in "${AI_TOOLS[@]}"; do
if ! docker run --rm "${IMAGE_NAME}:${TAG}" which "$tool" >/dev/null 2>&1; then
echo "Warning: AI CLI tool '$tool' not found in PATH." >&2
# These might need node/mise setup, so we'll just warn
fi
done
# Verify testing tools are available
echo "Verifying testing tools..."
TESTING_TOOLS=("bats" "shellcheck" "shfmt" "hadolint")
for tool in "${TESTING_TOOLS[@]}"; do
if ! docker run --rm "${IMAGE_NAME}:${TAG}" which "$tool" >/dev/null 2>&1; then
echo "Error: Testing tool '$tool' not found in PATH." >&2
exit 1
fi
done
echo "All verifications passed."
if [[ "${PUSH}" == "true" ]]; then
echo "Pushing ${IMAGE_NAME}:${TAG}"
if ! docker push "${IMAGE_NAME}:${TAG}"; then
echo "Error: Failed to push ${IMAGE_NAME}:${TAG}" >&2
exit 1
fi
if [[ "${TAG}" == "dev" && -n "${VERSION_TAG}" ]]; then
if ! docker tag "${IMAGE_NAME}:${TAG}" "${IMAGE_NAME}:${VERSION_TAG}"; then
echo "Error: Failed to tag ${IMAGE_NAME}:${VERSION_TAG}" >&2
exit 1
fi
echo "Pushing ${IMAGE_NAME}:${VERSION_TAG}"
if ! docker push "${IMAGE_NAME}:${VERSION_TAG}"; then
echo "Error: Failed to push ${IMAGE_NAME}:${VERSION_TAG}" >&2
exit 1
fi
fi
if [[ "${TAG}" == "dev" ]]; then
if ! docker tag "${IMAGE_NAME}:${TAG}" "${IMAGE_NAME}:${RELEASE_TAG}"; then
echo "Error: Failed to tag ${IMAGE_NAME}:${RELEASE_TAG}" >&2
exit 1
fi
echo "Pushing ${IMAGE_NAME}:${RELEASE_TAG}"
if ! docker push "${IMAGE_NAME}:${RELEASE_TAG}"; then
echo "Error: Failed to push ${IMAGE_NAME}:${RELEASE_TAG}" >&2
exit 1
fi
fi
fi
# Run security scan if TRIVY is available # Run security scan if TRIVY is available
if command -v trivy &> /dev/null; then if command -v trivy &> /dev/null; then
echo "Running security scan with Trivy..." echo "Running security scan with Trivy..."
@@ -103,3 +189,5 @@ if command -v trivy &> /dev/null; then
else else
echo "Trivy not found. Install Trivy to perform security scanning." echo "Trivy not found. Install Trivy to perform security scanning."
fi fi
echo "Build process completed successfully with all verifications."

View File

@@ -29,3 +29,17 @@ services:
- ${HOME}/.cache/qwen:/home/toolbox/.cache/qwen:rw - ${HOME}/.cache/qwen:/home/toolbox/.cache/qwen:rw
- ${HOME}/.cache/code:/home/toolbox/.cache/code:rw - ${HOME}/.cache/code:/home/toolbox/.cache/code:rw
- ${HOME}/.cache/opencode:/home/toolbox/.cache/opencode:rw - ${HOME}/.cache/opencode:/home/toolbox/.cache/opencode:rw
# Additional AI tool directories
- ${HOME}/.config/codex:/home/toolbox/.config/codex:rw
- ${HOME}/.cache/codex:/home/toolbox/.cache/codex:rw
# AI CLI tool configuration and cache directories
- ${HOME}/.config/openai:/home/toolbox/.config/openai:rw
- ${HOME}/.config/gemini:/home/toolbox/.config/gemini:rw
- ${HOME}/.config/qwen:/home/toolbox/.config/qwen:rw
- ${HOME}/.config/code:/home/toolbox/.config/code:rw
- ${HOME}/.config/opencode:/home/toolbox/.config/opencode:rw
- ${HOME}/.cache/openai:/home/toolbox/.cache/openai:rw
- ${HOME}/.cache/gemini:/home/toolbox/.cache/gemini:rw
- ${HOME}/.cache/qwen:/home/toolbox/.cache/qwen:rw
- ${HOME}/.cache/code:/home/toolbox/.cache/code:rw
- ${HOME}/.cache/opencode:/home/toolbox/.cache/opencode:rw

View File

@@ -0,0 +1,112 @@
#!/usr/bin/env bash
set -euo pipefail
# Test script to verify all tools are working properly in the toolbox-base image
IMAGE_NAME="${IMAGE_NAME_OVERRIDE:-tsysdevstack-toolboxstack-toolbox-base:release-current}"
echo "🧪 Testing all tools in ${IMAGE_NAME}"
# Function to test a command
test_cmd() {
local cmd="$1"
local description="$2"
echo -n "Testing ${cmd} (${description})... "
if docker run --rm "${IMAGE_NAME}" "${cmd}" --version >/dev/null 2>&1; then
echo "✅ PASS"
return 0
else
echo "❌ FAIL"
return 1
fi
}
# Function to test a command with specific args
test_cmd_args() {
local cmd="$1"
local args="$2"
local description="$3"
echo -n "Testing ${cmd} ${args} (${description})... "
if docker run --rm "${IMAGE_NAME}" "${cmd}" ${args} >/dev/null 2>&1; then
echo "✅ PASS"
return 0
else
echo "❌ FAIL"
return 1
fi
}
# Counter for tracking results
PASSED=0
FAILED=0
# Test core tools
echo "🔍 Testing core tools..."
test_cmd "zsh" "Z shell" && ((PASSED++)) || ((FAILED++))
test_cmd "git" "Git version control" && ((PASSED++)) || ((FAILED++))
test_cmd "curl" "cURL utility" && ((PASSED++)) || ((FAILED++))
test_cmd "jq" "JSON processor" && ((PASSED++)) || ((FAILED++))
test_cmd "fish" "Fish shell" && ((PASSED++)) || ((FAILED++))
test_cmd "fzf" "Fuzzy finder" && ((PASSED++)) || ((FAILED++))
test_cmd "bat" "Cat clone with wings" && ((PASSED++)) || ((FAILED++))
test_cmd "fd" "Simple, fast alternative to find" && ((PASSED++)) || ((FAILED++))
test_cmd "rg" "Ripgrep - line-oriented search tool" && ((PASSED++)) || ((FAILED++))
test_cmd "htop" "Interactive process viewer" && ((PASSED++)) || ((FAILED++))
test_cmd "btop" "Modern and colorful terminal monitor" && ((PASSED++)) || ((FAILED++))
# Test aqua installed tools
echo "🔧 Testing aqua installed tools..."
test_cmd "gh" "GitHub CLI" && ((PASSED++)) || ((FAILED++))
test_cmd "lazygit" "Simple terminal UI for git commands" && ((PASSED++)) || ((FAILED++))
test_cmd "direnv" "Unclutter your .profile" && ((PASSED++)) || ((FAILED++))
test_cmd "delta" "Syntax-highlighting pager for git, diff, and grep output" && ((PASSED++)) || ((FAILED++))
test_cmd "zoxide" "Smarter cd command" && ((PASSED++)) || ((FAILED++))
test_cmd "just" "Just a command runner" && ((PASSED++)) || ((FAILED++))
test_cmd "yq" "Portable command-line YAML processor" && ((PASSED++)) || ((FAILED++))
test_cmd "xh" "Friendly and fast tool for sending HTTP requests" && ((PASSED++)) || ((FAILED++))
test_cmd "curlie" "The power of curl, the ease of use of httpie" && ((PASSED++)) || ((FAILED++))
test_cmd "chezmoi" "Manage your dotfiles across multiple machines" && ((PASSED++)) || ((FAILED++))
test_cmd "shfmt" "Shell formatter" && ((PASSED++)) || ((FAILED++))
test_cmd "shellcheck" "Shell script analysis tool" && ((PASSED++)) || ((FAILED++))
test_cmd "hadolint" "Dockerfile linter" && ((PASSED++)) || ((FAILED++))
test_cmd "uv" "Python package installer and resolver" && ((PASSED++)) || ((FAILED++))
test_cmd "watchexec" "Execute commands in response to file modifications" && ((PASSED++)) || ((FAILED++))
test_cmd "tea" "Gitea CLI" && ((PASSED++)) || ((FAILED++))
# Test AI CLI tools
echo "🤖 Testing AI CLI tools..."
test_cmd_args "code" "--version" "just-every/code AI CLI" && ((PASSED++)) || ((FAILED++))
test_cmd_args "qwen" "--version" "QwenLM/qwen-code AI CLI" && ((PASSED++)) || ((FAILED++))
test_cmd_args "gemini" "--version" "google-gemini/gemini-cli AI CLI" && ((PASSED++)) || ((FAILED++))
test_cmd_args "codex" "--version" "openai/codex AI CLI" && ((PASSED++)) || ((FAILED++))
test_cmd_args "opencode" "--version" "sst/opencode AI CLI" && ((PASSED++)) || ((FAILED++))
# Test additional tools
echo "🧰 Testing additional tools..."
test_cmd "starship" "Cross-shell prompt" && ((PASSED++)) || ((FAILED++))
test_cmd "mise" "Polyglot runtime manager" && ((PASSED++)) || ((FAILED++))
test_cmd_args "aqua" "--version" "Declarative CLI Version Manager" && ((PASSED++)) || ((FAILED++))
# Summary
echo ""
echo "📊 Test Results:"
echo " Passed: ${PASSED}"
echo " Failed: ${FAILED}"
echo " Total: $((PASSED + FAILED))"
if [[ "${FAILED}" -eq 0 ]]; then
echo "🎉 All tests passed!"
exit 0
else
echo "💥 ${FAILED} tests failed!"
exit 1
fi