Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .azure/pipeline-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Codeflow Azure Pipeline Setup

The Codeflow engine deployment workflow uses GitHub Actions OIDC with a user-assigned managed identity. Do not use the legacy `AZURE_CREDENTIALS` JSON secret for the production deploy path.

## Production Environment Values

Create a GitHub environment named `production` and configure these environment variables:

| Variable | Purpose |
| --- | --- |
| `AZURE_CLIENT_ID` | Client ID of the pipeline user-assigned managed identity. |
| `AZURE_TENANT_ID` | Tenant ID for the Azure subscription. |
| `AZURE_SUBSCRIPTION_ID` | Subscription containing Codeflow production resources. |
| `AZURE_RESOURCE_GROUP` | Production resource group, expected default: `pvc-prod-codeflow-rg`. |
| `AZURE_CONTAINER_APP` | Production Container App, expected default: `pvc-prod-codeflow-api`. |
| `AZURE_CONTAINER_REGISTRY` | ACR name for production images, expected default: `pvcprodcodeflowacr`. |

The workflow deploys only to existing infrastructure. Provision or import the production Container App and ACR before running the deploy job.

Do not apply the root `orchestration/infrastructure/terraform` stack as the runtime prerequisite without reviewing it first; that stack still reflects an older AKS-shaped deployment. Use `orchestration/infrastructure/terraform/runtime` for the production Container App runtime stack.

## Azure Setup

Run `scripts/setup-azure-auth-for-pipeline.ps1` after confirming the production resource group exists. The script creates a dedicated pipeline identity, assigns resource-group scoped RBAC, grants ACR push access, and adds a federated credential for the GitHub `production` environment.

The signed-in Azure CLI identity running the script must be allowed to create role assignments on the deployment resource group or subscription. Use `Owner`, `User Access Administrator`, `Role Based Access Control Administrator`, or another role that includes `Microsoft.Authorization/roleAssignments/write`; `Contributor` alone is not sufficient for the RBAC step.

After setup, store the script outputs in the GitHub `production` environment variables. Keep any approval gates on the environment so pushes to `master` still require explicit deployment approval.
66 changes: 50 additions & 16 deletions .github/workflows/deploy-autopr-engine.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Build and Deploy CodeFlow Engine

Check warning on line 1 in .github/workflows/deploy-autopr-engine.yml

View workflow job for this annotation

GitHub Actions / Validate YAML Files

1:1 [document-start] missing document start "---"

on:
push:
Expand All @@ -8,17 +8,20 @@
- "engine/**"
- ".github/workflows/deploy-autopr-engine.yml"
- ".github/app-manifest.yml"
- ".azure/pipeline-setup.md"
- "scripts/setup-azure-auth-for-pipeline.ps1"
pull_request:
paths:
- "engine/**"
- ".github/workflows/deploy-autopr-engine.yml"
- ".github/app-manifest.yml"
- ".codeflow.yml"
- ".azure/pipeline-setup.md"
- "scripts/setup-azure-auth-for-pipeline.ps1"
workflow_dispatch:

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
IMAGE_REPOSITORY: codeflow-engine

jobs:
# PR validation - build and validate only, no push/deploy
Expand Down Expand Up @@ -70,28 +73,39 @@
name: Build and Push Container Image
runs-on: ubuntu-latest
if: github.event_name != 'pull_request'
environment: production
permissions:
contents: read
packages: write
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@v4
Comment on lines 81 to 82

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files .github/workflows/deploy-autopr-engine.yml || true

echo
echo "Workflow around checkout and later steps:"
if [ -f .github/workflows/deploy-autopr-engine.yml ]; then
  nl -ba .github/workflows/deploy-autopr-engine.yml | sed -n '1,140p'
fi

echo
echo "Search for git commands and checkout arguments in workflow:"
if [ -f .github/workflows/deploy-autopr-engine.yml ]; then
  rg -n "git |checkout@v4|persist-credentials|GITHUB_TOKEN|github_token|gitlab|npm|make|cargo|docker|gh " .github/workflows/deploy-autopr-engine.yml || true
fi

Repository: phoenixvc/codeflow-engine

Length of output: 297


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Workflow content:"
awk '{ printf "%6d\t%s\n", NR, $0 }' .github/workflows/deploy-autopr-engine.yml

