Skip to content

Commit 7d20c66

Browse files
author
Test
committed
feat: Introduce containerized validation system for GIV CLI
- Added `validate-installs-container.sh` to handle package validation inside a Docker container. - Refactored `validate-installs.sh` to orchestrate the containerized validation process. - Updated documentation to reflect the new containerized architecture and usage instructions. - Enhanced validation reporting with JSON output options. - Streamlined package installation tests for deb, pypi, npm, homebrew, and snap. - Improved error handling and reporting for validation failures. - Removed legacy validation logic from `validate-installs.sh` to simplify the script.
1 parent 38632ed commit 7d20c66

9 files changed

+1644
-554
lines changed

build/build-packages-container.sh

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
# Container-internal build script
5+
# This script runs inside the giv-packages container and performs the actual build
6+
7+
VERSION="${1:-}"
8+
if [[ -z "$VERSION" ]]; then
9+
echo "ERROR: Version not provided" >&2
10+
exit 1
11+
fi
12+
13+
echo "Building GIV CLI version $VERSION inside container..."
14+
15+
# Set up build environment
16+
mkdir -p .tmp
17+
BUILD_TEMP=$(mktemp -d -p .tmp)
18+
DIST_DIR="./dist/${VERSION}"
19+
20+
echo "Build temp directory: $BUILD_TEMP"
21+
echo "Distribution directory: $DIST_DIR"
22+
23+
# Clean and create dist directory
24+
rm -rf "${DIST_DIR}"
25+
mkdir -p "${DIST_DIR}"
26+
27+
# All necessary tools should be pre-installed in the container
28+
echo "Verifying build tools..."
29+
30+
# Check for required tools
31+
MISSING_TOOLS=()
32+
33+
if ! command -v fpm >/dev/null 2>&1; then
34+
MISSING_TOOLS+=("fpm")
35+
fi
36+
37+
if ! command -v npm >/dev/null 2>&1; then
38+
MISSING_TOOLS+=("npm")
39+
fi
40+
41+
if ! command -v python3 >/dev/null 2>&1; then
42+
MISSING_TOOLS+=("python3")
43+
fi
44+
45+
if ! command -v gem >/dev/null 2>&1; then
46+
MISSING_TOOLS+=("gem")
47+
fi
48+
49+
if [[ ${#MISSING_TOOLS[@]} -gt 0 ]]; then
50+
echo "ERROR: Missing required build tools: ${MISSING_TOOLS[*]}" >&2
51+
echo "The container may not have been built correctly." >&2
52+
exit 1
53+
fi
54+
55+
echo "✓ All required build tools are available"
56+
57+
# Prepare package files
58+
mkdir -p "${BUILD_TEMP}/package"
59+
cp -r src templates docs "${BUILD_TEMP}/package/"
60+
echo "Copied src, templates, docs to ${BUILD_TEMP}/package/"
61+
62+
cp README.md "${BUILD_TEMP}/package/docs"
63+
mv "${BUILD_TEMP}/package/src/giv.sh" "${BUILD_TEMP}/package/src/giv"
64+
65+
# Collect file lists for setup.py
66+
SH_FILES=$(find "${BUILD_TEMP}/package/src" -type f -name '*.sh' -print0 | xargs -0 -I{} bash -c 'printf "src/%s " "$(basename "{}")"')
67+
TEMPLATE_FILES=$(find "${BUILD_TEMP}/package/templates" -type f -print0 | xargs -0 -I{} bash -c 'printf "templates/%s " "$(basename "{}")"')
68+
DOCS_FILES=$(find "${BUILD_TEMP}/package/docs" -type f -print0 | xargs -0 -I{} bash -c 'printf "docs/%s " "$(basename "{}")"')
69+
70+
export SH_FILES TEMPLATE_FILES DOCS_FILES
71+
72+
echo "Building packages..."
73+
74+
# Build each package type
75+
echo "Building npm package..."
76+
./build/npm/build.sh "${VERSION}" "${BUILD_TEMP}"
77+
78+
echo "Building PyPI package..."
79+
./build/pypi/build.sh "${VERSION}" "${BUILD_TEMP}"
80+
81+
echo "Building Homebrew formula..."
82+
./build/homebrew/build.sh "${VERSION}" "${BUILD_TEMP}"
83+
84+
echo "Building Scoop manifest..."
85+
./build/scoop/build.sh "${VERSION}" "${BUILD_TEMP}"
86+
87+
echo "Building Linux packages (deb/rpm)..."
88+
./build/linux/build.sh "${VERSION}" "${BUILD_TEMP}" "deb"
89+
./build/linux/build.sh "${VERSION}" "${BUILD_TEMP}" "rpm"
90+
91+
echo "Building Snap package..."
92+
./build/snap/build.sh "${VERSION}" "${BUILD_TEMP}"
93+
94+
echo "Building Flatpak package..."
95+
./build/flatpak/build.sh "${VERSION}" "${BUILD_TEMP}"
96+
97+
echo "Building Docker image..."
98+
./build/docker/build.sh "${VERSION}" "${BUILD_TEMP}"
99+
100+
# Clean up temp directory
101+
rm -rf "${BUILD_TEMP}"
102+
103+
echo "Build completed successfully!"
104+
echo "Artifacts are available in: ${DIST_DIR}"
105+
106+
# List built artifacts
107+
echo
108+
echo "Built artifacts:"
109+
find "${DIST_DIR}" -type f -exec basename {} \; | sort

build/build-packages.sh

Lines changed: 89 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,106 @@
1-
#! /bin/bash
1+
#!/bin/bash
2+
set -euo pipefail
23

4+
# Build all packages using containerized environment
5+
# This script orchestrates the build process inside the giv-packages container
36

4-
mkdir -p .tmp
5-
BUILD_TEMP=$(mktemp -d -p .tmp)
6-
VERSION=$(sed -n 's/^__VERSION="\([^"]*\)"/\1/p' src/giv.sh)
7-
DIST_DIR="./dist/${VERSION}"
7+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
89

9-
printf "Building GIV CLI version %s...\n" "${VERSION}"
10-
rm -rf "${DIST_DIR}"
11-
mkdir -p "${DIST_DIR}"
10+
usage() {
11+
cat << EOF
12+
Usage: $0 [OPTIONS]
1213
13-
FPM_INSTALLED="false"
14-
# Check for fpm, try to install if missing
15-
if ! command -v fpm >/dev/null 2>&1; then
16-
echo "Trying: gem install dotenv fpm"
17-
if gem install dotenv fpm; then
18-
echo "fpm installed via gem."
19-
fi
20-
fi
14+
Build all giv packages using containerized build environment.
2115
22-
if ! command -v fpm >/dev/null 2>&1; then
23-
cat >&2 <<EOF
24-
Error: fpm is not installed and automatic installation failed.
16+
OPTIONS:
17+
-v, --version VERSION Override version detection
18+
-f, --force-build Force rebuild of container
19+
-c, --clean Clean dist directory before build
20+
-h, --help Show this help message
2521
26-
Manual installation instructions:
27-
- See https://fpm.readthedocs.io/en/latest/installation.html
28-
- On macOS: gem install fpm
29-
- On Linux (Debian/Ubuntu): sudo apt-get install ruby ruby-dev build-essential && sudo gem install --no-document fpm
30-
- On Linux (Fedora): sudo dnf install ruby ruby-devel make gcc && sudo gem install --no-document fpm
31-
- Or see the docs for more options.
22+
EXAMPLES:
23+
$0 # Build all packages for detected version
24+
$0 -v 1.2.3 # Build packages for specific version
25+
$0 -f # Force rebuild container and packages
26+
$0 -c # Clean dist directory first
3227
EOF
33-
FPM_INSTALLED="false"
28+
}
29+
30+
# Parse arguments
31+
VERSION_OVERRIDE=""
32+
FORCE_BUILD=false
33+
CLEAN_DIST=false
34+
35+
while [[ $# -gt 0 ]]; do
36+
case $1 in
37+
-v|--version)
38+
VERSION_OVERRIDE="$2"
39+
shift 2
40+
;;
41+
-f|--force-build)
42+
FORCE_BUILD=true
43+
shift
44+
;;
45+
-c|--clean)
46+
CLEAN_DIST=true
47+
shift
48+
;;
49+
-h|--help)
50+
usage
51+
exit 0
52+
;;
53+
*)
54+
echo "ERROR: Unknown option: $1" >&2
55+
usage
56+
exit 1
57+
;;
58+
esac
59+
done
60+
61+
# Ensure container is built
62+
echo "Ensuring giv-packages container is available..."
63+
if [[ "$FORCE_BUILD" == "true" ]]; then
64+
"$SCRIPT_DIR/container-build.sh" -f
3465
else
35-
FPM_INSTALLED="true"
66+
if ! docker image inspect giv-packages:latest >/dev/null 2>&1; then
67+
echo "Container not found, building..."
68+
"$SCRIPT_DIR/container-build.sh"
69+
else
70+
echo "✓ Container already exists"
71+
fi
3672
fi
3773

