From 6a362c00d4c2b008222e3f2aa41f8cbd4e5b3cd5 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 15:35:15 +0200 Subject: [PATCH 001/123] Support plan-diff --- action.yml | 61 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/action.yml b/action.yml index 75e08bde..97aa3cbf 100644 --- a/action.yml +++ b/action.yml @@ -22,7 +22,7 @@ inputs: atmos-version: description: The version of atmos to install required: false - default: ">= 1.158.0" + default: ">= 1.184.0" atmos-config-path: description: The path to the atmos.yaml file required: true @@ -238,7 +238,8 @@ runs: COMPONENT_NAME=$(echo "${{ inputs.component }}" | sed 's#/#_#g') COMPONENT_SLUG="$STACK_NAME-$COMPONENT_NAME" COMPONENT_CACHE_KEY=$(basename "${{ fromJson(steps.atmos-settings.outputs.settings).component-path }}") - PLAN_FILE="${COMPONENT_PATH}/$COMPONENT_SLUG-${{ inputs.sha }}.planfile" + PLAN_FILE="${COMPONENT_PATH}/$COMPONENT_SLUG.planfile" + RETRIEVED_PLAN_FILE="${COMPONENT_PATH}/$COMPONENT_SLUG-${{ inputs.sha }}.planfile" LOCK_FILE="${COMPONENT_PATH}/.terraform.lock.hcl" echo "stack_name=$STACK_NAME" >> $GITHUB_OUTPUT @@ -247,6 +248,7 @@ runs: echo "component_path=${COMPONENT_PATH}" >> $GITHUB_OUTPUT echo "cache-key=${COMPONENT_CACHE_KEY}" >> $GITHUB_OUTPUT echo "plan_file=$PLAN_FILE" >> $GITHUB_OUTPUT + echo "retrieved_plan_file=$RETRIEVED_PLAN_FILE" >> $GITHUB_OUTPUT echo "lock_file=$LOCK_FILE" >> $GITHUB_OUTPUT - name: Configure Plan AWS Credentials @@ -318,6 +320,42 @@ runs: role-session-name: "atmos-terraform-apply-gitops" mask-aws-account-id: "no" + - name: Cache .terraform + id: cache + uses: actions/cache@v4 + if: env.ACTIONS_ENABLED == 'true' + with: + path: | + ${{ steps.vars.outputs.component_path }}/.terraform + key: ${{ steps.vars.outputs.cache-key }} + + - name: Plan prepare + if: env.ACTIONS_ENABLED == 'true' + id: plan-diff + shell: bash + run: | + set +e + + # Remove the environment file from the cache to avoid conflicts with workspace select + rm -f ./.terraform/environment + + if [[ "${{ inputs.plan-storage == 'true' }}" == "true" ]]; then + atmos terraform plan-diff ${{ inputs.component }} \ + --stack ${{ inputs.stack }} \ + -input=false \ + -no-color \ + --orig ${{ steps.vars.outputs.retrieved_plan_file }} + PLAN_CHANGED=$? + else + atmos terraform plan ${{ inputs.component }} \ + --stack ${{ inputs.stack }} \ + -input=false \ + -no-color + PLAN_CHANGED=$? + fi + + echo "plan_changed=$PLAN_CHANGED" >> $GITHUB_OUTPUT + - name: Check Whether Infracost is Enabled if: env.ACTIONS_ENABLED == 'true' shell: bash @@ -335,7 +373,7 @@ runs: api-key: ${{ inputs.infracost-api-key }} - name: Convert PLANFILE to JSON - if: ${{ fromJson(steps.atmos-settings.outputs.settings).enable-infracost == 'true' && steps.atmos-plan.outputs.changes == 'true' }} + if: env.INFRACOST_ENABLED == 'true' shell: bash working-directory: ${{ steps.vars.outputs.component_path }} run: | @@ -380,15 +418,6 @@ runs: echo "infracost_details_diff_breakdown=$INFRACOST_DETAILS_DIFF_BREAKDOWN" >> "$GITHUB_OUTPUT" echo "infracost_diff_total_monthly_cost=$INFRACOST_DIFF_TOTAL_MONTHLY_COST" >> "$GITHUB_OUTPUT" - - name: Cache .terraform - id: cache - uses: actions/cache@v4 - if: env.ACTIONS_ENABLED == 'true' - with: - path: | - ${{ steps.vars.outputs.component_path }}/.terraform - key: ${{ steps.vars.outputs.cache-key }} - - name: Terraform Apply if: env.ACTIONS_ENABLED == 'true' id: apply @@ -401,6 +430,10 @@ runs: TERRAFORM_OUTPUT_FILE="./terraform-${GITHUB_RUN_ID}-output.txt" + if [[ "${{steps.plan-diff.outputs.plan_changed}}" != "0" ]]; then + exit 1 + fi + tfcmt \ --config "${GITHUB_ACTION_PATH}/config/atmos_github_summary.yaml" \ -var "target:${{ inputs.stack }}-${{ inputs.component }}" \ @@ -414,11 +447,11 @@ runs: --output "${{ github.workspace }}/atmos-apply-summary.md" \ --log-level $([[ "${{ inputs.debug }}" == "true" ]] && echo "DEBUG" || echo "INFO") \ apply -- \ - atmos terraform apply ${{ inputs.component }} \ + atmos terraform deploy ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ - -auto-approve \ -input=false \ -no-color \ + --planfile ${{ steps.vars.outputs.plan_file }} &> ${TERRAFORM_OUTPUT_FILE} TERRAFORM_RESULT=$? From c7bffc1e5286b1b092dce028988874c1c3f4ee1d Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 15:44:34 +0200 Subject: [PATCH 002/123] Support plan-diff --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 97aa3cbf..cf045129 100644 --- a/action.yml +++ b/action.yml @@ -239,7 +239,7 @@ runs: COMPONENT_SLUG="$STACK_NAME-$COMPONENT_NAME" COMPONENT_CACHE_KEY=$(basename "${{ fromJson(steps.atmos-settings.outputs.settings).component-path }}") PLAN_FILE="${COMPONENT_PATH}/$COMPONENT_SLUG.planfile" - RETRIEVED_PLAN_FILE="${COMPONENT_PATH}/$COMPONENT_SLUG-${{ inputs.sha }}.planfile" + RETRIEVED_PLAN_FILE="$COMPONENT_SLUG-${{ inputs.sha }}.planfile" LOCK_FILE="${COMPONENT_PATH}/.terraform.lock.hcl" echo "stack_name=$STACK_NAME" >> $GITHUB_OUTPUT From d6eacbafbd40ee15ac6c9b2e42eacf994485746a Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 15:53:50 +0200 Subject: [PATCH 003/123] Support plan-diff --- action.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/action.yml b/action.yml index cf045129..61885f4f 100644 --- a/action.yml +++ b/action.yml @@ -239,7 +239,8 @@ runs: COMPONENT_SLUG="$STACK_NAME-$COMPONENT_NAME" COMPONENT_CACHE_KEY=$(basename "${{ fromJson(steps.atmos-settings.outputs.settings).component-path }}") PLAN_FILE="${COMPONENT_PATH}/$COMPONENT_SLUG.planfile" - RETRIEVED_PLAN_FILE="$COMPONENT_SLUG-${{ inputs.sha }}.planfile" + RETRIEVED_PLAN_FILENAME="$COMPONENT_SLUG-${{ inputs.sha }}.planfile" + RETRIEVED_PLAN_FILE="${COMPONENT_PATH}/${RETRIEVED_PLAN_FILENAME}" LOCK_FILE="${COMPONENT_PATH}/.terraform.lock.hcl" echo "stack_name=$STACK_NAME" >> $GITHUB_OUTPUT @@ -248,6 +249,7 @@ runs: echo "component_path=${COMPONENT_PATH}" >> $GITHUB_OUTPUT echo "cache-key=${COMPONENT_CACHE_KEY}" >> $GITHUB_OUTPUT echo "plan_file=$PLAN_FILE" >> $GITHUB_OUTPUT + echo "retrieved_plan_filename=$RETRIEVED_PLAN_FILENAME" >> $GITHUB_OUTPUT echo "retrieved_plan_file=$RETRIEVED_PLAN_FILE" >> $GITHUB_OUTPUT echo "lock_file=$LOCK_FILE" >> $GITHUB_OUTPUT @@ -275,7 +277,7 @@ runs: with: action: getPlan commitSHA: ${{ inputs.sha }} - planPath: ${{ steps.vars.outputs.plan_file }} + planPath: ${{ steps.vars.outputs.retrieved_plan_file }} component: ${{ inputs.component }} stack: ${{ inputs.stack }} planRepositoryType: ${{ fromJson(steps.atmos-settings.outputs.settings).plan-repository-type || 's3' }} @@ -344,7 +346,7 @@ runs: --stack ${{ inputs.stack }} \ -input=false \ -no-color \ - --orig ${{ steps.vars.outputs.retrieved_plan_file }} + --orig ${{ steps.vars.outputs.retrieved_plan_filename }} PLAN_CHANGED=$? else atmos terraform plan ${{ inputs.component }} \ From 4cc3c5358bfbb49806f94de022ddad5663c8a960 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 16:33:01 +0200 Subject: [PATCH 004/123] Support plan-diff --- .github/workflows/test-atmos-pro-enabled.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/test-atmos-pro-enabled.yml b/.github/workflows/test-atmos-pro-enabled.yml index 323aa8f8..1097cdca 100644 --- a/.github/workflows/test-atmos-pro-enabled.yml +++ b/.github/workflows/test-atmos-pro-enabled.yml @@ -3,9 +3,6 @@ name: "Test - Atmos Pro Enabled" on: workflow_dispatch: {} - pull_request: - types: [opened, synchronize, reopened] - env: AWS_REGION: us-east-2 @@ -47,7 +44,7 @@ jobs: cat ${{ runner.temp }}/atmos.yaml - name: Plan Atmos Component - uses: cloudposse/github-action-atmos-terraform-plan@v4 + uses: cloudposse/github-action-atmos-terraform-plan@v5 with: component: "foobar-atmos-pro" stack: "plat-ue2-sandbox" From c0b4079a47e3898c2d274767a3a35a89f8d2dc0f Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 19:49:53 +0200 Subject: [PATCH 005/123] Support plan-diff --- action.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index 61885f4f..fdffe3d2 100644 --- a/action.yml +++ b/action.yml @@ -238,7 +238,7 @@ runs: COMPONENT_NAME=$(echo "${{ inputs.component }}" | sed 's#/#_#g') COMPONENT_SLUG="$STACK_NAME-$COMPONENT_NAME" COMPONENT_CACHE_KEY=$(basename "${{ fromJson(steps.atmos-settings.outputs.settings).component-path }}") - PLAN_FILE="${COMPONENT_PATH}/$COMPONENT_SLUG.planfile" + PLAN_FILE="$COMPONENT_SLUG.planfile" RETRIEVED_PLAN_FILENAME="$COMPONENT_SLUG-${{ inputs.sha }}.planfile" RETRIEVED_PLAN_FILE="${COMPONENT_PATH}/${RETRIEVED_PLAN_FILENAME}" LOCK_FILE="${COMPONENT_PATH}/.terraform.lock.hcl" @@ -253,7 +253,7 @@ runs: echo "retrieved_plan_file=$RETRIEVED_PLAN_FILE" >> $GITHUB_OUTPUT echo "lock_file=$LOCK_FILE" >> $GITHUB_OUTPUT - - name: Configure Plan AWS Credentials + - name: Configure Plan Storage AWS Credentials uses: aws-actions/configure-aws-credentials@v4 if: ${{ ( fromJson(steps.atmos-settings.outputs.settings).plan-repository-type == 's3' || fromJson(steps.atmos-settings.outputs.settings).plan-repository-type == '' || @@ -384,6 +384,7 @@ runs: - name: Generate Infracost Diff if: env.INFRACOST_ENABLED == 'true' shell: bash + working-directory: ${{ steps.vars.outputs.component_path }} run: | infracost diff \ --path="${{ steps.vars.outputs.plan_file }}.json" \ @@ -399,6 +400,7 @@ runs: - name: Debug Infracost if: env.INFRACOST_ENABLED == 'true' && env.DEBUG_ENABLED == 'true' shell: bash + working-directory: ${{ steps.vars.outputs.component_path }} run: | cat ${{ steps.vars.outputs.plan_file }}.json cat /tmp/infracost.txt From 9eff5af1dde69fdaa0810544fc098818a70ecf1f Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 20:00:49 +0200 Subject: [PATCH 006/123] Support plan-diff --- action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index fdffe3d2..ed49d9ba 100644 --- a/action.yml +++ b/action.yml @@ -409,6 +409,7 @@ runs: - name: Set Infracost Variables if: env.INFRACOST_ENABLED == 'true' id: infracost-diff + working-directory: ${{ steps.vars.outputs.component_path }} shell: bash run: | if [[ "${{ fromJson(steps.atmos-settings.outputs.settings).enable-infracost }}" == "true" ]]; then @@ -455,7 +456,7 @@ runs: --stack ${{ inputs.stack }} \ -input=false \ -no-color \ - --planfile ${{ steps.vars.outputs.plan_file }} + --from-plan &> ${TERRAFORM_OUTPUT_FILE} TERRAFORM_RESULT=$? From 0626b68681c5daa2535e2bf3fc21897445d3382e Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 20:09:03 +0200 Subject: [PATCH 007/123] Support plan-diff --- action.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/action.yml b/action.yml index ed49d9ba..1fb97f9f 100644 --- a/action.yml +++ b/action.yml @@ -356,6 +356,8 @@ runs: PLAN_CHANGED=$? fi + ls -l ${{ steps.vars.outputs.component_path }} + echo "plan_changed=$PLAN_CHANGED" >> $GITHUB_OUTPUT - name: Check Whether Infracost is Enabled @@ -439,6 +441,8 @@ runs: exit 1 fi + ls -l ${{ steps.vars.outputs.component_path }} + tfcmt \ --config "${GITHUB_ACTION_PATH}/config/atmos_github_summary.yaml" \ -var "target:${{ inputs.stack }}-${{ inputs.component }}" \ From 6b5bd33d305830643631202bbba30f8c1e161847 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 20:39:33 +0200 Subject: [PATCH 008/123] Support plan-diff --- action.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/action.yml b/action.yml index 1fb97f9f..f4d9515b 100644 --- a/action.yml +++ b/action.yml @@ -341,18 +341,20 @@ runs: # Remove the environment file from the cache to avoid conflicts with workspace select rm -f ./.terraform/environment + atmos terraform plan ${{ inputs.component }} \ + --stack ${{ inputs.stack }} \ + -input=false \ + -no-color + + PLAN_CHANGED=$? + if [[ "${{ inputs.plan-storage == 'true' }}" == "true" ]]; then atmos terraform plan-diff ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ -input=false \ -no-color \ --orig ${{ steps.vars.outputs.retrieved_plan_filename }} - PLAN_CHANGED=$? - else - atmos terraform plan ${{ inputs.component }} \ - --stack ${{ inputs.stack }} \ - -input=false \ - -no-color + --new ${{ steps.vars.outputs.plan_file }} PLAN_CHANGED=$? fi From 592701b4f16b197273d54d956154cfb91195a397 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 20:43:22 +0200 Subject: [PATCH 009/123] Support plan-diff --- action.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index f4d9515b..97dc9ff0 100644 --- a/action.yml +++ b/action.yml @@ -341,19 +341,23 @@ runs: # Remove the environment file from the cache to avoid conflicts with workspace select rm -f ./.terraform/environment + ls -l ${{ steps.vars.outputs.component_path }} + atmos terraform plan ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ -input=false \ -no-color + ls -l ${{ steps.vars.outputs.component_path }} + PLAN_CHANGED=$? - + if [[ "${{ inputs.plan-storage == 'true' }}" == "true" ]]; then atmos terraform plan-diff ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ -input=false \ -no-color \ - --orig ${{ steps.vars.outputs.retrieved_plan_filename }} + --orig ${{ steps.vars.outputs.retrieved_plan_filename }} \ --new ${{ steps.vars.outputs.plan_file }} PLAN_CHANGED=$? fi From 0a4aac22def3d93b26eac30039fd6a17e66d4cdc Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 20:53:52 +0200 Subject: [PATCH 010/123] Support plan-diff --- action.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/action.yml b/action.yml index 97dc9ff0..d69fbb4e 100644 --- a/action.yml +++ b/action.yml @@ -341,15 +341,11 @@ runs: # Remove the environment file from the cache to avoid conflicts with workspace select rm -f ./.terraform/environment - ls -l ${{ steps.vars.outputs.component_path }} - atmos terraform plan ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ -input=false \ -no-color - ls -l ${{ steps.vars.outputs.component_path }} - PLAN_CHANGED=$? if [[ "${{ inputs.plan-storage == 'true' }}" == "true" ]]; then @@ -357,8 +353,9 @@ runs: --stack ${{ inputs.stack }} \ -input=false \ -no-color \ - --orig ${{ steps.vars.outputs.retrieved_plan_filename }} \ - --new ${{ steps.vars.outputs.plan_file }} + --skip-init \ + --orig=${{ steps.vars.outputs.retrieved_plan_filename }} \ + --new=${{ steps.vars.outputs.plan_file }} PLAN_CHANGED=$? fi From df2958006be7d2c07103f5fa1d91f47f3fc74a4d Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 20:57:15 +0200 Subject: [PATCH 011/123] Support plan-diff --- action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index d69fbb4e..fe2049f8 100644 --- a/action.yml +++ b/action.yml @@ -354,8 +354,8 @@ runs: -input=false \ -no-color \ --skip-init \ - --orig=${{ steps.vars.outputs.retrieved_plan_filename }} \ - --new=${{ steps.vars.outputs.plan_file }} + --orig ${{ steps.vars.outputs.retrieved_plan_filename }} \ + --new ${{ steps.vars.outputs.plan_file }} PLAN_CHANGED=$? fi From 48c772d1473d7533cc16e3c01cfd653457f3e3db Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 21:03:53 +0200 Subject: [PATCH 012/123] Support plan-diff --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index fe2049f8..ede2ed70 100644 --- a/action.yml +++ b/action.yml @@ -350,10 +350,10 @@ runs: if [[ "${{ inputs.plan-storage == 'true' }}" == "true" ]]; then atmos terraform plan-diff ${{ inputs.component }} \ + --skip-init \ --stack ${{ inputs.stack }} \ -input=false \ -no-color \ - --skip-init \ --orig ${{ steps.vars.outputs.retrieved_plan_filename }} \ --new ${{ steps.vars.outputs.plan_file }} PLAN_CHANGED=$? From 98bffbd63e00571b5284dcd2f396660ddba7a884 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 21:08:06 +0200 Subject: [PATCH 013/123] Support plan-diff --- action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index ede2ed70..c6923ce5 100644 --- a/action.yml +++ b/action.yml @@ -350,12 +350,12 @@ runs: if [[ "${{ inputs.plan-storage == 'true' }}" == "true" ]]; then atmos terraform plan-diff ${{ inputs.component }} \ - --skip-init \ --stack ${{ inputs.stack }} \ -input=false \ -no-color \ --orig ${{ steps.vars.outputs.retrieved_plan_filename }} \ - --new ${{ steps.vars.outputs.plan_file }} + --new ${{ steps.vars.outputs.plan_file }} \ + --skip-init PLAN_CHANGED=$? fi From ad48f3bba195e2a03b0e23315a87187113aac0cd Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 21:22:38 +0200 Subject: [PATCH 014/123] Support plan-diff --- action.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index c6923ce5..49457e2c 100644 --- a/action.yml +++ b/action.yml @@ -349,12 +349,15 @@ runs: PLAN_CHANGED=$? if [[ "${{ inputs.plan-storage == 'true' }}" == "true" ]]; then + + cp ${{ steps.vars.outputs.component_path }}/${{ steps.vars.outputs.plan_file }} ${{ steps.vars.outputs.component_path }}/new.${{ steps.vars.outputs.plan_file }} + atmos terraform plan-diff ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ -input=false \ -no-color \ --orig ${{ steps.vars.outputs.retrieved_plan_filename }} \ - --new ${{ steps.vars.outputs.plan_file }} \ + --new new.${{ steps.vars.outputs.plan_file }} \ --skip-init PLAN_CHANGED=$? fi From 518c2fa321d47bc4605936b368071e16456c9ba2 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 21:27:04 +0200 Subject: [PATCH 015/123] Support plan-diff --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 49457e2c..42a97f72 100644 --- a/action.yml +++ b/action.yml @@ -466,7 +466,7 @@ runs: --stack ${{ inputs.stack }} \ -input=false \ -no-color \ - --from-plan + --planfile new.${{ steps.vars.outputs.plan_file }} &> ${TERRAFORM_OUTPUT_FILE} TERRAFORM_RESULT=$? From 3583afe14bab926f3e9b813be3098bd0bd1ce579 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 23:07:06 +0200 Subject: [PATCH 016/123] Support plan-diff --- action.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/action.yml b/action.yml index 42a97f72..ff715184 100644 --- a/action.yml +++ b/action.yml @@ -462,11 +462,11 @@ runs: --output "${{ github.workspace }}/atmos-apply-summary.md" \ --log-level $([[ "${{ inputs.debug }}" == "true" ]] && echo "DEBUG" || echo "INFO") \ apply -- \ - atmos terraform deploy ${{ inputs.component }} \ + atmos terraform apply ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ -input=false \ - -no-color \ - --planfile new.${{ steps.vars.outputs.plan_file }} + -no-color \ + new.${{ steps.vars.outputs.plan_file }} &> ${TERRAFORM_OUTPUT_FILE} TERRAFORM_RESULT=$? From 3449d11c2e3c428c0e9eadf32b0fdf670c9ee0d8 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 23:12:19 +0200 Subject: [PATCH 017/123] Support plan-diff --- action.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index ff715184..157c04bb 100644 --- a/action.yml +++ b/action.yml @@ -465,8 +465,9 @@ runs: atmos terraform apply ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ -input=false \ - -no-color \ - new.${{ steps.vars.outputs.plan_file }} + -no-color \ + --planfile new.${{ steps.vars.outputs.plan_file }} \ + --skip-init &> ${TERRAFORM_OUTPUT_FILE} TERRAFORM_RESULT=$? From b438a1adb3a08f79e50b4c47ad62f70d02dbf38b Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 23:17:06 +0200 Subject: [PATCH 018/123] Support plan-diff --- action.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/action.yml b/action.yml index 157c04bb..654ae41a 100644 --- a/action.yml +++ b/action.yml @@ -464,10 +464,9 @@ runs: apply -- \ atmos terraform apply ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ + --auto-approve \ -input=false \ - -no-color \ - --planfile new.${{ steps.vars.outputs.plan_file }} \ - --skip-init + -no-color &> ${TERRAFORM_OUTPUT_FILE} TERRAFORM_RESULT=$? From d71a4437e37f3fef1253bf20625fbec54de18959 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 23:20:53 +0200 Subject: [PATCH 019/123] Support plan-diff --- action.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/action.yml b/action.yml index 654ae41a..4d5f9d18 100644 --- a/action.yml +++ b/action.yml @@ -462,16 +462,19 @@ runs: --output "${{ github.workspace }}/atmos-apply-summary.md" \ --log-level $([[ "${{ inputs.debug }}" == "true" ]] && echo "DEBUG" || echo "INFO") \ apply -- \ - atmos terraform apply ${{ inputs.component }} \ + atmos terraform deploy ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ - --auto-approve \ -input=false \ - -no-color + -no-color \ + --planfile new.${{ steps.vars.outputs.plan_file }} \ + --skip-init &> ${TERRAFORM_OUTPUT_FILE} TERRAFORM_RESULT=$? set -e + + atmos terraform output ${{ inputs.component }} --stack ${{ inputs.stack }} --skip-init cat "${TERRAFORM_OUTPUT_FILE}" atmos terraform output ${{ inputs.component }} --stack ${{ inputs.stack }} --skip-init -- -json -compact-warnings -no-color | \ From 6412397e62bbfc40367c23aab5de1c73420e0671 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 23:26:31 +0200 Subject: [PATCH 020/123] Support plan-diff --- action.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/action.yml b/action.yml index 4d5f9d18..5d80e37b 100644 --- a/action.yml +++ b/action.yml @@ -474,7 +474,11 @@ runs: set -e + echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + atmos terraform output ${{ inputs.component }} --stack ${{ inputs.stack }} --skip-init + + echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" cat "${TERRAFORM_OUTPUT_FILE}" atmos terraform output ${{ inputs.component }} --stack ${{ inputs.stack }} --skip-init -- -json -compact-warnings -no-color | \ From 19fbf4a9b436edfd59f93dd63ffbf464188f3c33 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 23:30:37 +0200 Subject: [PATCH 021/123] Support plan-diff --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 5d80e37b..42155b3d 100644 --- a/action.yml +++ b/action.yml @@ -476,7 +476,7 @@ runs: echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - atmos terraform output ${{ inputs.component }} --stack ${{ inputs.stack }} --skip-init + atmos terraform output ${{ inputs.component }} --stack ${{ inputs.stack }} --skip-init -- -json -compact-warnings -no-color echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" From def6367a5c4a7a3f6e019255b28512270fff007e Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 23:36:10 +0200 Subject: [PATCH 022/123] Support plan-diff --- action.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/action.yml b/action.yml index 42155b3d..d2e3250c 100644 --- a/action.yml +++ b/action.yml @@ -473,18 +473,18 @@ runs: TERRAFORM_RESULT=$? set -e - - echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - - atmos terraform output ${{ inputs.component }} --stack ${{ inputs.stack }} --skip-init -- -json -compact-warnings -no-color - - echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" cat "${TERRAFORM_OUTPUT_FILE}" atmos terraform output ${{ inputs.component }} --stack ${{ inputs.stack }} --skip-init -- -json -compact-warnings -no-color | \ grep -v 'Switched to workspace' | \ awk '$1~/^Warnings:$/ {exit} {print}' | \ grep -v 'WARN detected' 1> output_values.json + + echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + + cat output_values.json + + echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" terraform-docs -c ${GITHUB_ACTION_PATH}/config/tfdocs-config.yaml --output-file ${{ github.workspace }}/atmos-apply-summary.md ./ sed -i "s#\`\`#![Sensitive](https://img.shields.io/badge/sensitive-c40000?style=for-the-badge)#g" ${{ github.workspace }}/atmos-apply-summary.md From e2424b4c68ce4a8b96041876eccff15afca011e0 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 5 Aug 2025 23:40:08 +0200 Subject: [PATCH 023/123] Support plan-diff --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index d2e3250c..ae7abba2 100644 --- a/action.yml +++ b/action.yml @@ -482,7 +482,7 @@ runs: echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - cat output_values.json + terraform-docs -c ${GITHUB_ACTION_PATH}/config/tfdocs-config.yaml ./ echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" terraform-docs -c ${GITHUB_ACTION_PATH}/config/tfdocs-config.yaml --output-file ${{ github.workspace }}/atmos-apply-summary.md ./ From 6a7db5951aee1b12245ee355682f96b5f342137c Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 10:58:39 +0200 Subject: [PATCH 024/123] Support plan-diff --- action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index ae7abba2..cb7a0527 100644 --- a/action.yml +++ b/action.yml @@ -190,7 +190,7 @@ runs: tag: ${{ startsWith(fromJson(steps.atmos-settings.outputs.settings).opentofu-version, 'v') && fromJson(steps.atmos-settings.outputs.settings).opentofu-version || format('v{0}', fromJson(steps.atmos-settings.outputs.settings).opentofu-version) }} skip: ${{ fromJson(steps.atmos-settings.outputs.settings).opentofu-version == '' || fromJson(steps.atmos-settings.outputs.settings).opentofu-version == 'null' }} suzuki-shunsuke/tfcmt: v4.14.0 - terraform-docs/terraform-docs: v0.18.0 + terraform-docs/terraform-docs: v0.20.0 - name: Configure Plan AWS Credentials uses: aws-actions/configure-aws-credentials@v4 @@ -484,6 +484,7 @@ runs: terraform-docs -c ${GITHUB_ACTION_PATH}/config/tfdocs-config.yaml ./ + echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" terraform-docs -c ${GITHUB_ACTION_PATH}/config/tfdocs-config.yaml --output-file ${{ github.workspace }}/atmos-apply-summary.md ./ From aa3a624d9a1ddd5b673cbcf187e58060749bc16b Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 11:06:31 +0200 Subject: [PATCH 025/123] Support plan-diff --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index cb7a0527..ed6fd296 100644 --- a/action.yml +++ b/action.yml @@ -482,7 +482,7 @@ runs: echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - terraform-docs -c ${GITHUB_ACTION_PATH}/config/tfdocs-config.yaml ./ + cat output_values.json echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" From 3b60c3712403d60f3fa8de0b84b37955f00d2e1b Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 13:29:25 +0200 Subject: [PATCH 026/123] Support plan-diff --- atmos-apply-summary.md | 6 ++++++ config/tfdocs-config.yaml | 5 +---- output_values.json | 33 +++++++++++++++++++++++++++++++++ tests/terraform/atmos.yaml | 2 +- 4 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 atmos-apply-summary.md create mode 100644 output_values.json diff --git a/atmos-apply-summary.md b/atmos-apply-summary.md new file mode 100644 index 00000000..10143907 --- /dev/null +++ b/atmos-apply-summary.md @@ -0,0 +1,6 @@ +[//]: # (BEGIN_TF_DOCS) +## Outputs + +No outputs. + +[//]: # (END_TF_DOCS) \ No newline at end of file diff --git a/config/tfdocs-config.yaml b/config/tfdocs-config.yaml index efc34604..bb6c8ad2 100644 --- a/config/tfdocs-config.yaml +++ b/config/tfdocs-config.yaml @@ -4,9 +4,6 @@ sections: show: - outputs -content: |- - {{ .Outputs }} - output: file: "atmos-apply-summary.md" mode: inject @@ -18,7 +15,7 @@ output: output-values: enabled: true - from: "output_values.json" + from: output_values.json sort: enabled: true diff --git a/output_values.json b/output_values.json new file mode 100644 index 00000000..add470d4 --- /dev/null +++ b/output_values.json @@ -0,0 +1,33 @@ +{ + "result": { + "sensitive": false, + "type": "string", + "value": "QMHOeZEaZoI" + }, + "sensitive_value": { + "sensitive": true, + "type": "string", + "value": "QMHOeZEaZoI" + }, + "structured_value": { + "sensitive": false, + "type": [ + "object", + { + "test": "string", + "value": [ + "object", + { + "result": "string" + } + ] + } + ], + "value": { + "test": "test", + "value": { + "result": "QMHOeZEaZoI" + } + } + } +} diff --git a/tests/terraform/atmos.yaml b/tests/terraform/atmos.yaml index e4037b08..ca4ea58e 100644 --- a/tests/terraform/atmos.yaml +++ b/tests/terraform/atmos.yaml @@ -62,7 +62,7 @@ stacks: integrations: github: gitops: - terraform-version: 1.5.7 + terraform-version: 1.10.4 infracost-enabled: __INFRACOST_ENABLED__ artifact-storage: region: __STORAGE_REGION__ From 20acd8a878d140baecb8b1c2fc591afb60e48884 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 13:48:17 +0200 Subject: [PATCH 027/123] Support plan-diff --- .../stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml index 3d552592..a5a9f045 100644 --- a/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml +++ b/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml @@ -8,7 +8,8 @@ terraform: s3: bucket: cptest-core-ue2-root-tfstate-plat dynamodb_table: cptest-core-ue2-root-tfstate-plat-lock - role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-plat + assume_role: + role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-plat encrypt: true key: terraform/terraform.tfstate acl: bucket-owner-full-control From 6f212709cdb17b8b5d84ec47764cac6d0381fd4b Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 13:57:05 +0200 Subject: [PATCH 028/123] Support plan-diff --- atmos-apply-summary.md | 6 ------ config/tfdocs-config.yaml | 2 +- output_values.json | 33 --------------------------------- 3 files changed, 1 insertion(+), 40 deletions(-) delete mode 100644 atmos-apply-summary.md delete mode 100644 output_values.json diff --git a/atmos-apply-summary.md b/atmos-apply-summary.md deleted file mode 100644 index 10143907..00000000 --- a/atmos-apply-summary.md +++ /dev/null @@ -1,6 +0,0 @@ -[//]: # (BEGIN_TF_DOCS) -## Outputs - -No outputs. - -[//]: # (END_TF_DOCS) \ No newline at end of file diff --git a/config/tfdocs-config.yaml b/config/tfdocs-config.yaml index bb6c8ad2..33b7d4e3 100644 --- a/config/tfdocs-config.yaml +++ b/config/tfdocs-config.yaml @@ -15,7 +15,7 @@ output: output-values: enabled: true - from: output_values.json + from: "output_values.json" sort: enabled: true diff --git a/output_values.json b/output_values.json deleted file mode 100644 index add470d4..00000000 --- a/output_values.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "result": { - "sensitive": false, - "type": "string", - "value": "QMHOeZEaZoI" - }, - "sensitive_value": { - "sensitive": true, - "type": "string", - "value": "QMHOeZEaZoI" - }, - "structured_value": { - "sensitive": false, - "type": [ - "object", - { - "test": "string", - "value": [ - "object", - { - "result": "string" - } - ] - } - ], - "value": { - "test": "test", - "value": { - "result": "QMHOeZEaZoI" - } - } - } -} From 04d87f6fbf6559e9190226254cfdf512b23a7545 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 13:57:22 +0200 Subject: [PATCH 029/123] Support plan-diff --- config/tfdocs-config.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/config/tfdocs-config.yaml b/config/tfdocs-config.yaml index 33b7d4e3..efc34604 100644 --- a/config/tfdocs-config.yaml +++ b/config/tfdocs-config.yaml @@ -4,6 +4,9 @@ sections: show: - outputs +content: |- + {{ .Outputs }} + output: file: "atmos-apply-summary.md" mode: inject From 28f062cc9a7f10e7d1ef2276deb4288682f4db75 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 14:11:34 +0200 Subject: [PATCH 030/123] Support plan-diff --- tests/terraform/components/terraform/foobar/outputs.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/terraform/components/terraform/foobar/outputs.tf b/tests/terraform/components/terraform/foobar/outputs.tf index 055f02d5..d5aea64b 100644 --- a/tests/terraform/components/terraform/foobar/outputs.tf +++ b/tests/terraform/components/terraform/foobar/outputs.tf @@ -6,7 +6,7 @@ output "result" { output "sensitive_value" { description = "Test sensitive description output" value = random_id.foo.id - sensitive = true + sensitive = false } From 3715c8732b0304469fe2608007ff2395a3219101 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 14:24:35 +0200 Subject: [PATCH 031/123] Support plan-diff --- action.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/action.yml b/action.yml index ed6fd296..4d2b8b86 100644 --- a/action.yml +++ b/action.yml @@ -478,15 +478,15 @@ runs: atmos terraform output ${{ inputs.component }} --stack ${{ inputs.stack }} --skip-init -- -json -compact-warnings -no-color | \ grep -v 'Switched to workspace' | \ awk '$1~/^Warnings:$/ {exit} {print}' | \ - grep -v 'WARN detected' 1> output_values.json + grep -v 'WARN detected' 1> ${{ steps.vars.outputs.component_path }}/output_values.json echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - cat output_values.json + cat ${{ steps.vars.outputs.component_path }}/output_values.json echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - terraform-docs -c ${GITHUB_ACTION_PATH}/config/tfdocs-config.yaml --output-file ${{ github.workspace }}/atmos-apply-summary.md ./ + terraform-docs -c ${GITHUB_ACTION_PATH}/config/tfdocs-config.yaml --output-file ${{ github.workspace }}/atmos-apply-summary.md ${{ steps.vars.outputs.component_path }} sed -i "s#\`\`#![Sensitive](https://img.shields.io/badge/sensitive-c40000?style=for-the-badge)#g" ${{ github.workspace }}/atmos-apply-summary.md sed -i "s#\`\"#\`#g" ${{ github.workspace }}/atmos-apply-summary.md From 091777a74577c2c0e765918b7ff01d92213412be Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 14:31:44 +0200 Subject: [PATCH 032/123] Support plan-diff --- action.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 4d2b8b86..8a7c71d3 100644 --- a/action.yml +++ b/action.yml @@ -486,7 +486,9 @@ runs: echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - terraform-docs -c ${GITHUB_ACTION_PATH}/config/tfdocs-config.yaml --output-file ${{ github.workspace }}/atmos-apply-summary.md ${{ steps.vars.outputs.component_path }} + cd ${{ steps.vars.outputs.component_path }} + terraform-docs -c ${GITHUB_ACTION_PATH}/config/tfdocs-config.yaml --output-file ${{ github.workspace }}/atmos-apply-summary.md ./ + cd - sed -i "s#\`\`#![Sensitive](https://img.shields.io/badge/sensitive-c40000?style=for-the-badge)#g" ${{ github.workspace }}/atmos-apply-summary.md sed -i "s#\`\"#\`#g" ${{ github.workspace }}/atmos-apply-summary.md From 214f390137ec2e0d87a00624c79180e8bc7248b6 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 15:43:09 +0300 Subject: [PATCH 033/123] Update outputs.tf --- tests/terraform/components/terraform/foobar/outputs.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/terraform/components/terraform/foobar/outputs.tf b/tests/terraform/components/terraform/foobar/outputs.tf index d5aea64b..7177f0bd 100644 --- a/tests/terraform/components/terraform/foobar/outputs.tf +++ b/tests/terraform/components/terraform/foobar/outputs.tf @@ -6,7 +6,7 @@ output "result" { output "sensitive_value" { description = "Test sensitive description output" value = random_id.foo.id - sensitive = false + sensitive = true } @@ -18,4 +18,4 @@ output "structured_value" { result = random_id.foo.id } } -} \ No newline at end of file +} From c017b95a27f7a8e02404dff52f9aa88d98b69c47 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 15:43:24 +0300 Subject: [PATCH 034/123] Update plat-ue2-sandbox.yaml --- .../stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml index a5a9f045..3d552592 100644 --- a/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml +++ b/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml @@ -8,8 +8,7 @@ terraform: s3: bucket: cptest-core-ue2-root-tfstate-plat dynamodb_table: cptest-core-ue2-root-tfstate-plat-lock - assume_role: - role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-plat + role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-plat encrypt: true key: terraform/terraform.tfstate acl: bucket-owner-full-control From c30dd0e6828eeabd6baabe4c4842d2a17a27ddad Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 15:43:48 +0300 Subject: [PATCH 035/123] Update atmos.yaml --- tests/terraform/atmos.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/terraform/atmos.yaml b/tests/terraform/atmos.yaml index ca4ea58e..e4037b08 100644 --- a/tests/terraform/atmos.yaml +++ b/tests/terraform/atmos.yaml @@ -62,7 +62,7 @@ stacks: integrations: github: gitops: - terraform-version: 1.10.4 + terraform-version: 1.5.7 infracost-enabled: __INFRACOST_ENABLED__ artifact-storage: region: __STORAGE_REGION__ From 79ca9d35c2bbe277b7f764cc9812f9f504df9321 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 15:45:32 +0200 Subject: [PATCH 036/123] Support plan-diff --- action.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/action.yml b/action.yml index 8a7c71d3..ddbff360 100644 --- a/action.yml +++ b/action.yml @@ -383,11 +383,12 @@ runs: api-key: ${{ inputs.infracost-api-key }} - name: Convert PLANFILE to JSON - if: env.INFRACOST_ENABLED == 'true' + # if: env.INFRACOST_ENABLED == 'true' shell: bash working-directory: ${{ steps.vars.outputs.component_path }} run: | ${{ fromJson(steps.atmos-settings.outputs.settings).command }} show -json "${{ steps.vars.outputs.plan_file }}" > "${{ steps.vars.outputs.plan_file }}.json" + cat ${{ steps.vars.outputs.plan_file }}.json - name: Generate Infracost Diff if: env.INFRACOST_ENABLED == 'true' @@ -480,12 +481,6 @@ runs: awk '$1~/^Warnings:$/ {exit} {print}' | \ grep -v 'WARN detected' 1> ${{ steps.vars.outputs.component_path }}/output_values.json - echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - - cat ${{ steps.vars.outputs.component_path }}/output_values.json - - - echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" cd ${{ steps.vars.outputs.component_path }} terraform-docs -c ${GITHUB_ACTION_PATH}/config/tfdocs-config.yaml --output-file ${{ github.workspace }}/atmos-apply-summary.md ./ cd - From f1abd4aadce4d08ee8cb4a2f307c7b160d491546 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 15:46:41 +0200 Subject: [PATCH 037/123] Support plan-diff --- .github/workflows/integration-tests.yml | 1 + action.yml | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index bb1bca00..26c2292d 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -47,6 +47,7 @@ jobs: component: "foobar" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} + debug: true - uses: actions/checkout@v4 with: diff --git a/action.yml b/action.yml index ddbff360..08cef5fa 100644 --- a/action.yml +++ b/action.yml @@ -383,12 +383,11 @@ runs: api-key: ${{ inputs.infracost-api-key }} - name: Convert PLANFILE to JSON - # if: env.INFRACOST_ENABLED == 'true' + if: env.INFRACOST_ENABLED == 'true' || env.DEBUG_ENABLED == 'true' shell: bash working-directory: ${{ steps.vars.outputs.component_path }} run: | ${{ fromJson(steps.atmos-settings.outputs.settings).command }} show -json "${{ steps.vars.outputs.plan_file }}" > "${{ steps.vars.outputs.plan_file }}.json" - cat ${{ steps.vars.outputs.plan_file }}.json - name: Generate Infracost Diff if: env.INFRACOST_ENABLED == 'true' From 0295b2a13581ac700807f8e89cbdf37a4aa45f74 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 15:54:00 +0200 Subject: [PATCH 038/123] Support plan-diff --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 08cef5fa..fd8ad4a5 100644 --- a/action.yml +++ b/action.yml @@ -387,7 +387,7 @@ runs: shell: bash working-directory: ${{ steps.vars.outputs.component_path }} run: | - ${{ fromJson(steps.atmos-settings.outputs.settings).command }} show -json "${{ steps.vars.outputs.plan_file }}" > "${{ steps.vars.outputs.plan_file }}.json" + ${{ fromJson(steps.atmos-settings.outputs.settings).command }} show -json "new.${{ steps.vars.outputs.plan_file }}" > "${{ steps.vars.outputs.plan_file }}.json" - name: Generate Infracost Diff if: env.INFRACOST_ENABLED == 'true' From 5dd1cda753943dec88714cae166246de26e2d137 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 16:00:22 +0200 Subject: [PATCH 039/123] Support plan-diff --- action.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/action.yml b/action.yml index fd8ad4a5..3dcb4f44 100644 --- a/action.yml +++ b/action.yml @@ -388,6 +388,9 @@ runs: working-directory: ${{ steps.vars.outputs.component_path }} run: | ${{ fromJson(steps.atmos-settings.outputs.settings).command }} show -json "new.${{ steps.vars.outputs.plan_file }}" > "${{ steps.vars.outputs.plan_file }}.json" + echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + cat "${{ steps.vars.outputs.plan_file }}.json" + echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - name: Generate Infracost Diff if: env.INFRACOST_ENABLED == 'true' From c34a5a326d63c410fb6ac2e967c615bae9991734 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 16:31:59 +0200 Subject: [PATCH 040/123] Support plan-diff --- action.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/action.yml b/action.yml index 3dcb4f44..a0d26088 100644 --- a/action.yml +++ b/action.yml @@ -388,9 +388,6 @@ runs: working-directory: ${{ steps.vars.outputs.component_path }} run: | ${{ fromJson(steps.atmos-settings.outputs.settings).command }} show -json "new.${{ steps.vars.outputs.plan_file }}" > "${{ steps.vars.outputs.plan_file }}.json" - echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - cat "${{ steps.vars.outputs.plan_file }}.json" - echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - name: Generate Infracost Diff if: env.INFRACOST_ENABLED == 'true' @@ -470,7 +467,7 @@ runs: -input=false \ -no-color \ --planfile new.${{ steps.vars.outputs.plan_file }} \ - --skip-init + --skip-init \ &> ${TERRAFORM_OUTPUT_FILE} TERRAFORM_RESULT=$? From d4d3e57e398e4ac7c48c34aaa3cdaddd53256d89 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 18:43:01 +0200 Subject: [PATCH 041/123] Support plan-diff --- ...led.yml => integration-test-atmos-pro.yml} | 7 +++- action.yml | 40 +++++++++++-------- 2 files changed, 29 insertions(+), 18 deletions(-) rename .github/workflows/{test-atmos-pro-enabled.yml => integration-test-atmos-pro.yml} (94%) diff --git a/.github/workflows/test-atmos-pro-enabled.yml b/.github/workflows/integration-test-atmos-pro.yml similarity index 94% rename from .github/workflows/test-atmos-pro-enabled.yml rename to .github/workflows/integration-test-atmos-pro.yml index 1097cdca..b86d5a65 100644 --- a/.github/workflows/test-atmos-pro-enabled.yml +++ b/.github/workflows/integration-test-atmos-pro.yml @@ -1,8 +1,11 @@ -name: "Test - Atmos Pro Enabled" +name: "Atmos Pro Integration Tests" on: workflow_dispatch: {} + pull_request: + types: [opened, synchronize, reopened] + env: AWS_REGION: us-east-2 @@ -44,7 +47,7 @@ jobs: cat ${{ runner.temp }}/atmos.yaml - name: Plan Atmos Component - uses: cloudposse/github-action-atmos-terraform-plan@v5 + uses: cloudposse/github-action-atmos-terraform-plan@v6 with: component: "foobar-atmos-pro" stack: "plat-ue2-sandbox" diff --git a/action.yml b/action.yml index a0d26088..0be178c2 100644 --- a/action.yml +++ b/action.yml @@ -238,9 +238,12 @@ runs: COMPONENT_NAME=$(echo "${{ inputs.component }}" | sed 's#/#_#g') COMPONENT_SLUG="$STACK_NAME-$COMPONENT_NAME" COMPONENT_CACHE_KEY=$(basename "${{ fromJson(steps.atmos-settings.outputs.settings).component-path }}") - PLAN_FILE="$COMPONENT_SLUG.planfile" + PLAN_FILENAME="$COMPONENT_SLUG.planfile" + PLAN_FILE="${COMPONENT_PATH}/${PLAN_FILENAME}" RETRIEVED_PLAN_FILENAME="$COMPONENT_SLUG-${{ inputs.sha }}.planfile" RETRIEVED_PLAN_FILE="${COMPONENT_PATH}/${RETRIEVED_PLAN_FILENAME}" + RENEWED_PLAN_FILENAME="new.${RETRIEVED_PLAN_FILENAME}" + RENEWED_PLAN_FILE="${COMPONENT_PATH}/${RENEWED_PLAN_FILENAME}" LOCK_FILE="${COMPONENT_PATH}/.terraform.lock.hcl" echo "stack_name=$STACK_NAME" >> $GITHUB_OUTPUT @@ -248,9 +251,12 @@ runs: echo "component_slug=$COMPONENT_SLUG" >> $GITHUB_OUTPUT echo "component_path=${COMPONENT_PATH}" >> $GITHUB_OUTPUT echo "cache-key=${COMPONENT_CACHE_KEY}" >> $GITHUB_OUTPUT + echo "plan_filename=$PLAN_FILENAME" >> $GITHUB_OUTPUT echo "plan_file=$PLAN_FILE" >> $GITHUB_OUTPUT echo "retrieved_plan_filename=$RETRIEVED_PLAN_FILENAME" >> $GITHUB_OUTPUT echo "retrieved_plan_file=$RETRIEVED_PLAN_FILE" >> $GITHUB_OUTPUT + echo "renewed_plan_filename=$RENEWED_PLAN_FILENAME" >> $GITHUB_OUTPUT + echo "renewed_plan_file=$RENEWED_PLAN_FILE" >> $GITHUB_OUTPUT echo "lock_file=$LOCK_FILE" >> $GITHUB_OUTPUT - name: Configure Plan Storage AWS Credentials @@ -348,26 +354,28 @@ runs: PLAN_CHANGED=$? - if [[ "${{ inputs.plan-storage == 'true' }}" == "true" ]]; then + if [[ "${{ inputs.plan-storage }}" == "true" ]]; then - cp ${{ steps.vars.outputs.component_path }}/${{ steps.vars.outputs.plan_file }} ${{ steps.vars.outputs.component_path }}/new.${{ steps.vars.outputs.plan_file }} + cp ${{ steps.vars.outputs.plan_file }} ${{ steps.vars.outputs.renewed_plan_file }} atmos terraform plan-diff ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ -input=false \ -no-color \ --orig ${{ steps.vars.outputs.retrieved_plan_filename }} \ - --new new.${{ steps.vars.outputs.plan_file }} \ + --new ${{ steps.vars.outputs.renewed_plan_filename }} \ --skip-init PLAN_CHANGED=$? fi - ls -l ${{ steps.vars.outputs.component_path }} - - echo "plan_changed=$PLAN_CHANGED" >> $GITHUB_OUTPUT + if [[ "${PLAN_CHANGED}" == "0" ]]; then + echo "plan_changed=false" >> $GITHUB_OUTPUT + else + echo "plan_changed=true" >> $GITHUB_OUTPUT + fi - name: Check Whether Infracost is Enabled - if: env.ACTIONS_ENABLED == 'true' + if: env.ACTIONS_ENABLED == 'true' && steps.plan-diff.outputs.plan_changed == 'false' shell: bash run: | if [[ "${{ fromJson(steps.atmos-settings.outputs.settings).enable-infracost }}" == "true" ]]; then @@ -377,20 +385,20 @@ runs: fi - name: Setup Infracost - if: env.INFRACOST_ENABLED == 'true' + if: env.INFRACOST_ENABLED == 'true' && steps.plan-diff.outputs.plan_changed == 'false' uses: infracost/actions/setup@v3 with: api-key: ${{ inputs.infracost-api-key }} - name: Convert PLANFILE to JSON - if: env.INFRACOST_ENABLED == 'true' || env.DEBUG_ENABLED == 'true' + if: env.INFRACOST_ENABLED == 'true' || env.DEBUG_ENABLED == 'true' && steps.plan-diff.outputs.plan_changed == 'false' shell: bash working-directory: ${{ steps.vars.outputs.component_path }} run: | - ${{ fromJson(steps.atmos-settings.outputs.settings).command }} show -json "new.${{ steps.vars.outputs.plan_file }}" > "${{ steps.vars.outputs.plan_file }}.json" + ${{ fromJson(steps.atmos-settings.outputs.settings).command }} show -json "${{ steps.vars.outputs.renewed_plan_file }}" > "${{ steps.vars.outputs.plan_file }}.json" - name: Generate Infracost Diff - if: env.INFRACOST_ENABLED == 'true' + if: env.INFRACOST_ENABLED == 'true' && steps.plan-diff.outputs.plan_changed == 'false' shell: bash working-directory: ${{ steps.vars.outputs.component_path }} run: | @@ -406,7 +414,7 @@ runs: --out-file=/tmp/infracost.json - name: Debug Infracost - if: env.INFRACOST_ENABLED == 'true' && env.DEBUG_ENABLED == 'true' + if: env.INFRACOST_ENABLED == 'true' && env.DEBUG_ENABLED == 'true' && steps.plan-diff.outputs.plan_changed == 'false' shell: bash working-directory: ${{ steps.vars.outputs.component_path }} run: | @@ -415,7 +423,7 @@ runs: cat /tmp/infracost.json - name: Set Infracost Variables - if: env.INFRACOST_ENABLED == 'true' + if: env.INFRACOST_ENABLED == 'true' && steps.plan-diff.outputs.plan_changed == 'false' id: infracost-diff working-directory: ${{ steps.vars.outputs.component_path }} shell: bash @@ -432,7 +440,7 @@ runs: echo "infracost_diff_total_monthly_cost=$INFRACOST_DIFF_TOTAL_MONTHLY_COST" >> "$GITHUB_OUTPUT" - name: Terraform Apply - if: env.ACTIONS_ENABLED == 'true' + if: env.ACTIONS_ENABLED == 'true' && steps.plan-diff.outputs.plan_changed == 'false' id: apply shell: bash run: | @@ -466,7 +474,7 @@ runs: --stack ${{ inputs.stack }} \ -input=false \ -no-color \ - --planfile new.${{ steps.vars.outputs.plan_file }} \ + --planfile ${{ steps.vars.outputs.renewed_plan_file }} \ --skip-init \ &> ${TERRAFORM_OUTPUT_FILE} From e405e866917718fc9bc23d53ce0ceaa87e95a9c5 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 18:44:27 +0200 Subject: [PATCH 042/123] Support plan-diff --- .github/workflows/integration-test-atmos-pro.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration-test-atmos-pro.yml b/.github/workflows/integration-test-atmos-pro.yml index b86d5a65..d7ebdac4 100644 --- a/.github/workflows/integration-test-atmos-pro.yml +++ b/.github/workflows/integration-test-atmos-pro.yml @@ -47,7 +47,7 @@ jobs: cat ${{ runner.temp }}/atmos.yaml - name: Plan Atmos Component - uses: cloudposse/github-action-atmos-terraform-plan@v6 + uses: cloudposse/github-action-atmos-terraform-plan@v5 with: component: "foobar-atmos-pro" stack: "plat-ue2-sandbox" From b10529ffe06d283141e808f99a70bc198a6329f0 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 19:00:57 +0200 Subject: [PATCH 043/123] Support plan-diff --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 0be178c2..e5f4a435 100644 --- a/action.yml +++ b/action.yml @@ -474,7 +474,7 @@ runs: --stack ${{ inputs.stack }} \ -input=false \ -no-color \ - --planfile ${{ steps.vars.outputs.renewed_plan_file }} \ + --planfile ${{ steps.vars.outputs.renewed_plan_filename }} \ --skip-init \ &> ${TERRAFORM_OUTPUT_FILE} From 4612f61c153a991d733bd7be0fca7d269d57cf0c Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 19:07:23 +0200 Subject: [PATCH 044/123] Support plan-diff --- action.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/action.yml b/action.yml index e5f4a435..03897d0b 100644 --- a/action.yml +++ b/action.yml @@ -451,12 +451,6 @@ runs: TERRAFORM_OUTPUT_FILE="./terraform-${GITHUB_RUN_ID}-output.txt" - if [[ "${{steps.plan-diff.outputs.plan_changed}}" != "0" ]]; then - exit 1 - fi - - ls -l ${{ steps.vars.outputs.component_path }} - tfcmt \ --config "${GITHUB_ACTION_PATH}/config/atmos_github_summary.yaml" \ -var "target:${{ inputs.stack }}-${{ inputs.component }}" \ From e2d17ecd5f8f0e3434e4d565aa5b030e00db3a69 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 19:47:29 +0200 Subject: [PATCH 045/123] Added A/B testings --- .../workflows/integration-test-atmos-pro.yml | 2 +- .../workflows/integration-tests-plan-diff.yml | 80 +++++ .github/workflows/integration-tests.yml | 2 +- tests/{ => a}/opentofu/atmos.yaml | 2 +- .../components/terraform/foobar/context.tf | 0 .../components/terraform/foobar/main.tf | 0 .../components/terraform/foobar/outputs.tf | 0 .../components/terraform/foobar/variables.tf | 0 .../stacks/catalog/foobar-atmos-pro.yaml | 0 .../opentofu/stacks/catalog/foobar.yaml | 0 .../foo/plat/sandbox/plat-ue2-sandbox.yaml | 0 tests/{ => a}/terraform/atmos.yaml | 0 .../components/terraform/foobar/context.tf | 0 .../components/terraform/foobar/main.tf | 0 .../components/terraform/foobar/outputs.tf | 0 .../components/terraform/foobar/variables.tf | 0 .../stacks/catalog/foobar-atmos-pro.yaml | 0 .../terraform/stacks/catalog/foobar.yaml | 0 .../foo/plat/sandbox/plat-ue2-sandbox.yaml | 0 tests/b/opentofu/atmos.yaml | 92 ++++++ .../components/terraform/foobar/context.tf | 279 ++++++++++++++++++ .../components/terraform/foobar/main.tf | 8 + .../components/terraform/foobar/outputs.tf | 21 ++ .../components/terraform/foobar/variables.tf | 5 + .../stacks/catalog/foobar-atmos-pro.yaml | 13 + tests/b/opentofu/stacks/catalog/foobar.yaml | 8 + .../foo/plat/sandbox/plat-ue2-sandbox.yaml | 30 ++ tests/b/terraform/atmos.yaml | 93 ++++++ .../components/terraform/foobar/context.tf | 279 ++++++++++++++++++ .../components/terraform/foobar/main.tf | 8 + .../components/terraform/foobar/outputs.tf | 21 ++ .../components/terraform/foobar/variables.tf | 5 + .../stacks/catalog/foobar-atmos-pro.yaml | 13 + tests/b/terraform/stacks/catalog/foobar.yaml | 8 + .../foo/plat/sandbox/plat-ue2-sandbox.yaml | 30 ++ 35 files changed, 996 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/integration-tests-plan-diff.yml rename tests/{ => a}/opentofu/atmos.yaml (99%) rename tests/{ => a}/opentofu/components/terraform/foobar/context.tf (100%) rename tests/{ => a}/opentofu/components/terraform/foobar/main.tf (100%) rename tests/{ => a}/opentofu/components/terraform/foobar/outputs.tf (100%) rename tests/{ => a}/opentofu/components/terraform/foobar/variables.tf (100%) rename tests/{ => a}/opentofu/stacks/catalog/foobar-atmos-pro.yaml (100%) rename tests/{ => a}/opentofu/stacks/catalog/foobar.yaml (100%) rename tests/{ => a}/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml (100%) rename tests/{ => a}/terraform/atmos.yaml (100%) rename tests/{ => a}/terraform/components/terraform/foobar/context.tf (100%) rename tests/{ => a}/terraform/components/terraform/foobar/main.tf (100%) rename tests/{ => a}/terraform/components/terraform/foobar/outputs.tf (100%) rename tests/{ => a}/terraform/components/terraform/foobar/variables.tf (100%) rename tests/{ => a}/terraform/stacks/catalog/foobar-atmos-pro.yaml (100%) rename tests/{ => a}/terraform/stacks/catalog/foobar.yaml (100%) rename tests/{ => a}/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml (100%) create mode 100644 tests/b/opentofu/atmos.yaml create mode 100644 tests/b/opentofu/components/terraform/foobar/context.tf create mode 100644 tests/b/opentofu/components/terraform/foobar/main.tf create mode 100644 tests/b/opentofu/components/terraform/foobar/outputs.tf create mode 100644 tests/b/opentofu/components/terraform/foobar/variables.tf create mode 100644 tests/b/opentofu/stacks/catalog/foobar-atmos-pro.yaml create mode 100644 tests/b/opentofu/stacks/catalog/foobar.yaml create mode 100644 tests/b/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml create mode 100644 tests/b/terraform/atmos.yaml create mode 100644 tests/b/terraform/components/terraform/foobar/context.tf create mode 100644 tests/b/terraform/components/terraform/foobar/main.tf create mode 100644 tests/b/terraform/components/terraform/foobar/outputs.tf create mode 100644 tests/b/terraform/components/terraform/foobar/variables.tf create mode 100644 tests/b/terraform/stacks/catalog/foobar-atmos-pro.yaml create mode 100644 tests/b/terraform/stacks/catalog/foobar.yaml create mode 100644 tests/b/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml diff --git a/.github/workflows/integration-test-atmos-pro.yml b/.github/workflows/integration-test-atmos-pro.yml index d7ebdac4..66f22c8e 100644 --- a/.github/workflows/integration-test-atmos-pro.yml +++ b/.github/workflows/integration-test-atmos-pro.yml @@ -35,7 +35,7 @@ jobs: shell: bash run: | mkdir -p ${{ runner.temp }} - cp ./tests/opentofu/atmos.yaml ${{ runner.temp }}/atmos.yaml + cp ./tests/a/opentofu/atmos.yaml ${{ runner.temp }}/atmos.yaml sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml new file mode 100644 index 00000000..cd4c3e73 --- /dev/null +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -0,0 +1,80 @@ +name: "Integration Tests - Plan failed" + +on: + workflow_dispatch: {} + + pull_request: + types: [opened, synchronize, reopened] + +env: + AWS_REGION: us-east-2 + + +# Permissions required for assuming AWS identity +permissions: + id-token: write + contents: read + +jobs: + test: + runs-on: ubuntu-latest + strategy: + max-parallel: 1 + fail-fast: false # Don't fail fast to avoid locking TF State + matrix: + platform: [terraform, opentofu] + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + + - shell: bash + run: | + mkdir -p ${{ runner.temp }} + cp ./tests/${{ matrix.platform }}/b/atmos.yaml ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_TABLE__#${{ secrets.TERRAFORM_STATE_TABLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_TABLE__#${{ secrets.TERRAFORM_STATE_TABLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_ROLE__#${{ secrets.TERRAFORM_STATE_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__PLAN_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__APPLY_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + + - name: Plan Atmos Component + uses: cloudposse/github-action-atmos-terraform-plan@v4 + with: + component: "foobar" + stack: "plat-ue2-sandbox" + atmos-config-path: ${{ runner.temp }} + debug: true + + - shell: bash + run: | + mkdir -p ${{ runner.temp }} + cp ./tests/${{ matrix.platform }}/a/atmos.yaml ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_TABLE__#${{ secrets.TERRAFORM_STATE_TABLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_TABLE__#${{ secrets.TERRAFORM_STATE_TABLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_ROLE__#${{ secrets.TERRAFORM_STATE_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__PLAN_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__APPLY_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + + - name: Wait 15 sec to wait s3 bucket would be consistent (read after write consistency) + shell: bash + run: | + sleep 15; + + - name: Apply Atmos Component + uses: ./ + with: + component: "foobar" + stack: "plat-ue2-sandbox" + atmos-config-path: ${{ runner.temp }} + debug: true diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 26c2292d..579bb0fc 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -31,7 +31,7 @@ jobs: - shell: bash run: | mkdir -p ${{ runner.temp }} - cp ./tests/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml + cp ./tests/${{ matrix.platform }}/a/atmos.yaml ${{ runner.temp }}/atmos.yaml sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml diff --git a/tests/opentofu/atmos.yaml b/tests/a/opentofu/atmos.yaml similarity index 99% rename from tests/opentofu/atmos.yaml rename to tests/a/opentofu/atmos.yaml index 46867467..c12261be 100644 --- a/tests/opentofu/atmos.yaml +++ b/tests/a/opentofu/atmos.yaml @@ -15,7 +15,7 @@ # are independent settings (supporting both absolute and relative paths). # If `base_path` is provided, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` # are considered paths relative to `base_path`. -base_path: "./tests/opentofu" +base_path: "./tests/a/opentofu" aliases: tofu: terraform diff --git a/tests/opentofu/components/terraform/foobar/context.tf b/tests/a/opentofu/components/terraform/foobar/context.tf similarity index 100% rename from tests/opentofu/components/terraform/foobar/context.tf rename to tests/a/opentofu/components/terraform/foobar/context.tf diff --git a/tests/opentofu/components/terraform/foobar/main.tf b/tests/a/opentofu/components/terraform/foobar/main.tf similarity index 100% rename from tests/opentofu/components/terraform/foobar/main.tf rename to tests/a/opentofu/components/terraform/foobar/main.tf diff --git a/tests/opentofu/components/terraform/foobar/outputs.tf b/tests/a/opentofu/components/terraform/foobar/outputs.tf similarity index 100% rename from tests/opentofu/components/terraform/foobar/outputs.tf rename to tests/a/opentofu/components/terraform/foobar/outputs.tf diff --git a/tests/opentofu/components/terraform/foobar/variables.tf b/tests/a/opentofu/components/terraform/foobar/variables.tf similarity index 100% rename from tests/opentofu/components/terraform/foobar/variables.tf rename to tests/a/opentofu/components/terraform/foobar/variables.tf diff --git a/tests/opentofu/stacks/catalog/foobar-atmos-pro.yaml b/tests/a/opentofu/stacks/catalog/foobar-atmos-pro.yaml similarity index 100% rename from tests/opentofu/stacks/catalog/foobar-atmos-pro.yaml rename to tests/a/opentofu/stacks/catalog/foobar-atmos-pro.yaml diff --git a/tests/opentofu/stacks/catalog/foobar.yaml b/tests/a/opentofu/stacks/catalog/foobar.yaml similarity index 100% rename from tests/opentofu/stacks/catalog/foobar.yaml rename to tests/a/opentofu/stacks/catalog/foobar.yaml diff --git a/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/a/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml similarity index 100% rename from tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml rename to tests/a/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml diff --git a/tests/terraform/atmos.yaml b/tests/a/terraform/atmos.yaml similarity index 100% rename from tests/terraform/atmos.yaml rename to tests/a/terraform/atmos.yaml diff --git a/tests/terraform/components/terraform/foobar/context.tf b/tests/a/terraform/components/terraform/foobar/context.tf similarity index 100% rename from tests/terraform/components/terraform/foobar/context.tf rename to tests/a/terraform/components/terraform/foobar/context.tf diff --git a/tests/terraform/components/terraform/foobar/main.tf b/tests/a/terraform/components/terraform/foobar/main.tf similarity index 100% rename from tests/terraform/components/terraform/foobar/main.tf rename to tests/a/terraform/components/terraform/foobar/main.tf diff --git a/tests/terraform/components/terraform/foobar/outputs.tf b/tests/a/terraform/components/terraform/foobar/outputs.tf similarity index 100% rename from tests/terraform/components/terraform/foobar/outputs.tf rename to tests/a/terraform/components/terraform/foobar/outputs.tf diff --git a/tests/terraform/components/terraform/foobar/variables.tf b/tests/a/terraform/components/terraform/foobar/variables.tf similarity index 100% rename from tests/terraform/components/terraform/foobar/variables.tf rename to tests/a/terraform/components/terraform/foobar/variables.tf diff --git a/tests/terraform/stacks/catalog/foobar-atmos-pro.yaml b/tests/a/terraform/stacks/catalog/foobar-atmos-pro.yaml similarity index 100% rename from tests/terraform/stacks/catalog/foobar-atmos-pro.yaml rename to tests/a/terraform/stacks/catalog/foobar-atmos-pro.yaml diff --git a/tests/terraform/stacks/catalog/foobar.yaml b/tests/a/terraform/stacks/catalog/foobar.yaml similarity index 100% rename from tests/terraform/stacks/catalog/foobar.yaml rename to tests/a/terraform/stacks/catalog/foobar.yaml diff --git a/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/a/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml similarity index 100% rename from tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml rename to tests/a/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml diff --git a/tests/b/opentofu/atmos.yaml b/tests/b/opentofu/atmos.yaml new file mode 100644 index 00000000..5e5b513c --- /dev/null +++ b/tests/b/opentofu/atmos.yaml @@ -0,0 +1,92 @@ +# CLI config is loaded from the following locations (from lowest to highest priority): +# system dir (`/usr/local/etc/atmos` on Linux, `%LOCALAPPDATA%/atmos` on Windows) +# home dir (~/.atmos) +# current directory +# ENV vars +# Command-line arguments +# +# It supports POSIX-style Globs for file names/paths (double-star `**` is supported) +# https://en.wikipedia.org/wiki/Glob_(programming) + +# Base path for components, stacks and workflows configurations. +# Can also be set using `ATMOS_BASE_PATH` ENV var, or `--base-path` command-line argument. +# Supports both absolute and relative paths. +# If not provided or is an empty string, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` +# are independent settings (supporting both absolute and relative paths). +# If `base_path` is provided, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` +# are considered paths relative to `base_path`. +base_path: "./tests/b/opentofu" + +aliases: + tofu: terraform + +components: + terraform: + command: "tofu" + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_BASE_PATH` ENV var, or `--terraform-dir` command-line argument + # Supports both absolute and relative paths + base_path: "components/terraform" + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE` ENV var + apply_auto_approve: false + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT` ENV var, or `--deploy-run-init` command-line argument + deploy_run_init: true + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_INIT_RUN_RECONFIGURE` ENV var, or `--init-run-reconfigure` command-line argument + init_run_reconfigure: true + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE` ENV var, or `--auto-generate-backend-file` command-line argument + auto_generate_backend_file: true + helmfile: + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_BASE_PATH` ENV var, or `--helmfile-dir` command-line argument + # Supports both absolute and relative paths + base_path: "components/helmfile" + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_KUBECONFIG_PATH` ENV var + kubeconfig_path: "/conf/.kube/" + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_HELM_AWS_PROFILE_PATTERN` ENV var + helm_aws_profile_pattern: "{namespace}-{tenant}-gbl-{stage}-helm" + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_CLUSTER_NAME_PATTERN` ENV var + cluster_name_pattern: "{namespace}-{tenant}-{environment}-{stage}-eks-cluster" + +stacks: + # Can also be set using `ATMOS_STACKS_BASE_PATH` ENV var, or `--config-dir` and `--stacks-dir` command-line arguments + # Supports both absolute and relative paths + base_path: "stacks" + # Can also be set using `ATMOS_STACKS_INCLUDED_PATHS` ENV var (comma-separated values string) + # Since we are distinguishing stacks based on namespace, and namespace is not part + # of the stack name, we have to set `included_paths` via the ENV var in the Dockerfile + included_paths: + - "orgs/**/*" + # Can also be set using `ATMOS_STACKS_EXCLUDED_PATHS` ENV var (comma-separated values string) + excluded_paths: + - "**/_defaults.yaml" + # exclude workflows directory if otherwise included in `included_paths` above + # - "workflows/**/*" + + # Can also be set using `ATMOS_STACKS_NAME_PATTERN` ENV var + name_pattern: "{tenant}-{environment}-{stage}" + +integrations: + github: + gitops: + opentofu-version: 1.7.3 + infracost-enabled: __INFRACOST_ENABLED__ + artifact-storage: + region: __STORAGE_REGION__ + bucket: __STORAGE_BUCKET__ + table: __STORAGE_TABLE__ + role: __STORAGE_ROLE__ + plan-repository-type: s3 + metadata-repository-type: dynamo + role: + plan: __PLAN_ROLE__ + apply: __APPLY_ROLE__ + matrix: + sort-by: .stack_slug + group-by: .stack_slug | split("-") | [.[0], .[2]] | join("-") + +workflows: + # Can also be set using `ATMOS_WORKFLOWS_BASE_PATH` ENV var, or `--workflows-dir` command-line arguments + # Supports both absolute and relative paths + base_path: "stacks/workflows" + +logs: + verbose: false + colors: true diff --git a/tests/b/opentofu/components/terraform/foobar/context.tf b/tests/b/opentofu/components/terraform/foobar/context.tf new file mode 100644 index 00000000..5e0ef885 --- /dev/null +++ b/tests/b/opentofu/components/terraform/foobar/context.tf @@ -0,0 +1,279 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "cloudposse/label/null" + version = "0.25.0" # requires Terraform >= 0.13.0 + + enabled = var.enabled + namespace = var.namespace + tenant = var.tenant + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + label_key_case = var.label_key_case + label_value_case = var.label_value_case + descriptor_formats = var.descriptor_formats + labels_as_tags = var.labels_as_tags + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = any + default = { + enabled = true + namespace = null + tenant = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + label_key_case = null + label_value_case = null + descriptor_formats = {} + # Note: we have to use [] instead of null for unset lists due to + # https://github.com/hashicorp/terraform/issues/28137 + # which was not fixed until Terraform 1.0.0, + # but we want the default to be all the labels in `label_order` + # and we want users to be able to prevent all tag generation + # by setting `labels_as_tags` to `[]`, so we need + # a different sentinel to indicate "default" + labels_as_tags = ["unset"] + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT + + validation { + condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`." + } + + validation { + condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" +} + +variable "tenant" { + type = string + default = null + description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" +} + +variable "environment" { + type = string + default = null + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = <<-EOT + ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. + This is the only ID element not also included as a `tag`. + The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. + EOT +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between ID elements. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = <<-EOT + ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, + in the order they appear in the list. New attributes are appended to the + end of the list. The elements of the list are joined by the `delimiter` + and treated as a single ID element. + EOT +} + +variable "labels_as_tags" { + type = set(string) + default = ["default"] + description = <<-EOT + Set of labels (ID elements) to include as tags in the `tags` output. + Default is to include all labels. + Tags with empty values will not be included in the `tags` output. + Set to `[]` to suppress all generated tags. + **Notes:** + The value of the `name` tag, if included, will be the `id`, not the `name`. + Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be + changed in later chained modules. Attempts to change it will be silently ignored. + EOT +} + +variable "tags" { + type = map(string) + default = {} + description = <<-EOT + Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). + Neither the tag keys nor the tag values will be modified by this module. + EOT +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = <<-EOT + Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. + This is for some rare cases where resources want additional configuration of tags + and therefore take a list of maps with tag key, value, and additional configuration. + EOT +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The order in which the labels (ID elements) appear in the `id`. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Terraform regular expression (regex) string. + Characters matching the regex will be removed from the ID elements. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters (minimum 6). + Set to `0` for unlimited length. + Set to `null` for keep the existing setting, which defaults to `0`. + Does not affect `id_full`. + EOT + validation { + condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 + error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." + } +} + +variable "label_key_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of the `tags` keys (label names) for tags generated by this module. + Does not affect keys of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper`. + Default value: `title`. + EOT + + validation { + condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) + error_message = "Allowed values: `lower`, `title`, `upper`." + } +} + +variable "label_value_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of ID elements (labels) as included in `id`, + set as tag values, and output by this module individually. + Does not affect values of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. + Default value: `lower`. + EOT + + validation { + condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "descriptor_formats" { + type = any + default = {} + description = <<-EOT + Describe additional descriptors to be output in the `descriptors` output map. + Map of maps. Keys are names of descriptors. Values are maps of the form + `{ + format = string + labels = list(string) + }` + (Type is `any` so the map values can later be enhanced to provide additional options.) + `format` is a Terraform format string to be passed to the `format()` function. + `labels` is a list of labels, in order, to pass to `format()` function. + Label values will be normalized before being passed to `format()` so they will be + identical to how they appear in `id`. + Default is `{}` (`descriptors` output will be empty). + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/tests/b/opentofu/components/terraform/foobar/main.tf b/tests/b/opentofu/components/terraform/foobar/main.tf new file mode 100644 index 00000000..5fc39577 --- /dev/null +++ b/tests/b/opentofu/components/terraform/foobar/main.tf @@ -0,0 +1,8 @@ +resource "random_id" "foo" { + keepers = { + # Generate a new id each time we switch to a new seed + seed = "${module.this.id}-${var.example}" + timestamp = "${timestamp()}" + } + byte_length = 8 +} diff --git a/tests/b/opentofu/components/terraform/foobar/outputs.tf b/tests/b/opentofu/components/terraform/foobar/outputs.tf new file mode 100644 index 00000000..055f02d5 --- /dev/null +++ b/tests/b/opentofu/components/terraform/foobar/outputs.tf @@ -0,0 +1,21 @@ +output "result" { + description = "Test description output" + value = random_id.foo.id +} + +output "sensitive_value" { + description = "Test sensitive description output" + value = random_id.foo.id + sensitive = true +} + + +output "structured_value" { + description = "Test structured output" + value = { + test = "test" + value = { + result = random_id.foo.id + } + } +} \ No newline at end of file diff --git a/tests/b/opentofu/components/terraform/foobar/variables.tf b/tests/b/opentofu/components/terraform/foobar/variables.tf new file mode 100644 index 00000000..d9b2dde4 --- /dev/null +++ b/tests/b/opentofu/components/terraform/foobar/variables.tf @@ -0,0 +1,5 @@ +variable "example" { + type = string + description = "testing variable" +} + diff --git a/tests/b/opentofu/stacks/catalog/foobar-atmos-pro.yaml b/tests/b/opentofu/stacks/catalog/foobar-atmos-pro.yaml new file mode 100644 index 00000000..87529334 --- /dev/null +++ b/tests/b/opentofu/stacks/catalog/foobar-atmos-pro.yaml @@ -0,0 +1,13 @@ +components: + terraform: + foobar-atmos-pro: + metadata: + component: foobar + settings: + pro: + enabled: true + github: + actions_enabled: false + vars: + example: blue + enabled: true \ No newline at end of file diff --git a/tests/b/opentofu/stacks/catalog/foobar.yaml b/tests/b/opentofu/stacks/catalog/foobar.yaml new file mode 100644 index 00000000..991c4742 --- /dev/null +++ b/tests/b/opentofu/stacks/catalog/foobar.yaml @@ -0,0 +1,8 @@ +components: + terraform: + foobar: + settings: + github: + actions_enabled: true + vars: + example: blue diff --git a/tests/b/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/b/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml new file mode 100644 index 00000000..65394b42 --- /dev/null +++ b/tests/b/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml @@ -0,0 +1,30 @@ +import: + - catalog/foobar + - catalog/foobar-atmos-pro + +terraform: + backend_type: s3 + backend: + s3: + bucket: cptest-core-ue2-root-tfstate-plat + dynamodb_table: cptest-core-ue2-root-tfstate-plat-lock + role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-plat + encrypt: true + key: opentofu/terraform.tfstate + acl: bucket-owner-full-control + region: us-east-2 + + vars: + environment: ue2 + namespace: foo + region: us-east-2 + stage: sandbox + tenant: plat + label_order: + - namespace + - tenant + - environment + - stage + - name + - attributes + diff --git a/tests/b/terraform/atmos.yaml b/tests/b/terraform/atmos.yaml new file mode 100644 index 00000000..b94de1a0 --- /dev/null +++ b/tests/b/terraform/atmos.yaml @@ -0,0 +1,93 @@ +# CLI config is loaded from the following locations (from lowest to highest priority): +# system dir (`/usr/local/etc/atmos` on Linux, `%LOCALAPPDATA%/atmos` on Windows) +# home dir (~/.atmos) +# current directory +# ENV vars +# Command-line arguments +# +# It supports POSIX-style Globs for file names/paths (double-star `**` is supported) +# https://en.wikipedia.org/wiki/Glob_(programming) + +# Base path for components, stacks and workflows configurations. +# Can also be set using `ATMOS_BASE_PATH` ENV var, or `--base-path` command-line argument. +# Supports both absolute and relative paths. +# If not provided or is an empty string, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` +# are independent settings (supporting both absolute and relative paths). +# If `base_path` is provided, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` +# are considered paths relative to `base_path`. +base_path: "./tests/b/terraform" + +components: + terraform: + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_BASE_PATH` ENV var, or `--terraform-dir` command-line argument + # Supports both absolute and relative paths + base_path: "components/terraform" + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE` ENV var + apply_auto_approve: false + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT` ENV var, or `--deploy-run-init` command-line argument + deploy_run_init: true + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_INIT_RUN_RECONFIGURE` ENV var, or `--init-run-reconfigure` command-line argument + init_run_reconfigure: true + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE` ENV var, or `--auto-generate-backend-file` command-line argument + auto_generate_backend_file: true + helmfile: + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_BASE_PATH` ENV var, or `--helmfile-dir` command-line argument + # Supports both absolute and relative paths + base_path: "components/helmfile" + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_KUBECONFIG_PATH` ENV var + kubeconfig_path: "/conf/.kube/" + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_HELM_AWS_PROFILE_PATTERN` ENV var + helm_aws_profile_pattern: "{namespace}-{tenant}-gbl-{stage}-helm" + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_CLUSTER_NAME_PATTERN` ENV var + cluster_name_pattern: "{namespace}-{tenant}-{environment}-{stage}-eks-cluster" + +stacks: + # Can also be set using `ATMOS_STACKS_BASE_PATH` ENV var, or `--config-dir` and `--stacks-dir` command-line arguments + # Supports both absolute and relative paths + base_path: "stacks" + # Can also be set using `ATMOS_STACKS_INCLUDED_PATHS` ENV var (comma-separated values string) + # Since we are distinguishing stacks based on namespace, and namespace is not part + # of the stack name, we have to set `included_paths` via the ENV var in the Dockerfile + included_paths: + - "orgs/**/*" + # Can also be set using `ATMOS_STACKS_EXCLUDED_PATHS` ENV var (comma-separated values string) + excluded_paths: + - "**/_defaults.yaml" + # exclude workflows directory if otherwise included in `included_paths` above + # - "workflows/**/*" + + # Can also be set using `ATMOS_STACKS_NAME_PATTERN` ENV var + name_pattern: "{tenant}-{environment}-{stage}" + +integrations: + github: + gitops: + terraform-version: 1.5.7 + infracost-enabled: __INFRACOST_ENABLED__ + artifact-storage: + region: __STORAGE_REGION__ + bucket: __STORAGE_BUCKET__ + table: __STORAGE_TABLE__ + role: __STORAGE_ROLE__ + plan-repository-type: s3 + metadata-repository-type: dynamo + blob-account-name: + blob-container-name: + cosmos-container-name: + cosmos-database-name: + cosmos-endpoint: + role: + plan: __PLAN_ROLE__ + apply: __APPLY_ROLE__ + matrix: + sort-by: .stack_slug + group-by: .stack_slug | split("-") | [.[0], .[2]] | join("-") + +workflows: + # Can also be set using `ATMOS_WORKFLOWS_BASE_PATH` ENV var, or `--workflows-dir` command-line arguments + # Supports both absolute and relative paths + base_path: "stacks/workflows" + +logs: + verbose: false + colors: true diff --git a/tests/b/terraform/components/terraform/foobar/context.tf b/tests/b/terraform/components/terraform/foobar/context.tf new file mode 100644 index 00000000..5e0ef885 --- /dev/null +++ b/tests/b/terraform/components/terraform/foobar/context.tf @@ -0,0 +1,279 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "cloudposse/label/null" + version = "0.25.0" # requires Terraform >= 0.13.0 + + enabled = var.enabled + namespace = var.namespace + tenant = var.tenant + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + label_key_case = var.label_key_case + label_value_case = var.label_value_case + descriptor_formats = var.descriptor_formats + labels_as_tags = var.labels_as_tags + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = any + default = { + enabled = true + namespace = null + tenant = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + label_key_case = null + label_value_case = null + descriptor_formats = {} + # Note: we have to use [] instead of null for unset lists due to + # https://github.com/hashicorp/terraform/issues/28137 + # which was not fixed until Terraform 1.0.0, + # but we want the default to be all the labels in `label_order` + # and we want users to be able to prevent all tag generation + # by setting `labels_as_tags` to `[]`, so we need + # a different sentinel to indicate "default" + labels_as_tags = ["unset"] + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT + + validation { + condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`." + } + + validation { + condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" +} + +variable "tenant" { + type = string + default = null + description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" +} + +variable "environment" { + type = string + default = null + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = <<-EOT + ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. + This is the only ID element not also included as a `tag`. + The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. + EOT +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between ID elements. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = <<-EOT + ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, + in the order they appear in the list. New attributes are appended to the + end of the list. The elements of the list are joined by the `delimiter` + and treated as a single ID element. + EOT +} + +variable "labels_as_tags" { + type = set(string) + default = ["default"] + description = <<-EOT + Set of labels (ID elements) to include as tags in the `tags` output. + Default is to include all labels. + Tags with empty values will not be included in the `tags` output. + Set to `[]` to suppress all generated tags. + **Notes:** + The value of the `name` tag, if included, will be the `id`, not the `name`. + Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be + changed in later chained modules. Attempts to change it will be silently ignored. + EOT +} + +variable "tags" { + type = map(string) + default = {} + description = <<-EOT + Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). + Neither the tag keys nor the tag values will be modified by this module. + EOT +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = <<-EOT + Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. + This is for some rare cases where resources want additional configuration of tags + and therefore take a list of maps with tag key, value, and additional configuration. + EOT +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The order in which the labels (ID elements) appear in the `id`. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Terraform regular expression (regex) string. + Characters matching the regex will be removed from the ID elements. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters (minimum 6). + Set to `0` for unlimited length. + Set to `null` for keep the existing setting, which defaults to `0`. + Does not affect `id_full`. + EOT + validation { + condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 + error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." + } +} + +variable "label_key_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of the `tags` keys (label names) for tags generated by this module. + Does not affect keys of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper`. + Default value: `title`. + EOT + + validation { + condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) + error_message = "Allowed values: `lower`, `title`, `upper`." + } +} + +variable "label_value_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of ID elements (labels) as included in `id`, + set as tag values, and output by this module individually. + Does not affect values of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. + Default value: `lower`. + EOT + + validation { + condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "descriptor_formats" { + type = any + default = {} + description = <<-EOT + Describe additional descriptors to be output in the `descriptors` output map. + Map of maps. Keys are names of descriptors. Values are maps of the form + `{ + format = string + labels = list(string) + }` + (Type is `any` so the map values can later be enhanced to provide additional options.) + `format` is a Terraform format string to be passed to the `format()` function. + `labels` is a list of labels, in order, to pass to `format()` function. + Label values will be normalized before being passed to `format()` so they will be + identical to how they appear in `id`. + Default is `{}` (`descriptors` output will be empty). + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/tests/b/terraform/components/terraform/foobar/main.tf b/tests/b/terraform/components/terraform/foobar/main.tf new file mode 100644 index 00000000..5fc39577 --- /dev/null +++ b/tests/b/terraform/components/terraform/foobar/main.tf @@ -0,0 +1,8 @@ +resource "random_id" "foo" { + keepers = { + # Generate a new id each time we switch to a new seed + seed = "${module.this.id}-${var.example}" + timestamp = "${timestamp()}" + } + byte_length = 8 +} diff --git a/tests/b/terraform/components/terraform/foobar/outputs.tf b/tests/b/terraform/components/terraform/foobar/outputs.tf new file mode 100644 index 00000000..7177f0bd --- /dev/null +++ b/tests/b/terraform/components/terraform/foobar/outputs.tf @@ -0,0 +1,21 @@ +output "result" { + description = "Test description output" + value = random_id.foo.id +} + +output "sensitive_value" { + description = "Test sensitive description output" + value = random_id.foo.id + sensitive = true +} + + +output "structured_value" { + description = "Test structured output" + value = { + test = "test" + value = { + result = random_id.foo.id + } + } +} diff --git a/tests/b/terraform/components/terraform/foobar/variables.tf b/tests/b/terraform/components/terraform/foobar/variables.tf new file mode 100644 index 00000000..d9b2dde4 --- /dev/null +++ b/tests/b/terraform/components/terraform/foobar/variables.tf @@ -0,0 +1,5 @@ +variable "example" { + type = string + description = "testing variable" +} + diff --git a/tests/b/terraform/stacks/catalog/foobar-atmos-pro.yaml b/tests/b/terraform/stacks/catalog/foobar-atmos-pro.yaml new file mode 100644 index 00000000..87529334 --- /dev/null +++ b/tests/b/terraform/stacks/catalog/foobar-atmos-pro.yaml @@ -0,0 +1,13 @@ +components: + terraform: + foobar-atmos-pro: + metadata: + component: foobar + settings: + pro: + enabled: true + github: + actions_enabled: false + vars: + example: blue + enabled: true \ No newline at end of file diff --git a/tests/b/terraform/stacks/catalog/foobar.yaml b/tests/b/terraform/stacks/catalog/foobar.yaml new file mode 100644 index 00000000..991c4742 --- /dev/null +++ b/tests/b/terraform/stacks/catalog/foobar.yaml @@ -0,0 +1,8 @@ +components: + terraform: + foobar: + settings: + github: + actions_enabled: true + vars: + example: blue diff --git a/tests/b/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/b/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml new file mode 100644 index 00000000..3d552592 --- /dev/null +++ b/tests/b/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml @@ -0,0 +1,30 @@ +import: + - catalog/foobar + - catalog/foobar-atmos-pro + +terraform: + backend_type: s3 + backend: + s3: + bucket: cptest-core-ue2-root-tfstate-plat + dynamodb_table: cptest-core-ue2-root-tfstate-plat-lock + role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-plat + encrypt: true + key: terraform/terraform.tfstate + acl: bucket-owner-full-control + region: us-east-2 + + vars: + environment: ue2 + namespace: foo + region: us-east-2 + stage: sandbox + tenant: plat + label_order: + - namespace + - tenant + - environment + - stage + - name + - attributes + From 43932a5b2af1f6cdddd14159cf5127f6a2c58449 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 19:50:33 +0200 Subject: [PATCH 046/123] Added A/B testings --- .github/workflows/integration-tests-plan-diff.yml | 4 ++-- .github/workflows/integration-tests.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index cd4c3e73..c36bf72f 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -31,7 +31,7 @@ jobs: - shell: bash run: | mkdir -p ${{ runner.temp }} - cp ./tests/${{ matrix.platform }}/b/atmos.yaml ${{ runner.temp }}/atmos.yaml + cp ./tests/b/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml @@ -52,7 +52,7 @@ jobs: - shell: bash run: | mkdir -p ${{ runner.temp }} - cp ./tests/${{ matrix.platform }}/a/atmos.yaml ${{ runner.temp }}/atmos.yaml + cp ./tests/a/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 579bb0fc..afecdcf5 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -31,7 +31,7 @@ jobs: - shell: bash run: | mkdir -p ${{ runner.temp }} - cp ./tests/${{ matrix.platform }}/a/atmos.yaml ${{ runner.temp }}/atmos.yaml + cp ./tests/a/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml From ff1330a09e8722fa67d2ccad2af178a2ed7e46fc Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 20:06:19 +0200 Subject: [PATCH 047/123] Added A/B testings --- tests/a/terraform/atmos.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/a/terraform/atmos.yaml b/tests/a/terraform/atmos.yaml index e4037b08..a7d8139b 100644 --- a/tests/a/terraform/atmos.yaml +++ b/tests/a/terraform/atmos.yaml @@ -15,7 +15,7 @@ # are independent settings (supporting both absolute and relative paths). # If `base_path` is provided, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` # are considered paths relative to `base_path`. -base_path: "./tests/terraform" +base_path: "./tests/a/terraform" components: terraform: From 3e794cc2ff514ab30251094361b4ee9053079204 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 20:31:03 +0200 Subject: [PATCH 048/123] Added A/B testings --- action.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 03897d0b..ca2a2787 100644 --- a/action.yml +++ b/action.yml @@ -367,7 +367,9 @@ runs: --skip-init PLAN_CHANGED=$? fi - + echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + echo "PLAN_CHANGED: $PLAN_CHANGED" + echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" if [[ "${PLAN_CHANGED}" == "0" ]]; then echo "plan_changed=false" >> $GITHUB_OUTPUT else From 347e9fbc3d8161970a4492e18d1c3f6758e8ece1 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 20:53:20 +0200 Subject: [PATCH 049/123] Added A/B testings --- .github/workflows/integration-tests.yml | 2 +- tests/opentofu/atmos.yaml | 92 ++++++ .../components/terraform/foobar/context.tf | 279 ++++++++++++++++++ .../components/terraform/foobar/main.tf | 7 + .../components/terraform/foobar/outputs.tf | 21 ++ .../components/terraform/foobar/variables.tf | 10 + .../stacks/catalog/foobar-atmos-pro.yaml | 13 + tests/opentofu/stacks/catalog/foobar.yaml | 8 + .../foo/plat/sandbox/plat-ue2-sandbox.yaml | 30 ++ tests/terraform/atmos.yaml | 93 ++++++ .../components/terraform/foobar/context.tf | 279 ++++++++++++++++++ .../components/terraform/foobar/main.tf | 7 + .../components/terraform/foobar/outputs.tf | 21 ++ .../components/terraform/foobar/variables.tf | 10 + .../stacks/catalog/foobar-atmos-pro.yaml | 13 + tests/terraform/stacks/catalog/foobar.yaml | 8 + .../foo/plat/sandbox/plat-ue2-sandbox.yaml | 30 ++ 17 files changed, 922 insertions(+), 1 deletion(-) create mode 100644 tests/opentofu/atmos.yaml create mode 100644 tests/opentofu/components/terraform/foobar/context.tf create mode 100644 tests/opentofu/components/terraform/foobar/main.tf create mode 100644 tests/opentofu/components/terraform/foobar/outputs.tf create mode 100644 tests/opentofu/components/terraform/foobar/variables.tf create mode 100644 tests/opentofu/stacks/catalog/foobar-atmos-pro.yaml create mode 100644 tests/opentofu/stacks/catalog/foobar.yaml create mode 100644 tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml create mode 100644 tests/terraform/atmos.yaml create mode 100644 tests/terraform/components/terraform/foobar/context.tf create mode 100644 tests/terraform/components/terraform/foobar/main.tf create mode 100644 tests/terraform/components/terraform/foobar/outputs.tf create mode 100644 tests/terraform/components/terraform/foobar/variables.tf create mode 100644 tests/terraform/stacks/catalog/foobar-atmos-pro.yaml create mode 100644 tests/terraform/stacks/catalog/foobar.yaml create mode 100644 tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index afecdcf5..26c2292d 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -31,7 +31,7 @@ jobs: - shell: bash run: | mkdir -p ${{ runner.temp }} - cp ./tests/a/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml + cp ./tests/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml diff --git a/tests/opentofu/atmos.yaml b/tests/opentofu/atmos.yaml new file mode 100644 index 00000000..46867467 --- /dev/null +++ b/tests/opentofu/atmos.yaml @@ -0,0 +1,92 @@ +# CLI config is loaded from the following locations (from lowest to highest priority): +# system dir (`/usr/local/etc/atmos` on Linux, `%LOCALAPPDATA%/atmos` on Windows) +# home dir (~/.atmos) +# current directory +# ENV vars +# Command-line arguments +# +# It supports POSIX-style Globs for file names/paths (double-star `**` is supported) +# https://en.wikipedia.org/wiki/Glob_(programming) + +# Base path for components, stacks and workflows configurations. +# Can also be set using `ATMOS_BASE_PATH` ENV var, or `--base-path` command-line argument. +# Supports both absolute and relative paths. +# If not provided or is an empty string, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` +# are independent settings (supporting both absolute and relative paths). +# If `base_path` is provided, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` +# are considered paths relative to `base_path`. +base_path: "./tests/opentofu" + +aliases: + tofu: terraform + +components: + terraform: + command: "tofu" + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_BASE_PATH` ENV var, or `--terraform-dir` command-line argument + # Supports both absolute and relative paths + base_path: "components/terraform" + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE` ENV var + apply_auto_approve: false + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT` ENV var, or `--deploy-run-init` command-line argument + deploy_run_init: true + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_INIT_RUN_RECONFIGURE` ENV var, or `--init-run-reconfigure` command-line argument + init_run_reconfigure: true + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE` ENV var, or `--auto-generate-backend-file` command-line argument + auto_generate_backend_file: true + helmfile: + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_BASE_PATH` ENV var, or `--helmfile-dir` command-line argument + # Supports both absolute and relative paths + base_path: "components/helmfile" + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_KUBECONFIG_PATH` ENV var + kubeconfig_path: "/conf/.kube/" + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_HELM_AWS_PROFILE_PATTERN` ENV var + helm_aws_profile_pattern: "{namespace}-{tenant}-gbl-{stage}-helm" + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_CLUSTER_NAME_PATTERN` ENV var + cluster_name_pattern: "{namespace}-{tenant}-{environment}-{stage}-eks-cluster" + +stacks: + # Can also be set using `ATMOS_STACKS_BASE_PATH` ENV var, or `--config-dir` and `--stacks-dir` command-line arguments + # Supports both absolute and relative paths + base_path: "stacks" + # Can also be set using `ATMOS_STACKS_INCLUDED_PATHS` ENV var (comma-separated values string) + # Since we are distinguishing stacks based on namespace, and namespace is not part + # of the stack name, we have to set `included_paths` via the ENV var in the Dockerfile + included_paths: + - "orgs/**/*" + # Can also be set using `ATMOS_STACKS_EXCLUDED_PATHS` ENV var (comma-separated values string) + excluded_paths: + - "**/_defaults.yaml" + # exclude workflows directory if otherwise included in `included_paths` above + # - "workflows/**/*" + + # Can also be set using `ATMOS_STACKS_NAME_PATTERN` ENV var + name_pattern: "{tenant}-{environment}-{stage}" + +integrations: + github: + gitops: + opentofu-version: 1.7.3 + infracost-enabled: __INFRACOST_ENABLED__ + artifact-storage: + region: __STORAGE_REGION__ + bucket: __STORAGE_BUCKET__ + table: __STORAGE_TABLE__ + role: __STORAGE_ROLE__ + plan-repository-type: s3 + metadata-repository-type: dynamo + role: + plan: __PLAN_ROLE__ + apply: __APPLY_ROLE__ + matrix: + sort-by: .stack_slug + group-by: .stack_slug | split("-") | [.[0], .[2]] | join("-") + +workflows: + # Can also be set using `ATMOS_WORKFLOWS_BASE_PATH` ENV var, or `--workflows-dir` command-line arguments + # Supports both absolute and relative paths + base_path: "stacks/workflows" + +logs: + verbose: false + colors: true diff --git a/tests/opentofu/components/terraform/foobar/context.tf b/tests/opentofu/components/terraform/foobar/context.tf new file mode 100644 index 00000000..5e0ef885 --- /dev/null +++ b/tests/opentofu/components/terraform/foobar/context.tf @@ -0,0 +1,279 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "cloudposse/label/null" + version = "0.25.0" # requires Terraform >= 0.13.0 + + enabled = var.enabled + namespace = var.namespace + tenant = var.tenant + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + label_key_case = var.label_key_case + label_value_case = var.label_value_case + descriptor_formats = var.descriptor_formats + labels_as_tags = var.labels_as_tags + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = any + default = { + enabled = true + namespace = null + tenant = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + label_key_case = null + label_value_case = null + descriptor_formats = {} + # Note: we have to use [] instead of null for unset lists due to + # https://github.com/hashicorp/terraform/issues/28137 + # which was not fixed until Terraform 1.0.0, + # but we want the default to be all the labels in `label_order` + # and we want users to be able to prevent all tag generation + # by setting `labels_as_tags` to `[]`, so we need + # a different sentinel to indicate "default" + labels_as_tags = ["unset"] + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT + + validation { + condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`." + } + + validation { + condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" +} + +variable "tenant" { + type = string + default = null + description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" +} + +variable "environment" { + type = string + default = null + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = <<-EOT + ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. + This is the only ID element not also included as a `tag`. + The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. + EOT +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between ID elements. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = <<-EOT + ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, + in the order they appear in the list. New attributes are appended to the + end of the list. The elements of the list are joined by the `delimiter` + and treated as a single ID element. + EOT +} + +variable "labels_as_tags" { + type = set(string) + default = ["default"] + description = <<-EOT + Set of labels (ID elements) to include as tags in the `tags` output. + Default is to include all labels. + Tags with empty values will not be included in the `tags` output. + Set to `[]` to suppress all generated tags. + **Notes:** + The value of the `name` tag, if included, will be the `id`, not the `name`. + Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be + changed in later chained modules. Attempts to change it will be silently ignored. + EOT +} + +variable "tags" { + type = map(string) + default = {} + description = <<-EOT + Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). + Neither the tag keys nor the tag values will be modified by this module. + EOT +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = <<-EOT + Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. + This is for some rare cases where resources want additional configuration of tags + and therefore take a list of maps with tag key, value, and additional configuration. + EOT +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The order in which the labels (ID elements) appear in the `id`. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Terraform regular expression (regex) string. + Characters matching the regex will be removed from the ID elements. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters (minimum 6). + Set to `0` for unlimited length. + Set to `null` for keep the existing setting, which defaults to `0`. + Does not affect `id_full`. + EOT + validation { + condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 + error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." + } +} + +variable "label_key_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of the `tags` keys (label names) for tags generated by this module. + Does not affect keys of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper`. + Default value: `title`. + EOT + + validation { + condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) + error_message = "Allowed values: `lower`, `title`, `upper`." + } +} + +variable "label_value_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of ID elements (labels) as included in `id`, + set as tag values, and output by this module individually. + Does not affect values of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. + Default value: `lower`. + EOT + + validation { + condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "descriptor_formats" { + type = any + default = {} + description = <<-EOT + Describe additional descriptors to be output in the `descriptors` output map. + Map of maps. Keys are names of descriptors. Values are maps of the form + `{ + format = string + labels = list(string) + }` + (Type is `any` so the map values can later be enhanced to provide additional options.) + `format` is a Terraform format string to be passed to the `format()` function. + `labels` is a list of labels, in order, to pass to `format()` function. + Label values will be normalized before being passed to `format()` so they will be + identical to how they appear in `id`. + Default is `{}` (`descriptors` output will be empty). + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/tests/opentofu/components/terraform/foobar/main.tf b/tests/opentofu/components/terraform/foobar/main.tf new file mode 100644 index 00000000..de59eb69 --- /dev/null +++ b/tests/opentofu/components/terraform/foobar/main.tf @@ -0,0 +1,7 @@ +resource "random_id" "foo" { + keepers = { + # Generate a new id each time we switch to a new seed + seed = "${module.this.id}-${var.example}-${var.seed}" + } + byte_length = 8 +} diff --git a/tests/opentofu/components/terraform/foobar/outputs.tf b/tests/opentofu/components/terraform/foobar/outputs.tf new file mode 100644 index 00000000..055f02d5 --- /dev/null +++ b/tests/opentofu/components/terraform/foobar/outputs.tf @@ -0,0 +1,21 @@ +output "result" { + description = "Test description output" + value = random_id.foo.id +} + +output "sensitive_value" { + description = "Test sensitive description output" + value = random_id.foo.id + sensitive = true +} + + +output "structured_value" { + description = "Test structured output" + value = { + test = "test" + value = { + result = random_id.foo.id + } + } +} \ No newline at end of file diff --git a/tests/opentofu/components/terraform/foobar/variables.tf b/tests/opentofu/components/terraform/foobar/variables.tf new file mode 100644 index 00000000..becf84e0 --- /dev/null +++ b/tests/opentofu/components/terraform/foobar/variables.tf @@ -0,0 +1,10 @@ +variable "example" { + type = string + description = "testing variable" +} + +variable "seed" { + type = string + description = "testing variable" + default = "seed" +} diff --git a/tests/opentofu/stacks/catalog/foobar-atmos-pro.yaml b/tests/opentofu/stacks/catalog/foobar-atmos-pro.yaml new file mode 100644 index 00000000..87529334 --- /dev/null +++ b/tests/opentofu/stacks/catalog/foobar-atmos-pro.yaml @@ -0,0 +1,13 @@ +components: + terraform: + foobar-atmos-pro: + metadata: + component: foobar + settings: + pro: + enabled: true + github: + actions_enabled: false + vars: + example: blue + enabled: true \ No newline at end of file diff --git a/tests/opentofu/stacks/catalog/foobar.yaml b/tests/opentofu/stacks/catalog/foobar.yaml new file mode 100644 index 00000000..991c4742 --- /dev/null +++ b/tests/opentofu/stacks/catalog/foobar.yaml @@ -0,0 +1,8 @@ +components: + terraform: + foobar: + settings: + github: + actions_enabled: true + vars: + example: blue diff --git a/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml new file mode 100644 index 00000000..65394b42 --- /dev/null +++ b/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml @@ -0,0 +1,30 @@ +import: + - catalog/foobar + - catalog/foobar-atmos-pro + +terraform: + backend_type: s3 + backend: + s3: + bucket: cptest-core-ue2-root-tfstate-plat + dynamodb_table: cptest-core-ue2-root-tfstate-plat-lock + role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-plat + encrypt: true + key: opentofu/terraform.tfstate + acl: bucket-owner-full-control + region: us-east-2 + + vars: + environment: ue2 + namespace: foo + region: us-east-2 + stage: sandbox + tenant: plat + label_order: + - namespace + - tenant + - environment + - stage + - name + - attributes + diff --git a/tests/terraform/atmos.yaml b/tests/terraform/atmos.yaml new file mode 100644 index 00000000..e4037b08 --- /dev/null +++ b/tests/terraform/atmos.yaml @@ -0,0 +1,93 @@ +# CLI config is loaded from the following locations (from lowest to highest priority): +# system dir (`/usr/local/etc/atmos` on Linux, `%LOCALAPPDATA%/atmos` on Windows) +# home dir (~/.atmos) +# current directory +# ENV vars +# Command-line arguments +# +# It supports POSIX-style Globs for file names/paths (double-star `**` is supported) +# https://en.wikipedia.org/wiki/Glob_(programming) + +# Base path for components, stacks and workflows configurations. +# Can also be set using `ATMOS_BASE_PATH` ENV var, or `--base-path` command-line argument. +# Supports both absolute and relative paths. +# If not provided or is an empty string, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` +# are independent settings (supporting both absolute and relative paths). +# If `base_path` is provided, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` +# are considered paths relative to `base_path`. +base_path: "./tests/terraform" + +components: + terraform: + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_BASE_PATH` ENV var, or `--terraform-dir` command-line argument + # Supports both absolute and relative paths + base_path: "components/terraform" + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE` ENV var + apply_auto_approve: false + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT` ENV var, or `--deploy-run-init` command-line argument + deploy_run_init: true + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_INIT_RUN_RECONFIGURE` ENV var, or `--init-run-reconfigure` command-line argument + init_run_reconfigure: true + # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE` ENV var, or `--auto-generate-backend-file` command-line argument + auto_generate_backend_file: true + helmfile: + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_BASE_PATH` ENV var, or `--helmfile-dir` command-line argument + # Supports both absolute and relative paths + base_path: "components/helmfile" + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_KUBECONFIG_PATH` ENV var + kubeconfig_path: "/conf/.kube/" + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_HELM_AWS_PROFILE_PATTERN` ENV var + helm_aws_profile_pattern: "{namespace}-{tenant}-gbl-{stage}-helm" + # Can also be set using `ATMOS_COMPONENTS_HELMFILE_CLUSTER_NAME_PATTERN` ENV var + cluster_name_pattern: "{namespace}-{tenant}-{environment}-{stage}-eks-cluster" + +stacks: + # Can also be set using `ATMOS_STACKS_BASE_PATH` ENV var, or `--config-dir` and `--stacks-dir` command-line arguments + # Supports both absolute and relative paths + base_path: "stacks" + # Can also be set using `ATMOS_STACKS_INCLUDED_PATHS` ENV var (comma-separated values string) + # Since we are distinguishing stacks based on namespace, and namespace is not part + # of the stack name, we have to set `included_paths` via the ENV var in the Dockerfile + included_paths: + - "orgs/**/*" + # Can also be set using `ATMOS_STACKS_EXCLUDED_PATHS` ENV var (comma-separated values string) + excluded_paths: + - "**/_defaults.yaml" + # exclude workflows directory if otherwise included in `included_paths` above + # - "workflows/**/*" + + # Can also be set using `ATMOS_STACKS_NAME_PATTERN` ENV var + name_pattern: "{tenant}-{environment}-{stage}" + +integrations: + github: + gitops: + terraform-version: 1.5.7 + infracost-enabled: __INFRACOST_ENABLED__ + artifact-storage: + region: __STORAGE_REGION__ + bucket: __STORAGE_BUCKET__ + table: __STORAGE_TABLE__ + role: __STORAGE_ROLE__ + plan-repository-type: s3 + metadata-repository-type: dynamo + blob-account-name: + blob-container-name: + cosmos-container-name: + cosmos-database-name: + cosmos-endpoint: + role: + plan: __PLAN_ROLE__ + apply: __APPLY_ROLE__ + matrix: + sort-by: .stack_slug + group-by: .stack_slug | split("-") | [.[0], .[2]] | join("-") + +workflows: + # Can also be set using `ATMOS_WORKFLOWS_BASE_PATH` ENV var, or `--workflows-dir` command-line arguments + # Supports both absolute and relative paths + base_path: "stacks/workflows" + +logs: + verbose: false + colors: true diff --git a/tests/terraform/components/terraform/foobar/context.tf b/tests/terraform/components/terraform/foobar/context.tf new file mode 100644 index 00000000..5e0ef885 --- /dev/null +++ b/tests/terraform/components/terraform/foobar/context.tf @@ -0,0 +1,279 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "cloudposse/label/null" + version = "0.25.0" # requires Terraform >= 0.13.0 + + enabled = var.enabled + namespace = var.namespace + tenant = var.tenant + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + label_key_case = var.label_key_case + label_value_case = var.label_value_case + descriptor_formats = var.descriptor_formats + labels_as_tags = var.labels_as_tags + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = any + default = { + enabled = true + namespace = null + tenant = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + label_key_case = null + label_value_case = null + descriptor_formats = {} + # Note: we have to use [] instead of null for unset lists due to + # https://github.com/hashicorp/terraform/issues/28137 + # which was not fixed until Terraform 1.0.0, + # but we want the default to be all the labels in `label_order` + # and we want users to be able to prevent all tag generation + # by setting `labels_as_tags` to `[]`, so we need + # a different sentinel to indicate "default" + labels_as_tags = ["unset"] + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT + + validation { + condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`." + } + + validation { + condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" +} + +variable "tenant" { + type = string + default = null + description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" +} + +variable "environment" { + type = string + default = null + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = <<-EOT + ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. + This is the only ID element not also included as a `tag`. + The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. + EOT +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between ID elements. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = <<-EOT + ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, + in the order they appear in the list. New attributes are appended to the + end of the list. The elements of the list are joined by the `delimiter` + and treated as a single ID element. + EOT +} + +variable "labels_as_tags" { + type = set(string) + default = ["default"] + description = <<-EOT + Set of labels (ID elements) to include as tags in the `tags` output. + Default is to include all labels. + Tags with empty values will not be included in the `tags` output. + Set to `[]` to suppress all generated tags. + **Notes:** + The value of the `name` tag, if included, will be the `id`, not the `name`. + Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be + changed in later chained modules. Attempts to change it will be silently ignored. + EOT +} + +variable "tags" { + type = map(string) + default = {} + description = <<-EOT + Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). + Neither the tag keys nor the tag values will be modified by this module. + EOT +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = <<-EOT + Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. + This is for some rare cases where resources want additional configuration of tags + and therefore take a list of maps with tag key, value, and additional configuration. + EOT +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The order in which the labels (ID elements) appear in the `id`. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Terraform regular expression (regex) string. + Characters matching the regex will be removed from the ID elements. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters (minimum 6). + Set to `0` for unlimited length. + Set to `null` for keep the existing setting, which defaults to `0`. + Does not affect `id_full`. + EOT + validation { + condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 + error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." + } +} + +variable "label_key_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of the `tags` keys (label names) for tags generated by this module. + Does not affect keys of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper`. + Default value: `title`. + EOT + + validation { + condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) + error_message = "Allowed values: `lower`, `title`, `upper`." + } +} + +variable "label_value_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of ID elements (labels) as included in `id`, + set as tag values, and output by this module individually. + Does not affect values of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. + Default value: `lower`. + EOT + + validation { + condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "descriptor_formats" { + type = any + default = {} + description = <<-EOT + Describe additional descriptors to be output in the `descriptors` output map. + Map of maps. Keys are names of descriptors. Values are maps of the form + `{ + format = string + labels = list(string) + }` + (Type is `any` so the map values can later be enhanced to provide additional options.) + `format` is a Terraform format string to be passed to the `format()` function. + `labels` is a list of labels, in order, to pass to `format()` function. + Label values will be normalized before being passed to `format()` so they will be + identical to how they appear in `id`. + Default is `{}` (`descriptors` output will be empty). + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/tests/terraform/components/terraform/foobar/main.tf b/tests/terraform/components/terraform/foobar/main.tf new file mode 100644 index 00000000..de59eb69 --- /dev/null +++ b/tests/terraform/components/terraform/foobar/main.tf @@ -0,0 +1,7 @@ +resource "random_id" "foo" { + keepers = { + # Generate a new id each time we switch to a new seed + seed = "${module.this.id}-${var.example}-${var.seed}" + } + byte_length = 8 +} diff --git a/tests/terraform/components/terraform/foobar/outputs.tf b/tests/terraform/components/terraform/foobar/outputs.tf new file mode 100644 index 00000000..7177f0bd --- /dev/null +++ b/tests/terraform/components/terraform/foobar/outputs.tf @@ -0,0 +1,21 @@ +output "result" { + description = "Test description output" + value = random_id.foo.id +} + +output "sensitive_value" { + description = "Test sensitive description output" + value = random_id.foo.id + sensitive = true +} + + +output "structured_value" { + description = "Test structured output" + value = { + test = "test" + value = { + result = random_id.foo.id + } + } +} diff --git a/tests/terraform/components/terraform/foobar/variables.tf b/tests/terraform/components/terraform/foobar/variables.tf new file mode 100644 index 00000000..61afd699 --- /dev/null +++ b/tests/terraform/components/terraform/foobar/variables.tf @@ -0,0 +1,10 @@ +variable "example" { + type = string + description = "testing variable" +} + +variable "seed" { + type = string + description = "testing variable" + default = "default" +} \ No newline at end of file diff --git a/tests/terraform/stacks/catalog/foobar-atmos-pro.yaml b/tests/terraform/stacks/catalog/foobar-atmos-pro.yaml new file mode 100644 index 00000000..87529334 --- /dev/null +++ b/tests/terraform/stacks/catalog/foobar-atmos-pro.yaml @@ -0,0 +1,13 @@ +components: + terraform: + foobar-atmos-pro: + metadata: + component: foobar + settings: + pro: + enabled: true + github: + actions_enabled: false + vars: + example: blue + enabled: true \ No newline at end of file diff --git a/tests/terraform/stacks/catalog/foobar.yaml b/tests/terraform/stacks/catalog/foobar.yaml new file mode 100644 index 00000000..991c4742 --- /dev/null +++ b/tests/terraform/stacks/catalog/foobar.yaml @@ -0,0 +1,8 @@ +components: + terraform: + foobar: + settings: + github: + actions_enabled: true + vars: + example: blue diff --git a/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml new file mode 100644 index 00000000..3d552592 --- /dev/null +++ b/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml @@ -0,0 +1,30 @@ +import: + - catalog/foobar + - catalog/foobar-atmos-pro + +terraform: + backend_type: s3 + backend: + s3: + bucket: cptest-core-ue2-root-tfstate-plat + dynamodb_table: cptest-core-ue2-root-tfstate-plat-lock + role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-plat + encrypt: true + key: terraform/terraform.tfstate + acl: bucket-owner-full-control + region: us-east-2 + + vars: + environment: ue2 + namespace: foo + region: us-east-2 + stage: sandbox + tenant: plat + label_order: + - namespace + - tenant + - environment + - stage + - name + - attributes + From 21dd50a5a9ab9f61dc1215ea316649488640143e Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 21:12:17 +0200 Subject: [PATCH 050/123] Added A/B testings --- .github/workflows/integration-test-atmos-pro.yml | 2 +- .github/workflows/integration-tests-plan-diff.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/integration-test-atmos-pro.yml b/.github/workflows/integration-test-atmos-pro.yml index 66f22c8e..d7ebdac4 100644 --- a/.github/workflows/integration-test-atmos-pro.yml +++ b/.github/workflows/integration-test-atmos-pro.yml @@ -35,7 +35,7 @@ jobs: shell: bash run: | mkdir -p ${{ runner.temp }} - cp ./tests/a/opentofu/atmos.yaml ${{ runner.temp }}/atmos.yaml + cp ./tests/opentofu/atmos.yaml ${{ runner.temp }}/atmos.yaml sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index c36bf72f..f4f341ea 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -31,7 +31,7 @@ jobs: - shell: bash run: | mkdir -p ${{ runner.temp }} - cp ./tests/b/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml + cp ./tests/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml @@ -52,7 +52,7 @@ jobs: - shell: bash run: | mkdir -p ${{ runner.temp }} - cp ./tests/a/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml + cp ./tests/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml From 12fde609b9e03ded1079ed8d21ac3e5e7c72f9b5 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 21:26:24 +0200 Subject: [PATCH 051/123] Added A/B testings --- .github/workflows/integration-tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 26c2292d..35c8d986 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -15,6 +15,9 @@ permissions: id-token: write contents: read +concurrency: + group: ${{ github.ref }} + jobs: test: runs-on: ubuntu-latest From 445ae52d791b0dfd2b5e927a26bdc667623e6cea Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 21:46:30 +0200 Subject: [PATCH 052/123] Added A/B testings --- .github/workflows/integration-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 35c8d986..6b163393 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -51,6 +51,8 @@ jobs: stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} debug: true + env: + TF_VAR_seed: ${{ env.GITHUB_RUN_ID }}-${{ env.GITHUB_RUN_ATTEMPT }} - uses: actions/checkout@v4 with: From fac998d5c6ac9c603a055cbf91d2d7adf4403d98 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 22:38:16 +0200 Subject: [PATCH 053/123] Added A/B testings --- .github/workflows/integration-tests.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 6b163393..3c3dd731 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -44,6 +44,8 @@ jobs: sed -i -e 's#__PLAN_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__APPLY_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + echo "TF_VAR_seed=${{ env.GITHUB_RUN_ID }}-${{ env.GITHUB_RUN_ATTEMPT }}" >> $GITHUB_ENV + - name: Plan Atmos Component uses: cloudposse/github-action-atmos-terraform-plan@v4 with: @@ -52,7 +54,8 @@ jobs: atmos-config-path: ${{ runner.temp }} debug: true env: - TF_VAR_seed: ${{ env.GITHUB_RUN_ID }}-${{ env.GITHUB_RUN_ATTEMPT }} + TF_VAR_seed: ${{ env.TF_VAR_seed }} + - uses: actions/checkout@v4 with: From 87b3d0dd0056f7295578d5967ec50026d9fc871d Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 22:43:35 +0200 Subject: [PATCH 054/123] Added A/B testings --- .github/workflows/integration-tests.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 3c3dd731..49e7082f 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -32,6 +32,7 @@ jobs: ref: ${{ github.event.pull_request.head.ref }} - shell: bash + id: env run: | mkdir -p ${{ runner.temp }} cp ./tests/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml @@ -44,7 +45,7 @@ jobs: sed -i -e 's#__PLAN_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__APPLY_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml - echo "TF_VAR_seed=${{ env.GITHUB_RUN_ID }}-${{ env.GITHUB_RUN_ATTEMPT }}" >> $GITHUB_ENV + echo "seed=${{ env.GITHUB_RUN_ID }}-${{ env.GITHUB_RUN_ATTEMPT }}" >> $GITHUB_OUTPUT - name: Plan Atmos Component uses: cloudposse/github-action-atmos-terraform-plan@v4 @@ -54,7 +55,7 @@ jobs: atmos-config-path: ${{ runner.temp }} debug: true env: - TF_VAR_seed: ${{ env.TF_VAR_seed }} + TF_VAR_seed: ${{ steps.env.outputs.seed }} - uses: actions/checkout@v4 From 425c6666f77c7d508d82d23ac64b42e3a3b9b276 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 22:46:31 +0200 Subject: [PATCH 055/123] Added A/B testings --- .github/workflows/integration-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 49e7082f..8de6ad6b 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -45,7 +45,7 @@ jobs: sed -i -e 's#__PLAN_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__APPLY_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml - echo "seed=${{ env.GITHUB_RUN_ID }}-${{ env.GITHUB_RUN_ATTEMPT }}" >> $GITHUB_OUTPUT + echo "seed=${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" >> $GITHUB_OUTPUT - name: Plan Atmos Component uses: cloudposse/github-action-atmos-terraform-plan@v4 From b08c319a86ffc8a49cc1ad820d3f0cb27a443458 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 22:53:46 +0200 Subject: [PATCH 056/123] Added A/B testings --- .github/workflows/integration-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 8de6ad6b..e8a22210 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -45,7 +45,7 @@ jobs: sed -i -e 's#__PLAN_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__APPLY_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml - echo "seed=${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}" >> $GITHUB_OUTPUT + echo "seed=${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${{ matrix.platform }}" >> $GITHUB_OUTPUT - name: Plan Atmos Component uses: cloudposse/github-action-atmos-terraform-plan@v4 From aaee2d6b471303fc9a48c75a69be3146e06462a3 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 23:05:05 +0200 Subject: [PATCH 057/123] Added A/B testings --- .github/workflows/integration-tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index e8a22210..7cd5d5ad 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -74,3 +74,6 @@ jobs: stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} debug: true + env: + TF_VAR_seed: ${{ steps.env.outputs.seed }} + \ No newline at end of file From 4b6b9ab146ad694f0e9b7a4bbc075951e451cf11 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 23:31:07 +0200 Subject: [PATCH 058/123] Added A/B testings --- .github/workflows/integration-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 7cd5d5ad..e28f841b 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -62,10 +62,10 @@ jobs: with: ref: ${{ github.event.pull_request.head.ref }} - - name: Wait 15 sec to wait s3 bucket would be consistent (read after write consistency) + - name: Wait 60 sec to wait s3 bucket would be consistent (read after write consistency) shell: bash run: | - sleep 15; + sleep 60; - name: Apply Atmos Component uses: ./ From 922b52d3d2345eb1200e6e94bb99cbac6bf44022 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 23:39:11 +0200 Subject: [PATCH 059/123] Added A/B testings --- .github/workflows/integration-tests-plan-diff.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index f4f341ea..2e476b5f 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -3,8 +3,8 @@ name: "Integration Tests - Plan failed" on: workflow_dispatch: {} - pull_request: - types: [opened, synchronize, reopened] + # pull_request: + # types: [opened, synchronize, reopened] env: AWS_REGION: us-east-2 From 5d7f7294ea7e028ae2e07d58c7a502075be5c482 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 23:46:06 +0200 Subject: [PATCH 060/123] Added A/B testings --- .github/workflows/integration-test-atmos-pro.yml | 3 +++ .github/workflows/integration-tests-plan-diff.yml | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-test-atmos-pro.yml b/.github/workflows/integration-test-atmos-pro.yml index d7ebdac4..ed1a150a 100644 --- a/.github/workflows/integration-test-atmos-pro.yml +++ b/.github/workflows/integration-test-atmos-pro.yml @@ -14,6 +14,9 @@ permissions: id-token: write contents: read +concurrency: + group: ${{ github.ref }} + jobs: setup: runs-on: ubuntu-latest diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index 2e476b5f..60b33fbe 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -3,8 +3,8 @@ name: "Integration Tests - Plan failed" on: workflow_dispatch: {} - # pull_request: - # types: [opened, synchronize, reopened] + pull_request: + types: [opened, synchronize, reopened] env: AWS_REGION: us-east-2 @@ -15,6 +15,9 @@ permissions: id-token: write contents: read +concurrency: + group: ${{ github.ref }} + jobs: test: runs-on: ubuntu-latest From ec6fc130905cd1a803b559500eb4e5eebbc64089 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Wed, 6 Aug 2025 23:52:08 +0200 Subject: [PATCH 061/123] Added A/B testings --- .github/workflows/integration-test-atmos-pro.yml | 3 --- .github/workflows/integration-tests-plan-diff.yml | 3 --- .github/workflows/integration-tests.yml | 3 --- 3 files changed, 9 deletions(-) diff --git a/.github/workflows/integration-test-atmos-pro.yml b/.github/workflows/integration-test-atmos-pro.yml index ed1a150a..d7ebdac4 100644 --- a/.github/workflows/integration-test-atmos-pro.yml +++ b/.github/workflows/integration-test-atmos-pro.yml @@ -14,9 +14,6 @@ permissions: id-token: write contents: read -concurrency: - group: ${{ github.ref }} - jobs: setup: runs-on: ubuntu-latest diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index 60b33fbe..f4f341ea 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -15,9 +15,6 @@ permissions: id-token: write contents: read -concurrency: - group: ${{ github.ref }} - jobs: test: runs-on: ubuntu-latest diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index e28f841b..bfdfcdbc 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -15,9 +15,6 @@ permissions: id-token: write contents: read -concurrency: - group: ${{ github.ref }} - jobs: test: runs-on: ubuntu-latest From 6af3d15960cec5e84a52706364674a5e5773b875 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 00:10:56 +0200 Subject: [PATCH 062/123] Added A/B testings --- .github/workflows/integration-tests-plan-diff.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index f4f341ea..2e476b5f 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -3,8 +3,8 @@ name: "Integration Tests - Plan failed" on: workflow_dispatch: {} - pull_request: - types: [opened, synchronize, reopened] + # pull_request: + # types: [opened, synchronize, reopened] env: AWS_REGION: us-east-2 From 270e53410d2044e0685dfaaf0a7789e0b62486cb Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 00:24:33 +0200 Subject: [PATCH 063/123] Added A/B testings --- .../workflows/integration-test-atmos-pro.yml | 8 +- .../workflows/integration-tests-plan-diff.yml | 15 +- tests/a/opentofu/atmos.yaml | 92 ------ .../components/terraform/foobar/context.tf | 279 ------------------ .../components/terraform/foobar/main.tf | 8 - .../components/terraform/foobar/outputs.tf | 21 -- .../components/terraform/foobar/variables.tf | 5 - .../stacks/catalog/foobar-atmos-pro.yaml | 13 - tests/a/opentofu/stacks/catalog/foobar.yaml | 8 - .../foo/plat/sandbox/plat-ue2-sandbox.yaml | 30 -- tests/a/terraform/atmos.yaml | 93 ------ .../components/terraform/foobar/context.tf | 279 ------------------ .../components/terraform/foobar/main.tf | 8 - .../components/terraform/foobar/outputs.tf | 21 -- .../components/terraform/foobar/variables.tf | 5 - .../stacks/catalog/foobar-atmos-pro.yaml | 13 - tests/a/terraform/stacks/catalog/foobar.yaml | 8 - .../foo/plat/sandbox/plat-ue2-sandbox.yaml | 30 -- tests/b/opentofu/atmos.yaml | 92 ------ .../components/terraform/foobar/context.tf | 279 ------------------ .../components/terraform/foobar/main.tf | 8 - .../components/terraform/foobar/outputs.tf | 21 -- .../components/terraform/foobar/variables.tf | 5 - .../stacks/catalog/foobar-atmos-pro.yaml | 13 - .../foo/plat/sandbox/plat-ue2-sandbox.yaml | 30 -- tests/b/terraform/atmos.yaml | 93 ------ .../components/terraform/foobar/context.tf | 279 ------------------ .../components/terraform/foobar/main.tf | 8 - .../components/terraform/foobar/outputs.tf | 21 -- .../components/terraform/foobar/variables.tf | 5 - .../stacks/catalog/foobar-atmos-pro.yaml | 13 - tests/b/terraform/stacks/catalog/foobar.yaml | 8 - .../foo/plat/sandbox/plat-ue2-sandbox.yaml | 30 -- .../stacks/catalog/foobar-plan-diff.yaml} | 2 +- .../foo/plat/sandbox/plat-ue2-sandbox.yaml | 1 + 35 files changed, 20 insertions(+), 1824 deletions(-) delete mode 100644 tests/a/opentofu/atmos.yaml delete mode 100644 tests/a/opentofu/components/terraform/foobar/context.tf delete mode 100644 tests/a/opentofu/components/terraform/foobar/main.tf delete mode 100644 tests/a/opentofu/components/terraform/foobar/outputs.tf delete mode 100644 tests/a/opentofu/components/terraform/foobar/variables.tf delete mode 100644 tests/a/opentofu/stacks/catalog/foobar-atmos-pro.yaml delete mode 100644 tests/a/opentofu/stacks/catalog/foobar.yaml delete mode 100644 tests/a/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml delete mode 100644 tests/a/terraform/atmos.yaml delete mode 100644 tests/a/terraform/components/terraform/foobar/context.tf delete mode 100644 tests/a/terraform/components/terraform/foobar/main.tf delete mode 100644 tests/a/terraform/components/terraform/foobar/outputs.tf delete mode 100644 tests/a/terraform/components/terraform/foobar/variables.tf delete mode 100644 tests/a/terraform/stacks/catalog/foobar-atmos-pro.yaml delete mode 100644 tests/a/terraform/stacks/catalog/foobar.yaml delete mode 100644 tests/a/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml delete mode 100644 tests/b/opentofu/atmos.yaml delete mode 100644 tests/b/opentofu/components/terraform/foobar/context.tf delete mode 100644 tests/b/opentofu/components/terraform/foobar/main.tf delete mode 100644 tests/b/opentofu/components/terraform/foobar/outputs.tf delete mode 100644 tests/b/opentofu/components/terraform/foobar/variables.tf delete mode 100644 tests/b/opentofu/stacks/catalog/foobar-atmos-pro.yaml delete mode 100644 tests/b/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml delete mode 100644 tests/b/terraform/atmos.yaml delete mode 100644 tests/b/terraform/components/terraform/foobar/context.tf delete mode 100644 tests/b/terraform/components/terraform/foobar/main.tf delete mode 100644 tests/b/terraform/components/terraform/foobar/outputs.tf delete mode 100644 tests/b/terraform/components/terraform/foobar/variables.tf delete mode 100644 tests/b/terraform/stacks/catalog/foobar-atmos-pro.yaml delete mode 100644 tests/b/terraform/stacks/catalog/foobar.yaml delete mode 100644 tests/b/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml rename tests/{b/opentofu/stacks/catalog/foobar.yaml => opentofu/stacks/catalog/foobar-plan-diff.yaml} (84%) diff --git a/.github/workflows/integration-test-atmos-pro.yml b/.github/workflows/integration-test-atmos-pro.yml index d7ebdac4..35f7b0e2 100644 --- a/.github/workflows/integration-test-atmos-pro.yml +++ b/.github/workflows/integration-test-atmos-pro.yml @@ -44,6 +44,8 @@ jobs: sed -i -e 's#__PLAN_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__APPLY_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + echo "seed=${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${{ matrix.platform }}" >> $GITHUB_OUTPUT + cat ${{ runner.temp }}/atmos.yaml - name: Plan Atmos Component @@ -52,6 +54,8 @@ jobs: component: "foobar-atmos-pro" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} + env: + TF_VAR_seed: ${{ steps.env.outputs.seed }} - uses: actions/checkout@v4 with: @@ -70,7 +74,9 @@ jobs: stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} atmos-version: ">= 1.174.0" - + env: + TF_VAR_seed: ${{ steps.env.outputs.seed }} + outputs: result: ${{ steps.current.outputs.status }} diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index 2e476b5f..a7f47ea0 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -3,8 +3,8 @@ name: "Integration Tests - Plan failed" on: workflow_dispatch: {} - # pull_request: - # types: [opened, synchronize, reopened] + pull_request: + types: [opened, synchronize, reopened] env: AWS_REGION: us-east-2 @@ -41,14 +41,18 @@ jobs: sed -i -e 's#__PLAN_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__APPLY_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + echo "seed=${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${{ matrix.platform }}" >> $GITHUB_OUTPUT + - name: Plan Atmos Component uses: cloudposse/github-action-atmos-terraform-plan@v4 with: - component: "foobar" + component: "foobar-plan-diff" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} debug: true - + env: + TF_VAR_seed: ${{ steps.env.outputs.seed }} + - shell: bash run: | mkdir -p ${{ runner.temp }} @@ -78,3 +82,6 @@ jobs: stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} debug: true + env: + TF_VAR_seed: ${{ steps.env.outputs.seed }} + \ No newline at end of file diff --git a/tests/a/opentofu/atmos.yaml b/tests/a/opentofu/atmos.yaml deleted file mode 100644 index c12261be..00000000 --- a/tests/a/opentofu/atmos.yaml +++ /dev/null @@ -1,92 +0,0 @@ -# CLI config is loaded from the following locations (from lowest to highest priority): -# system dir (`/usr/local/etc/atmos` on Linux, `%LOCALAPPDATA%/atmos` on Windows) -# home dir (~/.atmos) -# current directory -# ENV vars -# Command-line arguments -# -# It supports POSIX-style Globs for file names/paths (double-star `**` is supported) -# https://en.wikipedia.org/wiki/Glob_(programming) - -# Base path for components, stacks and workflows configurations. -# Can also be set using `ATMOS_BASE_PATH` ENV var, or `--base-path` command-line argument. -# Supports both absolute and relative paths. -# If not provided or is an empty string, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` -# are independent settings (supporting both absolute and relative paths). -# If `base_path` is provided, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` -# are considered paths relative to `base_path`. -base_path: "./tests/a/opentofu" - -aliases: - tofu: terraform - -components: - terraform: - command: "tofu" - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_BASE_PATH` ENV var, or `--terraform-dir` command-line argument - # Supports both absolute and relative paths - base_path: "components/terraform" - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE` ENV var - apply_auto_approve: false - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT` ENV var, or `--deploy-run-init` command-line argument - deploy_run_init: true - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_INIT_RUN_RECONFIGURE` ENV var, or `--init-run-reconfigure` command-line argument - init_run_reconfigure: true - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE` ENV var, or `--auto-generate-backend-file` command-line argument - auto_generate_backend_file: true - helmfile: - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_BASE_PATH` ENV var, or `--helmfile-dir` command-line argument - # Supports both absolute and relative paths - base_path: "components/helmfile" - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_KUBECONFIG_PATH` ENV var - kubeconfig_path: "/conf/.kube/" - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_HELM_AWS_PROFILE_PATTERN` ENV var - helm_aws_profile_pattern: "{namespace}-{tenant}-gbl-{stage}-helm" - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_CLUSTER_NAME_PATTERN` ENV var - cluster_name_pattern: "{namespace}-{tenant}-{environment}-{stage}-eks-cluster" - -stacks: - # Can also be set using `ATMOS_STACKS_BASE_PATH` ENV var, or `--config-dir` and `--stacks-dir` command-line arguments - # Supports both absolute and relative paths - base_path: "stacks" - # Can also be set using `ATMOS_STACKS_INCLUDED_PATHS` ENV var (comma-separated values string) - # Since we are distinguishing stacks based on namespace, and namespace is not part - # of the stack name, we have to set `included_paths` via the ENV var in the Dockerfile - included_paths: - - "orgs/**/*" - # Can also be set using `ATMOS_STACKS_EXCLUDED_PATHS` ENV var (comma-separated values string) - excluded_paths: - - "**/_defaults.yaml" - # exclude workflows directory if otherwise included in `included_paths` above - # - "workflows/**/*" - - # Can also be set using `ATMOS_STACKS_NAME_PATTERN` ENV var - name_pattern: "{tenant}-{environment}-{stage}" - -integrations: - github: - gitops: - opentofu-version: 1.7.3 - infracost-enabled: __INFRACOST_ENABLED__ - artifact-storage: - region: __STORAGE_REGION__ - bucket: __STORAGE_BUCKET__ - table: __STORAGE_TABLE__ - role: __STORAGE_ROLE__ - plan-repository-type: s3 - metadata-repository-type: dynamo - role: - plan: __PLAN_ROLE__ - apply: __APPLY_ROLE__ - matrix: - sort-by: .stack_slug - group-by: .stack_slug | split("-") | [.[0], .[2]] | join("-") - -workflows: - # Can also be set using `ATMOS_WORKFLOWS_BASE_PATH` ENV var, or `--workflows-dir` command-line arguments - # Supports both absolute and relative paths - base_path: "stacks/workflows" - -logs: - verbose: false - colors: true diff --git a/tests/a/opentofu/components/terraform/foobar/context.tf b/tests/a/opentofu/components/terraform/foobar/context.tf deleted file mode 100644 index 5e0ef885..00000000 --- a/tests/a/opentofu/components/terraform/foobar/context.tf +++ /dev/null @@ -1,279 +0,0 @@ -# -# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label -# All other instances of this file should be a copy of that one -# -# -# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf -# and then place it in your Terraform module to automatically get -# Cloud Posse's standard configuration inputs suitable for passing -# to Cloud Posse modules. -# -# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf -# -# Modules should access the whole context as `module.this.context` -# to get the input variables with nulls for defaults, -# for example `context = module.this.context`, -# and access individual variables as `module.this.`, -# with final values filled in. -# -# For example, when using defaults, `module.this.context.delimiter` -# will be null, and `module.this.delimiter` will be `-` (hyphen). -# - -module "this" { - source = "cloudposse/label/null" - version = "0.25.0" # requires Terraform >= 0.13.0 - - enabled = var.enabled - namespace = var.namespace - tenant = var.tenant - environment = var.environment - stage = var.stage - name = var.name - delimiter = var.delimiter - attributes = var.attributes - tags = var.tags - additional_tag_map = var.additional_tag_map - label_order = var.label_order - regex_replace_chars = var.regex_replace_chars - id_length_limit = var.id_length_limit - label_key_case = var.label_key_case - label_value_case = var.label_value_case - descriptor_formats = var.descriptor_formats - labels_as_tags = var.labels_as_tags - - context = var.context -} - -# Copy contents of cloudposse/terraform-null-label/variables.tf here - -variable "context" { - type = any - default = { - enabled = true - namespace = null - tenant = null - environment = null - stage = null - name = null - delimiter = null - attributes = [] - tags = {} - additional_tag_map = {} - regex_replace_chars = null - label_order = [] - id_length_limit = null - label_key_case = null - label_value_case = null - descriptor_formats = {} - # Note: we have to use [] instead of null for unset lists due to - # https://github.com/hashicorp/terraform/issues/28137 - # which was not fixed until Terraform 1.0.0, - # but we want the default to be all the labels in `label_order` - # and we want users to be able to prevent all tag generation - # by setting `labels_as_tags` to `[]`, so we need - # a different sentinel to indicate "default" - labels_as_tags = ["unset"] - } - description = <<-EOT - Single object for setting entire context at once. - See description of individual variables for details. - Leave string and numeric variables as `null` to use default value. - Individual variable settings (non-null) override settings in context object, - except for attributes, tags, and additional_tag_map, which are merged. - EOT - - validation { - condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) - error_message = "Allowed values: `lower`, `title`, `upper`." - } - - validation { - condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) - error_message = "Allowed values: `lower`, `title`, `upper`, `none`." - } -} - -variable "enabled" { - type = bool - default = null - description = "Set to false to prevent the module from creating any resources" -} - -variable "namespace" { - type = string - default = null - description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" -} - -variable "tenant" { - type = string - default = null - description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" -} - -variable "environment" { - type = string - default = null - description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" -} - -variable "stage" { - type = string - default = null - description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" -} - -variable "name" { - type = string - default = null - description = <<-EOT - ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. - This is the only ID element not also included as a `tag`. - The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. - EOT -} - -variable "delimiter" { - type = string - default = null - description = <<-EOT - Delimiter to be used between ID elements. - Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. - EOT -} - -variable "attributes" { - type = list(string) - default = [] - description = <<-EOT - ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, - in the order they appear in the list. New attributes are appended to the - end of the list. The elements of the list are joined by the `delimiter` - and treated as a single ID element. - EOT -} - -variable "labels_as_tags" { - type = set(string) - default = ["default"] - description = <<-EOT - Set of labels (ID elements) to include as tags in the `tags` output. - Default is to include all labels. - Tags with empty values will not be included in the `tags` output. - Set to `[]` to suppress all generated tags. - **Notes:** - The value of the `name` tag, if included, will be the `id`, not the `name`. - Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be - changed in later chained modules. Attempts to change it will be silently ignored. - EOT -} - -variable "tags" { - type = map(string) - default = {} - description = <<-EOT - Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). - Neither the tag keys nor the tag values will be modified by this module. - EOT -} - -variable "additional_tag_map" { - type = map(string) - default = {} - description = <<-EOT - Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. - This is for some rare cases where resources want additional configuration of tags - and therefore take a list of maps with tag key, value, and additional configuration. - EOT -} - -variable "label_order" { - type = list(string) - default = null - description = <<-EOT - The order in which the labels (ID elements) appear in the `id`. - Defaults to ["namespace", "environment", "stage", "name", "attributes"]. - You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. - EOT -} - -variable "regex_replace_chars" { - type = string - default = null - description = <<-EOT - Terraform regular expression (regex) string. - Characters matching the regex will be removed from the ID elements. - If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. - EOT -} - -variable "id_length_limit" { - type = number - default = null - description = <<-EOT - Limit `id` to this many characters (minimum 6). - Set to `0` for unlimited length. - Set to `null` for keep the existing setting, which defaults to `0`. - Does not affect `id_full`. - EOT - validation { - condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 - error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." - } -} - -variable "label_key_case" { - type = string - default = null - description = <<-EOT - Controls the letter case of the `tags` keys (label names) for tags generated by this module. - Does not affect keys of tags passed in via the `tags` input. - Possible values: `lower`, `title`, `upper`. - Default value: `title`. - EOT - - validation { - condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) - error_message = "Allowed values: `lower`, `title`, `upper`." - } -} - -variable "label_value_case" { - type = string - default = null - description = <<-EOT - Controls the letter case of ID elements (labels) as included in `id`, - set as tag values, and output by this module individually. - Does not affect values of tags passed in via the `tags` input. - Possible values: `lower`, `title`, `upper` and `none` (no transformation). - Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. - Default value: `lower`. - EOT - - validation { - condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) - error_message = "Allowed values: `lower`, `title`, `upper`, `none`." - } -} - -variable "descriptor_formats" { - type = any - default = {} - description = <<-EOT - Describe additional descriptors to be output in the `descriptors` output map. - Map of maps. Keys are names of descriptors. Values are maps of the form - `{ - format = string - labels = list(string) - }` - (Type is `any` so the map values can later be enhanced to provide additional options.) - `format` is a Terraform format string to be passed to the `format()` function. - `labels` is a list of labels, in order, to pass to `format()` function. - Label values will be normalized before being passed to `format()` so they will be - identical to how they appear in `id`. - Default is `{}` (`descriptors` output will be empty). - EOT -} - -#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/tests/a/opentofu/components/terraform/foobar/main.tf b/tests/a/opentofu/components/terraform/foobar/main.tf deleted file mode 100644 index 5fc39577..00000000 --- a/tests/a/opentofu/components/terraform/foobar/main.tf +++ /dev/null @@ -1,8 +0,0 @@ -resource "random_id" "foo" { - keepers = { - # Generate a new id each time we switch to a new seed - seed = "${module.this.id}-${var.example}" - timestamp = "${timestamp()}" - } - byte_length = 8 -} diff --git a/tests/a/opentofu/components/terraform/foobar/outputs.tf b/tests/a/opentofu/components/terraform/foobar/outputs.tf deleted file mode 100644 index 055f02d5..00000000 --- a/tests/a/opentofu/components/terraform/foobar/outputs.tf +++ /dev/null @@ -1,21 +0,0 @@ -output "result" { - description = "Test description output" - value = random_id.foo.id -} - -output "sensitive_value" { - description = "Test sensitive description output" - value = random_id.foo.id - sensitive = true -} - - -output "structured_value" { - description = "Test structured output" - value = { - test = "test" - value = { - result = random_id.foo.id - } - } -} \ No newline at end of file diff --git a/tests/a/opentofu/components/terraform/foobar/variables.tf b/tests/a/opentofu/components/terraform/foobar/variables.tf deleted file mode 100644 index d9b2dde4..00000000 --- a/tests/a/opentofu/components/terraform/foobar/variables.tf +++ /dev/null @@ -1,5 +0,0 @@ -variable "example" { - type = string - description = "testing variable" -} - diff --git a/tests/a/opentofu/stacks/catalog/foobar-atmos-pro.yaml b/tests/a/opentofu/stacks/catalog/foobar-atmos-pro.yaml deleted file mode 100644 index 87529334..00000000 --- a/tests/a/opentofu/stacks/catalog/foobar-atmos-pro.yaml +++ /dev/null @@ -1,13 +0,0 @@ -components: - terraform: - foobar-atmos-pro: - metadata: - component: foobar - settings: - pro: - enabled: true - github: - actions_enabled: false - vars: - example: blue - enabled: true \ No newline at end of file diff --git a/tests/a/opentofu/stacks/catalog/foobar.yaml b/tests/a/opentofu/stacks/catalog/foobar.yaml deleted file mode 100644 index 991c4742..00000000 --- a/tests/a/opentofu/stacks/catalog/foobar.yaml +++ /dev/null @@ -1,8 +0,0 @@ -components: - terraform: - foobar: - settings: - github: - actions_enabled: true - vars: - example: blue diff --git a/tests/a/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/a/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml deleted file mode 100644 index 65394b42..00000000 --- a/tests/a/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml +++ /dev/null @@ -1,30 +0,0 @@ -import: - - catalog/foobar - - catalog/foobar-atmos-pro - -terraform: - backend_type: s3 - backend: - s3: - bucket: cptest-core-ue2-root-tfstate-plat - dynamodb_table: cptest-core-ue2-root-tfstate-plat-lock - role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-plat - encrypt: true - key: opentofu/terraform.tfstate - acl: bucket-owner-full-control - region: us-east-2 - - vars: - environment: ue2 - namespace: foo - region: us-east-2 - stage: sandbox - tenant: plat - label_order: - - namespace - - tenant - - environment - - stage - - name - - attributes - diff --git a/tests/a/terraform/atmos.yaml b/tests/a/terraform/atmos.yaml deleted file mode 100644 index a7d8139b..00000000 --- a/tests/a/terraform/atmos.yaml +++ /dev/null @@ -1,93 +0,0 @@ -# CLI config is loaded from the following locations (from lowest to highest priority): -# system dir (`/usr/local/etc/atmos` on Linux, `%LOCALAPPDATA%/atmos` on Windows) -# home dir (~/.atmos) -# current directory -# ENV vars -# Command-line arguments -# -# It supports POSIX-style Globs for file names/paths (double-star `**` is supported) -# https://en.wikipedia.org/wiki/Glob_(programming) - -# Base path for components, stacks and workflows configurations. -# Can also be set using `ATMOS_BASE_PATH` ENV var, or `--base-path` command-line argument. -# Supports both absolute and relative paths. -# If not provided or is an empty string, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` -# are independent settings (supporting both absolute and relative paths). -# If `base_path` is provided, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` -# are considered paths relative to `base_path`. -base_path: "./tests/a/terraform" - -components: - terraform: - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_BASE_PATH` ENV var, or `--terraform-dir` command-line argument - # Supports both absolute and relative paths - base_path: "components/terraform" - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE` ENV var - apply_auto_approve: false - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT` ENV var, or `--deploy-run-init` command-line argument - deploy_run_init: true - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_INIT_RUN_RECONFIGURE` ENV var, or `--init-run-reconfigure` command-line argument - init_run_reconfigure: true - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE` ENV var, or `--auto-generate-backend-file` command-line argument - auto_generate_backend_file: true - helmfile: - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_BASE_PATH` ENV var, or `--helmfile-dir` command-line argument - # Supports both absolute and relative paths - base_path: "components/helmfile" - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_KUBECONFIG_PATH` ENV var - kubeconfig_path: "/conf/.kube/" - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_HELM_AWS_PROFILE_PATTERN` ENV var - helm_aws_profile_pattern: "{namespace}-{tenant}-gbl-{stage}-helm" - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_CLUSTER_NAME_PATTERN` ENV var - cluster_name_pattern: "{namespace}-{tenant}-{environment}-{stage}-eks-cluster" - -stacks: - # Can also be set using `ATMOS_STACKS_BASE_PATH` ENV var, or `--config-dir` and `--stacks-dir` command-line arguments - # Supports both absolute and relative paths - base_path: "stacks" - # Can also be set using `ATMOS_STACKS_INCLUDED_PATHS` ENV var (comma-separated values string) - # Since we are distinguishing stacks based on namespace, and namespace is not part - # of the stack name, we have to set `included_paths` via the ENV var in the Dockerfile - included_paths: - - "orgs/**/*" - # Can also be set using `ATMOS_STACKS_EXCLUDED_PATHS` ENV var (comma-separated values string) - excluded_paths: - - "**/_defaults.yaml" - # exclude workflows directory if otherwise included in `included_paths` above - # - "workflows/**/*" - - # Can also be set using `ATMOS_STACKS_NAME_PATTERN` ENV var - name_pattern: "{tenant}-{environment}-{stage}" - -integrations: - github: - gitops: - terraform-version: 1.5.7 - infracost-enabled: __INFRACOST_ENABLED__ - artifact-storage: - region: __STORAGE_REGION__ - bucket: __STORAGE_BUCKET__ - table: __STORAGE_TABLE__ - role: __STORAGE_ROLE__ - plan-repository-type: s3 - metadata-repository-type: dynamo - blob-account-name: - blob-container-name: - cosmos-container-name: - cosmos-database-name: - cosmos-endpoint: - role: - plan: __PLAN_ROLE__ - apply: __APPLY_ROLE__ - matrix: - sort-by: .stack_slug - group-by: .stack_slug | split("-") | [.[0], .[2]] | join("-") - -workflows: - # Can also be set using `ATMOS_WORKFLOWS_BASE_PATH` ENV var, or `--workflows-dir` command-line arguments - # Supports both absolute and relative paths - base_path: "stacks/workflows" - -logs: - verbose: false - colors: true diff --git a/tests/a/terraform/components/terraform/foobar/context.tf b/tests/a/terraform/components/terraform/foobar/context.tf deleted file mode 100644 index 5e0ef885..00000000 --- a/tests/a/terraform/components/terraform/foobar/context.tf +++ /dev/null @@ -1,279 +0,0 @@ -# -# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label -# All other instances of this file should be a copy of that one -# -# -# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf -# and then place it in your Terraform module to automatically get -# Cloud Posse's standard configuration inputs suitable for passing -# to Cloud Posse modules. -# -# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf -# -# Modules should access the whole context as `module.this.context` -# to get the input variables with nulls for defaults, -# for example `context = module.this.context`, -# and access individual variables as `module.this.`, -# with final values filled in. -# -# For example, when using defaults, `module.this.context.delimiter` -# will be null, and `module.this.delimiter` will be `-` (hyphen). -# - -module "this" { - source = "cloudposse/label/null" - version = "0.25.0" # requires Terraform >= 0.13.0 - - enabled = var.enabled - namespace = var.namespace - tenant = var.tenant - environment = var.environment - stage = var.stage - name = var.name - delimiter = var.delimiter - attributes = var.attributes - tags = var.tags - additional_tag_map = var.additional_tag_map - label_order = var.label_order - regex_replace_chars = var.regex_replace_chars - id_length_limit = var.id_length_limit - label_key_case = var.label_key_case - label_value_case = var.label_value_case - descriptor_formats = var.descriptor_formats - labels_as_tags = var.labels_as_tags - - context = var.context -} - -# Copy contents of cloudposse/terraform-null-label/variables.tf here - -variable "context" { - type = any - default = { - enabled = true - namespace = null - tenant = null - environment = null - stage = null - name = null - delimiter = null - attributes = [] - tags = {} - additional_tag_map = {} - regex_replace_chars = null - label_order = [] - id_length_limit = null - label_key_case = null - label_value_case = null - descriptor_formats = {} - # Note: we have to use [] instead of null for unset lists due to - # https://github.com/hashicorp/terraform/issues/28137 - # which was not fixed until Terraform 1.0.0, - # but we want the default to be all the labels in `label_order` - # and we want users to be able to prevent all tag generation - # by setting `labels_as_tags` to `[]`, so we need - # a different sentinel to indicate "default" - labels_as_tags = ["unset"] - } - description = <<-EOT - Single object for setting entire context at once. - See description of individual variables for details. - Leave string and numeric variables as `null` to use default value. - Individual variable settings (non-null) override settings in context object, - except for attributes, tags, and additional_tag_map, which are merged. - EOT - - validation { - condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) - error_message = "Allowed values: `lower`, `title`, `upper`." - } - - validation { - condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) - error_message = "Allowed values: `lower`, `title`, `upper`, `none`." - } -} - -variable "enabled" { - type = bool - default = null - description = "Set to false to prevent the module from creating any resources" -} - -variable "namespace" { - type = string - default = null - description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" -} - -variable "tenant" { - type = string - default = null - description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" -} - -variable "environment" { - type = string - default = null - description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" -} - -variable "stage" { - type = string - default = null - description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" -} - -variable "name" { - type = string - default = null - description = <<-EOT - ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. - This is the only ID element not also included as a `tag`. - The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. - EOT -} - -variable "delimiter" { - type = string - default = null - description = <<-EOT - Delimiter to be used between ID elements. - Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. - EOT -} - -variable "attributes" { - type = list(string) - default = [] - description = <<-EOT - ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, - in the order they appear in the list. New attributes are appended to the - end of the list. The elements of the list are joined by the `delimiter` - and treated as a single ID element. - EOT -} - -variable "labels_as_tags" { - type = set(string) - default = ["default"] - description = <<-EOT - Set of labels (ID elements) to include as tags in the `tags` output. - Default is to include all labels. - Tags with empty values will not be included in the `tags` output. - Set to `[]` to suppress all generated tags. - **Notes:** - The value of the `name` tag, if included, will be the `id`, not the `name`. - Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be - changed in later chained modules. Attempts to change it will be silently ignored. - EOT -} - -variable "tags" { - type = map(string) - default = {} - description = <<-EOT - Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). - Neither the tag keys nor the tag values will be modified by this module. - EOT -} - -variable "additional_tag_map" { - type = map(string) - default = {} - description = <<-EOT - Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. - This is for some rare cases where resources want additional configuration of tags - and therefore take a list of maps with tag key, value, and additional configuration. - EOT -} - -variable "label_order" { - type = list(string) - default = null - description = <<-EOT - The order in which the labels (ID elements) appear in the `id`. - Defaults to ["namespace", "environment", "stage", "name", "attributes"]. - You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. - EOT -} - -variable "regex_replace_chars" { - type = string - default = null - description = <<-EOT - Terraform regular expression (regex) string. - Characters matching the regex will be removed from the ID elements. - If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. - EOT -} - -variable "id_length_limit" { - type = number - default = null - description = <<-EOT - Limit `id` to this many characters (minimum 6). - Set to `0` for unlimited length. - Set to `null` for keep the existing setting, which defaults to `0`. - Does not affect `id_full`. - EOT - validation { - condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 - error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." - } -} - -variable "label_key_case" { - type = string - default = null - description = <<-EOT - Controls the letter case of the `tags` keys (label names) for tags generated by this module. - Does not affect keys of tags passed in via the `tags` input. - Possible values: `lower`, `title`, `upper`. - Default value: `title`. - EOT - - validation { - condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) - error_message = "Allowed values: `lower`, `title`, `upper`." - } -} - -variable "label_value_case" { - type = string - default = null - description = <<-EOT - Controls the letter case of ID elements (labels) as included in `id`, - set as tag values, and output by this module individually. - Does not affect values of tags passed in via the `tags` input. - Possible values: `lower`, `title`, `upper` and `none` (no transformation). - Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. - Default value: `lower`. - EOT - - validation { - condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) - error_message = "Allowed values: `lower`, `title`, `upper`, `none`." - } -} - -variable "descriptor_formats" { - type = any - default = {} - description = <<-EOT - Describe additional descriptors to be output in the `descriptors` output map. - Map of maps. Keys are names of descriptors. Values are maps of the form - `{ - format = string - labels = list(string) - }` - (Type is `any` so the map values can later be enhanced to provide additional options.) - `format` is a Terraform format string to be passed to the `format()` function. - `labels` is a list of labels, in order, to pass to `format()` function. - Label values will be normalized before being passed to `format()` so they will be - identical to how they appear in `id`. - Default is `{}` (`descriptors` output will be empty). - EOT -} - -#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/tests/a/terraform/components/terraform/foobar/main.tf b/tests/a/terraform/components/terraform/foobar/main.tf deleted file mode 100644 index 5fc39577..00000000 --- a/tests/a/terraform/components/terraform/foobar/main.tf +++ /dev/null @@ -1,8 +0,0 @@ -resource "random_id" "foo" { - keepers = { - # Generate a new id each time we switch to a new seed - seed = "${module.this.id}-${var.example}" - timestamp = "${timestamp()}" - } - byte_length = 8 -} diff --git a/tests/a/terraform/components/terraform/foobar/outputs.tf b/tests/a/terraform/components/terraform/foobar/outputs.tf deleted file mode 100644 index 7177f0bd..00000000 --- a/tests/a/terraform/components/terraform/foobar/outputs.tf +++ /dev/null @@ -1,21 +0,0 @@ -output "result" { - description = "Test description output" - value = random_id.foo.id -} - -output "sensitive_value" { - description = "Test sensitive description output" - value = random_id.foo.id - sensitive = true -} - - -output "structured_value" { - description = "Test structured output" - value = { - test = "test" - value = { - result = random_id.foo.id - } - } -} diff --git a/tests/a/terraform/components/terraform/foobar/variables.tf b/tests/a/terraform/components/terraform/foobar/variables.tf deleted file mode 100644 index d9b2dde4..00000000 --- a/tests/a/terraform/components/terraform/foobar/variables.tf +++ /dev/null @@ -1,5 +0,0 @@ -variable "example" { - type = string - description = "testing variable" -} - diff --git a/tests/a/terraform/stacks/catalog/foobar-atmos-pro.yaml b/tests/a/terraform/stacks/catalog/foobar-atmos-pro.yaml deleted file mode 100644 index 87529334..00000000 --- a/tests/a/terraform/stacks/catalog/foobar-atmos-pro.yaml +++ /dev/null @@ -1,13 +0,0 @@ -components: - terraform: - foobar-atmos-pro: - metadata: - component: foobar - settings: - pro: - enabled: true - github: - actions_enabled: false - vars: - example: blue - enabled: true \ No newline at end of file diff --git a/tests/a/terraform/stacks/catalog/foobar.yaml b/tests/a/terraform/stacks/catalog/foobar.yaml deleted file mode 100644 index 991c4742..00000000 --- a/tests/a/terraform/stacks/catalog/foobar.yaml +++ /dev/null @@ -1,8 +0,0 @@ -components: - terraform: - foobar: - settings: - github: - actions_enabled: true - vars: - example: blue diff --git a/tests/a/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/a/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml deleted file mode 100644 index 3d552592..00000000 --- a/tests/a/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml +++ /dev/null @@ -1,30 +0,0 @@ -import: - - catalog/foobar - - catalog/foobar-atmos-pro - -terraform: - backend_type: s3 - backend: - s3: - bucket: cptest-core-ue2-root-tfstate-plat - dynamodb_table: cptest-core-ue2-root-tfstate-plat-lock - role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-plat - encrypt: true - key: terraform/terraform.tfstate - acl: bucket-owner-full-control - region: us-east-2 - - vars: - environment: ue2 - namespace: foo - region: us-east-2 - stage: sandbox - tenant: plat - label_order: - - namespace - - tenant - - environment - - stage - - name - - attributes - diff --git a/tests/b/opentofu/atmos.yaml b/tests/b/opentofu/atmos.yaml deleted file mode 100644 index 5e5b513c..00000000 --- a/tests/b/opentofu/atmos.yaml +++ /dev/null @@ -1,92 +0,0 @@ -# CLI config is loaded from the following locations (from lowest to highest priority): -# system dir (`/usr/local/etc/atmos` on Linux, `%LOCALAPPDATA%/atmos` on Windows) -# home dir (~/.atmos) -# current directory -# ENV vars -# Command-line arguments -# -# It supports POSIX-style Globs for file names/paths (double-star `**` is supported) -# https://en.wikipedia.org/wiki/Glob_(programming) - -# Base path for components, stacks and workflows configurations. -# Can also be set using `ATMOS_BASE_PATH` ENV var, or `--base-path` command-line argument. -# Supports both absolute and relative paths. -# If not provided or is an empty string, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` -# are independent settings (supporting both absolute and relative paths). -# If `base_path` is provided, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` -# are considered paths relative to `base_path`. -base_path: "./tests/b/opentofu" - -aliases: - tofu: terraform - -components: - terraform: - command: "tofu" - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_BASE_PATH` ENV var, or `--terraform-dir` command-line argument - # Supports both absolute and relative paths - base_path: "components/terraform" - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE` ENV var - apply_auto_approve: false - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT` ENV var, or `--deploy-run-init` command-line argument - deploy_run_init: true - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_INIT_RUN_RECONFIGURE` ENV var, or `--init-run-reconfigure` command-line argument - init_run_reconfigure: true - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE` ENV var, or `--auto-generate-backend-file` command-line argument - auto_generate_backend_file: true - helmfile: - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_BASE_PATH` ENV var, or `--helmfile-dir` command-line argument - # Supports both absolute and relative paths - base_path: "components/helmfile" - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_KUBECONFIG_PATH` ENV var - kubeconfig_path: "/conf/.kube/" - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_HELM_AWS_PROFILE_PATTERN` ENV var - helm_aws_profile_pattern: "{namespace}-{tenant}-gbl-{stage}-helm" - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_CLUSTER_NAME_PATTERN` ENV var - cluster_name_pattern: "{namespace}-{tenant}-{environment}-{stage}-eks-cluster" - -stacks: - # Can also be set using `ATMOS_STACKS_BASE_PATH` ENV var, or `--config-dir` and `--stacks-dir` command-line arguments - # Supports both absolute and relative paths - base_path: "stacks" - # Can also be set using `ATMOS_STACKS_INCLUDED_PATHS` ENV var (comma-separated values string) - # Since we are distinguishing stacks based on namespace, and namespace is not part - # of the stack name, we have to set `included_paths` via the ENV var in the Dockerfile - included_paths: - - "orgs/**/*" - # Can also be set using `ATMOS_STACKS_EXCLUDED_PATHS` ENV var (comma-separated values string) - excluded_paths: - - "**/_defaults.yaml" - # exclude workflows directory if otherwise included in `included_paths` above - # - "workflows/**/*" - - # Can also be set using `ATMOS_STACKS_NAME_PATTERN` ENV var - name_pattern: "{tenant}-{environment}-{stage}" - -integrations: - github: - gitops: - opentofu-version: 1.7.3 - infracost-enabled: __INFRACOST_ENABLED__ - artifact-storage: - region: __STORAGE_REGION__ - bucket: __STORAGE_BUCKET__ - table: __STORAGE_TABLE__ - role: __STORAGE_ROLE__ - plan-repository-type: s3 - metadata-repository-type: dynamo - role: - plan: __PLAN_ROLE__ - apply: __APPLY_ROLE__ - matrix: - sort-by: .stack_slug - group-by: .stack_slug | split("-") | [.[0], .[2]] | join("-") - -workflows: - # Can also be set using `ATMOS_WORKFLOWS_BASE_PATH` ENV var, or `--workflows-dir` command-line arguments - # Supports both absolute and relative paths - base_path: "stacks/workflows" - -logs: - verbose: false - colors: true diff --git a/tests/b/opentofu/components/terraform/foobar/context.tf b/tests/b/opentofu/components/terraform/foobar/context.tf deleted file mode 100644 index 5e0ef885..00000000 --- a/tests/b/opentofu/components/terraform/foobar/context.tf +++ /dev/null @@ -1,279 +0,0 @@ -# -# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label -# All other instances of this file should be a copy of that one -# -# -# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf -# and then place it in your Terraform module to automatically get -# Cloud Posse's standard configuration inputs suitable for passing -# to Cloud Posse modules. -# -# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf -# -# Modules should access the whole context as `module.this.context` -# to get the input variables with nulls for defaults, -# for example `context = module.this.context`, -# and access individual variables as `module.this.`, -# with final values filled in. -# -# For example, when using defaults, `module.this.context.delimiter` -# will be null, and `module.this.delimiter` will be `-` (hyphen). -# - -module "this" { - source = "cloudposse/label/null" - version = "0.25.0" # requires Terraform >= 0.13.0 - - enabled = var.enabled - namespace = var.namespace - tenant = var.tenant - environment = var.environment - stage = var.stage - name = var.name - delimiter = var.delimiter - attributes = var.attributes - tags = var.tags - additional_tag_map = var.additional_tag_map - label_order = var.label_order - regex_replace_chars = var.regex_replace_chars - id_length_limit = var.id_length_limit - label_key_case = var.label_key_case - label_value_case = var.label_value_case - descriptor_formats = var.descriptor_formats - labels_as_tags = var.labels_as_tags - - context = var.context -} - -# Copy contents of cloudposse/terraform-null-label/variables.tf here - -variable "context" { - type = any - default = { - enabled = true - namespace = null - tenant = null - environment = null - stage = null - name = null - delimiter = null - attributes = [] - tags = {} - additional_tag_map = {} - regex_replace_chars = null - label_order = [] - id_length_limit = null - label_key_case = null - label_value_case = null - descriptor_formats = {} - # Note: we have to use [] instead of null for unset lists due to - # https://github.com/hashicorp/terraform/issues/28137 - # which was not fixed until Terraform 1.0.0, - # but we want the default to be all the labels in `label_order` - # and we want users to be able to prevent all tag generation - # by setting `labels_as_tags` to `[]`, so we need - # a different sentinel to indicate "default" - labels_as_tags = ["unset"] - } - description = <<-EOT - Single object for setting entire context at once. - See description of individual variables for details. - Leave string and numeric variables as `null` to use default value. - Individual variable settings (non-null) override settings in context object, - except for attributes, tags, and additional_tag_map, which are merged. - EOT - - validation { - condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) - error_message = "Allowed values: `lower`, `title`, `upper`." - } - - validation { - condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) - error_message = "Allowed values: `lower`, `title`, `upper`, `none`." - } -} - -variable "enabled" { - type = bool - default = null - description = "Set to false to prevent the module from creating any resources" -} - -variable "namespace" { - type = string - default = null - description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" -} - -variable "tenant" { - type = string - default = null - description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" -} - -variable "environment" { - type = string - default = null - description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" -} - -variable "stage" { - type = string - default = null - description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" -} - -variable "name" { - type = string - default = null - description = <<-EOT - ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. - This is the only ID element not also included as a `tag`. - The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. - EOT -} - -variable "delimiter" { - type = string - default = null - description = <<-EOT - Delimiter to be used between ID elements. - Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. - EOT -} - -variable "attributes" { - type = list(string) - default = [] - description = <<-EOT - ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, - in the order they appear in the list. New attributes are appended to the - end of the list. The elements of the list are joined by the `delimiter` - and treated as a single ID element. - EOT -} - -variable "labels_as_tags" { - type = set(string) - default = ["default"] - description = <<-EOT - Set of labels (ID elements) to include as tags in the `tags` output. - Default is to include all labels. - Tags with empty values will not be included in the `tags` output. - Set to `[]` to suppress all generated tags. - **Notes:** - The value of the `name` tag, if included, will be the `id`, not the `name`. - Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be - changed in later chained modules. Attempts to change it will be silently ignored. - EOT -} - -variable "tags" { - type = map(string) - default = {} - description = <<-EOT - Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). - Neither the tag keys nor the tag values will be modified by this module. - EOT -} - -variable "additional_tag_map" { - type = map(string) - default = {} - description = <<-EOT - Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. - This is for some rare cases where resources want additional configuration of tags - and therefore take a list of maps with tag key, value, and additional configuration. - EOT -} - -variable "label_order" { - type = list(string) - default = null - description = <<-EOT - The order in which the labels (ID elements) appear in the `id`. - Defaults to ["namespace", "environment", "stage", "name", "attributes"]. - You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. - EOT -} - -variable "regex_replace_chars" { - type = string - default = null - description = <<-EOT - Terraform regular expression (regex) string. - Characters matching the regex will be removed from the ID elements. - If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. - EOT -} - -variable "id_length_limit" { - type = number - default = null - description = <<-EOT - Limit `id` to this many characters (minimum 6). - Set to `0` for unlimited length. - Set to `null` for keep the existing setting, which defaults to `0`. - Does not affect `id_full`. - EOT - validation { - condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 - error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." - } -} - -variable "label_key_case" { - type = string - default = null - description = <<-EOT - Controls the letter case of the `tags` keys (label names) for tags generated by this module. - Does not affect keys of tags passed in via the `tags` input. - Possible values: `lower`, `title`, `upper`. - Default value: `title`. - EOT - - validation { - condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) - error_message = "Allowed values: `lower`, `title`, `upper`." - } -} - -variable "label_value_case" { - type = string - default = null - description = <<-EOT - Controls the letter case of ID elements (labels) as included in `id`, - set as tag values, and output by this module individually. - Does not affect values of tags passed in via the `tags` input. - Possible values: `lower`, `title`, `upper` and `none` (no transformation). - Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. - Default value: `lower`. - EOT - - validation { - condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) - error_message = "Allowed values: `lower`, `title`, `upper`, `none`." - } -} - -variable "descriptor_formats" { - type = any - default = {} - description = <<-EOT - Describe additional descriptors to be output in the `descriptors` output map. - Map of maps. Keys are names of descriptors. Values are maps of the form - `{ - format = string - labels = list(string) - }` - (Type is `any` so the map values can later be enhanced to provide additional options.) - `format` is a Terraform format string to be passed to the `format()` function. - `labels` is a list of labels, in order, to pass to `format()` function. - Label values will be normalized before being passed to `format()` so they will be - identical to how they appear in `id`. - Default is `{}` (`descriptors` output will be empty). - EOT -} - -#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/tests/b/opentofu/components/terraform/foobar/main.tf b/tests/b/opentofu/components/terraform/foobar/main.tf deleted file mode 100644 index 5fc39577..00000000 --- a/tests/b/opentofu/components/terraform/foobar/main.tf +++ /dev/null @@ -1,8 +0,0 @@ -resource "random_id" "foo" { - keepers = { - # Generate a new id each time we switch to a new seed - seed = "${module.this.id}-${var.example}" - timestamp = "${timestamp()}" - } - byte_length = 8 -} diff --git a/tests/b/opentofu/components/terraform/foobar/outputs.tf b/tests/b/opentofu/components/terraform/foobar/outputs.tf deleted file mode 100644 index 055f02d5..00000000 --- a/tests/b/opentofu/components/terraform/foobar/outputs.tf +++ /dev/null @@ -1,21 +0,0 @@ -output "result" { - description = "Test description output" - value = random_id.foo.id -} - -output "sensitive_value" { - description = "Test sensitive description output" - value = random_id.foo.id - sensitive = true -} - - -output "structured_value" { - description = "Test structured output" - value = { - test = "test" - value = { - result = random_id.foo.id - } - } -} \ No newline at end of file diff --git a/tests/b/opentofu/components/terraform/foobar/variables.tf b/tests/b/opentofu/components/terraform/foobar/variables.tf deleted file mode 100644 index d9b2dde4..00000000 --- a/tests/b/opentofu/components/terraform/foobar/variables.tf +++ /dev/null @@ -1,5 +0,0 @@ -variable "example" { - type = string - description = "testing variable" -} - diff --git a/tests/b/opentofu/stacks/catalog/foobar-atmos-pro.yaml b/tests/b/opentofu/stacks/catalog/foobar-atmos-pro.yaml deleted file mode 100644 index 87529334..00000000 --- a/tests/b/opentofu/stacks/catalog/foobar-atmos-pro.yaml +++ /dev/null @@ -1,13 +0,0 @@ -components: - terraform: - foobar-atmos-pro: - metadata: - component: foobar - settings: - pro: - enabled: true - github: - actions_enabled: false - vars: - example: blue - enabled: true \ No newline at end of file diff --git a/tests/b/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/b/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml deleted file mode 100644 index 65394b42..00000000 --- a/tests/b/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml +++ /dev/null @@ -1,30 +0,0 @@ -import: - - catalog/foobar - - catalog/foobar-atmos-pro - -terraform: - backend_type: s3 - backend: - s3: - bucket: cptest-core-ue2-root-tfstate-plat - dynamodb_table: cptest-core-ue2-root-tfstate-plat-lock - role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-plat - encrypt: true - key: opentofu/terraform.tfstate - acl: bucket-owner-full-control - region: us-east-2 - - vars: - environment: ue2 - namespace: foo - region: us-east-2 - stage: sandbox - tenant: plat - label_order: - - namespace - - tenant - - environment - - stage - - name - - attributes - diff --git a/tests/b/terraform/atmos.yaml b/tests/b/terraform/atmos.yaml deleted file mode 100644 index b94de1a0..00000000 --- a/tests/b/terraform/atmos.yaml +++ /dev/null @@ -1,93 +0,0 @@ -# CLI config is loaded from the following locations (from lowest to highest priority): -# system dir (`/usr/local/etc/atmos` on Linux, `%LOCALAPPDATA%/atmos` on Windows) -# home dir (~/.atmos) -# current directory -# ENV vars -# Command-line arguments -# -# It supports POSIX-style Globs for file names/paths (double-star `**` is supported) -# https://en.wikipedia.org/wiki/Glob_(programming) - -# Base path for components, stacks and workflows configurations. -# Can also be set using `ATMOS_BASE_PATH` ENV var, or `--base-path` command-line argument. -# Supports both absolute and relative paths. -# If not provided or is an empty string, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` -# are independent settings (supporting both absolute and relative paths). -# If `base_path` is provided, `components.terraform.base_path`, `components.helmfile.base_path`, `stacks.base_path` and `workflows.base_path` -# are considered paths relative to `base_path`. -base_path: "./tests/b/terraform" - -components: - terraform: - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_BASE_PATH` ENV var, or `--terraform-dir` command-line argument - # Supports both absolute and relative paths - base_path: "components/terraform" - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_APPLY_AUTO_APPROVE` ENV var - apply_auto_approve: false - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_DEPLOY_RUN_INIT` ENV var, or `--deploy-run-init` command-line argument - deploy_run_init: true - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_INIT_RUN_RECONFIGURE` ENV var, or `--init-run-reconfigure` command-line argument - init_run_reconfigure: true - # Can also be set using `ATMOS_COMPONENTS_TERRAFORM_AUTO_GENERATE_BACKEND_FILE` ENV var, or `--auto-generate-backend-file` command-line argument - auto_generate_backend_file: true - helmfile: - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_BASE_PATH` ENV var, or `--helmfile-dir` command-line argument - # Supports both absolute and relative paths - base_path: "components/helmfile" - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_KUBECONFIG_PATH` ENV var - kubeconfig_path: "/conf/.kube/" - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_HELM_AWS_PROFILE_PATTERN` ENV var - helm_aws_profile_pattern: "{namespace}-{tenant}-gbl-{stage}-helm" - # Can also be set using `ATMOS_COMPONENTS_HELMFILE_CLUSTER_NAME_PATTERN` ENV var - cluster_name_pattern: "{namespace}-{tenant}-{environment}-{stage}-eks-cluster" - -stacks: - # Can also be set using `ATMOS_STACKS_BASE_PATH` ENV var, or `--config-dir` and `--stacks-dir` command-line arguments - # Supports both absolute and relative paths - base_path: "stacks" - # Can also be set using `ATMOS_STACKS_INCLUDED_PATHS` ENV var (comma-separated values string) - # Since we are distinguishing stacks based on namespace, and namespace is not part - # of the stack name, we have to set `included_paths` via the ENV var in the Dockerfile - included_paths: - - "orgs/**/*" - # Can also be set using `ATMOS_STACKS_EXCLUDED_PATHS` ENV var (comma-separated values string) - excluded_paths: - - "**/_defaults.yaml" - # exclude workflows directory if otherwise included in `included_paths` above - # - "workflows/**/*" - - # Can also be set using `ATMOS_STACKS_NAME_PATTERN` ENV var - name_pattern: "{tenant}-{environment}-{stage}" - -integrations: - github: - gitops: - terraform-version: 1.5.7 - infracost-enabled: __INFRACOST_ENABLED__ - artifact-storage: - region: __STORAGE_REGION__ - bucket: __STORAGE_BUCKET__ - table: __STORAGE_TABLE__ - role: __STORAGE_ROLE__ - plan-repository-type: s3 - metadata-repository-type: dynamo - blob-account-name: - blob-container-name: - cosmos-container-name: - cosmos-database-name: - cosmos-endpoint: - role: - plan: __PLAN_ROLE__ - apply: __APPLY_ROLE__ - matrix: - sort-by: .stack_slug - group-by: .stack_slug | split("-") | [.[0], .[2]] | join("-") - -workflows: - # Can also be set using `ATMOS_WORKFLOWS_BASE_PATH` ENV var, or `--workflows-dir` command-line arguments - # Supports both absolute and relative paths - base_path: "stacks/workflows" - -logs: - verbose: false - colors: true diff --git a/tests/b/terraform/components/terraform/foobar/context.tf b/tests/b/terraform/components/terraform/foobar/context.tf deleted file mode 100644 index 5e0ef885..00000000 --- a/tests/b/terraform/components/terraform/foobar/context.tf +++ /dev/null @@ -1,279 +0,0 @@ -# -# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label -# All other instances of this file should be a copy of that one -# -# -# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf -# and then place it in your Terraform module to automatically get -# Cloud Posse's standard configuration inputs suitable for passing -# to Cloud Posse modules. -# -# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf -# -# Modules should access the whole context as `module.this.context` -# to get the input variables with nulls for defaults, -# for example `context = module.this.context`, -# and access individual variables as `module.this.`, -# with final values filled in. -# -# For example, when using defaults, `module.this.context.delimiter` -# will be null, and `module.this.delimiter` will be `-` (hyphen). -# - -module "this" { - source = "cloudposse/label/null" - version = "0.25.0" # requires Terraform >= 0.13.0 - - enabled = var.enabled - namespace = var.namespace - tenant = var.tenant - environment = var.environment - stage = var.stage - name = var.name - delimiter = var.delimiter - attributes = var.attributes - tags = var.tags - additional_tag_map = var.additional_tag_map - label_order = var.label_order - regex_replace_chars = var.regex_replace_chars - id_length_limit = var.id_length_limit - label_key_case = var.label_key_case - label_value_case = var.label_value_case - descriptor_formats = var.descriptor_formats - labels_as_tags = var.labels_as_tags - - context = var.context -} - -# Copy contents of cloudposse/terraform-null-label/variables.tf here - -variable "context" { - type = any - default = { - enabled = true - namespace = null - tenant = null - environment = null - stage = null - name = null - delimiter = null - attributes = [] - tags = {} - additional_tag_map = {} - regex_replace_chars = null - label_order = [] - id_length_limit = null - label_key_case = null - label_value_case = null - descriptor_formats = {} - # Note: we have to use [] instead of null for unset lists due to - # https://github.com/hashicorp/terraform/issues/28137 - # which was not fixed until Terraform 1.0.0, - # but we want the default to be all the labels in `label_order` - # and we want users to be able to prevent all tag generation - # by setting `labels_as_tags` to `[]`, so we need - # a different sentinel to indicate "default" - labels_as_tags = ["unset"] - } - description = <<-EOT - Single object for setting entire context at once. - See description of individual variables for details. - Leave string and numeric variables as `null` to use default value. - Individual variable settings (non-null) override settings in context object, - except for attributes, tags, and additional_tag_map, which are merged. - EOT - - validation { - condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) - error_message = "Allowed values: `lower`, `title`, `upper`." - } - - validation { - condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) - error_message = "Allowed values: `lower`, `title`, `upper`, `none`." - } -} - -variable "enabled" { - type = bool - default = null - description = "Set to false to prevent the module from creating any resources" -} - -variable "namespace" { - type = string - default = null - description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" -} - -variable "tenant" { - type = string - default = null - description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" -} - -variable "environment" { - type = string - default = null - description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" -} - -variable "stage" { - type = string - default = null - description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" -} - -variable "name" { - type = string - default = null - description = <<-EOT - ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. - This is the only ID element not also included as a `tag`. - The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. - EOT -} - -variable "delimiter" { - type = string - default = null - description = <<-EOT - Delimiter to be used between ID elements. - Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. - EOT -} - -variable "attributes" { - type = list(string) - default = [] - description = <<-EOT - ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, - in the order they appear in the list. New attributes are appended to the - end of the list. The elements of the list are joined by the `delimiter` - and treated as a single ID element. - EOT -} - -variable "labels_as_tags" { - type = set(string) - default = ["default"] - description = <<-EOT - Set of labels (ID elements) to include as tags in the `tags` output. - Default is to include all labels. - Tags with empty values will not be included in the `tags` output. - Set to `[]` to suppress all generated tags. - **Notes:** - The value of the `name` tag, if included, will be the `id`, not the `name`. - Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be - changed in later chained modules. Attempts to change it will be silently ignored. - EOT -} - -variable "tags" { - type = map(string) - default = {} - description = <<-EOT - Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). - Neither the tag keys nor the tag values will be modified by this module. - EOT -} - -variable "additional_tag_map" { - type = map(string) - default = {} - description = <<-EOT - Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. - This is for some rare cases where resources want additional configuration of tags - and therefore take a list of maps with tag key, value, and additional configuration. - EOT -} - -variable "label_order" { - type = list(string) - default = null - description = <<-EOT - The order in which the labels (ID elements) appear in the `id`. - Defaults to ["namespace", "environment", "stage", "name", "attributes"]. - You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. - EOT -} - -variable "regex_replace_chars" { - type = string - default = null - description = <<-EOT - Terraform regular expression (regex) string. - Characters matching the regex will be removed from the ID elements. - If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. - EOT -} - -variable "id_length_limit" { - type = number - default = null - description = <<-EOT - Limit `id` to this many characters (minimum 6). - Set to `0` for unlimited length. - Set to `null` for keep the existing setting, which defaults to `0`. - Does not affect `id_full`. - EOT - validation { - condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 - error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." - } -} - -variable "label_key_case" { - type = string - default = null - description = <<-EOT - Controls the letter case of the `tags` keys (label names) for tags generated by this module. - Does not affect keys of tags passed in via the `tags` input. - Possible values: `lower`, `title`, `upper`. - Default value: `title`. - EOT - - validation { - condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) - error_message = "Allowed values: `lower`, `title`, `upper`." - } -} - -variable "label_value_case" { - type = string - default = null - description = <<-EOT - Controls the letter case of ID elements (labels) as included in `id`, - set as tag values, and output by this module individually. - Does not affect values of tags passed in via the `tags` input. - Possible values: `lower`, `title`, `upper` and `none` (no transformation). - Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. - Default value: `lower`. - EOT - - validation { - condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) - error_message = "Allowed values: `lower`, `title`, `upper`, `none`." - } -} - -variable "descriptor_formats" { - type = any - default = {} - description = <<-EOT - Describe additional descriptors to be output in the `descriptors` output map. - Map of maps. Keys are names of descriptors. Values are maps of the form - `{ - format = string - labels = list(string) - }` - (Type is `any` so the map values can later be enhanced to provide additional options.) - `format` is a Terraform format string to be passed to the `format()` function. - `labels` is a list of labels, in order, to pass to `format()` function. - Label values will be normalized before being passed to `format()` so they will be - identical to how they appear in `id`. - Default is `{}` (`descriptors` output will be empty). - EOT -} - -#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/tests/b/terraform/components/terraform/foobar/main.tf b/tests/b/terraform/components/terraform/foobar/main.tf deleted file mode 100644 index 5fc39577..00000000 --- a/tests/b/terraform/components/terraform/foobar/main.tf +++ /dev/null @@ -1,8 +0,0 @@ -resource "random_id" "foo" { - keepers = { - # Generate a new id each time we switch to a new seed - seed = "${module.this.id}-${var.example}" - timestamp = "${timestamp()}" - } - byte_length = 8 -} diff --git a/tests/b/terraform/components/terraform/foobar/outputs.tf b/tests/b/terraform/components/terraform/foobar/outputs.tf deleted file mode 100644 index 7177f0bd..00000000 --- a/tests/b/terraform/components/terraform/foobar/outputs.tf +++ /dev/null @@ -1,21 +0,0 @@ -output "result" { - description = "Test description output" - value = random_id.foo.id -} - -output "sensitive_value" { - description = "Test sensitive description output" - value = random_id.foo.id - sensitive = true -} - - -output "structured_value" { - description = "Test structured output" - value = { - test = "test" - value = { - result = random_id.foo.id - } - } -} diff --git a/tests/b/terraform/components/terraform/foobar/variables.tf b/tests/b/terraform/components/terraform/foobar/variables.tf deleted file mode 100644 index d9b2dde4..00000000 --- a/tests/b/terraform/components/terraform/foobar/variables.tf +++ /dev/null @@ -1,5 +0,0 @@ -variable "example" { - type = string - description = "testing variable" -} - diff --git a/tests/b/terraform/stacks/catalog/foobar-atmos-pro.yaml b/tests/b/terraform/stacks/catalog/foobar-atmos-pro.yaml deleted file mode 100644 index 87529334..00000000 --- a/tests/b/terraform/stacks/catalog/foobar-atmos-pro.yaml +++ /dev/null @@ -1,13 +0,0 @@ -components: - terraform: - foobar-atmos-pro: - metadata: - component: foobar - settings: - pro: - enabled: true - github: - actions_enabled: false - vars: - example: blue - enabled: true \ No newline at end of file diff --git a/tests/b/terraform/stacks/catalog/foobar.yaml b/tests/b/terraform/stacks/catalog/foobar.yaml deleted file mode 100644 index 991c4742..00000000 --- a/tests/b/terraform/stacks/catalog/foobar.yaml +++ /dev/null @@ -1,8 +0,0 @@ -components: - terraform: - foobar: - settings: - github: - actions_enabled: true - vars: - example: blue diff --git a/tests/b/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/b/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml deleted file mode 100644 index 3d552592..00000000 --- a/tests/b/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml +++ /dev/null @@ -1,30 +0,0 @@ -import: - - catalog/foobar - - catalog/foobar-atmos-pro - -terraform: - backend_type: s3 - backend: - s3: - bucket: cptest-core-ue2-root-tfstate-plat - dynamodb_table: cptest-core-ue2-root-tfstate-plat-lock - role_arn: arn:aws:iam::822777368227:role/cptest-core-gbl-root-tfstate-plat - encrypt: true - key: terraform/terraform.tfstate - acl: bucket-owner-full-control - region: us-east-2 - - vars: - environment: ue2 - namespace: foo - region: us-east-2 - stage: sandbox - tenant: plat - label_order: - - namespace - - tenant - - environment - - stage - - name - - attributes - diff --git a/tests/b/opentofu/stacks/catalog/foobar.yaml b/tests/opentofu/stacks/catalog/foobar-plan-diff.yaml similarity index 84% rename from tests/b/opentofu/stacks/catalog/foobar.yaml rename to tests/opentofu/stacks/catalog/foobar-plan-diff.yaml index 991c4742..603b3206 100644 --- a/tests/b/opentofu/stacks/catalog/foobar.yaml +++ b/tests/opentofu/stacks/catalog/foobar-plan-diff.yaml @@ -1,6 +1,6 @@ components: terraform: - foobar: + foobar-plan-diff: settings: github: actions_enabled: true diff --git a/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml index 65394b42..910e6d14 100644 --- a/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml +++ b/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml @@ -1,5 +1,6 @@ import: - catalog/foobar + - catalog/foobar-plan-diff - catalog/foobar-atmos-pro terraform: From 7fad9c1a4ccdee3b55b84078c6b926ea86350731 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 00:28:34 +0200 Subject: [PATCH 064/123] Added A/B testings --- tests/opentofu/stacks/catalog/foobar-plan-diff.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/opentofu/stacks/catalog/foobar-plan-diff.yaml b/tests/opentofu/stacks/catalog/foobar-plan-diff.yaml index 603b3206..f518b9cd 100644 --- a/tests/opentofu/stacks/catalog/foobar-plan-diff.yaml +++ b/tests/opentofu/stacks/catalog/foobar-plan-diff.yaml @@ -1,8 +1,11 @@ components: terraform: foobar-plan-diff: + metadata: + component: foobar settings: github: actions_enabled: true vars: example: blue + enabled: true From b00631c9f6f58c338ffb44ada3aa930be7583d23 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 00:34:00 +0200 Subject: [PATCH 065/123] Added A/B testings --- .github/workflows/integration-tests-plan-diff.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index a7f47ea0..3424c2c7 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -78,7 +78,7 @@ jobs: - name: Apply Atmos Component uses: ./ with: - component: "foobar" + component: "foobar-plan-diff" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} debug: true From f3286e11eb7bab02a933b83df7ff7e4fde774014 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 15:57:54 +0200 Subject: [PATCH 066/123] Added A/B testings --- .github/workflows/integration-tests-plan-diff.yml | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index 3424c2c7..95798603 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -51,21 +51,8 @@ jobs: atmos-config-path: ${{ runner.temp }} debug: true env: - TF_VAR_seed: ${{ steps.env.outputs.seed }} + TF_VAR_seed: ${{ steps.env.outputs.seed }}-a - - shell: bash - run: | - mkdir -p ${{ runner.temp }} - cp ./tests/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml - sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml - sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml - sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml - sed -i -e 's#__STORAGE_TABLE__#${{ secrets.TERRAFORM_STATE_TABLE }}#g' ${{ runner.temp }}/atmos.yaml - sed -i -e 's#__STORAGE_TABLE__#${{ secrets.TERRAFORM_STATE_TABLE }}#g' ${{ runner.temp }}/atmos.yaml - sed -i -e 's#__STORAGE_ROLE__#${{ secrets.TERRAFORM_STATE_ROLE }}#g' ${{ runner.temp }}/atmos.yaml - sed -i -e 's#__PLAN_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml - sed -i -e 's#__APPLY_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml - - uses: actions/checkout@v4 with: ref: ${{ github.event.pull_request.head.ref }} From ee6bf03049ef636b10516684adebd7a923ed339d Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 16:09:55 +0200 Subject: [PATCH 067/123] Added A/B testings --- tests/terraform/stacks/catalog/foobar-plan-diff.yaml | 11 +++++++++++ .../orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml | 1 + 2 files changed, 12 insertions(+) create mode 100644 tests/terraform/stacks/catalog/foobar-plan-diff.yaml diff --git a/tests/terraform/stacks/catalog/foobar-plan-diff.yaml b/tests/terraform/stacks/catalog/foobar-plan-diff.yaml new file mode 100644 index 00000000..f518b9cd --- /dev/null +++ b/tests/terraform/stacks/catalog/foobar-plan-diff.yaml @@ -0,0 +1,11 @@ +components: + terraform: + foobar-plan-diff: + metadata: + component: foobar + settings: + github: + actions_enabled: true + vars: + example: blue + enabled: true diff --git a/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml index 3d552592..cd038716 100644 --- a/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml +++ b/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml @@ -1,5 +1,6 @@ import: - catalog/foobar + - catalog/foobar-plan-diff - catalog/foobar-atmos-pro terraform: From 5e3360e92cc03d37b1733cf339aac2fe2813a7e0 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 16:46:21 +0200 Subject: [PATCH 068/123] Added A/B testings --- action.yml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/action.yml b/action.yml index ca2a2787..c983066f 100644 --- a/action.yml +++ b/action.yml @@ -347,13 +347,20 @@ runs: # Remove the environment file from the cache to avoid conflicts with workspace select rm -f ./.terraform/environment + TERRAFORM_PLAN_OUTPUT_FILE="./terraform-${GITHUB_RUN_ID}-plan-output.txt" + atmos terraform plan ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ -input=false \ - -no-color + -no-color \ + &> ${TERRAFORM_PLAN_OUTPUT_FILE} PLAN_CHANGED=$? + if [[ "${PLAN_CHANGED}" != "0" ]]; then + echo "PLAN FAILED" >> $GITHUB_STEP_SUMMARY + fi + if [[ "${{ inputs.plan-storage }}" == "true" ]]; then cp ${{ steps.vars.outputs.plan_file }} ${{ steps.vars.outputs.renewed_plan_file }} @@ -367,13 +374,12 @@ runs: --skip-init PLAN_CHANGED=$? fi - echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" - echo "PLAN_CHANGED: $PLAN_CHANGED" - echo "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" + if [[ "${PLAN_CHANGED}" == "0" ]]; then echo "plan_changed=false" >> $GITHUB_OUTPUT else echo "plan_changed=true" >> $GITHUB_OUTPUT + echo "PLAN DIFFERENT" >> $GITHUB_STEP_SUMMARY fi - name: Check Whether Infracost is Enabled @@ -493,8 +499,6 @@ runs: sed -i "s#\"\`#\`#g" ${{ github.workspace }}/atmos-apply-summary.md sed -i "s#|--#|:-#g" ${{ github.workspace }}/atmos-apply-summary.md - cat "${{ github.workspace }}/atmos-apply-summary.md" >> $GITHUB_STEP_SUMMARY - if [[ "${TERRAFORM_RESULT}" == "0" ]]; then echo "status=succeeded" >> $GITHUB_OUTPUT echo "Terraform apply executed successfully" @@ -505,7 +509,9 @@ runs: # Link to a job that executed this action echo "[Job](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> "${{ github.workspace }}/atmos-apply-summary.md" - + + cat "${{ github.workspace }}/atmos-apply-summary.md" >> $GITHUB_STEP_SUMMARY + rm -f ${TERRAFORM_OUTPUT_FILE} exit $TERRAFORM_RESULT From bc0fd971b420a03412329248fdac38ed9dd1cc49 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 17:03:18 +0200 Subject: [PATCH 069/123] Added A/B testings --- action.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index c983066f..fd82d55a 100644 --- a/action.yml +++ b/action.yml @@ -359,8 +359,11 @@ runs: if [[ "${PLAN_CHANGED}" != "0" ]]; then echo "PLAN FAILED" >> $GITHUB_STEP_SUMMARY + exit 1 fi + TERRAFORM_PLAN_DIFF_OUTPUT_FILE="./terraform-${GITHUB_RUN_ID}-plan-diff-output.txt" + if [[ "${{ inputs.plan-storage }}" == "true" ]]; then cp ${{ steps.vars.outputs.plan_file }} ${{ steps.vars.outputs.renewed_plan_file }} @@ -371,7 +374,9 @@ runs: -no-color \ --orig ${{ steps.vars.outputs.retrieved_plan_filename }} \ --new ${{ steps.vars.outputs.renewed_plan_filename }} \ - --skip-init + --skip-init \ + &> ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE} + PLAN_CHANGED=$? fi @@ -380,6 +385,8 @@ runs: else echo "plan_changed=true" >> $GITHUB_OUTPUT echo "PLAN DIFFERENT" >> $GITHUB_STEP_SUMMARY + cat ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE} >> $GITHUB_STEP_SUMMARY + exit 1 fi - name: Check Whether Infracost is Enabled From 77def54cf3b72d870435c57dd927dc20b31102a9 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 17:06:29 +0200 Subject: [PATCH 070/123] Added A/B testings --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index fd82d55a..1f0e110d 100644 --- a/action.yml +++ b/action.yml @@ -375,7 +375,7 @@ runs: --orig ${{ steps.vars.outputs.retrieved_plan_filename }} \ --new ${{ steps.vars.outputs.renewed_plan_filename }} \ --skip-init \ - &> ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE} + > ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE} PLAN_CHANGED=$? fi From 5c1305642ea21b049cc22056e92d36035a9a9fb3 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 17:11:08 +0200 Subject: [PATCH 071/123] Added A/B testings --- action.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/action.yml b/action.yml index 1f0e110d..02de1dfb 100644 --- a/action.yml +++ b/action.yml @@ -385,7 +385,9 @@ runs: else echo "plan_changed=true" >> $GITHUB_OUTPUT echo "PLAN DIFFERENT" >> $GITHUB_STEP_SUMMARY + echo "```" >> $GITHUB_STEP_SUMMARY cat ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE} >> $GITHUB_STEP_SUMMARY + echo "```" >> $GITHUB_STEP_SUMMARY exit 1 fi From ef6a0eae1595441f1ed72d6b7baa78355b6f3247 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 17:16:03 +0200 Subject: [PATCH 072/123] Added A/B testings --- action.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/action.yml b/action.yml index 02de1dfb..1f0e110d 100644 --- a/action.yml +++ b/action.yml @@ -385,9 +385,7 @@ runs: else echo "plan_changed=true" >> $GITHUB_OUTPUT echo "PLAN DIFFERENT" >> $GITHUB_STEP_SUMMARY - echo "```" >> $GITHUB_STEP_SUMMARY cat ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE} >> $GITHUB_STEP_SUMMARY - echo "```" >> $GITHUB_STEP_SUMMARY exit 1 fi From 7b328d224da46c685947f2042e37c0297d8977ca Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 17:21:41 +0200 Subject: [PATCH 073/123] Added A/B testings --- action.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/action.yml b/action.yml index 1f0e110d..56eb31e7 100644 --- a/action.yml +++ b/action.yml @@ -374,7 +374,6 @@ runs: -no-color \ --orig ${{ steps.vars.outputs.retrieved_plan_filename }} \ --new ${{ steps.vars.outputs.renewed_plan_filename }} \ - --skip-init \ > ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE} PLAN_CHANGED=$? From b159b1d4e3ccca431925c1ba677e25101693a43d Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 20:11:59 +0200 Subject: [PATCH 074/123] Plan diff support skip init flag --- .github/workflows/integration-test-atmos-pro.yml | 2 +- .github/workflows/integration-tests-plan-diff.yml | 1 + .github/workflows/integration-tests.yml | 1 + action.yml | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/integration-test-atmos-pro.yml b/.github/workflows/integration-test-atmos-pro.yml index 35f7b0e2..0ed59e3c 100644 --- a/.github/workflows/integration-test-atmos-pro.yml +++ b/.github/workflows/integration-test-atmos-pro.yml @@ -73,7 +73,7 @@ jobs: component: "foobar-atmos-pro" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} - atmos-version: ">= 1.174.0" + atmos-version: "1.185.1-rc.2" env: TF_VAR_seed: ${{ steps.env.outputs.seed }} diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index 95798603..ff818739 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -68,6 +68,7 @@ jobs: component: "foobar-plan-diff" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} + atmos-version: "1.185.1-rc.2" debug: true env: TF_VAR_seed: ${{ steps.env.outputs.seed }} diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index bfdfcdbc..5968222f 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -70,6 +70,7 @@ jobs: component: "foobar" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} + atmos-version: "1.185.1-rc.2" debug: true env: TF_VAR_seed: ${{ steps.env.outputs.seed }} diff --git a/action.yml b/action.yml index 56eb31e7..1f0e110d 100644 --- a/action.yml +++ b/action.yml @@ -374,6 +374,7 @@ runs: -no-color \ --orig ${{ steps.vars.outputs.retrieved_plan_filename }} \ --new ${{ steps.vars.outputs.renewed_plan_filename }} \ + --skip-init \ > ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE} PLAN_CHANGED=$? From a77a47224e19abd87a2be0217f6bc523041b54ff Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Thu, 7 Aug 2025 20:35:27 +0200 Subject: [PATCH 075/123] Plan diff support skip init flag --- .github/workflows/integration-test-atmos-pro.yml | 2 +- .github/workflows/integration-tests-plan-diff.yml | 2 +- .github/workflows/integration-tests.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/integration-test-atmos-pro.yml b/.github/workflows/integration-test-atmos-pro.yml index 0ed59e3c..8de58b87 100644 --- a/.github/workflows/integration-test-atmos-pro.yml +++ b/.github/workflows/integration-test-atmos-pro.yml @@ -73,7 +73,7 @@ jobs: component: "foobar-atmos-pro" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} - atmos-version: "1.185.1-rc.2" + atmos-version: "v1.185.1-rc.2" env: TF_VAR_seed: ${{ steps.env.outputs.seed }} diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index ff818739..30caa3d7 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -68,7 +68,7 @@ jobs: component: "foobar-plan-diff" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} - atmos-version: "1.185.1-rc.2" + atmos-version: "v1.185.1-rc.2" debug: true env: TF_VAR_seed: ${{ steps.env.outputs.seed }} diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 5968222f..c28939d0 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -70,7 +70,7 @@ jobs: component: "foobar" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} - atmos-version: "1.185.1-rc.2" + atmos-version: "v1.185.1-rc.2" debug: true env: TF_VAR_seed: ${{ steps.env.outputs.seed }} From 1daf8a77933deeb108a780c6fcb4a85e77870541 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 11:05:41 +0200 Subject: [PATCH 076/123] Plan diff support skip init flag --- .github/workflows/integration-test-atmos-pro.yml | 1 - .github/workflows/integration-tests-plan-diff.yml | 1 - .github/workflows/integration-tests.yml | 1 - action.yml | 2 +- 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/integration-test-atmos-pro.yml b/.github/workflows/integration-test-atmos-pro.yml index 8de58b87..c08bd28d 100644 --- a/.github/workflows/integration-test-atmos-pro.yml +++ b/.github/workflows/integration-test-atmos-pro.yml @@ -73,7 +73,6 @@ jobs: component: "foobar-atmos-pro" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} - atmos-version: "v1.185.1-rc.2" env: TF_VAR_seed: ${{ steps.env.outputs.seed }} diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index 30caa3d7..95798603 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -68,7 +68,6 @@ jobs: component: "foobar-plan-diff" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} - atmos-version: "v1.185.1-rc.2" debug: true env: TF_VAR_seed: ${{ steps.env.outputs.seed }} diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index c28939d0..bfdfcdbc 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -70,7 +70,6 @@ jobs: component: "foobar" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} - atmos-version: "v1.185.1-rc.2" debug: true env: TF_VAR_seed: ${{ steps.env.outputs.seed }} diff --git a/action.yml b/action.yml index 1f0e110d..620e32e0 100644 --- a/action.yml +++ b/action.yml @@ -22,7 +22,7 @@ inputs: atmos-version: description: The version of atmos to install required: false - default: ">= 1.184.0" + default: ">= 1.186.0" atmos-config-path: description: The path to the atmos.yaml file required: true From 66051d3f5df3ae2eb1c894a762f205bc3b069f70 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 11:25:50 +0200 Subject: [PATCH 077/123] Plan diff support skip init flag --- action.yml | 7 +++++-- config/atmos_plan_diff_github_summary.md | 12 ++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 config/atmos_plan_diff_github_summary.md diff --git a/action.yml b/action.yml index 620e32e0..7aeba43a 100644 --- a/action.yml +++ b/action.yml @@ -384,8 +384,11 @@ runs: echo "plan_changed=false" >> $GITHUB_OUTPUT else echo "plan_changed=true" >> $GITHUB_OUTPUT - echo "PLAN DIFFERENT" >> $GITHUB_STEP_SUMMARY - cat ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE} >> $GITHUB_STEP_SUMMARY + cp ${GITHUB_ACTION_PATH}/config/atmos_plan_diff_github_summary.md ./atmos_plan_diff_github_summary.md + sed -i "s/{{COMPONENT_NAME}}/${{ inputs.component }}/g" ./atmos_plan_diff_github_summary.md + sed -i "s/{{STACK_NAME}}/${{ inputs.stack }}/g" ./atmos_plan_diff_github_summary.md + sed -i "s/{{DIFF}}/$(cat ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE})/g" ./atmos_plan_diff_github_summary.md + cat ./atmos_plan_diff_github_summary.md >> $GITHUB_STEP_SUMMARY exit 1 fi diff --git a/config/atmos_plan_diff_github_summary.md b/config/atmos_plan_diff_github_summary.md new file mode 100644 index 00000000..01e3c982 --- /dev/null +++ b/config/atmos_plan_diff_github_summary.md @@ -0,0 +1,12 @@ +## Plan outdated `{{COMPONENT_NAME}}` in `{{STACK_NAME}}` + + + [![failed](https://shields.io/badge/PLAN-REPLACE-critical?style=for-the-badge)](#user-content-replace-plat-ue2-sandbox-foobar-plan-diff) + +
Terraform Plan outdated diff + +``` +{{DIFF}} +``` + +
From ae732ad2b95f32c5b5dd65d74e50d3efb97a0ab5 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 11:33:45 +0200 Subject: [PATCH 078/123] Plan diff support skip init flag --- action.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 7aeba43a..de106b51 100644 --- a/action.yml +++ b/action.yml @@ -387,7 +387,8 @@ runs: cp ${GITHUB_ACTION_PATH}/config/atmos_plan_diff_github_summary.md ./atmos_plan_diff_github_summary.md sed -i "s/{{COMPONENT_NAME}}/${{ inputs.component }}/g" ./atmos_plan_diff_github_summary.md sed -i "s/{{STACK_NAME}}/${{ inputs.stack }}/g" ./atmos_plan_diff_github_summary.md - sed -i "s/{{DIFF}}/$(cat ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE})/g" ./atmos_plan_diff_github_summary.md + diff=$(cat ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE}) + sed -i "s/{{DIFF}}/${diff}/g" ./atmos_plan_diff_github_summary.md cat ./atmos_plan_diff_github_summary.md >> $GITHUB_STEP_SUMMARY exit 1 fi From d02b92fac5f754e6f7ab55c3288b318a1154fb46 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 11:39:35 +0200 Subject: [PATCH 079/123] Plan diff support skip init flag --- action.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/action.yml b/action.yml index de106b51..d8e17d34 100644 --- a/action.yml +++ b/action.yml @@ -387,8 +387,7 @@ runs: cp ${GITHUB_ACTION_PATH}/config/atmos_plan_diff_github_summary.md ./atmos_plan_diff_github_summary.md sed -i "s/{{COMPONENT_NAME}}/${{ inputs.component }}/g" ./atmos_plan_diff_github_summary.md sed -i "s/{{STACK_NAME}}/${{ inputs.stack }}/g" ./atmos_plan_diff_github_summary.md - diff=$(cat ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE}) - sed -i "s/{{DIFF}}/${diff}/g" ./atmos_plan_diff_github_summary.md + sed -i -e "s/{{DIFF}}/{r ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE}' -e 'd}/" ./atmos_plan_diff_github_summary.md cat ./atmos_plan_diff_github_summary.md >> $GITHUB_STEP_SUMMARY exit 1 fi From cdfa848758a3fd62c2fdeb3e89a4f0cdc2b767a0 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 11:40:33 +0200 Subject: [PATCH 080/123] Plan diff support skip init flag --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index d8e17d34..9e8ad046 100644 --- a/action.yml +++ b/action.yml @@ -387,7 +387,7 @@ runs: cp ${GITHUB_ACTION_PATH}/config/atmos_plan_diff_github_summary.md ./atmos_plan_diff_github_summary.md sed -i "s/{{COMPONENT_NAME}}/${{ inputs.component }}/g" ./atmos_plan_diff_github_summary.md sed -i "s/{{STACK_NAME}}/${{ inputs.stack }}/g" ./atmos_plan_diff_github_summary.md - sed -i -e "s/{{DIFF}}/{r ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE}' -e 'd}/" ./atmos_plan_diff_github_summary.md + sed -i -e "s/{{DIFF}}/{r ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE}" -e 'd}'./atmos_plan_diff_github_summary.md cat ./atmos_plan_diff_github_summary.md >> $GITHUB_STEP_SUMMARY exit 1 fi From a52c560e8cac2a0408b83c731928b89deb12ac8b Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 11:45:46 +0200 Subject: [PATCH 081/123] Plan diff support skip init flag --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 9e8ad046..25ce5c53 100644 --- a/action.yml +++ b/action.yml @@ -387,7 +387,7 @@ runs: cp ${GITHUB_ACTION_PATH}/config/atmos_plan_diff_github_summary.md ./atmos_plan_diff_github_summary.md sed -i "s/{{COMPONENT_NAME}}/${{ inputs.component }}/g" ./atmos_plan_diff_github_summary.md sed -i "s/{{STACK_NAME}}/${{ inputs.stack }}/g" ./atmos_plan_diff_github_summary.md - sed -i -e "s/{{DIFF}}/{r ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE}" -e 'd}'./atmos_plan_diff_github_summary.md + sed -i -e '/{{DIFF}}/{r terraform-${GITHUB_RUN_ID}-plan-diff-output.txt' -e 'd}'./atmos_plan_diff_github_summary.md cat ./atmos_plan_diff_github_summary.md >> $GITHUB_STEP_SUMMARY exit 1 fi From 3d1a1d6060e8025386030471a80169ece0da0c7b Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 11:49:32 +0200 Subject: [PATCH 082/123] Plan diff support skip init flag --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 25ce5c53..436497b8 100644 --- a/action.yml +++ b/action.yml @@ -387,7 +387,7 @@ runs: cp ${GITHUB_ACTION_PATH}/config/atmos_plan_diff_github_summary.md ./atmos_plan_diff_github_summary.md sed -i "s/{{COMPONENT_NAME}}/${{ inputs.component }}/g" ./atmos_plan_diff_github_summary.md sed -i "s/{{STACK_NAME}}/${{ inputs.stack }}/g" ./atmos_plan_diff_github_summary.md - sed -i -e '/{{DIFF}}/{r terraform-${GITHUB_RUN_ID}-plan-diff-output.txt' -e 'd}'./atmos_plan_diff_github_summary.md + sed -i -e '/{{DIFF}}/{r terraform-${GITHUB_RUN_ID}-plan-diff-output.txt' -e 'd}' ./atmos_plan_diff_github_summary.md cat ./atmos_plan_diff_github_summary.md >> $GITHUB_STEP_SUMMARY exit 1 fi From b10ccff8b6c155d0e29649439dd4d769d8540232 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 11:55:20 +0200 Subject: [PATCH 083/123] Plan diff support skip init flag --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 436497b8..0e7a166f 100644 --- a/action.yml +++ b/action.yml @@ -387,7 +387,7 @@ runs: cp ${GITHUB_ACTION_PATH}/config/atmos_plan_diff_github_summary.md ./atmos_plan_diff_github_summary.md sed -i "s/{{COMPONENT_NAME}}/${{ inputs.component }}/g" ./atmos_plan_diff_github_summary.md sed -i "s/{{STACK_NAME}}/${{ inputs.stack }}/g" ./atmos_plan_diff_github_summary.md - sed -i -e '/{{DIFF}}/{r terraform-${GITHUB_RUN_ID}-plan-diff-output.txt' -e 'd}' ./atmos_plan_diff_github_summary.md + sed -i -e "/{{DIFF}}/ {r terraform-${GITHUB_RUN_ID}-plan-diff-output.txt" -e 'd}' ./atmos_plan_diff_github_summary.md cat ./atmos_plan_diff_github_summary.md >> $GITHUB_STEP_SUMMARY exit 1 fi From db6d5101866cbacc9771d921be3abd0796b91b72 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 11:59:03 +0200 Subject: [PATCH 084/123] Plan diff support skip init flag --- action.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 0e7a166f..c2bd6943 100644 --- a/action.yml +++ b/action.yml @@ -387,8 +387,10 @@ runs: cp ${GITHUB_ACTION_PATH}/config/atmos_plan_diff_github_summary.md ./atmos_plan_diff_github_summary.md sed -i "s/{{COMPONENT_NAME}}/${{ inputs.component }}/g" ./atmos_plan_diff_github_summary.md sed -i "s/{{STACK_NAME}}/${{ inputs.stack }}/g" ./atmos_plan_diff_github_summary.md - sed -i -e "/{{DIFF}}/ {r terraform-${GITHUB_RUN_ID}-plan-diff-output.txt" -e 'd}' ./atmos_plan_diff_github_summary.md + sed -i -e "/{{DIFF}}/ {r ${TERRAFORM_PLAN_OUTPUT_FILE}" -e 'd}' ./atmos_plan_diff_github_summary.md cat ./atmos_plan_diff_github_summary.md >> $GITHUB_STEP_SUMMARY + + cat ${TERRAFORM_PLAN_OUTPUT_FILE} exit 1 fi From ea424e5cd246dd86e2066ad3d7ee1515bc006069 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 12:51:11 +0200 Subject: [PATCH 085/123] Plan diff support skip init flag --- action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index c2bd6943..4da8fc26 100644 --- a/action.yml +++ b/action.yml @@ -387,10 +387,10 @@ runs: cp ${GITHUB_ACTION_PATH}/config/atmos_plan_diff_github_summary.md ./atmos_plan_diff_github_summary.md sed -i "s/{{COMPONENT_NAME}}/${{ inputs.component }}/g" ./atmos_plan_diff_github_summary.md sed -i "s/{{STACK_NAME}}/${{ inputs.stack }}/g" ./atmos_plan_diff_github_summary.md - sed -i -e "/{{DIFF}}/ {r ${TERRAFORM_PLAN_OUTPUT_FILE}" -e 'd}' ./atmos_plan_diff_github_summary.md + sed -i -e "/{{DIFF}}/ {r ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE}" -e 'd}' ./atmos_plan_diff_github_summary.md cat ./atmos_plan_diff_github_summary.md >> $GITHUB_STEP_SUMMARY - cat ${TERRAFORM_PLAN_OUTPUT_FILE} + cat ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE} exit 1 fi From 74b44d8a293b553710db20228530a3e4eb140fb1 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 12:56:56 +0200 Subject: [PATCH 086/123] Plan diff support skip init flag --- config/atmos_plan_diff_github_summary.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/atmos_plan_diff_github_summary.md b/config/atmos_plan_diff_github_summary.md index 01e3c982..4425c6e2 100644 --- a/config/atmos_plan_diff_github_summary.md +++ b/config/atmos_plan_diff_github_summary.md @@ -5,6 +5,8 @@
Terraform Plan outdated diff +{{DIFF}} + ``` {{DIFF}} ``` From d0a421566e869d93fed366ec179a16a52a74488f Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 13:10:02 +0200 Subject: [PATCH 087/123] Plan diff support skip init flag --- config/atmos_plan_diff_github_summary.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/config/atmos_plan_diff_github_summary.md b/config/atmos_plan_diff_github_summary.md index 4425c6e2..1c497c28 100644 --- a/config/atmos_plan_diff_github_summary.md +++ b/config/atmos_plan_diff_github_summary.md @@ -1,14 +1,9 @@ ## Plan outdated `{{COMPONENT_NAME}}` in `{{STACK_NAME}}` - [![failed](https://shields.io/badge/PLAN-REPLACE-critical?style=for-the-badge)](#user-content-replace-plat-ue2-sandbox-foobar-plan-diff) + [![failed](https://shields.io/badge/PLAN-OUTDATED-critical?style=for-the-badge)](#user-content-plan-outdated-{{STACK_NAME}}-{{COMPONENT_NAME}}) -
Terraform Plan outdated diff - -{{DIFF}} - -``` +
Terraform Plan outdated diff {{DIFF}} -```
From e92ee3c1cd7036a96e27476d4f2a2292a32e7edf Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 13:25:02 +0200 Subject: [PATCH 088/123] Plan diff support skip init flag --- .github/workflows/integration-tests-plan-diff.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index 95798603..5fc02b9e 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -18,6 +18,7 @@ permissions: jobs: test: runs-on: ubuntu-latest + continue-on-error: true strategy: max-parallel: 1 fail-fast: false # Don't fail fast to avoid locking TF State From 5d4cbcd3c078d0c3042697013c3f92797a659999 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 13:37:34 +0200 Subject: [PATCH 089/123] Plan diff support skip init flag --- .../workflows/integration-tests-plan-diff.yml | 2 +- action.yml | 17 +++++++---------- config/atmos_plan_diff_github_summary.md | 2 +- 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index 5fc02b9e..bded0603 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -71,5 +71,5 @@ jobs: atmos-config-path: ${{ runner.temp }} debug: true env: - TF_VAR_seed: ${{ steps.env.outputs.seed }} + TF_VAR_seed: ${{ steps.env.outputs.seed }}-b \ No newline at end of file diff --git a/action.yml b/action.yml index 4da8fc26..e720df63 100644 --- a/action.yml +++ b/action.yml @@ -384,14 +384,11 @@ runs: echo "plan_changed=false" >> $GITHUB_OUTPUT else echo "plan_changed=true" >> $GITHUB_OUTPUT - cp ${GITHUB_ACTION_PATH}/config/atmos_plan_diff_github_summary.md ./atmos_plan_diff_github_summary.md - sed -i "s/{{COMPONENT_NAME}}/${{ inputs.component }}/g" ./atmos_plan_diff_github_summary.md - sed -i "s/{{STACK_NAME}}/${{ inputs.stack }}/g" ./atmos_plan_diff_github_summary.md - sed -i -e "/{{DIFF}}/ {r ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE}" -e 'd}' ./atmos_plan_diff_github_summary.md - cat ./atmos_plan_diff_github_summary.md >> $GITHUB_STEP_SUMMARY - - cat ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE} - exit 1 + cp ${GITHUB_ACTION_PATH}/config/atmos_plan_diff_github_summary.md ./atmos-apply-summary.md + sed -i "s/{{COMPONENT_NAME}}/${{ inputs.component }}/g" ./atmos-apply-summary.md + sed -i "s/{{STACK_NAME}}/${{ inputs.stack }}/g" ./atmos-apply-summary.md + sed -i -e "/{{DIFF}}/ {r ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE}" -e 'd}' ./atmos-apply-summary.md + cat ./atmos-apply-summary.md >> $GITHUB_STEP_SUMMARY fi - name: Check Whether Infracost is Enabled @@ -511,6 +508,8 @@ runs: sed -i "s#\"\`#\`#g" ${{ github.workspace }}/atmos-apply-summary.md sed -i "s#|--#|:-#g" ${{ github.workspace }}/atmos-apply-summary.md + cat "${{ github.workspace }}/atmos-apply-summary.md" >> $GITHUB_STEP_SUMMARY + if [[ "${TERRAFORM_RESULT}" == "0" ]]; then echo "status=succeeded" >> $GITHUB_OUTPUT echo "Terraform apply executed successfully" @@ -522,8 +521,6 @@ runs: # Link to a job that executed this action echo "[Job](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})" >> "${{ github.workspace }}/atmos-apply-summary.md" - cat "${{ github.workspace }}/atmos-apply-summary.md" >> $GITHUB_STEP_SUMMARY - rm -f ${TERRAFORM_OUTPUT_FILE} exit $TERRAFORM_RESULT diff --git a/config/atmos_plan_diff_github_summary.md b/config/atmos_plan_diff_github_summary.md index 1c497c28..c7e523fc 100644 --- a/config/atmos_plan_diff_github_summary.md +++ b/config/atmos_plan_diff_github_summary.md @@ -1,4 +1,4 @@ -## Plan outdated `{{COMPONENT_NAME}}` in `{{STACK_NAME}}` +## Apply failed `{{COMPONENT_NAME}}` in `{{STACK_NAME}}` [![failed](https://shields.io/badge/PLAN-OUTDATED-critical?style=for-the-badge)](#user-content-plan-outdated-{{STACK_NAME}}-{{COMPONENT_NAME}}) From cde34635a7ed5b29e72fb52abff156faef697910 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 13:45:33 +0200 Subject: [PATCH 090/123] Plan diff support skip init flag --- action.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/action.yml b/action.yml index e720df63..38cf8a42 100644 --- a/action.yml +++ b/action.yml @@ -389,6 +389,8 @@ runs: sed -i "s/{{STACK_NAME}}/${{ inputs.stack }}/g" ./atmos-apply-summary.md sed -i -e "/{{DIFF}}/ {r ${TERRAFORM_PLAN_DIFF_OUTPUT_FILE}" -e 'd}' ./atmos-apply-summary.md cat ./atmos-apply-summary.md >> $GITHUB_STEP_SUMMARY + + exit 1 fi - name: Check Whether Infracost is Enabled From cdbb1bae47324b85b8e895cbff54c8d6f48200c6 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 13:46:47 +0200 Subject: [PATCH 091/123] Plan diff support skip init flag --- config/atmos_plan_diff_github_summary.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/atmos_plan_diff_github_summary.md b/config/atmos_plan_diff_github_summary.md index c7e523fc..024e2cae 100644 --- a/config/atmos_plan_diff_github_summary.md +++ b/config/atmos_plan_diff_github_summary.md @@ -1,7 +1,7 @@ ## Apply failed `{{COMPONENT_NAME}}` in `{{STACK_NAME}}` - [![failed](https://shields.io/badge/PLAN-OUTDATED-critical?style=for-the-badge)](#user-content-plan-outdated-{{STACK_NAME}}-{{COMPONENT_NAME}}) + [![failed](https://shields.io/badge/APPLY-FAILED-critical?style=for-the-badge)](#user-content-plan-outdated-{{STACK_NAME}}-{{COMPONENT_NAME}})
Terraform Plan outdated diff {{DIFF}} From 4af46eec5cb778156e4237e544f4137fda581ca3 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 14:14:40 +0200 Subject: [PATCH 092/123] Plan diff support skip init flag --- ...ntegration-tests-plan-storage-disabled.yml | 61 +++++++++++++++++++ config/atmos_plan_diff_github_summary.md | 2 +- 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/integration-tests-plan-storage-disabled.yml diff --git a/.github/workflows/integration-tests-plan-storage-disabled.yml b/.github/workflows/integration-tests-plan-storage-disabled.yml new file mode 100644 index 00000000..cbd87d9b --- /dev/null +++ b/.github/workflows/integration-tests-plan-storage-disabled.yml @@ -0,0 +1,61 @@ +name: "Integration Tests - Plan Storage disabled" + +on: + workflow_dispatch: {} + + pull_request: + types: [opened, synchronize, reopened] + +env: + AWS_REGION: us-east-2 + + +# Permissions required for assuming AWS identity +permissions: + id-token: write + contents: read + +jobs: + test: + runs-on: ubuntu-latest + strategy: + max-parallel: 1 + fail-fast: false # Don't fail fast to avoid locking TF State + matrix: + platform: [terraform, opentofu] + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + + - shell: bash + id: env + run: | + mkdir -p ${{ runner.temp }} + cp ./tests/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_TABLE__#${{ secrets.TERRAFORM_STATE_TABLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_TABLE__#${{ secrets.TERRAFORM_STATE_TABLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_ROLE__#${{ secrets.TERRAFORM_STATE_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__PLAN_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__APPLY_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + + echo "seed=${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${{ matrix.platform }}" >> $GITHUB_OUTPUT + + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + + - name: Apply Atmos Component + uses: ./ + with: + component: "foobar" + stack: "plat-ue2-sandbox" + atmos-config-path: ${{ runner.temp }} + plan-storage: false + debug: true + env: + TF_VAR_seed: ${{ steps.env.outputs.seed }} + \ No newline at end of file diff --git a/config/atmos_plan_diff_github_summary.md b/config/atmos_plan_diff_github_summary.md index 024e2cae..e8de5d94 100644 --- a/config/atmos_plan_diff_github_summary.md +++ b/config/atmos_plan_diff_github_summary.md @@ -3,7 +3,7 @@ [![failed](https://shields.io/badge/APPLY-FAILED-critical?style=for-the-badge)](#user-content-plan-outdated-{{STACK_NAME}}-{{COMPONENT_NAME}}) -
Terraform Plan outdated diff +
Terraform Plan outdated {{DIFF}}
From 708993d2a1ba34151b652e8c259ddd9621f3a5be Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 14:21:05 +0200 Subject: [PATCH 093/123] Plan diff support skip init flag --- action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index 38cf8a42..fda9ba99 100644 --- a/action.yml +++ b/action.yml @@ -362,12 +362,12 @@ runs: exit 1 fi + cp ${{ steps.vars.outputs.plan_file }} ${{ steps.vars.outputs.renewed_plan_file }} + TERRAFORM_PLAN_DIFF_OUTPUT_FILE="./terraform-${GITHUB_RUN_ID}-plan-diff-output.txt" if [[ "${{ inputs.plan-storage }}" == "true" ]]; then - cp ${{ steps.vars.outputs.plan_file }} ${{ steps.vars.outputs.renewed_plan_file }} - atmos terraform plan-diff ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ -input=false \ From 6a1fa216b2f3842d8d9e45cac955cce86f6084bb Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 15:13:35 +0200 Subject: [PATCH 094/123] Plan diff support skip init flag --- .../integration-tests-plan-storage-disabled.yml | 2 +- .../opentofu/stacks/catalog/foobar-plan-storage.yaml | 11 +++++++++++ .../terraform/stacks/catalog/foobar-plan-storage.yaml | 11 +++++++++++ .../orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml | 1 + 4 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/opentofu/stacks/catalog/foobar-plan-storage.yaml create mode 100644 tests/terraform/stacks/catalog/foobar-plan-storage.yaml diff --git a/.github/workflows/integration-tests-plan-storage-disabled.yml b/.github/workflows/integration-tests-plan-storage-disabled.yml index cbd87d9b..9df5e03e 100644 --- a/.github/workflows/integration-tests-plan-storage-disabled.yml +++ b/.github/workflows/integration-tests-plan-storage-disabled.yml @@ -51,7 +51,7 @@ jobs: - name: Apply Atmos Component uses: ./ with: - component: "foobar" + component: "foobar-plan-storage" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} plan-storage: false diff --git a/tests/opentofu/stacks/catalog/foobar-plan-storage.yaml b/tests/opentofu/stacks/catalog/foobar-plan-storage.yaml new file mode 100644 index 00000000..9bbf84c7 --- /dev/null +++ b/tests/opentofu/stacks/catalog/foobar-plan-storage.yaml @@ -0,0 +1,11 @@ +components: + terraform: + foobar-plan-storage: + metadata: + component: foobar + settings: + github: + actions_enabled: true + vars: + example: blue + enabled: true diff --git a/tests/terraform/stacks/catalog/foobar-plan-storage.yaml b/tests/terraform/stacks/catalog/foobar-plan-storage.yaml new file mode 100644 index 00000000..9bbf84c7 --- /dev/null +++ b/tests/terraform/stacks/catalog/foobar-plan-storage.yaml @@ -0,0 +1,11 @@ +components: + terraform: + foobar-plan-storage: + metadata: + component: foobar + settings: + github: + actions_enabled: true + vars: + example: blue + enabled: true diff --git a/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml index cd038716..83cef821 100644 --- a/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml +++ b/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml @@ -1,6 +1,7 @@ import: - catalog/foobar - catalog/foobar-plan-diff + - catalog/foobar-plan-storage - catalog/foobar-atmos-pro terraform: From 8dbed374e5237d60bdb13bc8153f1af03ff8a744 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 15:20:52 +0200 Subject: [PATCH 095/123] Plan diff support skip init flag --- .../opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml index 910e6d14..1023e57e 100644 --- a/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml +++ b/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml @@ -1,6 +1,7 @@ import: - catalog/foobar - catalog/foobar-plan-diff + - catalog/foobar-plan-storage - catalog/foobar-atmos-pro terraform: From a5d424db36b033b0c95570ffab555b20fd6d505d Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 17:52:22 +0200 Subject: [PATCH 096/123] Plan diff support skip init flag --- .../workflows/integration-tests-plan-fail.yml | 61 +++++++++++++++++++ .../components/terraform/foobar/main.tf | 10 +++ .../components/terraform/foobar/variables.tf | 6 ++ 3 files changed, 77 insertions(+) create mode 100644 .github/workflows/integration-tests-plan-fail.yml diff --git a/.github/workflows/integration-tests-plan-fail.yml b/.github/workflows/integration-tests-plan-fail.yml new file mode 100644 index 00000000..3ff7892c --- /dev/null +++ b/.github/workflows/integration-tests-plan-fail.yml @@ -0,0 +1,61 @@ +name: "Integration Tests - Plan Fail" + +on: + workflow_dispatch: {} + + pull_request: + types: [opened, synchronize, reopened] + +env: + AWS_REGION: us-east-2 + + +# Permissions required for assuming AWS identity +permissions: + id-token: write + contents: read + +jobs: + test: + runs-on: ubuntu-latest + strategy: + max-parallel: 1 + fail-fast: false # Don't fail fast to avoid locking TF State + matrix: + platform: [terraform, opentofu] + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + + - shell: bash + id: env + run: | + mkdir -p ${{ runner.temp }} + cp ./tests/${{ matrix.platform }}/atmos.yaml ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__INFRACOST_ENABLED__#false#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_REGION__#${{ env.AWS_REGION }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_BUCKET__#${{ secrets.TERRAFORM_STATE_BUCKET }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_TABLE__#${{ secrets.TERRAFORM_STATE_TABLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_TABLE__#${{ secrets.TERRAFORM_STATE_TABLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__STORAGE_ROLE__#${{ secrets.TERRAFORM_STATE_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__PLAN_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + sed -i -e 's#__APPLY_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml + + echo "seed=${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${{ matrix.platform }}" >> $GITHUB_OUTPUT + + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.ref }} + + - name: Apply Atmos Component + uses: ./ + with: + component: "foobar-plan-fail" + stack: "plat-ue2-sandbox" + atmos-config-path: ${{ runner.temp }} + plan-storage: false + debug: true + env: + TF_VAR_seed: ${{ steps.env.outputs.seed }} + \ No newline at end of file diff --git a/tests/opentofu/components/terraform/foobar/main.tf b/tests/opentofu/components/terraform/foobar/main.tf index de59eb69..2105549b 100644 --- a/tests/opentofu/components/terraform/foobar/main.tf +++ b/tests/opentofu/components/terraform/foobar/main.tf @@ -5,3 +5,13 @@ resource "random_id" "foo" { } byte_length = 8 } + + +resource "null_resource" "dns_check" { + count = var.fail ? 1 : 0 + + provisioner "local-exec" { + command = "false" + interpreter = ["bash", "-c"] + } +} \ No newline at end of file diff --git a/tests/opentofu/components/terraform/foobar/variables.tf b/tests/opentofu/components/terraform/foobar/variables.tf index becf84e0..a7e9c219 100644 --- a/tests/opentofu/components/terraform/foobar/variables.tf +++ b/tests/opentofu/components/terraform/foobar/variables.tf @@ -8,3 +8,9 @@ variable "seed" { description = "testing variable" default = "seed" } + +variable "fail" { + type = bool + description = "Fail" + default = false +} From 45e0598991431a5573fffb41afa313c1ee6a107c Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 17:58:45 +0200 Subject: [PATCH 097/123] Plan diff support skip init flag --- tests/opentofu/stacks/catalog/foobar-plan-fail.yaml | 12 ++++++++++++ .../orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml | 1 + tests/terraform/stacks/catalog/foobar-plan-fail.yaml | 12 ++++++++++++ .../orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml | 1 + 4 files changed, 26 insertions(+) create mode 100644 tests/opentofu/stacks/catalog/foobar-plan-fail.yaml create mode 100644 tests/terraform/stacks/catalog/foobar-plan-fail.yaml diff --git a/tests/opentofu/stacks/catalog/foobar-plan-fail.yaml b/tests/opentofu/stacks/catalog/foobar-plan-fail.yaml new file mode 100644 index 00000000..f47acdee --- /dev/null +++ b/tests/opentofu/stacks/catalog/foobar-plan-fail.yaml @@ -0,0 +1,12 @@ +components: + terraform: + foobar-plan-fail: + metadata: + component: foobar + settings: + github: + actions_enabled: true + vars: + example: blue + enabled: true + fail: true diff --git a/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml index 1023e57e..5f5e5aba 100644 --- a/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml +++ b/tests/opentofu/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml @@ -2,6 +2,7 @@ import: - catalog/foobar - catalog/foobar-plan-diff - catalog/foobar-plan-storage + - catalog/foobar-plan-fail - catalog/foobar-atmos-pro terraform: diff --git a/tests/terraform/stacks/catalog/foobar-plan-fail.yaml b/tests/terraform/stacks/catalog/foobar-plan-fail.yaml new file mode 100644 index 00000000..f47acdee --- /dev/null +++ b/tests/terraform/stacks/catalog/foobar-plan-fail.yaml @@ -0,0 +1,12 @@ +components: + terraform: + foobar-plan-fail: + metadata: + component: foobar + settings: + github: + actions_enabled: true + vars: + example: blue + enabled: true + fail: true diff --git a/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml b/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml index 83cef821..aedcd1df 100644 --- a/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml +++ b/tests/terraform/stacks/orgs/foo/plat/sandbox/plat-ue2-sandbox.yaml @@ -2,6 +2,7 @@ import: - catalog/foobar - catalog/foobar-plan-diff - catalog/foobar-plan-storage + - catalog/foobar-plan-fail - catalog/foobar-atmos-pro terraform: From 10a337b3e7919f31fcc13a5d6feb4d8b761cbe2d Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 18:30:00 +0200 Subject: [PATCH 098/123] Plan diff support skip init flag --- tests/terraform/components/terraform/foobar/main.tf | 10 ++++++++++ .../terraform/components/terraform/foobar/variables.tf | 10 ++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/terraform/components/terraform/foobar/main.tf b/tests/terraform/components/terraform/foobar/main.tf index de59eb69..2105549b 100644 --- a/tests/terraform/components/terraform/foobar/main.tf +++ b/tests/terraform/components/terraform/foobar/main.tf @@ -5,3 +5,13 @@ resource "random_id" "foo" { } byte_length = 8 } + + +resource "null_resource" "dns_check" { + count = var.fail ? 1 : 0 + + provisioner "local-exec" { + command = "false" + interpreter = ["bash", "-c"] + } +} \ No newline at end of file diff --git a/tests/terraform/components/terraform/foobar/variables.tf b/tests/terraform/components/terraform/foobar/variables.tf index 61afd699..a7e9c219 100644 --- a/tests/terraform/components/terraform/foobar/variables.tf +++ b/tests/terraform/components/terraform/foobar/variables.tf @@ -6,5 +6,11 @@ variable "example" { variable "seed" { type = string description = "testing variable" - default = "default" -} \ No newline at end of file + default = "seed" +} + +variable "fail" { + type = bool + description = "Fail" + default = false +} From d0fd8c8f1d7b5bed8d8e9b007f3d866527f5cbcc Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 18:37:06 +0200 Subject: [PATCH 099/123] Plan diff support skip init flag --- action.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/action.yml b/action.yml index fda9ba99..4be63a42 100644 --- a/action.yml +++ b/action.yml @@ -357,6 +357,8 @@ runs: PLAN_CHANGED=$? + cat ${TERRAFORM_PLAN_OUTPUT_FILE} + if [[ "${PLAN_CHANGED}" != "0" ]]; then echo "PLAN FAILED" >> $GITHUB_STEP_SUMMARY exit 1 From df4c5f48144922a9720c04e14786808caea39686 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 18:46:42 +0200 Subject: [PATCH 100/123] Plan diff support skip init flag --- tests/opentofu/components/terraform/foobar/main.tf | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/opentofu/components/terraform/foobar/main.tf b/tests/opentofu/components/terraform/foobar/main.tf index 2105549b..d824f549 100644 --- a/tests/opentofu/components/terraform/foobar/main.tf +++ b/tests/opentofu/components/terraform/foobar/main.tf @@ -7,11 +7,9 @@ resource "random_id" "foo" { } -resource "null_resource" "dns_check" { +resource "null_resource" "default" { count = var.fail ? 1 : 0 - - provisioner "local-exec" { - command = "false" - interpreter = ["bash", "-c"] + triggers = { + test = random_id.foo["test"] } } \ No newline at end of file From 18446eba50f0ed2c88519cd95e6d4e489d5e28e4 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 19:09:53 +0200 Subject: [PATCH 101/123] Plan diff support skip init flag --- action.yml | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/action.yml b/action.yml index 4be63a42..69806307 100644 --- a/action.yml +++ b/action.yml @@ -349,18 +349,36 @@ runs: TERRAFORM_PLAN_OUTPUT_FILE="./terraform-${GITHUB_RUN_ID}-plan-output.txt" - atmos terraform plan ${{ inputs.component }} \ - --stack ${{ inputs.stack }} \ - -input=false \ - -no-color \ + tfcmt \ + --config "${GITHUB_ACTION_PATH}/config/atmos_github_summary.yaml" \ + -var "target:${{ inputs.stack }}-${{ inputs.component }}" \ + -var "component:${{ inputs.component }}" \ + -var "stack:${{ inputs.stack }}" \ + -var "job:${{ github.job }}" \ + -var "logoImage:${{ inputs.branding-logo-image }}" \ + -var "logoUrl:${{ inputs.branding-logo-url }}" \ + --output "${{ github.workspace }}/atmos-apply-summary.md" \ + --log-level $([[ "${{ inputs.debug }}" == "true" ]] && echo "DEBUG" || echo "INFO") \ + plan -- \ + atmos terraform plan ${{ inputs.component }} \ + --stack ${{ inputs.stack }} \ + -input=false \ + -no-color \ &> ${TERRAFORM_PLAN_OUTPUT_FILE} + # atmos terraform plan ${{ inputs.component }} \ + # --stack ${{ inputs.stack }} \ + # -input=false \ + # -no-color \ + # &> ${TERRAFORM_PLAN_OUTPUT_FILE} + PLAN_CHANGED=$? cat ${TERRAFORM_PLAN_OUTPUT_FILE} if [[ "${PLAN_CHANGED}" != "0" ]]; then echo "PLAN FAILED" >> $GITHUB_STEP_SUMMARY + cat ./atmos-apply-summary.md >> $GITHUB_STEP_SUMMARY exit 1 fi From e7f46bebb94100cba3a3c01870c5b37530adb41b Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 19:15:37 +0200 Subject: [PATCH 102/123] Plan diff support skip init flag --- .../terraform/foobar-fail/context.tf | 279 ++++++++++++++++++ .../components/terraform/foobar-fail/main.tf | 15 + .../terraform/foobar-fail/outputs.tf | 21 ++ .../terraform/foobar-fail/variables.tf | 16 + .../components/terraform/foobar/main.tf | 8 +- .../components/terraform/foobar/outputs.tf | 2 +- .../components/terraform/foobar/variables.tf | 6 - .../stacks/catalog/foobar-plan-fail.yaml | 2 +- .../terraform/foobar-fail/context.tf | 279 ++++++++++++++++++ .../components/terraform/foobar-fail/main.tf | 15 + .../terraform/foobar-fail/outputs.tf | 21 ++ .../terraform/foobar-fail/variables.tf | 16 + .../components/terraform/foobar/variables.tf | 6 - .../stacks/catalog/foobar-plan-fail.yaml | 2 +- 14 files changed, 670 insertions(+), 18 deletions(-) create mode 100644 tests/opentofu/components/terraform/foobar-fail/context.tf create mode 100644 tests/opentofu/components/terraform/foobar-fail/main.tf create mode 100644 tests/opentofu/components/terraform/foobar-fail/outputs.tf create mode 100644 tests/opentofu/components/terraform/foobar-fail/variables.tf create mode 100644 tests/terraform/components/terraform/foobar-fail/context.tf create mode 100644 tests/terraform/components/terraform/foobar-fail/main.tf create mode 100644 tests/terraform/components/terraform/foobar-fail/outputs.tf create mode 100644 tests/terraform/components/terraform/foobar-fail/variables.tf diff --git a/tests/opentofu/components/terraform/foobar-fail/context.tf b/tests/opentofu/components/terraform/foobar-fail/context.tf new file mode 100644 index 00000000..5e0ef885 --- /dev/null +++ b/tests/opentofu/components/terraform/foobar-fail/context.tf @@ -0,0 +1,279 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "cloudposse/label/null" + version = "0.25.0" # requires Terraform >= 0.13.0 + + enabled = var.enabled + namespace = var.namespace + tenant = var.tenant + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + label_key_case = var.label_key_case + label_value_case = var.label_value_case + descriptor_formats = var.descriptor_formats + labels_as_tags = var.labels_as_tags + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = any + default = { + enabled = true + namespace = null + tenant = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + label_key_case = null + label_value_case = null + descriptor_formats = {} + # Note: we have to use [] instead of null for unset lists due to + # https://github.com/hashicorp/terraform/issues/28137 + # which was not fixed until Terraform 1.0.0, + # but we want the default to be all the labels in `label_order` + # and we want users to be able to prevent all tag generation + # by setting `labels_as_tags` to `[]`, so we need + # a different sentinel to indicate "default" + labels_as_tags = ["unset"] + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT + + validation { + condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`." + } + + validation { + condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" +} + +variable "tenant" { + type = string + default = null + description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" +} + +variable "environment" { + type = string + default = null + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = <<-EOT + ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. + This is the only ID element not also included as a `tag`. + The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. + EOT +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between ID elements. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = <<-EOT + ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, + in the order they appear in the list. New attributes are appended to the + end of the list. The elements of the list are joined by the `delimiter` + and treated as a single ID element. + EOT +} + +variable "labels_as_tags" { + type = set(string) + default = ["default"] + description = <<-EOT + Set of labels (ID elements) to include as tags in the `tags` output. + Default is to include all labels. + Tags with empty values will not be included in the `tags` output. + Set to `[]` to suppress all generated tags. + **Notes:** + The value of the `name` tag, if included, will be the `id`, not the `name`. + Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be + changed in later chained modules. Attempts to change it will be silently ignored. + EOT +} + +variable "tags" { + type = map(string) + default = {} + description = <<-EOT + Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). + Neither the tag keys nor the tag values will be modified by this module. + EOT +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = <<-EOT + Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. + This is for some rare cases where resources want additional configuration of tags + and therefore take a list of maps with tag key, value, and additional configuration. + EOT +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The order in which the labels (ID elements) appear in the `id`. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Terraform regular expression (regex) string. + Characters matching the regex will be removed from the ID elements. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters (minimum 6). + Set to `0` for unlimited length. + Set to `null` for keep the existing setting, which defaults to `0`. + Does not affect `id_full`. + EOT + validation { + condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 + error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." + } +} + +variable "label_key_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of the `tags` keys (label names) for tags generated by this module. + Does not affect keys of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper`. + Default value: `title`. + EOT + + validation { + condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) + error_message = "Allowed values: `lower`, `title`, `upper`." + } +} + +variable "label_value_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of ID elements (labels) as included in `id`, + set as tag values, and output by this module individually. + Does not affect values of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. + Default value: `lower`. + EOT + + validation { + condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "descriptor_formats" { + type = any + default = {} + description = <<-EOT + Describe additional descriptors to be output in the `descriptors` output map. + Map of maps. Keys are names of descriptors. Values are maps of the form + `{ + format = string + labels = list(string) + }` + (Type is `any` so the map values can later be enhanced to provide additional options.) + `format` is a Terraform format string to be passed to the `format()` function. + `labels` is a list of labels, in order, to pass to `format()` function. + Label values will be normalized before being passed to `format()` so they will be + identical to how they appear in `id`. + Default is `{}` (`descriptors` output will be empty). + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/tests/opentofu/components/terraform/foobar-fail/main.tf b/tests/opentofu/components/terraform/foobar-fail/main.tf new file mode 100644 index 00000000..d824f549 --- /dev/null +++ b/tests/opentofu/components/terraform/foobar-fail/main.tf @@ -0,0 +1,15 @@ +resource "random_id" "foo" { + keepers = { + # Generate a new id each time we switch to a new seed + seed = "${module.this.id}-${var.example}-${var.seed}" + } + byte_length = 8 +} + + +resource "null_resource" "default" { + count = var.fail ? 1 : 0 + triggers = { + test = random_id.foo["test"] + } +} \ No newline at end of file diff --git a/tests/opentofu/components/terraform/foobar-fail/outputs.tf b/tests/opentofu/components/terraform/foobar-fail/outputs.tf new file mode 100644 index 00000000..055f02d5 --- /dev/null +++ b/tests/opentofu/components/terraform/foobar-fail/outputs.tf @@ -0,0 +1,21 @@ +output "result" { + description = "Test description output" + value = random_id.foo.id +} + +output "sensitive_value" { + description = "Test sensitive description output" + value = random_id.foo.id + sensitive = true +} + + +output "structured_value" { + description = "Test structured output" + value = { + test = "test" + value = { + result = random_id.foo.id + } + } +} \ No newline at end of file diff --git a/tests/opentofu/components/terraform/foobar-fail/variables.tf b/tests/opentofu/components/terraform/foobar-fail/variables.tf new file mode 100644 index 00000000..a7e9c219 --- /dev/null +++ b/tests/opentofu/components/terraform/foobar-fail/variables.tf @@ -0,0 +1,16 @@ +variable "example" { + type = string + description = "testing variable" +} + +variable "seed" { + type = string + description = "testing variable" + default = "seed" +} + +variable "fail" { + type = bool + description = "Fail" + default = false +} diff --git a/tests/opentofu/components/terraform/foobar/main.tf b/tests/opentofu/components/terraform/foobar/main.tf index d824f549..2105549b 100644 --- a/tests/opentofu/components/terraform/foobar/main.tf +++ b/tests/opentofu/components/terraform/foobar/main.tf @@ -7,9 +7,11 @@ resource "random_id" "foo" { } -resource "null_resource" "default" { +resource "null_resource" "dns_check" { count = var.fail ? 1 : 0 - triggers = { - test = random_id.foo["test"] + + provisioner "local-exec" { + command = "false" + interpreter = ["bash", "-c"] } } \ No newline at end of file diff --git a/tests/opentofu/components/terraform/foobar/outputs.tf b/tests/opentofu/components/terraform/foobar/outputs.tf index 055f02d5..7177f0bd 100644 --- a/tests/opentofu/components/terraform/foobar/outputs.tf +++ b/tests/opentofu/components/terraform/foobar/outputs.tf @@ -18,4 +18,4 @@ output "structured_value" { result = random_id.foo.id } } -} \ No newline at end of file +} diff --git a/tests/opentofu/components/terraform/foobar/variables.tf b/tests/opentofu/components/terraform/foobar/variables.tf index a7e9c219..becf84e0 100644 --- a/tests/opentofu/components/terraform/foobar/variables.tf +++ b/tests/opentofu/components/terraform/foobar/variables.tf @@ -8,9 +8,3 @@ variable "seed" { description = "testing variable" default = "seed" } - -variable "fail" { - type = bool - description = "Fail" - default = false -} diff --git a/tests/opentofu/stacks/catalog/foobar-plan-fail.yaml b/tests/opentofu/stacks/catalog/foobar-plan-fail.yaml index f47acdee..26d5304e 100644 --- a/tests/opentofu/stacks/catalog/foobar-plan-fail.yaml +++ b/tests/opentofu/stacks/catalog/foobar-plan-fail.yaml @@ -2,7 +2,7 @@ components: terraform: foobar-plan-fail: metadata: - component: foobar + component: foobar-fail settings: github: actions_enabled: true diff --git a/tests/terraform/components/terraform/foobar-fail/context.tf b/tests/terraform/components/terraform/foobar-fail/context.tf new file mode 100644 index 00000000..5e0ef885 --- /dev/null +++ b/tests/terraform/components/terraform/foobar-fail/context.tf @@ -0,0 +1,279 @@ +# +# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label +# All other instances of this file should be a copy of that one +# +# +# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf +# and then place it in your Terraform module to automatically get +# Cloud Posse's standard configuration inputs suitable for passing +# to Cloud Posse modules. +# +# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf +# +# Modules should access the whole context as `module.this.context` +# to get the input variables with nulls for defaults, +# for example `context = module.this.context`, +# and access individual variables as `module.this.`, +# with final values filled in. +# +# For example, when using defaults, `module.this.context.delimiter` +# will be null, and `module.this.delimiter` will be `-` (hyphen). +# + +module "this" { + source = "cloudposse/label/null" + version = "0.25.0" # requires Terraform >= 0.13.0 + + enabled = var.enabled + namespace = var.namespace + tenant = var.tenant + environment = var.environment + stage = var.stage + name = var.name + delimiter = var.delimiter + attributes = var.attributes + tags = var.tags + additional_tag_map = var.additional_tag_map + label_order = var.label_order + regex_replace_chars = var.regex_replace_chars + id_length_limit = var.id_length_limit + label_key_case = var.label_key_case + label_value_case = var.label_value_case + descriptor_formats = var.descriptor_formats + labels_as_tags = var.labels_as_tags + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = any + default = { + enabled = true + namespace = null + tenant = null + environment = null + stage = null + name = null + delimiter = null + attributes = [] + tags = {} + additional_tag_map = {} + regex_replace_chars = null + label_order = [] + id_length_limit = null + label_key_case = null + label_value_case = null + descriptor_formats = {} + # Note: we have to use [] instead of null for unset lists due to + # https://github.com/hashicorp/terraform/issues/28137 + # which was not fixed until Terraform 1.0.0, + # but we want the default to be all the labels in `label_order` + # and we want users to be able to prevent all tag generation + # by setting `labels_as_tags` to `[]`, so we need + # a different sentinel to indicate "default" + labels_as_tags = ["unset"] + } + description = <<-EOT + Single object for setting entire context at once. + See description of individual variables for details. + Leave string and numeric variables as `null` to use default value. + Individual variable settings (non-null) override settings in context object, + except for attributes, tags, and additional_tag_map, which are merged. + EOT + + validation { + condition = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`." + } + + validation { + condition = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"]) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "enabled" { + type = bool + default = null + description = "Set to false to prevent the module from creating any resources" +} + +variable "namespace" { + type = string + default = null + description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique" +} + +variable "tenant" { + type = string + default = null + description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for" +} + +variable "environment" { + type = string + default = null + description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = <<-EOT + ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'. + This is the only ID element not also included as a `tag`. + The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. + EOT +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between ID elements. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = <<-EOT + ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`, + in the order they appear in the list. New attributes are appended to the + end of the list. The elements of the list are joined by the `delimiter` + and treated as a single ID element. + EOT +} + +variable "labels_as_tags" { + type = set(string) + default = ["default"] + description = <<-EOT + Set of labels (ID elements) to include as tags in the `tags` output. + Default is to include all labels. + Tags with empty values will not be included in the `tags` output. + Set to `[]` to suppress all generated tags. + **Notes:** + The value of the `name` tag, if included, will be the `id`, not the `name`. + Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be + changed in later chained modules. Attempts to change it will be silently ignored. + EOT +} + +variable "tags" { + type = map(string) + default = {} + description = <<-EOT + Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`). + Neither the tag keys nor the tag values will be modified by this module. + EOT +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = <<-EOT + Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`. + This is for some rare cases where resources want additional configuration of tags + and therefore take a list of maps with tag key, value, and additional configuration. + EOT +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The order in which the labels (ID elements) appear in the `id`. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Terraform regular expression (regex) string. + Characters matching the regex will be removed from the ID elements. + If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. + EOT +} + +variable "id_length_limit" { + type = number + default = null + description = <<-EOT + Limit `id` to this many characters (minimum 6). + Set to `0` for unlimited length. + Set to `null` for keep the existing setting, which defaults to `0`. + Does not affect `id_full`. + EOT + validation { + condition = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0 + error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length." + } +} + +variable "label_key_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of the `tags` keys (label names) for tags generated by this module. + Does not affect keys of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper`. + Default value: `title`. + EOT + + validation { + condition = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case) + error_message = "Allowed values: `lower`, `title`, `upper`." + } +} + +variable "label_value_case" { + type = string + default = null + description = <<-EOT + Controls the letter case of ID elements (labels) as included in `id`, + set as tag values, and output by this module individually. + Does not affect values of tags passed in via the `tags` input. + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs. + Default value: `lower`. + EOT + + validation { + condition = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case) + error_message = "Allowed values: `lower`, `title`, `upper`, `none`." + } +} + +variable "descriptor_formats" { + type = any + default = {} + description = <<-EOT + Describe additional descriptors to be output in the `descriptors` output map. + Map of maps. Keys are names of descriptors. Values are maps of the form + `{ + format = string + labels = list(string) + }` + (Type is `any` so the map values can later be enhanced to provide additional options.) + `format` is a Terraform format string to be passed to the `format()` function. + `labels` is a list of labels, in order, to pass to `format()` function. + Label values will be normalized before being passed to `format()` so they will be + identical to how they appear in `id`. + Default is `{}` (`descriptors` output will be empty). + EOT +} + +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/tests/terraform/components/terraform/foobar-fail/main.tf b/tests/terraform/components/terraform/foobar-fail/main.tf new file mode 100644 index 00000000..d824f549 --- /dev/null +++ b/tests/terraform/components/terraform/foobar-fail/main.tf @@ -0,0 +1,15 @@ +resource "random_id" "foo" { + keepers = { + # Generate a new id each time we switch to a new seed + seed = "${module.this.id}-${var.example}-${var.seed}" + } + byte_length = 8 +} + + +resource "null_resource" "default" { + count = var.fail ? 1 : 0 + triggers = { + test = random_id.foo["test"] + } +} \ No newline at end of file diff --git a/tests/terraform/components/terraform/foobar-fail/outputs.tf b/tests/terraform/components/terraform/foobar-fail/outputs.tf new file mode 100644 index 00000000..055f02d5 --- /dev/null +++ b/tests/terraform/components/terraform/foobar-fail/outputs.tf @@ -0,0 +1,21 @@ +output "result" { + description = "Test description output" + value = random_id.foo.id +} + +output "sensitive_value" { + description = "Test sensitive description output" + value = random_id.foo.id + sensitive = true +} + + +output "structured_value" { + description = "Test structured output" + value = { + test = "test" + value = { + result = random_id.foo.id + } + } +} \ No newline at end of file diff --git a/tests/terraform/components/terraform/foobar-fail/variables.tf b/tests/terraform/components/terraform/foobar-fail/variables.tf new file mode 100644 index 00000000..a7e9c219 --- /dev/null +++ b/tests/terraform/components/terraform/foobar-fail/variables.tf @@ -0,0 +1,16 @@ +variable "example" { + type = string + description = "testing variable" +} + +variable "seed" { + type = string + description = "testing variable" + default = "seed" +} + +variable "fail" { + type = bool + description = "Fail" + default = false +} diff --git a/tests/terraform/components/terraform/foobar/variables.tf b/tests/terraform/components/terraform/foobar/variables.tf index a7e9c219..becf84e0 100644 --- a/tests/terraform/components/terraform/foobar/variables.tf +++ b/tests/terraform/components/terraform/foobar/variables.tf @@ -8,9 +8,3 @@ variable "seed" { description = "testing variable" default = "seed" } - -variable "fail" { - type = bool - description = "Fail" - default = false -} diff --git a/tests/terraform/stacks/catalog/foobar-plan-fail.yaml b/tests/terraform/stacks/catalog/foobar-plan-fail.yaml index f47acdee..26d5304e 100644 --- a/tests/terraform/stacks/catalog/foobar-plan-fail.yaml +++ b/tests/terraform/stacks/catalog/foobar-plan-fail.yaml @@ -2,7 +2,7 @@ components: terraform: foobar-plan-fail: metadata: - component: foobar + component: foobar-fail settings: github: actions_enabled: true From 431ed61b1ba1e022a181f204a1ed62b2f712f59f Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 19:18:57 +0200 Subject: [PATCH 103/123] Plan diff support skip init flag --- tests/opentofu/components/terraform/foobar/variables.tf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/opentofu/components/terraform/foobar/variables.tf b/tests/opentofu/components/terraform/foobar/variables.tf index becf84e0..a7e9c219 100644 --- a/tests/opentofu/components/terraform/foobar/variables.tf +++ b/tests/opentofu/components/terraform/foobar/variables.tf @@ -8,3 +8,9 @@ variable "seed" { description = "testing variable" default = "seed" } + +variable "fail" { + type = bool + description = "Fail" + default = false +} From 8c970cd351b51ab5856150c4e13263c9a6d3d712 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 19:21:14 +0200 Subject: [PATCH 104/123] Plan diff support skip init flag --- tests/terraform/components/terraform/foobar/variables.tf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/terraform/components/terraform/foobar/variables.tf b/tests/terraform/components/terraform/foobar/variables.tf index becf84e0..a7e9c219 100644 --- a/tests/terraform/components/terraform/foobar/variables.tf +++ b/tests/terraform/components/terraform/foobar/variables.tf @@ -8,3 +8,9 @@ variable "seed" { description = "testing variable" default = "seed" } + +variable "fail" { + type = bool + description = "Fail" + default = false +} From 438921d64223c48fdc8901bd2a2f992ace65bdce Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 19:25:34 +0200 Subject: [PATCH 105/123] Plan diff support skip init flag --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 69806307..000909ea 100644 --- a/action.yml +++ b/action.yml @@ -359,7 +359,7 @@ runs: -var "logoUrl:${{ inputs.branding-logo-url }}" \ --output "${{ github.workspace }}/atmos-apply-summary.md" \ --log-level $([[ "${{ inputs.debug }}" == "true" ]] && echo "DEBUG" || echo "INFO") \ - plan -- \ + apply -- \ atmos terraform plan ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ -input=false \ From d8ce095fe2229c9887550e0782e8dd534f453632 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 19:31:11 +0200 Subject: [PATCH 106/123] Plan diff support skip init flag --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 000909ea..916b718a 100644 --- a/action.yml +++ b/action.yml @@ -378,7 +378,7 @@ runs: if [[ "${PLAN_CHANGED}" != "0" ]]; then echo "PLAN FAILED" >> $GITHUB_STEP_SUMMARY - cat ./atmos-apply-summary.md >> $GITHUB_STEP_SUMMARY + cat ./atmos-apply-summary.md >> $GITHUB_STEP_SUMMARY exit 1 fi From 3d052c932bfaac8e6faefeab12e6d96c1864e280 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 19:36:46 +0200 Subject: [PATCH 107/123] Plan diff support skip init flag --- action.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/action.yml b/action.yml index 916b718a..e474e897 100644 --- a/action.yml +++ b/action.yml @@ -357,6 +357,8 @@ runs: -var "job:${{ github.job }}" \ -var "logoImage:${{ inputs.branding-logo-image }}" \ -var "logoUrl:${{ inputs.branding-logo-url }}" \ + -var "infracost_details_diff_breakdown:" \ + -var "infracost_total_monthly_cost:0" \ --output "${{ github.workspace }}/atmos-apply-summary.md" \ --log-level $([[ "${{ inputs.debug }}" == "true" ]] && echo "DEBUG" || echo "INFO") \ apply -- \ From 1839ef3f33eeb0580ef50bfd2caa12206bbcb21c Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 19:58:26 +0200 Subject: [PATCH 108/123] Plan diff support skip init flag --- .github/workflows/integration-tests-plan-diff.yml | 2 +- config/atmos_github_summary.yaml | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/integration-tests-plan-diff.yml index bded0603..88704fe7 100644 --- a/.github/workflows/integration-tests-plan-diff.yml +++ b/.github/workflows/integration-tests-plan-diff.yml @@ -1,4 +1,4 @@ -name: "Integration Tests - Plan failed" +name: "Integration Tests - Plan diff" on: workflow_dispatch: {} diff --git a/config/atmos_github_summary.yaml b/config/atmos_github_summary.yaml index 368746e5..ba7ac766 100644 --- a/config/atmos_github_summary.yaml +++ b/config/atmos_github_summary.yaml @@ -26,7 +26,12 @@ templates: {{ end }} result: | + {{- if eq .ExitCode 0 }}
{{if .Result}}{{ .Result }}{{end}} + {{- end }} + {{- if eq .ExitCode 1 }} +
:warning: Error summary + {{- end }}
To reproduce this locally, run:

@@ -60,6 +65,7 @@ templates: {{- end }} terraform: apply: + disable_label: false template: | {{template "apply_title" .}} {{template "branding" .}} From 57da58b34e1dbdacb2701464748da1582878b4ae Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 20:04:22 +0200 Subject: [PATCH 109/123] Plan diff support skip init flag --- action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/action.yml b/action.yml index e474e897..dbdce656 100644 --- a/action.yml +++ b/action.yml @@ -359,7 +359,7 @@ runs: -var "logoUrl:${{ inputs.branding-logo-url }}" \ -var "infracost_details_diff_breakdown:" \ -var "infracost_total_monthly_cost:0" \ - --output "${{ github.workspace }}/atmos-apply-summary.md" \ + --output "${{ github.workspace }}/atmos-plan-summary.md" \ --log-level $([[ "${{ inputs.debug }}" == "true" ]] && echo "DEBUG" || echo "INFO") \ apply -- \ atmos terraform plan ${{ inputs.component }} \ @@ -379,7 +379,7 @@ runs: cat ${TERRAFORM_PLAN_OUTPUT_FILE} if [[ "${PLAN_CHANGED}" != "0" ]]; then - echo "PLAN FAILED" >> $GITHUB_STEP_SUMMARY + mv ${{ github.workspace }}/atmos-plan-summary.md ${{ github.workspace }}/atmos-apply-summary.md cat ./atmos-apply-summary.md >> $GITHUB_STEP_SUMMARY exit 1 fi From 5e4805c2505cf252df9e5f3a2c96bf0972bf2413 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 22:41:03 +0200 Subject: [PATCH 110/123] Plan diff support skip init flag --- action.yml | 4 +- config/atmos_plan_summary.yaml | 68 ++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 config/atmos_plan_summary.yaml diff --git a/action.yml b/action.yml index dbdce656..eb4f9bc0 100644 --- a/action.yml +++ b/action.yml @@ -350,7 +350,7 @@ runs: TERRAFORM_PLAN_OUTPUT_FILE="./terraform-${GITHUB_RUN_ID}-plan-output.txt" tfcmt \ - --config "${GITHUB_ACTION_PATH}/config/atmos_github_summary.yaml" \ + --config "${GITHUB_ACTION_PATH}/config/atmos_plan_summary.yaml" \ -var "target:${{ inputs.stack }}-${{ inputs.component }}" \ -var "component:${{ inputs.component }}" \ -var "stack:${{ inputs.stack }}" \ @@ -361,7 +361,7 @@ runs: -var "infracost_total_monthly_cost:0" \ --output "${{ github.workspace }}/atmos-plan-summary.md" \ --log-level $([[ "${{ inputs.debug }}" == "true" ]] && echo "DEBUG" || echo "INFO") \ - apply -- \ + plan -- \ atmos terraform plan ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ -input=false \ diff --git a/config/atmos_plan_summary.yaml b/config/atmos_plan_summary.yaml new file mode 100644 index 00000000..04809901 --- /dev/null +++ b/config/atmos_plan_summary.yaml @@ -0,0 +1,68 @@ +# tfcmt Configuration used for posting Terraform GitHub Summaries +# https://suzuki-shunsuke.github.io/tfcmt/config +embedded_var_names: [] +ci: + pr: [] + owner: [] + repo: [] + sha: [] + link: [] + vars: {} +templates: + title: | + {{ if eq .ExitCode 1}} + ## Apply Failed for `{{.Vars.component}}` in `{{.Vars.stack}}` + {{ end }} + {{- if eq .ExitCode 0}} + ## Apply Succeeded for `{{.Vars.component}}` in `{{.Vars.stack}}` + {{ end }} + + badge: | + {{ if eq .ExitCode 1}} + [![apply](https://shields.io/badge/APPLY-FAILED-critical?style=for-the-badge)](#user-content-apply-{{.Vars.stack}}-{{.Vars.component}}) + {{ end }} + {{- if eq .ExitCode 0}} + [![apply](https://shields.io/badge/APPLY-SUCCESS-success?style=for-the-badge)](#user-content-apply-{{.Vars.stack}}-{{.Vars.component}}) + {{ end }} + + result: | + {{- if eq .ExitCode 0 }} +
{{if .Result}}{{ .Result }}{{end}} + {{- end }} + {{- if eq .ExitCode 1 }} +
:warning: Error summary + {{- end }} + +
+ To reproduce this locally, run:

+ + ```shell + atmos terraform plan {{.Vars.component}} -s {{.Vars.stack}} + ``` + + {{wrapCode .CombinedOutput}} +
+ + branding: | + {{- if ne .Vars.logoImage "" }} + + {{- end }} +terraform: + apply: + disable_label: false + template: | + {{template "title" .}} + {{template "branding" .}} + {{template "badge" .}} + {{template "result" .}} + + +
+ + when_parse_error: + template: | + {{template "title" .}} + +
Result + {{wrapCode .CombinedOutput}} +
From 200afd875b262a9e55fcf284939231ad02dbfa7d Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 22:48:53 +0200 Subject: [PATCH 111/123] Plan diff support skip init flag --- action.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/action.yml b/action.yml index eb4f9bc0..0ebfe7a0 100644 --- a/action.yml +++ b/action.yml @@ -357,11 +357,9 @@ runs: -var "job:${{ github.job }}" \ -var "logoImage:${{ inputs.branding-logo-image }}" \ -var "logoUrl:${{ inputs.branding-logo-url }}" \ - -var "infracost_details_diff_breakdown:" \ - -var "infracost_total_monthly_cost:0" \ --output "${{ github.workspace }}/atmos-plan-summary.md" \ --log-level $([[ "${{ inputs.debug }}" == "true" ]] && echo "DEBUG" || echo "INFO") \ - plan -- \ + apply -- \ atmos terraform plan ${{ inputs.component }} \ --stack ${{ inputs.stack }} \ -input=false \ From f00974831b18014424f763c213cdf514a9215c31 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 23:04:24 +0200 Subject: [PATCH 112/123] Plan diff support skip init flag --- .github/workflows/integration-tests-plan-fail.yml | 1 + config/atmos_plan_summary.yaml | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/integration-tests-plan-fail.yml b/.github/workflows/integration-tests-plan-fail.yml index 3ff7892c..9d5d3473 100644 --- a/.github/workflows/integration-tests-plan-fail.yml +++ b/.github/workflows/integration-tests-plan-fail.yml @@ -18,6 +18,7 @@ permissions: jobs: test: runs-on: ubuntu-latest + continue-on-error: true strategy: max-parallel: 1 fail-fast: false # Don't fail fast to avoid locking TF State diff --git a/config/atmos_plan_summary.yaml b/config/atmos_plan_summary.yaml index 04809901..68aa971a 100644 --- a/config/atmos_plan_summary.yaml +++ b/config/atmos_plan_summary.yaml @@ -56,7 +56,6 @@ terraform: {{template "badge" .}} {{template "result" .}} -
when_parse_error: From 137053b222a3704a7abd2efe529060b29287b354 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 23:11:16 +0200 Subject: [PATCH 113/123] Plan diff support skip init flag --- action.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/action.yml b/action.yml index 0ebfe7a0..982923fa 100644 --- a/action.yml +++ b/action.yml @@ -366,12 +366,6 @@ runs: -no-color \ &> ${TERRAFORM_PLAN_OUTPUT_FILE} - # atmos terraform plan ${{ inputs.component }} \ - # --stack ${{ inputs.stack }} \ - # -input=false \ - # -no-color \ - # &> ${TERRAFORM_PLAN_OUTPUT_FILE} - PLAN_CHANGED=$? cat ${TERRAFORM_PLAN_OUTPUT_FILE} From 0cf27851ab5aab1359e103841c3b7c47b8382d72 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 23:23:33 +0200 Subject: [PATCH 114/123] Plan diff support skip init flag --- .github/workflows/integration-test-atmos-pro.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/integration-test-atmos-pro.yml b/.github/workflows/integration-test-atmos-pro.yml index c08bd28d..cbe5a275 100644 --- a/.github/workflows/integration-test-atmos-pro.yml +++ b/.github/workflows/integration-test-atmos-pro.yml @@ -32,6 +32,7 @@ jobs: ref: ${{ github.event.pull_request.head.ref }} - name: Setup Atmos Test Config + id: env shell: bash run: | mkdir -p ${{ runner.temp }} From 6201877ba7597f1a79dbc2f5c4f03c8be851c1eb Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sat, 9 Aug 2025 23:56:06 +0200 Subject: [PATCH 115/123] Plan diff support skip init flag --- ...gration-test-atmos-pro.yml => test_atmos_pro.yml} | 0 .../{integration-tests.yml => tests_basic.yml} | 12 +++++++++--- ...ation-tests-plan-diff.yml => tests_plan_diff.yml} | 0 ...ation-tests-plan-fail.yml => tests_plan_fail.yml} | 0 ...-disabled.yml => tests_plan_storage_disabled.yml} | 0 5 files changed, 9 insertions(+), 3 deletions(-) rename .github/workflows/{integration-test-atmos-pro.yml => test_atmos_pro.yml} (100%) rename .github/workflows/{integration-tests.yml => tests_basic.yml} (89%) rename .github/workflows/{integration-tests-plan-diff.yml => tests_plan_diff.yml} (100%) rename .github/workflows/{integration-tests-plan-fail.yml => tests_plan_fail.yml} (100%) rename .github/workflows/{integration-tests-plan-storage-disabled.yml => tests_plan_storage_disabled.yml} (100%) diff --git a/.github/workflows/integration-test-atmos-pro.yml b/.github/workflows/test_atmos_pro.yml similarity index 100% rename from .github/workflows/integration-test-atmos-pro.yml rename to .github/workflows/test_atmos_pro.yml diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/tests_basic.yml similarity index 89% rename from .github/workflows/integration-tests.yml rename to .github/workflows/tests_basic.yml index bfdfcdbc..33654ffe 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/tests_basic.yml @@ -1,7 +1,12 @@ name: "Integration Tests" on: - workflow_dispatch: {} + workflow_dispatch: + inputs: + ref: + description: "The fully-formed ref of the branch or tag that triggered the workflow run" + required: false + type: string pull_request: types: [opened, synchronize, reopened] @@ -26,7 +31,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.ref }} + ref: ${{ inputs.ref }} - shell: bash id: env @@ -57,7 +62,7 @@ jobs: - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.ref }} + ref: ${{ inputs.ref }} - name: Wait 60 sec to wait s3 bucket would be consistent (read after write consistency) shell: bash @@ -71,6 +76,7 @@ jobs: stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} debug: true + sha: ${{ inputs.ref }} env: TF_VAR_seed: ${{ steps.env.outputs.seed }} \ No newline at end of file diff --git a/.github/workflows/integration-tests-plan-diff.yml b/.github/workflows/tests_plan_diff.yml similarity index 100% rename from .github/workflows/integration-tests-plan-diff.yml rename to .github/workflows/tests_plan_diff.yml diff --git a/.github/workflows/integration-tests-plan-fail.yml b/.github/workflows/tests_plan_fail.yml similarity index 100% rename from .github/workflows/integration-tests-plan-fail.yml rename to .github/workflows/tests_plan_fail.yml diff --git a/.github/workflows/integration-tests-plan-storage-disabled.yml b/.github/workflows/tests_plan_storage_disabled.yml similarity index 100% rename from .github/workflows/integration-tests-plan-storage-disabled.yml rename to .github/workflows/tests_plan_storage_disabled.yml From 3ef368d07ac543e0e957dce6091eabc754fd494a Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sun, 10 Aug 2025 18:59:54 +0200 Subject: [PATCH 116/123] Plan diff support skip init flag --- .github/workflows/test_atmos_pro.yml | 20 +++++++++++----- .github/workflows/tests_basic.yml | 10 ++++---- .github/workflows/tests_plan_diff.yml | 24 ++++++++++++------- .github/workflows/tests_plan_fail.yml | 19 ++++++++++----- .../workflows/tests_plan_storage_disabled.yml | 19 ++++++++++----- 5 files changed, 62 insertions(+), 30 deletions(-) diff --git a/.github/workflows/test_atmos_pro.yml b/.github/workflows/test_atmos_pro.yml index cbe5a275..4db22a15 100644 --- a/.github/workflows/test_atmos_pro.yml +++ b/.github/workflows/test_atmos_pro.yml @@ -1,10 +1,16 @@ name: "Atmos Pro Integration Tests" on: - workflow_dispatch: {} - - pull_request: - types: [opened, synchronize, reopened] + workflow_dispatch: + inputs: + ref: + description: "The fully-formed ref of the branch or tag that triggered the workflow run" + required: false + type: string + sha: + description: "The sha of the commit that triggered the workflow run" + required: false + type: string env: AWS_REGION: us-east-2 @@ -29,7 +35,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.ref }} + ref: ${{ inputs.ref }} - name: Setup Atmos Test Config id: env @@ -55,12 +61,13 @@ jobs: component: "foobar-atmos-pro" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} + sha: ${{ inputs.sha }} env: TF_VAR_seed: ${{ steps.env.outputs.seed }} - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.ref }} + ref: ${{ inputs.ref }} - name: Wait 15 sec to wait s3 bucket would be consistent (read after write consistency) shell: bash @@ -74,6 +81,7 @@ jobs: component: "foobar-atmos-pro" stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} + sha: ${{ inputs.sha }} env: TF_VAR_seed: ${{ steps.env.outputs.seed }} diff --git a/.github/workflows/tests_basic.yml b/.github/workflows/tests_basic.yml index 33654ffe..46decefd 100644 --- a/.github/workflows/tests_basic.yml +++ b/.github/workflows/tests_basic.yml @@ -7,9 +7,10 @@ on: description: "The fully-formed ref of the branch or tag that triggered the workflow run" required: false type: string - - pull_request: - types: [opened, synchronize, reopened] + sha: + description: "The sha of the commit that triggered the workflow run" + required: false + type: string env: AWS_REGION: us-east-2 @@ -56,6 +57,7 @@ jobs: stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} debug: true + sha: ${{ inputs.sha }} env: TF_VAR_seed: ${{ steps.env.outputs.seed }} @@ -76,7 +78,7 @@ jobs: stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} debug: true - sha: ${{ inputs.ref }} + sha: ${{ inputs.sha }} env: TF_VAR_seed: ${{ steps.env.outputs.seed }} \ No newline at end of file diff --git a/.github/workflows/tests_plan_diff.yml b/.github/workflows/tests_plan_diff.yml index 88704fe7..88338c1b 100644 --- a/.github/workflows/tests_plan_diff.yml +++ b/.github/workflows/tests_plan_diff.yml @@ -1,11 +1,17 @@ name: "Integration Tests - Plan diff" on: - workflow_dispatch: {} - - pull_request: - types: [opened, synchronize, reopened] - + workflow_dispatch: + inputs: + ref: + description: "The fully-formed ref of the branch or tag that triggered the workflow run" + required: false + type: string + sha: + description: "The sha of the commit that triggered the workflow run" + required: false + type: string + env: AWS_REGION: us-east-2 @@ -27,7 +33,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.ref }} + ref: ${{ inputs.ref }} - shell: bash run: | @@ -42,7 +48,7 @@ jobs: sed -i -e 's#__PLAN_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml sed -i -e 's#__APPLY_ROLE__#${{ secrets.TERRAFORM_APPLY_ROLE }}#g' ${{ runner.temp }}/atmos.yaml - echo "seed=${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${{ matrix.platform }}" >> $GITHUB_OUTPUT + echo "seed=${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-${{ matrix.platform }}" >> $GITHUB_OUTPUT - name: Plan Atmos Component uses: cloudposse/github-action-atmos-terraform-plan@v4 @@ -51,12 +57,13 @@ jobs: stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} debug: true + sha: ${{ inputs.sha }} env: TF_VAR_seed: ${{ steps.env.outputs.seed }}-a - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.ref }} + ref: ${{ inputs.ref }} - name: Wait 15 sec to wait s3 bucket would be consistent (read after write consistency) shell: bash @@ -70,6 +77,7 @@ jobs: stack: "plat-ue2-sandbox" atmos-config-path: ${{ runner.temp }} debug: true + sha: ${{ inputs.sha }} env: TF_VAR_seed: ${{ steps.env.outputs.seed }}-b \ No newline at end of file diff --git a/.github/workflows/tests_plan_fail.yml b/.github/workflows/tests_plan_fail.yml index 9d5d3473..9998f2b6 100644 --- a/.github/workflows/tests_plan_fail.yml +++ b/.github/workflows/tests_plan_fail.yml @@ -1,10 +1,16 @@ name: "Integration Tests - Plan Fail" on: - workflow_dispatch: {} - - pull_request: - types: [opened, synchronize, reopened] + workflow_dispatch: + inputs: + ref: + description: "The fully-formed ref of the branch or tag that triggered the workflow run" + required: false + type: string + sha: + description: "The sha of the commit that triggered the workflow run" + required: false + type: string env: AWS_REGION: us-east-2 @@ -27,7 +33,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.ref }} + ref: ${{ inputs.ref }} - shell: bash id: env @@ -47,7 +53,7 @@ jobs: - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.ref }} + ref: ${{ inputs.ref }} - name: Apply Atmos Component uses: ./ @@ -57,6 +63,7 @@ jobs: atmos-config-path: ${{ runner.temp }} plan-storage: false debug: true + sha: ${{ inputs.sha }} env: TF_VAR_seed: ${{ steps.env.outputs.seed }} \ No newline at end of file diff --git a/.github/workflows/tests_plan_storage_disabled.yml b/.github/workflows/tests_plan_storage_disabled.yml index 9df5e03e..ccfd2c2a 100644 --- a/.github/workflows/tests_plan_storage_disabled.yml +++ b/.github/workflows/tests_plan_storage_disabled.yml @@ -1,10 +1,16 @@ name: "Integration Tests - Plan Storage disabled" on: - workflow_dispatch: {} - - pull_request: - types: [opened, synchronize, reopened] + workflow_dispatch: + inputs: + ref: + description: "The fully-formed ref of the branch or tag that triggered the workflow run" + required: false + type: string + sha: + description: "The sha of the commit that triggered the workflow run" + required: false + type: string env: AWS_REGION: us-east-2 @@ -26,7 +32,7 @@ jobs: steps: - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.ref }} + ref: ${{ inputs.ref }} - shell: bash id: env @@ -46,7 +52,7 @@ jobs: - uses: actions/checkout@v4 with: - ref: ${{ github.event.pull_request.head.ref }} + ref: ${{ inputs.ref }} - name: Apply Atmos Component uses: ./ @@ -56,6 +62,7 @@ jobs: atmos-config-path: ${{ runner.temp }} plan-storage: false debug: true + sha: ${{ inputs.sha }} env: TF_VAR_seed: ${{ steps.env.outputs.seed }} \ No newline at end of file From 2f033eb33c3cf5a23b6675881bc492db08292176 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sun, 10 Aug 2025 19:50:15 +0200 Subject: [PATCH 117/123] Plan diff support skip init flag --- .github/workflows/{test_atmos_pro.yml => test-atmos_pro.yml} | 0 .github/workflows/{tests_basic.yml => tests-basic.yml} | 0 .../workflows/{tests_plan_diff.yml => tests-plan_diff.yml} | 5 ++++- .../workflows/{tests_plan_fail.yml => tests-plan_fail.yml} | 3 +++ ..._storage_disabled.yml => tests-plan_storage_disabled.yml} | 3 +++ 5 files changed, 10 insertions(+), 1 deletion(-) rename .github/workflows/{test_atmos_pro.yml => test-atmos_pro.yml} (100%) rename .github/workflows/{tests_basic.yml => tests-basic.yml} (100%) rename .github/workflows/{tests_plan_diff.yml => tests-plan_diff.yml} (97%) rename .github/workflows/{tests_plan_fail.yml => tests-plan_fail.yml} (97%) rename .github/workflows/{tests_plan_storage_disabled.yml => tests-plan_storage_disabled.yml} (97%) diff --git a/.github/workflows/test_atmos_pro.yml b/.github/workflows/test-atmos_pro.yml similarity index 100% rename from .github/workflows/test_atmos_pro.yml rename to .github/workflows/test-atmos_pro.yml diff --git a/.github/workflows/tests_basic.yml b/.github/workflows/tests-basic.yml similarity index 100% rename from .github/workflows/tests_basic.yml rename to .github/workflows/tests-basic.yml diff --git a/.github/workflows/tests_plan_diff.yml b/.github/workflows/tests-plan_diff.yml similarity index 97% rename from .github/workflows/tests_plan_diff.yml rename to .github/workflows/tests-plan_diff.yml index 88338c1b..4afef6d6 100644 --- a/.github/workflows/tests_plan_diff.yml +++ b/.github/workflows/tests-plan_diff.yml @@ -11,7 +11,10 @@ on: description: "The sha of the commit that triggered the workflow run" required: false type: string - + + pull_request: + types: [opened, synchronize, reopened] + env: AWS_REGION: us-east-2 diff --git a/.github/workflows/tests_plan_fail.yml b/.github/workflows/tests-plan_fail.yml similarity index 97% rename from .github/workflows/tests_plan_fail.yml rename to .github/workflows/tests-plan_fail.yml index 9998f2b6..91592fb9 100644 --- a/.github/workflows/tests_plan_fail.yml +++ b/.github/workflows/tests-plan_fail.yml @@ -12,6 +12,9 @@ on: required: false type: string + pull_request: + types: [opened, synchronize, reopened] + env: AWS_REGION: us-east-2 diff --git a/.github/workflows/tests_plan_storage_disabled.yml b/.github/workflows/tests-plan_storage_disabled.yml similarity index 97% rename from .github/workflows/tests_plan_storage_disabled.yml rename to .github/workflows/tests-plan_storage_disabled.yml index ccfd2c2a..006481fd 100644 --- a/.github/workflows/tests_plan_storage_disabled.yml +++ b/.github/workflows/tests-plan_storage_disabled.yml @@ -12,6 +12,9 @@ on: required: false type: string + pull_request: + types: [opened, synchronize, reopened] + env: AWS_REGION: us-east-2 From 6bbb1b9d3bef2a27524a03bd12a1294be6e03581 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sun, 10 Aug 2025 20:08:08 +0200 Subject: [PATCH 118/123] Plan diff support skip init flag --- .github/workflows/tests-basic.yml | 2 +- .github/workflows/tests-plan_diff.yml | 5 +---- .github/workflows/tests-plan_fail.yml | 3 --- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/.github/workflows/tests-basic.yml b/.github/workflows/tests-basic.yml index 46decefd..cf8c03ce 100644 --- a/.github/workflows/tests-basic.yml +++ b/.github/workflows/tests-basic.yml @@ -10,7 +10,7 @@ on: sha: description: "The sha of the commit that triggered the workflow run" required: false - type: string + type: string env: AWS_REGION: us-east-2 diff --git a/.github/workflows/tests-plan_diff.yml b/.github/workflows/tests-plan_diff.yml index 4afef6d6..c12e79ab 100644 --- a/.github/workflows/tests-plan_diff.yml +++ b/.github/workflows/tests-plan_diff.yml @@ -11,10 +11,7 @@ on: description: "The sha of the commit that triggered the workflow run" required: false type: string - - pull_request: - types: [opened, synchronize, reopened] - + env: AWS_REGION: us-east-2 diff --git a/.github/workflows/tests-plan_fail.yml b/.github/workflows/tests-plan_fail.yml index 91592fb9..227cf1e2 100644 --- a/.github/workflows/tests-plan_fail.yml +++ b/.github/workflows/tests-plan_fail.yml @@ -11,9 +11,6 @@ on: description: "The sha of the commit that triggered the workflow run" required: false type: string - - pull_request: - types: [opened, synchronize, reopened] env: AWS_REGION: us-east-2 From 6daa7ed3445b2aa36ae8d57bbd33220b764f79f1 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sun, 10 Aug 2025 20:08:37 +0200 Subject: [PATCH 119/123] Plan diff support skip init flag --- .github/workflows/tests-plan_storage_disabled.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/tests-plan_storage_disabled.yml b/.github/workflows/tests-plan_storage_disabled.yml index 006481fd..18e32b22 100644 --- a/.github/workflows/tests-plan_storage_disabled.yml +++ b/.github/workflows/tests-plan_storage_disabled.yml @@ -11,9 +11,6 @@ on: description: "The sha of the commit that triggered the workflow run" required: false type: string - - pull_request: - types: [opened, synchronize, reopened] env: AWS_REGION: us-east-2 From f81da09d4008261914d2b54110f92cdf7fe686fb Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sun, 10 Aug 2025 20:23:58 +0200 Subject: [PATCH 120/123] Plan diff support skip init flag --- .github/workflows/test-atmos_pro.yml | 3 +++ .github/workflows/{tests-basic.yml => test-basic.yml} | 3 +++ .../workflows/{tests-plan_diff.yml => test-plan_diff.yml} | 5 ++++- .../workflows/{tests-plan_fail.yml => test-plan_fail.yml} | 5 ++++- ...n_storage_disabled.yml => test-plan_storage_disabled.yml} | 5 ++++- 5 files changed, 18 insertions(+), 3 deletions(-) rename .github/workflows/{tests-basic.yml => test-basic.yml} (97%) rename .github/workflows/{tests-plan_diff.yml => test-plan_diff.yml} (97%) rename .github/workflows/{tests-plan_fail.yml => test-plan_fail.yml} (97%) rename .github/workflows/{tests-plan_storage_disabled.yml => test-plan_storage_disabled.yml} (97%) diff --git a/.github/workflows/test-atmos_pro.yml b/.github/workflows/test-atmos_pro.yml index 4db22a15..3c12dd45 100644 --- a/.github/workflows/test-atmos_pro.yml +++ b/.github/workflows/test-atmos_pro.yml @@ -12,6 +12,9 @@ on: required: false type: string + pull_request: + types: [opened, synchronize, reopened] + env: AWS_REGION: us-east-2 diff --git a/.github/workflows/tests-basic.yml b/.github/workflows/test-basic.yml similarity index 97% rename from .github/workflows/tests-basic.yml rename to .github/workflows/test-basic.yml index cf8c03ce..bf178fbc 100644 --- a/.github/workflows/tests-basic.yml +++ b/.github/workflows/test-basic.yml @@ -12,6 +12,9 @@ on: required: false type: string + pull_request: + types: [opened, synchronize, reopened] + env: AWS_REGION: us-east-2 diff --git a/.github/workflows/tests-plan_diff.yml b/.github/workflows/test-plan_diff.yml similarity index 97% rename from .github/workflows/tests-plan_diff.yml rename to .github/workflows/test-plan_diff.yml index c12e79ab..f33a84a8 100644 --- a/.github/workflows/tests-plan_diff.yml +++ b/.github/workflows/test-plan_diff.yml @@ -11,7 +11,10 @@ on: description: "The sha of the commit that triggered the workflow run" required: false type: string - + + pull_request: + types: [opened, synchronize, reopened] + env: AWS_REGION: us-east-2 diff --git a/.github/workflows/tests-plan_fail.yml b/.github/workflows/test-plan_fail.yml similarity index 97% rename from .github/workflows/tests-plan_fail.yml rename to .github/workflows/test-plan_fail.yml index 227cf1e2..ad480b5b 100644 --- a/.github/workflows/tests-plan_fail.yml +++ b/.github/workflows/test-plan_fail.yml @@ -11,7 +11,10 @@ on: description: "The sha of the commit that triggered the workflow run" required: false type: string - + + pull_request: + types: [opened, synchronize, reopened] + env: AWS_REGION: us-east-2 diff --git a/.github/workflows/tests-plan_storage_disabled.yml b/.github/workflows/test-plan_storage_disabled.yml similarity index 97% rename from .github/workflows/tests-plan_storage_disabled.yml rename to .github/workflows/test-plan_storage_disabled.yml index 18e32b22..54321bee 100644 --- a/.github/workflows/tests-plan_storage_disabled.yml +++ b/.github/workflows/test-plan_storage_disabled.yml @@ -11,7 +11,10 @@ on: description: "The sha of the commit that triggered the workflow run" required: false type: string - + + pull_request: + types: [opened, synchronize, reopened] + env: AWS_REGION: us-east-2 From 9ab66e2abe86b220c1d7e478d98636a5b667af9b Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sun, 10 Aug 2025 20:31:31 +0200 Subject: [PATCH 121/123] Plan diff support skip init flag --- .github/workflows/test-atmos_pro.yml | 3 --- .github/workflows/test-basic.yml | 3 --- .github/workflows/test-plan_diff.yml | 3 --- .github/workflows/test-plan_fail.yml | 3 --- .github/workflows/test-plan_storage_disabled.yml | 3 --- 5 files changed, 15 deletions(-) diff --git a/.github/workflows/test-atmos_pro.yml b/.github/workflows/test-atmos_pro.yml index 3c12dd45..4db22a15 100644 --- a/.github/workflows/test-atmos_pro.yml +++ b/.github/workflows/test-atmos_pro.yml @@ -12,9 +12,6 @@ on: required: false type: string - pull_request: - types: [opened, synchronize, reopened] - env: AWS_REGION: us-east-2 diff --git a/.github/workflows/test-basic.yml b/.github/workflows/test-basic.yml index bf178fbc..cf8c03ce 100644 --- a/.github/workflows/test-basic.yml +++ b/.github/workflows/test-basic.yml @@ -12,9 +12,6 @@ on: required: false type: string - pull_request: - types: [opened, synchronize, reopened] - env: AWS_REGION: us-east-2 diff --git a/.github/workflows/test-plan_diff.yml b/.github/workflows/test-plan_diff.yml index f33a84a8..3b01597e 100644 --- a/.github/workflows/test-plan_diff.yml +++ b/.github/workflows/test-plan_diff.yml @@ -12,9 +12,6 @@ on: required: false type: string - pull_request: - types: [opened, synchronize, reopened] - env: AWS_REGION: us-east-2 diff --git a/.github/workflows/test-plan_fail.yml b/.github/workflows/test-plan_fail.yml index ad480b5b..9998f2b6 100644 --- a/.github/workflows/test-plan_fail.yml +++ b/.github/workflows/test-plan_fail.yml @@ -12,9 +12,6 @@ on: required: false type: string - pull_request: - types: [opened, synchronize, reopened] - env: AWS_REGION: us-east-2 diff --git a/.github/workflows/test-plan_storage_disabled.yml b/.github/workflows/test-plan_storage_disabled.yml index 54321bee..ccfd2c2a 100644 --- a/.github/workflows/test-plan_storage_disabled.yml +++ b/.github/workflows/test-plan_storage_disabled.yml @@ -12,9 +12,6 @@ on: required: false type: string - pull_request: - types: [opened, synchronize, reopened] - env: AWS_REGION: us-east-2 From 67a9e871336df67029e978115670ce87a0648f83 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sun, 10 Aug 2025 21:02:10 +0200 Subject: [PATCH 122/123] Plan diff support skip init flag --- README.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.yaml b/README.yaml index 5c0bedc9..485e7472 100644 --- a/README.yaml +++ b/README.yaml @@ -65,7 +65,8 @@ usage: |- ### Config > [!IMPORTANT] - > **Please note!** This GitHub Action only works with `atmos >= 1.158.0`. + > **Please note!** This GitHub Action only works with `atmos >= 1.186.0`. + > If you are using `atmos >= 1.158.0, < 1.186.0` please use `v4` version of this action. > If you are using `atmos >= 1.99.0, < 1.158.0` please use `v3` version of this action. > If you are using `atmos >= 1.63.0, < 1.99.0` please use `v2` version of this action. > If you are using `atmos < 1.63.0` please use `v1` version of this action. @@ -215,6 +216,13 @@ usage: |- stack: "plat-ue2-sandbox" atmos-config-path: ./rootfs/usr/local/etc/atmos/ ``` + ### Migrating from `v4` to `v5` + + The notable changes in `v5` are: + + - `v5` works only with `atmos >= 1.186.0` + - `v5` uses `atmos terraform plan-diff` to ensure changes to be applied are consistent with the stored (approved by the user) planfile. + ### Migrating from `v3` to `v4` The notable changes in `v4` are: From 16d005bc5da3b1b9258ca9df1e516c30019fe12c Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Sun, 10 Aug 2025 21:14:35 +0200 Subject: [PATCH 123/123] Plan diff support skip init flag --- README.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.yaml b/README.yaml index 485e7472..2e7ec3a2 100644 --- a/README.yaml +++ b/README.yaml @@ -210,7 +210,7 @@ usage: |- runs-on: ubuntu-latest steps: - name: Terraform Apply - uses: cloudposse/github-action-atmos-terraform-apply@v2 + uses: cloudposse/github-action-atmos-terraform-apply@v5 with: component: "foobar" stack: "plat-ue2-sandbox"