save progress
This commit is contained in:
49
devops/docker/schema-versions/Dockerfile
Normal file
49
devops/docker/schema-versions/Dockerfile
Normal file
@@ -0,0 +1,49 @@
|
||||
# devops/docker/schema-versions/Dockerfile
|
||||
# Versioned PostgreSQL container for schema evolution testing
|
||||
# Sprint: SPRINT_20260105_002_005_TEST_cross_cutting
|
||||
# Task: CCUT-008
|
||||
#
|
||||
# USAGE:
|
||||
# ======
|
||||
# Build for specific module and version:
|
||||
# docker build --build-arg MODULE=scanner --build-arg SCHEMA_VERSION=v1.2.0 \
|
||||
# -t stellaops/schema-test:scanner-v1.2.0 .
|
||||
#
|
||||
# Run for testing:
|
||||
# docker run -d -p 5432:5432 stellaops/schema-test:scanner-v1.2.0
|
||||
|
||||
ARG POSTGRES_VERSION=16
|
||||
FROM postgres:${POSTGRES_VERSION}-alpine
|
||||
|
||||
# Build arguments
|
||||
ARG MODULE=scanner
|
||||
ARG SCHEMA_VERSION=latest
|
||||
ARG SCHEMA_DATE=""
|
||||
|
||||
# Labels for identification
|
||||
LABEL org.opencontainers.image.title="StellaOps Schema Test - ${MODULE}"
|
||||
LABEL org.opencontainers.image.description="PostgreSQL with ${MODULE} schema version ${SCHEMA_VERSION}"
|
||||
LABEL org.opencontainers.image.version="${SCHEMA_VERSION}"
|
||||
LABEL org.stellaops.module="${MODULE}"
|
||||
LABEL org.stellaops.schema.version="${SCHEMA_VERSION}"
|
||||
LABEL org.stellaops.schema.date="${SCHEMA_DATE}"
|
||||
|
||||
# Environment variables
|
||||
ENV POSTGRES_USER=stellaops_test
|
||||
ENV POSTGRES_PASSWORD=test_password
|
||||
ENV POSTGRES_DB=stellaops_schema_test
|
||||
ENV STELLAOPS_MODULE=${MODULE}
|
||||
ENV STELLAOPS_SCHEMA_VERSION=${SCHEMA_VERSION}
|
||||
|
||||
# Copy initialization scripts
|
||||
COPY docker-entrypoint-initdb.d/ /docker-entrypoint-initdb.d/
|
||||
|
||||
# Copy module-specific schema
|
||||
COPY schemas/${MODULE}/ /schemas/${MODULE}/
|
||||
|
||||
# Health check
|
||||
HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=3 \
|
||||
CMD pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB} || exit 1
|
||||
|
||||
# Expose PostgreSQL port
|
||||
EXPOSE 5432
|
||||
179
devops/docker/schema-versions/build-schema-images.sh
Normal file
179
devops/docker/schema-versions/build-schema-images.sh
Normal file
@@ -0,0 +1,179 @@
|
||||
#!/bin/bash
|
||||
# build-schema-images.sh
|
||||
# Build versioned PostgreSQL images for schema evolution testing
|
||||
# Sprint: SPRINT_20260105_002_005_TEST_cross_cutting
|
||||
# Task: CCUT-008
|
||||
#
|
||||
# USAGE:
|
||||
# ======
|
||||
# Build all versions for a module:
|
||||
# ./build-schema-images.sh scanner
|
||||
#
|
||||
# Build specific version:
|
||||
# ./build-schema-images.sh scanner v1.2.0
|
||||
#
|
||||
# Build all modules:
|
||||
# ./build-schema-images.sh --all
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||
REGISTRY="${SCHEMA_REGISTRY:-ghcr.io/stellaops}"
|
||||
POSTGRES_VERSION="${POSTGRES_VERSION:-16}"
|
||||
|
||||
# Modules with schema evolution support
|
||||
MODULES=("scanner" "concelier" "evidencelocker" "authority" "sbomservice" "policy")
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 <module|--all> [version]"
|
||||
echo ""
|
||||
echo "Arguments:"
|
||||
echo " module Module name (scanner, concelier, evidencelocker, authority, sbomservice, policy)"
|
||||
echo " --all Build all modules"
|
||||
echo " version Optional specific version to build (default: all versions)"
|
||||
echo ""
|
||||
echo "Environment variables:"
|
||||
echo " SCHEMA_REGISTRY Container registry (default: ghcr.io/stellaops)"
|
||||
echo " POSTGRES_VERSION PostgreSQL version (default: 16)"
|
||||
echo " PUSH_IMAGES Set to 'true' to push images after build"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get schema versions from git tags or migration files
|
||||
get_schema_versions() {
|
||||
local module=$1
|
||||
local versions=()
|
||||
|
||||
# Check for version tags
|
||||
local tags=$(git tag -l "${module}-schema-v*" 2>/dev/null | sed "s/${module}-schema-//" | sort -V)
|
||||
|
||||
if [ -n "$tags" ]; then
|
||||
versions=($tags)
|
||||
else
|
||||
# Fall back to migration file count
|
||||
local migration_dir="$REPO_ROOT/docs/db/migrations/${module}"
|
||||
if [ -d "$migration_dir" ]; then
|
||||
local count=$(ls -1 "$migration_dir"/*.sql 2>/dev/null | wc -l)
|
||||
for i in $(seq 1 $count); do
|
||||
versions+=("v1.0.$i")
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
# Always include 'latest'
|
||||
versions+=("latest")
|
||||
|
||||
echo "${versions[@]}"
|
||||
}
|
||||
|
||||
# Copy schema files to build context
|
||||
prepare_schema_context() {
|
||||
local module=$1
|
||||
local version=$2
|
||||
local build_dir="$SCRIPT_DIR/.build/${module}/${version}"
|
||||
|
||||
mkdir -p "$build_dir/schemas/${module}"
|
||||
mkdir -p "$build_dir/docker-entrypoint-initdb.d"
|
||||
|
||||
# Copy entrypoint scripts
|
||||
cp "$SCRIPT_DIR/docker-entrypoint-initdb.d/"*.sh "$build_dir/docker-entrypoint-initdb.d/"
|
||||
|
||||
# Copy base schema
|
||||
local base_schema="$REPO_ROOT/docs/db/schemas/${module}.sql"
|
||||
if [ -f "$base_schema" ]; then
|
||||
cp "$base_schema" "$build_dir/schemas/${module}/base.sql"
|
||||
fi
|
||||
|
||||
# Copy migrations directory
|
||||
local migrations_dir="$REPO_ROOT/docs/db/migrations/${module}"
|
||||
if [ -d "$migrations_dir" ]; then
|
||||
mkdir -p "$build_dir/schemas/${module}/migrations"
|
||||
cp "$migrations_dir"/*.sql "$build_dir/schemas/${module}/migrations/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo "$build_dir"
|
||||
}
|
||||
|
||||
# Build image for module and version
|
||||
build_image() {
|
||||
local module=$1
|
||||
local version=$2
|
||||
|
||||
echo "Building ${module} schema version ${version}..."
|
||||
|
||||
local build_dir=$(prepare_schema_context "$module" "$version")
|
||||
local image_tag="${REGISTRY}/schema-test:${module}-${version}"
|
||||
local schema_date=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
||||
|
||||
# Copy Dockerfile to build context
|
||||
cp "$SCRIPT_DIR/Dockerfile" "$build_dir/"
|
||||
|
||||
# Build the image
|
||||
docker build \
|
||||
--build-arg MODULE="$module" \
|
||||
--build-arg SCHEMA_VERSION="$version" \
|
||||
--build-arg SCHEMA_DATE="$schema_date" \
|
||||
--build-arg POSTGRES_VERSION="$POSTGRES_VERSION" \
|
||||
-t "$image_tag" \
|
||||
"$build_dir"
|
||||
|
||||
echo "Built: $image_tag"
|
||||
|
||||
# Push if requested
|
||||
if [ "$PUSH_IMAGES" = "true" ]; then
|
||||
echo "Pushing: $image_tag"
|
||||
docker push "$image_tag"
|
||||
fi
|
||||
|
||||
# Cleanup build directory
|
||||
rm -rf "$build_dir"
|
||||
}
|
||||
|
||||
# Build all versions for a module
|
||||
build_module() {
|
||||
local module=$1
|
||||
local target_version=$2
|
||||
|
||||
echo "========================================"
|
||||
echo "Building schema images for: $module"
|
||||
echo "========================================"
|
||||
|
||||
if [ -n "$target_version" ]; then
|
||||
build_image "$module" "$target_version"
|
||||
else
|
||||
local versions=$(get_schema_versions "$module")
|
||||
for version in $versions; do
|
||||
build_image "$module" "$version"
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
# Main
|
||||
if [ $# -lt 1 ]; then
|
||||
usage
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
--all)
|
||||
for module in "${MODULES[@]}"; do
|
||||
build_module "$module" "$2"
|
||||
done
|
||||
;;
|
||||
--help|-h)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
if [[ " ${MODULES[*]} " =~ " $1 " ]]; then
|
||||
build_module "$1" "$2"
|
||||
else
|
||||
echo "Error: Unknown module '$1'"
|
||||
echo "Valid modules: ${MODULES[*]}"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "Build complete!"
|
||||
echo "To push images, run with PUSH_IMAGES=true"
|
||||
@@ -0,0 +1,70 @@
|
||||
#!/bin/bash
|
||||
# 00-init-schema.sh
|
||||
# Initialize PostgreSQL with module schema for testing
|
||||
# Sprint: SPRINT_20260105_002_005_TEST_cross_cutting
|
||||
# Task: CCUT-008
|
||||
|
||||
set -e
|
||||
|
||||
echo "Initializing schema for module: ${STELLAOPS_MODULE}"
|
||||
echo "Schema version: ${STELLAOPS_SCHEMA_VERSION}"
|
||||
|
||||
# Create extensions
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
||||
CREATE EXTENSION IF NOT EXISTS "btree_gist";
|
||||
EOSQL
|
||||
|
||||
# Apply base schema if exists
|
||||
BASE_SCHEMA="/schemas/${STELLAOPS_MODULE}/base.sql"
|
||||
if [ -f "$BASE_SCHEMA" ]; then
|
||||
echo "Applying base schema: $BASE_SCHEMA"
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -f "$BASE_SCHEMA"
|
||||
fi
|
||||
|
||||
# Apply versioned schema if exists
|
||||
VERSION_SCHEMA="/schemas/${STELLAOPS_MODULE}/${STELLAOPS_SCHEMA_VERSION}.sql"
|
||||
if [ -f "$VERSION_SCHEMA" ]; then
|
||||
echo "Applying version schema: $VERSION_SCHEMA"
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -f "$VERSION_SCHEMA"
|
||||
fi
|
||||
|
||||
# Apply all migrations up to version
|
||||
MIGRATIONS_DIR="/schemas/${STELLAOPS_MODULE}/migrations"
|
||||
if [ -d "$MIGRATIONS_DIR" ]; then
|
||||
echo "Applying migrations from: $MIGRATIONS_DIR"
|
||||
|
||||
# Get version number for comparison
|
||||
VERSION_NUM=$(echo "$STELLAOPS_SCHEMA_VERSION" | sed 's/v//' | sed 's/\.//g')
|
||||
|
||||
for migration in $(ls -1 "$MIGRATIONS_DIR"/*.sql 2>/dev/null | sort -V); do
|
||||
MIGRATION_VERSION=$(basename "$migration" .sql | sed 's/[^0-9]//g')
|
||||
|
||||
if [ -n "$VERSION_NUM" ] && [ "$MIGRATION_VERSION" -gt "$VERSION_NUM" ]; then
|
||||
echo "Skipping migration $migration (version $MIGRATION_VERSION > $VERSION_NUM)"
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "Applying migration: $migration"
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" -f "$migration"
|
||||
done
|
||||
fi
|
||||
|
||||
# Record schema version in metadata table
|
||||
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||
CREATE TABLE IF NOT EXISTS _schema_metadata (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
INSERT INTO _schema_metadata (key, value)
|
||||
VALUES
|
||||
('module', '${STELLAOPS_MODULE}'),
|
||||
('schema_version', '${STELLAOPS_SCHEMA_VERSION}'),
|
||||
('initialized_at', NOW()::TEXT)
|
||||
ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value, updated_at = NOW();
|
||||
EOSQL
|
||||
|
||||
echo "Schema initialization complete for ${STELLAOPS_MODULE} version ${STELLAOPS_SCHEMA_VERSION}"
|
||||
Reference in New Issue
Block a user