CD/CD consolidation
This commit is contained in:
53
.gitea/scripts/validate/validate-compose.sh
Normal file
53
.gitea/scripts/validate/validate-compose.sh
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
# validate-compose.sh - Validate all Docker Compose profiles
|
||||
# Used by CI/CD pipelines to ensure Compose configurations are valid
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||
COMPOSE_DIR="${REPO_ROOT}/devops/compose"
|
||||
|
||||
# Default profiles to validate
|
||||
PROFILES=(dev stage prod airgap mirror)
|
||||
|
||||
echo "=== Docker Compose Validation ==="
|
||||
echo "Compose directory: $COMPOSE_DIR"
|
||||
|
||||
# Check if compose directory exists
|
||||
if [[ ! -d "$COMPOSE_DIR" ]]; then
|
||||
echo "::warning::Compose directory not found at $COMPOSE_DIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check for base docker-compose.yml
|
||||
BASE_COMPOSE="$COMPOSE_DIR/docker-compose.yml"
|
||||
if [[ ! -f "$BASE_COMPOSE" ]]; then
|
||||
echo "::warning::Base docker-compose.yml not found at $BASE_COMPOSE"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
FAILED=0
|
||||
|
||||
for profile in "${PROFILES[@]}"; do
|
||||
OVERLAY="$COMPOSE_DIR/docker-compose.$profile.yml"
|
||||
|
||||
if [[ -f "$OVERLAY" ]]; then
|
||||
echo "=== Validating docker-compose.$profile.yml ==="
|
||||
if docker compose -f "$BASE_COMPOSE" -f "$OVERLAY" config --quiet 2>&1; then
|
||||
echo "✓ Profile '$profile' is valid"
|
||||
else
|
||||
echo "✗ Profile '$profile' validation failed"
|
||||
FAILED=1
|
||||
fi
|
||||
else
|
||||
echo "⊘ Skipping profile '$profile' (no overlay file)"
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $FAILED -eq 1 ]]; then
|
||||
echo "::error::One or more Compose profiles failed validation"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== All Compose profiles valid! ==="
|
||||
59
.gitea/scripts/validate/validate-helm.sh
Normal file
59
.gitea/scripts/validate/validate-helm.sh
Normal file
@@ -0,0 +1,59 @@
|
||||
#!/bin/bash
|
||||
# validate-helm.sh - Validate Helm charts
|
||||
# Used by CI/CD pipelines to ensure Helm charts are valid
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)"
|
||||
HELM_DIR="${REPO_ROOT}/devops/helm"
|
||||
|
||||
echo "=== Helm Chart Validation ==="
|
||||
echo "Helm directory: $HELM_DIR"
|
||||
|
||||
# Check if helm is installed
|
||||
if ! command -v helm &>/dev/null; then
|
||||
echo "::error::Helm is not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if helm directory exists
|
||||
if [[ ! -d "$HELM_DIR" ]]; then
|
||||
echo "::warning::Helm directory not found at $HELM_DIR"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
FAILED=0
|
||||
|
||||
# Find all Chart.yaml files (indicates a Helm chart)
|
||||
while IFS= read -r -d '' chart_file; do
|
||||
chart_dir="$(dirname "$chart_file")"
|
||||
chart_name="$(basename "$chart_dir")"
|
||||
|
||||
echo "=== Validating chart: $chart_name ==="
|
||||
|
||||
# Lint the chart
|
||||
if helm lint "$chart_dir" 2>&1; then
|
||||
echo "✓ Chart '$chart_name' lint passed"
|
||||
else
|
||||
echo "✗ Chart '$chart_name' lint failed"
|
||||
FAILED=1
|
||||
continue
|
||||
fi
|
||||
|
||||
# Template the chart (dry-run)
|
||||
if helm template "$chart_name" "$chart_dir" --debug >/dev/null 2>&1; then
|
||||
echo "✓ Chart '$chart_name' template succeeded"
|
||||
else
|
||||
echo "✗ Chart '$chart_name' template failed"
|
||||
FAILED=1
|
||||
fi
|
||||
|
||||
done < <(find "$HELM_DIR" -name "Chart.yaml" -print0)
|
||||
|
||||
if [[ $FAILED -eq 1 ]]; then
|
||||
echo "::error::One or more Helm charts failed validation"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "=== All Helm charts valid! ==="
|
||||
@@ -4,12 +4,12 @@ on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'ops/devops/airgap/**'
|
||||
- 'devops/airgap/**'
|
||||
- '.gitea/workflows/airgap-sealed-ci.yml'
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'ops/devops/airgap/**'
|
||||
- 'devops/airgap/**'
|
||||
- '.gitea/workflows/airgap-sealed-ci.yml'
|
||||
|
||||
jobs:
|
||||
@@ -21,8 +21,8 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
- name: Install dnslib
|
||||
run: pip install dnslib
|
||||
- name: Run sealed-mode smoke
|
||||
run: sudo ops/devops/airgap/sealed-ci-smoke.sh
|
||||
run: sudo devops/airgap/sealed-ci-smoke.sh
|
||||
|
||||
@@ -50,9 +50,9 @@ jobs:
|
||||
|
||||
- name: Package AOC backfill release
|
||||
run: |
|
||||
chmod +x ops/devops/aoc/package-backfill-release.sh
|
||||
chmod +x devops/aoc/package-backfill-release.sh
|
||||
DATASET_HASH="${{ github.event.inputs.dataset_hash }}" \
|
||||
ops/devops/aoc/package-backfill-release.sh
|
||||
devops/aoc/package-backfill-release.sh
|
||||
env:
|
||||
DATASET_HASH: ${{ github.event.inputs.dataset_hash }}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ on:
|
||||
- 'src/Concelier/**'
|
||||
- 'src/Authority/**'
|
||||
- 'src/Excititor/**'
|
||||
- 'ops/devops/aoc/**'
|
||||
- 'devops/aoc/**'
|
||||
- '.gitea/workflows/aoc-guard.yml'
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
@@ -17,7 +17,7 @@ on:
|
||||
- 'src/Concelier/**'
|
||||
- 'src/Authority/**'
|
||||
- 'src/Excititor/**'
|
||||
- 'ops/devops/aoc/**'
|
||||
- 'devops/aoc/**'
|
||||
- '.gitea/workflows/aoc-guard.yml'
|
||||
|
||||
jobs:
|
||||
@@ -33,10 +33,10 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Export OpenSSL 1.1 shim for Mongo2Go
|
||||
run: scripts/enable-openssl11-shim.sh
|
||||
run: .gitea/scripts/util/enable-openssl11-shim.sh
|
||||
|
||||
- name: Set up .NET SDK
|
||||
uses: actions/setup-dotnet@v4
|
||||
@@ -113,10 +113,10 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Export OpenSSL 1.1 shim for Mongo2Go
|
||||
run: scripts/enable-openssl11-shim.sh
|
||||
run: .gitea/scripts/util/enable-openssl11-shim.sh
|
||||
|
||||
- name: Set up .NET SDK
|
||||
uses: actions/setup-dotnet@v4
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Build bundle
|
||||
run: |
|
||||
|
||||
@@ -59,7 +59,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Resolve Authority configuration
|
||||
id: config
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
- name: Validate Helm chart rendering
|
||||
run: |
|
||||
set -euo pipefail
|
||||
CHART_PATH="deploy/helm/stellaops"
|
||||
CHART_PATH="devops/helm/stellaops"
|
||||
helm lint "$CHART_PATH"
|
||||
for values in values.yaml values-dev.yaml values-stage.yaml values-prod.yaml values-airgap.yaml values-mirror.yaml; do
|
||||
release="stellaops-${values%.*}"
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
done
|
||||
|
||||
- name: Validate deployment profiles
|
||||
run: ./deploy/tools/validate-profiles.sh
|
||||
run: ./devops/tools/validate-profiles.sh
|
||||
|
||||
build-test:
|
||||
runs-on: ubuntu-22.04
|
||||
@@ -85,10 +85,10 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Export OpenSSL 1.1 shim for Mongo2Go
|
||||
run: scripts/enable-openssl11-shim.sh
|
||||
run: .gitea/scripts/util/enable-openssl11-shim.sh
|
||||
|
||||
- name: Verify binary layout
|
||||
run: scripts/verify-binaries.sh
|
||||
run: .gitea/scripts/validate/verify-binaries.sh
|
||||
|
||||
- name: Ensure binary manifests are up to date
|
||||
run: |
|
||||
@@ -106,22 +106,22 @@ jobs:
|
||||
run: python3 scripts/verify-policy-scopes.py
|
||||
|
||||
- name: Validate NuGet restore source ordering
|
||||
run: python3 ops/devops/validate_restore_sources.py
|
||||
run: python3 devops/validate_restore_sources.py
|
||||
|
||||
- name: Validate telemetry storage configuration
|
||||
run: python3 ops/devops/telemetry/validate_storage_stack.py
|
||||
run: python3 devops/telemetry/validate_storage_stack.py
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: |
|
||||
python3 scripts/packs/run-fixtures-check.sh
|
||||
python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Telemetry tenant isolation smoke
|
||||
env:
|
||||
COMPOSE_DIR: ${GITHUB_WORKSPACE}/deploy/compose
|
||||
COMPOSE_DIR: ${GITHUB_WORKSPACE}/devops/compose
|
||||
run: |
|
||||
set -euo pipefail
|
||||
./ops/devops/telemetry/generate_dev_tls.sh
|
||||
COMPOSE_DIR="${COMPOSE_DIR:-${GITHUB_WORKSPACE}/deploy/compose}"
|
||||
./devops/telemetry/generate_dev_tls.sh
|
||||
COMPOSE_DIR="${COMPOSE_DIR:-${GITHUB_WORKSPACE}/devops/compose}"
|
||||
cleanup() {
|
||||
set +e
|
||||
(cd "$COMPOSE_DIR" && docker compose -f docker-compose.telemetry.yaml down -v --remove-orphans >/dev/null 2>&1)
|
||||
@@ -131,8 +131,8 @@ jobs:
|
||||
(cd "$COMPOSE_DIR" && docker compose -f docker-compose.telemetry-storage.yaml up -d)
|
||||
(cd "$COMPOSE_DIR" && docker compose -f docker-compose.telemetry.yaml up -d)
|
||||
sleep 5
|
||||
python3 ops/devops/telemetry/smoke_otel_collector.py --host localhost
|
||||
python3 ops/devops/telemetry/tenant_isolation_smoke.py \
|
||||
python3 devops/telemetry/smoke_otel_collector.py --host localhost
|
||||
python3 devops/telemetry/tenant_isolation_smoke.py \
|
||||
--collector https://localhost:4318/v1 \
|
||||
--tempo https://localhost:3200 \
|
||||
--loki https://localhost:3100
|
||||
@@ -320,7 +320,7 @@ PY
|
||||
|
||||
curl -sSf -X POST -H 'Content-type: application/json' --data "$payload" "$SLACK_WEBHOOK"
|
||||
- name: Run release tooling tests
|
||||
run: python ops/devops/release/test_verify_release.py
|
||||
run: python devops/release/test_verify_release.py
|
||||
|
||||
- name: Build scanner language analyzer projects
|
||||
run: |
|
||||
@@ -592,9 +592,9 @@ PY
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "::group::Computing reachability metrics"
|
||||
if [ -f scripts/ci/compute-reachability-metrics.sh ]; then
|
||||
chmod +x scripts/ci/compute-reachability-metrics.sh
|
||||
METRICS=$(./scripts/ci/compute-reachability-metrics.sh --dry-run 2>/dev/null || echo '{}')
|
||||
if [ -f .gitea/scripts/metrics/compute-reachability-metrics.sh ]; then
|
||||
chmod +x .gitea/scripts/metrics/compute-reachability-metrics.sh
|
||||
METRICS=$(./.gitea/scripts/metrics/compute-reachability-metrics.sh --dry-run 2>/dev/null || echo '{}')
|
||||
echo "metrics=$METRICS" >> $GITHUB_OUTPUT
|
||||
echo "Reachability metrics: $METRICS"
|
||||
else
|
||||
@@ -607,9 +607,9 @@ PY
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "::group::Computing TTFS metrics"
|
||||
if [ -f scripts/ci/compute-ttfs-metrics.sh ]; then
|
||||
chmod +x scripts/ci/compute-ttfs-metrics.sh
|
||||
METRICS=$(./scripts/ci/compute-ttfs-metrics.sh --dry-run 2>/dev/null || echo '{}')
|
||||
if [ -f .gitea/scripts/metrics/compute-ttfs-metrics.sh ]; then
|
||||
chmod +x .gitea/scripts/metrics/compute-ttfs-metrics.sh
|
||||
METRICS=$(./.gitea/scripts/metrics/compute-ttfs-metrics.sh --dry-run 2>/dev/null || echo '{}')
|
||||
echo "metrics=$METRICS" >> $GITHUB_OUTPUT
|
||||
echo "TTFS metrics: $METRICS"
|
||||
else
|
||||
@@ -622,9 +622,9 @@ PY
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "::group::Enforcing performance SLOs"
|
||||
if [ -f scripts/ci/enforce-performance-slos.sh ]; then
|
||||
chmod +x scripts/ci/enforce-performance-slos.sh
|
||||
./scripts/ci/enforce-performance-slos.sh --warn-only || true
|
||||
if [ -f .gitea/scripts/metrics/enforce-performance-slos.sh ]; then
|
||||
chmod +x .gitea/scripts/metrics/enforce-performance-slos.sh
|
||||
./.gitea/scripts/metrics/enforce-performance-slos.sh --warn-only || true
|
||||
else
|
||||
echo "Performance SLO script not found, skipping"
|
||||
fi
|
||||
@@ -635,7 +635,7 @@ PY
|
||||
run: |
|
||||
set -euo pipefail
|
||||
echo "::group::Validating RLS policies"
|
||||
if [ -f deploy/postgres-validation/001_validate_rls.sql ]; then
|
||||
if [ -f devops/database/postgres/validation/001_validate_rls.sql ]; then
|
||||
echo "RLS validation script found"
|
||||
# Check that all tenant-scoped schemas have RLS enabled
|
||||
SCHEMAS=("scheduler" "vex" "authority" "notify" "policy" "findings_ledger")
|
||||
@@ -801,7 +801,7 @@ PY
|
||||
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Run sealed-mode CI harness
|
||||
working-directory: ops/devops/sealed-mode-ci
|
||||
working-directory: devops/sealed-mode-ci
|
||||
env:
|
||||
COMPOSE_PROJECT_NAME: sealedmode
|
||||
run: |
|
||||
@@ -812,7 +812,7 @@ PY
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: sealed-mode-ci
|
||||
path: ops/devops/sealed-mode-ci/artifacts/sealed-mode-ci
|
||||
path: devops/sealed-mode-ci/artifacts/sealed-mode-ci
|
||||
if-no-files-found: error
|
||||
retention-days: 14
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
@@ -35,8 +35,8 @@ jobs:
|
||||
|
||||
- name: Build CLI artifacts
|
||||
run: |
|
||||
chmod +x scripts/cli/build-cli.sh
|
||||
RIDS="${{ github.event.inputs.rids }}" CONFIG="${{ github.event.inputs.config }}" SBOM_TOOL=syft SIGN="${{ github.event.inputs.sign }}" COSIGN_KEY="${{ secrets.COSIGN_KEY }}" scripts/cli/build-cli.sh
|
||||
chmod +x .gitea/scripts/build/build-cli.sh
|
||||
RIDS="${{ github.event.inputs.rids }}" CONFIG="${{ github.event.inputs.config }}" SBOM_TOOL=syft SIGN="${{ github.event.inputs.sign }}" COSIGN_KEY="${{ secrets.COSIGN_KEY }}" .gitea/scripts/build/build-cli.sh
|
||||
|
||||
- name: List artifacts
|
||||
run: find out/cli -maxdepth 3 -type f -print
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup .NET 10 preview
|
||||
uses: actions/setup-dotnet@v4
|
||||
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
paths:
|
||||
- 'src/Web/**'
|
||||
- '.gitea/workflows/console-ci.yml'
|
||||
- 'ops/devops/console/**'
|
||||
- 'devops/console/**'
|
||||
|
||||
jobs:
|
||||
lint-test-build:
|
||||
|
||||
@@ -4,7 +4,7 @@ on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- 'ops/devops/console/**'
|
||||
- 'devops/console/**'
|
||||
- '.gitea/workflows/console-runner-image.yml'
|
||||
|
||||
jobs:
|
||||
@@ -21,12 +21,12 @@ jobs:
|
||||
RUN_ID: ${{ github.run_id }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
chmod +x ops/devops/console/build-runner-image.sh ops/devops/console/build-runner-image-ci.sh
|
||||
ops/devops/console/build-runner-image-ci.sh
|
||||
chmod +x devops/console/build-runner-image.sh devops/console/build-runner-image-ci.sh
|
||||
devops/console/build-runner-image-ci.sh
|
||||
|
||||
- name: Upload runner image artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: console-runner-image-${{ github.run_id }}
|
||||
path: ops/devops/artifacts/console-runner/
|
||||
path: devops/artifacts/console-runner/
|
||||
retention-days: 14
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
@@ -51,10 +51,10 @@ jobs:
|
||||
env:
|
||||
COSIGN_EXPERIMENTAL: "1"
|
||||
run: |
|
||||
chmod +x scripts/buildx/build-multiarch.sh
|
||||
chmod +x .gitea/scripts/build/build-multiarch.sh
|
||||
extra=""
|
||||
if [[ "${{ github.event.inputs.push }}" == "true" ]]; then extra="--push"; fi
|
||||
scripts/buildx/build-multiarch.sh \
|
||||
.gitea/scripts/build/build-multiarch.sh \
|
||||
"${{ github.event.inputs.image }}" \
|
||||
"${{ github.event.inputs.context }}" \
|
||||
--platform "${{ github.event.inputs.platforms }}" \
|
||||
@@ -62,8 +62,8 @@ jobs:
|
||||
|
||||
- name: Build air-gap bundle
|
||||
run: |
|
||||
chmod +x scripts/buildx/build-airgap-bundle.sh
|
||||
scripts/buildx/build-airgap-bundle.sh "${{ github.event.inputs.image }}"
|
||||
chmod +x .gitea/scripts/build/build-airgap-bundle.sh
|
||||
.gitea/scripts/build/build-airgap-bundle.sh "${{ github.event.inputs.image }}"
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup .NET 10 (preview)
|
||||
uses: actions/setup-dotnet@v4
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup Node (corepack/pnpm)
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
@@ -5,16 +5,16 @@ on:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'deploy/docker/**'
|
||||
- 'deploy/compose/docker-compose.*.yml'
|
||||
- 'devops/docker/**'
|
||||
- 'devops/compose/docker-compose.*.yml'
|
||||
- 'etc/appsettings.crypto.*.yaml'
|
||||
- 'etc/crypto-plugins-manifest.json'
|
||||
- 'src/__Libraries/StellaOps.Cryptography.Plugin.**'
|
||||
- '.gitea/workflows/docker-regional-builds.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'deploy/docker/**'
|
||||
- 'deploy/compose/docker-compose.*.yml'
|
||||
- 'devops/docker/**'
|
||||
- 'devops/compose/docker-compose.*.yml'
|
||||
- 'etc/appsettings.crypto.*.yaml'
|
||||
- 'etc/crypto-plugins-manifest.json'
|
||||
- 'src/__Libraries/StellaOps.Cryptography.Plugin.**'
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./deploy/docker/Dockerfile.platform
|
||||
file: ./devops/docker/Dockerfile.platform
|
||||
target: runtime-base
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
@@ -140,7 +140,7 @@ jobs:
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: ./deploy/docker/Dockerfile.crypto-profile
|
||||
file: ./devops/docker/Dockerfile.crypto-profile
|
||||
target: ${{ matrix.service }}
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
@@ -176,7 +176,7 @@ jobs:
|
||||
|
||||
- name: Validate docker-compose file
|
||||
run: |
|
||||
docker compose -f deploy/compose/docker-compose.${{ matrix.profile }}.yml config --quiet
|
||||
docker compose -f devops/compose/docker-compose.${{ matrix.profile }}.yml config --quiet
|
||||
|
||||
- name: Check required crypto configuration fields
|
||||
run: |
|
||||
|
||||
@@ -30,10 +30,10 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Export OpenSSL 1.1 shim for Mongo2Go
|
||||
run: scripts/enable-openssl11-shim.sh
|
||||
run: .gitea/scripts/util/enable-openssl11-shim.sh
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Emit retention summary
|
||||
env:
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Package staged Zastava artefacts
|
||||
run: |
|
||||
|
||||
@@ -5,14 +5,14 @@ on:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'src/ExportCenter/**'
|
||||
- 'ops/devops/export/**'
|
||||
- 'devops/export/**'
|
||||
- '.gitea/workflows/export-ci.yml'
|
||||
- 'docs/modules/devops/export-ci-contract.md'
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'src/ExportCenter/**'
|
||||
- 'ops/devops/export/**'
|
||||
- 'devops/export/**'
|
||||
- '.gitea/workflows/export-ci.yml'
|
||||
- 'docs/modules/devops/export-ci-contract.md'
|
||||
|
||||
@@ -30,12 +30,12 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Export OpenSSL 1.1 shim for Mongo2Go
|
||||
run: scripts/enable-openssl11-shim.sh
|
||||
run: .gitea/scripts/util/enable-openssl11-shim.sh
|
||||
|
||||
- name: Set up .NET SDK
|
||||
uses: actions/setup-dotnet@v4
|
||||
@@ -48,9 +48,9 @@ jobs:
|
||||
|
||||
- name: Bring up MinIO
|
||||
run: |
|
||||
docker compose -f ops/devops/export/minio-compose.yml up -d
|
||||
docker compose -f devops/export/minio-compose.yml up -d
|
||||
sleep 5
|
||||
MINIO_ENDPOINT=http://localhost:9000 ops/devops/export/seed-minio.sh
|
||||
MINIO_ENDPOINT=http://localhost:9000 devops/export/seed-minio.sh
|
||||
|
||||
- name: Build
|
||||
run: dotnet build src/ExportCenter/StellaOps.ExportCenter.WebService/StellaOps.ExportCenter.WebService.csproj -c Release /p:ContinuousIntegrationBuild=true
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
dotnet test src/ExportCenter/__Tests/StellaOps.ExportCenter.Tests/StellaOps.ExportCenter.Tests.csproj -c Release --logger "trx;LogFileName=export-tests.trx" --results-directory $ARTIFACT_DIR
|
||||
|
||||
- name: Trivy/OCI smoke
|
||||
run: ops/devops/export/trivy-smoke.sh
|
||||
run: devops/export/trivy-smoke.sh
|
||||
|
||||
- name: Schema lint
|
||||
run: |
|
||||
@@ -82,4 +82,4 @@ jobs:
|
||||
|
||||
- name: Teardown MinIO
|
||||
if: always()
|
||||
run: docker compose -f ops/devops/export/minio-compose.yml down -v
|
||||
run: docker compose -f devops/export/minio-compose.yml down -v
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup Trivy
|
||||
uses: aquasecurity/trivy-action@v0.24.0
|
||||
|
||||
@@ -9,10 +9,10 @@ on:
|
||||
paths:
|
||||
- 'src/Findings/**'
|
||||
- '.gitea/workflows/findings-ledger-ci.yml'
|
||||
- 'deploy/releases/2025.09-stable.yaml'
|
||||
- 'deploy/releases/2025.09-airgap.yaml'
|
||||
- 'deploy/downloads/manifest.json'
|
||||
- 'ops/devops/release/check_release_manifest.py'
|
||||
- 'devops/releases/2025.09-stable.yaml'
|
||||
- 'devops/releases/2025.09-airgap.yaml'
|
||||
- 'devops/downloads/manifest.json'
|
||||
- 'devops/release/check_release_manifest.py'
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
paths:
|
||||
@@ -217,7 +217,7 @@ jobs:
|
||||
- name: Validate release manifests (production)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python ops/devops/release/check_release_manifest.py
|
||||
python devops/release/check_release_manifest.py
|
||||
|
||||
- name: Re-apply RLS migration (idempotency check)
|
||||
run: |
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Install k6
|
||||
run: |
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'api/ledger/**'
|
||||
- 'ops/devops/ledger/**'
|
||||
- 'devops/ledger/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'api/ledger/**'
|
||||
@@ -30,8 +30,8 @@ jobs:
|
||||
|
||||
- name: Validate OpenAPI spec
|
||||
run: |
|
||||
chmod +x ops/devops/ledger/validate-oas.sh
|
||||
ops/devops/ledger/validate-oas.sh
|
||||
chmod +x devops/ledger/validate-oas.sh
|
||||
devops/ledger/validate-oas.sh
|
||||
|
||||
- name: Upload validation report
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -72,9 +72,9 @@ jobs:
|
||||
|
||||
- name: Check deprecation policy
|
||||
run: |
|
||||
if [ -f "ops/devops/ledger/deprecation-policy.yaml" ]; then
|
||||
if [ -f "devops/ledger/deprecation-policy.yaml" ]; then
|
||||
echo "Validating deprecation policy..."
|
||||
python3 -c "import yaml; yaml.safe_load(open('ops/devops/ledger/deprecation-policy.yaml'))"
|
||||
python3 -c "import yaml; yaml.safe_load(open('devops/ledger/deprecation-policy.yaml'))"
|
||||
echo "Deprecation policy is valid"
|
||||
else
|
||||
echo "[info] No deprecation policy yet (OK for initial setup)"
|
||||
|
||||
@@ -14,7 +14,7 @@ on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'ops/devops/ledger/**'
|
||||
- 'devops/ledger/**'
|
||||
|
||||
jobs:
|
||||
build-pack:
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
|
||||
- name: Build pack
|
||||
run: |
|
||||
chmod +x ops/devops/ledger/build-pack.sh
|
||||
chmod +x devops/ledger/build-pack.sh
|
||||
SNAPSHOT_ID="${{ github.event.inputs.snapshot_id }}"
|
||||
if [ -z "$SNAPSHOT_ID" ]; then
|
||||
SNAPSHOT_ID="ci-$(date +%Y%m%d%H%M%S)"
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
SIGN_FLAG="--sign"
|
||||
fi
|
||||
|
||||
SNAPSHOT_ID="$SNAPSHOT_ID" ops/devops/ledger/build-pack.sh $SIGN_FLAG
|
||||
SNAPSHOT_ID="$SNAPSHOT_ID" devops/ledger/build-pack.sh $SIGN_FLAG
|
||||
|
||||
- name: Verify checksums
|
||||
run: |
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
env:
|
||||
STAGING_MONGO_URI: ${{ inputs.mongo_uri }}
|
||||
run: |
|
||||
STAGING_MONGO_URI="$STAGING_MONGO_URI" ops/devops/lnm/backfill-validation.sh
|
||||
STAGING_MONGO_URI="$STAGING_MONGO_URI" devops/lnm/backfill-validation.sh
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
@@ -11,7 +11,7 @@ on:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'src/Concelier/__Libraries/StellaOps.Concelier.Migrations/**'
|
||||
- 'ops/devops/lnm/**'
|
||||
- 'devops/lnm/**'
|
||||
|
||||
jobs:
|
||||
build-runner:
|
||||
@@ -40,8 +40,8 @@ jobs:
|
||||
|
||||
- name: Build and package runner
|
||||
run: |
|
||||
chmod +x ops/devops/lnm/package-runner.sh
|
||||
ops/devops/lnm/package-runner.sh
|
||||
chmod +x devops/lnm/package-runner.sh
|
||||
devops/lnm/package-runner.sh
|
||||
|
||||
- name: Verify checksums
|
||||
run: |
|
||||
@@ -69,15 +69,15 @@ jobs:
|
||||
- name: Validate monitoring config
|
||||
run: |
|
||||
# Validate alert rules syntax
|
||||
if [ -f "ops/devops/lnm/alerts/lnm-alerts.yaml" ]; then
|
||||
if [ -f "devops/lnm/alerts/lnm-alerts.yaml" ]; then
|
||||
echo "Validating alert rules..."
|
||||
python3 -c "import yaml; yaml.safe_load(open('ops/devops/lnm/alerts/lnm-alerts.yaml'))"
|
||||
python3 -c "import yaml; yaml.safe_load(open('devops/lnm/alerts/lnm-alerts.yaml'))"
|
||||
fi
|
||||
|
||||
# Validate dashboard JSON
|
||||
if [ -f "ops/devops/lnm/dashboards/lnm-migration.json" ]; then
|
||||
if [ -f "devops/lnm/dashboards/lnm-migration.json" ]; then
|
||||
echo "Validating dashboard..."
|
||||
python3 -c "import json; json.load(open('ops/devops/lnm/dashboards/lnm-migration.json'))"
|
||||
python3 -c "import json; json.load(open('devops/lnm/dashboards/lnm-migration.json'))"
|
||||
fi
|
||||
|
||||
echo "Monitoring config validation complete"
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
@@ -78,9 +78,9 @@ jobs:
|
||||
|
||||
- name: Run fixture validation
|
||||
run: |
|
||||
if [ -f scripts/packs/run-fixtures-check.sh ]; then
|
||||
chmod +x scripts/packs/run-fixtures-check.sh
|
||||
./scripts/packs/run-fixtures-check.sh
|
||||
if [ -f .gitea/scripts/test/run-fixtures-check.sh ]; then
|
||||
chmod +x .gitea/scripts/test/run-fixtures-check.sh
|
||||
./.gitea/scripts/test/run-fixtures-check.sh
|
||||
fi
|
||||
|
||||
checksum-audit:
|
||||
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
include-prerelease: true
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Verify signing prerequisites
|
||||
run: scripts/mirror/check_signing_prereqs.sh
|
||||
|
||||
@@ -3,9 +3,9 @@ name: mock-dev-release
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- deploy/releases/2025.09-mock-dev.yaml
|
||||
- deploy/downloads/manifest.json
|
||||
- ops/devops/mock-release/**
|
||||
- devops/releases/2025.09-mock-dev.yaml
|
||||
- devops/downloads/manifest.json
|
||||
- devops/mock-release/**
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
@@ -19,19 +19,19 @@ jobs:
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p out/mock-release
|
||||
cp deploy/releases/2025.09-mock-dev.yaml out/mock-release/
|
||||
cp deploy/downloads/manifest.json out/mock-release/
|
||||
cp devops/releases/2025.09-mock-dev.yaml out/mock-release/
|
||||
cp devops/downloads/manifest.json out/mock-release/
|
||||
tar -czf out/mock-release/mock-dev-release.tgz -C out/mock-release .
|
||||
|
||||
- name: Compose config (dev + mock overlay)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
ops/devops/mock-release/config_check.sh
|
||||
devops/mock-release/config_check.sh
|
||||
|
||||
- name: Helm template (mock overlay)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
helm template mock ./deploy/helm/stellaops -f deploy/helm/stellaops/values-mock.yaml > /tmp/helm-mock.yaml
|
||||
helm template mock ./devops/helm/stellaops -f devops/helm/stellaops/values-mock.yaml > /tmp/helm-mock.yaml
|
||||
ls -lh /tmp/helm-mock.yaml
|
||||
|
||||
- name: Upload mock release bundle
|
||||
|
||||
405
.gitea/workflows/module-publish.yml
Normal file
405
.gitea/workflows/module-publish.yml
Normal file
@@ -0,0 +1,405 @@
|
||||
# .gitea/workflows/module-publish.yml
|
||||
# Per-module NuGet and container publishing to Gitea registry
|
||||
# Sprint: SPRINT_20251226_004_CICD
|
||||
|
||||
name: Module Publish
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
module:
|
||||
description: 'Module to publish'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- Authority
|
||||
- Attestor
|
||||
- Concelier
|
||||
- Scanner
|
||||
- Policy
|
||||
- Signer
|
||||
- Excititor
|
||||
- Gateway
|
||||
- Scheduler
|
||||
- Orchestrator
|
||||
- TaskRunner
|
||||
- Notify
|
||||
- CLI
|
||||
version:
|
||||
description: 'Semantic version (e.g., 1.2.3)'
|
||||
required: true
|
||||
type: string
|
||||
publish_nuget:
|
||||
description: 'Publish NuGet packages'
|
||||
type: boolean
|
||||
default: true
|
||||
publish_container:
|
||||
description: 'Publish container image'
|
||||
type: boolean
|
||||
default: true
|
||||
prerelease:
|
||||
description: 'Mark as prerelease'
|
||||
type: boolean
|
||||
default: false
|
||||
push:
|
||||
tags:
|
||||
- 'module-*-v*' # e.g., module-authority-v1.2.3
|
||||
|
||||
env:
|
||||
DOTNET_VERSION: '10.0.100'
|
||||
DOTNET_NOLOGO: 1
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
REGISTRY: git.stella-ops.org
|
||||
NUGET_SOURCE: https://git.stella-ops.org/api/packages/stella-ops.org/nuget/index.json
|
||||
|
||||
jobs:
|
||||
# ===========================================================================
|
||||
# PARSE TAG (for tag-triggered builds)
|
||||
# ===========================================================================
|
||||
|
||||
parse-tag:
|
||||
name: Parse Tag
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.event_name == 'push'
|
||||
outputs:
|
||||
module: ${{ steps.parse.outputs.module }}
|
||||
version: ${{ steps.parse.outputs.version }}
|
||||
steps:
|
||||
- name: Parse module and version from tag
|
||||
id: parse
|
||||
run: |
|
||||
TAG="${{ github.ref_name }}"
|
||||
# Expected format: module-{name}-v{version}
|
||||
# Example: module-authority-v1.2.3
|
||||
if [[ "$TAG" =~ ^module-([a-zA-Z]+)-v([0-9]+\.[0-9]+\.[0-9]+.*)$ ]]; then
|
||||
MODULE="${BASH_REMATCH[1]}"
|
||||
VERSION="${BASH_REMATCH[2]}"
|
||||
# Capitalize first letter
|
||||
MODULE="$(echo "${MODULE:0:1}" | tr '[:lower:]' '[:upper:]')${MODULE:1}"
|
||||
echo "module=$MODULE" >> "$GITHUB_OUTPUT"
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "Parsed: module=$MODULE, version=$VERSION"
|
||||
else
|
||||
echo "::error::Invalid tag format. Expected: module-{name}-v{version}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ===========================================================================
|
||||
# VALIDATE
|
||||
# ===========================================================================
|
||||
|
||||
validate:
|
||||
name: Validate Inputs
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [parse-tag]
|
||||
if: always() && (needs.parse-tag.result == 'success' || needs.parse-tag.result == 'skipped')
|
||||
outputs:
|
||||
module: ${{ steps.resolve.outputs.module }}
|
||||
version: ${{ steps.resolve.outputs.version }}
|
||||
publish_nuget: ${{ steps.resolve.outputs.publish_nuget }}
|
||||
publish_container: ${{ steps.resolve.outputs.publish_container }}
|
||||
steps:
|
||||
- name: Resolve inputs
|
||||
id: resolve
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "push" ]]; then
|
||||
MODULE="${{ needs.parse-tag.outputs.module }}"
|
||||
VERSION="${{ needs.parse-tag.outputs.version }}"
|
||||
PUBLISH_NUGET="true"
|
||||
PUBLISH_CONTAINER="true"
|
||||
else
|
||||
MODULE="${{ github.event.inputs.module }}"
|
||||
VERSION="${{ github.event.inputs.version }}"
|
||||
PUBLISH_NUGET="${{ github.event.inputs.publish_nuget }}"
|
||||
PUBLISH_CONTAINER="${{ github.event.inputs.publish_container }}"
|
||||
fi
|
||||
|
||||
echo "module=$MODULE" >> "$GITHUB_OUTPUT"
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "publish_nuget=$PUBLISH_NUGET" >> "$GITHUB_OUTPUT"
|
||||
echo "publish_container=$PUBLISH_CONTAINER" >> "$GITHUB_OUTPUT"
|
||||
|
||||
echo "=== Resolved Configuration ==="
|
||||
echo "Module: $MODULE"
|
||||
echo "Version: $VERSION"
|
||||
echo "Publish NuGet: $PUBLISH_NUGET"
|
||||
echo "Publish Container: $PUBLISH_CONTAINER"
|
||||
|
||||
- name: Validate version format
|
||||
run: |
|
||||
VERSION="${{ steps.resolve.outputs.version }}"
|
||||
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9.]+)?$ ]]; then
|
||||
echo "::error::Invalid version format. Expected: MAJOR.MINOR.PATCH[-prerelease]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ===========================================================================
|
||||
# PUBLISH NUGET
|
||||
# ===========================================================================
|
||||
|
||||
publish-nuget:
|
||||
name: Publish NuGet
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate]
|
||||
if: needs.validate.outputs.publish_nuget == 'true'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Determine project path
|
||||
id: path
|
||||
run: |
|
||||
MODULE="${{ needs.validate.outputs.module }}"
|
||||
|
||||
# Map module names to project paths
|
||||
case "$MODULE" in
|
||||
Authority)
|
||||
PROJECT="src/Authority/StellaOps.Authority.WebService/StellaOps.Authority.WebService.csproj"
|
||||
;;
|
||||
Attestor)
|
||||
PROJECT="src/Attestor/StellaOps.Attestor.WebService/StellaOps.Attestor.WebService.csproj"
|
||||
;;
|
||||
Concelier)
|
||||
PROJECT="src/Concelier/StellaOps.Concelier.WebService/StellaOps.Concelier.WebService.csproj"
|
||||
;;
|
||||
Scanner)
|
||||
PROJECT="src/Scanner/StellaOps.Scanner.WebService/StellaOps.Scanner.WebService.csproj"
|
||||
;;
|
||||
Policy)
|
||||
PROJECT="src/Policy/StellaOps.Policy.Gateway/StellaOps.Policy.Gateway.csproj"
|
||||
;;
|
||||
Signer)
|
||||
PROJECT="src/Signer/StellaOps.Signer.WebService/StellaOps.Signer.WebService.csproj"
|
||||
;;
|
||||
Excititor)
|
||||
PROJECT="src/Excititor/StellaOps.Excititor.WebService/StellaOps.Excititor.WebService.csproj"
|
||||
;;
|
||||
Gateway)
|
||||
PROJECT="src/Gateway/StellaOps.Gateway.WebService/StellaOps.Gateway.WebService.csproj"
|
||||
;;
|
||||
Scheduler)
|
||||
PROJECT="src/Scheduler/StellaOps.Scheduler.WebService/StellaOps.Scheduler.WebService.csproj"
|
||||
;;
|
||||
Orchestrator)
|
||||
PROJECT="src/Orchestrator/StellaOps.Orchestrator.WebService/StellaOps.Orchestrator.WebService.csproj"
|
||||
;;
|
||||
TaskRunner)
|
||||
PROJECT="src/TaskRunner/StellaOps.TaskRunner.WebService/StellaOps.TaskRunner.WebService.csproj"
|
||||
;;
|
||||
Notify)
|
||||
PROJECT="src/Notify/StellaOps.Notify.WebService/StellaOps.Notify.WebService.csproj"
|
||||
;;
|
||||
CLI)
|
||||
PROJECT="src/Cli/StellaOps.Cli/StellaOps.Cli.csproj"
|
||||
;;
|
||||
*)
|
||||
echo "::error::Unknown module: $MODULE"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "project=$PROJECT" >> "$GITHUB_OUTPUT"
|
||||
echo "Project path: $PROJECT"
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore ${{ steps.path.outputs.project }}
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
dotnet build ${{ steps.path.outputs.project }} \
|
||||
--configuration Release \
|
||||
--no-restore \
|
||||
-p:Version=${{ needs.validate.outputs.version }}
|
||||
|
||||
- name: Pack NuGet
|
||||
run: |
|
||||
dotnet pack ${{ steps.path.outputs.project }} \
|
||||
--configuration Release \
|
||||
--no-build \
|
||||
-p:Version=${{ needs.validate.outputs.version }} \
|
||||
-p:PackageVersion=${{ needs.validate.outputs.version }} \
|
||||
--output out/packages
|
||||
|
||||
- name: Push to Gitea NuGet registry
|
||||
run: |
|
||||
for nupkg in out/packages/*.nupkg; do
|
||||
echo "Pushing: $nupkg"
|
||||
dotnet nuget push "$nupkg" \
|
||||
--source "${{ env.NUGET_SOURCE }}" \
|
||||
--api-key "${{ secrets.GITEA_TOKEN }}" \
|
||||
--skip-duplicate
|
||||
done
|
||||
|
||||
- name: Upload NuGet artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: nuget-${{ needs.validate.outputs.module }}-${{ needs.validate.outputs.version }}
|
||||
path: out/packages/*.nupkg
|
||||
retention-days: 30
|
||||
|
||||
# ===========================================================================
|
||||
# PUBLISH CONTAINER
|
||||
# ===========================================================================
|
||||
|
||||
publish-container:
|
||||
name: Publish Container
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate]
|
||||
if: needs.validate.outputs.publish_container == 'true' && needs.validate.outputs.module != 'CLI'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Gitea Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITEA_TOKEN }}
|
||||
|
||||
- name: Determine image name
|
||||
id: image
|
||||
run: |
|
||||
MODULE="${{ needs.validate.outputs.module }}"
|
||||
VERSION="${{ needs.validate.outputs.version }}"
|
||||
MODULE_LOWER=$(echo "$MODULE" | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
IMAGE="${{ env.REGISTRY }}/stella-ops.org/${MODULE_LOWER}"
|
||||
|
||||
echo "name=$IMAGE" >> "$GITHUB_OUTPUT"
|
||||
echo "tag_version=${IMAGE}:${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "tag_latest=${IMAGE}:latest" >> "$GITHUB_OUTPUT"
|
||||
|
||||
echo "Image: $IMAGE"
|
||||
echo "Tags: ${VERSION}, latest"
|
||||
|
||||
- name: Build and push container
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: devops/docker/Dockerfile.platform
|
||||
target: ${{ needs.validate.outputs.module | lower }}
|
||||
push: true
|
||||
tags: |
|
||||
${{ steps.image.outputs.tag_version }}
|
||||
${{ steps.image.outputs.tag_latest }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
labels: |
|
||||
org.opencontainers.image.title=StellaOps ${{ needs.validate.outputs.module }}
|
||||
org.opencontainers.image.version=${{ needs.validate.outputs.version }}
|
||||
org.opencontainers.image.source=https://git.stella-ops.org/stella-ops.org/git.stella-ops.org
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
|
||||
# ===========================================================================
|
||||
# PUBLISH CLI BINARIES (multi-platform)
|
||||
# ===========================================================================
|
||||
|
||||
publish-cli:
|
||||
name: Publish CLI (${{ matrix.runtime }})
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate]
|
||||
if: needs.validate.outputs.module == 'CLI'
|
||||
strategy:
|
||||
matrix:
|
||||
runtime:
|
||||
- linux-x64
|
||||
- linux-arm64
|
||||
- win-x64
|
||||
- osx-x64
|
||||
- osx-arm64
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Install cross-compilation tools
|
||||
if: matrix.runtime == 'linux-arm64'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends binutils-aarch64-linux-gnu
|
||||
|
||||
- name: Publish CLI
|
||||
run: |
|
||||
dotnet publish src/Cli/StellaOps.Cli/StellaOps.Cli.csproj \
|
||||
--configuration Release \
|
||||
--runtime ${{ matrix.runtime }} \
|
||||
--self-contained true \
|
||||
-p:Version=${{ needs.validate.outputs.version }} \
|
||||
-p:PublishSingleFile=true \
|
||||
-p:PublishTrimmed=true \
|
||||
-p:EnableCompressionInSingleFile=true \
|
||||
--output out/cli/${{ matrix.runtime }}
|
||||
|
||||
- name: Create archive
|
||||
run: |
|
||||
VERSION="${{ needs.validate.outputs.version }}"
|
||||
RUNTIME="${{ matrix.runtime }}"
|
||||
|
||||
cd out/cli/$RUNTIME
|
||||
if [[ "$RUNTIME" == win-* ]]; then
|
||||
zip -r ../stellaops-cli-${VERSION}-${RUNTIME}.zip .
|
||||
else
|
||||
tar -czvf ../stellaops-cli-${VERSION}-${RUNTIME}.tar.gz .
|
||||
fi
|
||||
|
||||
- name: Upload CLI artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cli-${{ needs.validate.outputs.version }}-${{ matrix.runtime }}
|
||||
path: |
|
||||
out/cli/*.zip
|
||||
out/cli/*.tar.gz
|
||||
retention-days: 30
|
||||
|
||||
# ===========================================================================
|
||||
# SUMMARY
|
||||
# ===========================================================================
|
||||
|
||||
summary:
|
||||
name: Publish Summary
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate, publish-nuget, publish-container, publish-cli]
|
||||
if: always()
|
||||
steps:
|
||||
- name: Generate Summary
|
||||
run: |
|
||||
echo "## Module Publish Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Module | ${{ needs.validate.outputs.module }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Version | ${{ needs.validate.outputs.version }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| NuGet | ${{ needs.publish-nuget.result || 'skipped' }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Container | ${{ needs.publish-container.result || 'skipped' }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| CLI | ${{ needs.publish-cli.result || 'skipped' }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Registry URLs" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- NuGet: \`${{ env.NUGET_SOURCE }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
echo "- Container: \`${{ env.REGISTRY }}/stella-ops.org/${{ needs.validate.outputs.module | lower }}\`" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Check for failures
|
||||
if: contains(needs.*.result, 'failure')
|
||||
run: |
|
||||
echo "::error::One or more publish jobs failed"
|
||||
exit 1
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup Python (telemetry schema checks)
|
||||
uses: actions/setup-python@v5
|
||||
@@ -36,8 +36,8 @@ jobs:
|
||||
env:
|
||||
TELEMETRY_BUNDLE_SCHEMA: docs/modules/telemetry/schemas/telemetry-bundle.schema.json
|
||||
run: |
|
||||
chmod +x ops/devops/telemetry/tests/ci-run.sh
|
||||
ops/devops/telemetry/tests/ci-run.sh
|
||||
chmod +x devops/telemetry/tests/ci-run.sh
|
||||
devops/telemetry/tests/ci-run.sh
|
||||
|
||||
- name: Upload SLO results
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Install nats CLI
|
||||
run: |
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
run: |
|
||||
export COSIGN_KEY_B64=$(base64 -w0 out/policy-sign/keys/ci-policy-cosign.key)
|
||||
COSIGN_PASSWORD= \
|
||||
scripts/policy/sign-policy.sh --file docs/examples/policies/baseline.stella --out-dir out/policy-sign
|
||||
.gitea/scripts/sign/sign-policy.sh --file docs/examples/policies/baseline.stella --out-dir out/policy-sign
|
||||
|
||||
- name: Attest and verify sample policy blob
|
||||
run: |
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Resolve staging credentials
|
||||
id: staging
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Emit provenance summary
|
||||
run: |
|
||||
|
||||
@@ -3,10 +3,10 @@ name: release-manifest-verify
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- deploy/releases/2025.09-stable.yaml
|
||||
- deploy/releases/2025.09-airgap.yaml
|
||||
- deploy/downloads/manifest.json
|
||||
- ops/devops/release/check_release_manifest.py
|
||||
- devops/releases/2025.09-stable.yaml
|
||||
- devops/releases/2025.09-airgap.yaml
|
||||
- devops/downloads/manifest.json
|
||||
- devops/release/check_release_manifest.py
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
@@ -16,4 +16,4 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Validate release & downloads manifests
|
||||
run: |
|
||||
python ops/devops/release/check_release_manifest.py
|
||||
python devops/release/check_release_manifest.py
|
||||
|
||||
683
.gitea/workflows/release-suite.yml
Normal file
683
.gitea/workflows/release-suite.yml
Normal file
@@ -0,0 +1,683 @@
|
||||
# .gitea/workflows/release-suite.yml
|
||||
# Full suite release pipeline with Ubuntu-style versioning (YYYY.MM)
|
||||
# Sprint: SPRINT_20251226_005_CICD
|
||||
|
||||
name: Suite Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: 'Suite version (YYYY.MM format, e.g., 2026.04)'
|
||||
required: true
|
||||
type: string
|
||||
codename:
|
||||
description: 'Release codename (e.g., Nova, Orion, Pulsar)'
|
||||
required: true
|
||||
type: string
|
||||
channel:
|
||||
description: 'Release channel'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- edge
|
||||
- stable
|
||||
- lts
|
||||
default: edge
|
||||
skip_tests:
|
||||
description: 'Skip test execution (use with caution)'
|
||||
type: boolean
|
||||
default: false
|
||||
dry_run:
|
||||
description: 'Dry run (build but do not publish)'
|
||||
type: boolean
|
||||
default: false
|
||||
push:
|
||||
tags:
|
||||
- 'suite-*' # e.g., suite-2026.04
|
||||
|
||||
env:
|
||||
DOTNET_VERSION: '10.0.100'
|
||||
DOTNET_NOLOGO: 1
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
REGISTRY: git.stella-ops.org
|
||||
NUGET_SOURCE: https://git.stella-ops.org/api/packages/stella-ops.org/nuget/index.json
|
||||
|
||||
jobs:
|
||||
# ===========================================================================
|
||||
# PARSE TAG (for tag-triggered builds)
|
||||
# ===========================================================================
|
||||
|
||||
parse-tag:
|
||||
name: Parse Tag
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.event_name == 'push'
|
||||
outputs:
|
||||
version: ${{ steps.parse.outputs.version }}
|
||||
codename: ${{ steps.parse.outputs.codename }}
|
||||
channel: ${{ steps.parse.outputs.channel }}
|
||||
steps:
|
||||
- name: Parse version from tag
|
||||
id: parse
|
||||
run: |
|
||||
TAG="${{ github.ref_name }}"
|
||||
# Expected format: suite-{YYYY.MM} or suite-{YYYY.MM}-{codename}
|
||||
if [[ "$TAG" =~ ^suite-([0-9]{4}\.(04|10))(-([a-zA-Z]+))?$ ]]; then
|
||||
VERSION="${BASH_REMATCH[1]}"
|
||||
CODENAME="${BASH_REMATCH[4]:-TBD}"
|
||||
|
||||
# Determine channel based on month (04 = LTS, 10 = feature)
|
||||
MONTH="${BASH_REMATCH[2]}"
|
||||
if [[ "$MONTH" == "04" ]]; then
|
||||
CHANNEL="lts"
|
||||
else
|
||||
CHANNEL="stable"
|
||||
fi
|
||||
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "codename=$CODENAME" >> "$GITHUB_OUTPUT"
|
||||
echo "channel=$CHANNEL" >> "$GITHUB_OUTPUT"
|
||||
echo "Parsed: version=$VERSION, codename=$CODENAME, channel=$CHANNEL"
|
||||
else
|
||||
echo "::error::Invalid tag format. Expected: suite-YYYY.MM or suite-YYYY.MM-codename"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ===========================================================================
|
||||
# VALIDATE
|
||||
# ===========================================================================
|
||||
|
||||
validate:
|
||||
name: Validate Release
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [parse-tag]
|
||||
if: always() && (needs.parse-tag.result == 'success' || needs.parse-tag.result == 'skipped')
|
||||
outputs:
|
||||
version: ${{ steps.resolve.outputs.version }}
|
||||
codename: ${{ steps.resolve.outputs.codename }}
|
||||
channel: ${{ steps.resolve.outputs.channel }}
|
||||
dry_run: ${{ steps.resolve.outputs.dry_run }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Resolve inputs
|
||||
id: resolve
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "push" ]]; then
|
||||
VERSION="${{ needs.parse-tag.outputs.version }}"
|
||||
CODENAME="${{ needs.parse-tag.outputs.codename }}"
|
||||
CHANNEL="${{ needs.parse-tag.outputs.channel }}"
|
||||
DRY_RUN="false"
|
||||
else
|
||||
VERSION="${{ github.event.inputs.version }}"
|
||||
CODENAME="${{ github.event.inputs.codename }}"
|
||||
CHANNEL="${{ github.event.inputs.channel }}"
|
||||
DRY_RUN="${{ github.event.inputs.dry_run }}"
|
||||
fi
|
||||
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "codename=$CODENAME" >> "$GITHUB_OUTPUT"
|
||||
echo "channel=$CHANNEL" >> "$GITHUB_OUTPUT"
|
||||
echo "dry_run=$DRY_RUN" >> "$GITHUB_OUTPUT"
|
||||
|
||||
echo "=== Suite Release Configuration ==="
|
||||
echo "Version: $VERSION"
|
||||
echo "Codename: $CODENAME"
|
||||
echo "Channel: $CHANNEL"
|
||||
echo "Dry Run: $DRY_RUN"
|
||||
|
||||
- name: Validate version format
|
||||
run: |
|
||||
VERSION="${{ steps.resolve.outputs.version }}"
|
||||
if ! [[ "$VERSION" =~ ^[0-9]{4}\.(04|10)$ ]]; then
|
||||
echo "::error::Invalid version format. Expected YYYY.MM where MM is 04 or 10 (e.g., 2026.04)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Validate codename
|
||||
run: |
|
||||
CODENAME="${{ steps.resolve.outputs.codename }}"
|
||||
if [[ -z "$CODENAME" || "$CODENAME" == "TBD" ]]; then
|
||||
echo "::warning::No codename provided, release will use 'TBD'"
|
||||
elif ! [[ "$CODENAME" =~ ^[A-Z][a-z]+$ ]]; then
|
||||
echo "::warning::Codename should be capitalized (e.g., Nova, Orion)"
|
||||
fi
|
||||
|
||||
# ===========================================================================
|
||||
# RUN TESTS (unless skipped)
|
||||
# ===========================================================================
|
||||
|
||||
test-gate:
|
||||
name: Test Gate
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate]
|
||||
if: github.event.inputs.skip_tests != 'true'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore src/StellaOps.sln
|
||||
|
||||
- name: Build
|
||||
run: dotnet build src/StellaOps.sln -c Release --no-restore
|
||||
|
||||
- name: Run Release Tests
|
||||
run: |
|
||||
dotnet test src/StellaOps.sln \
|
||||
--filter "Category=Unit|Category=Architecture|Category=Contract" \
|
||||
--configuration Release \
|
||||
--no-build \
|
||||
--logger "trx;LogFileName=release-tests.trx" \
|
||||
--results-directory ./TestResults
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: release-test-results
|
||||
path: ./TestResults
|
||||
retention-days: 14
|
||||
|
||||
# ===========================================================================
|
||||
# BUILD MODULES (matrix strategy)
|
||||
# ===========================================================================
|
||||
|
||||
build-modules:
|
||||
name: Build ${{ matrix.module }}
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate, test-gate]
|
||||
if: always() && needs.validate.result == 'success' && (needs.test-gate.result == 'success' || needs.test-gate.result == 'skipped')
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
module:
|
||||
- name: Authority
|
||||
project: src/Authority/StellaOps.Authority.WebService/StellaOps.Authority.WebService.csproj
|
||||
- name: Attestor
|
||||
project: src/Attestor/StellaOps.Attestor.WebService/StellaOps.Attestor.WebService.csproj
|
||||
- name: Concelier
|
||||
project: src/Concelier/StellaOps.Concelier.WebService/StellaOps.Concelier.WebService.csproj
|
||||
- name: Scanner
|
||||
project: src/Scanner/StellaOps.Scanner.WebService/StellaOps.Scanner.WebService.csproj
|
||||
- name: Policy
|
||||
project: src/Policy/StellaOps.Policy.Gateway/StellaOps.Policy.Gateway.csproj
|
||||
- name: Signer
|
||||
project: src/Signer/StellaOps.Signer.WebService/StellaOps.Signer.WebService.csproj
|
||||
- name: Excititor
|
||||
project: src/Excititor/StellaOps.Excititor.WebService/StellaOps.Excititor.WebService.csproj
|
||||
- name: Gateway
|
||||
project: src/Gateway/StellaOps.Gateway.WebService/StellaOps.Gateway.WebService.csproj
|
||||
- name: Scheduler
|
||||
project: src/Scheduler/StellaOps.Scheduler.WebService/StellaOps.Scheduler.WebService.csproj
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Determine module version
|
||||
id: version
|
||||
run: |
|
||||
MODULE_NAME="${{ matrix.module.name }}"
|
||||
MODULE_LOWER=$(echo "$MODULE_NAME" | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
# Try to read version from version.txt, fallback to 1.0.0
|
||||
VERSION_FILE="src/${MODULE_NAME}/version.txt"
|
||||
if [[ -f "$VERSION_FILE" ]]; then
|
||||
MODULE_VERSION=$(cat "$VERSION_FILE" | tr -d '[:space:]')
|
||||
else
|
||||
MODULE_VERSION="1.0.0"
|
||||
fi
|
||||
|
||||
echo "module_version=$MODULE_VERSION" >> "$GITHUB_OUTPUT"
|
||||
echo "module_lower=$MODULE_LOWER" >> "$GITHUB_OUTPUT"
|
||||
echo "Module: $MODULE_NAME, Version: $MODULE_VERSION"
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore ${{ matrix.module.project }}
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
dotnet build ${{ matrix.module.project }} \
|
||||
--configuration Release \
|
||||
--no-restore \
|
||||
-p:Version=${{ steps.version.outputs.module_version }}
|
||||
|
||||
- name: Pack NuGet
|
||||
run: |
|
||||
dotnet pack ${{ matrix.module.project }} \
|
||||
--configuration Release \
|
||||
--no-build \
|
||||
-p:Version=${{ steps.version.outputs.module_version }} \
|
||||
-p:PackageVersion=${{ steps.version.outputs.module_version }} \
|
||||
--output out/packages
|
||||
|
||||
- name: Push NuGet
|
||||
if: needs.validate.outputs.dry_run != 'true'
|
||||
run: |
|
||||
for nupkg in out/packages/*.nupkg; do
|
||||
if [[ -f "$nupkg" ]]; then
|
||||
echo "Pushing: $nupkg"
|
||||
dotnet nuget push "$nupkg" \
|
||||
--source "${{ env.NUGET_SOURCE }}" \
|
||||
--api-key "${{ secrets.GITEA_TOKEN }}" \
|
||||
--skip-duplicate
|
||||
fi
|
||||
done
|
||||
|
||||
- name: Upload NuGet artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: nuget-${{ matrix.module.name }}
|
||||
path: out/packages/*.nupkg
|
||||
retention-days: 30
|
||||
if-no-files-found: ignore
|
||||
|
||||
# ===========================================================================
|
||||
# BUILD CONTAINERS
|
||||
# ===========================================================================
|
||||
|
||||
build-containers:
|
||||
name: Container ${{ matrix.module }}
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate, build-modules]
|
||||
if: needs.validate.outputs.dry_run != 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
module:
|
||||
- authority
|
||||
- attestor
|
||||
- concelier
|
||||
- scanner
|
||||
- policy
|
||||
- signer
|
||||
- excititor
|
||||
- gateway
|
||||
- scheduler
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Gitea Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITEA_TOKEN }}
|
||||
|
||||
- name: Build and push container
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: devops/docker/Dockerfile.platform
|
||||
target: ${{ matrix.module }}
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/stella-ops.org/${{ matrix.module }}:${{ needs.validate.outputs.version }}
|
||||
${{ env.REGISTRY }}/stella-ops.org/${{ matrix.module }}:${{ needs.validate.outputs.channel }}
|
||||
${{ env.REGISTRY }}/stella-ops.org/${{ matrix.module }}:latest
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
labels: |
|
||||
org.opencontainers.image.title=StellaOps ${{ matrix.module }}
|
||||
org.opencontainers.image.version=${{ needs.validate.outputs.version }}
|
||||
org.opencontainers.image.description=StellaOps ${{ needs.validate.outputs.version }} ${{ needs.validate.outputs.codename }}
|
||||
org.opencontainers.image.source=https://git.stella-ops.org/stella-ops.org/git.stella-ops.org
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
|
||||
# ===========================================================================
|
||||
# BUILD CLI (multi-platform)
|
||||
# ===========================================================================
|
||||
|
||||
build-cli:
|
||||
name: CLI (${{ matrix.runtime }})
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate, test-gate]
|
||||
if: always() && needs.validate.result == 'success' && (needs.test-gate.result == 'success' || needs.test-gate.result == 'skipped')
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
runtime:
|
||||
- linux-x64
|
||||
- linux-arm64
|
||||
- win-x64
|
||||
- osx-x64
|
||||
- osx-arm64
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Install cross-compilation tools
|
||||
if: matrix.runtime == 'linux-arm64'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends binutils-aarch64-linux-gnu
|
||||
|
||||
- name: Publish CLI
|
||||
run: |
|
||||
dotnet publish src/Cli/StellaOps.Cli/StellaOps.Cli.csproj \
|
||||
--configuration Release \
|
||||
--runtime ${{ matrix.runtime }} \
|
||||
--self-contained true \
|
||||
-p:Version=${{ needs.validate.outputs.version }}.0 \
|
||||
-p:PublishSingleFile=true \
|
||||
-p:PublishTrimmed=true \
|
||||
-p:EnableCompressionInSingleFile=true \
|
||||
--output out/cli/${{ matrix.runtime }}
|
||||
|
||||
- name: Create archive
|
||||
run: |
|
||||
VERSION="${{ needs.validate.outputs.version }}"
|
||||
RUNTIME="${{ matrix.runtime }}"
|
||||
CODENAME="${{ needs.validate.outputs.codename }}"
|
||||
|
||||
cd out/cli/$RUNTIME
|
||||
if [[ "$RUNTIME" == win-* ]]; then
|
||||
zip -r "../stellaops-cli-${VERSION}-${CODENAME}-${RUNTIME}.zip" .
|
||||
else
|
||||
tar -czvf "../stellaops-cli-${VERSION}-${CODENAME}-${RUNTIME}.tar.gz" .
|
||||
fi
|
||||
|
||||
- name: Upload CLI artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: cli-${{ needs.validate.outputs.version }}-${{ matrix.runtime }}
|
||||
path: |
|
||||
out/cli/*.zip
|
||||
out/cli/*.tar.gz
|
||||
retention-days: 90
|
||||
|
||||
# ===========================================================================
|
||||
# BUILD HELM CHART
|
||||
# ===========================================================================
|
||||
|
||||
build-helm:
|
||||
name: Helm Chart
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Helm
|
||||
run: |
|
||||
curl -fsSL https://get.helm.sh/helm-v3.16.0-linux-amd64.tar.gz | \
|
||||
tar -xzf - -C /tmp
|
||||
sudo install -m 0755 /tmp/linux-amd64/helm /usr/local/bin/helm
|
||||
|
||||
- name: Lint Helm chart
|
||||
run: helm lint devops/helm/stellaops
|
||||
|
||||
- name: Package Helm chart
|
||||
run: |
|
||||
VERSION="${{ needs.validate.outputs.version }}"
|
||||
CODENAME="${{ needs.validate.outputs.codename }}"
|
||||
|
||||
helm package devops/helm/stellaops \
|
||||
--version "$VERSION" \
|
||||
--app-version "$VERSION" \
|
||||
--destination out/helm
|
||||
|
||||
- name: Upload Helm chart
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: helm-chart-${{ needs.validate.outputs.version }}
|
||||
path: out/helm/*.tgz
|
||||
retention-days: 90
|
||||
|
||||
# ===========================================================================
|
||||
# GENERATE RELEASE MANIFEST
|
||||
# ===========================================================================
|
||||
|
||||
release-manifest:
|
||||
name: Release Manifest
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate, build-modules, build-cli, build-helm]
|
||||
if: always() && needs.validate.result == 'success'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Generate release manifest
|
||||
run: |
|
||||
VERSION="${{ needs.validate.outputs.version }}"
|
||||
CODENAME="${{ needs.validate.outputs.codename }}"
|
||||
CHANNEL="${{ needs.validate.outputs.channel }}"
|
||||
|
||||
mkdir -p out/release
|
||||
|
||||
cat > out/release/suite-${VERSION}.yaml << EOF
|
||||
apiVersion: stellaops.org/v1
|
||||
kind: SuiteRelease
|
||||
metadata:
|
||||
version: "${VERSION}"
|
||||
codename: "${CODENAME}"
|
||||
channel: "${CHANNEL}"
|
||||
date: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
||||
gitSha: "${{ github.sha }}"
|
||||
gitRef: "${{ github.ref }}"
|
||||
spec:
|
||||
modules:
|
||||
authority: "1.0.0"
|
||||
attestor: "1.0.0"
|
||||
concelier: "1.0.0"
|
||||
scanner: "1.0.0"
|
||||
policy: "1.0.0"
|
||||
signer: "1.0.0"
|
||||
excititor: "1.0.0"
|
||||
gateway: "1.0.0"
|
||||
scheduler: "1.0.0"
|
||||
platforms:
|
||||
- linux-x64
|
||||
- linux-arm64
|
||||
- win-x64
|
||||
- osx-x64
|
||||
- osx-arm64
|
||||
artifacts:
|
||||
containers: "${{ env.REGISTRY }}/stella-ops.org/*:${VERSION}"
|
||||
nuget: "${{ env.NUGET_SOURCE }}"
|
||||
helm: "stellaops-${VERSION}.tgz"
|
||||
EOF
|
||||
|
||||
echo "=== Release Manifest ==="
|
||||
cat out/release/suite-${VERSION}.yaml
|
||||
|
||||
- name: Generate checksums
|
||||
run: |
|
||||
VERSION="${{ needs.validate.outputs.version }}"
|
||||
cd artifacts
|
||||
find . -type f \( -name "*.nupkg" -o -name "*.tgz" -o -name "*.zip" -o -name "*.tar.gz" \) \
|
||||
-exec sha256sum {} \; > ../out/release/SHA256SUMS-${VERSION}.txt
|
||||
|
||||
echo "=== Checksums ==="
|
||||
cat ../out/release/SHA256SUMS-${VERSION}.txt
|
||||
|
||||
- name: Upload release manifest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release-manifest-${{ needs.validate.outputs.version }}
|
||||
path: out/release
|
||||
retention-days: 90
|
||||
|
||||
# ===========================================================================
|
||||
# CREATE GITEA RELEASE
|
||||
# ===========================================================================
|
||||
|
||||
create-release:
|
||||
name: Create Gitea Release
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate, build-modules, build-containers, build-cli, build-helm, release-manifest]
|
||||
if: needs.validate.outputs.dry_run != 'true'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Prepare release assets
|
||||
run: |
|
||||
VERSION="${{ needs.validate.outputs.version }}"
|
||||
CODENAME="${{ needs.validate.outputs.codename }}"
|
||||
|
||||
mkdir -p release-assets
|
||||
|
||||
# Copy CLI archives
|
||||
find artifacts -name "*.zip" -exec cp {} release-assets/ \;
|
||||
find artifacts -name "*.tar.gz" -exec cp {} release-assets/ \;
|
||||
|
||||
# Copy Helm chart
|
||||
find artifacts -name "*.tgz" -exec cp {} release-assets/ \;
|
||||
|
||||
# Copy manifest and checksums
|
||||
find artifacts -name "suite-*.yaml" -exec cp {} release-assets/ \;
|
||||
find artifacts -name "SHA256SUMS-*.txt" -exec cp {} release-assets/ \;
|
||||
|
||||
ls -la release-assets/
|
||||
|
||||
- name: Generate release notes
|
||||
run: |
|
||||
VERSION="${{ needs.validate.outputs.version }}"
|
||||
CODENAME="${{ needs.validate.outputs.codename }}"
|
||||
CHANNEL="${{ needs.validate.outputs.channel }}"
|
||||
|
||||
cat > release-notes.md << 'EOF'
|
||||
## StellaOps ${{ needs.validate.outputs.version }} "${{ needs.validate.outputs.codename }}"
|
||||
|
||||
### Release Information
|
||||
- **Version:** ${{ needs.validate.outputs.version }}
|
||||
- **Codename:** ${{ needs.validate.outputs.codename }}
|
||||
- **Channel:** ${{ needs.validate.outputs.channel }}
|
||||
- **Date:** $(date -u +%Y-%m-%d)
|
||||
- **Git SHA:** ${{ github.sha }}
|
||||
|
||||
### Included Modules
|
||||
| Module | Version | Container |
|
||||
|--------|---------|-----------|
|
||||
| Authority | 1.0.0 | `${{ env.REGISTRY }}/stella-ops.org/authority:${{ needs.validate.outputs.version }}` |
|
||||
| Attestor | 1.0.0 | `${{ env.REGISTRY }}/stella-ops.org/attestor:${{ needs.validate.outputs.version }}` |
|
||||
| Concelier | 1.0.0 | `${{ env.REGISTRY }}/stella-ops.org/concelier:${{ needs.validate.outputs.version }}` |
|
||||
| Scanner | 1.0.0 | `${{ env.REGISTRY }}/stella-ops.org/scanner:${{ needs.validate.outputs.version }}` |
|
||||
| Policy | 1.0.0 | `${{ env.REGISTRY }}/stella-ops.org/policy:${{ needs.validate.outputs.version }}` |
|
||||
| Signer | 1.0.0 | `${{ env.REGISTRY }}/stella-ops.org/signer:${{ needs.validate.outputs.version }}` |
|
||||
| Excititor | 1.0.0 | `${{ env.REGISTRY }}/stella-ops.org/excititor:${{ needs.validate.outputs.version }}` |
|
||||
| Gateway | 1.0.0 | `${{ env.REGISTRY }}/stella-ops.org/gateway:${{ needs.validate.outputs.version }}` |
|
||||
| Scheduler | 1.0.0 | `${{ env.REGISTRY }}/stella-ops.org/scheduler:${{ needs.validate.outputs.version }}` |
|
||||
|
||||
### CLI Downloads
|
||||
| Platform | Download |
|
||||
|----------|----------|
|
||||
| Linux x64 | `stellaops-cli-${{ needs.validate.outputs.version }}-${{ needs.validate.outputs.codename }}-linux-x64.tar.gz` |
|
||||
| Linux ARM64 | `stellaops-cli-${{ needs.validate.outputs.version }}-${{ needs.validate.outputs.codename }}-linux-arm64.tar.gz` |
|
||||
| Windows x64 | `stellaops-cli-${{ needs.validate.outputs.version }}-${{ needs.validate.outputs.codename }}-win-x64.zip` |
|
||||
| macOS x64 | `stellaops-cli-${{ needs.validate.outputs.version }}-${{ needs.validate.outputs.codename }}-osx-x64.tar.gz` |
|
||||
| macOS ARM64 | `stellaops-cli-${{ needs.validate.outputs.version }}-${{ needs.validate.outputs.codename }}-osx-arm64.tar.gz` |
|
||||
|
||||
### Installation
|
||||
|
||||
#### Helm
|
||||
```bash
|
||||
helm install stellaops ./stellaops-${{ needs.validate.outputs.version }}.tgz
|
||||
```
|
||||
|
||||
#### Docker Compose
|
||||
```bash
|
||||
docker compose -f devops/compose/docker-compose.yml up -d
|
||||
```
|
||||
|
||||
---
|
||||
See [CHANGELOG.md](CHANGELOG.md) for detailed changes.
|
||||
EOF
|
||||
|
||||
- name: Create Gitea release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||
run: |
|
||||
VERSION="${{ needs.validate.outputs.version }}"
|
||||
CODENAME="${{ needs.validate.outputs.codename }}"
|
||||
CHANNEL="${{ needs.validate.outputs.channel }}"
|
||||
|
||||
# Determine if prerelease
|
||||
PRERELEASE_FLAG=""
|
||||
if [[ "$CHANNEL" == "edge" ]]; then
|
||||
PRERELEASE_FLAG="--prerelease"
|
||||
fi
|
||||
|
||||
gh release create "suite-${VERSION}" \
|
||||
--title "StellaOps ${VERSION} ${CODENAME}" \
|
||||
--notes-file release-notes.md \
|
||||
$PRERELEASE_FLAG \
|
||||
release-assets/*
|
||||
|
||||
# ===========================================================================
|
||||
# SUMMARY
|
||||
# ===========================================================================
|
||||
|
||||
summary:
|
||||
name: Release Summary
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [validate, build-modules, build-containers, build-cli, build-helm, release-manifest, create-release]
|
||||
if: always()
|
||||
steps:
|
||||
- name: Generate Summary
|
||||
run: |
|
||||
echo "## Suite Release Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Release Information" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Version | ${{ needs.validate.outputs.version }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Codename | ${{ needs.validate.outputs.codename }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Channel | ${{ needs.validate.outputs.channel }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Dry Run | ${{ needs.validate.outputs.dry_run }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Job Results" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Build Modules | ${{ needs.build-modules.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Build Containers | ${{ needs.build-containers.result || 'skipped' }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Build CLI | ${{ needs.build-cli.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Build Helm | ${{ needs.build-helm.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Release Manifest | ${{ needs.release-manifest.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Create Release | ${{ needs.create-release.result || 'skipped' }} |" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Check for failures
|
||||
if: contains(needs.*.result, 'failure')
|
||||
run: |
|
||||
echo "::error::One or more release jobs failed"
|
||||
exit 1
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'deploy/**'
|
||||
- 'devops/**'
|
||||
- 'scripts/release/**'
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -24,12 +24,12 @@ jobs:
|
||||
|
||||
- name: Validate Helm charts
|
||||
run: |
|
||||
helm lint deploy/helm/stellaops
|
||||
helm template stellaops deploy/helm/stellaops --dry-run
|
||||
helm lint devops/helm/stellaops
|
||||
helm template stellaops devops/helm/stellaops --dry-run
|
||||
|
||||
- name: Validate Kubernetes manifests
|
||||
run: |
|
||||
for f in deploy/k8s/*.yaml; do
|
||||
for f in devops/k8s/*.yaml; do
|
||||
kubectl apply --dry-run=client -f "$f" || exit 1
|
||||
done
|
||||
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
for img in "${REQUIRED_IMAGES[@]}"; do
|
||||
echo "Checking $img..."
|
||||
# Validate Dockerfile exists
|
||||
if [ ! -f "src/${img^}/Dockerfile" ] && [ ! -f "deploy/docker/${img}/Dockerfile" ]; then
|
||||
if [ ! -f "src/${img^}/Dockerfile" ] && [ ! -f "devops/docker/${img}/Dockerfile" ]; then
|
||||
echo "Warning: Dockerfile not found for $img"
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -45,13 +45,13 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Validate NuGet restore source ordering
|
||||
run: python3 ops/devops/validate_restore_sources.py
|
||||
run: python3 devops/validate_restore_sources.py
|
||||
|
||||
- name: Validate telemetry storage configuration
|
||||
run: python3 ops/devops/telemetry/validate_storage_stack.py
|
||||
run: python3 devops/telemetry/validate_storage_stack.py
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -198,7 +198,7 @@ jobs:
|
||||
|
||||
- name: Enforce CLI parity gate
|
||||
run: |
|
||||
python3 ops/devops/check_cli_parity.py
|
||||
python3 .gitea/scripts/release/check_cli_parity.py
|
||||
|
||||
- name: Log in to registry
|
||||
if: steps.meta.outputs.push == 'true'
|
||||
@@ -225,7 +225,7 @@ jobs:
|
||||
if [[ "${{ steps.meta.outputs.push }}" != "true" ]]; then
|
||||
EXTRA_ARGS+=("--no-push")
|
||||
fi
|
||||
./ops/devops/release/build_release.py \
|
||||
./.gitea/scripts/release/build_release.py \
|
||||
--version "${{ steps.meta.outputs.version }}" \
|
||||
--channel "${{ steps.meta.outputs.channel }}" \
|
||||
--calendar "${{ steps.meta.outputs.calendar }}" \
|
||||
@@ -234,7 +234,7 @@ jobs:
|
||||
|
||||
- name: Verify release artefacts
|
||||
run: |
|
||||
python ops/devops/release/verify_release.py --release-dir out/release
|
||||
python .gitea/scripts/release/verify_release.py --release-dir out/release
|
||||
|
||||
- name: Upload release artefacts
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
@@ -6,7 +6,7 @@ on:
|
||||
paths:
|
||||
- 'src/ExportCenter/StellaOps.ExportCenter.RiskBundles/**'
|
||||
- 'src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Worker/**'
|
||||
- 'ops/devops/risk-bundle/**'
|
||||
- 'devops/risk-bundle/**'
|
||||
- '.gitea/workflows/risk-bundle-ci.yml'
|
||||
- 'docs/modules/export-center/operations/risk-bundle-*.md'
|
||||
pull_request:
|
||||
@@ -14,7 +14,7 @@ on:
|
||||
paths:
|
||||
- 'src/ExportCenter/StellaOps.ExportCenter.RiskBundles/**'
|
||||
- 'src/ExportCenter/StellaOps.ExportCenter/StellaOps.ExportCenter.Worker/**'
|
||||
- 'ops/devops/risk-bundle/**'
|
||||
- 'devops/risk-bundle/**'
|
||||
- '.gitea/workflows/risk-bundle-ci.yml'
|
||||
- 'docs/modules/export-center/operations/risk-bundle-*.md'
|
||||
workflow_dispatch:
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Export OpenSSL 1.1 shim for Mongo2Go
|
||||
run: scripts/enable-openssl11-shim.sh
|
||||
run: .gitea/scripts/util/enable-openssl11-shim.sh
|
||||
|
||||
- name: Set up .NET SDK
|
||||
uses: actions/setup-dotnet@v4
|
||||
@@ -68,10 +68,10 @@ jobs:
|
||||
- name: Build risk bundle (fixtures)
|
||||
run: |
|
||||
mkdir -p $BUNDLE_OUTPUT
|
||||
ops/devops/risk-bundle/build-bundle.sh --output "$BUNDLE_OUTPUT" --fixtures-only
|
||||
devops/risk-bundle/build-bundle.sh --output "$BUNDLE_OUTPUT" --fixtures-only
|
||||
|
||||
- name: Verify bundle integrity
|
||||
run: ops/devops/risk-bundle/verify-bundle.sh "$BUNDLE_OUTPUT/risk-bundle.tar.gz"
|
||||
run: devops/risk-bundle/verify-bundle.sh "$BUNDLE_OUTPUT/risk-bundle.tar.gz"
|
||||
|
||||
- name: Generate checksums
|
||||
run: |
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
@@ -19,8 +19,8 @@ jobs:
|
||||
|
||||
- name: Run determinism harness
|
||||
run: |
|
||||
chmod +x scripts/scanner/determinism-run.sh
|
||||
scripts/scanner/determinism-run.sh
|
||||
chmod +x .gitea/scripts/test/determinism-run.sh
|
||||
.gitea/scripts/test/determinism-run.sh
|
||||
|
||||
- name: Upload determinism artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
||||
@@ -4,14 +4,14 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'src/Sdk/**'
|
||||
- 'ops/devops/sdk/**'
|
||||
- 'devops/sdk/**'
|
||||
- 'scripts/sdk/**'
|
||||
- '.gitea/workflows/sdk-publish.yml'
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'src/Sdk/**'
|
||||
- 'ops/devops/sdk/**'
|
||||
- 'devops/sdk/**'
|
||||
- 'scripts/sdk/**'
|
||||
- '.gitea/workflows/sdk-publish.yml'
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup .NET 10 RC
|
||||
uses: actions/setup-dotnet@v4
|
||||
|
||||
@@ -5,7 +5,7 @@ on:
|
||||
paths:
|
||||
- 'src/Signals/**'
|
||||
- '.gitea/workflows/signals-ci.yml'
|
||||
- 'ops/devops/signals/**'
|
||||
- 'devops/signals/**'
|
||||
- 'helm/signals/**'
|
||||
- 'scripts/signals/**'
|
||||
push:
|
||||
@@ -13,7 +13,7 @@ on:
|
||||
paths:
|
||||
- 'src/Signals/**'
|
||||
- '.gitea/workflows/signals-ci.yml'
|
||||
- 'ops/devops/signals/**'
|
||||
- 'devops/signals/**'
|
||||
- 'helm/signals/**'
|
||||
- 'scripts/signals/**'
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup .NET 10 RC
|
||||
uses: actions/setup-dotnet@v4
|
||||
|
||||
@@ -18,7 +18,7 @@ on:
|
||||
- 'docs/modules/signals/unknowns/**'
|
||||
- 'docs/modules/signals/heuristics/**'
|
||||
- 'docs/modules/signals/SHA256SUMS'
|
||||
- 'tools/cosign/sign-signals.sh'
|
||||
- '.gitea/scripts/sign/sign-signals.sh'
|
||||
|
||||
jobs:
|
||||
sign-signals-artifacts:
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Install cosign
|
||||
uses: sigstore/cosign-installer@v3
|
||||
@@ -77,8 +77,8 @@ jobs:
|
||||
|
||||
- name: Sign signals artifacts
|
||||
run: |
|
||||
chmod +x tools/cosign/sign-signals.sh
|
||||
OUT_DIR="${OUT_DIR}" tools/cosign/sign-signals.sh
|
||||
chmod +x .gitea/scripts/sign/sign-signals.sh
|
||||
OUT_DIR="${OUT_DIR}" .gitea/scripts/sign/sign-signals.sh
|
||||
|
||||
- name: Verify signatures
|
||||
run: |
|
||||
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Install cosign
|
||||
uses: sigstore/cosign-installer@v3
|
||||
@@ -55,8 +55,8 @@ jobs:
|
||||
|
||||
- name: Sign signals artifacts
|
||||
run: |
|
||||
chmod +x tools/cosign/sign-signals.sh
|
||||
OUT_DIR="${OUT_DIR}" tools/cosign/sign-signals.sh
|
||||
chmod +x .gitea/scripts/sign/sign-signals.sh
|
||||
OUT_DIR="${OUT_DIR}" .gitea/scripts/sign/sign-signals.sh
|
||||
|
||||
- name: Build deterministic signals evidence tar
|
||||
run: |
|
||||
|
||||
@@ -17,7 +17,7 @@ on:
|
||||
- 'src/Signals/**'
|
||||
- 'scripts/signals/reachability-smoke.sh'
|
||||
- '.gitea/workflows/signals-reachability.yml'
|
||||
- 'tools/cosign/sign-signals.sh'
|
||||
- '.gitea/scripts/sign/sign-signals.sh'
|
||||
|
||||
jobs:
|
||||
reachability-smoke:
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup .NET 10 RC
|
||||
uses: actions/setup-dotnet@v4
|
||||
@@ -70,7 +70,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Install cosign
|
||||
uses: sigstore/cosign-installer@v3
|
||||
@@ -94,8 +94,8 @@ jobs:
|
||||
|
||||
- name: Sign signals artifacts
|
||||
run: |
|
||||
chmod +x tools/cosign/sign-signals.sh
|
||||
OUT_DIR="${OUT_DIR}" tools/cosign/sign-signals.sh
|
||||
chmod +x .gitea/scripts/sign/sign-signals.sh
|
||||
OUT_DIR="${OUT_DIR}" .gitea/scripts/sign/sign-signals.sh
|
||||
|
||||
- name: Upload signed artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
@@ -4,13 +4,13 @@ on:
|
||||
push:
|
||||
branches: [ main ]
|
||||
paths:
|
||||
- 'ops/devops/symbols/**'
|
||||
- 'devops/symbols/**'
|
||||
- 'scripts/symbols/**'
|
||||
- '.gitea/workflows/symbols-ci.yml'
|
||||
pull_request:
|
||||
branches: [ main, develop ]
|
||||
paths:
|
||||
- 'ops/devops/symbols/**'
|
||||
- 'devops/symbols/**'
|
||||
- 'scripts/symbols/**'
|
||||
- '.gitea/workflows/symbols-ci.yml'
|
||||
workflow_dispatch: {}
|
||||
@@ -27,10 +27,10 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Export OpenSSL 1.1 shim for Mongo2Go
|
||||
run: scripts/enable-openssl11-shim.sh
|
||||
run: .gitea/scripts/util/enable-openssl11-shim.sh
|
||||
|
||||
- name: Run Symbols.Server smoke
|
||||
run: |
|
||||
|
||||
@@ -18,10 +18,10 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Export OpenSSL 1.1 shim for Mongo2Go
|
||||
run: scripts/enable-openssl11-shim.sh
|
||||
run: .gitea/scripts/util/enable-openssl11-shim.sh
|
||||
|
||||
- name: Run Symbols.Server smoke
|
||||
env:
|
||||
|
||||
510
.gitea/workflows/test-matrix.yml
Normal file
510
.gitea/workflows/test-matrix.yml
Normal file
@@ -0,0 +1,510 @@
|
||||
# .gitea/workflows/test-matrix.yml
|
||||
# Unified test matrix pipeline with TRX reporting for all test categories
|
||||
# Sprint: SPRINT_20251226_003_CICD
|
||||
|
||||
name: Test Matrix
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '*.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '*.md'
|
||||
schedule:
|
||||
- cron: '0 5 * * *' # Daily at 5 AM UTC
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
include_performance:
|
||||
description: 'Include performance tests'
|
||||
type: boolean
|
||||
default: false
|
||||
include_benchmark:
|
||||
description: 'Include benchmark tests'
|
||||
type: boolean
|
||||
default: false
|
||||
include_airgap:
|
||||
description: 'Include airgap tests'
|
||||
type: boolean
|
||||
default: false
|
||||
include_chaos:
|
||||
description: 'Include chaos tests'
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
env:
|
||||
DOTNET_VERSION: '10.0.100'
|
||||
DOTNET_NOLOGO: 1
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT: 1
|
||||
TZ: UTC
|
||||
|
||||
jobs:
|
||||
# ===========================================================================
|
||||
# PR-GATING TESTS (run on every push/PR)
|
||||
# ===========================================================================
|
||||
|
||||
unit:
|
||||
name: Unit Tests
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore src/StellaOps.sln
|
||||
|
||||
- name: Build
|
||||
run: dotnet build src/StellaOps.sln -c Release --no-restore
|
||||
|
||||
- name: Run Unit Tests
|
||||
run: |
|
||||
dotnet test src/StellaOps.sln \
|
||||
--filter "Category=Unit" \
|
||||
--configuration Release \
|
||||
--no-build \
|
||||
--logger "trx;LogFileName=unit-tests.trx" \
|
||||
--results-directory ./TestResults/Unit \
|
||||
--collect:"XPlat Code Coverage"
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: test-results-unit
|
||||
path: ./TestResults/Unit
|
||||
retention-days: 14
|
||||
|
||||
architecture:
|
||||
name: Architecture Tests
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore src/StellaOps.sln
|
||||
|
||||
- name: Build
|
||||
run: dotnet build src/StellaOps.sln -c Release --no-restore
|
||||
|
||||
- name: Run Architecture Tests
|
||||
run: |
|
||||
dotnet test src/StellaOps.sln \
|
||||
--filter "Category=Architecture" \
|
||||
--configuration Release \
|
||||
--no-build \
|
||||
--logger "trx;LogFileName=architecture-tests.trx" \
|
||||
--results-directory ./TestResults/Architecture
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: test-results-architecture
|
||||
path: ./TestResults/Architecture
|
||||
retention-days: 14
|
||||
|
||||
contract:
|
||||
name: Contract Tests
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore src/StellaOps.sln
|
||||
|
||||
- name: Build
|
||||
run: dotnet build src/StellaOps.sln -c Release --no-restore
|
||||
|
||||
- name: Run Contract Tests
|
||||
run: |
|
||||
dotnet test src/StellaOps.sln \
|
||||
--filter "Category=Contract" \
|
||||
--configuration Release \
|
||||
--no-build \
|
||||
--logger "trx;LogFileName=contract-tests.trx" \
|
||||
--results-directory ./TestResults/Contract
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: test-results-contract
|
||||
path: ./TestResults/Contract
|
||||
retention-days: 14
|
||||
|
||||
integration:
|
||||
name: Integration Tests
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 30
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16
|
||||
env:
|
||||
POSTGRES_USER: stellaops
|
||||
POSTGRES_PASSWORD: stellaops
|
||||
POSTGRES_DB: stellaops_test
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore src/StellaOps.sln
|
||||
|
||||
- name: Build
|
||||
run: dotnet build src/StellaOps.sln -c Release --no-restore
|
||||
|
||||
- name: Run Integration Tests
|
||||
env:
|
||||
STELLAOPS_TEST_POSTGRES_CONNECTION: "Host=localhost;Port=5432;Database=stellaops_test;Username=stellaops;Password=stellaops"
|
||||
run: |
|
||||
dotnet test src/StellaOps.sln \
|
||||
--filter "Category=Integration" \
|
||||
--configuration Release \
|
||||
--no-build \
|
||||
--logger "trx;LogFileName=integration-tests.trx" \
|
||||
--results-directory ./TestResults/Integration
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: test-results-integration
|
||||
path: ./TestResults/Integration
|
||||
retention-days: 14
|
||||
|
||||
security:
|
||||
name: Security Tests
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore src/StellaOps.sln
|
||||
|
||||
- name: Build
|
||||
run: dotnet build src/StellaOps.sln -c Release --no-restore
|
||||
|
||||
- name: Run Security Tests
|
||||
run: |
|
||||
dotnet test src/StellaOps.sln \
|
||||
--filter "Category=Security" \
|
||||
--configuration Release \
|
||||
--no-build \
|
||||
--logger "trx;LogFileName=security-tests.trx" \
|
||||
--results-directory ./TestResults/Security
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: test-results-security
|
||||
path: ./TestResults/Security
|
||||
retention-days: 14
|
||||
|
||||
golden:
|
||||
name: Golden Tests
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore src/StellaOps.sln
|
||||
|
||||
- name: Build
|
||||
run: dotnet build src/StellaOps.sln -c Release --no-restore
|
||||
|
||||
- name: Run Golden Tests
|
||||
run: |
|
||||
dotnet test src/StellaOps.sln \
|
||||
--filter "Category=Golden" \
|
||||
--configuration Release \
|
||||
--no-build \
|
||||
--logger "trx;LogFileName=golden-tests.trx" \
|
||||
--results-directory ./TestResults/Golden
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: test-results-golden
|
||||
path: ./TestResults/Golden
|
||||
retention-days: 14
|
||||
|
||||
# ===========================================================================
|
||||
# SCHEDULED/ON-DEMAND TESTS
|
||||
# ===========================================================================
|
||||
|
||||
performance:
|
||||
name: Performance Tests
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 30
|
||||
if: github.event_name == 'schedule' || github.event.inputs.include_performance == 'true'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore src/StellaOps.sln
|
||||
|
||||
- name: Build
|
||||
run: dotnet build src/StellaOps.sln -c Release --no-restore
|
||||
|
||||
- name: Run Performance Tests
|
||||
run: |
|
||||
dotnet test src/StellaOps.sln \
|
||||
--filter "Category=Performance" \
|
||||
--configuration Release \
|
||||
--no-build \
|
||||
--logger "trx;LogFileName=performance-tests.trx" \
|
||||
--results-directory ./TestResults/Performance
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: test-results-performance
|
||||
path: ./TestResults/Performance
|
||||
retention-days: 14
|
||||
|
||||
benchmark:
|
||||
name: Benchmark Tests
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 45
|
||||
if: github.event_name == 'schedule' || github.event.inputs.include_benchmark == 'true'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore src/StellaOps.sln
|
||||
|
||||
- name: Build
|
||||
run: dotnet build src/StellaOps.sln -c Release --no-restore
|
||||
|
||||
- name: Run Benchmark Tests
|
||||
run: |
|
||||
dotnet test src/StellaOps.sln \
|
||||
--filter "Category=Benchmark" \
|
||||
--configuration Release \
|
||||
--no-build \
|
||||
--logger "trx;LogFileName=benchmark-tests.trx" \
|
||||
--results-directory ./TestResults/Benchmark
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: test-results-benchmark
|
||||
path: ./TestResults/Benchmark
|
||||
retention-days: 14
|
||||
|
||||
airgap:
|
||||
name: AirGap Tests
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 30
|
||||
if: github.event.inputs.include_airgap == 'true'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore src/StellaOps.sln
|
||||
|
||||
- name: Build
|
||||
run: dotnet build src/StellaOps.sln -c Release --no-restore
|
||||
|
||||
- name: Run AirGap Tests
|
||||
run: |
|
||||
dotnet test src/StellaOps.sln \
|
||||
--filter "Category=AirGap" \
|
||||
--configuration Release \
|
||||
--no-build \
|
||||
--logger "trx;LogFileName=airgap-tests.trx" \
|
||||
--results-directory ./TestResults/AirGap
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: test-results-airgap
|
||||
path: ./TestResults/AirGap
|
||||
retention-days: 14
|
||||
|
||||
chaos:
|
||||
name: Chaos Tests
|
||||
runs-on: ubuntu-22.04
|
||||
timeout-minutes: 30
|
||||
if: github.event.inputs.include_chaos == 'true'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
include-prerelease: true
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore src/StellaOps.sln
|
||||
|
||||
- name: Build
|
||||
run: dotnet build src/StellaOps.sln -c Release --no-restore
|
||||
|
||||
- name: Run Chaos Tests
|
||||
run: |
|
||||
dotnet test src/StellaOps.sln \
|
||||
--filter "Category=Chaos" \
|
||||
--configuration Release \
|
||||
--no-build \
|
||||
--logger "trx;LogFileName=chaos-tests.trx" \
|
||||
--results-directory ./TestResults/Chaos
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: test-results-chaos
|
||||
path: ./TestResults/Chaos
|
||||
retention-days: 14
|
||||
|
||||
# ===========================================================================
|
||||
# SUMMARY JOB
|
||||
# ===========================================================================
|
||||
|
||||
summary:
|
||||
name: Test Summary
|
||||
runs-on: ubuntu-22.04
|
||||
needs: [unit, architecture, contract, integration, security, golden]
|
||||
if: always()
|
||||
steps:
|
||||
- name: Download all test results
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
pattern: test-results-*
|
||||
path: ./TestResults
|
||||
|
||||
- name: Install trx2junit
|
||||
run: dotnet tool install -g trx2junit
|
||||
|
||||
- name: Convert TRX to JUnit
|
||||
run: |
|
||||
find ./TestResults -name "*.trx" -exec trx2junit {} \; || true
|
||||
|
||||
- name: Generate Summary
|
||||
run: |
|
||||
echo "## Test Results Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Category | Status |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|----------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Unit | ${{ needs.unit.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Architecture | ${{ needs.architecture.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Contract | ${{ needs.contract.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Integration | ${{ needs.integration.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Security | ${{ needs.security.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Golden | ${{ needs.golden.result }} |" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
- name: Upload Combined Results
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-results-combined
|
||||
path: ./TestResults
|
||||
retention-days: 14
|
||||
|
||||
- name: Check for failures
|
||||
if: contains(needs.*.result, 'failure')
|
||||
run: exit 1
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Task Pack offline bundle fixtures
|
||||
run: python3 scripts/packs/run-fixtures-check.sh
|
||||
run: python3 .gitea/scripts/test/run-fixtures-check.sh
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
|
||||
73
CLAUDE.md
73
CLAUDE.md
@@ -53,7 +53,13 @@ npm run api:lint
|
||||
npm run docs:attestor:validate
|
||||
|
||||
# Validate Helm chart
|
||||
helm lint deploy/helm/stellaops
|
||||
helm lint devops/helm/stellaops
|
||||
|
||||
# Validate Docker Compose profiles
|
||||
./devops/scripts/validate-compose.sh
|
||||
|
||||
# Run local CI tests
|
||||
./devops/scripts/test-local.sh
|
||||
```
|
||||
|
||||
## Architecture
|
||||
@@ -249,11 +255,66 @@ Before coding, confirm required docs are read:
|
||||
|
||||
## CI/CD
|
||||
|
||||
Workflows are in `.gitea/workflows/`. Key workflows:
|
||||
- `build-test-deploy.yml` - Main build, test, and deployment pipeline
|
||||
- `cli-build.yml` - CLI multi-platform builds
|
||||
- `scanner-determinism.yml` - Scanner output reproducibility tests
|
||||
- `policy-lint.yml` - Policy validation
|
||||
### Folder Structure
|
||||
|
||||
The CI/CD infrastructure uses a two-tier organization:
|
||||
|
||||
| Folder | Purpose |
|
||||
|--------|---------|
|
||||
| `.gitea/workflows/` | Gitea Actions workflow YAML files (87+) |
|
||||
| `.gitea/scripts/` | CI/CD scripts called by workflows |
|
||||
| `devops/` | Deployment, tooling, and operational configs |
|
||||
|
||||
### CI/CD Scripts (`.gitea/scripts/`)
|
||||
|
||||
```
|
||||
.gitea/scripts/
|
||||
├── build/ # Build orchestration (build-cli.sh, build-multiarch.sh)
|
||||
├── test/ # Test execution (test-lane.sh, determinism-run.sh)
|
||||
├── validate/ # Validation (validate-sbom.sh, validate-helm.sh)
|
||||
├── sign/ # Signing (sign-signals.sh, publish-attestation.sh)
|
||||
├── release/ # Release automation (build_release.py, verify_release.py)
|
||||
├── metrics/ # Performance metrics (compute-reachability-metrics.sh)
|
||||
├── evidence/ # Evidence bundles (upload-all-evidence.sh)
|
||||
└── util/ # Utilities (cleanup-runner-space.sh)
|
||||
```
|
||||
|
||||
### DevOps Folder (`devops/`)
|
||||
|
||||
```
|
||||
devops/
|
||||
├── compose/ # Docker Compose profiles (dev, stage, prod, airgap)
|
||||
├── helm/ # Helm charts (stellaops)
|
||||
├── docker/ # Dockerfiles (platform, crypto-profile, ci)
|
||||
├── telemetry/ # OpenTelemetry, Prometheus, Grafana configs
|
||||
├── services/ # Service-specific configs (authority, crypto, signals)
|
||||
├── offline/ # Air-gap and offline deployment
|
||||
├── observability/ # Alerts, SLOs, incident management
|
||||
├── database/ # PostgreSQL and MongoDB configs
|
||||
├── ansible/ # Ansible playbooks
|
||||
├── gitlab/ # GitLab CI templates
|
||||
├── releases/ # Release manifests
|
||||
├── tools/ # Development tools (callgraph, corpus, feeds)
|
||||
└── scripts/ # DevOps scripts (test-local.sh, validate-compose.sh)
|
||||
```
|
||||
|
||||
### Key Workflows
|
||||
|
||||
| Workflow | Purpose |
|
||||
|----------|---------|
|
||||
| `build-test-deploy.yml` | Main build, test, and deployment pipeline |
|
||||
| `test-matrix.yml` | Unified test execution with TRX reporting |
|
||||
| `module-publish.yml` | Per-module NuGet and container publishing |
|
||||
| `release-suite.yml` | Full suite release (Ubuntu-style versioning) |
|
||||
| `cli-build.yml` | CLI multi-platform builds |
|
||||
| `scanner-determinism.yml` | Scanner output reproducibility tests |
|
||||
| `policy-lint.yml` | Policy validation |
|
||||
|
||||
### Versioning
|
||||
|
||||
- **Suite releases**: Ubuntu-style `YYYY.MM` with codenames (e.g., "2026.04 Nova")
|
||||
- **Module releases**: Semantic versioning `MAJOR.MINOR.PATCH`
|
||||
- See `docs/releases/VERSIONING.md` for full documentation
|
||||
|
||||
## Environment Variables
|
||||
|
||||
|
||||
@@ -6,6 +6,21 @@
|
||||
<RestoreConfigFile Condition="'$(RestoreConfigFile)' == ''">$([System.IO.Path]::Combine('$(StellaOpsRepoRoot)','NuGet.config'))</RestoreConfigFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Package metadata for NuGet publishing -->
|
||||
<PropertyGroup>
|
||||
<Authors>StellaOps</Authors>
|
||||
<Company>StellaOps</Company>
|
||||
<Product>StellaOps</Product>
|
||||
<Copyright>Copyright (c) StellaOps. All rights reserved.</Copyright>
|
||||
<PackageLicenseExpression>AGPL-3.0-or-later</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://git.stella-ops.org/stella-ops.org/git.stella-ops.org</PackageProjectUrl>
|
||||
<RepositoryUrl>https://git.stella-ops.org/stella-ops.org/git.stella-ops.org</RepositoryUrl>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<PackageReadmeFile Condition="Exists('README.md')">README.md</PackageReadmeFile>
|
||||
<PackageTags>stellaops;security;sbom;vex;attestation;supply-chain</PackageTags>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<StellaOpsEnableCryptoPro Condition="'$(StellaOpsEnableCryptoPro)' == ''">false</StellaOpsEnableCryptoPro>
|
||||
<NoWarn>$(NoWarn);NU1608;NU1605;NU1202</NoWarn>
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<packageSources>
|
||||
<clear />
|
||||
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
<add key="stellaops" value="https://git.stella-ops.org/api/packages/stella-ops.org/nuget/index.json" />
|
||||
</packageSources>
|
||||
<fallbackPackageFolders>
|
||||
<clear />
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user