echo
echo "Search relevant commands:"
grep -Enio "git[ /]|checkout@v4|persist-credentials|GITHUB_TOKEN|github_token|npm|make|cargo|docker|gh |curl" .github/workflows/deploy-autopr-engine.yml || true

Repository: phoenixvc/codeflow-engine

Length of output: 7357


Disable persisted checkout credentials.

Only Docker builds and Azure updates follow this checkout, with no authenticated Git access needed. Set persist-credentials: false so GITHUB_TOKEN is not stored in local Git config during the build.

Proposed fix
       - name: Checkout code
         uses: actions/checkout@v4
+        with:
+          persist-credentials: false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Checkout code
uses: actions/checkout@v4
- name: Checkout code
uses: actions/checkout@v4
with:
persist-credentials: false
🧰 Tools
🪛 zizmor (1.26.1)

[warning] 81-82: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/deploy-autopr-engine.yml around lines 81 - 82, Update the
“Checkout code” step using actions/checkout@v4 to set persist-credentials to
false, ensuring the workflow does not retain GITHUB_TOKEN credentials in the
local Git configuration.

Source: Linters/SAST tools


- name: Azure Login
uses: azure/login@v2
with:
client-id: ${{ vars.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}

- name: Validate registry configuration
run: |
if [ -z "${{ vars.AZURE_CONTAINER_REGISTRY }}" ]; then
echo "::error::Configure AZURE_CONTAINER_REGISTRY in the production environment."
exit 1
fi

- name: Log in to Azure Container Registry
run: az acr login --name "${{ vars.AZURE_CONTAINER_REGISTRY }}"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
images: ${{ vars.AZURE_CONTAINER_REGISTRY }}.azurecr.io/${{ env.IMAGE_REPOSITORY }}
tags: |
type=ref,event=branch
type=ref,event=pr
Expand All @@ -118,20 +132,40 @@
runs-on: ubuntu-latest
needs: build-and-push
if: (github.ref == 'refs/heads/master' && github.event_name == 'push') || github.event_name == 'workflow_dispatch'
environment: production
permissions:
contents: read
id-token: write
steps:
- name: Azure Login
uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
client-id: ${{ vars.AZURE_CLIENT_ID }}
tenant-id: ${{ vars.AZURE_TENANT_ID }}
subscription-id: ${{ vars.AZURE_SUBSCRIPTION_ID }}

- name: Update existing Container App
env:
RESOURCE_GROUP: ${{ vars.AZURE_RESOURCE_GROUP }}
CONTAINER_APP: ${{ vars.AZURE_CONTAINER_APP }}
IMAGE: ${{ vars.AZURE_CONTAINER_REGISTRY }}.azurecr.io/${{ env.IMAGE_REPOSITORY }}:${{ github.ref_name }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== target file =="
wc -l .github/workflows/deploy-autopr-engine.yml || true

echo "== relevant workflow lines =="
sed -n '1,240p' .github/workflows/deploy-autopr-engine.yml || true

echo "== refs to deploy/build jobs and metadata =="
rg -n "metadata|IMAGE_REPOSITORY|build-and-push|needs\.|github\.ref_name|branches|INPUT_REF|pull_request|push|manual|workflow_dispatch|meta\.outputs" .github/workflows/deploy-autopr-engine.yml

Repository: phoenixvc/codeflow-engine

Length of output: 7210


🌐 Web query:

docker/metadata-action v5 type=ref,event=branch manual workflow_dispatch outputs.version

💡 Result:

In the docker/metadata-action (v5), the type=ref configuration is used to generate tags based on Git references for events such as branch, tag, and pull_request [1][2]. Crucially, workflow_dispatch is a GitHub event, not a valid ref type for the type=ref configuration [3]. While workflow_dispatch events are sometimes referenced in documentation tables to show how they behave when they trigger a workflow (e.g., they may associate with a branch reference), you cannot use type=ref,event=workflow_dispatch [3][4]. If you are attempting to use a manual input (such as an inputs.version from a workflow_dispatch event) as a tag, you should use the type=raw configuration with a custom value, rather than type=ref [3]. Example of using a manual input for tagging: tags: | type=raw,value=${{ github.event.inputs.version }} Alternatively, if you are using semver patterns with a manual version input, you can use the value attribute [5]: tags: | type=semver,pattern={{major}}.{{minor}}.{{patch}},value=${{ github.event.inputs.version }} The outputs.tags and outputs.labels generated by the action can then be accessed in subsequent steps, such as in the docker/build-push-action, using ${{ steps.meta.outputs.tags }} [1][6].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== metadata action outputs/tags relevant docs =="
python3 - <<'PY'
from urllib.request import urlopen, Request
url = "https://raw.githubusercontent.com/docker/metadata-action/v5/README.md"
req = Request(url, headers={"User-Agent": "CodeRabbit-review-verification"})
text = urlopen(req, timeout=20).read().decode()
lines = text.splitlines()
for i, line in enumerate(lines):
    if "outputs.tags" in line or "outputs.version" in line or "type=ref,event=branch" in line:
        start=max(0, i-3); end=min(len(lines), i+8)
        print(f"--- around line {i+1} ---")
        for j in range(start,end):
            print(f"{j+1:4}: {lines[j]}")
        print()
PY

Repository: phoenixvc/codeflow-engine

Length of output: 2806


🌐 Web query:

github docker metadata-action v5 source generate tags refs branch manual run ref_name

💡 Result:

When using docker/metadata-action in a GitHub Actions workflow triggered by a manual event like workflow_dispatch, you cannot directly use type=ref,event=branch (or other ref-based types) to automatically derive tags from the manual run's reference, as these types are designed for specific Git-event triggers (push, pull_request, etc.) [1][2][3]. To generate tags during a manual workflow_dispatch run, use type=raw and explicitly pass the reference name via the value attribute [4][3]. Example implementation: 1. Define an input in your workflow for the tag or branch name [3]. 2. Use type=raw in your metadata-action step to consume that input [3]. workflow configuration snippet: on: workflow_dispatch: inputs: tag_name: description: 'Tag or branch name to build' required: true default: 'main' jobs: docker: runs-on: ubuntu-latest steps: - name: Docker meta id: meta uses: docker/metadata-action@v5 with: images: name/app tags: | type=raw,value=${{ github.event.inputs.tag_name }} # Or use github.ref_name if the manual run is triggered on a specific branch # type=raw,value=${{ github.ref_name }} This approach bypasses the restrictions on ref-based tag generation by manually providing the value that the action should use for the image tag [4][3]. If you do not have a specific input, you can use ${{ github.ref_name }} directly as the value for type=raw, provided the workflow was triggered against the intended branch or tag context [1][3].

Citations:


🌐 Web query:

site:github.com/docker/metadata-action docker-metadata-action src tags branch refs manual branch sanitize

💡 Result:

The docker/metadata-action automatically handles tag sanitization to ensure compliance with Docker image tag specifications [1][2]. When generating tags—particularly from dynamic sources like branches or pull request references (via type=ref)—the action performs the following sanitization steps: 1. Character Replacement: It replaces sequences of invalid characters with a hyphen (-) [1][3]. While Docker tag specifications allow for lowercase/uppercase letters, digits, underscores, periods, and dashes, they have specific restrictions on positioning [1][4]. 2. Leading Character Stripping: The action strips leading dots (.) and hyphens (-) from tags, as these are not permitted as the first character of a Docker tag [4]. 3. Lowercasing: Although image names are strictly lowercased, the action typically preserves the casing of the input source (like branch names) unless specific configurations or behaviors apply [5]. Users sometimes encounter issues if the source reference (e.g., a branch name with uppercase letters) results in a tag that is rejected by a downstream registry or tool that expects strictly lowercase repository names [5]. For manual tag generation or when using raw inputs (e.g., type=raw), the action applies these same sanitization rules to ensure the resulting metadata is valid [4]. If a raw input sanitizes to an empty string, the action generally avoids creating an empty tag, often falling back to other defined values [4]. In summary, the action does not require manual sanitization of branch names or refs; it automatically processes them to meet Docker's syntax requirements [1][3]. If you are experiencing issues with tag validity in downstream processes (such as image pushes), it is often due to registry-specific requirements (like strict lowercasing) rather than a failure of the action's built-in sanitization logic [5].

Citations:


🌐 Web query:

docker metadata-action README outputs.version type ref github.ref_name workflow_dispatch

💡 Result:

In the docker/metadata-action GitHub Action, the version output is a string representing the generated Docker image version [1][2][3]. This version is derived based on the event that triggered the workflow and the Git reference provided [4][5]. Regarding the interaction between github.ref_name and workflow_dispatch: 1. Version Derivation: The docker/metadata-action automatically extracts metadata from the GitHub context, including the branch or tag name [5]. When a workflow is triggered by workflow_dispatch, it typically runs on the branch specified in the dispatch event (or the default branch if none is specified), and the action uses the corresponding Git reference to generate the version string [5]. 2. Event Behavior: For a workflow_dispatch event, the reference (github.ref_name) is the name of the branch from which the workflow was triggered [5]. The metadata-action uses this reference to help construct the image tags and the version output [5]. 3. Configuration: While the action automatically infers the version, you can influence how it is generated using the flavor and tags inputs in your workflow configuration to specify exactly how you want the version string or image tags to be formatted [1][3]. You can access the version output in your workflow using ${{ steps.<your_action_id>.outputs.version }} [1][3]. If you need more complex data, the json output provides a full object containing tags and labels that you can parse using fromJSON() [1][3].

Citations:


Deploy the exact tag emitted by the build job.

This workflow builds with steps.meta.outputs.tags but deploys by reconstructing the image tag from github.ref_name in later jobs. For manual dispatches or branch names containing characters that should be rewritten for Docker tag safety, the deploy can point at an image that was not built. Export steps.meta.outputs.version from build-and-push and use needs.build-and-push.outputs.image_tag in the deploy job, or at least tag all workflow_dispatch runs explicitly with the same type=ref,event=branch behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/deploy-autopr-engine.yml at line 151, Update the
build-and-push job to expose the exact image version from
steps.meta.outputs.version as its image_tag output, then change the deploy job’s
image reference to use needs.build-and-push.outputs.image_tag instead of
github.ref_name. Preserve the existing registry and repository components.

run: |
RESOURCE_GROUP="prod-rg-san-codeflow"
CONTAINER_APP="prod-codeflow-san-app"
IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}"
missing=0
for name in RESOURCE_GROUP CONTAINER_APP IMAGE; do
if [ -z "${!name}" ]; then
echo "::error::Missing required deployment value: $name"
missing=1
fi
done

if [ "$missing" -ne 0 ]; then
echo "::error::Configure the production environment variables documented in .azure/pipeline-setup.md."
exit 1
fi

if ! az containerapp show -n "$CONTAINER_APP" -g "$RESOURCE_GROUP" >/dev/null; then
echo "::error::Container App $CONTAINER_APP does not exist in $RESOURCE_GROUP. Create infrastructure from phoenixvc/codeflow-infrastructure first."
echo "::error::Cannot verify Container App $CONTAINER_APP in $RESOURCE_GROUP."
echo "::error::Confirm the app exists and the pipeline identity has access before deploying this image."
exit 1
fi

Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/pr-comment-handler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Quick checkout for config
uses: actions/checkout@v4
with:
sparse-checkout: configs/config.yaml
sparse-checkout: engine/configs/config.yaml
sparse-checkout-cone-mode: false

- name: Check if commenter is excluded bot
Expand All @@ -25,15 +25,15 @@ jobs:
echo "Checking if '$COMMENTER' is an excluded bot..."

# Check if bot exclusions are enabled
BOT_EXCLUSIONS_ENABLED=$(yq '.comment_analyzer.bot_exclusions.enabled // false' configs/config.yaml)
BOT_EXCLUSIONS_ENABLED=$(yq '.comment_analyzer.bot_exclusions.enabled // false' engine/configs/config.yaml)
if [ "$BOT_EXCLUSIONS_ENABLED" != "true" ]; then
echo "Bot exclusions disabled, processing comment"
echo "is_excluded=false" >> $GITHUB_OUTPUT
exit 0
fi

# Check excluded users list
EXCLUDED_USERS=$(yq '.comment_analyzer.bot_exclusions.excluded_users[]' configs/config.yaml 2>/dev/null || echo "")
EXCLUDED_USERS=$(yq '.comment_analyzer.bot_exclusions.excluded_users[]' engine/configs/config.yaml 2>/dev/null || echo "")
for user in $EXCLUDED_USERS; do
# Remove quotes from YAML output
user=$(echo "$user" | tr -d '"')
Expand All @@ -45,7 +45,7 @@ jobs:
done

# Check for [bot] suffix if enabled
EXCLUDE_BOT_SUFFIX=$(yq '.comment_analyzer.bot_exclusions.exclude_bot_suffix // false' configs/config.yaml)
EXCLUDE_BOT_SUFFIX=$(yq '.comment_analyzer.bot_exclusions.exclude_bot_suffix // false' engine/configs/config.yaml)
if [ "$EXCLUDE_BOT_SUFFIX" = "true" ]; then
if [[ "$COMMENTER" == *"[bot]" ]]; then
echo "User '$COMMENTER' has [bot] suffix, skipping"
Expand All @@ -61,7 +61,7 @@ jobs:
if: steps.check_bot.outputs.is_excluded != 'true'
id: check_config
run: |
ENABLED=$(yq '.comment_analyzer.enabled // false' configs/config.yaml)
ENABLED=$(yq '.comment_analyzer.enabled // false' engine/configs/config.yaml)
echo "result=$ENABLED" >> $GITHUB_OUTPUT

- name: Full checkout
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/validate-templates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ name: Validate Templates

on:
push:
branches:
- master
paths:
- "engine/templates/**/*.yml"
- "engine/templates/**/*.yaml"
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,13 @@ Thumbs.db
# Build artifacts
build-artifacts/

# Terraform local artifacts
**/.terraform/
*.tfstate
*.tfstate.*
*.tfplan
tfplan

# Credentials and sensitive files
.credentials-*.json
deployment-output.json
Expand Down
13 changes: 7 additions & 6 deletions orchestration/infrastructure/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ exception documented next to the stack.

## Naming

Current Codeflow resource names use:
Current Codeflow resource names follow the ADR-0027 style: structured identifiers with no trailing
region suffix. Region remains expressed by the resource group location.

- Resource group: `prod-rg-san-codeflow`
- Website Static Web App: `prod-stapp-san-codeflow`
- Runtime Container App: `prod-codeflow-san-app`
- Resource group: `pvc-prod-codeflow-rg`
- Website Static Web App: `pvc-prod-codeflow-swa`
- Runtime Container App: `pvc-prod-codeflow-api`

Keep future names aligned with `{env}-{resource-type}-{region}-codeflow` unless a provider
constraint requires otherwise.
Keep future names aligned with `pvc-{env}-codeflow-{type}` unless a provider constraint requires
otherwise. Storage accounts and ACR names omit dashes.
22 changes: 22 additions & 0 deletions orchestration/infrastructure/terraform/runtime/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions orchestration/infrastructure/terraform/runtime/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Codeflow Runtime Terraform

This stack owns the Azure Container Apps runtime for Codeflow Engine.

Names follow the ADR-0027-style convention used for live Codeflow resources:

- Resource group: `pvc-prod-codeflow-rg`
- Container App: `pvc-prod-codeflow-api`
- Container Apps Environment: `pvc-prod-codeflow-cae`
- Log Analytics Workspace: `pvc-prod-codeflow-law`
- Container Registry: `pvcprodcodeflowacr`

The stack expects the Codeflow image to exist in ACR. For a first-time bootstrap before the image is
available, override `initial_image` with a temporary public image, then switch it back to the ACR
image after the first build.
121 changes: 121 additions & 0 deletions orchestration/infrastructure/terraform/runtime/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
data "azurerm_resource_group" "codeflow" {
name = var.resource_group_name
}

resource "azurerm_log_analytics_workspace" "runtime" {
name = var.log_analytics_workspace_name
location = var.location
resource_group_name = data.azurerm_resource_group.codeflow.name
sku = "PerGB2018"
retention_in_days = 30

tags = var.tags
}

resource "azurerm_container_registry" "runtime" {
name = var.container_registry_name
location = var.location
resource_group_name = data.azurerm_resource_group.codeflow.name
sku = "Basic"
admin_enabled = false

tags = var.tags
}

resource "azurerm_user_assigned_identity" "container_app" {
name = var.container_app_identity_name
location = var.location
resource_group_name = data.azurerm_resource_group.codeflow.name

tags = var.tags
}

resource "azurerm_role_assignment" "container_app_acr_pull" {
scope = azurerm_container_registry.runtime.id
role_definition_name = "AcrPull"
principal_id = azurerm_user_assigned_identity.container_app.principal_id
}

resource "azurerm_container_app_environment" "runtime" {
name = var.container_app_environment_name
location = var.location
resource_group_name = data.azurerm_resource_group.codeflow.name
log_analytics_workspace_id = azurerm_log_analytics_workspace.runtime.id

tags = var.tags
}

resource "azurerm_container_app" "api" {
name = var.container_app_name
container_app_environment_id = azurerm_container_app_environment.runtime.id
resource_group_name = data.azurerm_resource_group.codeflow.name
revision_mode = "Single"

identity {
type = "UserAssigned"
identity_ids = [azurerm_user_assigned_identity.container_app.id]
}

registry {
server = azurerm_container_registry.runtime.login_server
identity = azurerm_user_assigned_identity.container_app.id
}

ingress {
external_enabled = true
target_port = 8080

traffic_weight {
percentage = 100
latest_revision = true
}
}

template {
min_replicas = 0
max_replicas = 1

container {
name = "codeflow-engine"
image = var.initial_image
Comment on lines +78 to +80

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file outline/size =="
wc -l orchestration/infrastructure/terraform/runtime/main.tf 2>/dev/null || true

echo "== relevant main.tf lines =="
sed -n '1,140p' orchestration/infrastructure/terraform/runtime/main.tf 2>/dev/null || true

echo "== search initial_image and workflow/image refs =="
rg -n "initial_image|workflow|image|ContainerApp|containerregistry|azure\.containerapps|azuredevops|github\.actions" orchestration/infrastructure -S || true
rg -n "initial_image|workflow-deploy|production dispatch|dispatch|ref|image" . -g '!**/.git/**' -g '!**/node_modules/**' -S | head -200

echo "== git diff stat if available =="
git diff --stat HEAD 2>/dev/null || true
git diff -- orchestration/infrastructure/terraform/runtime/main.tf 2>/dev/null | sed -n '1,220p' || true

Repository: phoenixvc/codeflow-engine

Length of output: 42293


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow files matching deploy-codeflow-engine or similar =="
git ls-files .github orchestration/infrastructure -z | tr '\0' '\n' | rg '(\.github/workflows/.*(deploy-codeflow-engine|deploy).*\.ya?ml|deploy-codeflow-engine)' || true

echo "== deploy workflow outline/content =="
fd -p '.github/workflows/deploy-codeflow-engine.yml' . -x sh -c 'echo "--- $1"; sed -n "1,220p" "$1"' sh {} 2>/dev/null || true

echo "== terraform lifecycle directives =="
rg -n "lifecycle|ignore_changes|azurerm_container_app|initial_image" orchestration/infrastructure/terraform -S || true

echo "== runtime variables/docs relevant =="
sed -n '1,90p' orchestration/infrastructure/terraform/runtime/variables.tf
sed -n '1,30p' orchestration/infrastructure/terraform/runtime/README.md

Repository: phoenixvc/codeflow-engine

Length of output: 4235


Prevent Terraform from reverting workflow-deployed images.

azurerm_container_app.api still defaults the image to var.initial_image, so any workflow/manual update to the same Container App can be overwritten by the next terraform apply. Give one system ownership of the image: route post-bootstrap deploys through Terraform, or add lifecycle { ignore_changes = [template[0].container[0].image] } for runtime-managed deploys.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@orchestration/infrastructure/terraform/runtime/main.tf` around lines 78 - 80,
Update the azurerm_container_app.api image ownership so Terraform does not
overwrite workflow or manual image deployments: either route post-bootstrap
image changes through Terraform, or add a lifecycle ignore_changes rule
targeting template[0].container[0].image for runtime-managed deployments.
Preserve var.initial_image for initial provisioning.

cpu = 0.5
memory = "1Gi"

env {
name = "CODEFLOW_JSON_LOGGING"
value = "true"
}

env {
name = "CODEFLOW_LOG_LEVEL"
value = "INFO"
}

env {
name = "CODEFLOW_SKIP_DB_INIT"
value = "1"
}

env {
name = "CODEFLOW_STORAGE_BACKEND"
value = "memory"
}

env {
name = "ENVIRONMENT"
value = "staging"
}
Comment on lines +104 to +107

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Set the production runtime environment correctly.

The resources, tags, documentation, and deployment workflow target production, but the Container App sets ENVIRONMENT=staging. This can select staging behavior in the production deployment; use production or an explicit production variable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@orchestration/infrastructure/terraform/runtime/main.tf` around lines 104 -
107, Update the ENVIRONMENT value in the runtime env block from staging to
production, using the repository’s established production environment variable
if one exists; leave the surrounding Container App configuration unchanged.


env {
name = "PORT"
value = "8080"
}
}
}

depends_on = [
azurerm_role_assignment.container_app_acr_pull
]

tags = var.tags
}
Loading
Loading