CD/CD consolidation

This commit is contained in:
StellaOps Bot
2025-12-26 17:32:23 +02:00
parent a866eb6277
commit c786faae84
638 changed files with 3821 additions and 181 deletions

View File

@@ -0,0 +1,43 @@
#!/usr/bin/env bash
set -euo pipefail
# DEVOPS-CONTAINERS-46-001: build air-gap bundle from existing buildx OCI archive
if [[ $# -lt 1 ]]; then
echo "Usage: $0 <image-tag> [bundle-dir]" >&2
exit 64
fi
IMAGE_TAG=$1
BUNDLE_DIR=${2:-"out/bundles/$(echo "$IMAGE_TAG" | tr '/:' '__')"}
SRC_DIR="out/buildx/$(echo "$IMAGE_TAG" | tr '/:' '__')"
OCI_ARCHIVE="${SRC_DIR}/image.oci"
if [[ ! -f "$OCI_ARCHIVE" ]]; then
echo "[airgap] OCI archive not found at $OCI_ARCHIVE. Run build-multiarch first." >&2
exit 66
fi
mkdir -p "$BUNDLE_DIR"
SBOM_FILE=""
if [[ -f "${SRC_DIR}/sbom.syft.json" ]]; then
SBOM_FILE="${SRC_DIR}/sbom.syft.json"
fi
cat > "${BUNDLE_DIR}/bundle-manifest.json" <<EOF
{
"image": "${IMAGE_TAG}",
"oci_archive": "image.oci",
"sbom": "$( [[ -n "$SBOM_FILE" ]] && echo sbom.syft.json || echo null )",
"created_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
}
EOF
cp "$OCI_ARCHIVE" "${BUNDLE_DIR}/image.oci"
[[ -n "$SBOM_FILE" ]] && cp "$SBOM_FILE" "${BUNDLE_DIR}/sbom.syft.json"
[[ -f "${SRC_DIR}/image.sha256" ]] && cp "${SRC_DIR}/image.sha256" "${BUNDLE_DIR}/image.sha256"
[[ -f "${SRC_DIR}/image.sig" ]] && cp "${SRC_DIR}/image.sig" "${BUNDLE_DIR}/image.sig"
tar -C "$BUNDLE_DIR" -czf "${BUNDLE_DIR}.tgz" .
echo "[airgap] bundle created at ${BUNDLE_DIR}.tgz"

View File

@@ -0,0 +1,131 @@
#!/usr/bin/env bash
set -euo pipefail
# DEVOPS-CLI-41-001: Build multi-platform CLI binaries with SBOM and checksums.
# Updated: SPRINT_5100_0001_0001 - CLI Consolidation: includes Aoc and Symbols plugins
RIDS="${RIDS:-linux-x64,win-x64,osx-arm64}"
CONFIG="${CONFIG:-Release}"
PROJECT="src/Cli/StellaOps.Cli/StellaOps.Cli.csproj"
OUT_ROOT="out/cli"
SBOM_TOOL="${SBOM_TOOL:-syft}" # syft|none
SIGN="${SIGN:-false}"
COSIGN_KEY="${COSIGN_KEY:-}"
# CLI Plugins to include in the distribution
# SPRINT_5100_0001_0001: CLI Consolidation - stella aoc and stella symbols
PLUGIN_PROJECTS=(
"src/Cli/__Libraries/StellaOps.Cli.Plugins.Aoc/StellaOps.Cli.Plugins.Aoc.csproj"
"src/Cli/__Libraries/StellaOps.Cli.Plugins.Symbols/StellaOps.Cli.Plugins.Symbols.csproj"
)
PLUGIN_MANIFESTS=(
"src/Cli/plugins/cli/StellaOps.Cli.Plugins.Aoc/stellaops.cli.plugins.aoc.manifest.json"
"src/Cli/plugins/cli/StellaOps.Cli.Plugins.Symbols/stellaops.cli.plugins.symbols.manifest.json"
)
IFS=',' read -ra TARGETS <<< "$RIDS"
mkdir -p "$OUT_ROOT"
if ! command -v dotnet >/dev/null 2>&1; then
echo "[cli-build] dotnet CLI not found" >&2
exit 69
fi
generate_sbom() {
local dir="$1"
local sbom="$2"
if [[ "$SBOM_TOOL" == "syft" ]] && command -v syft >/dev/null 2>&1; then
syft "dir:${dir}" -o json > "$sbom"
fi
}
sign_file() {
local file="$1"
if [[ "$SIGN" == "true" && -n "$COSIGN_KEY" && -x "$(command -v cosign || true)" ]]; then
COSIGN_EXPERIMENTAL=1 cosign sign-blob --key "$COSIGN_KEY" --output-signature "${file}.sig" "$file"
fi
}
for rid in "${TARGETS[@]}"; do
echo "[cli-build] publishing for $rid"
out_dir="${OUT_ROOT}/${rid}"
publish_dir="${out_dir}/publish"
plugins_dir="${publish_dir}/plugins/cli"
mkdir -p "$publish_dir"
mkdir -p "$plugins_dir"
# Build main CLI
dotnet publish "$PROJECT" -c "$CONFIG" -r "$rid" \
-o "$publish_dir" \
--self-contained true \
-p:PublishSingleFile=true \
-p:PublishTrimmed=false \
-p:DebugType=None \
>/dev/null
# Build and copy plugins
# SPRINT_5100_0001_0001: CLI Consolidation
for i in "${!PLUGIN_PROJECTS[@]}"; do
plugin_project="${PLUGIN_PROJECTS[$i]}"
manifest_path="${PLUGIN_MANIFESTS[$i]}"
if [[ ! -f "$plugin_project" ]]; then
echo "[cli-build] WARNING: Plugin project not found: $plugin_project"
continue
fi
# Get plugin name from project path
plugin_name=$(basename "$(dirname "$plugin_project")")
plugin_out="${plugins_dir}/${plugin_name}"
mkdir -p "$plugin_out"
echo "[cli-build] building plugin: $plugin_name"
dotnet publish "$plugin_project" -c "$CONFIG" -r "$rid" \
-o "$plugin_out" \
--self-contained false \
-p:DebugType=None \
>/dev/null 2>&1 || echo "[cli-build] WARNING: Plugin build failed for $plugin_name (may have pre-existing errors)"
# Copy manifest file
if [[ -f "$manifest_path" ]]; then
cp "$manifest_path" "$plugin_out/"
else
echo "[cli-build] WARNING: Manifest not found: $manifest_path"
fi
done
# Package
archive_ext="tar.gz"
archive_cmd=(tar -C "$publish_dir" -czf)
if [[ "$rid" == win-* ]]; then
archive_ext="zip"
archive_cmd=(zip -jr)
fi
archive_name="stella-cli-${rid}.${archive_ext}"
archive_path="${out_dir}/${archive_name}"
"${archive_cmd[@]}" "$archive_path" "$publish_dir"
sha256sum "$archive_path" > "${archive_path}.sha256"
sign_file "$archive_path"
# SBOM
generate_sbom "$publish_dir" "${archive_path}.sbom.json"
done
# Build manifest
manifest="${OUT_ROOT}/manifest.json"
plugin_list=$(printf '"%s",' "${PLUGIN_PROJECTS[@]}" | sed 's/,.*//' | sed 's/.*\///' | sed 's/\.csproj//')
cat > "$manifest" <<EOF
{
"generated_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
"config": "$CONFIG",
"rids": [$(printf '"%s",' "${TARGETS[@]}" | sed 's/,$//')],
"plugins": ["stellaops.cli.plugins.aoc", "stellaops.cli.plugins.symbols"],
"artifacts_root": "$OUT_ROOT",
"notes": "CLI Consolidation (SPRINT_5100_0001_0001) - includes aoc and symbols plugins"
}
EOF
echo "[cli-build] artifacts in $OUT_ROOT"

View File

@@ -0,0 +1,93 @@
#!/usr/bin/env bash
set -euo pipefail
# Multi-arch buildx helper for DEVOPS-CONTAINERS-44-001
# Requirements: docker CLI with buildx, optional syft (for SBOM) and cosign (for signing).
usage() {
echo "Usage: $0 <image-tag> <context-dir> [--platform linux/amd64,linux/arm64] [--push] [--sbom syft|none] [--sign <cosign-key>]" >&2
exit 64
}
if [[ $# -lt 2 ]]; then
usage
fi
IMAGE_TAG=$1; shift
CONTEXT_DIR=$1; shift
PLATFORMS="linux/amd64,linux/arm64"
PUSH=false
SBOM_TOOL="syft"
COSIGN_KEY=""
while [[ $# -gt 0 ]]; do
case "$1" in
--platform) PLATFORMS="$2"; shift 2;;
--push) PUSH=true; shift;;
--sbom) SBOM_TOOL="$2"; shift 2;;
--sign) COSIGN_KEY="$2"; shift 2;;
*) echo "Unknown option: $1" >&2; usage;;
esac
done
if ! command -v docker >/dev/null 2>&1; then
echo "[buildx] docker CLI not found" >&2
exit 69
fi
OUT_ROOT="out/buildx/$(echo "$IMAGE_TAG" | tr '/:' '__')"
mkdir -p "$OUT_ROOT"
BUILDER_NAME="stellaops-multiarch"
if ! docker buildx inspect "$BUILDER_NAME" >/dev/null 2>&1; then
docker buildx create --name "$BUILDER_NAME" --driver docker-container --use >/dev/null
else
docker buildx use "$BUILDER_NAME" >/dev/null
fi
BUILD_OPTS=(
--platform "$PLATFORMS"
-t "$IMAGE_TAG"
--provenance=false
--sbom=false
--output "type=oci,dest=${OUT_ROOT}/image.oci"
)
if $PUSH; then
BUILD_OPTS+=("--push")
fi
echo "[buildx] building $IMAGE_TAG for $PLATFORMS"
docker buildx build "${BUILD_OPTS[@]}" "$CONTEXT_DIR"
echo "[buildx] computing digest"
IMAGE_DIGEST=$(sha256sum "${OUT_ROOT}/image.oci" | awk '{print $1}')
echo "$IMAGE_DIGEST image.oci" > "${OUT_ROOT}/image.sha256"
if [[ "$SBOM_TOOL" == "syft" ]] && command -v syft >/dev/null 2>&1; then
echo "[buildx] generating SBOM via syft"
syft "oci-archive:${OUT_ROOT}/image.oci" -o json > "${OUT_ROOT}/sbom.syft.json"
else
echo "[buildx] skipping SBOM (tool=$SBOM_TOOL, syft available? $(command -v syft >/dev/null && echo yes || echo no))"
fi
if [[ -n "$COSIGN_KEY" ]] && command -v cosign >/dev/null 2>&1; then
echo "[buildx] signing digest with cosign key"
COSIGN_EXPERIMENTAL=1 cosign sign-blob --key "$COSIGN_KEY" --output-signature "${OUT_ROOT}/image.sig" --output-certificate "${OUT_ROOT}/image.cert" "${OUT_ROOT}/image.oci"
else
echo "[buildx] signature skipped (no key provided or cosign missing)"
fi
cat > "${OUT_ROOT}/build-metadata.json" <<EOF
{
"image": "${IMAGE_TAG}",
"platforms": "${PLATFORMS}",
"pushed": ${PUSH},
"digest_sha256": "${IMAGE_DIGEST}",
"generated_at": "$(date -u +"%Y-%m-%dT%H:%M:%SZ")",
"sbom": "$( [[ -f ${OUT_ROOT}/sbom.syft.json ]] && echo sbom.syft.json || echo null )"
}
EOF
echo "[buildx] artifacts written to ${OUT_ROOT}"