Set up deployment pipeline
Set up a deployment pipeline that builds your static website once and deploys it to S3/CloudFront across environments.
Before you begin
- Set up CloudFront static website infrastructure.
- Have a GitHub repository in the
oslokommuneorganization for your application (not your IaC repo). We recommend that you use your team name as prefix.
Step 1: Protect your default branch
Your repository automatically inherits branch rulesets from the GitHub organization when you set a custom property.
Go to Settings > Custom properties and set gp-repository-type to app.
After setting the custom property, verify that Settings > Rulesets shows rules inherited from the organization.
Step 2: Create a GitHub Actions environment for production
This restricts production deployments to the default branch.
- Go to Settings > Environments > New environment
- Set the name to match your production environment:
- For an application repo:
<environment>(e.g.,pirates-prod) - For an application in a monorepo
<environment>-<app-name>(e.g.,pirates-prod-zebra)
- For an application repo:
- Under Deployment branches and tags, select Selected branches and add your default branch (
mainormaster)
Manual approval
To enable manual approval, open your GitHub Actions environment for production:
- Set Required reviewers to your GitHub team
- Click Save protection rules
Step 3: Request CI/CD access
Message Utviklerflyt on Slack (#utviklerflyt-support) to add your application repository to their centralized configuration:
Hei! Kan dere gi
<repo-app>nødvendige tilganger for CI/CD?
Info
To increase the level of self-service, we're currently working on removing the need for this step.
Step 4: Add configuration files
Create a new branch and add the following configuration files.
Step 4.1: Add .gp.cicd.json
The configuration differs depending on your repository type:
- Application repo — the repository contains code for a single application, while the associated infrastructure lives in a separate IaC repository (e.g.,
pirates-iac). - Application monorepo — the repository contains code for multiple applications, while the associated infrastructure lives in a separate IaC repository (e.g.,
pirates-iac).
Download .gp.cicd.json:
gh api repos/oslokommune/golden-path-templates/contents/templates/gh-cicd-app/.gp.cicd.json \
--jq '.content' | base64 -d > .gp.cicd.json
Update these values (many of which can be found in common-config.yml in your infrastructure repository):
| Field | Description | Example |
|---|---|---|
<team-name> |
Your team name | pirates |
<repo-iac> |
Infrastructure-as-code repository name | pirates-iac |
<dev-aws-account-id> |
AWS account ID for dev | 123456789012 |
<prod-aws-account-id> |
AWS account ID for prod | 987654321098 |
<dev-environment-name> |
Name of your dev environment | pirates-dev |
<prod-environment-name> |
Name of your prod environment | pirates-prod |
<aws-region> |
Your AWS region | eu-west-1 |
Download .gp.cicd.json:
gh api repos/oslokommune/golden-path-templates/contents/templates/gh-cicd-app-monorepo/.gp.cicd.json \
--jq '.content' | base64 -d > .gp.cicd.json
Update these values (many of which can be found in common-config.yml in your infrastructure repository):
| Field | Description | Example |
|---|---|---|
<team-name> |
Your team name | pirates |
<repo-iac> |
Infrastructure-as-code repository name | pirates-iac |
<dev-aws-account-id> |
AWS account ID for dev | 123456789012 |
<prod-aws-account-id> |
AWS account ID for prod | 987654321098 |
<dev-environment-name> |
Name of your dev environment | pirates-dev |
<prod-environment-name> |
Name of your prod environment | pirates-prod |
<aws-region> |
Your AWS region | eu-west-1 |
Step 4.2: Add CODEOWNERS
Add a CODEOWNERS file to define who owns the repository and approves PRs:
| Field | Description | Example |
|---|---|---|
<github-team-name> |
The name of your GitHub team | utviklerflyt |
Step 4.3: Add Renovate configuration
Download renovate.json5 to the repository root:
gh api repos/oslokommune/golden-path-templates/contents/templates/gh-cicd-app/renovate.json5 \
--jq '.content' | base64 -d > renovate.json5
What is Renovate?
Renovate automatically creates pull requests to keep your dependencies up to date. Think of it as a better Dependabot. Learn more in the Renovate reference documentation.
Step 5: Add the deployment workflow
Download the zebra deployment workflow as a starting point and save it to .github/workflows/<app-name>_deployment.yml.
Address the TODO comments in the workflow. The main adaptation is in the build-and-upload-artifact job, where you customize the build and test steps to match your application.
Build once deploy many
The deployment pipeline is designed to build, upload and promote the exact same immutable artifact across environments ("build once, deploy many").
For static websites where configuration typically differs per environment, see how zebra handles environment configuration.
Post-deployment testing
The deployment pipeline contains a job test-dev and test-prod that runs after deployment to development and production, respectively. Feel free to add more tests to these jobs to validate the behavior of your running application in AWS after a deployment (e.g., smoke tests, end-to-end tests, etc.).
Step 6: Create a pull request
Push the branch and create a pull request.
Verify that the build job succeeds and that no deployment occurs.
Step 7: Merge and deploy
- Merge the pull request.
- The workflow deploys to your dev environment automatically. Verify the site is accessible by checking that the Test webapp job succeeds — a green check means the job curled your dev URL and got a response.
- Approve the production deployment when prompted. Verify that the production site is accessible.