38-
mkdir -p "${BUILD_TEMP}/package"
39-
cp -r src templates docs "${BUILD_TEMP}/package/"
40-
printf 'Copied src templates docs to %s\n' "${BUILD_TEMP}/package/"
41-
cp README.md "${BUILD_TEMP}/package/docs"
42-
mv "${BUILD_TEMP}/package/src/giv.sh" "${BUILD_TEMP}/package/src/giv"
43-
printf "Using build temp directory: %s\n" "${BUILD_TEMP}"
74+
# Detect version if not overridden
75+
if [[ -n "$VERSION_OVERRIDE" ]]; then
76+
VERSION="$VERSION_OVERRIDE"
77+
else
78+
VERSION=$(sed -n 's/__VERSION="\([^"]*\)"/\1/p' src/lib/system.sh)
79+
fi
4480

45-
# Collect file lists for setup.py
46-
SH_FILES=$(find "${BUILD_TEMP}/package/src" -type f -name '*.sh' -print0 | xargs -0 -I{} bash -c 'printf "src/%s " "$(basename "{}")"')
47-
TEMPLATE_FILES=$(find "${BUILD_TEMP}/package/templates" -type f -print0 | xargs -0 -I{} bash -c 'printf "templates/%s " "$(basename "{}")"')
48-
DOCS_FILES=$(find "${BUILD_TEMP}/package/docs" -type f -print0 | xargs -0 -I{} bash -c 'printf "docs/%s " "$(basename "{}")"')
81+
if [[ -z "$VERSION" ]]; then
82+
echo "ERROR: Could not detect version from src/lib/system.sh" >&2
83+
exit 1
84+
fi
4985

