From cdff2ffd4620cb62f496b92eb89e900835ac14f5 Mon Sep 17 00:00:00 2001 From: "@tanya_r" Date: Sun, 28 Jun 2026 20:33:38 -0300 Subject: [PATCH] ci(release): rebuild release workflow with image matrix, umbrella chart and sbom build all five service images from the root Dockerfile via ARG SERVICE plus the web image, sign each with cosign, and package a new fincore-engine umbrella helm chart over the ledger, payments and web sub-charts. wire the cyclonedx gradle plugin so cyclonedxBom emits an aggregate SBOM, and validate the umbrella chart in helm-test ci. replace the tag-incompatible release-please step with action-gh-release. --- .github/workflows/helm-test.yml | 37 +++++ .github/workflows/release.yml | 153 +++++++++++++----- build.gradle.kts | 1 + deploy/helm/fincore-engine/.helmignore | 9 ++ deploy/helm/fincore-engine/Chart.yaml | 24 +++ .../helm/fincore-engine/templates/NOTES.txt | 19 +++ deploy/helm/fincore-engine/values.yaml | 13 ++ gradle/libs.versions.toml | 2 + 8 files changed, 217 insertions(+), 41 deletions(-) create mode 100644 deploy/helm/fincore-engine/.helmignore create mode 100644 deploy/helm/fincore-engine/Chart.yaml create mode 100644 deploy/helm/fincore-engine/templates/NOTES.txt create mode 100644 deploy/helm/fincore-engine/values.yaml diff --git a/.github/workflows/helm-test.yml b/.github/workflows/helm-test.yml index 96b099f..0696c34 100644 --- a/.github/workflows/helm-test.yml +++ b/.github/workflows/helm-test.yml @@ -63,3 +63,40 @@ jobs: --set image.tag=test --set serviceMonitor.enabled=true) echo "$rendered" | grep -q 'kind: ServiceMonitor' echo "$rendered" | kubeconform -strict -summary -skip ServiceMonitor -kubernetes-version "$KUBERNETES_VERSION" + + umbrella-test: + name: Umbrella Lint & Validate + runs-on: ubuntu-latest + + permissions: + contents: read + + env: + KUBECONFORM_VERSION: v0.6.7 + KUBERNETES_VERSION: "1.31.0" + + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Set up Helm + uses: azure/setup-helm@v5 + with: + version: "v3.16.4" + + - name: Build chart dependencies + run: helm dependency build deploy/helm/fincore-engine + + - name: Helm lint + run: helm lint deploy/helm/fincore-engine + + - name: Install kubeconform + run: | + curl -sSL "https://github.com/yannh/kubeconform/releases/download/${KUBECONFORM_VERSION}/kubeconform-linux-amd64.tar.gz" \ + | tar -xz kubeconform + sudo mv kubeconform /usr/local/bin/ + + - name: Helm template and validate manifests + run: | + helm template fincore deploy/helm/fincore-engine \ + | kubeconform -strict -summary -skip ServiceMonitor -kubernetes-version "$KUBERNETES_VERSION" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1187a8f..4296586 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,20 +10,12 @@ concurrency: cancel-in-progress: false permissions: - contents: write - packages: write - id-token: write + contents: read jobs: - release: - name: Build, Push & Release + test: + name: Test gate runs-on: ubuntu-latest - - permissions: - contents: write - packages: write - id-token: write - steps: - name: Checkout uses: actions/checkout@v7 @@ -42,16 +34,46 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew + - name: Run tests + run: ./gradlew test integrationTest --no-daemon + + images: + name: Build & sign ${{ matrix.image }} + needs: test + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + id-token: write + + strategy: + fail-fast: false + matrix: + include: + - { image: fincore-ledger, context: ".", file: Dockerfile, build_args: "SERVICE=ledger" } + - { image: fincore-payments, context: ".", file: Dockerfile, build_args: "SERVICE=payments" } + - { image: fincore-compliance, context: ".", file: Dockerfile, build_args: "SERVICE=compliance" } + - { image: fincore-decision, context: ".", file: Dockerfile, build_args: "SERVICE=decision" } + - { image: fincore-web, context: "web", file: web/Dockerfile, build_args: "" } + + steps: + - name: Checkout + uses: actions/checkout@v7 + - name: Extract version from tag id: version run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" - - name: Run tests - run: ./gradlew test integrationTest --no-daemon - - name: Install cosign uses: sigstore/cosign-installer@v3 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + - name: Log in to GitHub Container Registry uses: docker/login-action@v4 with: @@ -59,67 +81,116 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 - - - name: Build and push ledger-service Docker image - id: docker-build-ledger + - name: Build and push image + id: build uses: docker/build-push-action@v7 with: - context: services/ledger - file: services/ledger/Dockerfile + context: ${{ matrix.context }} + file: ${{ matrix.file }} + build-args: ${{ matrix.build_args }} push: true platforms: linux/amd64,linux/arm64 tags: | - ghcr.io/tiana-code/fincore-ledger:${{ steps.version.outputs.version }} - ghcr.io/tiana-code/fincore-ledger:latest + ghcr.io/tiana-code/${{ matrix.image }}:${{ steps.version.outputs.version }} + ghcr.io/tiana-code/${{ matrix.image }}:latest labels: | org.opencontainers.image.source=https://github.com/tiana-code/fincore-engine org.opencontainers.image.version=${{ steps.version.outputs.version }} org.opencontainers.image.licenses=BUSL-1.1 - cache-from: type=gha - cache-to: type=gha,mode=max + cache-from: type=gha,scope=${{ matrix.image }} + cache-to: type=gha,mode=max,scope=${{ matrix.image }} - - name: Sign Docker image (ledger-service) with cosign + - name: Sign image with cosign (keyless) run: | cosign sign --yes \ - ghcr.io/tiana-code/fincore-ledger@${{ steps.docker-build-ledger.outputs.digest }} + ghcr.io/tiana-code/${{ matrix.image }}@${{ steps.build.outputs.digest }} + + helm: + name: Package & sign Helm umbrella chart + needs: test + runs-on: ubuntu-latest + + permissions: + contents: read + packages: write + id-token: write + + steps: + - name: Checkout + uses: actions/checkout@v7 + + - name: Extract version from tag + id: version + run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" - name: Set up Helm uses: azure/setup-helm@v5 with: version: "v3.16.4" - - name: Package Helm chart + - name: Install cosign + uses: sigstore/cosign-installer@v3 + + - name: Log in to GHCR for Helm OCI + run: | + echo "${{ secrets.GITHUB_TOKEN }}" \ + | helm registry login ghcr.io --username "${{ github.actor }}" --password-stdin + + - name: Build chart dependencies + run: helm dependency build deploy/helm/fincore-engine + + - name: Package Helm umbrella chart run: | helm package deploy/helm/fincore-engine \ - --version ${{ steps.version.outputs.version }} \ - --app-version ${{ steps.version.outputs.version }} \ + --version "${{ steps.version.outputs.version }}" \ + --app-version "${{ steps.version.outputs.version }}" \ --destination /tmp/helm-packages - name: Push Helm chart to GHCR OCI registry run: | - helm push /tmp/helm-packages/fincore-engine-${{ steps.version.outputs.version }}.tgz \ + helm push "/tmp/helm-packages/fincore-engine-${{ steps.version.outputs.version }}.tgz" \ oci://ghcr.io/tiana-code/charts - - name: Sign Helm chart with cosign + - name: Sign Helm chart with cosign (keyless) run: | cosign sign --yes \ ghcr.io/tiana-code/charts/fincore-engine:${{ steps.version.outputs.version }} - - name: Generate SBOM (CycloneDX) - run: ./gradlew cyclonedxBom --no-daemon + release: + name: SBOM & GitHub release + needs: [images, helm] + runs-on: ubuntu-latest + + permissions: + contents: write - - name: Create GitHub Release - uses: googleapis/release-please-action@v5 + steps: + - name: Checkout + uses: actions/checkout@v7 with: - token: ${{ secrets.GITHUB_TOKEN }} - release-type: simple - config-file: .github/release-please-config.json + fetch-depth: 0 + + - name: Set up JDK 21 (Temurin) + uses: actions/setup-java@v5 + with: + java-version: "21" + distribution: temurin + + - name: Set up Gradle + uses: gradle/actions/setup-gradle@v6 + + - name: Grant execute permission for gradlew + run: chmod +x gradlew + + - name: Generate SBOM (CycloneDX aggregate) + run: ./gradlew cyclonedxBom --no-daemon - - name: Upload SBOM to release + - name: Create GitHub release uses: softprops/action-gh-release@v3 with: - files: "**/build/reports/bom.json" + generate_release_notes: true + files: | + build/reports/cyclonedx/bom.json + build/reports/cyclonedx/bom.xml env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/build.gradle.kts b/build.gradle.kts index d55d320..719cd58 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -11,6 +11,7 @@ plugins { alias(libs.plugins.ksp) apply false alias(libs.plugins.detekt) alias(libs.plugins.spotless) + alias(libs.plugins.cyclonedx) } group = "com.fincore" diff --git a/deploy/helm/fincore-engine/.helmignore b/deploy/helm/fincore-engine/.helmignore new file mode 100644 index 0000000..ca646ab --- /dev/null +++ b/deploy/helm/fincore-engine/.helmignore @@ -0,0 +1,9 @@ +# Patterns to ignore when building packages. +.DS_Store +.git/ +.gitignore +*.tmproj +*.bak +*.orig +.idea/ +*.swp diff --git a/deploy/helm/fincore-engine/Chart.yaml b/deploy/helm/fincore-engine/Chart.yaml new file mode 100644 index 0000000..a8327b7 --- /dev/null +++ b/deploy/helm/fincore-engine/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: fincore-engine +description: FinCore Engine umbrella chart, deploys the ledger, payments and sandbox web services as one stack +type: application +version: 0.1.0 +appVersion: "0.1.0" +home: https://github.com/tiana-code/fincore-engine +sources: + - https://github.com/tiana-code/fincore-engine +maintainers: + - name: FinCore Engine Authors +dependencies: + - name: ledger + version: 0.1.0 + repository: file://../ledger + condition: ledger.enabled + - name: payments + version: 0.1.0 + repository: file://../payments + condition: payments.enabled + - name: web + version: 0.1.0 + repository: file://../web + condition: web.enabled diff --git a/deploy/helm/fincore-engine/templates/NOTES.txt b/deploy/helm/fincore-engine/templates/NOTES.txt new file mode 100644 index 0000000..95579eb --- /dev/null +++ b/deploy/helm/fincore-engine/templates/NOTES.txt @@ -0,0 +1,19 @@ +FinCore Engine has been deployed. + +Enabled services: +{{- if .Values.ledger.enabled }} + - ledger +{{- end }} +{{- if .Values.payments.enabled }} + - payments +{{- end }} +{{- if .Values.web.enabled }} + - web (sandbox dashboard) +{{- end }} + +Check rollout status: + kubectl get pods -n {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }} + +Each service is its own sub-chart. Tune a service by overriding under its key, +for example: + helm upgrade {{ .Release.Name }} . --set ledger.replicaCount=3 diff --git a/deploy/helm/fincore-engine/values.yaml b/deploy/helm/fincore-engine/values.yaml new file mode 100644 index 0000000..bd1aeb7 --- /dev/null +++ b/deploy/helm/fincore-engine/values.yaml @@ -0,0 +1,13 @@ +# Umbrella values. Each block below is forwarded to the matching sub-chart. +# Toggle a service off to deploy a subset of the stack. Per-service tuning +# (resources, image tag, secrets) lives in the sub-chart values and can be +# overridden here under the same key. + +ledger: + enabled: true + +payments: + enabled: true + +web: + enabled: true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d6dc696..f168376 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,6 +19,7 @@ cloudevents = "4.1.1" ksp = "2.0.21-1.0.28" spring-dependency-management = "1.1.7" spotless = "7.0.4" +cyclonedx = "3.2.4" [libraries] # Kotlin @@ -96,3 +97,4 @@ spring-dependency-management = { id = "io.spring.dependency-management", version ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } spotless = { id = "com.diffplug.spotless", version.ref = "spotless" } +cyclonedx = { id = "org.cyclonedx.bom", version.ref = "cyclonedx" }