├── .github └── workflows │ ├── cd-argocd.yml │ ├── cd-atmos-stack-deploy.yml │ ├── cd-ecs.yml │ ├── cd-ecspresso.yml │ ├── cd-helmfile.yml │ ├── cd-preview-argocd.yml │ ├── cd-preview-ecs.yml │ ├── cd-preview-ecspresso.yml │ ├── cd-preview-helmfile.yml │ ├── ci-atmos-stack-plan.yml │ ├── ci-codeowners.yml │ ├── ci-dockerized-app-build.yml │ ├── ci-dockerized-app-promote-or-build.yml │ ├── ci-dockerized-app-promote.yml │ ├── ci-dockerized-app-verify.yml │ ├── ci-github-action.yml │ ├── ci-readme.yml │ ├── ci-terraform-chatops.yml │ ├── ci-terraform.yml │ ├── ci-typescript-app-check-dist.yml │ ├── controller-atmos-affected-stacks.yml │ ├── controller-atmos-github-workflows.yml │ ├── controller-draft-release.yml │ ├── controller-hotfix-reintegrate.yml │ ├── controller-hotfix-release-branch.yml │ ├── controller-hotfix-release.yml │ ├── controller-labels.yml │ ├── controller-monorepo.yml │ ├── controller-release-branches.yml │ ├── controller-release.yml │ ├── scheduled-context.yml │ └── scheduled-readme.yml ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── README.yaml ├── docs └── github-actions-reusable-workflows.md └── renovate.json /.github/workflows/cd-argocd.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CD - Deploy to EKS with ArgoCD and Helmfile 3 | 4 | Deploy Docker image to EKS with ArgoCD and Helmfile 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Deploy 10 | on: 11 | push: 12 | branches: [ main ] 13 | 14 | jobs: 15 | cd: 16 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-argocd.yml@main 17 | with: 18 | image: registry.hub.docker.com/library/nginx 19 | tag: latest 20 | repository: $\{\{ github.event.repository.name \}\} 21 | environment: dev 22 | secrets: 23 | secret-outputs-passphrase: $\{\{ secrets.secret-outputs-passphrase \}\} 24 | github-private-actions-pat: $\{\{ secrets.github-private-actions-pat \}\} 25 | ``` 26 | 27 | on: 28 | workflow_call: 29 | inputs: 30 | image: 31 | description: "Docker Image to deploy" 32 | required: true 33 | type: string 34 | tag: 35 | description: "Docker Image tag to deploy" 36 | required: true 37 | type: string 38 | organization: 39 | description: "Repository owner organization (ex. acme for repo acme/example)" 40 | required: true 41 | type: string 42 | repository: 43 | description: "Repository name (ex. example for repo acme/example)" 44 | required: true 45 | type: string 46 | environment: 47 | description: "Environment name deploy to" 48 | type: string 49 | required: true 50 | synchronously: 51 | type: boolean 52 | description: "Wait until ArgoCD successfully apply the changes" 53 | default: false 54 | toolchain: 55 | description: "Toolchain ('helm', 'helmfile')" 56 | required: false 57 | default: "helmfile" 58 | type: string 59 | path: 60 | description: "The path where lives the helmfile or helm chart." 61 | required: true 62 | type: string 63 | values_file: 64 | type: string 65 | description: Helmfile values file 66 | default: '' 67 | required: false 68 | runs-on: 69 | description: "Overrides job runs-on setting (json-encoded list)" 70 | type: string 71 | required: false 72 | default: '["ubuntu-latest"]' 73 | secrets: 74 | secret-outputs-passphrase: 75 | description: "Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs)" 76 | required: true 77 | github-private-actions-pat: 78 | description: "Github PAT allow to pull private repos" 79 | required: true 80 | 81 | permissions: 82 | id-token: write 83 | contents: read 84 | 85 | jobs: 86 | deploy: 87 | runs-on: ${{ fromJSON(inputs.runs-on) }} 88 | environment: 89 | name: ${{ inputs.environment }} 90 | url: ${{ steps.deploy.outputs.webapp-url }} 91 | steps: 92 | - uses: cloudposse/github-action-secret-outputs@0.1.2 93 | id: image 94 | with: 95 | secret: ${{ secrets.secret-outputs-passphrase }} 96 | op: decode 97 | in: ${{ inputs.image }} 98 | 99 | - name: Checkout 100 | uses: actions/checkout@v4 101 | 102 | - name: Environment Info 103 | uses: cloudposse/github-action-interface-environment@0.4.0 104 | id: environment 105 | with: 106 | implementation_repository: cloudposse/actions-private 107 | implementation_path: 'argocd-environments/' 108 | implementation_ref: main 109 | implementation_github_pat: ${{ secrets.github-private-actions-pat }} 110 | environment: ${{ inputs.environment }} 111 | namespace: ${{ inputs.environment }} 112 | repository: ${{ inputs.repository }} 113 | 114 | - name: Configure AWS Credentials 115 | uses: aws-actions/configure-aws-credentials@v4.0.2 116 | with: 117 | aws-region: ${{ steps.environment.outputs.region }} 118 | role-to-assume: ${{ steps.environment.outputs.role }} 119 | role-skip-session-tagging: true 120 | 121 | - name: Deploy 122 | uses: cloudposse/github-action-deploy-argocd@0.8.1 123 | id: deploy 124 | with: 125 | toolchain: ${{ inputs.toolchain }} 126 | path: ${{ inputs.path }} 127 | values_file: ${{ format(inputs.values_file, steps.environment.outputs.name) }} 128 | application: ${{ inputs.repository }} 129 | ssm-path: ${{ steps.environment.outputs.ssm-path }} 130 | aws-region: ${{ steps.environment.outputs.region }} 131 | cluster: ${{ steps.environment.outputs.cluster }} 132 | environment: ${{ steps.environment.outputs.name }} 133 | namespace: ${{ steps.environment.outputs.namespace }} 134 | image: ${{ steps.image.outputs.out }} 135 | image-tag: ${{ inputs.tag }} 136 | operation: deploy 137 | github-pat: ${{ secrets.github-private-actions-pat }} 138 | repository: ${{ inputs.organization }}/${{ inputs.repository }} 139 | ref: ${{ github.sha }} 140 | synchronously: ${{ inputs.synchronously }} 141 | -------------------------------------------------------------------------------- /.github/workflows/cd-atmos-stack-deploy.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CD - Atmos stack deploy 3 | 4 | Deploy atmos stack 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Feature Branch 10 | on: 11 | pull_request: 12 | branches: [ 'master' ] 13 | types: [opened, synchronize, reopened, closed, labeled, unlabeled] 14 | 15 | jobs: 16 | cd: 17 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-atmos-stack-deploy.yaml@main 18 | ``` 19 | on: 20 | workflow_call: 21 | inputs: 22 | stack: 23 | description: The stack name. 24 | required: true 25 | type: string 26 | component: 27 | description: The component name. 28 | required: true 29 | type: string 30 | environment: 31 | description: Environment. 32 | required: true 33 | type: string 34 | runs-on: 35 | description: "Overrides job runs-on setting (json-encoded list)" 36 | type: string 37 | required: false 38 | default: '["ubuntu-latest"]' 39 | jobs: 40 | plan: 41 | runs-on: ${{ fromJSON(inputs.runs-on) }} 42 | environment: 43 | name: ${{ inputs.environment }} 44 | steps: 45 | # This is just to mock calling terraform plan. In reality, this would be a call to `atmos terraform plan` 46 | - run: echo "atmos terraform plan ${{inputs.component}} -s ${{inputs.stack}}" 47 | -------------------------------------------------------------------------------- /.github/workflows/cd-ecs.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CD - Deploy to ECS with Spacelift 3 | 4 | Deploy Docker image to ECS with Spacelift 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Deploy 10 | on: 11 | push: 12 | branches: [ main ] 13 | 14 | jobs: 15 | cd: 16 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-ecs.yml@main 17 | with: 18 | image: registry.hub.docker.com/library/nginx 19 | tag: latest 20 | repository: $\{\{ github.event.repository.name \}\} 21 | environment: dev 22 | spacelift-organization: $\{\{ inputs.spacelift-organization \}\} 23 | secrets: 24 | secret-outputs-passphrase: "$\{\{ secrets.secret-outputs-passphrase \}\}" 25 | github-private-actions-pat: "$\{\{ secrets.github-private-actions-pat \}\}" 26 | spacelift-api-key-id: "$\{\{ secrets.spacelift-api-key-id \}\}" 27 | spacelift-api-key-secret: "$\{\{ secrets.spacelift-api-key-secret \}\}" 28 | ``` 29 | 30 | on: 31 | workflow_call: 32 | inputs: 33 | image: 34 | description: "Docker Image to deploy" 35 | required: true 36 | type: string 37 | tag: 38 | description: "Docker Image tag to deploy" 39 | required: true 40 | type: string 41 | repository: 42 | description: "Repository name (ex. example for repo acme/example)" 43 | required: true 44 | type: string 45 | app: 46 | description: "Application name. Used with monorepo pattern when there are several applications in the repo" 47 | required: false 48 | type: string 49 | environment: 50 | description: "Environment name deploy to" 51 | type: string 52 | required: true 53 | spacelift-organization: 54 | description: "Spacelift organization name" 55 | type: string 56 | required: true 57 | matrix-step-name: 58 | description: "Matrix step name - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction)" 59 | required: false 60 | type: string 61 | matrix-key: 62 | description: "Matrix key - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction)" 63 | required: false 64 | type: string 65 | runs-on: 66 | description: "Overrides job runs-on setting (json-encoded list)" 67 | type: string 68 | required: false 69 | default: '["ubuntu-latest"]' 70 | secrets: 71 | secret-outputs-passphrase: 72 | description: "Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs)" 73 | required: true 74 | github-private-actions-pat: 75 | description: "Github PAT allow to pull private repos" 76 | required: true 77 | spacelift-api-key-id: 78 | description: "Spacelift API Key ID" 79 | required: true 80 | spacelift-api-key-secret: 81 | description: "Spacelift API Key Secret" 82 | required: true 83 | 84 | permissions: 85 | id-token: write 86 | contents: read 87 | 88 | jobs: 89 | deploy: 90 | runs-on: ${{ fromJSON(inputs.runs-on) }} 91 | environment: 92 | name: ${{ inputs.environment }} 93 | url: ${{ steps.deploy.outputs.webapp-url }} 94 | steps: 95 | - uses: cloudposse/github-action-secret-outputs@0.1.2 96 | id: image 97 | with: 98 | secret: ${{ secrets.secret-outputs-passphrase }} 99 | op: decode 100 | in: ${{ inputs.image }} 101 | 102 | - name: Checkout 103 | uses: actions/checkout@v4 104 | 105 | - name: Environment Info 106 | uses: cloudposse/github-action-interface-environment@0.4.0 107 | id: environment 108 | with: 109 | implementation_repository: cloudposse/actions-private 110 | implementation_path: 'ecs-environments' 111 | implementation_ref: main 112 | implementation_github_pat: ${{ secrets.github-private-actions-pat }} 113 | environment: ${{ inputs.environment }} 114 | namespace: ${{ inputs.environment }} 115 | repository: ${{ inputs.repository }} 116 | application: ${{ inputs.app }} 117 | 118 | - name: Configure AWS Credentials 119 | uses: aws-actions/configure-aws-credentials@v4.0.2 120 | with: 121 | aws-region: ${{ steps.environment.outputs.region }} 122 | role-to-assume: ${{ steps.environment.outputs.role }} 123 | role-skip-session-tagging: true 124 | 125 | - name: Deploy 126 | uses: cloudposse/github-action-deploy-ecs@0.1.0 127 | id: deploy 128 | with: 129 | stack: ${{ steps.environment.outputs.cluster }} 130 | region: ${{ steps.environment.outputs.region }} 131 | ssm-path: ${{ steps.environment.outputs.ssm-path }} 132 | namespace: ${{ steps.environment.outputs.namespace }} 133 | image: ${{ steps.image.outputs.out }} 134 | image-tag: ${{ inputs.tag }} 135 | operation: deploy 136 | debug: false 137 | github_token: ${{ secrets.github-private-actions-pat }} 138 | organization: ${{ inputs.spacelift-organization }} 139 | api_key_id: ${{ secrets.spacelift-api-key-id }} 140 | api_key_secret: ${{ secrets.spacelift-api-key-secret }} 141 | -------------------------------------------------------------------------------- /.github/workflows/cd-ecspresso.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CD - Deploy to ECS with Ecspresso 3 | 4 | Deploy Docker image to ECS with Ecspresso 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Deploy 10 | on: 11 | push: 12 | branches: [ main ] 13 | 14 | jobs: 15 | cd: 16 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-ecspresso.yml@main 17 | with: 18 | image: registry.hub.docker.com/library/nginx 19 | tag: latest 20 | repository: $\{\{ github.event.repository.name \}\} 21 | environment: dev 22 | enable-migration: $\{\{ inputs.enable-migration \}\} 23 | support-rollback: $\{\{ inputs.support-rollback \}\} 24 | secrets: 25 | secret-outputs-passphrase: "$\{\{ secrets.secret-outputs-passphrase \}\}" 26 | github-private-actions-pat: $\{\{ secrets.github-private-actions-pat \}\} 27 | ``` 28 | 29 | on: 30 | workflow_call: 31 | inputs: 32 | image: 33 | description: "Docker Image to deploy" 34 | required: true 35 | type: string 36 | tag: 37 | description: "Docker Image tag to deploy" 38 | required: true 39 | type: string 40 | repository: 41 | description: "Repository name (ex. example for repo acme/example)" 42 | required: true 43 | type: string 44 | app: 45 | description: "Application name. Used with monorepo pattern when there are several applications in the repo" 46 | required: false 47 | type: string 48 | environment: 49 | description: "Environment name deploy to" 50 | type: string 51 | required: true 52 | path: 53 | description: "The path tp task definition template json file." 54 | required: false 55 | default: ./deploy/taskdef.json 56 | type: string 57 | enable-migration: 58 | description: "Run DB migration" 59 | type: boolean 60 | required: false 61 | default: false 62 | support-rollback: 63 | description: "Perform rollback on failure" 64 | type: boolean 65 | required: false 66 | default: false 67 | matrix-step-name: 68 | description: "Matrix step name - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction)" 69 | required: false 70 | type: string 71 | matrix-key: 72 | description: "Matrix key - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction)" 73 | required: false 74 | type: string 75 | runs-on: 76 | description: "Overrides job runs-on setting (json-encoded list)" 77 | type: string 78 | required: false 79 | default: '["ubuntu-latest"]' 80 | secrets: 81 | secret-outputs-passphrase: 82 | description: "Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs)" 83 | required: true 84 | github-private-actions-pat: 85 | description: "Github PAT allow to pull private repos" 86 | required: true 87 | 88 | permissions: 89 | id-token: write 90 | contents: read 91 | 92 | jobs: 93 | deploy: 94 | runs-on: ${{ fromJSON(inputs.runs-on) }} 95 | environment: 96 | name: ${{ inputs.environment }} 97 | url: ${{ steps.result.outputs.webapp-url }} 98 | steps: 99 | - uses: cloudposse/github-action-secret-outputs@0.1.2 100 | id: image 101 | with: 102 | secret: ${{ secrets.secret-outputs-passphrase }} 103 | op: decode 104 | in: ${{ inputs.image }} 105 | 106 | - name: Checkout 107 | uses: actions/checkout@v4 108 | 109 | - name: Environment Info 110 | uses: cloudposse/github-action-interface-environment@0.4.0 111 | id: environment 112 | with: 113 | implementation_repository: cloudposse/actions-private 114 | implementation_path: 'ecspresso-environments' 115 | implementation_ref: main 116 | implementation_github_pat: ${{ secrets.github-private-actions-pat }} 117 | environment: ${{ inputs.environment }} 118 | namespace: ${{ inputs.environment }} 119 | repository: ${{ inputs.repository }} 120 | application: ${{ inputs.app }} 121 | 122 | - name: Configure AWS Credentials 123 | uses: aws-actions/configure-aws-credentials@v4.0.2 124 | with: 125 | aws-region: ${{ steps.environment.outputs.region }} 126 | role-to-assume: ${{ steps.environment.outputs.role }}-gha 127 | role-skip-session-tagging: true 128 | 129 | - name: Run DB Migration 130 | uses: cloudposse/github-action-run-ecspresso@0.1.0 131 | continue-on-error: true 132 | if: ${{ inputs.enable-migration }} 133 | id: db_migrate 134 | with: 135 | image: ${{ steps.image.outputs.out }} 136 | image-tag: ${{ inputs.tag }} 137 | region: ${{ steps.environment.outputs.region }} 138 | debug: false 139 | cluster: ${{ steps.environment.outputs.cluster }} 140 | application: ${{ steps.environment.outputs.name }} 141 | taskdef-path: ${{ inputs.path }} 142 | overrides: |- 143 | { 144 | "containerOverrides":[ 145 | { 146 | "name": "app", 147 | "environment": [{ 148 | "name": "RUN_DB_MIGRATION", 149 | "value": "true" 150 | }] 151 | } 152 | ] 153 | } 154 | env: 155 | STAGE: ${{ steps.environment.outputs.stage }} 156 | AWS_ACCOUNT_ID: ${{ steps.environment.outputs.account-id }} 157 | ECS_SERVICE_NAME: ${{ steps.environment.outputs.name }} 158 | ECS_SERVICE_TASK_ROLE: ${{ steps.environment.outputs.role }}-task 159 | ECS_SERVICE_EXECUTION_ROLE: ${{ steps.environment.outputs.role }}-exec 160 | 161 | - name: Deploy 162 | uses: cloudposse/github-action-deploy-ecspresso@0.5.0 163 | continue-on-error: true 164 | if: ${{ steps.db_migrate.outcome != 'failure' }} 165 | id: deploy 166 | with: 167 | image: ${{ steps.image.outputs.out }} 168 | image-tag: ${{ inputs.tag }} 169 | region: ${{ steps.environment.outputs.region }} 170 | operation: deploy 171 | debug: false 172 | cluster: ${{ steps.environment.outputs.cluster }} 173 | application: ${{ steps.environment.outputs.name }} 174 | taskdef-path: ${{ inputs.path }} 175 | mirror_to_s3_bucket: ${{ steps.environment.outputs.s3-bucket }} 176 | timeout: 10m 177 | env: 178 | STAGE: ${{ steps.environment.outputs.stage }} 179 | AWS_ACCOUNT_ID: ${{ steps.environment.outputs.account-id }} 180 | ECS_SERVICE_NAME: ${{ steps.environment.outputs.name }} 181 | ECS_SERVICE_TASK_ROLE: ${{ steps.environment.outputs.role }}-task 182 | ECS_SERVICE_EXECUTION_ROLE: ${{ steps.environment.outputs.role }}-exec 183 | 184 | - name: Run DB Rollback 185 | uses: cloudposse/github-action-run-ecspresso@0.1.0 186 | if: ${{ inputs.enable-migration && inputs.support-rollback && ( steps.db_migrate.outcome == 'failure' || steps.deploy.outcome == 'failure' ) }} 187 | id: db_rollback 188 | with: 189 | image: ${{ steps.image.outputs.out }} 190 | image-tag: ${{ inputs.tag }} 191 | region: ${{ steps.environment.outputs.region }} 192 | debug: false 193 | cluster: ${{ steps.environment.outputs.cluster }} 194 | application: ${{ steps.environment.outputs.name }} 195 | taskdef-path: ${{ inputs.path }} 196 | overrides: |- 197 | { 198 | "containerOverrides":[ 199 | { 200 | "name": "app", 201 | "environment": [{ 202 | "name": "RUN_DB_ROLLBACK", 203 | "value": "true" 204 | }] 205 | } 206 | ] 207 | } 208 | env: 209 | STAGE: ${{ steps.environment.outputs.stage }} 210 | AWS_ACCOUNT_ID: ${{ steps.environment.outputs.account-id }} 211 | ECS_SERVICE_NAME: ${{ steps.environment.outputs.name }} 212 | ECS_SERVICE_TASK_ROLE: ${{ steps.environment.outputs.role }}-task 213 | ECS_SERVICE_EXECUTION_ROLE: ${{ steps.environment.outputs.role }}-exec 214 | 215 | - name: Fail 216 | if: ${{ steps.db_migrate.outcome == 'failure' || steps.deploy.outcome == 'failure' }} 217 | uses: cutenode/action-always-fail@v1.0.1 218 | 219 | - uses: Produce8/actions-aws-ssm-params-to-env@1.1.0 220 | with: 221 | ssm-path: ${{ steps.environment.outputs.ssm-path }} 222 | prefix: SSM_URL_ 223 | decryption: true 224 | 225 | - name: Output web app url 226 | id: result 227 | run: | 228 | echo "webapp-url=${SSM_URL_0}" >> $GITHUB_OUTPUT 229 | -------------------------------------------------------------------------------- /.github/workflows/cd-helmfile.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CD - Deploy to EKS with Helmfile 3 | 4 | Deploy Docker image to EKS with Helmfile 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Deploy 10 | on: 11 | push: 12 | branches: [ main ] 13 | 14 | jobs: 15 | cd: 16 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-helmfile.yml@main 17 | with: 18 | image: registry.hub.docker.com/library/nginx 19 | tag: latest 20 | repository: $\{\{ github.event.repository.name \}\} 21 | environment: dev 22 | secrets: 23 | secret-outputs-passphrase: $\{\{ secrets.secret-outputs-passphrase \}\} 24 | github-private-actions-pat: $\{\{ secrets.github-private-actions-pat \}\} 25 | ``` 26 | 27 | on: 28 | workflow_call: 29 | inputs: 30 | image: 31 | description: "Docker Image to deploy" 32 | required: true 33 | type: string 34 | tag: 35 | description: "Docker Image tag to deploy" 36 | required: true 37 | type: string 38 | repository: 39 | description: "Repository name (ex. example for repo acme/example)" 40 | required: true 41 | type: string 42 | environment: 43 | description: "Environment name deploy to" 44 | type: string 45 | required: true 46 | runs-on: 47 | description: "Overrides job runs-on setting (json-encoded list)" 48 | type: string 49 | required: false 50 | default: '["self-hosted"]' 51 | secrets: 52 | secret-outputs-passphrase: 53 | description: "Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs)" 54 | required: true 55 | github-private-actions-pat: 56 | description: "Github PAT allow to pull private repos" 57 | required: true 58 | 59 | permissions: 60 | id-token: write 61 | contents: read 62 | 63 | jobs: 64 | deploy: 65 | runs-on: ${{ fromJSON(inputs.runs-on) }} 66 | environment: 67 | name: ${{ inputs.environment }} 68 | url: ${{ steps.deploy.outputs.webapp-url }} 69 | steps: 70 | - uses: cloudposse/github-action-secret-outputs@0.1.2 71 | id: image 72 | with: 73 | secret: ${{ secrets.secret-outputs-passphrase }} 74 | op: decode 75 | in: ${{ inputs.image }} 76 | 77 | - name: Checkout 78 | uses: actions/checkout@v4 79 | 80 | - name: Environment Info 81 | uses: cloudposse/github-action-interface-environment@0.4.0 82 | id: environment 83 | with: 84 | implementation_repository: cloudposse/actions-private 85 | implementation_path: 'environments/' 86 | implementation_ref: main 87 | implementation_github_pat: ${{ secrets.github-private-actions-pat }} 88 | environment: ${{ inputs.environment }} 89 | namespace: ${{ inputs.environment }} 90 | repository: ${{ inputs.repository }} 91 | 92 | - name: Configure AWS Credentials 93 | uses: aws-actions/configure-aws-credentials@v4.0.2 94 | with: 95 | aws-region: ${{ steps.environment.outputs.region }} 96 | role-to-assume: ${{ steps.environment.outputs.role }} 97 | role-skip-session-tagging: true 98 | 99 | - name: Deploy 100 | uses: cloudposse/github-action-deploy-helmfile@0.6.0 101 | id: deploy 102 | with: 103 | aws-region: ${{ steps.environment.outputs.region }} 104 | cluster: ${{ steps.environment.outputs.cluster }} 105 | environment: ${{ steps.environment.outputs.name }} 106 | namespace: ${{ steps.environment.outputs.namespace }} 107 | image: ${{ steps.image.outputs.out }} 108 | image-tag: ${{ inputs.tag }} 109 | operation: deploy 110 | -------------------------------------------------------------------------------- /.github/workflows/cd-preview-argocd.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CD - Deploy to EKS Preview envs with Helmfile 3 | 4 | Deploy Docker image to ECS Preview envs with Helmfile 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Feature Branch 10 | on: 11 | pull_request: 12 | branches: [ 'master' ] 13 | types: [opened, synchronize, reopened, closed, labeled, unlabeled] 14 | 15 | jobs: 16 | cd: 17 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-preview-helmfile.yml@main 18 | if: $\{\{ always() \}\} 19 | with: 20 | image: registry.hub.docker.com/library/nginx 21 | tag: latest 22 | repository: $\{\{ github.event.repository.name \}\} 23 | open: $\{\{ github.event.pull_request.state == 'open' \}\} 24 | labels: $\{\{ toJSON(github.event.pull_request.labels.*.name) \}\} 25 | ref: $\{\{ github.event.pull_request.head.ref \}\} 26 | exclusive: false 27 | env-label: | 28 | preview: deploy 29 | secrets: 30 | secret-outputs-passphrase: $\{\{ secrets.secret-outputs-passphrase \}\} 31 | github-private-actions-pat: $\{\{ secrets.github-private-actions-pat \}\} 32 | ``` 33 | 34 | on: 35 | workflow_call: 36 | inputs: 37 | image: 38 | description: "Docker Image to deploy" 39 | required: true 40 | type: string 41 | tag: 42 | description: "Docker Image tag to deploy" 43 | required: true 44 | type: string 45 | organization: 46 | description: "Repository owner organization (ex. acme for repo acme/example)" 47 | required: true 48 | type: string 49 | repository: 50 | description: "Repository name (ex. example for repo acme/example)" 51 | required: true 52 | type: string 53 | ref: 54 | description: "The fully-formed ref of the branch or tag that triggered the workflow run" 55 | required: true 56 | type: string 57 | open: 58 | description: "Pull Request open/close state. Set true if opened" 59 | required: true 60 | type: boolean 61 | labels: 62 | description: "Pull Request labels" 63 | required: false 64 | type: string 65 | default: "{}" 66 | toolchain: 67 | description: "Toolchain ('helm', 'helmfile')" 68 | required: false 69 | default: "helmfile" 70 | type: string 71 | path: 72 | description: "The path where lives the helmfile or helm chart." 73 | required: true 74 | type: string 75 | values_file: 76 | type: string 77 | description: Helmfile values file, or helm chart values file 78 | default: "" 79 | required: false 80 | exclusive: 81 | description: "Deactivate previous GitHub deployments" 82 | required: false 83 | type: boolean 84 | default: true 85 | env-label: 86 | description: "YAML formatted {environment}: {label} map" 87 | type: string 88 | default: | 89 | preview: deploy 90 | synchronously: 91 | type: boolean 92 | description: "Wait until ArgoCD successfully apply the changes" 93 | default: false 94 | runs-on: 95 | description: "Overrides job runs-on setting (json-encoded list)" 96 | type: string 97 | required: false 98 | default: '["ubuntu-latest"]' 99 | secrets: 100 | secret-outputs-passphrase: 101 | description: "Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs)" 102 | required: true 103 | github-private-actions-pat: 104 | description: "Github PAT allow to pull private repos" 105 | required: true 106 | 107 | permissions: 108 | pull-requests: write 109 | deployments: write 110 | id-token: write 111 | contents: read 112 | 113 | jobs: 114 | preview: 115 | runs-on: ${{ fromJSON(inputs.runs-on) }} 116 | steps: 117 | - name: Preview deployments controller 118 | uses: cloudposse/github-action-preview-environment-controller@0.11.0 119 | id: controller 120 | with: 121 | labels: ${{ inputs.labels }} 122 | open: ${{ inputs.open }} 123 | env-label: ${{ inputs.env-label }} 124 | 125 | outputs: 126 | namespace: ${{ inputs.ref }} 127 | labels_env: ${{ steps.controller.outputs.labels_env }} 128 | deploy_envs: ${{ steps.controller.outputs.deploy_envs }} 129 | destroy_envs: ${{ steps.controller.outputs.destroy_envs }} 130 | 131 | 132 | deploy: 133 | runs-on: ubuntu-latest 134 | needs: [ preview ] 135 | if: ${{ needs.preview.outputs.deploy_envs != '[]' }} 136 | strategy: 137 | matrix: 138 | env: ${{ fromJson(needs.preview.outputs.deploy_envs) }} 139 | environment: 140 | name: ${{ matrix.env }} 141 | url: ${{ steps.deploy.outputs.webapp-url }} 142 | steps: 143 | - uses: cloudposse/github-action-secret-outputs@0.1.2 144 | id: image 145 | with: 146 | secret: ${{ secrets.secret-outputs-passphrase }} 147 | op: decode 148 | in: ${{ inputs.image }} 149 | 150 | - name: Deactive environment 151 | uses: bobheadxi/deployments@v1 152 | if: ${{ inputs.exclusive }} 153 | with: 154 | step: deactivate-env 155 | token: ${{ github.token }} 156 | env: ${{ matrix.env }} 157 | desc: Environment purged 158 | 159 | - name: Checkout 160 | uses: actions/checkout@v4 161 | 162 | - name: Environment Info 163 | uses: cloudposse/github-action-interface-environment@0.4.0 164 | id: environment 165 | with: 166 | implementation_repository: cloudposse/actions-private 167 | implementation_path: 'argocd-environments/' 168 | implementation_ref: main 169 | implementation_github_pat: ${{ secrets.github-private-actions-pat }} 170 | environment: ${{ matrix.env }} 171 | namespace: ${{ needs.preview.outputs.namespace }} 172 | repository: ${{ inputs.repository }} 173 | 174 | - name: Configure AWS Credentials 175 | uses: aws-actions/configure-aws-credentials@v4.0.2 176 | with: 177 | aws-region: ${{ steps.environment.outputs.region }} 178 | role-to-assume: ${{ steps.environment.outputs.role }} 179 | role-skip-session-tagging: true 180 | 181 | - name: Deploy 182 | uses: cloudposse/github-action-deploy-argocd@0.8.1 183 | id: deploy 184 | with: 185 | toolchain: ${{ inputs.toolchain }} 186 | synchronously: ${{ inputs.synchronously }} 187 | path: ${{ inputs.path }} 188 | values_file: ${{ format(inputs.values_file, steps.environment.outputs.name) }} 189 | application: ${{ inputs.repository }} 190 | ssm-path: ${{ steps.environment.outputs.ssm-path }} 191 | aws-region: ${{ steps.environment.outputs.region }} 192 | cluster: ${{ steps.environment.outputs.cluster }} 193 | environment: ${{ steps.environment.outputs.name }} 194 | namespace: ${{ steps.environment.outputs.namespace }} 195 | image: ${{ steps.image.outputs.out }} 196 | image-tag: ${{ inputs.tag }} 197 | operation: deploy 198 | github-pat: ${{ secrets.github-private-actions-pat }} 199 | repository: ${{ inputs.organization }}/${{ inputs.repository }} 200 | ref: ${{ github.sha }} 201 | 202 | destroy: 203 | runs-on: ubuntu-latest 204 | needs: [ preview ] 205 | if: ${{ needs.preview.outputs.destroy_envs != '[]' }} 206 | strategy: 207 | matrix: 208 | env: ${{ fromJson(needs.preview.outputs.destroy_envs) }} 209 | permissions: 210 | pull-requests: write 211 | deployments: write 212 | id-token: write 213 | contents: read 214 | steps: 215 | - name: Checkout 216 | uses: actions/checkout@v4 217 | 218 | - name: Seek deployment 219 | uses: cloudposse/github-action-seek-deployment@0.1.1 220 | id: deployment 221 | with: 222 | github-token: ${{ secrets.GITHUB_TOKEN }} 223 | environment: ${{ matrix.env }} 224 | ref: ${{ inputs.ref }} 225 | status: success 226 | 227 | - name: Environment Info 228 | uses: cloudposse/github-action-interface-environment@0.4.0 229 | if: ${{ steps.deployment.outputs.id != '' }} 230 | id: environment 231 | with: 232 | implementation_repository: cloudposse/actions-private 233 | implementation_path: 'argocd-environments/' 234 | implementation_ref: main 235 | implementation_github_pat: ${{ secrets.github-private-actions-pat }} 236 | environment: ${{ matrix.env }} 237 | namespace: ${{ needs.preview.outputs.namespace }} 238 | repository: ${{ inputs.repository }} 239 | 240 | - name: Configure AWS Credentials 241 | uses: aws-actions/configure-aws-credentials@v4.0.2 242 | if: ${{ steps.deployment.outputs.id != '' }} 243 | with: 244 | aws-region: ${{ steps.environment.outputs.region }} 245 | role-to-assume: ${{ steps.environment.outputs.role }} 246 | role-skip-session-tagging: true 247 | 248 | - name: Destroy 249 | uses: cloudposse/github-action-deploy-argocd@0.8.1 250 | if: ${{ steps.deployment.outputs.id != '' }} 251 | id: deploy 252 | with: 253 | toolchain: ${{ inputs.toolchain }} 254 | synchronously: ${{ inputs.synchronously }} 255 | path: ${{ inputs.path }} 256 | application: ${{ inputs.repository }} 257 | values_file: ${{ format(inputs.values_file, steps.environment.outputs.name) }} 258 | ssm-path: ${{ steps.environment.outputs.ssm-path }} 259 | aws-region: ${{ steps.environment.outputs.region }} 260 | cluster: ${{ steps.environment.outputs.cluster }} 261 | environment: ${{ steps.environment.outputs.name }} 262 | namespace: ${{ steps.environment.outputs.namespace }} 263 | image: "" 264 | image-tag: "" 265 | operation: destroy 266 | github-pat: ${{ secrets.github-private-actions-pat }} 267 | debug: false 268 | repository: ${{ inputs.organization }}/${{ inputs.repository }} 269 | ref: ${{ github.sha }} 270 | 271 | - name: Inactivate deployment 272 | uses: chrnorm/deployment-status@v2.0.3 273 | if: ${{ steps.deployment.outputs.id != '' }} 274 | with: 275 | state: inactive 276 | token: ${{ github.token }} 277 | deployment-id: ${{ steps.deployment.outputs.id }} 278 | 279 | - name: Cleanup label 280 | uses: cloudposse/github-action-preview-labels-cleanup@0.1.1 281 | if: ${{ ! inputs.open }} 282 | with: 283 | labels_env: ${{ needs.preview.outputs.labels_env }} 284 | env: ${{ matrix.env }} 285 | -------------------------------------------------------------------------------- /.github/workflows/cd-preview-ecs.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CD - Deploy to ECS QA/Preview envs with Spacelift 3 | 4 | Deploy Docker image to ECS QA/Preview envs with Spacelift 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Feature Branch 10 | on: 11 | pull_request: 12 | branches: [ 'master' ] 13 | types: [opened, synchronize, reopened, closed, labeled, unlabeled] 14 | 15 | jobs: 16 | cd: 17 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-preview-ecs.yml@main 18 | if: $\{\{ always() \}\} 19 | with: 20 | image: registry.hub.docker.com/library/nginx 21 | tag: latest 22 | repository: $\{\{ github.event.repository.name \}\} 23 | spacelift-organization: $\{\{ inputs.spacelift-organization \}\} 24 | open: $\{\{ github.event.pull_request.state == 'open' \}\} 25 | labels: $\{\{ toJSON(github.event.pull_request.labels.*.name) \}\} 26 | ref: $\{\{ github.event.pull_request.head.ref \}\} 27 | exclusive: true 28 | env-label: | 29 | qa1: deploy/qa1 30 | qa2: deploy/qa2 31 | qa3: deploy/qa3 32 | qa4: deploy/qa4 33 | secrets: 34 | secret-outputs-passphrase: $\{\{ secrets.secret-outputs-passphrase \}\} 35 | github-private-actions-pat: $\{\{ secrets.github-private-actions-pat \}\} 36 | spacelift-api-key-id: "$\{\{ secrets.spacelift-api-key-id \}\}" 37 | spacelift-api-key-secret: "$\{\{ secrets.spacelift-api-key-secret \}\}" 38 | ``` 39 | 40 | on: 41 | workflow_call: 42 | inputs: 43 | image: 44 | description: "Docker Image to deploy" 45 | required: true 46 | type: string 47 | tag: 48 | description: "Docker Image tag to deploy" 49 | required: true 50 | type: string 51 | repository: 52 | description: "Repository name (ex. example for repo acme/example)" 53 | required: true 54 | type: string 55 | app: 56 | description: "Application name. Used with monorepo pattern when there are several applications in the repo" 57 | required: false 58 | type: string 59 | ref: 60 | description: "The fully-formed ref of the branch or tag that triggered the workflow run" 61 | required: true 62 | type: string 63 | open: 64 | description: "Pull Request open/close state. Set true if opened" 65 | required: true 66 | type: boolean 67 | labels: 68 | description: "Pull Request labels" 69 | required: false 70 | type: string 71 | default: "{}" 72 | exclusive: 73 | description: "Deactivate previous GitHub deployments" 74 | required: false 75 | type: boolean 76 | default: true 77 | env-label: 78 | description: "YAML formatted {environment}: {label} map" 79 | type: string 80 | default: | 81 | preview: deploy 82 | spacelift-organization: 83 | description: "Spacelift organization name" 84 | type: string 85 | required: true 86 | matrix-step-name: 87 | description: "Matrix step name - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction)" 88 | required: false 89 | type: string 90 | matrix-key: 91 | description: "Matrix key - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction)" 92 | required: false 93 | type: string 94 | runs-on: 95 | description: "Overrides job runs-on setting (json-encoded list)" 96 | type: string 97 | required: false 98 | default: '["ubuntu-latest"]' 99 | secrets: 100 | secret-outputs-passphrase: 101 | description: "Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs)" 102 | required: true 103 | github-private-actions-pat: 104 | description: "Github PAT allow to pull private repos" 105 | required: true 106 | spacelift-api-key-id: 107 | description: "Spacelift API Key ID" 108 | required: true 109 | spacelift-api-key-secret: 110 | description: "Spacelift API Key Secret" 111 | required: true 112 | 113 | permissions: 114 | pull-requests: write 115 | deployments: write 116 | id-token: write 117 | contents: read 118 | 119 | jobs: 120 | preview: 121 | runs-on: ${{ fromJSON(inputs.runs-on) }} 122 | steps: 123 | - name: Preview deployments controller 124 | uses: cloudposse/github-action-preview-environment-controller@0.11.0 125 | id: controller 126 | with: 127 | labels: ${{ inputs.labels }} 128 | open: ${{ inputs.open }} 129 | env-label: ${{ inputs.env-label }} 130 | 131 | outputs: 132 | namespace: ${{ inputs.ref }} 133 | labels_env: ${{ steps.controller.outputs.labels_env }} 134 | deploy_envs: ${{ steps.controller.outputs.deploy_envs }} 135 | destroy_envs: ${{ steps.controller.outputs.destroy_envs }} 136 | 137 | deploy: 138 | runs-on: ubuntu-latest 139 | if: ${{ needs.preview.outputs.deploy_envs != '[]' }} 140 | strategy: 141 | matrix: 142 | env: ${{ fromJson(needs.preview.outputs.deploy_envs) }} 143 | environment: 144 | name: ${{ matrix.env }} 145 | url: ${{ steps.deploy.outputs.webapp-url }} 146 | needs: [ preview ] 147 | steps: 148 | - uses: cloudposse/github-action-secret-outputs@0.1.2 149 | id: image 150 | with: 151 | secret: ${{ secrets.secret-outputs-passphrase }} 152 | op: decode 153 | in: ${{ inputs.image }} 154 | 155 | - name: Deactive environment 156 | uses: bobheadxi/deployments@v1 157 | if: ${{ inputs.exclusive }} 158 | with: 159 | step: deactivate-env 160 | token: ${{ github.token }} 161 | env: ${{ matrix.env }} 162 | desc: Environment purged 163 | 164 | - name: Checkout 165 | uses: actions/checkout@v4 166 | - name: Environment Info 167 | uses: cloudposse/github-action-interface-environment@0.4.0 168 | id: environment 169 | with: 170 | implementation_repository: cloudposse/actions-private 171 | implementation_path: 'ecs-environments' 172 | implementation_ref: main 173 | implementation_github_pat: ${{ secrets.github-private-actions-pat }} 174 | environment: ${{ matrix.env }} 175 | namespace: ${{ inputs.environment }} 176 | repository: ${{ inputs.repository }} 177 | application: ${{ inputs.app }} 178 | 179 | - name: Configure AWS Credentials 180 | uses: aws-actions/configure-aws-credentials@v4.0.2 181 | with: 182 | aws-region: ${{ steps.environment.outputs.region }} 183 | role-to-assume: ${{ steps.environment.outputs.role }} 184 | role-skip-session-tagging: true 185 | 186 | - name: Deploy 187 | uses: cloudposse/github-action-deploy-ecs@0.1.0 188 | id: deploy 189 | with: 190 | stack: ${{ steps.environment.outputs.cluster }} 191 | region: ${{ steps.environment.outputs.region }} 192 | ssm-path: ${{ steps.environment.outputs.ssm-path }} 193 | namespace: ${{ steps.environment.outputs.namespace }} 194 | image: ${{ steps.image.outputs.out }} 195 | image-tag: ${{ inputs.tag }} 196 | operation: deploy 197 | debug: false 198 | github_token: ${{ secrets.github-private-actions-pat }} 199 | organization: ${{ inputs.spacelift-organization }} 200 | api_key_id: ${{ secrets.spacelift-api-key-id }} 201 | api_key_secret: ${{ secrets.spacelift-api-key-secret }} 202 | 203 | cleanup: 204 | runs-on: ubuntu-latest 205 | if: ${{ needs.preview.outputs.destroy_envs != '[]' }} 206 | strategy: 207 | matrix: 208 | env: ${{ fromJson(needs.preview.outputs.destroy_envs) }} 209 | permissions: 210 | pull-requests: write 211 | deployments: write 212 | id-token: write 213 | contents: read 214 | needs: [ preview ] 215 | steps: 216 | - name: Seek deployment 217 | uses: cloudposse/github-action-seek-deployment@0.1.1 218 | id: deployment 219 | with: 220 | github-token: ${{ secrets.GITHUB_TOKEN }} 221 | environment: ${{ matrix.env }} 222 | ref: ${{ inputs.ref }} 223 | status: success 224 | 225 | - name: Inactivate deployment 226 | uses: chrnorm/deployment-status@v2.0.3 227 | if: ${{ steps.deployment.outputs.id != '' }} 228 | with: 229 | state: inactive 230 | token: ${{ github.token }} 231 | deployment-id: ${{ steps.deployment.outputs.id }} 232 | 233 | - name: Cleanup label 234 | uses: cloudposse/github-action-preview-labels-cleanup@0.1.1 235 | if: ${{ ! inputs.open }} 236 | with: 237 | labels_env: ${{ needs.preview.outputs.labels_env }} 238 | env: ${{ matrix.env }} 239 | -------------------------------------------------------------------------------- /.github/workflows/cd-preview-ecspresso.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CD - Deploy to ECS QA/Preview envs with Ecspresso 3 | 4 | Deploy Docker image to ECS QA/Preview envs with Ecspresso 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Feature Branch 10 | on: 11 | pull_request: 12 | branches: [ 'main' ] 13 | types: [opened, synchronize, reopened, closed, labeled, unlabeled] 14 | 15 | jobs: 16 | cd: 17 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-preview-ecspresso.yml@main 18 | if: $\{\{ always() \}\} 19 | with: 20 | image: registry.hub.docker.com/library/nginx 21 | tag: latest 22 | repository: $\{\{ github.event.repository.name \}\} 23 | open: $\{\{ github.event.pull_request.state == 'open' \}\} 24 | labels: $\{\{ toJSON(github.event.pull_request.labels.*.name) \}\} 25 | ref: $\{\{ github.event.pull_request.head.ref \}\} 26 | exclusive: true 27 | env-label: | 28 | qa1: deploy/qa1 29 | qa2: deploy/qa2 30 | secrets: 31 | secret-outputs-passphrase: $\{\{ secrets.secret-outputs-passphrase \}\} 32 | github-private-actions-pat: $\{\{ secrets.github-private-actions-pat \}\} 33 | ``` 34 | 35 | on: 36 | workflow_call: 37 | inputs: 38 | image: 39 | description: "Docker Image to deploy" 40 | required: true 41 | type: string 42 | tag: 43 | description: "Docker Image tag to deploy" 44 | required: true 45 | type: string 46 | repository: 47 | description: "Repository name (ex. example for repo acme/example)" 48 | required: true 49 | type: string 50 | app: 51 | description: "Application name. Used with monorepo pattern when there are several applications in the repo" 52 | required: false 53 | type: string 54 | ref: 55 | description: "The fully-formed ref of the branch or tag that triggered the workflow run" 56 | required: true 57 | type: string 58 | path: 59 | description: "The path to task definition template json file." 60 | required: false 61 | default: ./deploy/taskdef.json 62 | type: string 63 | open: 64 | description: "Pull Request open/close state. Set true if opened" 65 | required: true 66 | type: boolean 67 | labels: 68 | description: "Pull Request labels" 69 | required: false 70 | type: string 71 | default: "{}" 72 | exclusive: 73 | description: "Deactivate previous GitHub deployments" 74 | required: false 75 | type: boolean 76 | default: true 77 | env-label: 78 | description: "YAML formatted {environment}: {label} map" 79 | type: string 80 | default: | 81 | preview: deploy 82 | enable-migration: 83 | description: "Run DB migration" 84 | type: boolean 85 | required: false 86 | default: false 87 | support-rollback: 88 | description: "Perform rollback on failure" 89 | type: boolean 90 | required: false 91 | default: false 92 | matrix-step-name: 93 | description: "Matrix step name - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction)" 94 | required: false 95 | type: string 96 | matrix-key: 97 | description: "Matrix key - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction)" 98 | required: false 99 | type: string 100 | runs-on: 101 | description: "Overrides job runs-on setting (json-encoded list)" 102 | type: string 103 | required: false 104 | default: '["ubuntu-latest"]' 105 | secrets: 106 | secret-outputs-passphrase: 107 | description: "Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs)" 108 | required: true 109 | github-private-actions-pat: 110 | description: "Github PAT allow to pull private repos" 111 | required: true 112 | 113 | permissions: 114 | pull-requests: write 115 | deployments: write 116 | id-token: write 117 | contents: read 118 | 119 | jobs: 120 | preview: 121 | name: preview // controller 122 | runs-on: ${{ fromJSON(inputs.runs-on) }} 123 | steps: 124 | - name: Preview deployments controller 125 | uses: cloudposse/github-action-preview-environment-controller@0.11.0 126 | id: controller 127 | with: 128 | labels: ${{ inputs.labels }} 129 | open: ${{ inputs.open }} 130 | env-label: ${{ inputs.env-label }} 131 | 132 | outputs: 133 | namespace: ${{ inputs.ref }} 134 | labels_env: ${{ steps.controller.outputs.labels_env }} 135 | deploy_envs: ${{ steps.controller.outputs.deploy_envs }} 136 | destroy_envs: ${{ steps.controller.outputs.destroy_envs }} 137 | 138 | deploy: 139 | runs-on: ${{ fromJSON(inputs.runs-on) }} 140 | if: ${{ needs.preview.outputs.deploy_envs != '[]' }} 141 | strategy: 142 | matrix: 143 | env: ${{ fromJson(needs.preview.outputs.deploy_envs) }} 144 | environment: 145 | name: ${{ matrix.env }} 146 | url: ${{ steps.result.outputs.webapp-url }} 147 | needs: [ preview ] 148 | steps: 149 | - uses: cloudposse/github-action-secret-outputs@0.1.2 150 | id: image 151 | with: 152 | secret: ${{ secrets.secret-outputs-passphrase }} 153 | op: decode 154 | in: ${{ inputs.image }} 155 | 156 | - name: Deactivate environment 157 | uses: bobheadxi/deployments@v1 158 | if: ${{ inputs.exclusive }} 159 | with: 160 | step: deactivate-env 161 | token: ${{ github.token }} 162 | env: ${{ matrix.env }} 163 | desc: Environment purged 164 | 165 | - name: Checkout 166 | uses: actions/checkout@v4 167 | 168 | - name: Environment Info 169 | uses: cloudposse/github-action-interface-environment@0.4.0 170 | id: environment 171 | with: 172 | implementation_repository: cloudposse/actions-private 173 | implementation_path: 'ecspresso-environments' 174 | implementation_ref: main 175 | implementation_github_pat: ${{ secrets.github-private-actions-pat }} 176 | environment: ${{ matrix.env }} 177 | namespace: ${{ needs.preview.outputs.namespace }} 178 | repository: ${{ inputs.repository }} 179 | application: ${{ inputs.app }} 180 | 181 | - name: Configure AWS Credentials 182 | uses: aws-actions/configure-aws-credentials@v4.0.2 183 | with: 184 | aws-region: ${{ steps.environment.outputs.region }} 185 | role-to-assume: ${{ steps.environment.outputs.role }}-gha 186 | role-skip-session-tagging: true 187 | 188 | - name: Run DB Migration 189 | uses: cloudposse/github-action-run-ecspresso@0.1.0 190 | continue-on-error: true 191 | if: ${{ inputs.enable-migration }} 192 | id: db_migrate 193 | with: 194 | image: ${{ steps.image.outputs.out }} 195 | image-tag: ${{ inputs.tag }} 196 | region: ${{ steps.environment.outputs.region }} 197 | debug: false 198 | cluster: ${{ steps.environment.outputs.cluster }} 199 | application: ${{ steps.environment.outputs.name }} 200 | taskdef-path: ${{ inputs.path }} 201 | overrides: |- 202 | { 203 | "containerOverrides":[ 204 | { 205 | "name": "app", 206 | "environment": [{ 207 | "name": "RUN_DB_MIGRATION", 208 | "value": "true" 209 | }] 210 | } 211 | ] 212 | } 213 | env: 214 | STAGE: ${{ steps.environment.outputs.stage }} 215 | AWS_ACCOUNT_ID: ${{ steps.environment.outputs.account-id }} 216 | ECS_SERVICE_NAME: ${{ steps.environment.outputs.name }} 217 | ECS_SERVICE_TASK_ROLE: ${{ steps.environment.outputs.role }}-task 218 | ECS_SERVICE_EXECUTION_ROLE: ${{ steps.environment.outputs.role }}-exec 219 | 220 | - name: Deploy 221 | uses: cloudposse/github-action-deploy-ecspresso@0.5.0 222 | continue-on-error: true 223 | if: ${{ steps.db_migrate.outcome != 'failure' }} 224 | id: deploy 225 | with: 226 | image: ${{ steps.image.outputs.out }} 227 | image-tag: ${{ inputs.tag }} 228 | region: ${{ steps.environment.outputs.region }} 229 | operation: deploy 230 | debug: false 231 | cluster: ${{ steps.environment.outputs.cluster }} 232 | application: ${{ steps.environment.outputs.name }} 233 | taskdef-path: ${{ inputs.path }} 234 | timeout: 10m 235 | env: 236 | STAGE: ${{ steps.environment.outputs.stage }} 237 | AWS_ACCOUNT_ID: ${{ steps.environment.outputs.account-id }} 238 | ECS_SERVICE_NAME: ${{ steps.environment.outputs.name }} 239 | ECS_SERVICE_TASK_ROLE: ${{ steps.environment.outputs.role }}-task 240 | ECS_SERVICE_EXECUTION_ROLE: ${{ steps.environment.outputs.role }}-exec 241 | 242 | - name: Run DB Rollback 243 | uses: cloudposse/github-action-run-ecspresso@0.1.0 244 | if: ${{ inputs.enable-migration && inputs.support-rollback && ( steps.db_migrate.outcome == 'failure' || steps.deploy.outcome == 'failure' ) }} 245 | id: db_rollback 246 | with: 247 | image: ${{ steps.image.outputs.out }} 248 | image-tag: ${{ inputs.tag }} 249 | region: ${{ steps.environment.outputs.region }} 250 | debug: false 251 | cluster: ${{ steps.environment.outputs.cluster }} 252 | application: ${{ steps.environment.outputs.name }} 253 | taskdef-path: ${{ inputs.path }} 254 | overrides: |- 255 | { 256 | "containerOverrides":[ 257 | { 258 | "name": "app", 259 | "environment": [{ 260 | "name": "RUN_DB_ROLLBACK", 261 | "value": "true" 262 | }] 263 | } 264 | ] 265 | } 266 | env: 267 | STAGE: ${{ steps.environment.outputs.stage }} 268 | AWS_ACCOUNT_ID: ${{ steps.environment.outputs.account-id }} 269 | ECS_SERVICE_NAME: ${{ steps.environment.outputs.name }} 270 | ECS_SERVICE_TASK_ROLE: ${{ steps.environment.outputs.role }}-task 271 | ECS_SERVICE_EXECUTION_ROLE: ${{ steps.environment.outputs.role }}-exec 272 | 273 | - name: Fail 274 | if: ${{ steps.db_migrate.outcome == 'failure' || steps.deploy.outcome == 'failure' }} 275 | uses: cutenode/action-always-fail@v1.0.1 276 | 277 | - uses: Produce8/actions-aws-ssm-params-to-env@1.1.0 278 | with: 279 | ssm-path: ${{ steps.environment.outputs.ssm-path }} 280 | prefix: SSM_URL_ 281 | decryption: true 282 | 283 | - name: Output web app url 284 | id: result 285 | run: | 286 | echo "webapp-url=${SSM_URL_0}" >> $GITHUB_OUTPUT 287 | 288 | cleanup: 289 | runs-on: ${{ fromJSON(inputs.runs-on) }} 290 | if: ${{ needs.preview.outputs.destroy_envs != '[]' }} 291 | strategy: 292 | matrix: 293 | env: ${{ fromJson(needs.preview.outputs.destroy_envs) }} 294 | permissions: 295 | pull-requests: write 296 | deployments: write 297 | id-token: write 298 | contents: read 299 | needs: [ preview ] 300 | steps: 301 | - uses: cloudposse/github-action-secret-outputs@0.1.2 302 | id: image 303 | with: 304 | secret: ${{ secrets.secret-outputs-passphrase }} 305 | op: decode 306 | in: ${{ inputs.image }} 307 | 308 | - name: Seek deployment 309 | uses: cloudposse/github-action-seek-deployment@0.1.1 310 | id: deployment 311 | with: 312 | github-token: ${{ secrets.GITHUB_TOKEN }} 313 | environment: ${{ matrix.env }} 314 | ref: ${{ inputs.ref }} 315 | status: success 316 | 317 | - name: Deactivate deployment 318 | uses: chrnorm/deployment-status@v2.0.3 319 | if: ${{ steps.deployment.outputs.id != '' }} 320 | with: 321 | state: inactive 322 | token: ${{ github.token }} 323 | deployment-id: ${{ steps.deployment.outputs.id }} 324 | 325 | - name: Checkout 326 | uses: actions/checkout@v4 327 | 328 | - name: Environment Info 329 | uses: cloudposse/github-action-interface-environment@0.4.0 330 | id: environment 331 | with: 332 | implementation_repository: cloudposse/actions-private 333 | implementation_path: 'ecspresso-environments' 334 | implementation_ref: main 335 | implementation_github_pat: ${{ secrets.github-private-actions-pat }} 336 | environment: ${{ matrix.env }} 337 | namespace: ${{ needs.preview.outputs.namespace }} 338 | repository: ${{ inputs.repository }} 339 | application: ${{ inputs.app }} 340 | 341 | - name: Configure AWS Credentials 342 | uses: aws-actions/configure-aws-credentials@v4.0.2 343 | with: 344 | aws-region: ${{ steps.environment.outputs.region }} 345 | role-to-assume: ${{ steps.environment.outputs.role }}-gha 346 | role-skip-session-tagging: true 347 | 348 | - name: Run DB Rollback 349 | uses: cloudposse/github-action-run-ecspresso@0.1.0 350 | if: ${{ inputs.enable-migration && inputs.support-rollback }} 351 | id: db_rollback 352 | with: 353 | image: ${{ steps.image.outputs.out }} 354 | image-tag: ${{ inputs.tag }} 355 | region: ${{ steps.environment.outputs.region }} 356 | debug: false 357 | cluster: ${{ steps.environment.outputs.cluster }} 358 | application: ${{ steps.environment.outputs.name }} 359 | taskdef-path: ${{ inputs.path }} 360 | overrides: |- 361 | { 362 | "containerOverrides":[ 363 | { 364 | "name": "app", 365 | "environment": [{ 366 | "name": "RUN_DB_ROLLBACK", 367 | "value": "true" 368 | }] 369 | } 370 | ] 371 | } 372 | env: 373 | STAGE: ${{ steps.environment.outputs.stage }} 374 | AWS_ACCOUNT_ID: ${{ steps.environment.outputs.account-id }} 375 | ECS_SERVICE_NAME: ${{ steps.environment.outputs.name }} 376 | ECS_SERVICE_TASK_ROLE: ${{ steps.environment.outputs.role }}-task 377 | ECS_SERVICE_EXECUTION_ROLE: ${{ steps.environment.outputs.role }}-exec 378 | 379 | - name: Cleanup label 380 | uses: cloudposse/github-action-preview-labels-cleanup@0.1.1 381 | if: ${{ ! inputs.open }} 382 | with: 383 | labels_env: ${{ needs.preview.outputs.labels_env }} 384 | env: ${{ matrix.env }} 385 | -------------------------------------------------------------------------------- /.github/workflows/cd-preview-helmfile.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CD - Deploy to EKS Preview envs with Helmfile 3 | 4 | Deploy Docker image to ECS Preview envs with Helmfile 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Feature Branch 10 | on: 11 | pull_request: 12 | branches: [ 'master' ] 13 | types: [opened, synchronize, reopened, closed, labeled, unlabeled] 14 | 15 | jobs: 16 | cd: 17 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-preview-helmfile.yml@main 18 | if: $\{\{ always() \}\} 19 | with: 20 | image: registry.hub.docker.com/library/nginx 21 | tag: latest 22 | repository: $\{\{ github.event.repository.name \}\} 23 | open: $\{\{ github.event.pull_request.state == 'open' \}\} 24 | labels: $\{\{ toJSON(github.event.pull_request.labels.*.name) \}\} 25 | ref: $\{\{ github.event.pull_request.head.ref \}\} 26 | exclusive: false 27 | env-label: | 28 | preview: deploy 29 | secrets: 30 | secret-outputs-passphrase: $\{\{ secrets.secret-outputs-passphrase \}\} 31 | github-private-actions-pat: $\{\{ secrets.github-private-actions-pat \}\} 32 | ``` 33 | 34 | on: 35 | workflow_call: 36 | inputs: 37 | image: 38 | description: "Docker Image to deploy" 39 | required: true 40 | type: string 41 | tag: 42 | description: "Docker Image tag to deploy" 43 | required: true 44 | type: string 45 | repository: 46 | description: "Repository name (ex. example for repo acme/example)" 47 | required: true 48 | type: string 49 | ref: 50 | description: "The fully-formed ref of the branch or tag that triggered the workflow run" 51 | required: true 52 | type: string 53 | open: 54 | description: "Pull Request open/close state. Set true if opened" 55 | required: true 56 | type: boolean 57 | labels: 58 | description: "Pull Request labels" 59 | required: false 60 | type: string 61 | default: "{}" 62 | exclusive: 63 | description: "Deactivate previous GitHub deployments" 64 | required: false 65 | type: boolean 66 | default: true 67 | env-label: 68 | description: "YAML formatted {environment}: {label} map" 69 | type: string 70 | default: | 71 | preview: deploy 72 | runs-on: 73 | description: "Overrides job runs-on setting (json-encoded list)" 74 | type: string 75 | required: false 76 | default: '["self-hosted"]' 77 | secrets: 78 | secret-outputs-passphrase: 79 | description: "Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs)" 80 | required: true 81 | github-private-actions-pat: 82 | description: "Github PAT allow to pull private repos" 83 | required: true 84 | 85 | permissions: 86 | pull-requests: write 87 | deployments: write 88 | id-token: write 89 | contents: read 90 | 91 | jobs: 92 | preview: 93 | runs-on: ${{ fromJSON(inputs.runs-on) }} 94 | steps: 95 | - name: Preview deployments controller 96 | uses: cloudposse/github-action-preview-environment-controller@0.11.0 97 | id: controller 98 | with: 99 | labels: ${{ inputs.labels }} 100 | open: ${{ inputs.open }} 101 | env-label: ${{ inputs.env-label }} 102 | 103 | outputs: 104 | namespace: ${{ inputs.ref }} 105 | labels_env: ${{ steps.controller.outputs.labels_env }} 106 | deploy_envs: ${{ steps.controller.outputs.deploy_envs }} 107 | destroy_envs: ${{ steps.controller.outputs.destroy_envs }} 108 | 109 | 110 | deploy: 111 | runs-on: ${{ fromJSON(inputs.runs-on) }} 112 | needs: [ preview ] 113 | if: ${{ needs.preview.outputs.deploy_envs != '[]' }} 114 | strategy: 115 | matrix: 116 | env: ${{ fromJson(needs.preview.outputs.deploy_envs) }} 117 | environment: 118 | name: ${{ matrix.env }} 119 | url: ${{ steps.deploy.outputs.webapp-url }} 120 | steps: 121 | - uses: cloudposse/github-action-secret-outputs@0.1.2 122 | id: image 123 | with: 124 | secret: ${{ secrets.secret-outputs-passphrase }} 125 | op: decode 126 | in: ${{ inputs.image }} 127 | 128 | - name: Deactive environment 129 | uses: bobheadxi/deployments@v1 130 | if: ${{ inputs.exclusive }} 131 | with: 132 | step: deactivate-env 133 | token: ${{ github.token }} 134 | env: ${{ matrix.env }} 135 | desc: Environment purged 136 | 137 | - name: Checkout 138 | uses: actions/checkout@v4 139 | 140 | - name: Environment Info 141 | uses: cloudposse/github-action-interface-environment@0.4.0 142 | id: environment 143 | with: 144 | implementation_repository: cloudposse/actions-private 145 | implementation_path: 'environments' 146 | implementation_ref: main 147 | implementation_github_pat: ${{ secrets.github-private-actions-pat }} 148 | environment: ${{ matrix.env }} 149 | namespace: ${{ needs.preview.outputs.namespace }} 150 | repository: ${{ inputs.repository }} 151 | 152 | - name: Configure AWS Credentials 153 | uses: aws-actions/configure-aws-credentials@v4.0.2 154 | with: 155 | aws-region: ${{ steps.environment.outputs.region }} 156 | role-to-assume: ${{ steps.environment.outputs.cluster-role }} 157 | role-skip-session-tagging: true 158 | 159 | - name: Deploy 160 | uses: cloudposse/github-action-deploy-helmfile@0.6.0 161 | id: deploy 162 | with: 163 | aws-region: ${{ steps.environment.outputs.region }} 164 | cluster: ${{ steps.environment.outputs.cluster }} 165 | environment: ${{ steps.environment.outputs.name }} 166 | namespace: ${{ steps.environment.outputs.namespace }} 167 | image: ${{ steps.image.outputs.out }} 168 | image-tag: ${{ needs.build.outputs.tag }} 169 | operation: deploy 170 | debug: false 171 | 172 | 173 | destroy: 174 | runs-on: ${{ fromJSON(inputs.runs-on) }} 175 | needs: [ preview ] 176 | if: ${{ needs.preview.outputs.destroy_envs != '[]' }} 177 | strategy: 178 | matrix: 179 | env: ${{ fromJson(needs.preview.outputs.destroy_envs) }} 180 | permissions: 181 | pull-requests: write 182 | deployments: write 183 | id-token: write 184 | contents: read 185 | steps: 186 | - name: Checkout 187 | uses: actions/checkout@v4 188 | 189 | - name: Seek deployment 190 | uses: cloudposse/github-action-seek-deployment@0.1.1 191 | id: deployment 192 | with: 193 | github-token: ${{ secrets.GITHUB_TOKEN }} 194 | environment: ${{ matrix.env }} 195 | ref: ${{ inputs.ref }} 196 | status: success 197 | 198 | - name: Environment Info 199 | uses: cloudposse/github-action-interface-environment@0.4.0 200 | if: ${{ steps.deployment.outputs.id != '' }} 201 | id: environment 202 | with: 203 | implementation_repository: cloudposse/actions-private 204 | implementation_path: 'environments' 205 | implementation_ref: main 206 | implementation_github_pat: ${{ secrets.github-private-actions-pat }} 207 | environment: ${{ matrix.env }} 208 | namespace: ${{ needs.preview.outputs.namespace }} 209 | repository: ${{ inputs.repository }} 210 | 211 | - name: Configure AWS Credentials 212 | uses: aws-actions/configure-aws-credentials@v4.0.2 213 | if: ${{ steps.deployment.outputs.id != '' }} 214 | with: 215 | aws-region: ${{ steps.environment.outputs.region }} 216 | role-to-assume: ${{ steps.environment.outputs.role }} 217 | role-skip-session-tagging: true 218 | 219 | - name: Destroy 220 | uses: cloudposse/github-action-deploy-helmfile@0.6.0 221 | if: ${{ steps.deployment.outputs.id != '' }} 222 | id: deploy 223 | with: 224 | aws-region: ${{ steps.environment.outputs.region }} 225 | cluster: ${{ steps.environment.outputs.cluster }} 226 | environment: ${{ steps.environment.outputs.name }} 227 | namespace: ${{ steps.environment.outputs.namespace }} 228 | image: "" 229 | image-tag: "" 230 | operation: destroy 231 | debug: false 232 | 233 | - name: Inactivate deployment 234 | uses: chrnorm/deployment-status@v2.0.3 235 | if: ${{ steps.deployment.outputs.id != '' }} 236 | with: 237 | state: inactive 238 | token: ${{ github.token }} 239 | deployment-id: ${{ steps.deployment.outputs.id }} 240 | 241 | - name: Cleanup label 242 | uses: cloudposse/github-action-preview-labels-cleanup@0.1.1 243 | if: ${{ ! inputs.open }} 244 | with: 245 | labels_env: ${{ needs.preview.outputs.labels_env }} 246 | env: ${{ matrix.env }} 247 | -------------------------------------------------------------------------------- /.github/workflows/ci-atmos-stack-plan.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CI - Atmos stack plan 3 | 4 | Plan atmos stack 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Feature Branch 10 | on: 11 | pull_request: 12 | branches: [ 'master' ] 13 | types: [opened, synchronize, reopened, closed, labeled, unlabeled] 14 | 15 | jobs: 16 | cd: 17 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-atmos-stack-plan.yaml@main 18 | ``` 19 | on: 20 | workflow_call: 21 | inputs: 22 | stack: 23 | description: The stack name. 24 | required: true 25 | type: string 26 | component: 27 | description: The component name. 28 | required: true 29 | type: string 30 | runs-on: 31 | description: "Overrides job runs-on setting (json-encoded list)" 32 | type: string 33 | required: false 34 | default: '["ubuntu-latest"]' 35 | jobs: 36 | plan: 37 | runs-on: ${{ fromJSON(inputs.runs-on) }} 38 | steps: 39 | # This is just to mock calling terraform plan. In reality, this would be a call to `atmos terraform plan` 40 | - run: echo "atmos terraform plan ${{inputs.component}} -s ${{inputs.stack}}" 41 | -------------------------------------------------------------------------------- /.github/workflows/ci-codeowners.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CI - Codeowners 3 | 4 | Validate CODEOWNERS and suggest changes 5 | 6 | ### Usage 7 | ```yaml 8 | name: Validate CODEOWNERS 9 | on: 10 | workflow_call: 11 | 12 | jobs: 13 | ci-codeowners: 14 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-codeowners-full.yml@main 15 | with: 16 | is_fork: $\{\{ github.event.pull_request.head.repo.full_name != github.repository \}\} 17 | secrets: inherit 18 | ``` 19 | on: 20 | workflow_call: 21 | inputs: 22 | is_fork: 23 | description: "Run workflow in fork mode (decreased permissions and features)" 24 | type: boolean 25 | required: true 26 | runs-on: 27 | description: "Overrides job runs-on setting (json-encoded list)" 28 | type: string 29 | required: false 30 | default: '["ubuntu-latest"]' 31 | 32 | jobs: 33 | syntax: 34 | runs-on: ${{ fromJSON(inputs.runs-on) }} 35 | name: Validate Codeowners (syntax) 36 | steps: 37 | - name: Checkout 38 | uses: actions/checkout@v4 39 | 40 | - uses: mszostok/codeowners-validator@v0.7.1 41 | # Pull request from a fork 42 | name: "Validate CODEOWNERS" 43 | with: 44 | checks: "syntax,duppatterns" 45 | owner_checker_allow_unowned_patterns: "false" 46 | 47 | owners: 48 | runs-on: ${{ fromJSON(inputs.runs-on) }} 49 | name: Validate Codeowners (owners) 50 | if: ${{ false && ! inputs.is_fork }} 51 | environment: release 52 | steps: 53 | - uses: actions/create-github-app-token@v1 54 | id: github-app 55 | with: 56 | app-id: ${{ vars.BOT_GITHUB_APP_ID }} 57 | private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} 58 | 59 | - name: Checkout 60 | uses: actions/checkout@v4 61 | with: 62 | token: ${{ steps.github-app.outputs.token }} 63 | 64 | - uses: mszostok/codeowners-validator@v0.7.4 65 | # Main branch / Pull request from the same repo 66 | name: "Validate CODEOWNERS" 67 | with: 68 | # For now, remove "files" check to allow CODEOWNERS to specify non-existent 69 | # files so we can use the same CODEOWNERS file for Terraform and non-Terraform repos 70 | # checks: "files,syntax,owners,duppatterns" 71 | checks: "owners" 72 | owner_checker_allow_unowned_patterns: "false" 73 | # Admin GitHub access token is required only if the `owners` check is enabled 74 | github_access_token: ${{ steps.github-app.outputs.token }} 75 | 76 | -------------------------------------------------------------------------------- /.github/workflows/ci-dockerized-app-build.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CI - Build Docker image 3 | 4 | Build Docker image and push it to ECR 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Deploy 10 | on: 11 | push: 12 | branches: [ main ] 13 | 14 | jobs: 15 | ci: 16 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-build.yml@main 17 | with: 18 | organization: $\{\{ github.event.repository.owner.login \}\} 19 | repository: $\{\{ github.event.repository.name \}\} 20 | secrets: 21 | ecr-region: $\{\{ secrets.ecr-region \}\} 22 | ecr-iam-role: $\{\{ secrets.ecr-iam-role \}\} 23 | registry: $\{\{ secrets.registry \}\} 24 | secret-outputs-passphrase: $\{\{ secrets.secret-outputs-passphrase \}\} 25 | ``` 26 | on: 27 | workflow_call: 28 | inputs: 29 | organization: 30 | description: "Repository owner organization (ex. acme for repo acme/example)" 31 | required: true 32 | type: string 33 | repository: 34 | description: "Repository name (ex. example for repo acme/example)" 35 | required: true 36 | type: string 37 | tests_enabled: 38 | description: "Enable CI Test Stage" 39 | type: boolean 40 | default: true 41 | required: false 42 | runs-on: 43 | description: "Overrides job runs-on setting (json-encoded list)" 44 | type: string 45 | required: false 46 | default: '["ubuntu-latest"]' 47 | secrets: 48 | ecr-region: 49 | description: "ECR AWS region" 50 | required: true 51 | ecr-iam-role: 52 | description: "IAM Role ARN provide ECR write/read access" 53 | required: true 54 | secret-outputs-passphrase: 55 | description: "Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs)" 56 | required: true 57 | registry: 58 | description: "ECR Docker registry" 59 | required: true 60 | outputs: 61 | image: 62 | description: "Docker Image" 63 | value: ${{ jobs.build.outputs.image }} 64 | tag: 65 | description: "Docker image tag" 66 | value: ${{ jobs.build.outputs.tag }} 67 | 68 | permissions: 69 | id-token: write 70 | contents: read 71 | 72 | jobs: 73 | build: 74 | name: build 75 | runs-on: ${{ fromJSON(inputs.runs-on) }} 76 | steps: 77 | - name: Checkout 78 | uses: actions/checkout@v4 79 | 80 | - name: Configure AWS Credentials 81 | uses: aws-actions/configure-aws-credentials@v4.0.2 82 | with: 83 | aws-region: ${{ secrets.ecr-region }} 84 | role-to-assume: ${{ secrets.ecr-iam-role }} 85 | 86 | - name: Build 87 | id: build 88 | uses: cloudposse/github-action-docker-build-push@1.15.0 89 | with: 90 | organization: ${{ inputs.organization }} 91 | repository: ${{ inputs.repository }} 92 | registry: ${{ secrets.registry }} 93 | 94 | - uses: cloudposse/github-action-secret-outputs@0.1.2 95 | id: image 96 | with: 97 | secret: ${{ secrets.secret-outputs-passphrase }} 98 | op: encode 99 | in: ${{ steps.build.outputs.image }} 100 | 101 | outputs: 102 | image: ${{ steps.image.outputs.out }} 103 | tag: ${{ steps.build.outputs.tag }} 104 | 105 | test: 106 | runs-on: ${{ fromJSON(inputs.runs-on) }} 107 | if: ${{ inputs.tests_enabled }} 108 | needs: [ build ] 109 | steps: 110 | - name: Checkout 111 | uses: actions/checkout@v4 112 | 113 | - name: Configure AWS Credentials 114 | uses: aws-actions/configure-aws-credentials@v4.0.2 115 | with: 116 | aws-region: ${{ secrets.ecr-region }} 117 | role-to-assume: ${{ secrets.ecr-iam-role }} 118 | 119 | - name: Tests 120 | id: test 121 | uses: cloudposse/github-action-docker-compose-test-run@0.2.0 122 | with: 123 | file: test/docker-compose.yml 124 | service: app 125 | command: test/test.sh 126 | registry: ${{ secrets.registry }} 127 | 128 | -------------------------------------------------------------------------------- /.github/workflows/ci-dockerized-app-promote-or-build.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CI - Promote or build Docker image 3 | 4 | Promote or build Docker image and push it to ECR 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Deploy 10 | on: 11 | push: 12 | branches: [ main ] 13 | 14 | jobs: 15 | ci: 16 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-promote-or-build.yml@main 17 | with: 18 | organization: $\{\{ github.event.repository.owner.login \}\} 19 | repository: $\{\{ github.event.repository.name \}\} 20 | force-build: false 21 | secrets: 22 | ecr-region: $\{\{ secrets.ecr-region \}\} 23 | ecr-iam-role: $\{\{ secrets.ecr-iam-role \}\} 24 | registry: $\{\{ secrets.registry \}\} 25 | secret-outputs-passphrase: $\{\{ secrets.secret-outputs-passphrase \}\} 26 | ``` 27 | on: 28 | workflow_call: 29 | inputs: 30 | organization: 31 | description: "Repository owner organization (ex. acme for repo acme/example)" 32 | required: true 33 | type: string 34 | repository: 35 | description: "Repository name (ex. example for repo acme/example)" 36 | required: true 37 | type: string 38 | app: 39 | description: "Application name. Used with monorepo pattern when there are several applications in the repo" 40 | required: true 41 | type: string 42 | force-build: 43 | description: "Force build (skip promotion)" 44 | default: false 45 | required: true 46 | type: boolean 47 | matrix-step-name: 48 | description: "Matrix step name - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction)" 49 | required: false 50 | type: string 51 | matrix-key: 52 | description: "Matrix key - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction)" 53 | required: false 54 | type: string 55 | runs-on: 56 | description: "Overrides job runs-on setting (json-encoded list)" 57 | type: string 58 | required: false 59 | default: '["ubuntu-latest"]' 60 | secrets: 61 | ecr-region: 62 | description: "ECR AWS region" 63 | required: true 64 | ecr-iam-role: 65 | description: "IAM Role ARN provide ECR write/read access" 66 | required: true 67 | secret-outputs-passphrase: 68 | description: "Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs)" 69 | required: true 70 | registry: 71 | description: "ECR Docker registry" 72 | required: true 73 | outputs: 74 | image: 75 | description: "Docker Image" 76 | value: ${{ jobs.promote-or-build.outputs.image }} 77 | tag: 78 | description: "Docker image tag" 79 | value: ${{ jobs.promote-or-build.outputs.tag }} 80 | 81 | permissions: 82 | id-token: write 83 | contents: read 84 | 85 | jobs: 86 | promote-or-build: 87 | name: promote or build 88 | runs-on: ${{ fromJSON(inputs.runs-on) }} 89 | steps: 90 | - name: Configure AWS Credentials 91 | uses: aws-actions/configure-aws-credentials@v4.0.2 92 | with: 93 | aws-region: ${{ secrets.ecr-region }} 94 | role-to-assume: ${{ secrets.ecr-iam-role }} 95 | 96 | - name: Checkout 97 | uses: actions/checkout@v4 98 | with: 99 | fetch-depth: 2 100 | 101 | - name: Get previous commit 102 | if: ${{ ! inputs.force-build }} 103 | id: prev-commit 104 | run: echo "sha=$(git rev-parse --verify HEAD^1)" >> $GITHUB_OUTPUT 105 | 106 | - uses: cloudposse/github-action-docker-promote@0.3.0 107 | if: ${{ ! inputs.force-build }} 108 | id: promote 109 | continue-on-error: true 110 | with: 111 | registry: ${{ secrets.registry }} 112 | organization: ${{ inputs.organization }} 113 | repository: ${{ inputs.repository }}/${{ inputs.app }} 114 | from: sha-${{ steps.prev-commit.outputs.sha }} 115 | to: sha-${{ github.sha }} 116 | use_metadata: true 117 | 118 | - name: Build 119 | if: ${{ inputs.force-build || steps.promote.outcome == 'failure' }} 120 | id: build 121 | uses: cloudposse/github-action-docker-build-push@1.15.0 122 | with: 123 | organization: ${{ inputs.organization }} 124 | repository: ${{ inputs.repository }}/${{ inputs.app }} 125 | registry: ${{ secrets.registry }} 126 | workdir: ./apps/${{ inputs.app }} 127 | 128 | - uses: cloudposse/github-action-yaml-config-query@0.1.3 129 | id: result 130 | with: 131 | ## There is a bug in GHA - skipped step return `success` outcome. So we can not rely only on steps.build.outcome 132 | query: .${{ steps.build.outcome == 'success' && ( inputs.force-build || steps.promote.outcome == 'failure' ) }} 133 | config: |- 134 | true: 135 | builded: true 136 | image: ${{ steps.build.outputs.image }} 137 | tag: ${{ steps.build.outputs.tag }} 138 | false: 139 | builded: false 140 | image: ${{ steps.promote.outputs.image }} 141 | tag: ${{ steps.promote.outputs.tag }} 142 | 143 | - uses: cloudposse/github-action-secret-outputs@0.1.2 144 | id: image 145 | with: 146 | secret: ${{ secrets.secret-outputs-passphrase }} 147 | op: encode 148 | in: ${{ steps.result.outputs.image }} 149 | 150 | - uses: cloudposse/github-action-matrix-outputs-write@1.0.0 151 | id: outputs 152 | with: 153 | matrix-step-name: ${{ inputs.matrix-step-name }} 154 | matrix-key: ${{ inputs.matrix-key }} 155 | outputs: | 156 | image: ${{ steps.image.outputs.out }} 157 | tag: ${{ steps.result.outputs.tag }} 158 | 159 | outputs: 160 | builded: ${{ steps.result.outputs.builded }} 161 | image: ${{ fromJson(steps.outputs.outputs.result).image }} 162 | tag: ${{ fromJson(steps.outputs.outputs.result).tag }} 163 | 164 | test: 165 | runs-on: ${{ fromJSON(inputs.runs-on) }} 166 | if: ${{ needs.promote-or-build.outputs.builded == 'true' }} 167 | needs: [ promote-or-build ] 168 | steps: 169 | - name: Checkout 170 | uses: actions/checkout@v4 171 | 172 | - name: Configure AWS Credentials 173 | uses: aws-actions/configure-aws-credentials@v4.0.2 174 | with: 175 | aws-region: ${{ secrets.ecr-region }} 176 | role-to-assume: ${{ secrets.ecr-iam-role }} 177 | 178 | - name: Tests 179 | id: test 180 | uses: cloudposse/github-action-docker-compose-test-run@0.2.0 181 | with: 182 | workdir: ./apps/${{ inputs.app }} 183 | file: test/docker-compose.yml 184 | service: app 185 | command: test/test.sh 186 | registry: ${{ secrets.registry }} 187 | 188 | -------------------------------------------------------------------------------- /.github/workflows/ci-dockerized-app-promote.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CI - Promote Docker image 3 | 4 | Promote Docker image to specific version tag and push it to ECR 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Release 10 | on: 11 | release: 12 | types: [published] 13 | 14 | jobs: 15 | ci: 16 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-promote.yml@main 17 | with: 18 | organization: $\{\{ github.event.repository.owner.login \}\} 19 | repository: $\{\{ github.event.repository.name \}\} 20 | version: $\{\{ github.event.release.tag_name \}\} 21 | secrets: 22 | ecr-region: $\{\{ secrets.ecr-region \}\} 23 | ecr-iam-role: $\{\{ secrets.ecr-iam-role \}\} 24 | registry: $\{\{ secrets.registry \}\} 25 | secret-outputs-passphrase: $\{\{ secrets.secret-outputs-passphrase \}\} 26 | 27 | ``` 28 | 29 | on: 30 | workflow_call: 31 | inputs: 32 | organization: 33 | description: "Repository owner organization (ex. acme for repo acme/example)" 34 | required: true 35 | type: string 36 | repository: 37 | description: "Repository name (ex. example for repo acme/example)" 38 | required: true 39 | type: string 40 | app: 41 | description: "Application name. Used with monorepo pattern when there are several applications in the repo" 42 | required: false 43 | type: string 44 | version: 45 | description: "New version tag" 46 | required: true 47 | type: string 48 | matrix-step-name: 49 | description: "Matrix step name - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction)" 50 | required: false 51 | type: string 52 | matrix-key: 53 | description: "Matrix key - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction)" 54 | required: false 55 | type: string 56 | runs-on: 57 | description: "Overrides job runs-on setting (json-encoded list)" 58 | type: string 59 | required: false 60 | default: '["ubuntu-latest"]' 61 | secrets: 62 | ecr-region: 63 | description: "ECR AWS region" 64 | required: true 65 | ecr-iam-role: 66 | description: "IAM Role ARN provide ECR write/read access" 67 | required: true 68 | secret-outputs-passphrase: 69 | description: "Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs)" 70 | required: true 71 | registry: 72 | description: "ECR Docker registry" 73 | required: true 74 | outputs: 75 | image: 76 | description: "Docker Image" 77 | value: ${{ jobs.promote.outputs.image }} 78 | tag: 79 | description: "Docker image tag" 80 | value: ${{ jobs.promote.outputs.tag }} 81 | 82 | permissions: 83 | id-token: write 84 | contents: read 85 | 86 | jobs: 87 | promote: 88 | runs-on: ${{ fromJSON(inputs.runs-on) }} 89 | steps: 90 | - name: Configure AWS Credentials 91 | uses: aws-actions/configure-aws-credentials@v4.0.2 92 | with: 93 | aws-region: ${{ secrets.ecr-region }} 94 | role-to-assume: ${{ secrets.ecr-iam-role }} 95 | 96 | - name: Context 97 | id: context 98 | uses: cloudposse/github-action-yaml-config-query@0.1.3 99 | with: 100 | query: .${{ inputs.app == '' }} 101 | config: | 102 | true: 103 | image: ${{ inputs.repository }} 104 | false: 105 | image: ${{ inputs.repository }}/${{ inputs.app }} 106 | 107 | - uses: cloudposse/github-action-docker-promote@0.3.0 108 | id: promote 109 | with: 110 | registry: ${{ secrets.registry }} 111 | organization: ${{ inputs.organization }} 112 | repository: ${{ steps.context.outputs.image }} 113 | from: sha-${{ github.sha }} 114 | to: ${{ inputs.version }} 115 | use_metadata: false 116 | 117 | - uses: cloudposse/github-action-secret-outputs@0.1.2 118 | id: image 119 | with: 120 | secret: ${{ secrets.secret-outputs-passphrase }} 121 | op: encode 122 | in: ${{ steps.promote.outputs.image }} 123 | 124 | - uses: cloudposse/github-action-matrix-outputs-write@1.0.0 125 | id: outputs 126 | with: 127 | matrix-step-name: ${{ inputs.matrix-step-name }} 128 | matrix-key: ${{ inputs.matrix-key }} 129 | outputs: | 130 | image: ${{ steps.image.outputs.out }} 131 | tag: ${{ steps.promote.outputs.tag }} 132 | 133 | outputs: 134 | image: ${{ fromJson(steps.outputs.outputs.result).image }} 135 | tag: ${{ fromJson(steps.outputs.outputs.result).tag }} 136 | -------------------------------------------------------------------------------- /.github/workflows/ci-dockerized-app-verify.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CI - Verify Docker image exists 3 | 4 | Verify Docker image exists on ECR 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Release 10 | on: 11 | release: 12 | types: [published] 13 | 14 | jobs: 15 | ci: 16 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-verify.yml@main 17 | with: 18 | organization: $\{\{ github.event.repository.owner.login \}\} 19 | repository: $\{\{ github.event.repository.name \}\} 20 | version: $\{\{ github.event.release.tag_name \}\} 21 | secrets: 22 | ecr-region: $\{\{ secrets.ecr-region \}\} 23 | ecr-iam-role: $\{\{ secrets.ecr-iam-role \}\} 24 | registry: $\{\{ secrets.registry \}\} 25 | secret-outputs-passphrase: $\{\{ secrets.secret-outputs-passphrase \}\} 26 | 27 | ``` 28 | 29 | on: 30 | workflow_call: 31 | inputs: 32 | organization: 33 | description: "Repository owner organization (ex. acme for repo acme/example)" 34 | required: true 35 | type: string 36 | repository: 37 | description: "Repository name (ex. example for repo acme/example)" 38 | required: true 39 | type: string 40 | app: 41 | description: "Application name. Used with monorepo pattern when there are several applications in the repo" 42 | required: true 43 | type: string 44 | version: 45 | description: "Release version tag" 46 | required: true 47 | type: string 48 | runs-on: 49 | description: "Overrides job runs-on setting (json-encoded list)" 50 | type: string 51 | required: false 52 | default: '["self-hosted"]' 53 | secrets: 54 | ecr-region: 55 | description: "ECR AWS region" 56 | required: true 57 | ecr-iam-role: 58 | description: "IAM Role ARN provide ECR write/read access" 59 | required: true 60 | secret-outputs-passphrase: 61 | description: "Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs)" 62 | required: true 63 | registry: 64 | description: "ECR Docker registry" 65 | required: true 66 | outputs: 67 | image: 68 | description: "Docker Image" 69 | value: ${{ jobs.pull.outputs.image }} 70 | tag: 71 | description: "Docker image tag" 72 | value: ${{ jobs.pull.outputs.tag }} 73 | 74 | permissions: 75 | id-token: write 76 | contents: read 77 | 78 | jobs: 79 | pull: 80 | runs-on: ${{ fromJSON(inputs.runs-on) }} 81 | steps: 82 | - name: Configure AWS Credentials 83 | uses: aws-actions/configure-aws-credentials@v4.0.2 84 | with: 85 | aws-region: ${{ secrets.ecr-region }} 86 | role-to-assume: ${{ secrets.ecr-iam-role }} 87 | 88 | - uses: cloudposse/github-action-docker-image-exists@0.2.0 89 | id: pull 90 | with: 91 | organization: ${{ inputs.organization }} 92 | repository: ${{ inputs.repository }}/${{ inputs.app }} 93 | registry: ${{ secrets.registry }} 94 | tag: ${{ inputs.version }} 95 | 96 | - uses: cloudposse/github-action-secret-outputs@0.1.2 97 | id: image 98 | with: 99 | secret: ${{ secrets.secret-outputs-passphrase }} 100 | op: encode 101 | in: ${{ steps.pull.outputs.image }} 102 | 103 | outputs: 104 | image: ${{ steps.image.outputs.out }} 105 | tag: ${{ steps.pull.outputs.tag }} 106 | -------------------------------------------------------------------------------- /.github/workflows/ci-github-action.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CI - GitHub Action 3 | 4 | Lint and test github action 5 | 6 | ### Usage 7 | ```yaml 8 | name: Validate Terraform 9 | on: 10 | workflow_call: 11 | 12 | permissions: 13 | pull-requests: write 14 | id-token: write 15 | contents: read 16 | 17 | jobs: 18 | ci-terraform: 19 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-terraform.yml@main 20 | with: 21 | suggestions: true 22 | filter-mode: diff_context 23 | ``` 24 | on: 25 | workflow_call: 26 | inputs: 27 | organization: 28 | description: "Repository owner organization (ex. acme for repo acme/example)" 29 | required: false 30 | default: ${{ github.event.repository.owner.login }} 31 | type: string 32 | repository: 33 | description: "Repository name (ex. example for repo acme/example)" 34 | required: false 35 | default: ${{ github.event.repository.name }} 36 | type: string 37 | ref: 38 | description: "The fully-formed ref of the branch or tag that triggered the workflow run" 39 | required: false 40 | default: ${{ github.ref }} 41 | type: string 42 | tests-prefix: 43 | description: "Workflows file name prefix to run as tests" 44 | required: false 45 | type: string 46 | default: 'test-*' 47 | runs-on: 48 | description: "Overrides job runs-on setting (json-encoded list)" 49 | type: string 50 | required: false 51 | default: '["ubuntu-latest"]' 52 | 53 | permissions: 54 | contents: write 55 | actions: write 56 | 57 | jobs: 58 | context: 59 | runs-on: ${{ fromJSON(inputs.runs-on) }} 60 | steps: 61 | - name: Checkout main 62 | uses: actions/checkout@v4 63 | 64 | - name: Workflows 65 | id: workflows 66 | shell: bash 67 | run: | 68 | TEST_FILES=$(find ./.github/workflows -type f -name "${{ inputs.tests-prefix }}" -exec basename {} \; | jq -MRc -s '. | split("\n") | map(select(. != ""))') 69 | echo "list=${TEST_FILES}" >> $GITHUB_OUTPUT 70 | 71 | outputs: 72 | tests: ${{ steps.workflows.outputs.list }} 73 | 74 | lint: 75 | runs-on: ${{ fromJSON(inputs.runs-on) }} 76 | steps: 77 | - name: Checkout 78 | uses: actions/checkout@v4 79 | 80 | - name: YAML file validation 81 | uses: mpoc/nexus-validate-using-remote-schema-action@main 82 | with: 83 | api-endpoint: https://raw.githubusercontent.com/SchemaStore/schemastore/master/src/schemas/json/github-action.json 84 | yaml-file: action.yml 85 | 86 | test: 87 | runs-on: ${{ fromJSON(inputs.runs-on) }} 88 | if: ${{ needs.context.outputs.tests != '[]' }} 89 | strategy: 90 | matrix: 91 | env: ${{ fromJson(needs.context.outputs.tests) }} 92 | needs: [ lint, context ] 93 | steps: 94 | - uses: convictional/trigger-workflow-and-wait@v1.6.5 95 | with: 96 | owner: ${{ inputs.organization }} 97 | repo: ${{ inputs.repository }} 98 | github_token: ${{ github.token }} 99 | workflow_file_name: ${{ matrix.env }} 100 | ref: ${{ inputs.ref }} 101 | wait_interval: 10 102 | client_payload: '{}' 103 | propagate_failure: true 104 | trigger_workflow: true 105 | wait_workflow: true 106 | -------------------------------------------------------------------------------- /.github/workflows/ci-readme.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CI - Readme 3 | 4 | Validate README.yaml, README.md and suggest changes 5 | 6 | ### Usage 7 | ```yaml 8 | name: Validate Readme 9 | on: 10 | workflow_call: 11 | 12 | permissions: 13 | pull-requests: write 14 | id-token: write 15 | contents: read 16 | 17 | jobs: 18 | ci-readme: 19 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-readme.yml@main 20 | with: 21 | suggestions: true 22 | filter-mode: diff_context 23 | ``` 24 | on: 25 | workflow_call: 26 | inputs: 27 | ref: 28 | description: "Checkout ref" 29 | type: string 30 | required: false 31 | default: ${{ github.ref_name }} 32 | repository: 33 | description: "Checkout repository" 34 | type: string 35 | required: false 36 | default: ${{ github.repository }} 37 | runs-on: 38 | description: "Overrides job runs-on setting (json-encoded list)" 39 | type: string 40 | required: false 41 | default: '["ubuntu-latest"]' 42 | 43 | jobs: 44 | validate: 45 | runs-on: ${{ fromJSON(inputs.runs-on) }} 46 | name: "Readme" 47 | environment: release 48 | steps: 49 | - uses: actions/create-github-app-token@v1 50 | id: github-app 51 | with: 52 | app-id: ${{ vars.BOT_GITHUB_APP_ID }} 53 | private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} 54 | 55 | - name: Checkout 56 | uses: actions/checkout@v4 57 | with: 58 | ref: ${{ inputs.ref }} 59 | repository: ${{ inputs.repository }} 60 | fetch-depth: 0 61 | token: ${{ steps.github-app.outputs.token }} 62 | 63 | - uses: cloudposse-github-actions/readme@v0 64 | with: 65 | token: ${{ steps.github-app.outputs.token }} 66 | readme_enabled: true 67 | banner_enabled: true 68 | validate_readme: true 69 | commit_method: 'commit' 70 | commit_push_options: '--force-with-lease' 71 | -------------------------------------------------------------------------------- /.github/workflows/ci-terraform-chatops.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CI - Terraform ChatOps 3 | 4 | Trigger terraform tests using ChatOps 5 | 6 | ### Usage 7 | ```yaml 8 | name: Terraform ChatOps 9 | on: 10 | workflow_call: 11 | 12 | permissions: 13 | pull-requests: write 14 | id-token: write 15 | contents: read 16 | 17 | jobs: 18 | ci-terraform-chatops: 19 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-terraform-chatops.yml@main 20 | secrets: 21 | github_access_token: $\{\{ secrets.REPO_ACCESS_TOKEN \}\} 22 | ``` 23 | on: 24 | workflow_call: 25 | inputs: 26 | runs-on: 27 | description: "Overrides job runs-on setting (json-encoded list)" 28 | type: string 29 | required: false 30 | default: '["ubuntu-latest"]' 31 | secrets: 32 | github_access_token: 33 | description: "GitHub API token" 34 | required: true 35 | 36 | jobs: 37 | terratest: 38 | runs-on: ${{ fromJSON(inputs.runs-on) }} 39 | steps: 40 | - name: Checkout 41 | uses: actions/checkout@v4 42 | 43 | - uses: cloudposse/actions/github/slash-command-dispatch@0.33.0 44 | with: 45 | token: ${{ secrets.github_access_token }} 46 | repository: cloudposse/actions 47 | commands: terratest 48 | permission: triage 49 | issue-type: pull-request 50 | reactions: false 51 | -------------------------------------------------------------------------------- /.github/workflows/ci-terraform.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CI - Terraform 3 | 4 | Lint, format and validate terraform code 5 | 6 | ### Usage 7 | ```yaml 8 | name: Validate Terraform 9 | on: 10 | workflow_call: 11 | 12 | permissions: 13 | pull-requests: write 14 | id-token: write 15 | contents: read 16 | 17 | jobs: 18 | ci-terraform: 19 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-terraform.yml@main 20 | with: 21 | suggestions: true 22 | filter-mode: diff_context 23 | ``` 24 | on: 25 | workflow_call: 26 | inputs: 27 | suggestions: 28 | description: "Enable Reviewdog suggestions (pull request only)" 29 | type: boolean 30 | required: true 31 | filter-mode: 32 | description: "Reviewdog filter mode" 33 | type: string 34 | required: true 35 | runs-on: 36 | description: "Overrides job runs-on setting (json-encoded list)" 37 | type: string 38 | required: false 39 | default: '["ubuntu-latest"]' 40 | 41 | jobs: 42 | format: 43 | runs-on: ${{ fromJSON(inputs.runs-on) }} 44 | name: Format HCL 45 | steps: 46 | - name: Checkout 47 | uses: actions/checkout@v4 48 | 49 | - name: Terraform format 50 | uses: dflook/terraform-fmt@v1 51 | 52 | - name: Reviewdog suggester 53 | if: ${{ inputs.suggestions }} 54 | uses: reviewdog/action-suggester@v1 55 | with: 56 | tool_name: "terraform fmt -recursive" 57 | cleanup: false 58 | filter_mode: ${{ inputs.filter-mode }} 59 | 60 | - name: Status check 61 | shell: bash 62 | run: git diff --exit-code 63 | 64 | bats: 65 | runs-on: ubuntu-latest 66 | container: cloudposse/test-harness:latest 67 | env: 68 | MAKE_INCLUDES: Makefile 69 | TF_PLUGIN_CACHE_DIR: /tmp 70 | BATS_MODULE_TESTS: input-descriptions module-pinning provider-pinning output-descriptions 71 | BATS_EXAMPLES_TESTS: input-descriptions lint output-descriptions 72 | steps: 73 | - name: Checkout 74 | uses: actions/checkout@v4 75 | with: 76 | fetch-depth: 0 77 | 78 | - name: Run tests on modified modules 79 | shell: bash -x -e -o pipefail {0} 80 | run: | 81 | # when running in test-harness, need to mark the directory safe for git operations 82 | make git-safe-directory 83 | MODIFIED_MODULES=($(find . -type f -name "*.tf" | xargs -I{} dirname {} | sort | uniq | grep -v ^./.git/ || true)) 84 | pass=true 85 | for relative_dir in "${MODIFIED_MODULES[@]}"; do 86 | dir=$(realpath $relative_dir) 87 | printf "\n\nBegin testing in $dir\n" 88 | ( 89 | status=pass 90 | cd $dir 91 | [[ $relative_dir =~ ./examples/.* ]] && tests=$BATS_EXAMPLES_TESTS || tests=$BATS_MODULE_TESTS 92 | for test in $tests; do 93 | printf "\n\nRunning ${test} in $dir\n" 94 | bats -t /test/terraform/${test}.bats || status=fail 95 | done 96 | [[ $status == "pass" ]] 97 | ) || pass=false 98 | printf "\n\nEnd of testing in $dir\n\n\n" 99 | done 100 | [[ $pass == "true" ]] 101 | 102 | lint-find-dirs: 103 | name: Find modules 104 | runs-on: ${{ fromJSON(inputs.runs-on) }} 105 | steps: 106 | - uses: actions/checkout@v4 107 | 108 | - id: set-matrix 109 | # Ignore directories whose names start with .terraform or obsolete 110 | run: | 111 | matrix=$(find . -type d \( -name '.terraform*' -o -name 'obsolete*' \) -prune -o \ 112 | -name '*.tf' \ 113 | -not -path '*/.terraform/*' \ 114 | -exec dirname {} \; \ 115 | | sort \ 116 | | uniq \ 117 | | jq --raw-input --slurp 'split("\n")| map(select(. != ""))') 118 | echo "matrix=$(echo $matrix)" >> $GITHUB_OUTPUT 119 | outputs: 120 | tfdirs_matrix: ${{ steps.set-matrix.outputs.matrix }} 121 | 122 | lint: 123 | runs-on: ${{ fromJSON(inputs.runs-on) }} 124 | name: Lint (${{ matrix.tfdir }}) 125 | needs: lint-find-dirs 126 | strategy: 127 | fail-fast: false 128 | matrix: 129 | tfdir: ${{ fromJson(needs.lint-find-dirs.outputs.tfdirs_matrix) }} 130 | env: 131 | TFLINT_PLUGIN_DIR: ${{ github.workspace }}/.tflint.d/plugins 132 | TFLINT_PLUGINS: aws 133 | TFLINT_CACHE_VER: 1 # Increment this to force a cache refresh 134 | steps: 135 | - uses: actions/checkout@v4 136 | 137 | - uses: hashicorp/setup-terraform@v3 138 | 139 | - run: terraform init 140 | working-directory: ${{ matrix.tfdir }} 141 | 142 | - name: cache tflint plugins 143 | id: cache-plugins 144 | uses: actions/cache@v4 145 | with: 146 | path: ${{ env.TFLINT_PLUGIN_DIR }} 147 | key: tflint-plugins-${{ env.TFLINT_CACHE_VER }} 148 | 149 | - name: tflint 150 | uses: reviewdog/action-tflint@v1.22.0 151 | with: 152 | reporter: ${{ inputs.suggestions && 'github-pr-annotations' || 'local' }} 153 | fail_on_error: ${{ inputs.suggestions }} 154 | tflint_rulesets: ${{ env.TFLINT_PLUGINS }} 155 | tflint_init: true 156 | working_directory: ${{ matrix.tfdir }} 157 | filter_mode: ${{ inputs.filter-mode }} 158 | tflint_version: "v0.49.0" 159 | -------------------------------------------------------------------------------- /.github/workflows/ci-typescript-app-check-dist.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | CI - Check dist Directory 3 | 4 | This workflow helps ensure that generated contents of the `dist` directory matches the output of the `yarn build` 5 | command. The `dist` directory has special meaning in GitHub Actions in that it that contains the runnable JS files. 6 | 7 | In Cloud Posse's TypeScript actions, the `dist` directory is generated through a build process from the TypeScript 8 | source files by running the `yarn build` command. 9 | 10 | 11 | ### Usage 12 | 13 | ```yaml 14 | name: Build 15 | on: 16 | push: 17 | branches: [ main ] 18 | 19 | jobs: 20 | check-dist: 21 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-typescript-app-check-dist.yml@main 22 | ``` 23 | 24 | on: 25 | workflow_call: 26 | inputs: 27 | commit-message: 28 | description: 29 | "Optional input to set a commit message. If it's not set, it defaults to 'Update the contents of dist 30 | directory'" 31 | required: false 32 | type: string 33 | default: "Update contents of the dist directory" 34 | dist-path: 35 | description: "Optional input to set a path to the dist folder. If it's not set, it defaults to './dist'" 36 | required: false 37 | type: string 38 | default: "./dist" 39 | node-version: 40 | description: 41 | "Optional input to set the version of Node.js used to build a project. The input syntax corresponds to the 42 | setup-node's one" 43 | required: false 44 | type: string 45 | default: "16.x" 46 | node-caching: 47 | description: 48 | "Optional input to set up caching for the setup-node action. The input syntax corresponds to the setup-node's 49 | one. Set to an empty string if caching isn't needed" 50 | required: false 51 | type: string 52 | default: "yarn" 53 | runs-on: 54 | description: "Overrides job runs-on setting (json-encoded list)" 55 | type: string 56 | required: false 57 | default: '["ubuntu-latest"]' 58 | 59 | jobs: 60 | check-dist: 61 | runs-on: ${{ fromJSON(inputs.runs-on) }} 62 | 63 | permissions: 64 | contents: write 65 | 66 | steps: 67 | - name: Checkout 68 | uses: actions/checkout@v4 69 | with: 70 | ref: ${{ github.head_ref }} 71 | 72 | - name: Setup Node.js ${{inputs.node-version}} 73 | uses: actions/setup-node@v4 74 | with: 75 | node-version: ${{inputs.node-version}} 76 | cache: ${{inputs.node-caching}} 77 | 78 | - name: Install dependencies 79 | run: yarn install --frozen-lockfile --prefer-offline 80 | 81 | - name: Rebuild the dist directory 82 | run: yarn build 83 | 84 | - name: Compare the expected and actual dist directories 85 | run: | 86 | if [ "$(git diff --ignore-space-at-eol ${{inputs.dist-path}} | wc -l)" -gt "0" ]; then 87 | echo "Detected uncommitted changes after the build. See the status below:" 88 | git diff 89 | echo "has-diff=true" >> $GITHUB_OUTPUT 90 | else 91 | echo "has-diff=false" >> $GITHUB_OUTPUT 92 | fi 93 | id: diff 94 | 95 | # If contents of the dist directory were different than expected, commit the changes and push them to the repo 96 | - name: Commit and Push Changes 97 | if: ${{steps.diff.outputs.has-diff == 'true'}} 98 | uses: stefanzweifel/git-auto-commit-action@v5 99 | with: 100 | commit_message: ${{inputs.commit-message}} 101 | file_pattern: ${{inputs.dist-path}} 102 | -------------------------------------------------------------------------------- /.github/workflows/controller-atmos-affected-stacks.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | Controller - Atmos affected stacks 3 | 4 | Get stacks affected in the commit 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Stacks affected 10 | on: 11 | push: 12 | branches: [ main ] 13 | 14 | jobs: 15 | do: 16 | uses: cloudposse/github-actions-workflows/.github/workflows/controller-atmos-affected-stacks.yml@main 17 | ``` 18 | 19 | on: 20 | workflow_call: 21 | inputs: 22 | head-ref: 23 | description: The head ref to checkout. If not provided, the head default branch is used. 24 | type: string 25 | required: false 26 | runs-on: 27 | description: "Overrides job runs-on setting (json-encoded list)" 28 | type: string 29 | required: false 30 | default: '["ubuntu-latest"]' 31 | outputs: 32 | stacks: 33 | description: "Affected stacks" 34 | value: ${{ jobs.get-affected-property-stacks.outputs.matrix }} 35 | has-affected-stacks: 36 | description: "Has affected stacks" 37 | value: ${{ jobs.get-affected-property-stacks.outputs.has-affected-stacks }} 38 | 39 | jobs: 40 | get-affected-property-stacks: 41 | runs-on: ${{ fromJSON(inputs.runs-on) }} 42 | outputs: 43 | matrix: ${{ steps.matrix.outputs.matrix }} 44 | has-affected-stacks: ${{ steps.matrix.outputs.matrix!='{"include":[]}'}} 45 | steps: 46 | - uses: actions/checkout@v4 47 | - id: affected 48 | uses: cloudposse/github-action-atmos-affected-stacks@1.2.0 49 | with: 50 | head-ref: ${{ inputs.head-ref }} 51 | - id: matrix 52 | run: | 53 | matrix=$(echo ${{ steps.affected.outputs.affected }} | jq -c '{include:[.[]]}') 54 | echo "matrix=$matrix" >> $GITHUB_OUTPUT 55 | -------------------------------------------------------------------------------- /.github/workflows/controller-atmos-github-workflows.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | Controller - Atmos affected stacks 3 | 4 | Get stacks affected in the commit 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Stacks affected 10 | on: 11 | push: 12 | branches: [ main ] 13 | 14 | jobs: 15 | do: 16 | uses: cloudposse/github-actions-workflows/.github/workflows/controller-atmos-affected-stacks.yml@main 17 | ``` 18 | 19 | on: 20 | workflow_call: 21 | inputs: 22 | stacks: 23 | description: Stacks 24 | required: false 25 | type: string 26 | runs-on: 27 | description: "Overrides job runs-on setting (json-encoded list)" 28 | type: string 29 | required: false 30 | default: '["ubuntu-latest"]' 31 | 32 | jobs: 33 | create-files: 34 | runs-on: ${{ fromJSON(inputs.runs-on) }} 35 | steps: 36 | - name: Checkout 37 | uses: actions/checkout@v4 38 | 39 | - uses: finnp/create-file-action@2.0.0 40 | env: 41 | FILE_NAME: ./tmp/template.jsonnet 42 | FILE_DATA: |- 43 | local result=[ 44 | { 45 | ['stack-' + x + '.yml']: std.manifestYamlDoc({ 46 | name: 'Stack ' + x, 47 | on: { 48 | workflow_dispatch: {}, 49 | }, 50 | permissions: { 51 | deployments: 'write', 52 | "id-token": 'write', 53 | contents: 'read', 54 | }, 55 | jobs: { 56 | do: { 57 | uses: 'cloudposse/github-actions-workflows-atmos/.github/workflows/stack-deploy.yml@main', 58 | with: { 59 | stack: x, 60 | component: x, 61 | environment: x, 62 | }, 63 | secrets: { 64 | "github-private-actions-pat": '$\{\{ secrets.PUBLIC_REPO_ACCESS_TOKEN \}\}', 65 | }, 66 | }, 67 | }, 68 | }) 69 | } 70 | for x in stacks ]; 71 | 72 | result[0] 73 | 74 | - id: jsonnet-render 75 | uses: alexdglover/jsonnet-render@v2 76 | with: 77 | file: ./tmp/template.jsonnet 78 | output_dir: .github/workflows/ 79 | params: stacks=${{ inputs.stacks }} 80 | 81 | - run: | 82 | ls -l .github/workflows/ 83 | -------------------------------------------------------------------------------- /.github/workflows/controller-draft-release.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | Controller - Draft release 3 | 4 | Create or update draft release 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Draft release 10 | on: 11 | push: 12 | branches: [ main ] 13 | 14 | jobs: 15 | do: 16 | uses: cloudposse/github-actions-workflows/.github/workflows/controller-draft-release.yml@main 17 | with: 18 | ref: $\{\{ github.sha \}\} 19 | secrets: 20 | github-private-actions-pat: $\{\{ secrets.github-private-actions-pat \}\} 21 | 22 | ``` 23 | 24 | on: 25 | workflow_call: 26 | inputs: 27 | ref: 28 | description: "The release target, i.e. branch or commit it should point to" 29 | required: false 30 | default: ${{ github.sha }} 31 | type: string 32 | runs-on: 33 | description: "Overrides job runs-on setting (json-encoded list)" 34 | type: string 35 | required: false 36 | default: '["ubuntu-latest"]' 37 | 38 | secrets: 39 | github-private-actions-pat: 40 | description: "Github PAT allow to create release" 41 | required: true 42 | jobs: 43 | draft: 44 | runs-on: ${{ fromJSON(inputs.runs-on) }} 45 | steps: 46 | # Drafts your next Release notes as Pull Requests are merged into "master" 47 | - name: Create/Update Draft release 48 | uses: release-drafter/release-drafter@v6 49 | with: 50 | publish: false 51 | prerelease: false 52 | config-name: configs/draft-release.yml 53 | commitish: ${{ inputs.ref }} 54 | env: 55 | GITHUB_TOKEN: ${{ secrets.github-private-actions-pat }} 56 | -------------------------------------------------------------------------------- /.github/workflows/controller-hotfix-reintegrate.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | Controller - Reingtegrate hotfix branch 3 | 4 | Create PR into `target_branch` to reintegrate hotfix from current branch 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Release 10 | on: 11 | release: 12 | types: [published] 13 | 14 | jobs: 15 | do: 16 | uses: cloudposse/github-action-workflows/.github/workflows/controller-hotfix-reintegrate.yml@main 17 | with: 18 | ref: $\{\{ github.ref \}\} 19 | target_branch: main 20 | secrets: 21 | github-private-actions-pat: $\{\{ secrets.github-private-actions-pat \}\} 22 | ``` 23 | 24 | on: 25 | workflow_call: 26 | inputs: 27 | ref: 28 | description: "The fully-formed ref of the branch or tag that triggered the workflow run" 29 | required: true 30 | type: string 31 | target_branch: 32 | description: "Target branch to reintegrate hotfix" 33 | required: false 34 | type: string 35 | default: main 36 | runs-on: 37 | description: "Overrides job runs-on setting (json-encoded list)" 38 | type: string 39 | required: false 40 | default: '["ubuntu-latest"]' 41 | secrets: 42 | github-private-actions-pat: 43 | description: "Github PAT allow to create a pull request" 44 | required: true 45 | jobs: 46 | changes: 47 | runs-on: ${{ fromJSON(inputs.runs-on) }} 48 | steps: 49 | - name: Checkout 50 | uses: actions/checkout@v4 51 | with: 52 | fetch-depth: 0 53 | ref: ${{ inputs.ref }} 54 | 55 | - name: Create reingtegration PR 56 | uses: devops-infra/action-pull-request@v0.5.5 57 | with: 58 | github_token: ${{ secrets.github-private-actions-pat }} 59 | target_branch: ${{ inputs.target_branch }} 60 | title: Reintegrate ${{ inputs.ref }} hotfix into main branch 61 | template: .github/REINTEGRATE_PULL_REQUEST_TEMPLATE.md 62 | get_diff: true 63 | -------------------------------------------------------------------------------- /.github/workflows/controller-hotfix-release-branch.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | Controller - Create Release branch 3 | 4 | Create `release/{version}` branch for the release 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Main branch 10 | on: 11 | release: 12 | types: [published] 13 | 14 | jobs: 15 | do: 16 | uses: cloudposse/github-action-workflows/.github/workflows/controller-hotfix-release-branch.yml@main 17 | with: 18 | version: $\{\{ github.event.release.tag_name \}\} 19 | ``` 20 | 21 | on: 22 | workflow_call: 23 | inputs: 24 | version: 25 | description: "Release version" 26 | required: true 27 | type: string 28 | runs-on: 29 | description: "Overrides job runs-on setting (json-encoded list)" 30 | type: string 31 | required: false 32 | default: '["ubuntu-latest"]' 33 | 34 | jobs: 35 | release-branch: 36 | runs-on: ${{ fromJSON(inputs.runs-on) }} 37 | steps: 38 | - name: Checkout 39 | uses: actions/checkout@v4 40 | 41 | - name: Create branch for specific version 42 | uses: satya-500/create-branch-from-tag@v1.0 43 | env: 44 | GITHUB_TOKEN: ${{ github.token }} 45 | with: 46 | branch: release/${{ inputs.version }} 47 | from: tags/${{ inputs.version }} 48 | 49 | -------------------------------------------------------------------------------- /.github/workflows/controller-hotfix-release.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | Controller - Create hotfix release 3 | 4 | Create next patch version release 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | on: 10 | push: 11 | branches: [ 'release/**' ] 12 | 13 | jobs: 14 | do: 15 | uses: cloudposse/github-action-workflows/.github/workflows/controller-hotfix-release.yml@main 16 | with: 17 | ref: $\{\{ github.ref \}\} 18 | ``` 19 | 20 | on: 21 | workflow_call: 22 | inputs: 23 | ref: 24 | description: "The fully-formed ref of the branch or tag that triggered the workflow run" 25 | required: true 26 | type: string 27 | runs-on: 28 | description: "Overrides job runs-on setting (json-encoded list)" 29 | type: string 30 | required: false 31 | default: '["ubuntu-latest"]' 32 | outputs: 33 | version: 34 | description: Release version 35 | value: ${{ jobs.create.outputs.version }} 36 | jobs: 37 | create: 38 | runs-on: ${{ fromJSON(inputs.runs-on) }} 39 | steps: 40 | - name: Checkout 41 | uses: actions/checkout@v4 42 | with: 43 | ref: ${{ inputs.ref }} 44 | fetch-depth: 0 45 | 46 | - name: Get Previous tag 47 | id: previoustag 48 | shell: sh 49 | run: | 50 | git fetch --tags --force 51 | git describe --always --tags --abbrev=0 ${{ inputs.ref }} 52 | ## Return a prev tag that points to any commit prev to the current. 53 | ## If no tag - return SHA 54 | ANY_VERSION=$(git describe --always --tags --abbrev=0 ${{ inputs.ref }}) 55 | ## Get latest tag pointing to the specific commit 56 | ## If no tag - return SHA 57 | VERSION=$( ( echo ${ANY_VERSION} && git tag --points-at ${ANY_VERSION} ) | tail -1 ) 58 | echo "version=${VERSION}" >> $GITHUB_OUTPUT 59 | 60 | - name: Get next minor version 61 | id: semvers 62 | uses: "WyriHaximus/github-action-next-semvers@v1" 63 | with: 64 | version: ${{ steps.previoustag.outputs.version }} 65 | 66 | - name: Create release 67 | uses: ncipollo/release-action@v1 68 | with: 69 | tag: ${{ steps.semvers.outputs.patch }} 70 | commit: ${{ inputs.ref }} 71 | generateReleaseNotes: true 72 | token: ${{ github.token }} 73 | 74 | outputs: 75 | version: ${{ steps.semvers.outputs.patch }} 76 | -------------------------------------------------------------------------------- /.github/workflows/controller-labels.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | Controller - Labels 3 | 4 | Label a pull request with one or more labels 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Label pull request 10 | on: 11 | workflow_call: 12 | 13 | jobs: 14 | label: 15 | uses: cloudposse/github-actions-workflows/.github/workflows/controller-labels.yml@main 16 | with: 17 | labels: ['ready-for-review'] 18 | ``` 19 | 20 | on: 21 | workflow_call: 22 | inputs: 23 | labels: 24 | description: The labels' name to be added. Must be separated with line breaks if there are multiple labels. 25 | type: string 26 | required: true 27 | runs-on: 28 | description: "Overrides job runs-on setting (json-encoded list)" 29 | type: string 30 | required: false 31 | default: '["ubuntu-latest"]' 32 | 33 | jobs: 34 | add-labels: 35 | runs-on: ${{ fromJSON(inputs.runs-on) }} 36 | steps: 37 | - name: Checkout 38 | uses: actions/checkout@v4 39 | 40 | - name: Add labels 41 | uses: actions-ecosystem/action-add-labels@v1 42 | with: 43 | labels: ${{ inputs.labels }} -------------------------------------------------------------------------------- /.github/workflows/controller-monorepo.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | Controller - Monorepo Controller 3 | 4 | Mocked monorepo controller that outputs list of applications, lists of apps with and without changes. 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: Monorepo 10 | on: 11 | push: 12 | branches: [ main ] 13 | 14 | jobs: 15 | do: 16 | uses: cloudposse/github-actions-workflows/.github/workflows/controller-monorepo.yml@main 17 | with: 18 | dir: ./apps 19 | ``` 20 | 21 | on: 22 | workflow_call: 23 | inputs: 24 | dir: 25 | description: Directory with applications 26 | required: true 27 | type: string 28 | runs-on: 29 | description: "Overrides job runs-on setting (json-encoded list)" 30 | type: string 31 | required: false 32 | default: '["ubuntu-latest"]' 33 | outputs: 34 | apps: 35 | description: "Applications" 36 | value: ${{ jobs.monorepo.outputs.apps }} 37 | changes: 38 | description: "Changed applications" 39 | value: ${{ jobs.monorepo.outputs.changes }} 40 | no-changes: 41 | description: "Unchanged applications" 42 | value: ${{ jobs.monorepo.outputs.no-changes }} 43 | 44 | jobs: 45 | monorepo: 46 | runs-on: ${{ fromJSON(inputs.runs-on) }} 47 | steps: 48 | - name: Checkout 49 | uses: actions/checkout@v4 50 | 51 | - name: Monorepo controller 52 | id: controller 53 | uses: cloudposse/github-action-monorepo-random-controller@0.2.0 54 | with: 55 | dir: ${{ inputs.dir }} 56 | 57 | outputs: 58 | apps: ${{ steps.controller.outputs.apps }} 59 | changes: ${{ steps.controller.outputs.changes }} 60 | no-changes: ${{ steps.controller.outputs.no-changes }} 61 | -------------------------------------------------------------------------------- /.github/workflows/controller-release-branches.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | Controller - Managing Release Branches and Tags 3 | 4 | Manages long-living release branches and their releases 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: release 10 | on: 11 | release: 12 | types: 13 | - published 14 | 15 | permissions: 16 | contents: write 17 | id-token: write 18 | 19 | jobs: 20 | terraform-module: 21 | uses: cloudposse/github-actions-workflows/.github/workflows/controller-release-branches.yml@main 22 | 23 | ``` 24 | 25 | on: 26 | workflow_call: 27 | inputs: 28 | runs-on: 29 | description: "Overrides job runs-on setting (json-encoded list)" 30 | type: string 31 | required: false 32 | default: '["ubuntu-latest"]' 33 | 34 | jobs: 35 | major-release-tagger: 36 | runs-on: ${{ fromJSON(inputs.runs-on) }} 37 | steps: 38 | - uses: cloudposse/github-action-major-release-tagger@v1 39 | 40 | release-branch-manager: 41 | runs-on: ${{ fromJSON(inputs.runs-on) }} 42 | steps: 43 | - uses: cloudposse/github-action-release-branch-manager@v1 -------------------------------------------------------------------------------- /.github/workflows/controller-release.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | Controller - Release 3 | 4 | Create a github release 5 | 6 | ### Usage 7 | 8 | ```yaml 9 | name: release-branch 10 | on: 11 | push: 12 | branches: 13 | - main 14 | - release/** 15 | 16 | permissions: 17 | contents: write 18 | id-token: write 19 | 20 | jobs: 21 | release: 22 | uses: cloudposse/github-actions-workflows/.github/workflows/controller-release.yml@main 23 | 24 | ``` 25 | 26 | on: 27 | workflow_call: 28 | inputs: 29 | ref_name: 30 | description: "The release target, i.e. branch to release from" 31 | required: false 32 | default: ${{ github.ref_name }} 33 | type: string 34 | sha: 35 | description: "Pull request merge commit sha" 36 | required: false 37 | default: ${{ github.sha }} 38 | type: string 39 | config-name: 40 | description: "Name of the release drafter config file" 41 | required: false 42 | default: auto-release.yml 43 | type: string 44 | publish: 45 | description: "Publish github release if true and no-release PR label is not set." 46 | required: false 47 | default: true 48 | type: boolean 49 | runs-on: 50 | description: "Overrides job runs-on setting (json-encoded list)" 51 | type: string 52 | required: false 53 | default: '["ubuntu-latest"]' 54 | secrets: 55 | github_access_token: 56 | description: "GitHub API token" 57 | required: false 58 | 59 | jobs: 60 | release: 61 | runs-on: ${{ fromJSON(inputs.runs-on) }} 62 | steps: 63 | - name: Checkout 64 | uses: actions/checkout@v4 65 | with: 66 | fetch-depth: 0 67 | 68 | - name: Fetch pull request for the given ref 69 | id: get-pull-request 70 | uses: cloudposse-github-actions/get-pr@v1 71 | with: 72 | sha: ${{ inputs.sha }} 73 | 74 | - name: Check duplicate 75 | id: check-duplicate 76 | run: | 77 | latest_hash=$(git rev-parse ${{ github.ref_name }}) 78 | tags=$(git tag --contains "$latest_hash") 79 | if [[ -n $tags ]]; then 80 | echo "duplicate=true" >> "$GITHUB_OUTPUT" 81 | else 82 | echo "duplicate=false" >> "$GITHUB_OUTPUT" 83 | fi 84 | 85 | - name: Do release 86 | if: steps.check-duplicate.outputs.duplicate == 'false' 87 | id: release 88 | uses: release-drafter/release-drafter@v6 89 | with: 90 | publish: ${{ inputs.publish && !contains(steps.get-pull-request.outputs.labels, 'no-release') }} 91 | config-name: ${{ inputs.config-name }} 92 | commitish: ${{ inputs.ref_name }} 93 | env: 94 | GITHUB_TOKEN: ${{ secrets.github_access_token || secrets.GITHUB_TOKEN }} 95 | 96 | - name: Verify release # Workaround for https://github.com/release-drafter/release-drafter/issues/1313 97 | if: steps.check-duplicate.outputs.duplicate == 'false' 98 | shell: bash 99 | run: | 100 | echo 'Checking release id not empty: "${{ steps.release.outputs.id }}"' 101 | ! test -z "${{ steps.release.outputs.id }}" 102 | -------------------------------------------------------------------------------- /.github/workflows/scheduled-context.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | Scheduled Context 3 | 4 | Scheduled update of context.tf and related docs 5 | 6 | ### Usage 7 | ```yaml 8 | name: scheduled-context 9 | on: 10 | workflow_call: 11 | 12 | permissions: 13 | pull-requests: write 14 | id-token: write 15 | contents: read 16 | 17 | jobs: 18 | scheduled-context: 19 | uses: cloudposse/github-actions-workflows/.github/workflows/scheduled-context.yml@main 20 | ``` 21 | on: 22 | workflow_call: 23 | inputs: 24 | base-branch: 25 | description: "Repo default branch" 26 | type: string 27 | required: false 28 | default: 'main' 29 | runs-on: 30 | description: "Overrides job runs-on setting (json-encoded list)" 31 | type: string 32 | required: false 33 | default: '["ubuntu-latest"]' 34 | secrets: 35 | github_access_token: 36 | description: "GitHub API token" 37 | required: true 38 | 39 | jobs: 40 | update: 41 | runs-on: ${{ fromJSON(inputs.runs-on) }} 42 | steps: 43 | - name: Checkout 44 | uses: actions/checkout@v4 45 | 46 | - name: Update context.tf 47 | shell: bash 48 | id: update 49 | env: 50 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 51 | run: | 52 | if [[ -f context.tf ]]; then 53 | echo "Discovered existing context.tf! Fetching most recent version to see if there is an update." 54 | curl -o context.tf -fsSL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf 55 | if git diff --no-patch --exit-code context.tf; then 56 | echo "No changes detected! Exiting the job..." 57 | else 58 | echo "context.tf file has changed. Update examples and rebuild README.md." 59 | make init 60 | make github/init/context.tf 61 | make readme/build 62 | echo "create_pull_request=true" >> $GITHUB_OUTPUT 63 | fi 64 | else 65 | echo "This module has not yet been updated to support the context.tf pattern! Please update in order to support automatic updates." 66 | fi 67 | 68 | - name: Create Pull Request 69 | if: steps.update.outputs.create_pull_request == 'true' 70 | uses: cloudposse/actions/github/create-pull-request@0.33.0 71 | with: 72 | commit-message: Update context.tf from origin source 73 | title: Update context.tf 74 | body: |- 75 | ## what 76 | This is an auto-generated PR that updates the `context.tf` file to the latest version from `cloudposse/terraform-null-label` 77 | 78 | ## why 79 | To support all the features of the `context` interface. 80 | 81 | branch: auto-update/context.tf 82 | base: ${{ inputs.base-branch }} 83 | delete-branch: true 84 | labels: | 85 | auto-update 86 | context 87 | # Requires a GitHub PAT used to open PRs that trigger other workflows 88 | # https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow 89 | token: ${{ secrets.github_access_token }} -------------------------------------------------------------------------------- /.github/workflows/scheduled-readme.yml: -------------------------------------------------------------------------------- 1 | name: |- 2 | Scheduled Readme 3 | 4 | Scheduled update of readme.md 5 | 6 | ### Usage 7 | ```yaml 8 | name: scheduled-readme 9 | on: 10 | workflow_call: 11 | 12 | permissions: 13 | pull-requests: write 14 | id-token: write 15 | contents: read 16 | 17 | jobs: 18 | scheduled-readme: 19 | uses: cloudposse/github-actions-workflows/.github/workflows/scheduled-readme.yml@main 20 | ``` 21 | on: 22 | workflow_call: 23 | inputs: 24 | base-branch: 25 | description: "Repo default branch" 26 | type: string 27 | required: false 28 | default: 'main' 29 | runs-on: 30 | description: "Overrides job runs-on setting (json-encoded list)" 31 | type: string 32 | required: false 33 | default: '["ubuntu-latest"]' 34 | 35 | jobs: 36 | ci-readme: 37 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-readme.yml@main 38 | with: 39 | runs-on: ${{ inputs.runs-on }} 40 | secrets: inherit 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .build-harness 2 | build-harness -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | 3 | # List of targets the `readme` target should call before generating the readme 4 | export README_DEPS ?= docs/github-actions-reusable-workflows.md 5 | 6 | -include $(shell curl -sSL -o .build-harness "https://cloudposse.tools/build-harness"; echo .build-harness) 7 | -------------------------------------------------------------------------------- /README.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | # 3 | # This is the canonical configuration for the `README.md` 4 | # Run `make readme` to rebuild the `README.md` 5 | # 6 | 7 | # Name of this project 8 | name: github-actions-workflows 9 | 10 | # Tags of this project 11 | tags: 12 | - github-action 13 | - release workflows 14 | - CI/CD 15 | 16 | # Logo for this project 17 | #logo: docs/logo.png 18 | 19 | # License of this project 20 | license: "APACHE2" 21 | 22 | # Canonical GitHub repo 23 | github_repo: cloudposse/github-actions-workflows 24 | 25 | # Badges to display 26 | badges: 27 | - name: "Latest Release" 28 | image: "https://img.shields.io/github/release/cloudposse/github-actions-workflows.svg" 29 | url: "https://github.com/cloudposse/github-actions-workflows/releases/latest" 30 | - name: "Slack Community" 31 | image: "https://slack.cloudposse.com/badge.svg" 32 | url: "https://slack.cloudposse.com" 33 | 34 | related: [] 35 | 36 | # Short description of this project 37 | description: General purpose reusable Github Action workflows 38 | 39 | introduction: |- 40 | Use provided [GitHub Actions reusable workflows](https://docs.github.com/en/actions/using-workflows/reusing-workflows) 41 | to implement consistent release workflow for Github Actions repositories across your organization. 42 | Avoid duplication and simplify maintain of the workflows. 43 | 44 | references: 45 | - name: "github-actions-workflows" 46 | description: "Reusable workflows for different types of projects" 47 | url: "https://github.com/cloudposse/github-actions-workflows" 48 | - name: "github-action-docker-build-push" 49 | description: "Simple docker build action" 50 | url: "https://github.com/cloudposse/github-action-docker-build-push" 51 | 52 | include: 53 | - "docs/github-actions-reusable-workflows.md" 54 | 55 | # Contributors to this project 56 | contributors: 57 | - name: "Igor Rodionov" 58 | github: "goruha" -------------------------------------------------------------------------------- /docs/github-actions-reusable-workflows.md: -------------------------------------------------------------------------------- 1 | 2 | ## Workflows 3 | 4 | | Name | Description | 5 | |------|-------------| 6 | | [CD - Deploy to EKS with ArgoCD and Helmfile](#cd---deploy-to-eks-with-argocd-and-helmfile) | Deploy Docker image to EKS with ArgoCD and Helmfile | 7 | | [CD - Deploy to ECS with Spacelift](#cd---deploy-to-ecs-with-spacelift) | Deploy Docker image to ECS with Spacelift | 8 | | [CD - Deploy to EKS with Helmfile](#cd---deploy-to-eks-with-helmfile) | Deploy Docker image to EKS with Helmfile | 9 | | [CD - Deploy to EKS Preview envs with Helmfile](#cd---deploy-to-eks-preview-envs-with-helmfile) | Deploy Docker image to ECS Preview envs with Helmfile | 10 | | [CD - Deploy to ECS QA/Preview envs with Spacelift](#cd---deploy-to-ecs-qapreview-envs-with-spacelift) | Deploy Docker image to ECS QA/Preview envs with Spacelift | 11 | | [CD - Deploy to EKS Preview envs with Helmfile](#cd---deploy-to-eks-preview-envs-with-helmfile) | Deploy Docker image to ECS Preview envs with Helmfile | 12 | | [CI - Codeowners](#ci---codeowners) | Validate CODEOWNERS and suggest changes | 13 | | [CI - Build Docker image](#ci---build-docker-image) | Build Docker image and push it to ECR | 14 | | [CI - Promote or build Docker image](#ci---promote-or-build-docker-image) | Promote or build Docker image and push it to ECR | 15 | | [CI - Promote Docker image ](#ci---promote-docker-image) | Promote Docker image to specific version tag and push it to ECR | 16 | | [CI - Verify Docker image exists](#ci---verify-docker-image-exists) | Verify Docker image exists on ECR | 17 | | [CI - Readme](#ci---readme) | Validate README.yaml, README.md and suggest changes | 18 | | [CI - Terraform ChatOps](#ci---terraform-chatops) | Trigger terraform tests using ChatOps | 19 | | [CI - Terraform](#ci---terraform) | Lint, format and validate terraform code | 20 | | [CI - Check dist Directory](#ci---check-dist-directory) | This workflow helps ensure that generated contents of the `dist` directory matches the output of the `yarn build` | 21 | | [Controller - Draft release](#controller---draft-release) | Create or update draft release | 22 | | [Controller - Reingtegrate hotfix branch](#controller---reingtegrate-hotfix-branch) | Create PR into `target\_branch` to reintegrate hotfix from current branch | 23 | | [Controller - Create Release branch](#controller---create-release-branch) | Create `release/{version}` branch for the release | 24 | | [Controller - Create hotfix release](#controller---create-hotfix-release) | Create next patch version release | 25 | | [Controller - Labels](#controller---labels) | Label a pull request with one or more labels | 26 | | [Controller - Monorepo Controller](#controller---monorepo-controller) | Mocked monorepo controller that outputs list of applications, lists of apps with and without changes. | 27 | | [Controller - Release](#controller---release) | Create a github release | 28 | | [Scheduled Context](#scheduled-context) | Scheduled update of context.tf and related docs | 29 | | [Scheduled Readme](#scheduled-readme) | Scheduled update of readme.md | 30 | 31 | 32 | 33 | 34 | ## CD - Deploy to EKS with ArgoCD and Helmfile 35 | 36 | Deploy Docker image to EKS with ArgoCD and Helmfile 37 | 38 | ### Usage 39 | 40 | ```yaml 41 | name: Deploy 42 | on: 43 | push: 44 | branches: [ main ] 45 | 46 | jobs: 47 | cd: 48 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-argocd.yml@main 49 | with: 50 | image: registry.hub.docker.com/library/nginx 51 | tag: latest 52 | repository: ${{ github.event.repository.name }} 53 | environment: dev 54 | secrets: 55 | secret-outputs-passphrase: ${{ secrets.secret-outputs-passphrase }} 56 | github-private-actions-pat: ${{ secrets.github-private-actions-pat }} 57 | ``` 58 | 59 | 60 | 61 | ### Inputs 62 | 63 | | Name | Description | Type | Default | Required | 64 | |------|-------------|------|---------|----------| 65 | | environment | Environment name deploy to | string | N/A | true | 66 | | image | Docker Image to deploy | string | N/A | true | 67 | | organization | Repository owner organization (ex. acme for repo acme/example) | string | N/A | true | 68 | | repository | Repository name (ex. example for repo acme/example) | string | N/A | true | 69 | | synchronously | Wait until ArgoCD successfully apply the changes | boolean | false | false | 70 | | tag | Docker Image tag to deploy | string | N/A | true | 71 | 72 | 73 | 74 | ### Secrets 75 | 76 | | Name | Description | Required | 77 | |------|-------------|----------| 78 | | github-private-actions-pat | Github PAT allow to pull private repos | true | 79 | | secret-outputs-passphrase | Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs) | true | 80 | 81 | 82 | 83 | 84 | 85 | 86 | ## CD - Deploy to ECS with Spacelift 87 | 88 | Deploy Docker image to ECS with Spacelift 89 | 90 | ### Usage 91 | 92 | ```yaml 93 | name: Deploy 94 | on: 95 | push: 96 | branches: [ main ] 97 | 98 | jobs: 99 | cd: 100 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-ecs.yml@main 101 | with: 102 | image: registry.hub.docker.com/library/nginx 103 | tag: latest 104 | repository: ${{ github.event.repository.name }} 105 | environment: dev 106 | spacelift-organization: ${{ inputs.spacelift-organization }} 107 | secrets: 108 | secret-outputs-passphrase: "${{ secrets.secret-outputs-passphrase }}" 109 | github-private-actions-pat: "${{ secrets.github-private-actions-pat }}" 110 | spacelift-api-key-id: "${{ secrets.spacelift-api-key-id }}" 111 | spacelift-api-key-secret: "${{ secrets.spacelift-api-key-secret }}" 112 | ``` 113 | 114 | 115 | 116 | ### Inputs 117 | 118 | | Name | Description | Type | Default | Required | 119 | |------|-------------|------|---------|----------| 120 | | app | Application name. Used with monorepo pattern when there are several applications in the repo | string | N/A | false | 121 | | environment | Environment name deploy to | string | N/A | true | 122 | | image | Docker Image to deploy | string | N/A | true | 123 | | matrix-key | Matrix key - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction) | string | N/A | false | 124 | | matrix-step-name | Matrix step name - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction) | string | N/A | false | 125 | | repository | Repository name (ex. example for repo acme/example) | string | N/A | true | 126 | | spacelift-organization | Spacelift organization name | string | N/A | true | 127 | | tag | Docker Image tag to deploy | string | N/A | true | 128 | 129 | 130 | 131 | ### Secrets 132 | 133 | | Name | Description | Required | 134 | |------|-------------|----------| 135 | | github-private-actions-pat | Github PAT allow to pull private repos | true | 136 | | secret-outputs-passphrase | Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs) | true | 137 | | spacelift-api-key-id | Spacelift API Key ID | true | 138 | | spacelift-api-key-secret | Spacelift API Key Secret | true | 139 | 140 | 141 | 142 | 143 | 144 | 145 | ## CD - Deploy to EKS with Helmfile 146 | 147 | Deploy Docker image to EKS with Helmfile 148 | 149 | ### Usage 150 | 151 | ```yaml 152 | name: Deploy 153 | on: 154 | push: 155 | branches: [ main ] 156 | 157 | jobs: 158 | cd: 159 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-helmfile.yml@main 160 | with: 161 | image: registry.hub.docker.com/library/nginx 162 | tag: latest 163 | repository: ${{ github.event.repository.name }} 164 | environment: dev 165 | secrets: 166 | secret-outputs-passphrase: ${{ secrets.secret-outputs-passphrase }} 167 | github-private-actions-pat: ${{ secrets.github-private-actions-pat }} 168 | ``` 169 | 170 | 171 | 172 | ### Inputs 173 | 174 | | Name | Description | Type | Default | Required | 175 | |------|-------------|------|---------|----------| 176 | | environment | Environment name deploy to | string | N/A | true | 177 | | image | Docker Image to deploy | string | N/A | true | 178 | | repository | Repository name (ex. example for repo acme/example) | string | N/A | true | 179 | | tag | Docker Image tag to deploy | string | N/A | true | 180 | 181 | 182 | 183 | ### Secrets 184 | 185 | | Name | Description | Required | 186 | |------|-------------|----------| 187 | | github-private-actions-pat | Github PAT allow to pull private repos | true | 188 | | secret-outputs-passphrase | Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs) | true | 189 | 190 | 191 | 192 | 193 | 194 | 195 | ## CD - Deploy to EKS Preview envs with Helmfile 196 | 197 | Deploy Docker image to ECS Preview envs with Helmfile 198 | 199 | ### Usage 200 | 201 | ```yaml 202 | name: Feature Branch 203 | on: 204 | pull_request: 205 | branches: [ 'master' ] 206 | types: [opened, synchronize, reopened, closed, labeled, unlabeled] 207 | 208 | jobs: 209 | cd: 210 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-preview-helmfile.yml@main 211 | if: ${{ always() }} 212 | with: 213 | image: registry.hub.docker.com/library/nginx 214 | tag: latest 215 | repository: ${{ github.event.repository.name }} 216 | open: ${{ github.event.pull_request.state == 'open' }} 217 | labels: ${{ toJSON(github.event.pull_request.labels.*.name) }} 218 | ref: ${{ github.event.pull_request.head.ref }} 219 | exclusive: false 220 | env-label: | 221 | preview: deploy 222 | secrets: 223 | secret-outputs-passphrase: ${{ secrets.secret-outputs-passphrase }} 224 | github-private-actions-pat: ${{ secrets.github-private-actions-pat }} 225 | ``` 226 | 227 | 228 | 229 | ### Inputs 230 | 231 | | Name | Description | Type | Default | Required | 232 | |------|-------------|------|---------|----------| 233 | | env-label | YAML formatted {environment}: {label} map | string | preview: deploy
| false | 234 | | exclusive | Deactivate previous GitHub deployments | boolean | true | false | 235 | | image | Docker Image to deploy | string | N/A | true | 236 | | labels | Pull Request labels | string | {} | false | 237 | | open | Pull Request open/close state. Set true if opened | boolean | N/A | true | 238 | | organization | Repository owner organization (ex. acme for repo acme/example) | string | N/A | true | 239 | | ref | The fully-formed ref of the branch or tag that triggered the workflow run | string | N/A | true | 240 | | repository | Repository name (ex. example for repo acme/example) | string | N/A | true | 241 | | synchronously | Wait until ArgoCD successfully apply the changes | boolean | false | false | 242 | | tag | Docker Image tag to deploy | string | N/A | true | 243 | 244 | 245 | 246 | ### Secrets 247 | 248 | | Name | Description | Required | 249 | |------|-------------|----------| 250 | | github-private-actions-pat | Github PAT allow to pull private repos | true | 251 | | secret-outputs-passphrase | Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs) | true | 252 | 253 | 254 | 255 | 256 | 257 | 258 | ## CD - Deploy to ECS QA/Preview envs with Spacelift 259 | 260 | Deploy Docker image to ECS QA/Preview envs with Spacelift 261 | 262 | ### Usage 263 | 264 | ```yaml 265 | name: Feature Branch 266 | on: 267 | pull_request: 268 | branches: [ 'master' ] 269 | types: [opened, synchronize, reopened, closed, labeled, unlabeled] 270 | 271 | jobs: 272 | cd: 273 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-preview-ecs.yml@main 274 | if: ${{ always() }} 275 | with: 276 | image: registry.hub.docker.com/library/nginx 277 | tag: latest 278 | repository: ${{ github.event.repository.name }} 279 | spacelift-organization: ${{ inputs.spacelift-organization }} 280 | open: ${{ github.event.pull_request.state == 'open' }} 281 | labels: ${{ toJSON(github.event.pull_request.labels.*.name) }} 282 | ref: ${{ github.event.pull_request.head.ref }} 283 | exclusive: true 284 | env-label: | 285 | qa1: deploy/qa1 286 | qa2: deploy/qa2 287 | qa3: deploy/qa3 288 | qa4: deploy/qa4 289 | secrets: 290 | secret-outputs-passphrase: ${{ secrets.secret-outputs-passphrase }} 291 | github-private-actions-pat: ${{ secrets.github-private-actions-pat }} 292 | spacelift-api-key-id: "${{ secrets.spacelift-api-key-id }}" 293 | spacelift-api-key-secret: "${{ secrets.spacelift-api-key-secret }}" 294 | ``` 295 | 296 | 297 | 298 | ### Inputs 299 | 300 | | Name | Description | Type | Default | Required | 301 | |------|-------------|------|---------|----------| 302 | | app | Application name. Used with monorepo pattern when there are several applications in the repo | string | N/A | false | 303 | | env-label | YAML formatted {environment}: {label} map | string | preview: deploy
| false | 304 | | exclusive | Deactivate previous GitHub deployments | boolean | true | false | 305 | | image | Docker Image to deploy | string | N/A | true | 306 | | labels | Pull Request labels | string | {} | false | 307 | | matrix-key | Matrix key - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction) | string | N/A | false | 308 | | matrix-step-name | Matrix step name - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction) | string | N/A | false | 309 | | open | Pull Request open/close state. Set true if opened | boolean | N/A | true | 310 | | ref | The fully-formed ref of the branch or tag that triggered the workflow run | string | N/A | true | 311 | | repository | Repository name (ex. example for repo acme/example) | string | N/A | true | 312 | | spacelift-organization | Spacelift organization name | string | N/A | true | 313 | | tag | Docker Image tag to deploy | string | N/A | true | 314 | 315 | 316 | 317 | ### Secrets 318 | 319 | | Name | Description | Required | 320 | |------|-------------|----------| 321 | | github-private-actions-pat | Github PAT allow to pull private repos | true | 322 | | secret-outputs-passphrase | Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs) | true | 323 | | spacelift-api-key-id | Spacelift API Key ID | true | 324 | | spacelift-api-key-secret | Spacelift API Key Secret | true | 325 | 326 | 327 | 328 | 329 | 330 | 331 | ## CD - Deploy to EKS Preview envs with Helmfile 332 | 333 | Deploy Docker image to ECS Preview envs with Helmfile 334 | 335 | ### Usage 336 | 337 | ```yaml 338 | name: Feature Branch 339 | on: 340 | pull_request: 341 | branches: [ 'master' ] 342 | types: [opened, synchronize, reopened, closed, labeled, unlabeled] 343 | 344 | jobs: 345 | cd: 346 | uses: cloudposse/github-actions-workflows/.github/workflows/cd-preview-helmfile.yml@main 347 | if: ${{ always() }} 348 | with: 349 | image: registry.hub.docker.com/library/nginx 350 | tag: latest 351 | repository: ${{ github.event.repository.name }} 352 | open: ${{ github.event.pull_request.state == 'open' }} 353 | labels: ${{ toJSON(github.event.pull_request.labels.*.name) }} 354 | ref: ${{ github.event.pull_request.head.ref }} 355 | exclusive: false 356 | env-label: | 357 | preview: deploy 358 | secrets: 359 | secret-outputs-passphrase: ${{ secrets.secret-outputs-passphrase }} 360 | github-private-actions-pat: ${{ secrets.github-private-actions-pat }} 361 | ``` 362 | 363 | 364 | 365 | ### Inputs 366 | 367 | | Name | Description | Type | Default | Required | 368 | |------|-------------|------|---------|----------| 369 | | env-label | YAML formatted {environment}: {label} map | string | preview: deploy
| false | 370 | | exclusive | Deactivate previous GitHub deployments | boolean | true | false | 371 | | image | Docker Image to deploy | string | N/A | true | 372 | | labels | Pull Request labels | string | {} | false | 373 | | open | Pull Request open/close state. Set true if opened | boolean | N/A | true | 374 | | ref | The fully-formed ref of the branch or tag that triggered the workflow run | string | N/A | true | 375 | | repository | Repository name (ex. example for repo acme/example) | string | N/A | true | 376 | | tag | Docker Image tag to deploy | string | N/A | true | 377 | 378 | 379 | 380 | ### Secrets 381 | 382 | | Name | Description | Required | 383 | |------|-------------|----------| 384 | | github-private-actions-pat | Github PAT allow to pull private repos | true | 385 | | secret-outputs-passphrase | Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs) | true | 386 | 387 | 388 | 389 | 390 | 391 | 392 | ## CI - Codeowners 393 | 394 | Validate CODEOWNERS and suggest changes 395 | 396 | ### Usage 397 | ```yaml 398 | name: Validate CODEOWNERS 399 | on: 400 | workflow_call: 401 | 402 | jobs: 403 | ci-codeowners: 404 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-codeowners-full.yml@main 405 | with: 406 | is_fork: ${{ github.event.pull_request.head.repo.full_name != github.repository }} 407 | ``` 408 | 409 | 410 | 411 | ### Inputs 412 | 413 | | Name | Description | Type | Default | Required | 414 | |------|-------------|------|---------|----------| 415 | | is\_fork | Run workflow in fork mode (decreased permissions and features) | boolean | N/A | true | 416 | | runs-on | Overrides job runs-on setting (json-encoded list) | string | ["ubuntu-latest"] | false | 417 | 418 | 419 | 420 | ### Secrets 421 | 422 | | Name | Description | Required | 423 | |------|-------------|----------| 424 | | github\_access\_token | GitHub API token | false | 425 | 426 | 427 | 428 | 429 | 430 | 431 | ## CI - Build Docker image 432 | 433 | Build Docker image and push it to ECR 434 | 435 | ### Usage 436 | 437 | ```yaml 438 | name: Deploy 439 | on: 440 | push: 441 | branches: [ main ] 442 | 443 | jobs: 444 | ci: 445 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-build.yml@main 446 | with: 447 | organization: ${{ github.event.repository.owner.login }} 448 | repository: ${{ github.event.repository.name }} 449 | secrets: 450 | ecr-region: ${{ secrets.ecr-region }} 451 | ecr-iam-role: ${{ secrets.ecr-iam-role }} 452 | registry: ${{ secrets.registry }} 453 | secret-outputs-passphrase: ${{ secrets.secret-outputs-passphrase }} 454 | ``` 455 | 456 | 457 | 458 | ### Inputs 459 | 460 | | Name | Description | Type | Default | Required | 461 | |------|-------------|------|---------|----------| 462 | | organization | Repository owner organization (ex. acme for repo acme/example) | string | N/A | true | 463 | | repository | Repository name (ex. example for repo acme/example) | string | N/A | true | 464 | 465 | 466 | 467 | ### Secrets 468 | 469 | | Name | Description | Required | 470 | |------|-------------|----------| 471 | | ecr-iam-role | IAM Role ARN provide ECR write/read access | true | 472 | | ecr-region | ECR AWS region | true | 473 | | registry | ECR Docker registry | true | 474 | | secret-outputs-passphrase | Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs) | true | 475 | 476 | 477 | 478 | ### Outputs 479 | 480 | | Name | Description | 481 | |------|-------------| 482 | | image | Docker Image | 483 | | tag | Docker image tag | 484 | 485 | 486 | 487 | ## CI - Promote or build Docker image 488 | 489 | Promote or build Docker image and push it to ECR 490 | 491 | ### Usage 492 | 493 | ```yaml 494 | name: Deploy 495 | on: 496 | push: 497 | branches: [ main ] 498 | 499 | jobs: 500 | ci: 501 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-promote-or-build.yml@main 502 | with: 503 | organization: ${{ github.event.repository.owner.login }} 504 | repository: ${{ github.event.repository.name }} 505 | force-build: false 506 | secrets: 507 | ecr-region: ${{ secrets.ecr-region }} 508 | ecr-iam-role: ${{ secrets.ecr-iam-role }} 509 | registry: ${{ secrets.registry }} 510 | secret-outputs-passphrase: ${{ secrets.secret-outputs-passphrase }} 511 | ``` 512 | 513 | 514 | 515 | ### Inputs 516 | 517 | | Name | Description | Type | Default | Required | 518 | |------|-------------|------|---------|----------| 519 | | app | Application name. Used with monorepo pattern when there are several applications in the repo | string | N/A | true | 520 | | force-build | Force build (skip promotion) | boolean | false | true | 521 | | matrix-key | Matrix key - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction) | string | N/A | false | 522 | | matrix-step-name | Matrix step name - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction) | string | N/A | false | 523 | | organization | Repository owner organization (ex. acme for repo acme/example) | string | N/A | true | 524 | | repository | Repository name (ex. example for repo acme/example) | string | N/A | true | 525 | 526 | 527 | 528 | ### Secrets 529 | 530 | | Name | Description | Required | 531 | |------|-------------|----------| 532 | | ecr-iam-role | IAM Role ARN provide ECR write/read access | true | 533 | | ecr-region | ECR AWS region | true | 534 | | registry | ECR Docker registry | true | 535 | | secret-outputs-passphrase | Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs) | true | 536 | 537 | 538 | 539 | ### Outputs 540 | 541 | | Name | Description | 542 | |------|-------------| 543 | | image | Docker Image | 544 | | tag | Docker image tag | 545 | 546 | 547 | 548 | ## CI - Promote Docker image 549 | 550 | Promote Docker image to specific version tag and push it to ECR 551 | 552 | ### Usage 553 | 554 | ```yaml 555 | name: Release 556 | on: 557 | release: 558 | types: [published] 559 | 560 | jobs: 561 | ci: 562 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-promote.yml@main 563 | with: 564 | organization: ${{ github.event.repository.owner.login }} 565 | repository: ${{ github.event.repository.name }} 566 | version: ${{ github.event.release.tag_name }} 567 | secrets: 568 | ecr-region: ${{ secrets.ecr-region }} 569 | ecr-iam-role: ${{ secrets.ecr-iam-role }} 570 | registry: ${{ secrets.registry }} 571 | secret-outputs-passphrase: ${{ secrets.secret-outputs-passphrase }} 572 | 573 | ``` 574 | 575 | 576 | 577 | ### Inputs 578 | 579 | | Name | Description | Type | Default | Required | 580 | |------|-------------|------|---------|----------| 581 | | app | Application name. Used with monorepo pattern when there are several applications in the repo | string | N/A | false | 582 | | matrix-key | Matrix key - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction) | string | N/A | false | 583 | | matrix-step-name | Matrix step name - matrix output workaround. [Read more](https://github.com/cloudposse/github-action-matrix-outputs-write#introduction) | string | N/A | false | 584 | | organization | Repository owner organization (ex. acme for repo acme/example) | string | N/A | true | 585 | | repository | Repository name (ex. example for repo acme/example) | string | N/A | true | 586 | | version | New version tag | string | N/A | true | 587 | 588 | 589 | 590 | ### Secrets 591 | 592 | | Name | Description | Required | 593 | |------|-------------|----------| 594 | | ecr-iam-role | IAM Role ARN provide ECR write/read access | true | 595 | | ecr-region | ECR AWS region | true | 596 | | registry | ECR Docker registry | true | 597 | | secret-outputs-passphrase | Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs) | true | 598 | 599 | 600 | 601 | ### Outputs 602 | 603 | | Name | Description | 604 | |------|-------------| 605 | | image | Docker Image | 606 | | tag | Docker image tag | 607 | 608 | 609 | 610 | ## CI - Verify Docker image exists 611 | 612 | Verify Docker image exists on ECR 613 | 614 | ### Usage 615 | 616 | ```yaml 617 | name: Release 618 | on: 619 | release: 620 | types: [published] 621 | 622 | jobs: 623 | ci: 624 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-verify.yml@main 625 | with: 626 | organization: ${{ github.event.repository.owner.login }} 627 | repository: ${{ github.event.repository.name }} 628 | version: ${{ github.event.release.tag_name }} 629 | secrets: 630 | ecr-region: ${{ secrets.ecr-region }} 631 | ecr-iam-role: ${{ secrets.ecr-iam-role }} 632 | registry: ${{ secrets.registry }} 633 | secret-outputs-passphrase: ${{ secrets.secret-outputs-passphrase }} 634 | 635 | ``` 636 | 637 | 638 | 639 | ### Inputs 640 | 641 | | Name | Description | Type | Default | Required | 642 | |------|-------------|------|---------|----------| 643 | | app | Application name. Used with monorepo pattern when there are several applications in the repo | string | N/A | true | 644 | | organization | Repository owner organization (ex. acme for repo acme/example) | string | N/A | true | 645 | | repository | Repository name (ex. example for repo acme/example) | string | N/A | true | 646 | | version | Release version tag | string | N/A | true | 647 | 648 | 649 | 650 | ### Secrets 651 | 652 | | Name | Description | Required | 653 | |------|-------------|----------| 654 | | ecr-iam-role | IAM Role ARN provide ECR write/read access | true | 655 | | ecr-region | ECR AWS region | true | 656 | | registry | ECR Docker registry | true | 657 | | secret-outputs-passphrase | Passphrase to encrypt/decrypt secret outputs with gpg. For more information [read](https://github.com/cloudposse/github-action-secret-outputs) | true | 658 | 659 | 660 | 661 | ### Outputs 662 | 663 | | Name | Description | 664 | |------|-------------| 665 | | image | Docker Image | 666 | | tag | Docker image tag | 667 | 668 | 669 | 670 | ## CI - Readme 671 | 672 | Validate README.yaml, README.md and suggest changes 673 | 674 | ### Usage 675 | ```yaml 676 | name: Validate Readme 677 | on: 678 | workflow_call: 679 | 680 | permissions: 681 | pull-requests: write 682 | id-token: write 683 | contents: read 684 | 685 | jobs: 686 | ci-readme: 687 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-readme.yml@main 688 | with: 689 | suggestions: true 690 | filter-mode: diff_context 691 | ``` 692 | 693 | 694 | 695 | ### Inputs 696 | 697 | | Name | Description | Type | Default | Required | 698 | |------|-------------|------|---------|----------| 699 | | filter-mode | Reviewdog filter mode | string | N/A | true | 700 | | runs-on | Overrides job runs-on setting (json-encoded list) | string | ["ubuntu-latest"] | false | 701 | | suggestions | Enable Reviewdog suggestions (pull request only) | boolean | N/A | true | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | ## CI - Terraform ChatOps 711 | 712 | Trigger terraform tests using ChatOps 713 | 714 | ### Usage 715 | ```yaml 716 | name: Terraform ChatOps 717 | on: 718 | workflow_call: 719 | 720 | permissions: 721 | pull-requests: write 722 | id-token: write 723 | contents: read 724 | 725 | jobs: 726 | ci-terraform-chatops: 727 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-terraform-chatops.yml@main 728 | secrets: 729 | github_access_token: ${{ secrets.REPO_ACCESS_TOKEN }} 730 | ``` 731 | 732 | 733 | 734 | ### Inputs 735 | 736 | | Name | Description | Type | Default | Required | 737 | |------|-------------|------|---------|----------| 738 | | runs-on | Overrides job runs-on setting (json-encoded list) | string | ["ubuntu-latest"] | false | 739 | 740 | 741 | 742 | ### Secrets 743 | 744 | | Name | Description | Required | 745 | |------|-------------|----------| 746 | | github\_access\_token | GitHub API token | true | 747 | 748 | 749 | 750 | 751 | 752 | 753 | ## CI - Terraform 754 | 755 | Lint, format and validate terraform code 756 | 757 | ### Usage 758 | ```yaml 759 | name: Validate Terraform 760 | on: 761 | workflow_call: 762 | 763 | permissions: 764 | pull-requests: write 765 | id-token: write 766 | contents: read 767 | 768 | jobs: 769 | ci-terraform: 770 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-terraform.yml@main 771 | with: 772 | suggestions: true 773 | filter-mode: diff_context 774 | ``` 775 | 776 | 777 | 778 | ### Inputs 779 | 780 | | Name | Description | Type | Default | Required | 781 | |------|-------------|------|---------|----------| 782 | | filter-mode | Reviewdog filter mode | string | N/A | true | 783 | | runs-on | Overrides job runs-on setting (json-encoded list) | string | ["ubuntu-latest"] | false | 784 | | suggestions | Enable Reviewdog suggestions (pull request only) | boolean | N/A | true | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | ## CI - Check dist Directory 794 | 795 | This workflow helps ensure that generated contents of the `dist` directory matches the output of the `yarn build` 796 | command. The `dist` directory has special meaning in GitHub Actions in that it that contains the runnable JS files. 797 | 798 | In Cloud Posse's TypeScript actions, the `dist` directory is generated through a build process from the TypeScript 799 | source files by running the `yarn build` command. 800 | 801 | 802 | ### Usage 803 | 804 | ```yaml 805 | name: Build 806 | on: 807 | push: 808 | branches: [ main ] 809 | 810 | jobs: 811 | check-dist: 812 | uses: cloudposse/github-actions-workflows/.github/workflows/ci-typescript-app-check-dist.yml@main 813 | ``` 814 | 815 | 816 | 817 | ### Inputs 818 | 819 | | Name | Description | Type | Default | Required | 820 | |------|-------------|------|---------|----------| 821 | | commit-message | Optional input to set a commit message. If it's not set, it defaults to 'Update the contents of dist directory' | string | Update contents of the dist directory | false | 822 | | dist-path | Optional input to set a path to the dist folder. If it's not set, it defaults to './dist' | string | ./dist | false | 823 | | node-caching | Optional input to set up caching for the setup-node action. The input syntax corresponds to the setup-node's one. Set to an empty string if caching isn't needed | string | yarn | false | 824 | | node-version | Optional input to set the version of Node.js used to build a project. The input syntax corresponds to the setup-node's one | string | 16.x | false | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | ## Controller - Draft release 834 | 835 | Create or update draft release 836 | 837 | ### Usage 838 | 839 | ```yaml 840 | name: Draft release 841 | on: 842 | push: 843 | branches: [ main ] 844 | 845 | jobs: 846 | do: 847 | uses: cloudposse/github-actions-workflows/.github/workflows/controller-draft-release.yml@main 848 | with: 849 | ref: ${{ github.sha }} 850 | secrets: 851 | github-private-actions-pat: ${{ secrets.github-private-actions-pat }} 852 | 853 | ``` 854 | 855 | 856 | 857 | ### Inputs 858 | 859 | | Name | Description | Type | Default | Required | 860 | |------|-------------|------|---------|----------| 861 | | ref | The release target, i.e. branch or commit it should point to | string | ${{ github.sha }} | false | 862 | 863 | 864 | 865 | ### Secrets 866 | 867 | | Name | Description | Required | 868 | |------|-------------|----------| 869 | | github-private-actions-pat | Github PAT allow to create release | true | 870 | 871 | 872 | 873 | 874 | 875 | 876 | ## Controller - Reingtegrate hotfix branch 877 | 878 | Create PR into `target_branch` to reintegrate hotfix from current branch 879 | 880 | ### Usage 881 | 882 | ```yaml 883 | name: Release 884 | on: 885 | release: 886 | types: [published] 887 | 888 | jobs: 889 | do: 890 | uses: cloudposse/github-action-workflows/.github/workflows/controller-hotfix-reintegrate.yml@main 891 | with: 892 | ref: ${{ github.ref }} 893 | target_branch: main 894 | secrets: 895 | github-private-actions-pat: ${{ secrets.github-private-actions-pat }} 896 | ``` 897 | 898 | 899 | 900 | ### Inputs 901 | 902 | | Name | Description | Type | Default | Required | 903 | |------|-------------|------|---------|----------| 904 | | ref | The fully-formed ref of the branch or tag that triggered the workflow run | string | N/A | true | 905 | | target\_branch | Target branch to reintegrate hotfix | string | main | false | 906 | 907 | 908 | 909 | ### Secrets 910 | 911 | | Name | Description | Required | 912 | |------|-------------|----------| 913 | | github-private-actions-pat | Github PAT allow to create a pull request | true | 914 | 915 | 916 | 917 | 918 | 919 | 920 | ## Controller - Create Release branch 921 | 922 | Create `release/{version}` branch for the release 923 | 924 | ### Usage 925 | 926 | ```yaml 927 | name: Main branch 928 | on: 929 | release: 930 | types: [published] 931 | 932 | jobs: 933 | do: 934 | uses: cloudposse/github-action-workflows/.github/workflows/controller-hotfix-release-branch.yml@main 935 | with: 936 | version: ${{ github.event.release.tag_name }} 937 | ``` 938 | 939 | 940 | 941 | ### Inputs 942 | 943 | | Name | Description | Type | Default | Required | 944 | |------|-------------|------|---------|----------| 945 | | version | Release version | string | N/A | true | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | ## Controller - Create hotfix release 955 | 956 | Create next patch version release 957 | 958 | ### Usage 959 | 960 | ```yaml 961 | on: 962 | push: 963 | branches: [ 'release/**' ] 964 | 965 | jobs: 966 | do: 967 | uses: cloudposse/github-action-workflows/.github/workflows/controller-hotfix-release.yml@main 968 | with: 969 | ref: ${{ github.ref }} 970 | ``` 971 | 972 | 973 | 974 | ### Inputs 975 | 976 | | Name | Description | Type | Default | Required | 977 | |------|-------------|------|---------|----------| 978 | | ref | The fully-formed ref of the branch or tag that triggered the workflow run | string | N/A | true | 979 | 980 | 981 | 982 | 983 | 984 | ### Outputs 985 | 986 | | Name | Description | 987 | |------|-------------| 988 | | version | Release version | 989 | 990 | 991 | 992 | ## Controller - Labels 993 | 994 | Label a pull request with one or more labels 995 | 996 | ### Usage 997 | 998 | ```yaml 999 | name: Label pull request 1000 | on: 1001 | workflow_call: 1002 | 1003 | jobs: 1004 | label: 1005 | uses: cloudposse/github-actions-workflows/.github/workflows/controller-labels.yml@main 1006 | with: 1007 | labels: ['ready-for-review'] 1008 | ``` 1009 | 1010 | 1011 | 1012 | ### Inputs 1013 | 1014 | | Name | Description | Type | Default | Required | 1015 | |------|-------------|------|---------|----------| 1016 | | labels | The labels' name to be added. Must be separated with line breaks if there are multiple labels. | string | N/A | true | 1017 | | runs-on | Overrides job runs-on setting (json-encoded list) | string | ["ubuntu-latest"] | false | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | ## Controller - Monorepo Controller 1027 | 1028 | Mocked monorepo controller that outputs list of applications, lists of apps with and without changes. 1029 | 1030 | ### Usage 1031 | 1032 | ```yaml 1033 | name: Monorepo 1034 | on: 1035 | push: 1036 | branches: [ main ] 1037 | 1038 | jobs: 1039 | do: 1040 | uses: cloudposse/github-actions-workflows/.github/workflows/controller-monorepo.yml@main 1041 | with: 1042 | dir: ./apps 1043 | ``` 1044 | 1045 | 1046 | 1047 | ### Inputs 1048 | 1049 | | Name | Description | Type | Default | Required | 1050 | |------|-------------|------|---------|----------| 1051 | | dir | Directory with applications | string | N/A | true | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | ### Outputs 1058 | 1059 | | Name | Description | 1060 | |------|-------------| 1061 | | apps | Applications | 1062 | | changes | Changed applications | 1063 | | no-changes | Unchanged applications | 1064 | 1065 | 1066 | 1067 | ## Controller - Release 1068 | 1069 | Create a github release 1070 | 1071 | ### Usage 1072 | 1073 | ```yaml 1074 | name: Draft release 1075 | on: 1076 | workflow_call: 1077 | 1078 | jobs: 1079 | release: 1080 | uses: cloudposse/github-actions-workflows/.github/workflows/controller-release.yml@main 1081 | 1082 | ``` 1083 | 1084 | 1085 | 1086 | ### Inputs 1087 | 1088 | | Name | Description | Type | Default | Required | 1089 | |------|-------------|------|---------|----------| 1090 | | config-name | Name of the release drafter config file | string | auto-release.yml | false | 1091 | | ref | The release target, i.e. branch or commit it should point to | string | ${{ github.sha }} | false | 1092 | | runs-on | Overrides job runs-on setting (json-encoded list) | string | ["ubuntu-latest"] | false | 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | ## Scheduled Context 1102 | 1103 | Scheduled update of context.tf and related docs 1104 | 1105 | ### Usage 1106 | ```yaml 1107 | name: scheduled-context 1108 | on: 1109 | workflow_call: 1110 | 1111 | permissions: 1112 | pull-requests: write 1113 | id-token: write 1114 | contents: read 1115 | 1116 | jobs: 1117 | scheduled-context: 1118 | uses: cloudposse/github-actions-workflows/.github/workflows/scheduled-context.yml@main 1119 | ``` 1120 | 1121 | 1122 | 1123 | ### Inputs 1124 | 1125 | | Name | Description | Type | Default | Required | 1126 | |------|-------------|------|---------|----------| 1127 | | base-branch | Repo default branch | string | main | false | 1128 | | runs-on | Overrides job runs-on setting (json-encoded list) | string | ["ubuntu-latest"] | false | 1129 | 1130 | 1131 | 1132 | ### Secrets 1133 | 1134 | | Name | Description | Required | 1135 | |------|-------------|----------| 1136 | | github\_access\_token | GitHub API token | true | 1137 | 1138 | 1139 | 1140 | 1141 | 1142 | 1143 | ## Scheduled Readme 1144 | 1145 | Scheduled update of readme.md 1146 | 1147 | ### Usage 1148 | ```yaml 1149 | name: scheduled-readme 1150 | on: 1151 | workflow_call: 1152 | 1153 | permissions: 1154 | pull-requests: write 1155 | id-token: write 1156 | contents: read 1157 | 1158 | jobs: 1159 | scheduled-readme: 1160 | uses: cloudposse/github-actions-workflows/.github/workflows/scheduled-readme.yml@main 1161 | ``` 1162 | 1163 | 1164 | 1165 | ### Inputs 1166 | 1167 | | Name | Description | Type | Default | Required | 1168 | |------|-------------|------|---------|----------| 1169 | | base-branch | Repo default branch | string | main | false | 1170 | | runs-on | Overrides job runs-on setting (json-encoded list) | string | ["ubuntu-latest"] | false | 1171 | 1172 | 1173 | 1174 | ### Secrets 1175 | 1176 | | Name | Description | Required | 1177 | |------|-------------|----------| 1178 | | github\_access\_token | GitHub API token | true | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | 1185 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base" 5 | ] 6 | } 7 | --------------------------------------------------------------------------------