Compare commits
3 Commits
8eabe6cf37
...
3dd420a500
| Author | SHA1 | Date | |
|---|---|---|---|
| 3dd420a500 | |||
| 87f32cfd4b | |||
| 0337f401a7 |
@@ -205,9 +205,9 @@ update_status() {
|
|||||||
# Sanitize inputs to prevent injection
|
# Sanitize inputs to prevent injection
|
||||||
# Remove any pipe characters which would interfere with table format
|
# Remove any pipe characters which would interfere with table format
|
||||||
# Escape regex special characters to prevent sed injection
|
# Escape regex special characters to prevent sed injection
|
||||||
local clean_app_name=$(printf '%s\n' "$app_name" | sed 's/|//g; s/[[\.*^$()+?{|\\]/\\&/g')
|
local clean_app_name=$(printf '%s\n' "$app_name" | sed 's/|//g; s/[\[\.*^$()+?{|\\]/\\&/g')
|
||||||
local clean_status=$(printf '%s\n' "$new_status" | sed 's/|//g; s/[[\.*^$()+?{|\\]/\\&/g')
|
local clean_status=$(printf '%s\n' "$new_status" | sed 's/|//g; s/[\[\.*^$()+?{|\\]/\\&/g')
|
||||||
local clean_notes=$(printf '%s\n' "$notes" | sed 's/|//g; s/[[\.*^$()+?{|\\]/\\&/g' | sed 's/&/&/g; s/</</g; s/>/>/g')
|
local clean_notes=$(printf '%s\n' "$notes" | sed 's/|//g; s/[\[\.*^$()+?{|\\]/\\&/g' | sed 's/&/&/g; s/</</g; s/>/>/g')
|
||||||
|
|
||||||
# Use file locking to prevent race conditions when multiple processes update the file
|
# Use file locking to prevent race conditions when multiple processes update the file
|
||||||
local lock_file="$STATUS_FILE.lock"
|
local lock_file="$STATUS_FILE.lock"
|
||||||
@@ -331,7 +331,9 @@ run_packaging_script() {
|
|||||||
# Clone repository
|
# Clone repository
|
||||||
if [ ! -d "$workspace_dir/repo" ] || [ -z "$(ls -A "$workspace_dir/repo" 2>/dev/null)" ]; then
|
if [ ! -d "$workspace_dir/repo" ] || [ -z "$(ls -A "$workspace_dir/repo" 2>/dev/null)" ]; then
|
||||||
echo "Cloning $url to $workspace_dir/repo" | tee -a "$app_log_file"
|
echo "Cloning $url to $workspace_dir/repo" | tee -a "$app_log_file"
|
||||||
if ! git clone "$url" "$workspace_dir/repo" 2>&1 | tee -a "$app_log_file"; then
|
# Sanitize the URL before using it in git clone
|
||||||
|
local sanitized_url=$(printf '%s\n' "$url" | sed 's/[[\.*^$()+?{|\\]/\\&/g')
|
||||||
|
if ! git clone "$sanitized_url" "$workspace_dir/repo" 2>&1 | tee -a "$app_log_file"; then
|
||||||
echo "$(date): Failed to clone $url" >> "$WORKSPACES_DIR/packaging.log"
|
echo "$(date): Failed to clone $url" >> "$WORKSPACES_DIR/packaging.log"
|
||||||
update_status "$repo_name" "🛑 FAILED" "Failed to clone repository"
|
update_status "$repo_name" "🛑 FAILED" "Failed to clone repository"
|
||||||
return 1
|
return 1
|
||||||
@@ -362,7 +364,9 @@ run_packaging_script() {
|
|||||||
update_status "$repo_name" "🔄 IN PROGRESS" "Repo update failed, will retry with fresh clone"
|
update_status "$repo_name" "🔄 IN PROGRESS" "Repo update failed, will retry with fresh clone"
|
||||||
# Remove the repo and try to clone again
|
# Remove the repo and try to clone again
|
||||||
rm -rf "$workspace_dir/repo"
|
rm -rf "$workspace_dir/repo"
|
||||||
if ! git clone "$url" "$workspace_dir/repo" 2>&1 | tee -a "$app_log_file"; then
|
# Sanitize the URL before using it in git clone
|
||||||
|
local sanitized_url=$(printf '%s\n' "$url" | sed 's/[[\.*^$()+?{|\\]/\\&/g')
|
||||||
|
if ! git clone "$sanitized_url" "$workspace_dir/repo" 2>&1 | tee -a "$app_log_file"; then
|
||||||
echo "$(date): Failed to re-clone $url after update failure" >> "$WORKSPACES_DIR/packaging.log"
|
echo "$(date): Failed to re-clone $url after update failure" >> "$WORKSPACES_DIR/packaging.log"
|
||||||
update_status "$repo_name" "🛑 FAILED" "Failed to update or re-clone repository"
|
update_status "$repo_name" "🛑 FAILED" "Failed to update or re-clone repository"
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ RUN chown "${USER_ID}:${GROUP_ID}" /tmp/aqua.yaml \
|
|||||||
&& su - "${USERNAME}" -c 'AQUA_GLOBAL_CONFIG=~/.config/aquaproj-aqua/aqua.yaml aqua install'
|
&& su - "${USERNAME}" -c 'AQUA_GLOBAL_CONFIG=~/.config/aquaproj-aqua/aqua.yaml aqua install'
|
||||||
|
|
||||||
# Install AI CLI tools via npm using mise to ensure Node.js is available
|
# Install AI CLI tools via npm using mise to ensure Node.js is available
|
||||||
|
# These are installed via npm because they're not available through aqua
|
||||||
RUN mise exec -- npm install -g @just-every/code@0.4.6 @qwen-code/qwen-code@0.1.1 @google/gemini-cli@0.11.0 @openai/codex@0.50.0 opencode-ai@0.15.29
|
RUN mise exec -- npm install -g @just-every/code@0.4.6 @qwen-code/qwen-code@0.1.1 @google/gemini-cli@0.11.0 @openai/codex@0.50.0 opencode-ai@0.15.29
|
||||||
|
|
||||||
# Install the same AI CLI tools for the toolbox user so they are available in the container runtime
|
# Install the same AI CLI tools for the toolbox user so they are available in the container runtime
|
||||||
|
|||||||
@@ -37,3 +37,10 @@ packages:
|
|||||||
|
|
||||||
# Diagram generation
|
# Diagram generation
|
||||||
- name: yuzutech/kroki-cli@0.10.0
|
- name: yuzutech/kroki-cli@0.10.0
|
||||||
|
|
||||||
|
# AI CLI tools (baked into image)
|
||||||
|
- name: just-every/code@0.4.6
|
||||||
|
- name: QwenLM/qwen-code@0.1.1
|
||||||
|
- name: google-gemini/gemini-cli@0.11.0
|
||||||
|
- name: openai/codex@0.50.0
|
||||||
|
- name: sst/opencode@0.15.29
|
||||||
|
|||||||
@@ -16,6 +16,26 @@ RUN if getent passwd "${USER_ID}" >/dev/null; then \
|
|||||||
fi \
|
fi \
|
||||||
&& useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /usr/bin/zsh --create-home "${USERNAME}"
|
&& useradd --uid "${USER_ID}" --gid "${GROUP_ID}" --shell /usr/bin/zsh --create-home "${USERNAME}"
|
||||||
|
|
||||||
|
# Install toolbox-specific packages here
|
||||||
|
# Example:
|
||||||
|
# RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
# specific-package \
|
||||||
|
# && apt-get clean \
|
||||||
|
# && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install toolbox-specific aqua packages here
|
||||||
|
# Example:
|
||||||
|
# COPY aqua.yaml /tmp/aqua.yaml
|
||||||
|
# RUN chown "${USER_ID}:${GROUP_ID}" /tmp/aqua.yaml \
|
||||||
|
# && su - "${USERNAME}" -c 'mkdir -p ~/.config/aquaproj-aqua' \
|
||||||
|
# && su - "${USERNAME}" -c 'cp /tmp/aqua.yaml ~/.config/aquaproj-aqua/aqua.yaml' \
|
||||||
|
# && AQUA_GLOBAL_CONFIG=/tmp/aqua.yaml aqua install \
|
||||||
|
# && su - "${USERNAME}" -c 'AQUA_GLOBAL_CONFIG=~/.config/aquaproj-aqua/aqua.yaml aqua install'
|
||||||
|
|
||||||
|
# Install toolbox-specific npm packages here
|
||||||
|
# Example:
|
||||||
|
# RUN mise exec -- npm install -g @scope/package@version
|
||||||
|
|
||||||
# Remove sudo to ensure no root escalation is possible at runtime
|
# Remove sudo to ensure no root escalation is possible at runtime
|
||||||
RUN apt-get remove -y sudo 2>/dev/null || true && apt-get autoremove -y 2>/dev/null || true && rm -rf /var/lib/apt/lists/* 2>/dev/null || true
|
RUN apt-get remove -y sudo 2>/dev/null || true && apt-get autoremove -y 2>/dev/null || true && rm -rf /var/lib/apt/lists/* 2>/dev/null || true
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Current state:
|
|||||||
- See ../PROMPT for shared toolbox contribution expectations (documentation sync, build cadence, commit/push discipline, Conventional Commits, atomic history).
|
- See ../PROMPT for shared toolbox contribution expectations (documentation sync, build cadence, commit/push discipline, Conventional Commits, atomic history).
|
||||||
|
|
||||||
Collaboration checklist:
|
Collaboration checklist:
|
||||||
1. Build upon the base tooling with {{toolbox_name}}-specific additions; mirror outcomes in README.md and this PROMPT.
|
1. Translate SEED goals into concrete tooling decisions; mirror outcomes in README.md and this PROMPT (do not rewrite SEED unless the scope resets).
|
||||||
2. Prefer aqua-managed CLIs and mise-managed runtimes for reproducibility.
|
2. Prefer aqua-managed CLIs and mise-managed runtimes for reproducibility.
|
||||||
3. After each tooling change, update README/PROMPT, run ./build.sh, commit (Conventional Commit message, focused diff), and push only once the build succeeds per ../PROMPT.
|
3. After each tooling change, update README/PROMPT, run ./build.sh, commit (Conventional Commit message, focused diff), and push only once the build succeeds per ../PROMPT.
|
||||||
4. Record verification steps (build/test commands) as they are performed.
|
4. Record verification steps (build/test commands) as they are performed.
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ This SEED file defines the high-level objectives for all toolboxes created from
|
|||||||
- **Dockerfile**: Extend from base with toolbox-specific tooling
|
- **Dockerfile**: Extend from base with toolbox-specific tooling
|
||||||
- **docker-compose.yml**: Configure service with inherited + custom settings
|
- **docker-compose.yml**: Configure service with inherited + custom settings
|
||||||
- **build.sh**: Wrapper around `docker build` with UID/GID mapping
|
- **build.sh**: Wrapper around `docker build` with UID/GID mapping
|
||||||
- **run.sh**: Helper to bring service up/down with proper directory setup
|
- **run.sh**: Helper to bring service up/down
|
||||||
- **devcontainer.json**: VS Code remote container definition
|
- **devcontainer.json**: VS Code remote container definition
|
||||||
- **SEED**: Define toolbox-specific objectives (this file)
|
- **SEED**: Define toolbox-specific objectives (this file)
|
||||||
- **PROMPT**: LLM onboarding prompt for future contributors
|
- **PROMPT**: LLM onboarding prompt for future contributors
|
||||||
|
|||||||
@@ -5,4 +5,18 @@ registries:
|
|||||||
packages:
|
packages:
|
||||||
# Add additional packages specific to your toolbox here
|
# Add additional packages specific to your toolbox here
|
||||||
# Example:
|
# Example:
|
||||||
# - name: cli/cli@v2.82.1
|
# - name: cli/cli@v2.82.1
|
||||||
|
# - name: jesseduffield/lazygit@v0.55.1
|
||||||
|
# - name: direnv/direnv@v2.37.1
|
||||||
|
# - name: dandavison/delta@0.18.2
|
||||||
|
# - name: ajeetdsouza/zoxide@v0.9.8
|
||||||
|
# - name: casey/just@1.43.0
|
||||||
|
# - name: mikefarah/yq@v4.48.1
|
||||||
|
# - name: ducaale/xh@v0.25.0
|
||||||
|
# - name: rs/curlie@v1.8.2
|
||||||
|
# - name: twpayne/chezmoi@v2.66.1
|
||||||
|
# - name: mvdan/sh@v3.12.0
|
||||||
|
# - name: koalaman/shellcheck@v0.11.0
|
||||||
|
# - name: hadolint/hadolint@v2.14.0
|
||||||
|
# - name: astral-sh/uv@0.9.6
|
||||||
|
# - name: watchexec/watchexec@v2.3.2
|
||||||
@@ -29,7 +29,6 @@ fi
|
|||||||
TOOLBOX_NAME="${TOOLBOX_NAME_OVERRIDE:-$(basename "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")}"
|
TOOLBOX_NAME="${TOOLBOX_NAME_OVERRIDE:-$(basename "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")}"
|
||||||
sanitized_input "$TOOLBOX_NAME"
|
sanitized_input "$TOOLBOX_NAME"
|
||||||
IMAGE_NAME="tsysdevstack-toolboxstack-${TOOLBOX_NAME#toolbox-}"
|
IMAGE_NAME="tsysdevstack-toolboxstack-${TOOLBOX_NAME#toolbox-}"
|
||||||
sanitized_input "$IMAGE_NAME"
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
# Sanitize user input
|
# Sanitize user input
|
||||||
@@ -44,21 +43,46 @@ sanitized_input "$TEA_VERSION"
|
|||||||
BUILDER_NAME="${BUILDER_NAME:-tsysdevstack-toolboxstack-builder}"
|
BUILDER_NAME="${BUILDER_NAME:-tsysdevstack-toolboxstack-builder}"
|
||||||
sanitized_input "$BUILDER_NAME"
|
sanitized_input "$BUILDER_NAME"
|
||||||
CACHE_DIR="${SCRIPT_DIR}/.build-cache"
|
CACHE_DIR="${SCRIPT_DIR}/.build-cache"
|
||||||
|
TAG="${TAG_OVERRIDE:-dev}"
|
||||||
|
sanitized_input "$TAG"
|
||||||
|
RELEASE_TAG="${RELEASE_TAG_OVERRIDE:-release-current}"
|
||||||
|
sanitized_input "$RELEASE_TAG"
|
||||||
|
VERSION_TAG="${VERSION_TAG_OVERRIDE:-}"
|
||||||
|
if [[ -n "$VERSION_TAG" ]]; then
|
||||||
|
sanitized_input "$VERSION_TAG"
|
||||||
|
fi
|
||||||
|
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}"
|
||||||
|
|
||||||
|
# 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 \
|
||||||
@@ -68,15 +92,102 @@ docker buildx build \
|
|||||||
--build-arg TEA_VERSION="${TEA_VERSION}" \
|
--build-arg TEA_VERSION="${TEA_VERSION}" \
|
||||||
--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 "${IMAGE_NAME}:${TAG}" \
|
||||||
"${SCRIPT_DIR}"
|
"${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."
|
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 "Error: Aqua tool '$tool' not found in PATH." >&2
|
||||||
|
exit 1
|
||||||
|
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 "Error: AI CLI tool '$tool' not found in PATH." >&2
|
||||||
|
exit 1
|
||||||
|
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."
|
||||||
|
|
||||||
|
# Push if requested
|
||||||
|
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..."
|
||||||
trivy image --exit-code 0 --severity HIGH,CRITICAL "${IMAGE_NAME}"
|
trivy image --exit-code 0 --severity HIGH,CRITICAL "${IMAGE_NAME}:${TAG}"
|
||||||
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."
|
||||||
@@ -32,15 +32,4 @@ services:
|
|||||||
- ${HOME}/.cache/opencode:/home/toolbox/.cache/opencode:rw
|
- ${HOME}/.cache/opencode:/home/toolbox/.cache/opencode:rw
|
||||||
# Additional AI tool directories
|
# Additional AI tool directories
|
||||||
- ${HOME}/.config/codex:/home/toolbox/.config/codex:rw
|
- ${HOME}/.config/codex:/home/toolbox/.config/codex:rw
|
||||||
- ${HOME}/.cache/codex:/home/toolbox/.cache/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
|
|
||||||
@@ -10,9 +10,12 @@ Examples:
|
|||||||
./release.sh 0.2.0
|
./release.sh 0.2.0
|
||||||
./release.sh --dry-run 0.2.0
|
./release.sh --dry-run 0.2.0
|
||||||
|
|
||||||
This script promotes the dev tag to:
|
This script rebuilds the toolbox image, tags it as:
|
||||||
|
- tsysdevstack-toolboxstack-<name>:dev
|
||||||
- tsysdevstack-toolboxstack-<name>:release-current
|
- tsysdevstack-toolboxstack-<name>:release-current
|
||||||
- tsysdevstack-toolboxstack-<name>:v<semver>
|
- tsysdevstack-toolboxstack-<name>:v<semver>
|
||||||
|
|
||||||
|
When run without --dry-run it pushes all three tags.
|
||||||
EOU
|
EOU
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,32 +74,38 @@ elif [[ -z "${REPO_ROOT}" ]]; then
|
|||||||
echo "Warning: unable to resolve git repository root; skipping clean tree check." >&2
|
echo "Warning: unable to resolve git repository root; skipping clean tree check." >&2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Get the toolbox name from the directory name
|
# Get the toolbox name from the directory name (or you can pass it as an argument)
|
||||||
TOOLBOX_NAME="${TOOLBOX_NAME_OVERRIDE:-$(basename "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")}"
|
TOOLBOX_NAME="${TOOLBOX_NAME_OVERRIDE:-$(basename "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")}"
|
||||||
IMAGE_NAME="tsysdevstack-toolboxstack-${TOOLBOX_NAME#toolbox-}"
|
IMAGE_NAME="tsysdevstack-toolboxstack-${TOOLBOX_NAME#toolbox-}"
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
|
||||||
|
USER_ID="${USER_ID_OVERRIDE:-$(id -u)}"
|
||||||
|
GROUP_ID="${GROUP_ID_OVERRIDE:-$(id -g)}"
|
||||||
|
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:-}"
|
||||||
|
if [[ -n "$VERSION_TAG" ]]; then
|
||||||
|
VERSION_TAG="$SEMVER"
|
||||||
|
fi
|
||||||
|
PUSH="${PUSH_OVERRIDE:-false}"
|
||||||
|
|
||||||
echo "Preparing release for ${SEMVER}"
|
echo "Preparing release for ${SEMVER}"
|
||||||
echo " dry-run: ${DRY_RUN}"
|
echo " dry-run: ${DRY_RUN}"
|
||||||
echo " allow-dirty: ${ALLOW_DIRTY}"
|
echo " allow-dirty: ${ALLOW_DIRTY}"
|
||||||
|
|
||||||
# First, ensure we have the dev tag built
|
|
||||||
if [[ "${DRY_RUN}" == "true" ]]; then
|
if [[ "${DRY_RUN}" == "true" ]]; then
|
||||||
echo "[dry-run] Would build dev tag"
|
echo "[dry-run] Would build ${IMAGE_NAME}:${TAG}"
|
||||||
|
TAG_OVERRIDE="${TAG}" PUSH_OVERRIDE=false "${SCRIPT_DIR}/build.sh"
|
||||||
|
echo "[dry-run] Skipped pushing tags."
|
||||||
else
|
else
|
||||||
echo "Building dev tag..."
|
echo "Building ${IMAGE_NAME}:${TAG}"
|
||||||
"${SCRIPT_DIR}/build.sh"
|
TAG_OVERRIDE="${TAG}" PUSH_OVERRIDE=true RELEASE_TAG_OVERRIDE="${RELEASE_TAG}" VERSION_TAG_OVERRIDE="${SEMVER}" "${SCRIPT_DIR}/build.sh"
|
||||||
fi
|
echo "Release ${SEMVER} pushed as:"
|
||||||
|
echo " - ${IMAGE_NAME}:dev"
|
||||||
# Tag the dev image as release-current and with the version
|
|
||||||
if [[ "${DRY_RUN}" == "true" ]]; then
|
|
||||||
echo "[dry-run] Would tag ${IMAGE_NAME}:dev as:"
|
|
||||||
echo " - ${IMAGE_NAME}:release-current"
|
|
||||||
echo " - ${IMAGE_NAME}:${SEMVER}"
|
|
||||||
else
|
|
||||||
echo "Tagging ${IMAGE_NAME}:dev as release-current and ${SEMVER}..."
|
|
||||||
docker tag "${IMAGE_NAME}:dev" "${IMAGE_NAME}:release-current"
|
|
||||||
docker tag "${IMAGE_NAME}:dev" "${IMAGE_NAME}:${SEMVER}"
|
|
||||||
echo "Release ${SEMVER} tagged as:"
|
|
||||||
echo " - ${IMAGE_NAME}:release-current"
|
echo " - ${IMAGE_NAME}:release-current"
|
||||||
echo " - ${IMAGE_NAME}:${SEMVER}"
|
echo " - ${IMAGE_NAME}:${SEMVER}"
|
||||||
fi
|
fi
|
||||||
@@ -28,13 +28,14 @@ fi
|
|||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
COMPOSE_FILE="${SCRIPT_DIR}/docker-compose.yml"
|
COMPOSE_FILE="${SCRIPT_DIR}/docker-compose.yml"
|
||||||
|
|
||||||
# Sanitize user input
|
|
||||||
export LOCAL_UID="${USER_ID_OVERRIDE:-$(id -u)}"
|
export LOCAL_UID="${USER_ID_OVERRIDE:-$(id -u)}"
|
||||||
sanitized_input "$LOCAL_UID"
|
sanitized_input "$LOCAL_UID"
|
||||||
export LOCAL_GID="${GROUP_ID_OVERRIDE:-$(id -g)}"
|
export LOCAL_GID="${GROUP_ID_OVERRIDE:-$(id -g)}"
|
||||||
sanitized_input "$LOCAL_GID"
|
sanitized_input "$LOCAL_GID"
|
||||||
export LOCAL_USERNAME="${USERNAME_OVERRIDE:-toolbox}"
|
export LOCAL_USERNAME="${USERNAME_OVERRIDE:-toolbox}"
|
||||||
sanitized_input "$LOCAL_USERNAME"
|
sanitized_input "$LOCAL_USERNAME"
|
||||||
|
export TOOLBOX_IMAGE="${TOOLBOX_IMAGE_OVERRIDE:-tsysdevstack-toolboxstack-{{toolbox_name}}}"
|
||||||
|
sanitized_input "$TOOLBOX_IMAGE"
|
||||||
|
|
||||||
if [[ ! -f "${COMPOSE_FILE}" ]]; then
|
if [[ ! -f "${COMPOSE_FILE}" ]]; then
|
||||||
echo "Error: docker-compose.yml not found at ${COMPOSE_FILE}" >&2
|
echo "Error: docker-compose.yml not found at ${COMPOSE_FILE}" >&2
|
||||||
@@ -51,6 +52,7 @@ if [[ "${ACTION}" == "up" ]]; then
|
|||||||
mkdir -p "${HOME}/.config" "${HOME}/.local/share"
|
mkdir -p "${HOME}/.config" "${HOME}/.local/share"
|
||||||
mkdir -p "${HOME}/.cache/openai" "${HOME}/.cache/gemini" "${HOME}/.cache/qwen" "${HOME}/.cache/code" "${HOME}/.cache/opencode"
|
mkdir -p "${HOME}/.cache/openai" "${HOME}/.cache/gemini" "${HOME}/.cache/qwen" "${HOME}/.cache/code" "${HOME}/.cache/opencode"
|
||||||
mkdir -p "${HOME}/.config/openai" "${HOME}/.config/gemini" "${HOME}/.config/qwen" "${HOME}/.config/code" "${HOME}/.config/opencode"
|
mkdir -p "${HOME}/.config/openai" "${HOME}/.config/gemini" "${HOME}/.config/qwen" "${HOME}/.config/code" "${HOME}/.config/opencode"
|
||||||
|
mkdir -p "${HOME}/.config/codex" "${HOME}/.cache/codex"
|
||||||
|
|
||||||
# Set proper permissions for created directories
|
# Set proper permissions for created directories
|
||||||
chmod 700 "${HOME}/.config" "${HOME}/.local/share" "${HOME}/.cache" 2>/dev/null || true
|
chmod 700 "${HOME}/.config" "${HOME}/.local/share" "${HOME}/.cache" 2>/dev/null || true
|
||||||
@@ -59,7 +61,7 @@ fi
|
|||||||
case "${ACTION}" in
|
case "${ACTION}" in
|
||||||
up)
|
up)
|
||||||
docker compose -f "${COMPOSE_FILE}" up --build --detach "$@"
|
docker compose -f "${COMPOSE_FILE}" up --build --detach "$@"
|
||||||
echo "Container started. Use 'docker exec -it $(basename "$SCRIPT_DIR" | sed 's/toolbox-//') zsh' to access the shell."
|
echo "Container started. Use 'docker exec -it tsysdevstack-toolboxstack-{{toolbox_name}} zsh' to access the shell."
|
||||||
;;
|
;;
|
||||||
down)
|
down)
|
||||||
docker compose -f "${COMPOSE_FILE}" down "$@"
|
docker compose -f "${COMPOSE_FILE}" down "$@"
|
||||||
@@ -69,4 +71,4 @@ case "${ACTION}" in
|
|||||||
echo "Usage: $0 [up|down] [additional docker compose args]" >&2
|
echo "Usage: $0 [up|down] [additional docker compose args]" >&2
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
Reference in New Issue
Block a user