86+
DIST_DIR="./dist/${VERSION}"
5087

51-
export SH_FILES TEMPLATE_FILES DOCS_FILES
88+
echo "Building GIV CLI version $VERSION using containerized environment..."
5289

53-
./build/npm/build.sh "${VERSION}" "${BUILD_TEMP}"
54-
./build/pypi/build.sh "${VERSION}" "${BUILD_TEMP}"
55-
./build/homebrew/build.sh "${VERSION}" "${BUILD_TEMP}"
56-
./build/scoop/build.sh "${VERSION}" "${BUILD_TEMP}"
57-
if [ "${FPM_INSTALLED}" = "true" ]; then
58-
./build/linux/build.sh "${VERSION}" "${BUILD_TEMP}" "deb"
59-
./build/linux/build.sh "${VERSION}" "${BUILD_TEMP}" "rpm"
90+
# Clean dist directory if requested
91+
if [[ "$CLEAN_DIST" == "true" ]]; then
92+
echo "Cleaning dist directory..."
93+
rm -rf "$DIST_DIR"
6094
fi
61-
./build/snap/build.sh "${VERSION}" "${BUILD_TEMP}"
62-
./build/flatpak/build.sh "${VERSION}" "${BUILD_TEMP}"
63-
./build/docker/build.sh "${VERSION}" "${BUILD_TEMP}"
6495

65-
#rm -rf "${BUILD_TEMP}"
66-
printf "Build completed. Files are in %s\n" "${DIST_DIR}"
96+
mkdir -p "$DIST_DIR"
6797

