Skip to content

chore: runtime app configuration sources#17729

Merged
martinothamar merged 1 commit intomainfrom
chore/runtime-app-configuration
Feb 17, 2026
Merged

chore: runtime app configuration sources#17729
martinothamar merged 1 commit intomainfrom
chore/runtime-app-configuration

Conversation

@martinothamar
Copy link
Contributor

@martinothamar martinothamar commented Feb 13, 2026

Description

Related to: Altinn/app-lib-dotnet#1661

But with -env variants as well so we can use envFrom or something in deploy-app pipeline (works also for old apps)

Verification

  • Related issues are connected (if applicable)
  • Your code builds clean without any errors or warnings
  • Manual testing done (required)
  • Relevant automated test added (if you find this hard, leave it and we'll help out)

Summary by CodeRabbit

Release Notes

  • New Features

    • Implemented automated runtime application configuration management with support for multiple deployment environments (production, staging, test rings).
  • Chores

    • Added infrastructure automation workflows for streamlined deployment of environment-specific configurations.

@github-actions github-actions bot added skip-releasenotes Issues that do not make sense to list in our release notes skip-second-approval Pull requests that only need one approval from a reviewer. labels Feb 13, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 13, 2026

📝 Walkthrough

Walkthrough

This change introduces a comprehensive infrastructure layer for runtime application configuration management. It establishes Kubernetes manifests, environment-specific Kustomization patches for multiple environments (AT22, AT23, AT24, TT02, YT01, PROD), a FluxCD-based synchronisation mechanism, and a GitHub Actions workflow for automated artifact deployment and tagging across environments.

Changes

Cohort / File(s) Summary
Syncroot Base Configuration
infra/runtime/syncroot/base/kustomization.yaml, infra/runtime/syncroot/base/apps-config.yaml
Added reference to apps-config resource and introduced FluxCD OCIRepository and Kustomization manifest for automated, environment-parameterised configuration synchronisation from Azure container registry.
GitHub Actions Workflows
.github/workflows/deploy-runtime-apps-config.yaml, .github/workflows/deploy-runtime-syncroot.yaml
Introduced new workflow for apps config deployment with artifact construction, Azure/ACR login, Flux integration, and matrix-based environment tagging. Updated existing syncroot workflow to include new trigger branch and revise default rings configuration.
Apps Config Base Setup
infra/runtime/apps-config/base/kustomization.yaml, infra/runtime/apps-config/base/apps-runtime-common-env.yaml, infra/runtime/apps-config/base/apps-runtime-common.yaml
Established base Kubernetes ConfigMaps and Secrets for common runtime configuration, including repository settings, PDF generator endpoints, platform settings, and Application Insights credentials.
Environment-Specific Configurations
infra/runtime/apps-config/at22/kustomization.yaml, infra/runtime/apps-config/at23/kustomization.yaml, infra/runtime/apps-config/at24/kustomization.yaml, infra/runtime/apps-config/prod/kustomization.yaml, infra/runtime/apps-config/tt02/kustomization.yaml, infra/runtime/apps-config/yt01/kustomization.yaml
Added environment-specific Kustomization patches that override base ConfigMaps with environment-targeted endpoints, hostnames, OpenID well-known endpoints, ASPNETCORE_ENVIRONMENT settings, and runtime-overrides.json payloads containing nested configuration structures for each deployment ring.

Sequence Diagram

sequenceDiagram
    participant GHA as GitHub Actions
    participant ACR as Azure Container<br/>Registry (OCI)
    participant Flux as FluxCD
    participant K8s as Kubernetes<br/>Cluster
    participant CM as ConfigMaps

    GHA->>GHA: construct-rings-array: Build rings JSON
    GHA->>ACR: push-apps-config-artifact: Push OCI artifact<br/>(via Flux)
    GHA->>ACR: tag-apps-config: Tag artifact per<br/>environment/ring (matrix)
    
    Note over Flux: Continuous reconciliation loop
    Flux->>ACR: Poll OCIRepository at 5m interval
    Flux->>Flux: Detect new/updated artifact
    Flux->>Flux: Resolve ENVIRONMENT variable
    Flux->>K8s: Apply Kustomization with<br/>environment-specific patches
    K8s->>CM: Update/create ConfigMaps<br/>(apps-runtime-common-config*)
    CM-->>Flux: Reconciliation complete
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Hops of joy through configs new,
Flux and rings in azure blue,
Each environment, a burrow deep,
With patches stacked for runtime's keep,
From AT to TT we hop and play,
Automation guides the way! 🌿✨

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'chore: runtime app configuration sources' accurately summarises the main change: introducing new configuration sources and infrastructure for runtime app configuration management across multiple environments.
Description check ✅ Passed The pull request description includes a clear reference to the related work and explains the purpose of adding -env variants. However, the verification checklist items are not explicitly marked as completed or addressed.

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/runtime-app-configuration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In @.github/workflows/deploy-runtime-apps-runtime-config.yaml:
- Around line 35-41: Replace direct interpolation of github.event.inputs.rings
in the run script with environment variables to avoid shell injection: declare
env keys for RINGS and DEFAULT_RINGS on the workflow step (e.g., env: RINGS: ${{
github.event.inputs.rings }} DEFAULT_RINGS: ${{ env.default-rings }}), then in
the run block use safe variable expansion (rings="$RINGS"; if [ -z "$rings" ];
then rings="$DEFAULT_RINGS"; fi; echo "Raw rings input: $rings"; echo
"ringsjson=${rings}" >> $GITHUB_OUTPUT). This removes the inline '${{
github.event.inputs.rings }}' interpolation inside the shell command and uses
the RINGS/DEFAULT_RINGS variables instead.
🧹 Nitpick comments (2)
.github/workflows/deploy-runtime-apps-runtime-config.yaml (2)

