CD/CD consolidation
This commit is contained in:
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
|
||||
Reference in New Issue
Block a user