68-
rm -rf "${BUILD_TEMP}"
98+
# Run the actual build inside the container
99+
echo "Starting containerized build process..."
100+
if "$SCRIPT_DIR/container-run.sh" /workspace/build/build-packages-container.sh "$VERSION"; then
101+
echo "✓ Containerized build completed successfully"
102+
echo "Build artifacts are available in: $DIST_DIR"
103+
else
104+
echo "ERROR: Containerized build failed" >&2
105+
exit 1
106+
fi

build/container-build.sh

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
# Container build helper script
5+
# Builds the giv-packages container with all necessary tools
6+
7+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
9+
10+
IMAGE_NAME="giv-packages"
11+
IMAGE_TAG="latest"
12+
DOCKERFILE="$SCRIPT_DIR/Dockerfile.packages"
13+
14+
usage() {
15+
cat << EOF
16+
Usage: $0 [OPTIONS]
17+
18+
Build the giv-packages container with all necessary build tools.
19+
20+
OPTIONS:
21+
-t, --tag TAG Container tag (default: latest)
22+
-n, --name NAME Container image name (default: giv-packages)
23+
-f, --force Force rebuild (no cache)
24+
-q, --quiet Quiet build output
25+
-h, --help Show this help message
26+
27+
EXAMPLES:
28+
$0 # Build with default settings
29+
$0 -t v1.0.0 # Build with specific tag
30+
$0 -f # Force rebuild without cache
31+
$0 -n my-giv-packages # Use custom image name
32+
EOF
33+
}
34+
35+
# Parse arguments
36+
FORCE_BUILD=false
37+
QUIET=false
38+
39+
while [[ $# -gt 0 ]]; do
40+
case $1 in
41+
-t|--tag)
42+
IMAGE_TAG="$2"
43+
shift 2
44+
;;
45+
-n|--name)
46+
IMAGE_NAME="$2"
47+
shift 2
48+
;;
49+
-f|--force)
50+
FORCE_BUILD=true
51+
shift
52+
;;
53+
-q|--quiet)
54+
QUIET=true
55+
shift
56+
;;
57+
-h|--help)
58+
usage
59+
exit 0
60+
;;
61+
*)
62+
echo "ERROR: Unknown option: $1" >&2
63+
usage
64+
exit 1
65+
;;
66+
esac
67+
done
68+
69+
FULL_IMAGE_NAME="$IMAGE_NAME:$IMAGE_TAG"
70+
71+
echo "Building container image: $FULL_IMAGE_NAME"
72+
echo "Dockerfile: $DOCKERFILE"
73+
echo "Build context: $PROJECT_ROOT"
74+
75+
# Check if Dockerfile exists
76+
if [[ ! -f "$DOCKERFILE" ]]; then
77+
echo "ERROR: Dockerfile not found: $DOCKERFILE" >&2
78+
exit 1
79+
fi
80+
81+
# Build arguments
82+
BUILD_ARGS=()
83+
BUILD_ARGS+=("-t" "$FULL_IMAGE_NAME")
84+
BUILD_ARGS+=("-f" "$DOCKERFILE")
85+
86+
if [[ "$FORCE_BUILD" == "true" ]]; then
87+
BUILD_ARGS+=("--no-cache")
88+
fi
89+
90+
if [[ "$QUIET" == "true" ]]; then
91+
BUILD_ARGS+=("--quiet")
92+
else
93+
BUILD_ARGS+=("--progress=plain")
94+
fi
95+
96+
# Add the build context (project root)
97+
BUILD_ARGS+=("$PROJECT_ROOT")
98+
99+
echo "Running: docker build ${BUILD_ARGS[*]}"
100+
101+
# Build the container
102+
if docker build "${BUILD_ARGS[@]}"; then
103+
echo "✓ Container build successful: $FULL_IMAGE_NAME"
104+
105+
# Show image info
106+
echo
107+
echo "Image details:"
108+
docker images "$IMAGE_NAME" --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedAt}}"
109+
110+
echo
111+
echo "Container is ready for use with:"
112+
echo " ./build/container-run.sh [COMMAND]"
113+
else
114+
echo "ERROR: Container build failed" >&2
115+
exit 1
116+
fi

0 commit comments

Comments
 (0)