50-52: Job output config-repo is a static expression, not a step output reference.

Line 52 defines the job output as a literal expression rather than referencing a step output. While this is valid GHA syntax, it duplicates the CONFIG_REPO env definition on line 50. If the path changes, both need updating.

Consider outputting from a step instead, or at minimum add a comment noting the duplication with env.CONFIG_REPO.


97-98: Hardcoded registry name instead of using a variable.

Line 98 hardcodes altinncr while the push-apps-runtime-config-artifact job uses env.REGISTRY_NAME. Minor inconsistency — if the registry name ever changes, this would be missed.

@martinothamar martinothamar force-pushed the chore/runtime-app-configuration branch from 7fe6c89 to aad1da7 Compare February 16, 2026 11:31
@martinothamar martinothamar requested a review from a team as a code owner February 16, 2026 11:31
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
infra/runtime/apps-runtime-config/prod/kustomization.yaml (1)

9-59: Consider reducing duplication between the two patch formats.

Every setting is maintained twice — once as flat __-delimited env vars and once as nested JSON in runtime-overrides.json. When a new endpoint is added or a URL changes, both blocks must be updated in lockstep across every environment overlay. This is fragile and a likely source of drift over time.

Could the runtime-overrides.json content be generated from the env-var entries (or vice versa) at build/CI time, so there is a single source of truth per environment?

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/deploy-runtime-syncroot.yaml (1)

58-60: ⚠️ Potential issue | 🟡 Minor

Misleading comment: fetch-depth: 0 is a full clone, not a shallow clone.

The same issue appears on line 98. fetch-depth: 0 fetches the entire history. Either update the comment or use fetch-depth: 1 for an actual shallow clone.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-runtime-syncroot.yaml around lines 58 - 60, The
comment next to the checkout step incorrectly states "Shallow clone" while
fetch-depth: 0 performs a full clone; update the actions/checkout usage by
either changing the comment to reflect a full clone or set fetch-depth: 1 to
perform an actual shallow clone — modify the lines around the actions/checkout
entry and the fetch-depth: 0 key (also adjust the identical occurrence later) so
the comment and value are consistent.
🧹 Nitpick comments (4)
infra/runtime/apps-config/at22/kustomization.yaml (1)

1-53: Consider reducing duplication across environment overlays.

All environment kustomizations (at22, at23, at24, yt01, tt02) duplicate the same list of endpoint keys, differing only in the hostname portion of the URLs. This is manageable now but will become a maintenance burden if new settings are added — each file must be updated in lockstep.

