Skip to content

feat(gitops-update): support per-cluster env suffix variants (-st / -mt)#423

Open
ferr3ira-gabriel wants to merge 1 commit into
developfrom
feature/gitops-update-env-suffixes
Open

feat(gitops-update): support per-cluster env suffix variants (-st / -mt)#423
ferr3ira-gabriel wants to merge 1 commit into
developfrom
feature/gitops-update-env-suffixes

Conversation

@ferr3ira-gabriel

@ferr3ira-gabriel ferr3ira-gabriel commented Jun 11, 2026

Copy link
Copy Markdown
Member

Summary

Adds per-cluster env-suffix expansion to the gitops-update workflow so clusters that host multiple parallel variants per environment (e.g. Benedita with single-tenant -st and multi-tenant -mt) can be onboarded without forking the workflow.

Closes #422.

Manifest change (additive)

clusters:
  benedita:
    env_suffixes: ["-st", "-mt"]         # produces dev-st, dev-mt, stg-st, ...
    suffix_excludes_envs: ["sandbox"]    # sandbox stays bare
    apps: [...]

Both fields are optional:

Field Default Effect
env_suffixes [""] List of suffixes appended to each tag-derived env. Default preserves single-variant behavior.
suffix_excludes_envs [] Tag-derived env names that should NOT receive any suffix (stay bare).

Resolution example

Manifest: benedita declares env_suffixes: ["-st", "-mt"], suffix_excludes_envs: ["sandbox"].

Tag type Tag-derived envs Final envs for benedita
beta (v1.2.3-beta.1) dev dev-st, dev-mt
rc (v1.2.3-rc.1) stg stg-st, stg-mt
production (v1.2.3) dev stg prd sandbox dev-st, dev-mt, stg-st, stg-mt, prd-st, prd-mt, sandbox
sandbox (v1.2.3-sandbox.1) sandbox sandbox

For firmino/clotilde/anacleto (no manifest change), env_suffixes defaults to [""], so the final env list equals the tag-derived list verbatim. Byte-identical behavior to today.

Workflow changes

  1. resolve_clusters step — extended to emit a per-cluster JSON map of env_suffixes and suffix_excludes_envs resolved from the manifest (with defaults applied).

  2. apply_tags step — new helper expand_envs_for_server runs the cross-product of the tag-derived env list × the cluster's env_suffixes, with suffix_excludes_envs honored. The expanded env name flows through unchanged to:

    • Helmfile path: environments/{server}/helmfile/applications/{ENV}/{app}/values.yaml where ENV is now dev-st etc.
    • ArgoCD app name template ({server}-{app}-{env} by default) — benedita-midaz-dev-st resolves naturally with no new workflow inputs.
  3. Cross-app handling — when an app has app_helmfile_env set (e.g. forge: cross), the suffix expansion is bypassed and the sync target's env equals the override value (cross). This makes benedita-forge-cross the correct ArgoCD app name once the cross apps are renamed to follow the standard convention.

  4. Sync-matrix dedup — the updated (server, env) pairs are now de-duplicated before being emitted as the ArgoCD sync matrix. This prevents cross apps (visited once per outer env iteration) from being queued for sync multiple times.

  5. Kustomize layout — unchanged. The kustomize branch already bypasses the env list when its sentinel env (-) is in effect; expand_envs_for_server returns the input unchanged in that case.

Lint extension

