-
-
Notifications
You must be signed in to change notification settings - Fork 29
143 lines (129 loc) · 7.93 KB
/
deploy-pr.yml
File metadata and controls
143 lines (129 loc) · 7.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
name: Deploy PR
on:
workflow_call:
permissions:
id-token: write
jobs:
deploy-pr:
name: Deploy PR
runs-on: ubuntu-latest
environment: staging
steps:
- name: Check if any label matches *.ghost.is
id: check-labels
env:
LABELS: ${{ toJson(github.event.pull_request.labels) }}
run: |
export LABEL_NAMES=$(echo "$LABELS" | jq -r '[.[] | select(.name | test("\\.ghost\\.is$")) | .name] | join(",")')
echo "Label names: $LABEL_NAMES"
if [ "$LABEL_NAMES" != "" ]; then
echo "Label matching *.ghost.is found."
echo "is_ephemeral_staging=true" >> "$GITHUB_OUTPUT"
else
echo "No label matching .*.ghost.is found."
echo "is_ephemeral_staging=false" >> "$GITHUB_OUTPUT"
fi
- name: Checkout activitypub-infra repo
if: ${{ steps.check-labels.outputs.is_ephemeral_staging == 'true' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
repository: TryGhost/activitypub-infra
ssh-key: ${{ secrets.ACTIVITYPUB_INFRA_DEPLOY_KEY }}
path: activitypub-infra
- name: Checkout terraform repo
if: ${{ steps.check-labels.outputs.is_ephemeral_staging == 'true' }}
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
repository: TryGhost/terraform
ssh-key: ${{ secrets.TERRAFORM_DEPLOY_KEY }}
path: terraform
- name: Get terraform version
if: ${{ steps.check-labels.outputs.is_ephemeral_staging == 'true' }}
id: terraform-version
run: |
echo "terraform_version=$(cat activitypub-infra/infrastructure/activitypub-staging-environments/.terraform-version)" >> "$GITHUB_OUTPUT"
- name: Setup terraform
if: ${{ steps.check-labels.outputs.is_ephemeral_staging == 'true' }}
uses: hashicorp/setup-terraform@5e8dbf3c6d9deaf4193ca7a8fb23f2ac83bb6c85 # v4
with:
terraform_version: ${{ steps.terraform-version.outputs.terraform_version }}
- name: Change github.com url in modules to local directories and add backend prefix
if: ${{ steps.check-labels.outputs.is_ephemeral_staging == 'true' }}
run: |
cd activitypub-infra/infrastructure/activitypub-staging-environments
sed -i 's/github\.com\/TryGhost/\.\.\/\.\.\/\.\./gI' main.tf
sed -i 's/\?ref=main//g' main.tf
sed -i 's/REPLACE_ME/${{ github.event.pull_request.number }}/g' terraform.tf
- name: Authenticate with GCP
if: ${{ steps.check-labels.outputs.is_ephemeral_staging == 'true' }}
uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3
with:
token_format: access_token
workload_identity_provider: projects/203831262197/locations/global/workloadIdentityPools/github-oidc-activitypub/providers/github-provider-activitypub
service_account: stg-activitypub-terraform-cicd@ghost-activitypub-stg.iam.gserviceaccount.com
- name: Terraform init
if: ${{ steps.check-labels.outputs.is_ephemeral_staging == 'true' }}
run: |
cd activitypub-infra/infrastructure/activitypub-staging-environments
terraform init
- name: Terraform apply
if: ${{ steps.check-labels.outputs.is_ephemeral_staging == 'true' }}
run: |
cd activitypub-infra/infrastructure/activitypub-staging-environments
export TF_VAR_github_pr_number=${{ github.event.pull_request.number }}
export TF_VAR_primary_region_name=netherlands
export TF_VAR_migrations_image=europe-docker.pkg.dev/ghost-activitypub/activitypub/migrations:pr-${{ github.event.pull_request.number }}
export TF_VAR_api_image=europe-docker.pkg.dev/ghost-activitypub/activitypub/activitypub:pr-${{ github.event.pull_request.number }}
export TF_VAR_queue_image=europe-docker.pkg.dev/ghost-activitypub/activitypub/activitypub:pr-${{ github.event.pull_request.number }}
terraform apply -auto-approve
- name: Deploy Migrations to Cloud Run
if: ${{ steps.check-labels.outputs.is_ephemeral_staging == 'true' }}
uses: google-github-actions/deploy-cloudrun@2028e2d7d30a78c6910e0632e48dd561b064884d # v3
with:
image: europe-docker.pkg.dev/ghost-activitypub/activitypub/migrations:pr-${{ github.event.pull_request.number }}
region: europe-west4
job: stg-pr-${{ github.event.pull_request.number }}-migrations
flags: --wait --execute-now
skip_default_labels: true
labels: |-
commit-sha=${{ github.sha }}
- name: Destroy Tests databases
if: ${{ steps.check-labels.outputs.is_ephemeral_staging == 'true' }}
env:
GCP_PROJECT: ghost-activitypub-stg
run: |
TEST_DATABASES=$(gcloud sql databases list --instance=stg-netherlands-activitypub --filter="name~pr_${{ github.event.pull_request.number }}_test*" --format="value(name)" --project ${GCP_PROJECT})
for TEST_DATABASE in ${TEST_DATABASES}; do
gcloud sql databases delete ${TEST_DATABASE} --instance=stg-netherlands-activitypub --quiet --project ${GCP_PROJECT}
done
- name: Add route to GCP Load Balancer
if: ${{ steps.check-labels.outputs.is_ephemeral_staging == 'true' }}
env:
LABELS: ${{ toJson(github.event.pull_request.labels) }}
GCP_PROJECT: ghost-activitypub-stg
run: |
set -euo pipefail
# Get current config
gcloud compute url-maps export stg-activitypub --global --project ${GCP_PROJECT} > config.yml
# Delete unnecessary fields
yq -i 'del(.fingerprint)' config.yml
yq -i 'del(.creationTimestamp)' config.yml
export DEFAULT_SERVICE="https://www.googleapis.com/compute/v1/projects/${GCP_PROJECT}/global/backendServices/stg-netherlands-activitypub-api"
export PR_SERVICE="https://www.googleapis.com/compute/v1/projects/${GCP_PROJECT}/global/backendServices/stg-pr-${{ github.event.pull_request.number }}-api"
# Add host rules and path matchers if they don't exist
yq -i '.hostRules = (.hostRules // [{"hosts": ["activitypub.ghostinfra.net"], "pathMatcher": "all-paths"}])' config.yml
yq -i '.pathMatchers = (.pathMatchers // [{"name": "all-paths", "defaultService": "'"$DEFAULT_SERVICE"'", "routeRules": []}])' config.yml
# Remove existing route rules for the PR service
yq -i '.pathMatchers[] |= (.routeRules |= map(select((.routeAction.weightedBackendServices // []) | length == 0 or .routeAction.weightedBackendServices[0].backendService != env(PR_SERVICE))))' config.yml
# Add new route rules for the PR service
export MIN_PRIORITY=$(yq '[.pathMatchers[] | select(.name == "all-paths") | .routeRules[]?.priority] | min // 0' config.yml)
export NEXT_PRIORITY=$((MIN_PRIORITY - 1))
LABELS_JSON=$(echo "$LABELS" | jq -c '[.[] | select(.name | test("\\.ghost\\.is$")) | .name]')
for LABEL in $(echo "$LABELS_JSON" | jq -r '.[]'); do
echo "Adding route for label: $LABEL"
yq -i '.pathMatchers[0].routeRules = [{"priority": '${NEXT_PRIORITY}', "matchRules": [{"prefixMatch": "/", "headerMatches": [{"headerName": "X-Forwarded-Host", "exactMatch": "'"${LABEL}"'"}]}], "routeAction": {"weightedBackendServices": [{"backendService": "'"${PR_SERVICE}"'", "weight": 100}]}, "headerAction": {"requestHeadersToAdd": [{"headerName": "X-ActivityPub-PR", "headerValue": "${{ github.event.pull_request.number }}"}, {"headerName": "X-ActivityPub-Commit", "headerValue": "${{ github.event.pull_request.head.sha }}"}]}}] + .pathMatchers[0].routeRules' config.yml
export NEXT_PRIORITY=$((NEXT_PRIORITY + 1))
done
echo "Updating url map with:"
cat config.yml
gcloud compute url-maps import stg-activitypub --source=config.yml --global --project ${GCP_PROJECT} --quiet