Skip to content

v1.4.9

v1.4.9 #43

Workflow file for this run

name: Deploy to Production
on:
release:
types: [published]
env:
REGISTRY: "236848092535.dkr.ecr.eu-west-2.amazonaws.com"
jobs:
build:
name: Build frontend
runs-on: ubuntu-20.04
environment: Production
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup NodeJS
uses: actions/setup-node@v2
with:
node-version: '18'
- name: Install pnpm
uses: pnpm/action-setup@v2
id: pnpm-install
with:
version: 7
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install frontend dependencies
run: |
cd ./uclapi-frontend && pnpm install --frozen-lockfile
- name: Build frontend
env:
AWS_S3_BUCKET_NAME: uclapi-static
AWS_S3_BUCKET_PATH: static/
AWS_S3_STATICS: True
SENTRY_DSN_REACT: ${{ secrets.SENTRY_DSN_REACT }}
SENTRY_DSN_ENV: production
run: |
cd ./uclapi-frontend && pnpm build
test-backend:
name: Run backend tests
runs-on: ubuntu-20.04
env:
DB_UCLAPI_HOST: localhost
DB_UCLAPI_PASSWORD: supersecure
DB_UCLAPI_USERNAME: uclapi
FORBIDDEN_CALLBACK_URLS: uclapi.com;staging.ninja
REDIS_UCLAPI_HOST: localhost
UCLAPI_PRODUCTION: False
UCLAPI_RUNNING_ON_AWS_ELB: False
WHITELISTED_CALLBACK_URLS: https://live-roombookings.uclapi.com/webhook/;https://hackathon.uclapi.com/callback
UCLAPI_DOMAIN: uclapi.com
AZURE_AD_ROOT: https://login.microsoftonline.com/directory_tenant_id
AZURE_AD_CLIENT_ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
AZURE_AD_CLIENT_SECRET: aaa
AZURE_GRAPH_ROOT: https://graph.microsoft.com/v1.0/
services:
Redis:
image: redis
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
Postgres:
image: postgres
env:
POSTGRES_USER: uclapi
POSTGRES_PASSWORD: supersecure
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.8.10'
- name: Install Oracle Instant Client
run: ./.github/workflows/scripts/setup-oracle.sh
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip && \
cd ./backend/uclapi && \
pip install codecov && \
pip install -r requirements.txt
- name: Run migrations
run: |
cp ./backend/uclapi/webpack-stats.sample.json ./backend/uclapi/static/webpack-stats.json && \
cd ./backend/uclapi && \
python ./manage.py migrate --settings=uclapi.settings_mocked
- name: Run tests
run: |
cd ./backend/uclapi && \
coverage run --source='.' --omit='*migrations*' manage.py test --settings=uclapi.settings_mocked
test-frontend:
name: Run frontend tests
runs-on: ubuntu-20.04
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup NodeJS
uses: actions/setup-node@v2
with:
node-version: '18'
- name: Install pnpm
uses: pnpm/action-setup@v2
id: pnpm-install
with:
version: 7
run_install: false
- name: Get pnpm store directory
id: pnpm-cache
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
name: Setup pnpm cache
with:
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install frontend dependencies
run: |
cd ./uclapi-frontend/ && pnpm install --frozen-lockfile
- name: Run frontend tests
run: |
cd ./uclapi-frontend && pnpm test
collect-statics:
name: Collect statics
needs:
- build
- test-backend
- test-frontend
runs-on: ubuntu-20.04
environment: Production
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
with:
python-version: '3.8.10'
- name: Cache Python
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Install Python dependencies
run: |
python -m pip install --upgrade pip && \
cd ./backend/uclapi && \
pip install -r requirements.txt
- name: Collect statics to S3
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_S3_BUCKET_NAME: uclapi-static
AWS_S3_BUCKET_PATH: static/
AWS_S3_REGION: eu-west-2
AWS_S3_STATICS_CREDENTIALS_ENABLED: True
AWS_S3_STATICS: True
UCLAPI_PRODUCTION: True
UCLAPI_RUNNING_ON_AWS_ELB: False
run: |
cd ./backend/uclapi && \
./manage.py collectstatic --noinput
build-containers:
name: Build containers
needs:
- test-backend
- test-frontend
runs-on: ubuntu-20.04
environment: Production
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: eu-west-2
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Get version
id: version
uses: juliangruber/read-file-action@v1
with:
path: ./version
- name: Extract non-public secrets
env:
FILES: ${{ secrets.FILES }}
UCLAPI_VERSION: "${{ steps.version.outputs.content }}"
run: |
cd ./docker/deployment && \
mkdir -p non-public/production && \
cd non-public/production && \
echo "$FILES" | base64 --decode > compressed.zip && \
unzip -qq compressed.zip && \
rm compressed.zip && \
echo "UCLAPI_VERSION=$UCLAPI_VERSION" >> uclapi/uclapi.env
echo "UCLAPI_VERSION=$UCLAPI_VERSION" >> uclapi/uclapi-web.env
- name: Build containers
env:
CRON_CPU_COUNT: 1
CRON_MEMORY_KB: 2048000
ENVIRONMENT: production
UCLAPI_VERSION: "${{ steps.version.outputs.content }}"
run: |
cd docker/deployment && \
sed -i "s/:version/:${{ steps.version.outputs.content }}/g" docker-compose-production.yml && \
docker compose -f docker-compose-production.yml build
- name: Push containers
env:
CRON_CPU_COUNT: 1
CRON_MEMORY_KB: 2048000
run: |
cd docker/deployment && \
docker compose -f docker-compose-production.yml push
- name: Create artifact
run: echo ${{ steps.version.outputs.content }} > container-id.txt
- name: Upload container id
uses: actions/upload-artifact@v2
with:
name: container-id.txt
path: container-id.txt
deploy:
name: Deploy
needs:
- collect-statics
- build-containers
runs-on: ubuntu-20.04
environment: Production
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Get version
id: version
uses: juliangruber/read-file-action@v1
with:
path: ./version
- name: Extract non-public secrets
env:
FILES: ${{ secrets.FILES }}
run: |
echo "$FILES" | base64 --decode > compressed.zip && \
unzip -qq compressed.zip && \
rm compressed.zip
- name: Copy docker compose configuration
uses: appleboy/scp-action@v0.1.4
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
key_path: key.pem
source: "docker/deployment/docker-compose.yml,docker/deployment/docker-compose-production.yml"
target: "~"
strip_components: 2
- name: Docker compose up
uses: appleboy/ssh-action@v0.1.10
env:
ENVIRONMENT: production
VERSION: ${{ steps.version.outputs.content }}
CRON_CPU_COUNT: 1
CRON_MEMORY_KB: 2048000
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USERNAME }}
key_path: key.pem
envs: ENVIRONMENT,REGISTRY,VERSION,CRON_CPU_COUNT,CRON_MEMORY_KB
script_stop: true
script: |
aws ecr get-login-password --region eu-west-2 | docker login --username AWS --password-stdin $REGISTRY
if ((`df -h /dev/root | awk '(NR > 1) {print substr($5, 1, length($5)-1)}'` < 5)); then docker system prune -f; fi
export CRON_CPU_COUNT=$CRON_CPU_COUNT
export CRON_MEMORY_KB=$CRON_MEMORY_KB
envsubst < docker-compose-production.yml > docker-compose-tmp.yml
sed -i "s/:version/:$VERSION/g" docker-compose-tmp.yml
cat docker-compose-tmp.yml | yq e '(.services[] | select(.depends_on | tag == "!!map")).depends_on |= (. | keys)' - > docker-compose-tmp-2.yml
sed -i -E "s/cpus: ([0-9\\.]+)/cpus: '\\1'/" docker-compose-tmp-2.yml
rm docker-compose-tmp.yml docker-compose-production.yml
mv -f docker-compose-tmp-2.yml docker-compose.yml
docker stack deploy -c docker-compose.yml --with-registry-auth uclapi
- name: Create Sentry release
uses: getsentry/action-release@v1.1.6
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
with:
environment: production
version: "${{ steps.version.outputs.content }}"
- name: Repository Dispatch (JS SDK)
uses: peter-evans/repository-dispatch@v2
with:
token: ${{ secrets.JS_SDK_REPO_DEPLOY_PRIVATE_KEY }}
event-type: new-release
repository: uclapi/uclapi-js-sdk
client-payload: '{"version": "${{ steps.version.outputs.content }}", "sha": "${{ github.sha }}"}'