Skip to content

[infrastructure] add explicit autoscaling logic to Hasura service #7208

[infrastructure] add explicit autoscaling logic to Hasura service

[infrastructure] add explicit autoscaling logic to Hasura service #7208

Workflow file for this run

name: Pull Request
on:
pull_request:
types:
- opened
- synchronize
branches-ignore:
- production
env:
DOMAIN: planx.pizza
FULL_DOMAIN: ${{ github.event.number }}.planx.pizza
PULLREQUEST_ID: ${{ github.event.number }}
EDITOR_DIRECTORY: editor.planx.uk
permissions:
pull-requests: write
packages: read
jobs:
changes:
name: Check file changes
runs-on: ubuntu-22.04
permissions:
pull-requests: read
outputs:
api: ${{ steps.filter.outputs.api }}
e2e: ${{ steps.filter.outputs.e2e }}
editor: ${{ steps.filter.outputs.editor }}
hasura: ${{ steps.filter.outputs.hasura }}
infrastructure: ${{ steps.filter.outputs.infrastructure }}
sharedb: ${{ steps.filter.outputs.sharedb }}
commit: ${{ steps.commit.outputs.commit }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Get commit message
id: commit
run: |
echo "commit=$(git show -s --format=%s)" >> $GITHUB_OUTPUT
- uses: dorny/paths-filter@v2
id: filter
with:
filters: |
api:
- 'api.planx.uk/**'
e2e:
- 'e2e/**'
hasura:
- 'hasura.planx.uk/**'
infrastructure:
- 'infrastructure/**'
editor:
- 'editor.planx.uk/**'
sharedb:
- 'sharedb.planx.uk/**'
integration_tests:
name: Run Integration tests
runs-on: ubuntu-22.04
needs: [changes]
if: ${{ needs.changes.outputs.api == 'true' || needs.changes.outputs.e2e == 'true' || needs.changes.outputs.editor == 'true' || needs.changes.outputs.sharedb == 'true' || needs.changes.outputs.hasura == 'true' }}
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.PIZZA_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.PIZZA_AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-2
- name: Copy .env files from Staging S3 to the current working directory with AWS CLI
run: ./scripts/pull-secrets.sh
- name: Check if .env files exist
id: check_files
uses: andstor/file-existence-action@v2
with:
files: ".env, .env.staging, api.planx.uk/.env.test, hasura.planx.uk/.env.test"
fail: true
- name: Setup .gitconfig
run: mv .gitconfig ~/.gitconfig
- uses: pnpm/action-setup@v4.0.0
with:
version: ${{ vars.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ vars.NODE_VERSION }}
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
- run: pnpm install --frozen-lockfile
working-directory: ${{ env.EDITOR_DIRECTORY }}
- name: Start test containers
run: ./scripts/start-containers-for-tests.sh
- name: Postgres Tests
run: ./hasura.planx.uk/run-postgres-tests.sh
- run: pnpm i -g hasura-cli@2.36.1
- name: Hasura Tests
run: pnpm install --frozen-lockfile && pnpm test
working-directory: hasura.planx.uk/tests
api_tests:
name: Run API Tests
runs-on: ubuntu-22.04
timeout-minutes: 10
needs: [changes]
if: ${{ needs.changes.outputs.api == 'true' }}
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.PIZZA_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.PIZZA_AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-2
- name: Copy .env files from Staging S3 to the current working directory with AWS CLI
run: ./scripts/pull-secrets.sh
- name: Check if .env files exist
id: check_files
uses: andstor/file-existence-action@v2
with:
files: ".env, .env.staging, api.planx.uk/.env.test, hasura.planx.uk/.env.test"
fail: true
- name: Setup .gitconfig
run: mv .gitconfig ~/.gitconfig
- uses: pnpm/action-setup@v4.0.0
with:
version: ${{ vars.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ vars.NODE_VERSION }}
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
- name: Install dependencies
run: pnpm install --frozen-lockfile
working-directory: api.planx.uk
- name: Run API Tests
run: pnpm install --frozen-lockfile && pnpm check && pnpm test
working-directory: api.planx.uk
test_react:
name: Run React Tests
runs-on: ubuntu-22.04
needs: [changes]
if: ${{ needs.changes.outputs.editor == 'true' }}
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.PIZZA_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.PIZZA_AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-2
- name: Copy .env files from Staging S3 to the current working directory with AWS CLI
run: ./scripts/pull-secrets.sh
- name: Check if .env files exist
id: check_files
uses: andstor/file-existence-action@v2
with:
files: ".env, .env.staging, api.planx.uk/.env.test, hasura.planx.uk/.env.test"
fail: true
- uses: pnpm/action-setup@v4.0.0
with:
version: ${{ vars.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ vars.NODE_VERSION }}
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
- name: Setup .gitconfig
run: mv .gitconfig ~/.gitconfig
- run: pnpm install --frozen-lockfile
working-directory: ${{ env.EDITOR_DIRECTORY }}
- run: pnpm build
working-directory: ${{ env.EDITOR_DIRECTORY }}
- run: pnpm test:silent
working-directory: ${{ env.EDITOR_DIRECTORY }}
build_react_app:
name: Build React App
runs-on: ubuntu-22.04
needs: [changes]
if: "${{ !contains(needs.changes.outputs.commit, '[skip pizza]') }}"
steps:
- uses: actions/checkout@v4
- name: Cache build assets
id: cache-react-build-assets
uses: actions/cache@v4
with:
path: ./${{ env.EDITOR_DIRECTORY }}/build
key: ${{ runner.os }}-${{ hashFiles('editor.planx.uk/**') }}
- uses: pnpm/action-setup@v4.0.0
if: steps.cache-react-build-assets.outputs.cache-hit != 'true'
with:
version: ${{ vars.PNPM_VERSION }}
- uses: actions/setup-node@v4
if: steps.cache-react-build-assets.outputs.cache-hit != 'true'
with:
node-version: ${{ vars.NODE_VERSION }}
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
- name: Setup .gitconfig
run: mv .gitconfig ~/.gitconfig
- run: pnpm install --frozen-lockfile
if: steps.cache-react-build-assets.outputs.cache-hit != 'true'
working-directory: ${{ env.EDITOR_DIRECTORY }}
- run: pnpm build
if: steps.cache-react-build-assets.outputs.cache-hit != 'true'
env:
VITE_APP_AIRBRAKE_PROJECT_ID: ${{ secrets.AIRBRAKE_PROJECT_ID }}
VITE_APP_AIRBRAKE_PROJECT_KEY: ${{ secrets.AIRBRAKE_PROJECT_KEY }}
VITE_APP_API_URL: https://api.${{ env.FULL_DOMAIN }}
VITE_APP_HASURA_URL: https://hasura.${{ env.FULL_DOMAIN }}/v1/graphql
VITE_APP_HASURA_WEBSOCKET: wss://hasura.${{ env.FULL_DOMAIN }}/v1/graphql
VITE_APP_MAPBOX_ACCESS_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN }}
VITE_APP_SHAREDB_URL: wss://sharedb.${{ env.FULL_DOMAIN }}
# needed because there's no API to change google/microsoft's allowed redirect URIs
VITE_APP_GOOGLE_OAUTH_OVERRIDE: https://api.editor.planx.dev
VITE_APP_MICROSOFT_OAUTH_OVERRIDE: https://api.editor.planx.dev
VITE_APP_ENV: pizza
working-directory: ${{ env.EDITOR_DIRECTORY }}
- run: pnpm build-storybook
if: steps.cache-react-build-assets.outputs.cache-hit != 'true'
working-directory: ${{ env.EDITOR_DIRECTORY }}
env:
# same env as above, if it's job.env it can't access existing env.[variable]
VITE_APP_AIRBRAKE_PROJECT_ID: ${{ secrets.AIRBRAKE_PROJECT_ID }}
VITE_APP_AIRBRAKE_PROJECT_KEY: ${{ secrets.AIRBRAKE_PROJECT_KEY }}
VITE_APP_API_URL: https://api.${{ env.FULL_DOMAIN }}
VITE_APP_HASURA_URL: https://hasura.${{ env.FULL_DOMAIN }}/v1/graphql
VITE_APP_HASURA_WEBSOCKET: wss://hasura.${{ env.FULL_DOMAIN }}/v1/graphql
VITE_APP_MAPBOX_ACCESS_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN }}
VITE_APP_SHAREDB_URL: wss://sharedb.${{ env.FULL_DOMAIN }}
VITE_APP_GOOGLE_OAUTH_OVERRIDE: https://api.editor.planx.dev
VITE_APP_MICROSOFT_OAUTH_OVERRIDE: https://api.editor.planx.dev
VITE_APP_ENV: pizza
pulumi_preview:
name: Run Pulumi Preview
runs-on: ubuntu-22.04
needs: [changes, build_react_app]
if: ${{ needs.changes.outputs.infrastructure == 'true' }}
steps:
- uses: actions/checkout@v4
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.STAGING_AWS_ACCESS_KEY_ID }}
aws-region: eu-west-2
aws-secret-access-key: ${{ secrets.STAGING_AWS_SECRET_ACCESS_KEY }}
- uses: pnpm/action-setup@v4.0.0
with:
version: ${{ vars.PNPM_VERSION }}
- uses: actions/setup-node@v4
with:
node-version: ${{ vars.NODE_VERSION }}
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
- run: pnpm install --frozen-lockfile
working-directory: infrastructure/application
- name: Download React build assets
id: cache-react-build-assets
uses: actions/cache@v4
with:
path: ./${{ env.EDITOR_DIRECTORY }}/build
key: ${{ runner.os }}-${{ hashFiles('editor.planx.uk/**', '!editor.planx/build/**') }}
- uses: pulumi/actions@v5
with:
command: preview
stack-name: staging
work-dir: infrastructure/application
edit-pr-comment: true
env:
PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }}
hasura-change-summary:
name: Generate Hasura Change Summary
runs-on: ubuntu-22.04
needs: [changes]
if: ${{ needs.changes.outputs.hasura == 'true' }}
steps:
- uses: actions/checkout@v4
- uses: Fieldguide/action-hasura-change-summary@v2
id: hasura-change
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
hasura_endpoint: https://hasura.${{ env.FULL_DOMAIN }}
project_dir: ./hasura.planx.uk
- uses: marocchino/sticky-pull-request-comment@v2
if: ${{steps.hasura-change.outputs.change_html != ''}}
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
header: hasura-change-summary
message: ${{ steps.hasura-change.outputs.change_html }}
- uses: marocchino/sticky-pull-request-comment@v2
if: ${{ steps.hasura-change.outputs.change_html == '' }}
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
header: hasura-change-summary
delete: true
create_or_update_vultr_instance:
name: Upsert Vultr Instance
needs: [changes, build_react_app]
runs-on: ubuntu-22.04
if: "${{ success() && !contains(needs.changes.outputs.commit, '[skip pizza]') }}"
steps:
- name: Create Pizza (if it doesn't exist)
id: create
uses: theopensystemslab/vultr-action@v2.0
with:
action: create
api_key: ${{ secrets.VULTR_API_KEY }}
domain: ${{ env.DOMAIN }}
os_type: alpine
plan: vc2-1c-1gb
pull_request_id: ${{ env.PULLREQUEST_ID }}
region: lhr
tag: pullrequest
# CREATE STEPS
- if: steps.create.outputs.ip_address != null
name: Create commands
uses: appleboy/ssh-action@master
with:
host: ${{ env.FULL_DOMAIN }}
username: root
password: ${{ steps.create.outputs.default_password }}
command_timeout: 20m
script: |
apk update
apk add docker
addgroup root docker
rc-update add docker default
service docker start
apk add docker-cli-compose
apk add git
git clone "${{ secrets.AUTHENTICATED_REPO_URL }}"
cd planx-new
git fetch origin "pull/${{ env.PULLREQUEST_ID }}/head" && git checkout FETCH_HEAD
apk add aws-cli
export AWS_ACCESS_KEY_ID=${{ secrets.PIZZA_AWS_ACCESS_KEY_ID }}
export AWS_SECRET_ACCESS_KEY=${{ secrets.PIZZA_AWS_SECRET_ACCESS_KEY }}
export AWS_REGION=eu-west-2
CI=true ./scripts/pull-secrets.sh
echo -e "\nROOT_DOMAIN=${{ env.FULL_DOMAIN }}\n" > .env.temp
cat .env .env.temp .env.staging > .env.pizza
SSH_PASSWORD=${{ secrets.SSH_PASSWORD }} ./scripts/pullrequest/create.sh
# UPDATE STEPS
- if: steps.create.outputs.ip_address == null
name: Update commands
uses: appleboy/ssh-action@master
with:
host: ${{ env.FULL_DOMAIN }}
username: root
password: ${{ secrets.SSH_PASSWORD }}
command_timeout: 10m
# TODO: some of below script might be superfluous for server update (rather than create)
script: |
apk update
apk add docker
addgroup root docker
rc-update add docker default
service docker start
apk add docker-cli-compose
git clone "${{ secrets.AUTHENTICATED_REPO_URL }}"
cd planx-new
git add . && git stash
git fetch origin "pull/${{ env.PULLREQUEST_ID }}/head" && git checkout FETCH_HEAD
apk add aws-cli
export AWS_ACCESS_KEY_ID=${{ secrets.PIZZA_AWS_ACCESS_KEY_ID }}
export AWS_SECRET_ACCESS_KEY=${{ secrets.PIZZA_AWS_SECRET_ACCESS_KEY }}
export AWS_REGION=eu-west-2
CI=true ./scripts/pull-secrets.sh
echo -e "\nROOT_DOMAIN=${{ env.FULL_DOMAIN }}\n" > .env.temp
cat .env .env.temp .env.staging > .env.pizza
./scripts/pullrequest/update.sh
# CREATE & UPDATE STEPS
- uses: actions/checkout@v4
- name: Download React build assets
id: cache-react-build-assets
uses: actions/cache@v4
with:
path: ./${{ env.EDITOR_DIRECTORY }}/build
key: ${{ runner.os }}-${{ hashFiles('editor.planx.uk/**', '!editor.planx/build/**') }}
- name: upload built editor
uses: appleboy/scp-action@master
with:
host: ${{ env.FULL_DOMAIN }}
username: root
password: ${{ secrets.SSH_PASSWORD }}
source: "./${{ env.EDITOR_DIRECTORY }}/build"
target: "planx-new/"
overwrite: true
- uses: marocchino/sticky-pull-request-comment@v2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
header: vultr
message: |
## Pizza
Deployed ${{ github.sha }} to https://${{ env.FULL_DOMAIN }}.
Useful links:
- [Editor](https://${{ env.FULL_DOMAIN }})
- [Storybook](https://storybook.${{ env.FULL_DOMAIN }})
- [Hasura](https://hasura.${{ env.FULL_DOMAIN }})
- [API](https://api.${{ env.FULL_DOMAIN }}/docs)
- [ShareDB](https://sharedb.${{ env.FULL_DOMAIN }})
healthcheck:
name: Run Healthcheck on Pizza Services
needs: [create_or_update_vultr_instance]
runs-on: ubuntu-22.04
steps:
- name: Wait for Vultr to warm up
run: bash -c "sleep 30s"
- name: API healthcheck
run: |
timeout 150s bash -c "until curl --fail https://api.${{ env.FULL_DOMAIN }}; do sleep 1; done"
- name: Hasura healthcheck
run: |
timeout 150s bash -c "until curl --fail https://hasura.${{ env.FULL_DOMAIN }}/healthz; do sleep 1; done"
- name: Editor healthcheck
run: |
timeout 150s bash -c "until curl --fail https://${{ env.FULL_DOMAIN }}; do sleep 1; done"
end_to_end_tests:
name: E2E tests
runs-on: ubuntu-22.04
needs: [changes]
if: ${{ needs.changes.outputs.api == 'true' || needs.changes.outputs.e2e == 'true' || needs.changes.outputs.editor == 'true' || needs.changes.outputs.sharedb == 'true' || needs.changes.outputs.hasura == 'true' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.PIZZA_AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.PIZZA_AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-2
- name: Copy .env files from Staging S3 to the current working directory with AWS CLI
run: ./scripts/pull-secrets.sh
- name: Setup PNPM
uses: pnpm/action-setup@v4.0.0
with:
version: ${{ vars.PNPM_VERSION }}
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ vars.NODE_VERSION }}
cache: "pnpm"
cache-dependency-path: "**/pnpm-lock.yaml"
- name: Setup .gitconfig
run: mv .gitconfig ~/.gitconfig
- name: PNPM Install
run: pnpm install --frozen-lockfile
working-directory: e2e
- name: Code checks
run: pnpm check
working-directory: e2e
- name: Install Playwright Dependencies
run: pnpm playwright install --with-deps
working-directory: e2e/tests/ui-driven
- name: Start test containers
run: ./scripts/start-containers-for-tests.sh
- name: End-to-end Tests
run: pnpm test
working-directory: e2e
- name: Archive Playwright Test Results
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: e2e/tests/ui-driven/test-results/
retention-days: 3