A lighter approach would be to template the base URLs using Kustomize replacements or Flux postBuild.substitute with a single HOST variable per environment, reducing each overlay to a few lines. That said, the current explicit approach is a well-understood Kustomize pattern, so this is optional.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@infra/runtime/apps-config/at22/kustomization.yaml` around lines 1 - 53, The
overlay duplicates many environment-specific endpoint URLs across
kustomizations; update the at22 overlay to compute hostname once and substitute
it into endpoints instead of hardcoding each URL by: replace the repeated full
URLs in the ConfigMap patches (targets apps-runtime-common-config-env and
apps-runtime-common-config, including the runtime-overrides.json value) with
templates that use a single HOST variable for host (e.g. HOST=at22.altinn.cloud)
and switch to Kustomize replacements or Flux postBuild.substitute to inject that
HOST into each endpoint pattern, so future overlays only change the HOST value
rather than every URL.
.github/workflows/deploy-runtime-apps-config.yaml (3)

67-68: Minor: az acr login uses ${{ env.REGISTRY_NAME }} interpolation in run:.

While not exploitable (the value is workflow-controlled), for consistency with the injection hardening above, consider using shell variable expansion instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-runtime-apps-config.yaml around lines 67 - 68, The
run step invoking the Azure CLI uses GitHub Actions expression interpolation (${
{ env.REGISTRY_NAME }}) inside the run string; change it to use shell
environment variable expansion so the command becomes az acr login --name
"$REGISTRY_NAME" (i.e., reference REGISTRY_NAME via the shell in the run step),
ensuring the step that sets REGISTRY_NAME remains exported in the job
environment and keeping the step name az acr login unchanged.

14-16: Default rings value is duplicated in two places.

The default rings JSON is defined both as the workflow_dispatch input default (line 16) and as the job-level env.default-rings (line 30). If one is updated without the other, they will silently diverge. Consider referencing a single source of truth — e.g., only use the env variable and drop the input default, or use a reusable mechanism.

Also applies to: 29-30

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-runtime-apps-config.yaml around lines 14 - 16, The
default rings JSON is duplicated between the workflow_dispatch input default for
"rings" and the job-level env variable "default-rings"; pick a single source of
truth and reference it instead of duplicating: remove the hard-coded JSON from
the workflow_dispatch input default and set the input's default to the env
variable (e.g., reference env.default-rings) or conversely remove the job-level
env and read the workflow input into env.default-rings at job start (use
defaults: or set env: default-rings: ${{ github.event.inputs.rings }}), ensuring
only the unique identifiers "rings" (workflow input) and "default-rings" (job
env) are used and kept in one place.

6-7: Remove the feature branch trigger before merging to main.

Line 7 includes chore/runtime-app-configuration as a push trigger. This will become a no-op once the branch is merged and deleted, but it adds unnecessary noise. Consider removing it so that only main triggers the workflow post-merge.

Proposed fix
   push:
     branches:
       - main
-      - chore/runtime-app-configuration
     paths:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/deploy-runtime-apps-config.yaml around lines 6 - 7, Remove
the feature branch trigger from the workflow push triggers: locate the push
triggers list that currently includes "main" and
"chore/runtime-app-configuration" and delete the
"chore/runtime-app-configuration" entry so only "main" remains; ensure the YAML
syntax (dash list) remains valid after removal and commit the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/deploy-runtime-apps-config.yaml:
- Around line 104-107: The run block interpolates matrix.ring directly into
shell which allows script injection; change it to use a GitHub Actions
environment variable instead: set an env entry like RING: ${{ matrix.ring }} for
the step (or the job) and then reference $RING inside the run script when
calling the flux tag artifact command (ensure you replace direct `${{
matrix.ring }}` with the env var reference), so the shell receives only the
sanitized env value rather than raw workflow interpolation.

In @.github/workflows/deploy-runtime-syncroot.yaml:
- Line 7: The workflow currently includes a push trigger for the temporary
branch name "chore/runtime-app-configuration"; remove that branch entry from the
push triggers in the deploy-runtime-syncroot.yaml so the workflow no longer runs
on pushes to that temporary branch (leave only intended branches like main).
Locate the push trigger array where "chore/runtime-app-configuration" appears
and delete that string entry, then commit the change.
- Line 31: The workflow currently uses a single-ring configuration [{"ring":
"at_ring1", "environment": "runtime_at_ring1"}] and has a temporary commit
intent; either expand the rings array to include all intended deployment
rings/environments (add additional objects with "ring" and "environment" keys)
if this should deploy across multiple targets on pushes to main, or
remove/change the push:on: main trigger so it doesn't run automatically until
finalized; also replace the "tmp: deploy" commit/message with a descriptive
commit and update the array or trigger accordingly.

---

Outside diff comments:
In @.github/workflows/deploy-runtime-syncroot.yaml:
- Around line 58-60: The comment next to the checkout step incorrectly states
"Shallow clone" while fetch-depth: 0 performs a full clone; update the
actions/checkout usage by either changing the comment to reflect a full clone or
set fetch-depth: 1 to perform an actual shallow clone — modify the lines around
the actions/checkout entry and the fetch-depth: 0 key (also adjust the identical
occurrence later) so the comment and value are consistent.

---

Duplicate comments:
In @.github/workflows/deploy-runtime-apps-config.yaml:
- Around line 36-42: Do not interpolate github.event.inputs.rings directly into
the shell; instead pass the workflow input into an environment variable and
reference that env var inside the run block to avoid command injection: export
or set RINGS from the workflow inputs (so the shell sees $RINGS), fall back to
env.default-rings when empty, ensure you always use the quoted variable
expansion ("$RINGS") when testing/echoing, and then write ringsjson=${RINGS} to
GITHUB_OUTPUT; update the code that currently uses the literal '${{
github.event.inputs.rings }}' to use the environment variable and quoted
expansions for the rings variable and the final echo to GITHUB_OUTPUT.

---

Nitpick comments:
In @.github/workflows/deploy-runtime-apps-config.yaml:
- Around line 67-68: The run step invoking the Azure CLI uses GitHub Actions
expression interpolation (${ { env.REGISTRY_NAME }}) inside the run string;
change it to use shell environment variable expansion so the command becomes az
acr login --name "$REGISTRY_NAME" (i.e., reference REGISTRY_NAME via the shell
in the run step), ensuring the step that sets REGISTRY_NAME remains exported in
the job environment and keeping the step name az acr login unchanged.
- Around line 14-16: The default rings JSON is duplicated between the
workflow_dispatch input default for "rings" and the job-level env variable
"default-rings"; pick a single source of truth and reference it instead of
duplicating: remove the hard-coded JSON from the workflow_dispatch input default
and set the input's default to the env variable (e.g., reference
env.default-rings) or conversely remove the job-level env and read the workflow
input into env.default-rings at job start (use defaults: or set env:
default-rings: ${{ github.event.inputs.rings }}), ensuring only the unique
identifiers "rings" (workflow input) and "default-rings" (job env) are used and
kept in one place.
- Around line 6-7: Remove the feature branch trigger from the workflow push
triggers: locate the push triggers list that currently includes "main" and
"chore/runtime-app-configuration" and delete the
"chore/runtime-app-configuration" entry so only "main" remains; ensure the YAML
syntax (dash list) remains valid after removal and commit the change.

In `@infra/runtime/apps-config/at22/kustomization.yaml`:
- Around line 1-53: The overlay duplicates many environment-specific endpoint
URLs across kustomizations; update the at22 overlay to compute hostname once and
substitute it into endpoints instead of hardcoding each URL by: replace the
repeated full URLs in the ConfigMap patches (targets
apps-runtime-common-config-env and apps-runtime-common-config, including the
runtime-overrides.json value) with templates that use a single HOST variable for
host (e.g. HOST=at22.altinn.cloud) and switch to Kustomize replacements or Flux
postBuild.substitute to inject that HOST into each endpoint pattern, so future
overlays only change the HOST value rather than every URL.

@martinothamar martinothamar force-pushed the chore/runtime-app-configuration branch from 3b21572 to 76ddf19 Compare February 17, 2026 08:27
@martinothamar martinothamar merged commit 6b248bb into main Feb 17, 2026
3 checks passed
@martinothamar martinothamar deleted the chore/runtime-app-configuration branch February 17, 2026 09:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-releasenotes Issues that do not make sense to list in our release notes skip-second-approval Pull requests that only need one approval from a reviewer.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants