Skip to content

Bootstrap

Bootstrap #91

Workflow file for this run

name: Bootstrap
# Perform initial project setup to enable development of a new service
on:
workflow_dispatch:
inputs:
issue_number:
description: Issue number (e.g. PI-123)
required: true
type: string
project_name:
description: Project name
required: true
type: string
project_template:
description: Project template
required: true
type: choice
default: message-listener-with-api-client
options:
- api-client-and-server
- api-server
- message-listener
- message-listener-with-api-client
- message-listener-with-api-client-and-server
- 'No template - I want to create the project from scratch'
create_sentry_project:
description: Will the service use Sentry for capturing exceptions?
default: true
required: true
type: boolean
create_oauth_client:
description: Will the service consume another HTTP API that requires HMPPS Auth client credentials?
default: true
required: true
type: boolean
create_ingress:
description: Will the service provide a HTTP API?
default: false
required: true
type: boolean
create_queue:
description: Will the service consume HMPPS domain event messages?
default: true
required: true
type: boolean
create_infra:
description: Will the service be deployed to MOJ Cloud Platform?
default: true
required: true
type: boolean
jobs:
auth-setup:
runs-on: ubuntu-latest
if: ${{ inputs.create_oauth_client }}
steps:
- uses: actions/checkout@v4
- name: Create issue for manual steps
run: |
gh issue create \
--title "${{ inputs.issue_number }} Request HMPPS Auth client for ${{ inputs.project_name }}" \
--body '
- [ ] Clone Jira ticket: [HAAR-1662](https://dsdmoj.atlassian.net/browse/HAAR-1662)
- [ ] Raise in Slack: [#hmpps-auth-audit-registers](https://mojdt.slack.com/archives/C02S71KUBED)' \
--label bootstrap
env:
GITHUB_TOKEN: ${{ github.token }}
project-setup:
if: ${{ inputs.project_template != 'No template - I want to create the project from scratch' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- name: Render project template
uses: ./.github/actions/render-project-template
with:
project_name: ${{ inputs.project_name }}
project_template: ${{ inputs.project_template }}
- name: Create pull request
id: pr
uses: ./.github/actions/create-signed-pull-request
with:
add-paths: |
settings.gradle.kts
.github/workflows
.idea/runConfigurations
doc/tech-docs
projects/${{ inputs.project_name }}
branch: bootstrap/${{ inputs.project_name }}
commit-message: ${{ inputs.issue_number }} Create initial project for ${{ inputs.project_name }}
private-key: ${{ secrets.BOT_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.BOT_GPG_PASSPHRASE }}
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- name: Create issue for manual steps
run: |
gh issue create \
--title "${{ inputs.issue_number }} Complete project setup for ${{ inputs.project_name }}" \
--body "- [ ] Merge pull request: ${{ steps.pr.outputs.pull-request-url }}" \
--label bootstrap
env:
GITHUB_TOKEN: ${{ github.token }}
sentry-setup:
runs-on: ubuntu-latest
if: ${{ inputs.create_sentry_project }}
outputs:
project_slug: ${{ steps.project.outputs.slug }}
steps:
- uses: actions/checkout@v4
- name: Create project
id: project
run: |
response=$(curl https://sentry.io/api/0/teams/ministryofjustice/probation-integration/projects/ --fail \
-H "Authorization: Bearer $SENTRY_AUTH_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"name":"${{ inputs.project_name }}"}')
echo "slug=$(echo "$response" | jq -r '.slug')" | tee -a "$GITHUB_OUTPUT"
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
- name: Set platform to Kotlin
run: |
curl -X PUT "https://sentry.io/api/0/projects/ministryofjustice/$SLUG/" --fail \
-H "Authorization: Bearer $SENTRY_AUTH_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"platform":"kotlin"}'
env:
SLUG: ${{ steps.project.outputs.slug }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
- name: Get client key id
id: client_key
run: |
response=$(curl "https://sentry.io/api/0/projects/ministryofjustice/$SLUG/keys/" --fail \
-H "Authorization: Bearer $SENTRY_AUTH_TOKEN")
echo "id=$(echo "$response" | jq -r '.[0].id')" | tee -a "$GITHUB_OUTPUT"
env:
SLUG: ${{ steps.project.outputs.slug }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
- name: Set rate limit (10/minute)
run: |
curl -X PUT "https://sentry.io/api/0/projects/ministryofjustice/$SLUG/keys/$KEY_ID/" --fail \
-H "Authorization: Bearer $SENTRY_AUTH_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"rateLimit":{"count":10,"window":60}}'
env:
SLUG: ${{ steps.project.outputs.slug }}
KEY_ID: ${{ steps.client_key.outputs.id }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
- name: Create alert
run: |
curl -X POST "https://sentry.io/api/0/projects/ministryofjustice/$SLUG/rules/?duplicateRule=true&wizardV3=true" --fail \
-H "Authorization: Bearer $SENTRY_AUTH_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"conditions":[{"id":"sentry.rules.conditions.first_seen_event.FirstSeenEventCondition","name":"A new issue is created"},{"id":"sentry.rules.conditions.regression_event.RegressionEventCondition","name":"The issue changes state from resolved to unresolved"},{"id":"sentry.rules.conditions.reappeared_event.ReappearedEventCondition","name":"The issue changes state from ignored to unresolved"}],"filters":[],"actions":[{"workspace":"50134","id":"sentry.integrations.slack.notify_action.SlackNotifyServiceAction","channel":"probation-integration-notifications","channel_id":"C033HPR0W91","tags":"","name":"Send a notification to the MOJ Digital & Technology Slack workspace to probation-integration-notifications (optionally, an ID: C033HPR0W91) and show tags [] in notification"}],"actionMatch":"any","filterMatch":"all","frequency":5,"name":"New issues","dateCreated":"2023-01-23T12:03:42.969890Z","owner":"team:1611212","environment":null,"projects":["${{ steps.project.outputs.slug }}"]}'
env:
SLUG: ${{ steps.project.outputs.slug }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
sentry-secrets:
runs-on: ubuntu-latest
if: ${{ inputs.create_sentry_project }}
needs: sentry-setup
strategy:
matrix:
environment: ["test", "preprod", "prod"]
environment: ${{ matrix.environment }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/cloud-platform-auth
with:
api: ${{ secrets.KUBE_ENV_API }}
cert: ${{ secrets.KUBE_CERT }}
cluster: ${{ secrets.KUBE_CLUSTER }}
namespace: ${{ secrets.KUBE_NAMESPACE }}
token: ${{ secrets.KUBE_TOKEN }}
- name: Get client key DSN
id: client_key
run: |
response=$(curl "https://sentry.io/api/0/projects/ministryofjustice/$SLUG/keys/" --fail \
-H "Authorization: Bearer $SENTRY_AUTH_TOKEN")
dsn=$(echo "$response" | jq -r '.[0].dsn.public')
echo "::add-mask::$dsn"
echo "dsn=$dsn" | tee -a "$GITHUB_OUTPUT"
env:
SLUG: ${{ needs.sentry-setup.outputs.project_slug }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
- name: Store DSN as Kubernetes secret
run: kubectl create secret generic "$PROJECT-sentry" --from-literal "SENTRY_DSN=$VALUE" --from-literal "SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN"
env:
PROJECT: ${{ inputs.project_name }}
VALUE: ${{ steps.client_key.outputs.dsn }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
sqs-queue-setup:
runs-on: ubuntu-latest
if: ${{ inputs.create_queue }}
steps:
- id: project_name
run: echo "with_underscores_uppercase=$(echo '${{ inputs.project_name }}' | sed 's/-/_/g' | tr '[:lower:]' '[:upper:]')" | tee -a "$GITHUB_OUTPUT"
- uses: actions/checkout@v4
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- uses: actions/checkout@v4
with:
path: cloud-platform-environments-dev
repository: ministryofjustice/cloud-platform-environments
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- uses: actions/checkout@v4
with:
path: cloud-platform-environments-preprod
repository: ministryofjustice/cloud-platform-environments
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- uses: actions/checkout@v4
with:
path: cloud-platform-environments-prod
repository: ministryofjustice/cloud-platform-environments
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- name: Render Terraform queue template
run: |
sed 's/SERVICE_NAME_UPPERCASE/${{ steps.project_name.outputs.with_underscores_uppercase }}/g;s/SERVICE_NAME/${{ inputs.project_name }}/g' templates/sqs.tf > 'cloud-platform-environments-dev/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-dev/resources/${{ inputs.project_name }}-queue.tf'
sed 's/SERVICE_NAME_UPPERCASE/${{ steps.project_name.outputs.with_underscores_uppercase }}/g;s/SERVICE_NAME/${{ inputs.project_name }}/g' templates/sqs.tf > 'cloud-platform-environments-preprod/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-preprod/resources/${{ inputs.project_name }}-queue.tf'
sed 's/SERVICE_NAME_UPPERCASE/${{ steps.project_name.outputs.with_underscores_uppercase }}/g;s/SERVICE_NAME/${{ inputs.project_name }}/g' templates/sqs.tf > 'cloud-platform-environments-prod/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-prod/resources/${{ inputs.project_name }}-queue.tf'
- name: Update IAM access to queues
run: |
sed -i '/queue = \[/a \ module.${{ inputs.project_name }}-queue,' 'cloud-platform-environments-dev/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-dev/resources/iam.tf'
sed -i '/queue = \[/a \ module.${{ inputs.project_name }}-queue,' 'cloud-platform-environments-preprod/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-preprod/resources/iam.tf'
sed -i '/queue = \[/a \ module.${{ inputs.project_name }}-queue,' 'cloud-platform-environments-prod/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-prod/resources/iam.tf'
sed -i '/dlq = \[/a \ module.${{ inputs.project_name }}-dlq,' 'cloud-platform-environments-dev/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-dev/resources/iam.tf'
sed -i '/dlq = \[/a \ module.${{ inputs.project_name }}-dlq,' 'cloud-platform-environments-preprod/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-preprod/resources/iam.tf'
sed -i '/dlq = \[/a \ module.${{ inputs.project_name }}-dlq,' 'cloud-platform-environments-prod/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-prod/resources/iam.tf'
- name: Create dev pull request
id: dev-pr
uses: ./.github/actions/create-signed-pull-request
with:
path: cloud-platform-environments-dev
add-paths: namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-dev
branch: ${{ inputs.issue_number }}-create-${{ inputs.project_name }}-queue-dev
commit-message: ${{ inputs.issue_number }} Create SQS queues for ${{ inputs.project_name }} (dev)
private-key: ${{ secrets.BOT_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.BOT_GPG_PASSPHRASE }}
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- name: Create preprod pull request
id: preprod-pr
uses: ./.github/actions/create-signed-pull-request
with:
path: cloud-platform-environments-preprod
add-paths: namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-preprod
branch: ${{ inputs.issue_number }}-create-${{ inputs.project_name }}-queue-preprod
commit-message: ${{ inputs.issue_number }} Create SQS queues for ${{ inputs.project_name }} (preprod)
private-key: ${{ secrets.BOT_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.BOT_GPG_PASSPHRASE }}
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- name: Create prod pull request
id: prod-pr
uses: ./.github/actions/create-signed-pull-request
with:
path: cloud-platform-environments-prod
add-paths: namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-prod
branch: ${{ inputs.issue_number }}-create-${{ inputs.project_name }}-queue-prod
commit-message: ${{ inputs.issue_number }} Create SQS queues for ${{ inputs.project_name }} (prod)
private-key: ${{ secrets.BOT_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.BOT_GPG_PASSPHRASE }}
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- name: Create issue for manual steps
run: |
gh issue create \
--title '${{ inputs.issue_number }} Complete queue setup for ${{ inputs.project_name }}' \
--body '
- [ ] Enter the event types the service will consume into the filter_policy for dev: [Edit file](https://github.com/ministryofjustice/cloud-platform-environments/edit/${{ inputs.issue_number }}-create-${{ inputs.project_name }}-queue-dev/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-dev/resources/${{ inputs.project_name }}-queue.tf)
- [ ] Enter the event types the service will consume into the filter_policy for preprod: [Edit file](https://github.com/ministryofjustice/cloud-platform-environments/edit/${{ inputs.issue_number }}-create-${{ inputs.project_name }}-queue-preprod/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-preprod/resources/${{ inputs.project_name }}-queue.tf)
- [ ] Enter the event types the service will consume into the filter_policy for prod: [Edit file](https://github.com/ministryofjustice/cloud-platform-environments/edit/${{ inputs.issue_number }}-create-${{ inputs.project_name }}-queue-prod/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-prod/resources/${{ inputs.project_name }}-queue.tf)
- [ ] Request approval in [#ask-cloud-platform](https://mojdt.slack.com/archives/C57UPMZLY)
> ${{ steps.dev-pr.outputs.pull-request-url }}
> ${{ steps.preprod-pr.outputs.pull-request-url }}
> ${{ steps.prod-pr.outputs.pull-request-url }}
- [ ] Merge the pull requests' \
--label bootstrap
env:
GITHUB_TOKEN: ${{ github.token }}
infra-setup:
runs-on: ubuntu-latest
if: ${{ inputs.create_infra }}
steps:
- id: project_name
run: echo "hash=$(echo -n '${{ inputs.project_name }}' | sha1sum | head -c 8)" | tee -a "$GITHUB_OUTPUT"
- uses: actions/checkout@v4
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- uses: actions/checkout@v4
with:
path: cloud-platform-environments-dev
repository: ministryofjustice/cloud-platform-environments
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- uses: actions/checkout@v4
with:
path: cloud-platform-environments-preprod
repository: ministryofjustice/cloud-platform-environments
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- uses: actions/checkout@v4
with:
path: cloud-platform-environments-prod
repository: ministryofjustice/cloud-platform-environments
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- name: Add Pingdom check
run: sed -i '/add new projects here/i \ "${{ inputs.project_name }}",' 'cloud-platform-environments-prod/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-prod/resources/pingdom.tf'
- name: Render certificate templates
run: |
sed 's/$SERVICE_NAME/${{ inputs.project_name }}/g;s/$SERVICE_URL/${{ inputs.project_name }}-dev.hmpps.service.justice.gov.uk/g;s/$SERVICE_SHORT_URL/${{ steps.project_name.outputs.hash }}-dev.hmpps.service.justice.gov.uk/g;s/$ENV/dev/g' templates/certificate.yml >> 'cloud-platform-environments-dev/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-dev/05-certificates.yml'
sed 's/$SERVICE_NAME/${{ inputs.project_name }}/g;s/$SERVICE_URL/${{ inputs.project_name }}-preprod.hmpps.service.justice.gov.uk/g;s/$SERVICE_SHORT_URL/${{ steps.project_name.outputs.hash }}-preprod.hmpps.service.justice.gov.uk/g;s/$ENV/preprod/g' templates/certificate.yml >> 'cloud-platform-environments-preprod/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-preprod/05-certificates.yml'
sed 's/$SERVICE_NAME/${{ inputs.project_name }}/g;s/$SERVICE_URL/${{ inputs.project_name }}.hmpps.service.justice.gov.uk/g;s/$SERVICE_SHORT_URL/${{ steps.project_name.outputs.hash }}.hmpps.service.justice.gov.uk/g;s/$ENV/prod/g' templates/certificate.yml >> 'cloud-platform-environments-prod/namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-prod/05-certificates.yml'
- name: Create dev pull request
id: dev-pr
uses: ./.github/actions/create-signed-pull-request
with:
path: cloud-platform-environments-dev
add-paths: namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-dev
branch: ${{ inputs.issue_number }}-create-${{ inputs.project_name }}-infra-dev
commit-message: ${{ inputs.issue_number }} Create certificate for ${{ inputs.project_name }} (dev)
private-key: ${{ secrets.BOT_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.BOT_GPG_PASSPHRASE }}
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- name: Create preprod pull request
id: preprod-pr
uses: ./.github/actions/create-signed-pull-request
with:
path: cloud-platform-environments-preprod
add-paths: namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-preprod
branch: ${{ inputs.issue_number }}-create-${{ inputs.project_name }}-infra-preprod
commit-message: ${{ inputs.issue_number }} Create certificate for ${{ inputs.project_name }} (preprod)
private-key: ${{ secrets.BOT_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.BOT_GPG_PASSPHRASE }}
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- name: Create prod pull request
id: prod-pr
uses: ./.github/actions/create-signed-pull-request
with:
path: cloud-platform-environments-prod
add-paths: namespaces/live.cloud-platform.service.justice.gov.uk/hmpps-probation-integration-services-prod
branch: ${{ inputs.issue_number }}-create-${{ inputs.project_name }}-infra-prod
commit-message: ${{ inputs.issue_number }} Create Pingdom check and certificate for ${{ inputs.project_name }} (prod)
private-key: ${{ secrets.BOT_GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.BOT_GPG_PASSPHRASE }}
token: ${{ secrets.BOT_GITHUB_TOKEN }}
- name: Create issue for manual steps
run: |
gh issue create \
--title '${{ inputs.issue_number }} Complete infrastructure setup for ${{ inputs.project_name }}' \
--body '
- [ ] Request approval in [#ask-cloud-platform](https://mojdt.slack.com/archives/C57UPMZLY) for the following pull requests
> ${{ steps.dev-pr.outputs.pull-request-url }}
> ${{ steps.preprod-pr.outputs.pull-request-url }}
> ${{ steps.prod-pr.outputs.pull-request-url }}
- [ ] Merge the pull requests' \
--label bootstrap
env:
GITHUB_TOKEN: ${{ github.token }}