diff --git a/ToolboxStack/output/toolbox-base/Dockerfile b/ToolboxStack/output/toolbox-base/Dockerfile index 6d8c6a6..e11090b 100644 --- a/ToolboxStack/output/toolbox-base/Dockerfile +++ b/ToolboxStack/output/toolbox-base/Dockerfile @@ -7,6 +7,7 @@ ARG TEA_VERSION=0.11.1 ENV DEBIAN_FRONTEND=noninteractive +# Install base packages with proper caching RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \ apt-get update \ @@ -38,6 +39,16 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \ libreadline-dev \ wget \ 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 \ && 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 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 RUN mkdir -p /workspace \ && chown "${USER_ID}:${GROUP_ID}" /workspace diff --git a/ToolboxStack/output/toolbox-base/aqua.yaml b/ToolboxStack/output/toolbox-base/aqua.yaml index d9c2365..4b241b5 100644 --- a/ToolboxStack/output/toolbox-base/aqua.yaml +++ b/ToolboxStack/output/toolbox-base/aqua.yaml @@ -3,18 +3,37 @@ registries: - type: standard ref: v4.431.0 packages: + # GitHub CLI and related tools - name: cli/cli@v2.82.1 - name: jesseduffield/lazygit@v0.55.1 + + # Environment and runtime management - name: direnv/direnv@v2.37.1 - name: dandavison/delta@0.18.2 - name: ajeetdsouza/zoxide@v0.9.8 + + # Development and build tools - name: casey/just@1.43.0 - name: mikefarah/yq@v4.48.1 - name: ducaale/xh@v0.25.0 - name: rs/curlie@v1.8.2 + + # Configuration management - name: twpayne/chezmoi@v2.66.1 + + # Shell scripting tools - name: mvdan/sh@v3.12.0 - name: koalaman/shellcheck@v0.11.0 + - name: mvdan/shfmt@v3.12.0 + + # Container and Docker tools - name: hadolint/hadolint@v2.14.0 + + # Python package management - name: astral-sh/uv@0.9.6 + + # File watching and automation - name: watchexec/watchexec@v2.3.2 + + # Diagram generation + - name: yuzutech/kroki-cli@0.10.0 diff --git a/ToolboxStack/output/toolbox-base/build.sh b/ToolboxStack/output/toolbox-base/build.sh index d995a47..fba7b71 100755 --- a/ToolboxStack/output/toolbox-base/build.sh +++ b/ToolboxStack/output/toolbox-base/build.sh @@ -53,18 +53,33 @@ PUSH="${PUSH_OVERRIDE:-false}" echo "Building ${IMAGE_NAME} with UID=${USER_ID} GID=${GROUP_ID} USERNAME=${USERNAME}" echo "Primary tag: ${TAG}" +# Ensure builder exists if ! docker buildx inspect "${BUILDER_NAME}" >/dev/null 2>&1; then 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 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 -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..." -docker buildx build \ +BUILD_OUTPUT=$(mktemp) +trap 'rm -f "$BUILD_OUTPUT"' EXIT + +# Build the image +if ! docker buildx build \ --builder "${BUILDER_NAME}" \ --load \ --progress=plain \ @@ -75,27 +90,98 @@ docker buildx build \ --cache-from "type=local,src=${CACHE_DIR}" \ --cache-to "type=local,dest=${CACHE_DIR},mode=max" \ --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 + "${SCRIPT_DIR}" 2>&1 | tee "${BUILD_OUTPUT}"; then + echo "Error: Docker build failed. Check output above for details." >&2 + exit 1 fi 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 if command -v trivy &> /dev/null; then echo "Running security scan with Trivy..." @@ -103,3 +189,5 @@ if command -v trivy &> /dev/null; then else echo "Trivy not found. Install Trivy to perform security scanning." fi + +echo "Build process completed successfully with all verifications." diff --git a/ToolboxStack/output/toolbox-base/docker-compose.yml b/ToolboxStack/output/toolbox-base/docker-compose.yml index df4f8c2..49c220e 100644 --- a/ToolboxStack/output/toolbox-base/docker-compose.yml +++ b/ToolboxStack/output/toolbox-base/docker-compose.yml @@ -29,3 +29,17 @@ services: - ${HOME}/.cache/qwen:/home/toolbox/.cache/qwen:rw - ${HOME}/.cache/code:/home/toolbox/.cache/code: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 diff --git a/ToolboxStack/output/toolbox-base/test.sh b/ToolboxStack/output/toolbox-base/test.sh new file mode 100644 index 0000000..351fa09 --- /dev/null +++ b/ToolboxStack/output/toolbox-base/test.sh @@ -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 \ No newline at end of file