src/lint/deployment-matrix/action.yml was previously validating only version, apps.registry, and clusters.<name>.apps. This PR extends it to validate:

  • env_suffixes (list of strings, unique, non-empty list)
  • suffix_excludes_envs (list of valid env names; warns if pointing at unknown env or used without env_suffixes)
  • app_helmfile_env (pre-existing field, now validated: dict whose keys must reference apps in the cluster's apps list)

Testing

Simulated the full env resolution offline against the updated manifest for all four clusters × four tag types. Output verified manually:

=== Production tag (dev stg prd sandbox) ===
firmino: dev stg prd sandbox                       # unchanged
clotilde: dev stg prd sandbox                      # unchanged
anacleto: dev stg prd sandbox                      # unchanged
benedita: dev-st dev-mt stg-st stg-mt prd-st prd-mt sandbox

=== Beta tag (dev) ===
firmino/clotilde/anacleto: dev
benedita: dev-st dev-mt

Workflow and action YAML pass actionlint clean.
Extended lint passes on the updated manifest (violations=0 warnings=0).

Out of scope

  • Per-app suffix restriction (e.g. "tenant-manager is MT-only") — to be added as app_env_suffixes in a follow-up when an actual MT-only or ST-only app emerges.
  • Renaming non-standard ArgoCD app names on Benedita (benedita-forgebenedita-forge-cross, etc.) — handled separately in the gitops repo by the cluster owner.

Reviewer checklist

  • Manifest change in config/deployment-matrix.yml reads sensibly and the schema comments make the new fields discoverable
  • Workflow diff in gitops-update.yml preserves existing behavior for firmino/clotilde/anacleto (default env_suffixes=[""] produces no env list change)
  • expand_envs_for_server correctly handles edge cases: empty ENV_CONFIG, kustomize sentinel -, missing fields
  • Sync matrix dedup uses sort -u and the resulting JSON array preserves the (server, env) shape
  • Documentation in docs/gitops-update-workflow.md describes the new fields and resolution rules
  • Lint extension in src/lint/deployment-matrix/action.yml covers the new fields and the pre-existing app_helmfile_env

Summary by CodeRabbit

  • New Features

    • Added support for per-cluster environment variant configuration, enabling applications to define environment-specific suffixes across deployment targets.
    • Updated deployment workflow to correctly resolve application names based on variant configurations.
  • Documentation

    • Added guide explaining per-cluster environment variant setup and deployment behavior.
  • Chores

    • Enhanced deployment configuration validation with stricter schema checks.

Adds two additive, backward-compatible fields to the deployment matrix
manifest to express clusters that host multiple parallel variants per
environment (e.g. single-tenant -st + multi-tenant -mt on benedita):

  clusters:
    benedita:
      env_suffixes: ["-st", "-mt"]
      suffix_excludes_envs: ["sandbox"]

The gitops-update workflow expands each tag-derived env (dev/stg/prd/sandbox)
against the cluster's env_suffixes, except envs listed in suffix_excludes_envs
which stay bare. The expanded env name flows through unchanged to the helmfile
path resolution and the ArgoCD app name template, so 'benedita-midaz-dev-st'
resolves naturally without any new workflow inputs.

Cross apps (those with app_helmfile_env set, e.g. forge: cross) bypass the
suffix expansion - they update once at the override path and their sync target
uses the override env, so 'benedita-forge-cross' resolves correctly when the
cluster renames its ArgoCD apps to follow the {server}-{app}-{env} convention.

Defaults preserve byte-identical behavior for firmino/clotilde/anacleto:
env_suffixes defaults to [""] (single empty-suffix expansion), suffix_excludes_envs
defaults to []. Tag-derived env list for those clusters is unchanged.

Also extends the deployment-matrix lint action to validate the new fields
plus the pre-existing app_helmfile_env field (which was previously unvalidated).

Closes #422
@ferr3ira-gabriel ferr3ira-gabriel requested a review from a team as a code owner June 11, 2026 17:27
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 792df98e-9f19-4417-98c6-3b3c58406608

📥 Commits

Reviewing files that changed from the base of the PR and between ff16b50 and d91ef1b.

📒 Files selected for processing (4)
  • .github/workflows/gitops-update.yml
  • config/deployment-matrix.yml
  • docs/gitops-update-workflow.md
  • src/lint/deployment-matrix/action.yml

Walkthrough

The PR extends the GitOps deployment matrix workflow to support per-cluster environment suffix variants, enabling clusters like Benedita to run multiple parallel environments (single-tenant, multi-tenant) per base environment. It adds schema fields, validation, environment expansion logic, corrects ArgoCD sync targets, and deduplicates output.

Changes

Per-Cluster Environment Suffix Variants

Layer / File(s) Summary
Config schema and validation
config/deployment-matrix.yml, src/lint/deployment-matrix/action.yml
Schema extends to env_suffixes (list of suffix strings) and suffix_excludes_envs (list of bare environments). Validator enforces non-empty lists, detects duplicates, warns on invalid env values, and validates app override mappings against declared apps.
Environment expansion in resolve_clusters and apply_tags
.github/workflows/gitops-update.yml
resolve_clusters computes and exports env_config with per-cluster suffix and exclusion defaults. apply_tags receives this config and expand_envs_for_server() derives the final environment list by applying suffix expansion to base environments except those in suffix_excludes_envs, then iterates over the expanded set.
ArgoCD sync target uses Helmfile environment
.github/workflows/gitops-update.yml
When values.yaml changes are detected, the workflow records the ArgoCD sync target environment as HELMFILE_ENV (per-app Helmfile override) instead of tag-derived ENV, ensuring correct app name resolution for apps with overridden paths.
Sync matrix deduplication
.github/workflows/gitops-update.yml
Updated (server, env) pairs are sorted and deduplicated before producing the final JSON sync matrix.
Documentation
docs/gitops-update-workflow.md
New section explains per-cluster suffix expansion, interaction with app-level Helmfile overrides, and provides concrete examples of env list transformations.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and clearly summarizes the main change: adding per-cluster env suffix support for the gitops-update workflow.
Description check ✅ Passed The description covers manifest changes, workflow logic, testing, and lint updates with specific examples; all template sections are filled with substantive detail.
Linked Issues check ✅ Passed All acceptance criteria from issue #422 are addressed: (1) per-cluster env suffix expansion with excludes for benedita, (2) byte-identical behavior for other clusters via default empty suffix, (3) ArgoCD app name resolution requires no new inputs, (4) documentation provided.
Out of Scope Changes check ✅ Passed All code changes directly serve the stated objective: workflow env expansion, manifest schema/validation updates, documentation, and lint extension. No unrelated refactors or dependency bumps detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/gitops-update-env-suffixes

Comment @coderabbitai help to get the list of available commands and usage tips.

@lerian-studio lerian-studio added size/M PR changes 200–499 lines documentation Improvements or additions to documentation workflow Changes to one or more reusable workflow files lint Changes to linting and code quality checks deployment-matrix Changes to the canonical deployment matrix (config/deployment-matrix.yml) composite Changes to any composite action manifest (src/**/*.yml) labels Jun 11, 2026
@lerian-studio

lerian-studio commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

🛡️ CodeQL Analysis Results

Languages analyzed: actions

Found 2 issue(s): 2 Medium

Severity Rule File Message
🟡 Medium actions/untrusted-checkout/medium .github/workflows/gitops-update.yml:143 Potential unsafe checkout of untrusted pull request on privileged workflow.
🟡 Medium actions/untrusted-checkout/medium .github/workflows/gitops-update.yml:151 Potential unsafe checkout of untrusted pull request on privileged workflow.

🔍 View full scan logs | 🛡️ Security tab

@lerian-studio

lerian-studio commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

🔍 PR Validation Summary

✅ PR Mergeable — no blocking failures

Check Status Blocking
Source Branch ✅ success yes
PR Title ✅ success yes
PR Description ✅ success yes
PR Size ✅ success no
Auto Labels ✅ success no
PR Metadata ✅ success no

🔍 View workflow run

@lerian-studio

lerian-studio commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

🔍 Lint Analysis

Check Files Scanned Status
YAML Lint 3 file(s) ✅ success
Action Lint 1 file(s) ✅ success
Pinned Actions 2 file(s) ✅ success
Markdown Link Check 1 file(s) ✅ success
Spelling Check 4 file(s) ✅ success
Shell Check 2 file(s) ✅ success
README Check 2 file(s) ✅ success
Composite Schema 1 file(s) ✅ success
Deployment Matrix 1 file(s) ✅ success

🔍 View full scan logs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

composite Changes to any composite action manifest (src/**/*.yml) deployment-matrix Changes to the canonical deployment matrix (config/deployment-matrix.yml) documentation Improvements or additions to documentation lint Changes to linting and code quality checks size/M PR changes 200–499 lines workflow Changes to one or more reusable workflow files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants