Repository: chanzuckerberg/fogg
Pull request #684 (2022-07-15 23:31:05)

feat: updated ci that is faster and better
### Summary
This PR updates the code that is generated to `fogg_ci.yml` for github actions. It has been tested in a few iterations in [shared-infra](https://github.com/chanzuckerberg/shared-infra/blob/main/.github/workflows/new_ci.yml). The following new features include:

* auto fix terraform-docs and commit back to branch
* auto fix fogg apply and commit back to branch
* auto fix terraform fmt and commit back to branch
* caching fogg apply using action/cache
* only doing the above on envs/accounts/modules that have changed files
* no more code generation; changed directories are collect dynamically and run in parallel
* fewer bash scripting and more github actions (such as terraform-docs)
* no more SSH keys in secrets; all code is downloaded using a github app credentials (github app's have finer grain access controls and are easier to manage at an org-wide level)
* no more random ordering of steps based on `fogg apply`. should be the same `fogg_ci.yml` every time

### Test Plan
* Testing on shared-infra

### References

In testing on shared-infra, this has been [about 4 minutes faster](https://github.com/chanzuckerberg/shared-infra/pull/5675) than the previous iteration, per PR commit.


Patch:
diff --git a/templates/templates/.github/workflows/fogg_ci.yml.tmpl b/templates/templates/.github/workflows/fogg_ci.yml.tmpl
index 0193abcc..5faa5198 100644
--- a/templates/templates/.github/workflows/fogg_ci.yml.tmpl
+++ b/templates/templates/.github/workflows/fogg_ci.yml.tmpl
@@ -1,86 +1,107 @@
 # Auto-generated by fogg. Do not edit
 # Make improvements in fogg, so that everyone can benefit.
-{{- $githubActionsCI := . }}
 
 on: push
 
-{{- if $githubActionsCI.Env }}
-env:
-{{- range $k, $v := .Env }}
-    {{ $k }}: {{ $v }}
-{{- end }}
-{{- end }}
-
-# cancel old runs if we push new commits to the same ref
 concurrency:
-  group: {{ "${{ github.ref }}" }}
-  cancel-in-progress: true
+  group: {{`${{ github.ref }}`}}
 
 jobs:
-{{- range $idx, $testBucket := $githubActionsCI.TestBuckets }}
-  terraform_{{$idx}}:
+  fogg-apply:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2
-      - name: Set up Python 3.x
-        uses: actions/setup-python@v1
+      - name: Generate token
+        id: generate_token
+        uses: chanzuckerberg/github-app-token@v1.1.4
         with:
-          python-version: '3.6'
-      - run: |
-          mkdir /tmp/terraform-docs
-          cd /tmp/terraform-docs
-
-          # https://terraform-docs.io/user-guide/installation/#pre-compiled-binary
-          curl -sSLo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-linux-amd64.tar.gz
-          tar -xzf terraform-docs.tar.gz
-          chmod +x terraform-docs
-          echo "$PWD" >> $GITHUB_PATH
-      - run: python3 -m venv venv
-      - run: . venv/bin/activate
-      - run: pip install awscli --upgrade --user
-      - run: aws --version
-      {{- if not (eq (len $githubActionsCI.SSHKeySecrets) 0) }}
-      - name: Install SSH key
-        uses: webfactory/ssh-agent@v0.4.1
+          app_id: {{`${{ secrets.CZI_GITHUB_HELPER_APP_ID }}`}}
+          private_key: {{`${{ secrets.CZI_GITHUB_HELPER_PK }}`}}
+      - uses: actions/checkout@v3
+        with:
+          token: {{`${{ steps.generate_token.outputs.token }}`}}
+      - name: Cache Fogg
+        id: cache-fogg
+        uses: actions/cache@v3
+        with:
+          path: ~/.fogg/cache
+          key: fogg-cache-{{`${{ hashFiles('**/.fogg-version') }}`}}
+      - run: make setup
+      - run: .fogg/bin/fogg apply
+        env:
+          FOGG_GITHUBAPPTOKEN: {{`${{ steps.generate_token.outputs.token }}`}}
+      - uses: EndBug/add-and-commit@v9
         with:
-          ssh-private-key: |
-          {{ range $idx, $secret := $githubActionsCI.SSHKeySecrets }}
-            {{`${{`}} secrets.{{ $secret }} {{`}}`}}
-          {{ end }}
-      {{ end }}
-      - run: FOGG_VERSION="v{{ $githubActionsCI.FoggVersion }}" make setup
-      - run: |
-          .fogg/bin/fogg apply
-          if [ "$(git status --porcelain)" != "" ]; then
-            echo "git tree is dirty after running fogg apply"
-            echo "ensure you run fogg apply on your branch"
-            git status
-            exit 1
-          fi
-{{- if not (eq (len $githubActionsCI.AWSProfiles) 0) }}
-      - run: aws configure set aws_access_key_id     {{`${{`}} secrets.IDACCT_AWS_ACCESS_KEY_ID {{`}}`}}     --profile _idacct
-      - run: aws configure set aws_secret_access_key {{`${{`}} secrets.IDACCT_AWS_SECRET_ACCESS_KEY {{`}}`}} --profile _idacct
-      - run: aws --profile _idacct sts get-caller-identity
-{{- end }}
-{{- range $profileName, $profile := $githubActionsCI.AWSProfiles }}
-      - run: aws configure set profile.{{ $profileName }}.role_arn arn:aws:iam::{{ $profile.AccountID }}:role/{{ $profile.RoleName}}
-      - run: aws configure set profile.{{ $profileName }}.source_profile _idacct
-      - run: aws --profile {{ $profileName }} sts get-caller-identity
-{{- end }}
-      # we only run the following if there are changes in the terraform/* directory
-      # to optimize CI time
-      # can use this filter to decide whether or not to run linters or tests.
-      - uses: dorny/paths-filter@v2.2.1
+          add: -A
+          message: |
+            commit from fogg_ci -- ran fogg apply and pushed
+  find-changed-dirs:
+    runs-on: ubuntu-latest
+    outputs:
+      allChanges: {{`${{ steps.changedDirs.outputs.allChanges }}`}}
+    steps:
+      - uses: actions/checkout@v3
+      - uses: dorny/paths-filter@v2.10.2
         id: filter
         with:
+          initial-fetch-depth: '1'
+          list-files: json
           filters: |
-            terraform:
-              - 'terraform/**'
-  {{- range $component := $testBucket }}
-      - name: {{ $component.Dir }}
-        if: {{ "${{ steps.filter.outputs.terraform == 'true' }}" }}
+            changed:
+              - added|modified: 'terraform/**'
+      - uses: actions/github-script@v6
+        id: changedDirs
+        with:
+          script: |
+            const path = require("path")
+            const changedFiles = {{`${{ steps.filter.outputs.changed_files }}`}}
+            const changedDirs = changedFiles.map(f => path.dirname(f))
+            console.log(`Found the following changed dirs: ${JSON.stringify(changedDirs, null, 2)}\n OG: ${JSON.stringify(changedFiles, null, 2)} `)
+            const changedModules = [... new Set(changedDirs.filter(d => d.indexOf("modules") !== -1))]
+            const changedAccounts = [... new Set(changedDirs.filter(d => d.indexOf("accounts") !== -1 && d.split("/").length === 3))]
+            const changedEnvs = [... new Set(changedDirs.filter(d => d.indexOf("envs") !== -1 && d.split("/").length === 4))]
+            const allChanges = [...changedAccounts,...changedEnvs, ...changedModules]
+            console.log(`changedModules: ${JSON.stringify(changedModules)}`)
+            console.log(`changedAccounts: ${JSON.stringify(changedAccounts)}`)
+            console.log(`changedEnvs: ${JSON.stringify(changedEnvs)}`)
+            core.setOutput("allChanges", allChanges)
+  lint-changed-dirs:
+    runs-on: ubuntu-latest
+    needs: find-changed-dirs
+    strategy:
+      matrix:
+        tfmodule: {{`${{ fromJson(needs.find-changed-dirs.outputs.allChanges) }}`}}
+    if: {{`${{ needs.find-changed-dirs.outputs.allChanges != '[]' }}`}}
+    steps:
+      - name: Generate token
+        id: generate_token
+        uses: chanzuckerberg/github-app-token@v1.1.4
+        with:
+          app_id: {{`${{ secrets.CZI_GITHUB_HELPER_APP_ID }}`}}
+          private_key: {{`${{ secrets.CZI_GITHUB_HELPER_PK }}`}}
+      - uses: actions/checkout@v3
+        with:
+          token: {{`${{ steps.generate_token.outputs.token }}`}}
+      - name: fix terraform docs
+        uses: terraform-docs/gh-actions@v1.0.0
+        if: contains(matrix.tfmodule, 'modules') # only need to make docs on the modules
+        with:
+          working-dir: {{`${{matrix.tfmodule}}`}}
+          git-push: "true"
+          template: <!-- START -->\n{{`{{ .Content }}`}}\n<!-- END -->
+          ref: {{`${{ github.event.pull_request.head.ref }}`}}
+          git-commit-message: |
+            commit from fogg_ci -- ran terraform-docs and pushed
+      - name: fix terraform fmt
+        run: |
+          cd {{`${{matrix.tfmodule}}`}}
+          make fmt
+      - uses: EndBug/add-and-commit@v9
+        with:
+          add: -A
+          message: |
+            commit from fogg_ci -- ran terraform fmt and pushed
+      - name: tflint
         run: |
-          cd {{ $component.Dir }}
-          make  {{ $component.Command }}
-  {{- end }}
-{{- end }}
+          make setup
+          cd {{`${{matrix.tfmodule}}`}}
+          ${GITHUB_WORKSPACE}/.fogg/bin/tflint


Test patch:
diff --git a/testdata/github_actions/.github/workflows/fogg_ci.yml b/testdata/github_actions/.github/workflows/fogg_ci.yml
index 0e6956e5..558fb4e6 100644
--- a/testdata/github_actions/.github/workflows/fogg_ci.yml
+++ b/testdata/github_actions/.github/workflows/fogg_ci.yml
@@ -3,287 +3,105 @@
 
 on: push
 
-# cancel old runs if we push new commits to the same ref
 concurrency:
   group: ${{ github.ref }}
-  cancel-in-progress: true
 
 jobs:
-  terraform_0:
+  fogg-apply:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2
-      - name: Set up Python 3.x
-        uses: actions/setup-python@v1
+      - name: Generate token
+        id: generate_token
+        uses: chanzuckerberg/github-app-token@v1.1.4
         with:
-          python-version: '3.6'
-      - run: |
-          mkdir /tmp/terraform-docs
-          cd /tmp/terraform-docs
-
-          # https://terraform-docs.io/user-guide/installation/#pre-compiled-binary
-          curl -sSLo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-linux-amd64.tar.gz
-          tar -xzf terraform-docs.tar.gz
-          chmod +x terraform-docs
-          echo "$PWD" >> $GITHUB_PATH
-      - run: python3 -m venv venv
-      - run: . venv/bin/activate
-      - run: pip install awscli --upgrade --user
-      - run: aws --version
-      - run: FOGG_VERSION="vundefined-pre+undefined.dirty" make setup
-      - run: |
-          .fogg/bin/fogg apply
-          if [ "$(git status --porcelain)" != "" ]; then
-            echo "git tree is dirty after running fogg apply"
-            echo "ensure you run fogg apply on your branch"
-            git status
-            exit 1
-          fi
-      # we only run the following if there are changes in the terraform/* directory
-      # to optimize CI time
-      # can use this filter to decide whether or not to run linters or tests.
-      - uses: dorny/paths-filter@v2.2.1
-        id: filter
+          app_id: ${{ secrets.CZI_GITHUB_HELPER_APP_ID }}
+          private_key: ${{ secrets.CZI_GITHUB_HELPER_PK }}
+      - uses: actions/checkout@v3
         with:
-          filters: |
-            terraform:
-              - 'terraform/**'
-      - name: terraform/global
-        if: ${{ steps.filter.outputs.terraform == 'true' }}
-        run: |
-          cd terraform/global
-          make  lint
-  terraform_1:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v2
-      - name: Set up Python 3.x
-        uses: actions/setup-python@v1
+          token: ${{ steps.generate_token.outputs.token }}
+      - name: Cache Fogg
+        id: cache-fogg
+        uses: actions/cache@v3
         with:
-          python-version: '3.6'
-      - run: |
-          mkdir /tmp/terraform-docs
-          cd /tmp/terraform-docs
-
-          # https://terraform-docs.io/user-guide/installation/#pre-compiled-binary
-          curl -sSLo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-linux-amd64.tar.gz
-          tar -xzf terraform-docs.tar.gz
-          chmod +x terraform-docs
-          echo "$PWD" >> $GITHUB_PATH
-      - run: python3 -m venv venv
-      - run: . venv/bin/activate
-      - run: pip install awscli --upgrade --user
-      - run: aws --version
-      - run: FOGG_VERSION="vundefined-pre+undefined.dirty" make setup
-      - run: |
-          .fogg/bin/fogg apply
-          if [ "$(git status --porcelain)" != "" ]; then
-            echo "git tree is dirty after running fogg apply"
-            echo "ensure you run fogg apply on your branch"
-            git status
-            exit 1
-          fi
-      # we only run the following if there are changes in the terraform/* directory
-      # to optimize CI time
-      # can use this filter to decide whether or not to run linters or tests.
-      - uses: dorny/paths-filter@v2.2.1
-        id: filter
+          path: ~/.fogg/cache
+          key: fogg-cache-${{ hashFiles('**/.fogg-version') }}
+      - run: make setup
+      - run: .fogg/bin/fogg apply
+        env:
+          FOGG_GITHUBAPPTOKEN: ${{ steps.generate_token.outputs.token }}
+      - uses: EndBug/add-and-commit@v9
         with:
-          filters: |
-            terraform:
-              - 'terraform/**'
-  terraform_2:
+          add: -A
+          message: |
+            commit from fogg_ci -- ran fogg apply and pushed
+  find-changed-dirs:
     runs-on: ubuntu-latest
+    outputs:
+      allChanges: ${{ steps.changedDirs.outputs.allChanges }}
     steps:
-      - uses: actions/checkout@v2
-      - name: Set up Python 3.x
-        uses: actions/setup-python@v1
-        with:
-          python-version: '3.6'
-      - run: |
-          mkdir /tmp/terraform-docs
-          cd /tmp/terraform-docs
-
-          # https://terraform-docs.io/user-guide/installation/#pre-compiled-binary
-          curl -sSLo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-linux-amd64.tar.gz
-          tar -xzf terraform-docs.tar.gz
-          chmod +x terraform-docs
-          echo "$PWD" >> $GITHUB_PATH
-      - run: python3 -m venv venv
-      - run: . venv/bin/activate
-      - run: pip install awscli --upgrade --user
-      - run: aws --version
-      - run: FOGG_VERSION="vundefined-pre+undefined.dirty" make setup
-      - run: |
-          .fogg/bin/fogg apply
-          if [ "$(git status --porcelain)" != "" ]; then
-            echo "git tree is dirty after running fogg apply"
-            echo "ensure you run fogg apply on your branch"
-            git status
-            exit 1
-          fi
-      # we only run the following if there are changes in the terraform/* directory
-      # to optimize CI time
-      # can use this filter to decide whether or not to run linters or tests.
-      - uses: dorny/paths-filter@v2.2.1
-        id: filter
-        with:
-          filters: |
-            terraform:
-              - 'terraform/**'
-  terraform_3:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v2
-      - name: Set up Python 3.x
-        uses: actions/setup-python@v1
-        with:
-          python-version: '3.6'
-      - run: |
-          mkdir /tmp/terraform-docs
-          cd /tmp/terraform-docs
-
-          # https://terraform-docs.io/user-guide/installation/#pre-compiled-binary
-          curl -sSLo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-linux-amd64.tar.gz
-          tar -xzf terraform-docs.tar.gz
-          chmod +x terraform-docs
-          echo "$PWD" >> $GITHUB_PATH
-      - run: python3 -m venv venv
-      - run: . venv/bin/activate
-      - run: pip install awscli --upgrade --user
-      - run: aws --version
-      - run: FOGG_VERSION="vundefined-pre+undefined.dirty" make setup
-      - run: |
-          .fogg/bin/fogg apply
-          if [ "$(git status --porcelain)" != "" ]; then
-            echo "git tree is dirty after running fogg apply"
-            echo "ensure you run fogg apply on your branch"
-            git status
-            exit 1
-          fi
-      # we only run the following if there are changes in the terraform/* directory
-      # to optimize CI time
-      # can use this filter to decide whether or not to run linters or tests.
-      - uses: dorny/paths-filter@v2.2.1
+      - uses: actions/checkout@v3
+      - uses: dorny/paths-filter@v2.10.2
         id: filter
         with:
+          initial-fetch-depth: '1'
+          list-files: json
           filters: |
-            terraform:
-              - 'terraform/**'
-  terraform_4:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v2
-      - name: Set up Python 3.x
-        uses: actions/setup-python@v1
+            changed:
+              - added|modified: 'terraform/**'
+      - uses: actions/github-script@v6
+        id: changedDirs
         with:
-          python-version: '3.6'
-      - run: |
-          mkdir /tmp/terraform-docs
-          cd /tmp/terraform-docs
-
-          # https://terraform-docs.io/user-guide/installation/#pre-compiled-binary
-          curl -sSLo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-linux-amd64.tar.gz
-          tar -xzf terraform-docs.tar.gz
-          chmod +x terraform-docs
-          echo "$PWD" >> $GITHUB_PATH
-      - run: python3 -m venv venv
-      - run: . venv/bin/activate
-      - run: pip install awscli --upgrade --user
-      - run: aws --version
-      - run: FOGG_VERSION="vundefined-pre+undefined.dirty" make setup
-      - run: |
-          .fogg/bin/fogg apply
-          if [ "$(git status --porcelain)" != "" ]; then
-            echo "git tree is dirty after running fogg apply"
-            echo "ensure you run fogg apply on your branch"
-            git status
-            exit 1
-          fi
-      # we only run the following if there are changes in the terraform/* directory
-      # to optimize CI time
-      # can use this filter to decide whether or not to run linters or tests.
-      - uses: dorny/paths-filter@v2.2.1
-        id: filter
-        with:
-          filters: |
-            terraform:
-              - 'terraform/**'
-  terraform_5:
+          script: |
+            const path = require("path")
+            const changedFiles = ${{ steps.filter.outputs.changed_files }}
+            const changedDirs = changedFiles.map(f => path.dirname(f))
+            console.log(`Found the following changed dirs: ${JSON.stringify(changedDirs, null, 2)}\n OG: ${JSON.stringify(changedFiles, null, 2)} `)
+            const changedModules = [... new Set(changedDirs.filter(d => d.indexOf("modules") !== -1))]
+            const changedAccounts = [... new Set(changedDirs.filter(d => d.indexOf("accounts") !== -1 && d.split("/").length === 3))]
+            const changedEnvs = [... new Set(changedDirs.filter(d => d.indexOf("envs") !== -1 && d.split("/").length === 4))]
+            const allChanges = [...changedAccounts,...changedEnvs, ...changedModules]
+            console.log(`changedModules: ${JSON.stringify(changedModules)}`)
+            console.log(`changedAccounts: ${JSON.stringify(changedAccounts)}`)
+            console.log(`changedEnvs: ${JSON.stringify(changedEnvs)}`)
+            core.setOutput("allChanges", allChanges)
+  lint-changed-dirs:
     runs-on: ubuntu-latest
+    needs: find-changed-dirs
+    strategy:
+      matrix:
+        tfmodule: ${{ fromJson(needs.find-changed-dirs.outputs.allChanges) }}
+    if: ${{ needs.find-changed-dirs.outputs.allChanges != '[]' }}
     steps:
-      - uses: actions/checkout@v2
-      - name: Set up Python 3.x
-        uses: actions/setup-python@v1
+      - name: Generate token
+        id: generate_token
+        uses: chanzuckerberg/github-app-token@v1.1.4
         with:
-          python-version: '3.6'
-      - run: |
-          mkdir /tmp/terraform-docs
-          cd /tmp/terraform-docs
-
-          # https://terraform-docs.io/user-guide/installation/#pre-compiled-binary
-          curl -sSLo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-linux-amd64.tar.gz
-          tar -xzf terraform-docs.tar.gz
-          chmod +x terraform-docs
-          echo "$PWD" >> $GITHUB_PATH
-      - run: python3 -m venv venv
-      - run: . venv/bin/activate
-      - run: pip install awscli --upgrade --user
-      - run: aws --version
-      - run: FOGG_VERSION="vundefined-pre+undefined.dirty" make setup
-      - run: |
-          .fogg/bin/fogg apply
-          if [ "$(git status --porcelain)" != "" ]; then
-            echo "git tree is dirty after running fogg apply"
-            echo "ensure you run fogg apply on your branch"
-            git status
-            exit 1
-          fi
-      # we only run the following if there are changes in the terraform/* directory
-      # to optimize CI time
-      # can use this filter to decide whether or not to run linters or tests.
-      - uses: dorny/paths-filter@v2.2.1
-        id: filter
+          app_id: ${{ secrets.CZI_GITHUB_HELPER_APP_ID }}
+          private_key: ${{ secrets.CZI_GITHUB_HELPER_PK }}
+      - uses: actions/checkout@v3
         with:
-          filters: |
-            terraform:
-              - 'terraform/**'
-  terraform_6:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v2
-      - name: Set up Python 3.x
-        uses: actions/setup-python@v1
+          token: ${{ steps.generate_token.outputs.token }}
+      - name: fix terraform docs
+        uses: terraform-docs/gh-actions@v1.0.0
+        if: contains(matrix.tfmodule, 'modules') # only need to make docs on the modules
         with:
-          python-version: '3.6'
-      - run: |
-          mkdir /tmp/terraform-docs
-          cd /tmp/terraform-docs
-
-          # https://terraform-docs.io/user-guide/installation/#pre-compiled-binary
-          curl -sSLo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-linux-amd64.tar.gz
-          tar -xzf terraform-docs.tar.gz
-          chmod +x terraform-docs
-          echo "$PWD" >> $GITHUB_PATH
-      - run: python3 -m venv venv
-      - run: . venv/bin/activate
-      - run: pip install awscli --upgrade --user
-      - run: aws --version
-      - run: FOGG_VERSION="vundefined-pre+undefined.dirty" make setup
-      - run: |
-          .fogg/bin/fogg apply
-          if [ "$(git status --porcelain)" != "" ]; then
-            echo "git tree is dirty after running fogg apply"
-            echo "ensure you run fogg apply on your branch"
-            git status
-            exit 1
-          fi
-      # we only run the following if there are changes in the terraform/* directory
-      # to optimize CI time
-      # can use this filter to decide whether or not to run linters or tests.
-      - uses: dorny/paths-filter@v2.2.1
-        id: filter
+          working-dir: ${{matrix.tfmodule}}
+          git-push: "true"
+          template: <!-- START -->\n{{ .Content }}\n<!-- END -->
+          ref: ${{ github.event.pull_request.head.ref }}
+          git-commit-message: |
+            commit from fogg_ci -- ran terraform-docs and pushed
+      - name: fix terraform fmt
+        run: |
+          cd ${{matrix.tfmodule}}
+          make fmt
+      - uses: EndBug/add-and-commit@v9
         with:
-          filters: |
-            terraform:
-              - 'terraform/**'
+          add: -A
+          message: |
+            commit from fogg_ci -- ran terraform fmt and pushed
+      - name: tflint
+        run: |
+          make setup
+          cd ${{matrix.tfmodule}}
+          ${GITHUB_WORKSPACE}/.fogg/bin/tflint
diff --git a/testdata/v2_full_yaml/.github/workflows/fogg_ci.yml b/testdata/v2_full_yaml/.github/workflows/fogg_ci.yml
index 3594ee23..558fb4e6 100644
--- a/testdata/v2_full_yaml/.github/workflows/fogg_ci.yml
+++ b/testdata/v2_full_yaml/.github/workflows/fogg_ci.yml
@@ -2,117 +2,106 @@
 # Make improvements in fogg, so that everyone can benefit.
 
 on: push
-env:
-    FOO: bar
 
-# cancel old runs if we push new commits to the same ref
 concurrency:
   group: ${{ github.ref }}
-  cancel-in-progress: true
 
 jobs:
-  terraform_0:
+  fogg-apply:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2
-      - name: Set up Python 3.x
-        uses: actions/setup-python@v1
+      - name: Generate token
+        id: generate_token
+        uses: chanzuckerberg/github-app-token@v1.1.4
         with:
-          python-version: '3.6'
-      - run: |
-          mkdir /tmp/terraform-docs
-          cd /tmp/terraform-docs
-
-          # https://terraform-docs.io/user-guide/installation/#pre-compiled-binary
-          curl -sSLo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.16.0/terraform-docs-v0.16.0-linux-amd64.tar.gz
-          tar -xzf terraform-docs.tar.gz
-          chmod +x terraform-docs
-          echo "$PWD" >> $GITHUB_PATH
-      - run: python3 -m venv venv
-      - run: . venv/bin/activate
-      - run: pip install awscli --upgrade --user
-      - run: aws --version
-      - run: FOGG_VERSION="vundefined-pre+undefined.dirty" make setup
-      - run: |
-          .fogg/bin/fogg apply
-          if [ "$(git status --porcelain)" != "" ]; then
-            echo "git tree is dirty after running fogg apply"
-            echo "ensure you run fogg apply on your branch"
-            git status
-            exit 1
-          fi
-      - run: aws configure set aws_access_key_id     ${{ secrets.IDACCT_AWS_ACCESS_KEY_ID }}     --profile _idacct
-      - run: aws configure set aws_secret_access_key ${{ secrets.IDACCT_AWS_SECRET_ACCESS_KEY }} --profile _idacct
-      - run: aws --profile _idacct sts get-caller-identity
-      - run: aws configure set profile.profile.role_arn arn:aws:iam::00456:role/foo
-      - run: aws configure set profile.profile.source_profile _idacct
-      - run: aws --profile profile sts get-caller-identity
-      # we only run the following if there are changes in the terraform/* directory
-      # to optimize CI time
-      # can use this filter to decide whether or not to run linters or tests.
-      - uses: dorny/paths-filter@v2.2.1
+          app_id: ${{ secrets.CZI_GITHUB_HELPER_APP_ID }}
+          private_key: ${{ secrets.CZI_GITHUB_HELPER_PK }}
+      - uses: actions/checkout@v3
+        with:
+          token: ${{ steps.generate_token.outputs.token }}
+      - name: Cache Fogg
+        id: cache-fogg
+        uses: actions/cache@v3
+        with:
+          path: ~/.fogg/cache
+          key: fogg-cache-${{ hashFiles('**/.fogg-version') }}
+      - run: make setup
+      - run: .fogg/bin/fogg apply
+        env:
+          FOGG_GITHUBAPPTOKEN: ${{ steps.generate_token.outputs.token }}
+      - uses: EndBug/add-and-commit@v9
+        with:
+          add: -A
+          message: |
+            commit from fogg_ci -- ran fogg apply and pushed
+  find-changed-dirs:
+    runs-on: ubuntu-latest
+    outputs:
+      allChanges: ${{ steps.changedDirs.outputs.allChanges }}
+    steps:
+      - uses: actions/checkout@v3
+      - uses: dorny/paths-filter@v2.10.2
         id: filter
         with:
+          initial-fetch-depth: '1'
+          list-files: json
           filters: |
-            terraform:
-              - 'terraform/**'
-      - name: terraform/accounts/bar
-        if: ${{ steps.filter.outputs.terraform == 'true' }}
-        run: |
-          cd terraform/accounts/bar
-          make  lint
-      - name: terraform/accounts/foo
-        if: ${{ steps.filter.outputs.terraform == 'true' }}
-        run: |
-          cd terraform/accounts/foo
-          make  lint
-      - name: terraform/global
-        if: ${{ steps.filter.outputs.terraform == 'true' }}
-        run: |
-          cd terraform/global
-          make  lint
-      - name: terraform/modules/my_module
-        if: ${{ steps.filter.outputs.terraform == 'true' }}
-        run: |
-          cd terraform/modules/my_module
-          make  check
-      - name: terraform/envs/prod/datadog
-        if: ${{ steps.filter.outputs.terraform == 'true' }}
-        run: |
-          cd terraform/envs/prod/datadog
-          make  lint
-      - name: terraform/envs/prod/hero
-        if: ${{ steps.filter.outputs.terraform == 'true' }}
-        run: |
-          cd terraform/envs/prod/hero
-          make  lint
-      - name: terraform/envs/prod/okta
-        if: ${{ steps.filter.outputs.terraform == 'true' }}
-        run: |
-          cd terraform/envs/prod/okta
-          make  lint
-      - name: terraform/envs/prod/sentry
-        if: ${{ steps.filter.outputs.terraform == 'true' }}
-        run: |
-          cd terraform/envs/prod/sentry
-          make  lint
-      - name: terraform/envs/prod/vpc
-        if: ${{ steps.filter.outputs.terraform == 'true' }}
-        run: |
-          cd terraform/envs/prod/vpc
-          make  lint
-      - name: terraform/envs/staging/comp1
-        if: ${{ steps.filter.outputs.terraform == 'true' }}
-        run: |
-          cd terraform/envs/staging/comp1
-          make  lint
-      - name: terraform/envs/staging/comp2
-        if: ${{ steps.filter.outputs.terraform == 'true' }}
+            changed:
+              - added|modified: 'terraform/**'
+      - uses: actions/github-script@v6
+        id: changedDirs
+        with:
+          script: |
+            const path = require("path")
+            const changedFiles = ${{ steps.filter.outputs.changed_files }}
+            const changedDirs = changedFiles.map(f => path.dirname(f))
+            console.log(`Found the following changed dirs: ${JSON.stringify(changedDirs, null, 2)}\n OG: ${JSON.stringify(changedFiles, null, 2)} `)
+            const changedModules = [... new Set(changedDirs.filter(d => d.indexOf("modules") !== -1))]
+            const changedAccounts = [... new Set(changedDirs.filter(d => d.indexOf("accounts") !== -1 && d.split("/").length === 3))]
+            const changedEnvs = [... new Set(changedDirs.filter(d => d.indexOf("envs") !== -1 && d.split("/").length === 4))]
+            const allChanges = [...changedAccounts,...changedEnvs, ...changedModules]
+            console.log(`changedModules: ${JSON.stringify(changedModules)}`)
+            console.log(`changedAccounts: ${JSON.stringify(changedAccounts)}`)
+            console.log(`changedEnvs: ${JSON.stringify(changedEnvs)}`)
+            core.setOutput("allChanges", allChanges)
+  lint-changed-dirs:
+    runs-on: ubuntu-latest
+    needs: find-changed-dirs
+    strategy:
+      matrix:
+        tfmodule: ${{ fromJson(needs.find-changed-dirs.outputs.allChanges) }}
+    if: ${{ needs.find-changed-dirs.outputs.allChanges != '[]' }}
+    steps:
+      - name: Generate token
+        id: generate_token
+        uses: chanzuckerberg/github-app-token@v1.1.4
+        with:
+          app_id: ${{ secrets.CZI_GITHUB_HELPER_APP_ID }}
+          private_key: ${{ secrets.CZI_GITHUB_HELPER_PK }}
+      - uses: actions/checkout@v3
+        with:
+          token: ${{ steps.generate_token.outputs.token }}
+      - name: fix terraform docs
+        uses: terraform-docs/gh-actions@v1.0.0
+        if: contains(matrix.tfmodule, 'modules') # only need to make docs on the modules
+        with:
+          working-dir: ${{matrix.tfmodule}}
+          git-push: "true"
+          template: <!-- START -->\n{{ .Content }}\n<!-- END -->
+          ref: ${{ github.event.pull_request.head.ref }}
+          git-commit-message: |
+            commit from fogg_ci -- ran terraform-docs and pushed
+      - name: fix terraform fmt
         run: |
-          cd terraform/envs/staging/comp2
-          make  lint
-      - name: terraform/envs/staging/vpc
-        if: ${{ steps.filter.outputs.terraform == 'true' }}
+          cd ${{matrix.tfmodule}}
+          make fmt
+      - uses: EndBug/add-and-commit@v9
+        with:
+          add: -A
+          message: |
+            commit from fogg_ci -- ran terraform fmt and pushed
+      - name: tflint
         run: |
-          cd terraform/envs/staging/vpc
-          make  lint
+          make setup
+          cd ${{matrix.tfmodule}}
+          ${GITHUB_WORKSPACE}/.fogg/bin/tflint