CD/CD consolidation

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

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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

View File

@@ -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:

View File

@@ -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: |

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -6,7 +6,7 @@ on:
paths:
- 'src/Web/**'
- '.gitea/workflows/console-ci.yml'
- 'ops/devops/console/**'
- 'devops/console/**'
jobs:
lint-test-build:

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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: |

View File

@@ -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

View File

@@ -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: |

View File

@@ -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

View File

@@ -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

View File

@@ -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: |

View File

@@ -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: |

View File

@@ -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

View File

@@ -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)"

View File

@@ -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: |

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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: |

View File

@@ -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

View File

@@ -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: |

View File

@@ -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

View File

@@ -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: |

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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: |

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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: |

View File

@@ -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: |

View File

@@ -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

View File

@@ -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: |

View File

@@ -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:

View 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

View File

@@ -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