From 8e3fde0b4f7b752f8651b933d208ada7bda66358 Mon Sep 17 00:00:00 2001 From: maoanran Date: Mon, 23 Feb 2026 15:04:31 +0100 Subject: [PATCH] feat: add deploy-kotlin-v2 workflow for service repo-based deployments This workflow supports the v2 deployment pattern where helm values are stored in a separate service repository instead of the central kube-manifests repo. Key features: - Uses component-deploy-v2 for service repository-based deployment - Includes all Kotlin-specific features (tests, Gradle, service profile) - Adds helm-values-path, repository-name, and argocd-app-name inputs - Supports architecture input for ARM64 runners - Maintains compatibility with release tags and changelog generation Updated documentation: - Added comprehensive workflow guide section with usage examples - Updated CLAUDE.md with recent changes - Added service repository structure guidelines --- .github/workflows/deploy-kotlin-v2.yml | 329 +++++++++++++++++++++++++ CLAUDE.md | 15 +- docs/workflow-guide.md | 234 +++++++++++++++++- 3 files changed, 567 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/deploy-kotlin-v2.yml diff --git a/.github/workflows/deploy-kotlin-v2.yml b/.github/workflows/deploy-kotlin-v2.yml new file mode 100644 index 0000000..4c18cf9 --- /dev/null +++ b/.github/workflows/deploy-kotlin-v2.yml @@ -0,0 +1,329 @@ +name: Deploy V2 (Service Repo) + +on: + workflow_call: + inputs: + runner-size: + required: false + type: string + description: "Runner to use for the job (normal, or large)" + default: "normal" + stage: + required: true + type: string + description: 'stage being released (dev,staging,production)' + service-name: + required: true + type: string + description: 'Proper name for your service i.e OCPP Service, Vehicle Service' + service-emoji: + required: true + type: string + description: 'An emoji to identify your service by :)' + service-identifier: + required: true + type: string + description: 'Identifier of the service being released i.e ocpp, vehicle, server, wallet.' + gradle-module: + required: false + type: string + description: 'Name of the Gradle module being tested' + java-version: + required: false + type: string + default: "21" + description: 'Java version to use' + gradle-args: + required: false + type: string + default: "--no-daemon --parallel" + description: 'Additional Gradle arguments' + region: + required: false + type: string + default: "eu-west-1" + description: 'AWS region to deploy to' + docker-file-name: + required: false + type: string + description: Name of the docker file to be built + default: "Dockerfile" + additional-build-args: + required: false + type: string + description: 'Additional build arguments for Docker' + ecr-repository-name: + required: false + type: string + description: 'ECR repository name override' + enable-release-tag: + required: false + type: boolean + default: false + description: 'Enable automatic release tag creation on workflow_dispatch' + release-tag-prefix: + required: false + type: string + description: "Optional prefix for release tag names. If provided, creates tags like 'prefix-YYYY-MM-DD-HH-MM'. Leave empty for date-only tags." + enable-changelog: + required: false + type: boolean + default: false + description: 'Enable changelog generation after deployment' + changelog-tag-pattern: + required: false + type: string + description: 'Regex pattern for matching tag patterns (group 1 should match version) - example: processor-(.*)' + changelog-path-exclude-pattern: + required: false + type: string + description: 'Regex pattern for excluding file paths from changelog - example: ^gateway/' + comment-on-prs: + required: false + type: boolean + default: true + description: 'Comment on PRs with production deployment information (automatically disabled if requirements not met)' + comment-on-jira: + required: false + type: boolean + default: true + description: 'Comment on JIRA tickets with production deployment information (automatically disabled if requirements not met)' + run-tests: + required: false + type: boolean + default: true + description: 'Run tests before deployment' + update-service-profile: + required: false + type: boolean + default: true + description: 'Use generated openapi spec to generate linkerd service profile and update the service helm chart' + helm-values-path: + required: false + type: string + description: 'Path to helm values directory (default: helm/{service-identifier}/{stage}/app)' + repository-name: + required: false + type: string + description: 'Repository name override (default: service-{service-identifier})' + argocd-server: + required: false + type: string + description: 'ArgoCD server URL (e.g., argocd.monta.app) for deployment monitoring' + argocd-app-name: + required: false + type: string + description: 'ArgoCD application name prefix (without stage). Defaults to service-identifier. Used for kube-manifests lookup (apps/{argocd-app-name}/{stage}/...) and ArgoCD app name ({argocd-app-name}-{stage}).' + argocd-sync-wait-seconds: + required: false + default: 300 + type: number + description: 'Timeout duration in seconds to wait for ArgoCD sync to apply' + git-sha: + required: false + type: string + description: 'Git SHA to checkout and build from. Defaults to the triggering commit SHA.' + + secrets: + GHL_USERNAME: + required: true + description: 'GitHub username for Gradle plugin' + GHL_PASSWORD: + required: true + description: 'GitHub password/token for Gradle plugin' + AWS_ACCOUNT_ID: + required: true + description: 'AWS Account ID for ECR and deployment access' + SLACK_APP_TOKEN: + required: true + description: 'Slack app-level token for workflow notifications' + MANIFEST_REPO_PAT: + required: true + description: 'GitHub PAT to commit/push to service repository' + SENTRY_AUTH_TOKEN: + required: false + description: 'Sentry auth token, passed as Docker build secret' + AWS_CDN_ACCESS_KEY_ID: + required: false + description: 'CDN access key ID for S3 access, injected into Docker image' + AWS_CDN_SECRET_ACCESS_KEY: + required: false + description: 'CDN secret access key for S3 access, injected into Docker image' + LOKALISE_TOKEN: + required: false + description: 'Lokalise token for Lokalise API' + LOKALISE_PROJECT_ID: + required: false + description: 'Lokalise project ID for Lokalise API' + JIRA_EMAIL: + required: false + description: 'Email for JIRA API authentication (used for ticket operations in changelog)' + JIRA_TOKEN: + required: false + description: 'JIRA API token for authentication (used for ticket operations in changelog)' + CHANGELOG_GITHUB_TOKEN: + required: false + description: 'GitHub token for changelog generation' + ARGOCD_TOKEN: + required: false + description: 'ArgoCD authentication token for API access' + + outputs: + slack-message-id: + description: 'Slack message ID for deployment notifications' + value: ${{ jobs.deploy.outputs.slack-message-id }} + stage: + description: 'Stage that was deployed to (dev,staging,production)' + value: ${{ jobs.deploy.outputs.stage }} + docker-image: + description: 'Docker image repository path' + value: ${{ jobs.deploy.outputs.docker-image }} + previous-image-tag: + description: 'Docker image tag before the deployment (for rollback reference)' + value: ${{ jobs.deploy.outputs.previous-image-tag }} + image-tag: + description: 'Docker image tag that was deployed' + value: ${{ jobs.deploy.outputs.image-tag }} + deployment-start-time: + description: 'ISO 8601 timestamp when deployment started (only if ArgoCD auto-sync enabled)' + value: ${{ jobs.deploy.outputs.deployment-start-time }} + deployment-end-time: + description: 'ISO 8601 timestamp when deployment became healthy (only if ArgoCD auto-sync enabled)' + value: ${{ jobs.deploy.outputs.deployment-end-time }} + deployment-url: + description: 'Direct URL to the application in ArgoCD UI (only if ArgoCD auto-sync enabled)' + value: ${{ jobs.deploy.outputs.deployment-url }} + +permissions: + id-token: write + contents: write + actions: write + +jobs: + initialize: + name: Initialize + uses: ./.github/workflows/component-initialize.yml + with: + service-name: ${{ inputs.service-name }} + service-emoji: ${{ inputs.service-emoji }} + secrets: + SLACK_APP_TOKEN: ${{ secrets.SLACK_APP_TOKEN }} + test: + name: Test + needs: initialize + if: always() && inputs.run-tests && needs.initialize.result == 'success' + uses: ./.github/workflows/component-test-kotlin.yml + with: + runner-size: ${{ inputs.runner-size }} + service-name: ${{ inputs.service-name }} + service-emoji: ${{ inputs.service-emoji }} + gradle-module: ${{ inputs.gradle-module }} + java-version: ${{ inputs.java-version }} + gradle-args: ${{ inputs.gradle-args }} + slack-message-id: ${{ needs.initialize.outputs.slack-message-id }} + secrets: + GHL_USERNAME: ${{ secrets.GHL_USERNAME }} + GHL_PASSWORD: ${{ secrets.GHL_PASSWORD }} + SLACK_APP_TOKEN: ${{ secrets.SLACK_APP_TOKEN }} + build: + name: Build + needs: initialize + if: always() && needs.initialize.result == 'success' + uses: ./.github/workflows/component-build.yml + with: + runner-size: ${{ inputs.runner-size }} + stage: ${{ inputs.stage }} + service-name: ${{ inputs.service-name }} + service-emoji: ${{ inputs.service-emoji }} + service-identifier: ${{ inputs.service-identifier }} + region: ${{ inputs.region }} + docker-file-name: ${{ inputs.docker-file-name }} + additional-build-args: ${{ inputs.additional-build-args }} + ecr-repository-name: ${{ inputs.ecr-repository-name }} + slack-message-id: ${{ needs.initialize.outputs.slack-message-id }} + git-sha: ${{ inputs.git-sha }} + secrets: + AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} + SLACK_APP_TOKEN: ${{ secrets.SLACK_APP_TOKEN }} + GHL_USERNAME: ${{ secrets.GHL_USERNAME }} + GHL_PASSWORD: ${{ secrets.GHL_PASSWORD }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + AWS_CDN_ACCESS_KEY_ID: ${{ secrets.AWS_CDN_ACCESS_KEY_ID }} + AWS_CDN_SECRET_ACCESS_KEY: ${{ secrets.AWS_CDN_SECRET_ACCESS_KEY }} + LOKALISE_TOKEN: ${{ secrets.LOKALISE_TOKEN }} + LOKALISE_PROJECT_ID: ${{ secrets.LOKALISE_PROJECT_ID }} + deploy: + name: Deploy + needs: + - initialize + - test + - build + if: always() && needs.initialize.result == 'success' && (!inputs.run-tests || needs.test.result == 'success') && needs.build.result == 'success' + uses: ./.github/workflows/component-deploy-v2.yml + with: + service-name: ${{ inputs.service-name }} + service-emoji: ${{ inputs.service-emoji }} + service-identifier: ${{ inputs.service-identifier }} + stage: ${{ inputs.stage }} + image-tag: ${{ needs.build.outputs.image-tag }} + slack-message-id: ${{ needs.initialize.outputs.slack-message-id }} + helm-values-path: ${{ inputs.helm-values-path }} + repository-name: ${{ inputs.repository-name }} + argocd-server: ${{ inputs.argocd-server }} + argocd-app-name: ${{ inputs.argocd-app-name }} + secrets: + MANIFEST_REPO_PAT: ${{ secrets.MANIFEST_REPO_PAT }} + SLACK_APP_TOKEN: ${{ secrets.SLACK_APP_TOKEN }} + ARGOCD_TOKEN: ${{ secrets.ARGOCD_TOKEN }} + update-service-profile: + name: Update Service Profile + needs: deploy + if: always() && inputs.update-service-profile && needs.deploy.result == 'success' + uses: ./.github/workflows/component-service-profile-kotlin.yml + with: + service-identifier: ${{ inputs.service-identifier }} + stage: ${{ inputs.stage }} + gradle-module: ${{ inputs.gradle-module }} + java-version: ${{ inputs.java-version }} + secrets: + GHL_USERNAME: ${{ secrets.GHL_USERNAME }} + GHL_PASSWORD: ${{ secrets.GHL_PASSWORD }} + MANIFEST_REPO_PAT: ${{ secrets.MANIFEST_REPO_PAT }} + create-release-tag: + name: Create Release Tag + if: always() && inputs.enable-release-tag && needs.deploy.result == 'success' + needs: deploy + uses: ./.github/workflows/create-release-tag.yml + with: + prefix: ${{ inputs.release-tag-prefix }} + create-changelog: + name: Create and Publish Changelog + needs: [create-release-tag, deploy] + if: always() && inputs.enable-changelog && needs.deploy.result == 'success' + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Run changelog cli action + uses: monta-app/changelog-cli-action@main + with: + service-name: ${{ inputs.service-name }} + github-release: true + github-token: ${{ secrets.CHANGELOG_GITHUB_TOKEN }} + github-tag-pattern: ${{ inputs.changelog-tag-pattern }} + github-path-exclude-pattern: ${{ inputs.changelog-path-exclude-pattern }} + jira-app-name: "montaapp" + jira-email: ${{ secrets.JIRA_EMAIL }} + jira-token: ${{ secrets.JIRA_TOKEN }} + output: "slack" + slack-token: ${{ secrets.SLACK_APP_TOKEN }} + # Slack channel: C02PDBL6GAU = #info-releases + slack-channel: "C02PDBL6GAU" + stage: ${{ needs.deploy.outputs.stage }} + docker-image: ${{ needs.deploy.outputs.docker-image }} + image-tag: ${{ needs.deploy.outputs.image-tag }} + previous-image-tag: ${{ needs.deploy.outputs.previous-image-tag }} + deployment-start-time: ${{ needs.deploy.outputs.deployment-start-time }} + deployment-end-time: ${{ needs.deploy.outputs.deployment-end-time }} + deployment-url: ${{ needs.deploy.outputs.deployment-url }} + comment-on-prs: ${{ inputs.comment-on-prs }} + comment-on-jira: ${{ inputs.comment-on-jira }} diff --git a/CLAUDE.md b/CLAUDE.md index 3106d87..a2f56a3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,11 +1,18 @@ # Claude Code Notes ## Last Documentation Update -- **Date**: 2025-07-11 -- **Latest SHA**: 6a249ca (check for newer commits) -- **Changes**: Added `release-tag-prefix` parameter to deploy-kotlin workflow for customizable release tag prefixes +- **Date**: 2026-02-23 +- **Latest SHA**: b65d4f5 (check for newer commits) +- **Changes**: Created `deploy-kotlin-v2.yml` workflow for repo-based Kotlin service deployments -## Recent Workflow Changes (2025-07-11) +## Recent Workflow Changes (2026-02-23) +1. **Kotlin V2 Deploy Workflow**: Created `deploy-kotlin-v2.yml` for repo-based deployments + - Uses `component-deploy-v2.yml` for service repository-based deployment pattern + - Includes all Kotlin-specific features: tests, Gradle, service profile updates, release tags, changelog + - Added `helm-values-path`, `repository-name`, and `argocd-app-name` inputs for flexible repo configuration + - Maintains compatibility with all existing Kotlin workflow features + +## Previous Changes (2025-07-11) 1. **Release Tag Prefix**: Added `release-tag-prefix` input to `deploy-kotlin.yml` for creating prefixed release tags (e.g., 'service-2024-01-15-14-30') 2. **Documentation**: Updated workflow guide with prefix parameter and usage example diff --git a/docs/workflow-guide.md b/docs/workflow-guide.md index 0b5386a..eaa6a12 100644 --- a/docs/workflow-guide.md +++ b/docs/workflow-guide.md @@ -12,13 +12,14 @@ This guide provides a comprehensive overview of all reusable GitHub workflows in 6. [Component Initialize](#component-initialize) 7. [Component Test (Kotlin)](#component-test-kotlin) 8. [Deploy Kotlin](#deploy-kotlin) -9. [Publish Tech Docs](#publish-tech-docs) -10. [Pull Request Kotlin](#pull-request-kotlin) -11. [Pull Request React (Bun)](#pull-request-react-bun) -12. [Pull Request React (pnpm)](#pull-request-react-pnpm) -13. [Rollback](#rollback) -14. [SonarCloud Analysis](#sonarcloud-analysis) -15. [Track Pending Release](#track-pending-release) +9. [Deploy Kotlin V2 (Service Repo)](#deploy-kotlin-v2-service-repo) +10. [Publish Tech Docs](#publish-tech-docs) +11. [Pull Request Kotlin](#pull-request-kotlin) +12. [Pull Request React (Bun)](#pull-request-react-bun) +13. [Pull Request React (pnpm)](#pull-request-react-pnpm) +14. [Rollback](#rollback) +15. [SonarCloud Analysis](#sonarcloud-analysis) +16. [Track Pending Release](#track-pending-release) --- @@ -566,6 +567,225 @@ jobs: --- +## Deploy Kotlin V2 (Service Repo) + +**File:** `deploy-kotlin-v2.yml` +**Purpose:** Complete CI/CD pipeline for Kotlin services using service repository-based deployment pattern. This workflow follows the v2 pattern where helm values are stored in a separate service repository instead of the central kube-manifests repo. + +### What it does: +1. **Initialize**: Sets up Slack notifications for the deployment process +2. **Test**: Runs unit tests and validates code quality (optional, controlled by `run-tests`) +3. **Build**: Creates multi-architecture Docker images and pushes to ECR +4. **Deploy**: Updates helm values in the service repository and syncs with ArgoCD +5. **Update Service Profile** (optional): Generates linkerd service profile from OpenAPI spec +6. **Create Release Tag** (optional): Creates a release tag when `enable-release-tag` is true +7. **Create Changelog** (optional): Generates and publishes changelog to Slack and GitHub releases + +### Differences from v1 (`deploy-kotlin.yml`): +- Uses `component-deploy-v2.yml` which updates a separate service repository instead of kube-manifests +- Adds `helm-values-path` input for flexible helm values directory structure +- Adds `repository-name` input to specify the service repository name +- Adds `argocd-app-name` input for custom ArgoCD application naming + +### Inputs: +| Input | Required | Default | Description | +|-------|----------|---------|-------------| +| `runner-size` | No | "normal" | Runner size: "normal" or "large" | +| `stage` | Yes | - | Deployment stage: "dev", "staging", or "production" | +| `service-name` | Yes | - | Human-readable service name (e.g., "Charging Service") | +| `service-emoji` | Yes | - | Emoji to identify the service in Slack notifications | +| `service-identifier` | Yes | - | Service identifier for ECR and Kubernetes (e.g., "charging") | +| `gradle-module` | No | - | Gradle module name for multi-module projects | +| `java-version` | No | "21" | Java version to use | +| `gradle-args` | No | "--no-daemon --parallel" | Additional Gradle arguments | +| `region` | No | "eu-west-1" | AWS region for deployment | +| `docker-file-name` | No | "Dockerfile" | Name of the Dockerfile to build | +| `additional-build-args` | No | - | Additional Docker build arguments | +| `ecr-repository-name` | No | - | Override ECR repository name | +| `run-tests` | No | true | Run tests before deployment | +| `update-service-profile` | No | true | Generate linkerd service profile from OpenAPI spec | +| `helm-values-path` | No | `helm/{service-identifier}/{stage}/app` | Path to helm values directory in service repo | +| `repository-name` | No | `service-{service-identifier}` | Service repository name override | +| `argocd-server` | No | - | ArgoCD server URL (e.g., argocd.monta.app) | +| `argocd-app-name` | No | `{service-identifier}` | ArgoCD application name prefix (without stage) | +| `argocd-sync-wait-seconds` | No | 300 | Timeout for ArgoCD sync monitoring | +| `git-sha` | No | - | Git SHA to checkout and build from | +| `enable-release-tag` | No | false | Enable automatic release tag creation | +| `release-tag-prefix` | No | '' | Optional prefix for release tag names | +| `enable-changelog` | No | false | Enable changelog generation | +| `changelog-tag-pattern` | No | - | Regex pattern for tag matching (monorepo filtering) | +| `changelog-path-exclude-pattern` | No | - | Regex pattern for excluding paths from changelog | +| `comment-on-prs` | No | true | Comment on PRs with deployment info | +| `comment-on-jira` | No | true | Comment on JIRA tickets with deployment info | + +### Secrets: +| Secret | Required | Description | +|--------|----------|-------------| +| `GHL_USERNAME` | Yes | GitHub username for Gradle dependencies | +| `GHL_PASSWORD` | Yes | GitHub token for Gradle dependencies | +| `AWS_ACCOUNT_ID` | Yes | AWS Account ID for ECR and deployment | +| `SLACK_APP_TOKEN` | Yes | Slack token for notifications | +| `MANIFEST_REPO_PAT` | Yes | GitHub PAT for updating service repository | +| `SENTRY_AUTH_TOKEN` | No | Sentry authentication token | +| `AWS_CDN_ACCESS_KEY_ID` | No | CDN access key for S3 access | +| `AWS_CDN_SECRET_ACCESS_KEY` | No | CDN secret key for S3 access | +| `LOKALISE_TOKEN` | No | Lokalise API token | +| `LOKALISE_PROJECT_ID` | No | Lokalise project ID | +| `JIRA_EMAIL` | No | Email for JIRA API authentication | +| `JIRA_TOKEN` | No | JIRA API token | +| `CHANGELOG_GITHUB_TOKEN` | No | GitHub token for changelog generation | +| `ARGOCD_TOKEN` | No | ArgoCD authentication token | + +### Outputs: +- `slack-message-id`: Slack message ID for notifications +- `stage`: Stage that was deployed to +- `docker-image`: Docker image repository path +- `previous-image-tag`: Previous Docker image tag (for rollback) +- `image-tag`: Deployed Docker image tag +- `deployment-start-time`: ISO 8601 timestamp when deployment started +- `deployment-end-time`: ISO 8601 timestamp when deployment completed +- `deployment-url`: Direct URL to the application in ArgoCD UI + +### Example Usage: + +#### Basic Deployment with Service Repo: +```yaml +name: Deploy to Production +on: + push: + branches: [main] + +jobs: + deploy: + uses: monta-app/github-workflows/.github/workflows/deploy-kotlin-v2.yml@main + with: + stage: "production" + service-name: "Payment Service" + service-emoji: "💳" + service-identifier: "payment" + repository-name: "service-payment" # Service repo with helm values + secrets: + GHL_USERNAME: ${{ secrets.GHL_USERNAME }} + GHL_PASSWORD: ${{ secrets.GHL_PASSWORD }} + AWS_ACCOUNT_ID: ${{ secrets.PRODUCTION_AWS_ACCOUNT_ID }} + SLACK_APP_TOKEN: ${{ secrets.SLACK_APP_TOKEN }} + MANIFEST_REPO_PAT: ${{ secrets.MANIFEST_REPO_PAT }} +``` + +#### With Custom Helm Path and ArgoCD Monitoring: +```yaml +name: Deploy to Staging +on: + workflow_dispatch: + +jobs: + deploy: + uses: monta-app/github-workflows/.github/workflows/deploy-kotlin-v2.yml@main + with: + stage: "staging" + service-name: "Auth Service" + service-emoji: "🔐" + service-identifier: "auth" + repository-name: "service-auth" + helm-values-path: "infrastructure/helm/staging/app" + argocd-server: "argocd.monta.app" + argocd-app-name: "auth" + java-version: "21" + gradle-module: "auth-api" + secrets: + GHL_USERNAME: ${{ secrets.GHL_USERNAME }} + GHL_PASSWORD: ${{ secrets.GHL_PASSWORD }} + AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} + SLACK_APP_TOKEN: ${{ secrets.SLACK_APP_TOKEN }} + MANIFEST_REPO_PAT: ${{ secrets.MANIFEST_REPO_PAT }} + ARGOCD_TOKEN: ${{ secrets.ARGOCD_TOKEN }} +``` + +#### Production with Release Management: +```yaml +name: Deploy Production with Release +on: + push: + tags: ['*'] + workflow_dispatch: + +jobs: + deploy: + uses: monta-app/github-workflows/.github/workflows/deploy-kotlin-v2.yml@main + with: + stage: "production" + runner-size: "large" + service-name: "Gateway Service" + service-emoji: "🚪" + service-identifier: "gateway" + repository-name: "service-gateway" + enable-release-tag: true + release-tag-prefix: "gateway" + enable-changelog: true + changelog-tag-pattern: "gateway-(.*)" + argocd-server: "argocd.monta.app" + comment-on-prs: true + comment-on-jira: true + secrets: + GHL_USERNAME: ${{ secrets.GHL_USERNAME }} + GHL_PASSWORD: ${{ secrets.GHL_PASSWORD }} + AWS_ACCOUNT_ID: ${{ secrets.PRODUCTION_AWS_ACCOUNT_ID }} + SLACK_APP_TOKEN: ${{ secrets.SLACK_APP_TOKEN }} + MANIFEST_REPO_PAT: ${{ secrets.MANIFEST_REPO_PAT }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + CHANGELOG_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }} + JIRA_TOKEN: ${{ secrets.JIRA_TOKEN }} + ARGOCD_TOKEN: ${{ secrets.ARGOCD_TOKEN }} +``` + +### Service Repository Structure: +The service repository should have the following structure: +``` +service-{identifier}/ +├── helm/ +│ ├── {service-identifier}/ +│ │ ├── dev/ +│ │ │ ├── app/ +│ │ │ │ └── values.yaml +│ │ │ └── cluster/ +│ │ │ └── config.yaml # Optional: ArgoCD auto-sync config +│ │ ├── staging/ +│ │ │ └── app/ +│ │ │ └── values.yaml +│ │ └── production/ +│ │ └── app/ +│ │ └── values.yaml +└── ... +``` + +Or with custom path: +``` +service-{identifier}/ +├── infrastructure/ +│ └── helm/ +│ ├── dev/ +│ │ └── app/ +│ │ └── values.yaml +│ └── staging/ +│ └── app/ +│ └── values.yaml +└── ... +``` + +### When to Use V2 vs V1: +- **Use V2** (`deploy-kotlin-v2.yml`) when: + - Helm values should live in the service repository + - You want tighter coupling between code and infrastructure + - Each service manages its own deployment configuration + +- **Use V1** (`deploy-kotlin.yml`) when: + - Helm values are centralized in the `kube-manifests` repository + - You prefer separation of concerns between code and infrastructure + - Infrastructure team manages all deployment configurations + +--- + ## Publish Tech Docs **File:** `publish-tech-docs.yml`