diff --git a/docs/layers/software-delivery/ecs-ecspresso/ecs-ecspresso.mdx b/docs/layers/software-delivery/ecs-ecspresso/ecs-ecspresso.mdx index e4cffc6f8..21a112b14 100644 --- a/docs/layers/software-delivery/ecs-ecspresso/ecs-ecspresso.mdx +++ b/docs/layers/software-delivery/ecs-ecspresso/ecs-ecspresso.mdx @@ -7,6 +7,7 @@ import Intro from '@site/src/components/Intro'; import KeyPoints from '@site/src/components/KeyPoints'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +import CollapsibleText from '@site/src/components/CollapsibleText'; We use the [`ecspresso`](https://github.com/kayac/ecspresso) deployment tool for Amazon ECS to manage ECS services using a code-driven approach, alongside reusable GitHub Action workflows. This setup allows tasks to be defined with Terraform within the infrastructure repository, and task definitions to reside alongside the application code. Ecspresso provides extensive configuration options via YAML, JSON, and Jsonnet, and includes plugins for enhanced functionality such as Terraform state lookups. @@ -57,192 +58,192 @@ sequenceDiagram ### Github Action Workflows -The basic deployment flow is for feature branches. You can use the following -sample workflow to add pull request deploys to your application repository: +The basic deployment flow is for feature branches. You can use the following sample workflow to add pull request deploys to your application repository: -
-Deploy +:::tip Latest Examples - - - - -```yaml -name: Feature Branch -on: - pull_request: - branches: [ 'main' ] - types: [opened, synchronize, reopened, closed, labeled, unlabeled] - -permissions: - pull-requests: write - deployments: write - id-token: write - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: false - -jobs: - monorepo: - uses: cloudposse/github-actions-workflows/.github/workflows/controller-monorepo.yml@main - with: - file: ./deploy/config.yaml - - ci: - uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-build.yml@main - needs: [ monorepo ] - with: - organization: "cloudposse" - repository: ${{ github.event.repository.name }} - secrets: - ecr-region: ${{ secrets.ECR_REGION }} - ecr-iam-role: ${{ secrets.ECR_IAM_ROLE }} - registry: ${{ secrets.ECR_REGISTRY }} - secret-outputs-passphrase: ${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }} - - cd: - uses: cloudposse/github-actions-workflows/.github/workflows/cd-preview-ecspresso.yml@main - needs: [ ci, monorepo ] - if: ${{ always() && needs.monorepo.outputs.apps != '[]' }} - strategy: - matrix: - app: ${{ fromJson(needs.monorepo.outputs.apps) }} - with: - image: ${{ needs.ci.outputs.image }} - tag: ${{ needs.ci.outputs.tag }} - repository: ${{ github.event.repository.name }} - app: ${{ matrix.app }} - open: ${{ github.event.pull_request.state == 'open' }} - labels: ${{ toJSON(github.event.pull_request.labels.*.name) }} - ref: ${{ github.event.pull_request.head.ref }} - exclusive: true - enable-migration: ${{ contains(fromJSON(needs.monorepo.outputs.migrations), matrix.app) }} - settings: ${{ needs.monorepo.outputs.settings }} - env-label: | - qa1: deploy/qa1 - secrets: - secret-outputs-passphrase: ${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }} -``` +Check out our [example app-on-ecs](https://github.com/cloudposse-examples/app-on-ecs) for the latest example of how to use `ecspresso` with GitHub Actions. - - - - -```yaml -name: 2 - Main Branch -on: - push: - branches: [ main ] - -permissions: - contents: write - id-token: write - pull-requests: read - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: false - -jobs: - monorepo: - uses: cloudposse/github-actions-workflows/.github/workflows/controller-monorepo.yml@main - with: - file: ./deploy/config.yaml - - ci: - uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-build.yml@main - needs: [ monorepo ] - with: - organization: "cloudposse" - repository: ${{ github.event.repository.name }} - secrets: - ecr-region: ${{ secrets.ECR_REGION }} - ecr-iam-role: ${{ secrets.ECR_IAM_ROLE }} - registry: ${{ secrets.ECR_REGISTRY }} - secret-outputs-passphrase: ${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }} - - cd: - uses: cloudposse/github-actions-workflows/.github/workflows/cd-ecspresso.yml@main - needs: [ ci, monorepo ] - strategy: - matrix: - app: ${{ fromJson(needs.monorepo.outputs.apps) }} - with: - image: ${{ needs.ci.outputs.image }} - tag: ${{ needs.ci.outputs.tag }} - repository: ${{ github.event.repository.name }} - app: ${{ matrix.app }} - environment: dev - enable-migration: ${{ contains(fromJSON(needs.monorepo.outputs.migrations), matrix.app) }} - settings: ${{ needs.monorepo.outputs.settings }} - secrets: - secret-outputs-passphrase: ${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }} - - release: - uses: cloudposse/github-actions-workflows/.github/workflows/controller-draft-release.yml@main - needs: [ cd ] -``` +::: - - - - -```yaml -name: 3 - Release -on: - release: - types: [published] - -permissions: - id-token: write - contents: write - -concurrency: - group: ${{ github.workflow }} - cancel-in-progress: false - -jobs: - monorepo: - uses: cloudposse/github-actions-workflows/.github/workflows/controller-monorepo.yml@main - with: - file: ./deploy/config.yaml - - ci: - uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-promote.yml@main - needs: [ monorepo ] - with: - organization: "cloudposse" - repository: ${{ github.event.repository.name }} - version: ${{ github.event.release.tag_name }} - secrets: - ecr-region: ${{ secrets.ECR_REGION }} - ecr-iam-role: ${{ secrets.ECR_IAM_ROLE }} - registry: ${{ secrets.ECR_REGISTRY }} - secret-outputs-passphrase: ${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }} - - cd: - uses: cloudposse/github-actions-workflows/.github/workflows/cd-ecspresso.yml@main - needs: [ ci, monorepo ] - strategy: - matrix: - app: ${{ fromJson(needs.monorepo.outputs.apps) }} - with: - image: ${{ needs.ci.outputs.image }} - tag: ${{ needs.ci.outputs.tag }} - repository: ${{ github.event.repository.name }} - app: ${{ matrix.app }} - environment: "staging" - enable-migration: ${{ contains(fromJSON(needs.monorepo.outputs.migrations), matrix.app) }} - settings: ${{ needs.monorepo.outputs.settings }} - secrets: - secret-outputs-passphrase: ${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }} -``` - - + + + + ```yaml title=".github/workflows/feature-branch.yaml" + name: 1 - Feature Branch + on: + pull_request: + branches: [ main ] + types: [opened, synchronize, reopened, closed, labeled, unlabeled] + + permissions: + pull-requests: write + deployments: write + id-token: write + contents: read + + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + + jobs: + monorepo: + uses: cloudposse/github-actions-workflows/.github/workflows/controller-monorepo.yml@main + with: + file: ./deploy/config.yaml + + ci: + uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-build.yml@main + needs: [ monorepo ] + with: + organization: "cloudposse" + repository: ${{ github.event.repository.name }} + secrets: + ecr-region: ${{ secrets.ECR_REGION }} + ecr-iam-role: ${{ secrets.ECR_IAM_ROLE }} + registry: ${{ secrets.ECR_REGISTRY }} + secret-outputs-passphrase: ${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }} + + cd: + uses: cloudposse/github-actions-workflows/.github/workflows/cd-preview-ecspresso.yml@main + needs: [ ci, monorepo ] + if: ${{ always() && needs.monorepo.outputs.apps != '[]' }} + strategy: + matrix: + app: ${{ fromJson(needs.monorepo.outputs.apps) }} + with: + image: ${{ needs.ci.outputs.image }} + tag: ${{ needs.ci.outputs.tag }} + repository: ${{ github.event.repository.name }} + app: ${{ matrix.app }} + open: ${{ github.event.pull_request.state == 'open' }} + labels: ${{ toJSON(github.event.pull_request.labels.*.name) }} + ref: ${{ github.event.pull_request.head.ref }} + exclusive: true + enable-migration: ${{ contains(fromJSON(needs.monorepo.outputs.migrations), matrix.app) }} + settings: ${{ needs.monorepo.outputs.settings }} + env-label: | + qa1: deploy/qa1 + secrets: + secret-outputs-passphrase: ${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }} + ``` + + + + + + ```yaml title=".github/workflows/main-branch.yaml" + name: 2 - Main Branch + on: + push: + branches: [ main ] + + permissions: + contents: write + id-token: write + pull-requests: read + + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + + jobs: + monorepo: + uses: cloudposse/github-actions-workflows/.github/workflows/controller-monorepo.yml@main + with: + file: ./deploy/config.yaml + + ci: + uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-build.yml@main + needs: [ monorepo ] + with: + organization: "cloudposse" + repository: ${{ github.event.repository.name }} + secrets: + ecr-region: ${{ secrets.ECR_REGION }} + ecr-iam-role: ${{ secrets.ECR_IAM_ROLE }} + registry: ${{ secrets.ECR_REGISTRY }} + secret-outputs-passphrase: ${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }} + + cd: + uses: cloudposse/github-actions-workflows/.github/workflows/cd-ecspresso.yml@main + needs: [ ci, monorepo ] + strategy: + matrix: + app: ${{ fromJson(needs.monorepo.outputs.apps) }} + with: + image: ${{ needs.ci.outputs.image }} + tag: ${{ needs.ci.outputs.tag }} + repository: ${{ github.event.repository.name }} + app: ${{ matrix.app }} + environment: dev + enable-migration: ${{ contains(fromJSON(needs.monorepo.outputs.migrations), matrix.app) }} + settings: ${{ needs.monorepo.outputs.settings }} + secrets: + secret-outputs-passphrase: ${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }} + + release: + uses: cloudposse/github-actions-workflows/.github/workflows/controller-draft-release.yml@main + needs: [ cd ] + ``` + + + + + + ```yaml title=".github/workflows/release.yaml" + name: 3 - Release + on: + release: + types: [published] + + permissions: + id-token: write + contents: write + + concurrency: + group: ${{ github.workflow }} + cancel-in-progress: false + + jobs: + monorepo: + uses: cloudposse/github-actions-workflows/.github/workflows/controller-monorepo.yml@main + with: + file: ./deploy/config.yaml + + ci: + uses: cloudposse/github-actions-workflows/.github/workflows/ci-dockerized-app-promote.yml@main + needs: [ monorepo ] + with: + organization: "cloudposse" + repository: ${{ github.event.repository.name }} + version: ${{ github.event.release.tag_name }} + secrets: + ecr-region: ${{ secrets.ECR_REGION }} + ecr-iam-role: ${{ secrets.ECR_IAM_ROLE }} + registry: ${{ secrets.ECR_REGISTRY }} + secret-outputs-passphrase: ${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }} + + cd: + uses: cloudposse/github-actions-workflows/.github/workflows/cd-ecspresso.yml@main + needs: [ ci, monorepo ] + strategy: + matrix: + app: ${{ fromJson(needs.monorepo.outputs.apps) }} + with: + image: ${{ needs.ci.outputs.image }} + tag: ${{ needs.ci.outputs.tag }} + repository: ${{ github.event.repository.name }} + app: ${{ matrix.app }} + environment: "staging" + enable-migration: ${{ contains(fromJSON(needs.monorepo.outputs.migrations), matrix.app) }} + settings: ${{ needs.monorepo.outputs.settings }} + secrets: + secret-outputs-passphrase: ${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }} + ``` + + -
## References - [Ecspresso](https://github.com/kayac/ecspresso) : Tool repo diff --git a/docs/layers/software-delivery/eks-argocd/eks-argocd.mdx b/docs/layers/software-delivery/eks-argocd/eks-argocd.mdx index aefc215fe..73ee7a393 100644 --- a/docs/layers/software-delivery/eks-argocd/eks-argocd.mdx +++ b/docs/layers/software-delivery/eks-argocd/eks-argocd.mdx @@ -8,6 +8,7 @@ import KeyPoints from '@site/src/components/KeyPoints'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import Note from '@site/src/components/Note'; +import CollapsibleText from '@site/src/components/CollapsibleText'; Argo CD is an open-source declarative, GitOps continuous delivery tool for Kubernetes applications. It enables developers to manage and deploy applications on Kubernetes clusters using Git repositories as the source of truth for configuration and definitions. Argo CD follows the GitOps methodology, which means that the entire application configuration, including manifests, parameters, and even application state, is stored in a Git repository. @@ -97,106 +98,102 @@ sequenceDiagram Application repository will create a deployment when a workflow is triggered and call the relevant shared workflow. -
-Deploy +:::tip Latest Examples - - - - -```yaml -# .github/workflows/feature-branch.yaml -name: Feature Branch -on: - pull_request: - branches: [ 'main' ] - types: [opened, synchronize, reopened, closed, labeled, unlabeled] - -permissions: - pull-requests: write - deployments: write - id-token: write - contents: read - -jobs: - do: - uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/feature-branch.yml@main - with: - organization: "${{ github.event.repository.owner.login }}" - repository: "${{ github.event.repository.name }}" - open: ${{ github.event.pull_request.state == 'open' }} - labels: ${{ toJSON(github.event.pull_request.labels.*.name) }} - ref: ${{ github.event.pull_request.head.ref }} - secrets: - github-private-actions-pat: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}" - registry: "${{ secrets.ECR_REGISTRY }}" - secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}" - ecr-region: "${{ secrets.ECR_REGION }}" - ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}" -``` - - - - - -```yaml -# .github/workflows/main-branch.yaml -name: Main Branch -on: - push: - branches: [ main ] - -permissions: - contents: write - id-token: write - -jobs: - do: - uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/main-branch.yml@main - with: - organization: "${{ github.event.repository.owner.login }}" - repository: "${{ github.event.repository.name }}" - secrets: - github-private-actions-pat: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}" - registry: "${{ secrets.ECR_REGISTRY }}" - secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}" - ecr-region: "${{ secrets.ECR_REGION }}" - ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}" -``` - - - - +Check out our [example app-on-eks-with-argocd](https://github.com/cloudposse-examples/app-on-eks-with-argocd) for the latest example of how to use ArgoCD with GitHub Actions. -```yaml -# .github/workflows/release.yaml -name: Release -on: - release: - types: [published] - -permissions: - id-token: write - contents: write - -jobs: - perform: - uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/release.yml@main - with: - organization: "${{ github.event.repository.owner.login }}" - repository: "${{ github.event.repository.name }}" - version: ${{ github.event.release.tag_name }} - secrets: - github-private-actions-pat: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}" - registry: "${{ secrets.ECR_REGISTRY }}" - secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}" - ecr-region: "${{ secrets.ECR_REGION }}" - ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}" -``` +::: - + + + + ```yaml title=".github/workflows/feature-branch.yaml" + name: Feature Branch + on: + pull_request: + branches: [ 'main' ] + types: [opened, synchronize, reopened, closed, labeled, unlabeled] + + permissions: + pull-requests: write + deployments: write + id-token: write + contents: read + + jobs: + do: + uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/feature-branch.yml@main + with: + organization: "${{ github.event.repository.owner.login }}" + repository: "${{ github.event.repository.name }}" + open: ${{ github.event.pull_request.state == 'open' }} + labels: ${{ toJSON(github.event.pull_request.labels.*.name) }} + ref: ${{ github.event.pull_request.head.ref }} + secrets: + github-private-actions-pat: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}" + registry: "${{ secrets.ECR_REGISTRY }}" + secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}" + ecr-region: "${{ secrets.ECR_REGION }}" + ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}" + ``` + + + + + ```yaml title=".github/workflows/main-branch.yaml" + name: Main Branch + on: + push: + branches: [ main ] + + permissions: + contents: write + id-token: write + + jobs: + do: + uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/main-branch.yml@main + with: + organization: "${{ github.event.repository.owner.login }}" + repository: "${{ github.event.repository.name }}" + secrets: + github-private-actions-pat: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}" + registry: "${{ secrets.ECR_REGISTRY }}" + secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}" + ecr-region: "${{ secrets.ECR_REGION }}" + ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}" + ``` + + + + + ```yaml title=".github/workflows/release.yaml" + name: Release + on: + release: + types: [published] + + permissions: + id-token: write + contents: write + + jobs: + perform: + uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/release.yml@main + with: + organization: "${{ github.event.repository.owner.login }}" + repository: "${{ github.event.repository.name }}" + version: ${{ github.event.release.tag_name }} + secrets: + github-private-actions-pat: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}" + registry: "${{ secrets.ECR_REGISTRY }}" + secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}" + ecr-region: "${{ secrets.ECR_REGION }}" + ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}" + ``` + + -
That workflow calls a Reusable Workflow, `cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd`, that is designed to deploy a dockerized application from ECR to EKS using ArgoCD specifically. @@ -207,114 +204,107 @@ Hotfix workflows are designed to push changes directly to a released version in In order to enable hotfix workflows, create two additional workflows and modify the existing release workflow. See each of the following workflows: -
-Hotfix Workflows - - - -Before running any hotfix workflows, we must first create release branches with any release. Modify the existing release workflow to include the `hotfix` job below. - -```yaml -# .github/workflows/release.yaml -name: Release -on: - release: - types: [published] - -permissions: - id-token: write - contents: write - -jobs: - perform: - ... - - hotfix: - name: release / branch - uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/hotfix-mixin.yml@main - with: - version: ${{ github.event.release.tag_name }} -``` - - - - -This `hotfix-branch.yaml` workflow will deploy a duplicate app in the _production_ cluster to a new namespace. We need to deploy to production to validate a hotfix directly for production. - -Deploy this workflow by creating a Pull Request into the a release branch and adding the `deploy` label. - -```yaml -# .github/workflows/hotfix-branch.yaml -name: Hotfix Branch -on: - pull_request: - branches: [ 'release/**' ] - types: [opened, synchronize, reopened, closed, labeled, unlabeled] - -permissions: - pull-requests: write - deployments: write - id-token: write - contents: read - -jobs: - do: - uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/hotfix-branch.yml@main - with: - organization: "${{ github.event.repository.owner.login }}" - repository: "${{ github.event.repository.name }}" - open: ${{ github.event.pull_request.state == 'open' }} - labels: ${{ toJSON(github.event.pull_request.labels.*.name) }} - ref: ${{ github.event.pull_request.head.ref }} - path: deploy - secrets: - github-private-actions-pat: "${{ secrets.PRIVATE_REPO_ACCESS_TOKEN }}" - registry: "${{ secrets.ECR_REGISTRY }}" - secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}" - ecr-region: "${{ secrets.ECR_REGION }}" - ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}" -``` - - - - -Once we've validated a Pull Request for a given hotfix, we can merge that change into the release branch. When changes are pushed to a release branch, the "Hotfix Release" workflow is triggered. _This workflow will deploy the given change directly to production_. - -Before deploying, the workflow will create a minor version release and test it. -After the deployment, it will create a reintegration pull request to bring the hotfix back into the main branch and lower environments. - -In order to enable the "Hotfix Release" workflow, add the following: - -```yaml -# .github/workflows/hotfix-release.yaml -name: Hotfix Release -on: - push: - branches: [ 'release/**' ] - -permissions: - contents: write - id-token: write - -jobs: - do: - uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/hotfix-release.yml@main - with: - organization: "${{ github.event.repository.owner.login }}" - repository: "${{ github.event.repository.name }}" - path: deploy - secrets: - github-private-actions-pat: "${{ secrets.PRIVATE_REPO_ACCESS_TOKEN }}" - registry: "${{ secrets.ECR_REGISTRY }}" - secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}" - ecr-region: "${{ secrets.ECR_REGION }}" - ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}" -``` - - + + Before running any hotfix workflows, we must first create release branches with any release. Modify the existing release workflow to include the `hotfix` job below. + + ```yaml title=".github/workflows/release.yaml" + name: Release + on: + release: + types: [published] + + permissions: + id-token: write + contents: write + + jobs: + perform: + ... + + hotfix: + name: release / branch + uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/hotfix-mixin.yml@main + with: + version: ${{ github.event.release.tag_name }} + ``` + + + + This `hotfix-branch.yaml` workflow will deploy a duplicate app in the _production_ cluster to a new namespace. We need to deploy to production to validate a hotfix directly for production. + + Deploy this workflow by creating a Pull Request into the a release branch and adding the `deploy` label. + + + ```yaml title=".github/workflows/hotfix-branch.yaml" + name: Hotfix Branch + on: + pull_request: + branches: [ 'release/**' ] + types: [opened, synchronize, reopened, closed, labeled, unlabeled] + + permissions: + pull-requests: write + deployments: write + id-token: write + contents: read + + jobs: + do: + uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/hotfix-branch.yml@main + with: + organization: "${{ github.event.repository.owner.login }}" + repository: "${{ github.event.repository.name }}" + open: ${{ github.event.pull_request.state == 'open' }} + labels: ${{ toJSON(github.event.pull_request.labels.*.name) }} + ref: ${{ github.event.pull_request.head.ref }} + path: deploy + secrets: + github-private-actions-pat: "${{ secrets.PRIVATE_REPO_ACCESS_TOKEN }}" + registry: "${{ secrets.ECR_REGISTRY }}" + secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}" + ecr-region: "${{ secrets.ECR_REGION }}" + ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}" + ``` + + + + Once we've validated a Pull Request for a given hotfix, we can merge that change into the release branch. When changes are pushed to a release branch, the "Hotfix Release" workflow is triggered. _This workflow will deploy the given change directly to production_. + + Before deploying, the workflow will create a minor version release and test it. + After the deployment, it will create a reintegration pull request to bring the hotfix back into the main branch and lower environments. + + In order to enable the "Hotfix Release" workflow, add the following: + + + ```yaml title=".github/workflows/hotfix-release.yaml" + name: Hotfix Release + on: + push: + branches: [ 'release/**' ] + + permissions: + contents: write + id-token: write + + jobs: + do: + uses: cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd/.github/workflows/hotfix-release.yml@main + with: + organization: "${{ github.event.repository.owner.login }}" + repository: "${{ github.event.repository.name }}" + path: deploy + secrets: + github-private-actions-pat: "${{ secrets.PRIVATE_REPO_ACCESS_TOKEN }}" + registry: "${{ secrets.ECR_REGISTRY }}" + secret-outputs-passphrase: "${{ secrets.GHA_SECRET_OUTPUT_PASSPHRASE }}" + ecr-region: "${{ secrets.ECR_REGION }}" + ecr-iam-role: "${{ secrets.ECR_IAM_ROLE }}" + ``` + + + -
These workflows also call the same Reusuable Workflow repository, `cloudposse/github-actions-workflows-docker-ecr-eks-helm-argocd`, as well as several of the same Reusuable Workflows called from that repository. For example, `cloudposse/github-actions-workflows` and `cloudposse/actions-private`. diff --git a/docs/layers/software-delivery/lambda/lambda.mdx b/docs/layers/software-delivery/lambda/lambda.mdx index 72ee82cdd..3266301a7 100644 --- a/docs/layers/software-delivery/lambda/lambda.mdx +++ b/docs/layers/software-delivery/lambda/lambda.mdx @@ -8,6 +8,7 @@ import Intro from '@site/src/components/Intro'; import KeyPoints from '@site/src/components/KeyPoints'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; +import CollapsibleText from '@site/src/components/CollapsibleText'; Deploy Lambda functions using GitHub Workflows with a code-driven approach. The build process updates S3 with assets and SSM with the new version, requiring a Terraform run for promotion. GitHub Workflows manage the entire lifecycle, from building and packaging Lambda functions to deploying them with reusable workflows. @@ -58,184 +59,175 @@ flowchart LR Application repository updates S3 with build assets, then updates SSM with the new version. Each SSM update is basically a promotion, and requires a Terraform run to realize the change. -
-Build and Dev Promote - - - - ```yaml - # .github/workflows/reusable-publish-lambda-zip.yaml - name: Publish Lambda Function - on: - workflow_call: - inputs: - function-name: - required: true - type: string - source-folder: - required: true - type: string - artifacts-bucket-and-prefix: - required: true - type: string - aws-region: - required: true - type: string - secrets: - cicd-role-arn: - required: true - - permissions: - id-token: write - contents: read - - jobs: - publish: - runs-on: self-hosted - steps: - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ inputs.cicd-role-arn }} - aws-region: ${{ inputs.aws-region }} - - name: Checkout - uses: actions/checkout@v4 - - name: Package Lambda - run: | - cd ${{ inputs.source-folder }} && zip ${{ github.sha }}.zip * - - name: Push Lambda - run: | - aws s3 cp ${{ inputs.source-folder }}/${{ github.sha }}.zip s3://${{ inputs.artifacts-bucket-and-prefix }}/${{ inputs.function-name }}/ --sse - - name: Write tag to SSM - run: | - aws ssm put-parameter --name /lambda/${{ inputs.function-name}}/tag --type String --value ${{ github.sha }} --overwrite - ``` - + + ```yaml title=".github/workflows/reusable-publish-lambda-zip.yaml" + name: Publish Lambda Function + on: + workflow_call: + inputs: + function-name: + required: true + type: string + source-folder: + required: true + type: string + artifacts-bucket-and-prefix: + required: true + type: string + aws-region: + required: true + type: string + secrets: + cicd-role-arn: + required: true + + permissions: + id-token: write + contents: read + + jobs: + publish: + runs-on: self-hosted + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ inputs.cicd-role-arn }} + aws-region: ${{ inputs.aws-region }} + - name: Checkout + uses: actions/checkout@v4 + - name: Package Lambda + run: | + cd ${{ inputs.source-folder }} && zip ${{ github.sha }}.zip * + - name: Push Lambda + run: | + aws s3 cp ${{ inputs.source-folder }}/${{ github.sha }}.zip s3://${{ inputs.artifacts-bucket-and-prefix }}/${{ inputs.function-name }}/ --sse + - name: Write tag to SSM + run: | + aws ssm put-parameter --name /lambda/${{ inputs.function-name}}/tag --type String --value ${{ github.sha }} --overwrite + ``` + - - - ```yaml - # .github/workflows/reusable-promote-lambda-zip.yaml - name: Publish Lambda Function - on: - workflow_call: - inputs: - function-name: - required: true - type: string - artifacts-bucket-and-prefix: - required: true - type: string - aws-region: - required: true - type: string - secrets: - cicd-role-arn: - required: true - staging-role-arn: - required: true - prod-role-arn: - required: true - - permissions: - id-token: write - contents: read - - jobs: - publish: - runs-on: self-hosted - steps: - - name: Configure AWS credentials for 'cicd' role - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ inputs.cicd-role-arn }} - aws-region: ${{ inputs.aws-region }} - - name: Configure AWS credentials for source stage - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }} - aws-session-token: ${{ env.AWS_SESSION_TOKEN }} - role-duration-seconds: 3000 - role-skip-session-tagging: true - role-to-assume: ${{ inputs.staging-role-arn }} - aws-region: ${{ inputs.aws-region }} - - name: Checkout - uses: actions/checkout@v4 - - name: Get tag from SSM - id: get-tag-from-ssm - run: | - TAG=`aws ssm get-parameter --name /lambda/${{ inputs.function-name }}/tag | jq -r .Parameter.Value` - echo "tag=$TAG" >> $GITHUB_OUTPUT - - name: Copy Lambda to local - run: | - aws s3 cp s3://${{ inputs.artifacts-bucket-and-prefix }}/${{ inputs.function-name }}/${{ steps.get-tag-from-ssm.outputs.tag }}.zip . - - name: Configure AWS credentials for 'cicd' role - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ inputs.cicd-role-arn }} - aws-region: ${{ inputs.aws-region }} - - name: Configure AWS credentials for destination stage - uses: aws-actions/configure-aws-credentials@v4 - with: - aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }} - aws-session-token: ${{ env.AWS_SESSION_TOKEN }} - role-duration-seconds: 3000 - role-skip-session-tagging: true - role-to-assume: ${{ inputs.prod-role-arn }} - aws-region: ${{ inputs.aws-region }} - - name: Copy Lambda to destination bucket - run: | - aws s3 cp ${{ steps.get-tag-from-ssm.outputs.tag }}.zip \ - s3://${{ inputs.artifacts-bucket-and-prefix }}/${{ inputs.function-name }}/ --sse - - name: Write tag to SSM - run: | - aws ssm put-parameter --name /lambda/${{ inputs.function-name}}/tag --type String --value ${{ steps.get-tag-from-ssm.outputs.tag }} --overwrite - ``` - + + ```yaml title=".github/workflows/reusable-promote-lambda-zip.yaml" + name: Publish Lambda Function + on: + workflow_call: + inputs: + function-name: + required: true + type: string + artifacts-bucket-and-prefix: + required: true + type: string + aws-region: + required: true + type: string + secrets: + cicd-role-arn: + required: true + staging-role-arn: + required: true + prod-role-arn: + required: true + + permissions: + id-token: write + contents: read + + jobs: + publish: + runs-on: self-hosted + steps: + - name: Configure AWS credentials for 'cicd' role + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ inputs.cicd-role-arn }} + aws-region: ${{ inputs.aws-region }} + - name: Configure AWS credentials for source stage + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }} + aws-session-token: ${{ env.AWS_SESSION_TOKEN }} + role-duration-seconds: 3000 + role-skip-session-tagging: true + role-to-assume: ${{ inputs.staging-role-arn }} + aws-region: ${{ inputs.aws-region }} + - name: Checkout + uses: actions/checkout@v4 + - name: Get tag from SSM + id: get-tag-from-ssm + run: | + TAG=`aws ssm get-parameter --name /lambda/${{ inputs.function-name }}/tag | jq -r .Parameter.Value` + echo "tag=$TAG" >> $GITHUB_OUTPUT + - name: Copy Lambda to local + run: | + aws s3 cp s3://${{ inputs.artifacts-bucket-and-prefix }}/${{ inputs.function-name }}/${{ steps.get-tag-from-ssm.outputs.tag }}.zip . + - name: Configure AWS credentials for 'cicd' role + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ inputs.cicd-role-arn }} + aws-region: ${{ inputs.aws-region }} + - name: Configure AWS credentials for destination stage + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ env.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ env.AWS_SECRET_ACCESS_KEY }} + aws-session-token: ${{ env.AWS_SESSION_TOKEN }} + role-duration-seconds: 3000 + role-skip-session-tagging: true + role-to-assume: ${{ inputs.prod-role-arn }} + aws-region: ${{ inputs.aws-region }} + - name: Copy Lambda to destination bucket + run: | + aws s3 cp ${{ steps.get-tag-from-ssm.outputs.tag }}.zip \ + s3://${{ inputs.artifacts-bucket-and-prefix }}/${{ inputs.function-name }}/ --sse + - name: Write tag to SSM + run: | + aws ssm put-parameter --name /lambda/${{ inputs.function-name}}/tag --type String --value ${{ steps.get-tag-from-ssm.outputs.tag }} --overwrite + ``` + - - ```yaml - # .github/workflows/reusable-promote-lambda-zip.yaml - name: Deploy Lambda via Spacelift - on: - workflow_call: - inputs: - function-name: - required: true - type: string - stack: - required: true - type: string - secrets: - spacelift-api-key-id: - required: true - spacelift-api-key-secret: - required: true - - jobs: - deploy: - runs-on: self-hosted - container: 123456789012.dkr.ecr.us-east-2.amazonaws.com/acme/infra:latest - steps: - - name: Trigger Spacelift Stack Execution - env: - SPACELIFT_API_ENDPOINT: https://acme.app.spacelift.io - SPACELIFT_API_KEY_ID: ${{ secrets.spacelift-api-key-id }} - SPACELIFT_API_KEY_SECRET: ${{ secrets.spacelift-api-key-secret }} - run: | - spacectl stack deploy --id ${{ inputs.stack }}-lambda-${{ inputs.function-name}} --tail - ``` - + + ```yaml title=".github/workflows/reusable-promote-lambda-zip.yaml" + name: Deploy Lambda via Spacelift + on: + workflow_call: + inputs: + function-name: + required: true + type: string + stack: + required: true + type: string + secrets: + spacelift-api-key-id: + required: true + spacelift-api-key-secret: + required: true + + jobs: + deploy: + runs-on: self-hosted + container: 123456789012.dkr.ecr.us-east-2.amazonaws.com/acme/infra:latest + steps: + - name: Trigger Spacelift Stack Execution + env: + SPACELIFT_API_ENDPOINT: https://acme.app.spacelift.io + SPACELIFT_API_KEY_ID: ${{ secrets.spacelift-api-key-id }} + SPACELIFT_API_KEY_SECRET: ${{ secrets.spacelift-api-key-secret }} + run: | + spacectl stack deploy --id ${{ inputs.stack }}-lambda-${{ inputs.function-name}} --tail + ``` + -
### Implementation diff --git a/examples/snippets/.github/workflows/atmos-terraform-apply.yaml b/examples/snippets/.github/workflows/atmos-terraform-apply.yaml index dc33047b5..ecf28fa1c 100644 --- a/examples/snippets/.github/workflows/atmos-terraform-apply.yaml +++ b/examples/snippets/.github/workflows/atmos-terraform-apply.yaml @@ -21,7 +21,7 @@ jobs: - "amd64" - "common" steps: - - uses: cloudposse-github-actions/get-pr@v1 + - uses: cloudposse-github-actions/get-pr@v2 id: pr outputs: diff --git a/examples/snippets/stacks/workflows/grafana.yaml b/examples/snippets/stacks/workflows/grafana.yaml index 09e9ab41e..379af9ce7 100644 --- a/examples/snippets/stacks/workflows/grafana.yaml +++ b/examples/snippets/stacks/workflows/grafana.yaml @@ -30,7 +30,7 @@ workflows: command: |- echo "Now update the eks/cluster map_additional_iam_roles and reapply eks/cluster" - deploy/data-sources: + deploy/grafana: description: deploys centralized Grafana and all sub components steps: - command: terraform deploy grafana -s core-use1-auto