Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: CDK for infrastructure management and deployment #2576

Open
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

almarcotte
Copy link
Contributor

@almarcotte almarcotte commented Jan 25, 2025

Build and Release

Goals

  1. Automate the build, release and deployment of the application
  2. Automate version management
  3. Make sure manual input is still required

How it works

On manual input, the workflow should do the following:

  1. Release a new version (which includes creating a tag and updating package.json) automatically
  2. Build and publish to S3 (using the existing publish.js script)
  3. Trigger next workflow to deploy the CDK stack for both environments

Manual input will be needed for the deployments to actually go through. This has to be enabled in the environment settings on the repository:

image

I'm bringing semantic versioning. It's used for a few things but primarily to keep the package.json's version field up-to-date. It'll also create the tags and generate a CHANGELOG.md file. A lot of this depends on conventional commits so if it's too involved then we can just drop it. I know that @dekkerglen publishes a blog on the website for bigger releases so the automated change log might be useful.

Deployment

Adding a workflow to deploy CDK changes. It can be used manually to deploy or be called by another workflow (like the app release) to trigger a deployment of the infrastructure with CDK.

image

The values picked there are passed as context values to CDK to determine which environment to deploy into.

It requires a role which can be created by CDK so this will require one last manual run by @dekkerglen to get the role created. Then, it needs to be added as a secret on the repository (CDK_IAM_ROLE). There are also a couple more secrets to add, mostly the values that are taken from the environment variables.

Scheduled Jobs

Creating a Fargate cluster and a reusable way for us to deploy scheduled jobs to it. For a given job it will create:

  • An ECR repository
  • A task definition
  • A schedule rule

All we need to do afterwards is push an image to the ECR repository and Fargate will take care of the rest. There is a bit of a chicken-and-egg situation where we need the repository created to be able to push to it but the task definition needs a repository. What would happen now is this:

  1. We create a job in the stack (by adding a new entry in the jobs config)
  2. Deploy the stack
  3. The repository will be created, along with the job definition

From this point on the job will run on schedule but fail immediately (can't pull the image because it doesn't exist). I think we're fine with this? It means very minimal costs because nothing runs. Once we push the image to the repository the next scheduled run will execute as expected.

A bit of restructuring

The goal was to reorganize the code a bit so that the main stack file didn't grow too wildly. I wanted to make sure that the generated CloudFormation template was the same so I generated both and diffed them:

80c80,82
<     "ApplicationName": "CubeCobra-development-app",
---
>     "ApplicationName": {
>      "Ref": "Application"
>     },
97c99,101
<     "ApplicationName": "CubeCobra-development-app",
---
>     "ApplicationName": {
>      "Ref": "Application"
>     },
335c339
<     "Analytics": "v2:deflate64:H4sIAAAAAAAA/1WPwWrDQAxEvyX3tRq7FNpjMTnkFhzotShrOShea4NWTg7L/ntxmpD2NMw8mGEaqOsPWK/wmirfj1XgA+S9oR9dRynO6snhNX1nT2o8sEejCQWPpJDbZ+baQf7Y4hgnyF0MN/LQrSRD8bTTOHCg4ihgMvYHwoWEEXI7yOf5HJYWjuL+2y/SdE83cmGNMpFYcRpno7dXWKbIR+33ZOU2fP9QnMSe4JReLs0a6neoV6fEXOksxhNB96s/DdtzHA4BAAA="
---
>     "Analytics": "v2:deflate64:H4sIAAAAAAAA/1WPzW7CQAyEn4X7xiWgSu2xRBy4oSD1iszGqUw2XrR24LDad0ehVG1Po29m5J8V1PU7LBd408p3QxX4BPlg6AfXksYpeXJ402P2lIx79mg0ouAXJcjNr+eaXv5gcYwj5DaGR/KjO1FD8bRPsedAxekaNpMfyDao5CigGvsT4dwLA+Sml4/LJcwzOYr7j5+U9Olu5copykhixaU4Gb2uYV5MPqbuQFYeZzw/Kk5iR3DWl+tqCfUb1IuzMldpEuORoP3WO6rBml4cAQAA"

infra/jest.config.js Outdated Show resolved Hide resolved
Comment on lines +24 to +29
- name: Run Semantic Release
id: semantic_release
run: |
npx semantic-release --ci
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This should work because it's not a PR coming in from a fork. semantic-release needs write access to make a commit (update version in package.json) and create a tag.

Comment on lines +68 to +72
strategy:
matrix:
target:
- development
- production
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This will create 2 parallel jobs but both require manual approval before starting so development can be deployed first. We could have a deploy_dev and deploy_prod job that needs the dev one instead.

@almarcotte almarcotte force-pushed the feat/move-cdk-to-main-repo branch from 463335e to 3af9871 Compare February 3, 2025 20:25
Comment on lines +11 to +24
export class BootstrapStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);

const pipeline = new Pipeline(this, 'Pipeline', {
githubRepositories: ['dekkerglen/CubeCobra'],
});

new ssm.StringParameter(this, 'GitHubActionsRoleArnParameter', {
parameterName: '/cdk/bootstrap/github-actions-role-arn',
stringValue: pipeline.githubRole.roleArn,
});
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need this role so that GitHub can deploy CDK. It needs to be one once before anything else. @dekkerglen can create it locally on his machine with:

npx cdk deploy --context environment=development --context bootstrap=true

npx cdk deploy --context environment=production --context bootstrap=true

then the role should be stored in environment secrets on GitHub as CDK_IAM_ROLE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants