Files
git.stella-ops.org/ops/devops/console/build-console-image.sh
StellaOps Bot e2e404e705
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
console-runner-image / build-runner-image (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
up
2025-12-14 16:24:16 +02:00

87 lines
3.1 KiB
Bash

#!/usr/bin/env bash
# Build console container image with SBOM and optional attestations
# Usage: ./build-console-image.sh [tag] [registry]
# Example: ./build-console-image.sh 2025.10.0-edge ghcr.io/stellaops
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
TAG="${1:-$(date +%Y%m%dT%H%M%S)}"
REGISTRY="${2:-registry.stella-ops.org/stellaops}"
IMAGE_NAME="console"
FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}:${TAG}"
# Freeze timestamps for reproducibility
export SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH:-1704067200}
echo "==> Building console image: ${FULL_IMAGE}"
# Build using the existing Dockerfile.console
docker build \
--file "${REPO_ROOT}/ops/devops/docker/Dockerfile.console" \
--build-arg APP_DIR=src/Web/StellaOps.Web \
--build-arg APP_PORT=8080 \
--tag "${FULL_IMAGE}" \
--label "org.opencontainers.image.created=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--label "org.opencontainers.image.revision=$(git -C "${REPO_ROOT}" rev-parse HEAD 2>/dev/null || echo 'unknown')" \
--label "org.opencontainers.image.source=https://github.com/stellaops/stellaops" \
--label "org.opencontainers.image.title=StellaOps Console" \
--label "org.opencontainers.image.description=StellaOps Angular Console (non-root nginx)" \
"${REPO_ROOT}"
# Get digest
DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "${FULL_IMAGE}" 2>/dev/null || echo "${FULL_IMAGE}")
echo "==> Image built: ${FULL_IMAGE}"
echo "==> Digest: ${DIGEST}"
# Output metadata for CI
mkdir -p "${SCRIPT_DIR}/../artifacts/console"
cat > "${SCRIPT_DIR}/../artifacts/console/build-metadata.json" <<EOF
{
"image": "${FULL_IMAGE}",
"digest": "${DIGEST}",
"tag": "${TAG}",
"registry": "${REGISTRY}",
"buildTime": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"gitCommit": "$(git -C "${REPO_ROOT}" rev-parse HEAD 2>/dev/null || echo 'unknown')",
"sourceDateEpoch": "${SOURCE_DATE_EPOCH}"
}
EOF
echo "==> Build metadata written to ops/devops/artifacts/console/build-metadata.json"
# Generate SBOM if syft is available
if command -v syft &>/dev/null; then
echo "==> Generating SBOM..."
syft "${FULL_IMAGE}" -o spdx-json > "${SCRIPT_DIR}/../artifacts/console/console.spdx.json"
syft "${FULL_IMAGE}" -o cyclonedx-json > "${SCRIPT_DIR}/../artifacts/console/console.cdx.json"
echo "==> SBOMs written to ops/devops/artifacts/console/"
else
echo "==> Skipping SBOM generation (syft not found)"
fi
# Sign and attest if cosign is available and key is set
if command -v cosign &>/dev/null; then
if [[ -n "${COSIGN_KEY:-}" ]]; then
echo "==> Signing image with cosign..."
cosign sign --key "${COSIGN_KEY}" "${FULL_IMAGE}"
if [[ -f "${SCRIPT_DIR}/../artifacts/console/console.spdx.json" ]]; then
echo "==> Attesting SBOM..."
cosign attest --predicate "${SCRIPT_DIR}/../artifacts/console/console.spdx.json" \
--type spdx --key "${COSIGN_KEY}" "${FULL_IMAGE}"
fi
echo "==> Image signed and attested"
else
echo "==> Skipping signing (COSIGN_KEY not set)"
fi
else
echo "==> Skipping signing (cosign not found)"
fi
echo "==> Console image build complete"
echo " Image: ${FULL_IMAGE}"