#!/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" <