- Renamed DocStack to dockstack - Transformed toolbox-template into toolbox-qadocker with new functionality - Removed NewToolbox.sh script - Updated PROMPT and configuration files across all toolboxes - Consolidated audit and testing scripts - Updated QWEN.md to reflect new filesystem structure as authoritative source - Merged PROMPT content into QWEN.md as requested Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com> The filesystem structure has been intentionally restructured and is now the authoritative source of truth for the project organization.
175 lines
5.8 KiB
Bash
Executable File
175 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
# Security: Validate input parameters to prevent command injection
|
|
sanitized_input() {
|
|
local input="$1"
|
|
# Check for potentially dangerous characters/commands
|
|
case "$input" in
|
|
*[\;\|\&\`\$]*)
|
|
echo "Error: Invalid input detected: $input" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Validate dependencies
|
|
if ! command -v docker &> /dev/null; then
|
|
echo "Error: docker is required but not installed." >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! docker buildx version &> /dev/null; then
|
|
echo "Error: docker buildx is required but not available." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# 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)")}"
|
|
sanitized_input "$TOOLBOX_NAME"
|
|
# Convert to lowercase and replace any uppercase letters to ensure valid Docker image name
|
|
IMAGE_NAME_RAW="tsysdevstack-toolboxstack-${TOOLBOX_NAME#toolbox-}"
|
|
IMAGE_NAME=$(echo "$IMAGE_NAME_RAW" | tr '[:upper:]' '[:lower:]')
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
# Sanitize user input
|
|
USER_ID="${USER_ID_OVERRIDE:-$(id -u)}"
|
|
sanitized_input "$USER_ID"
|
|
GROUP_ID="${GROUP_ID_OVERRIDE:-$(id -g)}"
|
|
sanitized_input "$GROUP_ID"
|
|
USERNAME="${USERNAME_OVERRIDE:-toolbox}"
|
|
sanitized_input "$USERNAME"
|
|
TEA_VERSION="${TEA_VERSION_OVERRIDE:-0.11.1}"
|
|
sanitized_input "$TEA_VERSION"
|
|
BUILDER_NAME="${BUILDER_NAME:-tsysdevstack-toolboxstack-builder}"
|
|
sanitized_input "$BUILDER_NAME"
|
|
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 "Primary tag: ${TAG}"
|
|
|
|
# Ensure builder exists
|
|
if ! docker buildx inspect "${BUILDER_NAME}" >/dev/null 2>&1; then
|
|
echo "Creating builder: ${BUILDER_NAME}"
|
|
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}"
|
|
if ! docker buildx use "${BUILDER_NAME}" >/dev/null; then
|
|
echo "Error: Failed to use Docker buildx builder." >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# 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..."
|
|
BUILD_OUTPUT=$(mktemp)
|
|
trap 'rm -f "$BUILD_OUTPUT"' EXIT
|
|
|
|
# Build the image
|
|
if ! docker buildx build \
|
|
--builder "${BUILDER_NAME}" \
|
|
--load \
|
|
--progress=plain \
|
|
--build-arg USER_ID="${USER_ID}" \
|
|
--build-arg GROUP_ID="${GROUP_ID}" \
|
|
--build-arg USERNAME="${USERNAME}" \
|
|
--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}" \
|
|
"${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 for Docker auditing are available
|
|
echo "Verifying Docker auditing tools..."
|
|
CRITICAL_TOOLS=("git" "curl" "wget" "docker" "hadolint" "dive")
|
|
for tool in "${CRITICAL_TOOLS[@]}"; do
|
|
if ! docker run --rm "${IMAGE_NAME}:${TAG}" which "$tool" >/dev/null 2>&1; then
|
|
echo "Error: Critical Docker auditing tool '$tool' not found in PATH." >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
# Verify additional aqua tools for QA are available
|
|
echo "Verifying QA aqua tools..."
|
|
AQUA_TOOLS=("lazygit" "direnv" "delta" "zoxide" "yq" "xh" "curlie" "shellcheck" "trivy" "grype" "docker-bench-security")
|
|
for tool in "${AQUA_TOOLS[@]}"; do
|
|
if ! docker run --rm "${IMAGE_NAME}:${TAG}" which "$tool" >/dev/null 2>&1; then
|
|
echo "Error: QA aqua 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
|
|
if command -v trivy &> /dev/null; then
|
|
echo "Running security scan with Trivy..."
|
|
trivy image --exit-code 0 --severity HIGH,CRITICAL "${IMAGE_NAME}:${TAG}"
|
|
else
|
|
echo "Trivy not found. Install Trivy to perform security scanning."
|
|
fi
|
|
|
|
echo "Build process completed successfully with all verifications." |