Skip to content

merged

merged #620

Workflow file for this run

name: "CI/CD"
env:
REGISTRY: ghcr.io
DEVELOPMENT: dev
STAGING: stag
PRODUCTION: prod
MAIN_BRANCH: master
DEV_DOMAIN: api.d.sayapp.company
STAGE_DOMAIN: api.s.sayapp.company
PROD_DOMAIN: api.sayapp.company
TARGET_LAYER: prod
TEST_TARGET_LAYER: development
DEV_STACK_NAME: say-dev-backend
STAGE_STACK_NAME: say-stag-backend
PROD_STACK_NAME: say-backend
DOCKER_COMPOSE_PATH: docker-compose.yml
DOCKER_STACK_PATH: docker-stack.yml
OVERRIDE_STACK_FILE: -f docker-compose-prod.yml
on:
push:
branches:
- "master"
- "develop"
- "release*"
jobs:
build_and_push:
name: Build and Push
runs-on: ubuntu-latest
outputs:
image_id: ${{ steps.image_id.outputs.image_id }}
test_image_id: ${{ steps.image_id.outputs.test_image_id }}
steps:
- name: Git Checkout
uses: actions/checkout@v2
- id: image_id
name: Generate Image ID
run: |
echo "::set-output name=image_id::${{ env.REGISTRY }}/$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]'):${{ github.sha }}"
echo "::set-output name=test_image_id::${{ env.REGISTRY }}/$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]'):${{ github.sha }}-test"
- name: Get Ref Name
run: echo "REF=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
- name: Set Development Envars
if: ${{ env.REF == 'develop' }}
run: |
echo "ENVIRONMENT=${{ env.DEVELOPMENT }}" >> $GITHUB_ENV
- name: Set Staging Envars
if: ${{ env.REF == 'master' }}
run: |
echo "ENVIRONMENT=stag" >> $GITHUB_ENV
- name: Set Production Envars
if: ${{ env.REF == 'release' }}
run: |
echo "ENVIRONMENT=prod" >> $GITHUB_ENV
- name: Login to GitHub Container Registry
run: echo ${{ secrets.GITHUB_TOKEN }} | docker login -u ${{ github.repository_owner }} --password-stdin ${{ env.REGISTRY }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
- name: Build Image
uses: docker/build-push-action@v2
with:
context: .
target: ${{ env.TARGET_LAYER }}
push: true
tags: ${{ steps.image_id.outputs.image_id }}
build-args: |
ENVIRONMENT=${ENVIRONMENT}
cache-from: type=local,src=/tmp/.buildx-cache
- name: Build Test Image
uses: docker/build-push-action@v2
with:
context: .
target: ${{ env.TEST_TARGET_LAYER }}
push: true
tags: ${{ steps.image_id.outputs.test_image_id }}
build-args: |
ENVIRONMENT=${ENVIRONMENT}
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,mode=max,dest=/tmp/.buildx-cache-new # mode=max: https://github.com/docker/buildx#--cache-tonametypetypekeyvalue
- # Temp fix
# https://github.com/docker/build-push-action/issues/252
# https://github.com/moby/buildkit/issues/1896
name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
run-tests:
name: Run Tests
timeout-minutes: 10
runs-on: ubuntu-latest
needs: build_and_push
env:
IMAGE_ID: ${{ needs.build_and_push.outputs.test_image_id }}
outputs:
image_id: ${{ needs.build_and_push.outputs.image_id }}
steps:
- name: Git Checkout
uses: actions/checkout@v2
- name: Get Ref Name
run: echo "REF=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV
- name: Build Compose File
run: >
CONTAINER_IMAGE=${IMAGE_ID}
docker compose
-f docker-compose.yml
-f docker-compose-dev.yml
config > compose.yml
- name: Pull Images
run: docker compose -f compose.yml pull
- name: Run Tests
run: >
docker compose -f compose.yml
run --rm backend pytest -vvv --cov=./ --cov-report=xml
# - name: Upload coverage to Codecov
# uses: codecov/codecov-action@v2
# with:
# directory: ./coverage/reports/
# env_vars: OS,PYTHON
# fail_ci_if_error: true
# files: ./coverage.xml
# flags: pytest
# name: say-codecov
# verbose: true
deploy_dev:
name: Deploy to Development Server
runs-on: ubuntu-latest
if: github.event.ref == 'refs/heads/develop'
needs:
- run-tests
env:
IMAGE_ID: ${{ needs.run-tests.outputs.image_id }}
environment:
name: Development
url: https://${{ env.DEV_DOMAIN }}
steps:
- name: Git Checkout
uses: actions/checkout@v2
- name: Set Envars
run: |
echo "STACK_FILE=docker-stack-${{ env.DEV_STACK_NAME }}-${{ github.sha }}.yml" >> $GITHUB_ENV
- name: Prepare Stack File
run: >
ENVIRONMENT=${{ env.DEVELOPMENT }} DOMAIN=${{ env.DEV_DOMAIN }} CONTAINER_IMAGE=${IMAGE_ID} STACK_NAME=${{ env.DEV_STACK_NAME }}
docker-compose -f ${{ env.DOCKER_COMPOSE_PATH }} -f ${{ env.DOCKER_STACK_PATH }} config
> ${{ env.STACK_FILE }}
- name: Move Stack File to Server
uses: appleboy/[email protected]
with:
host: ${{ secrets.DEV_SERVER_ADDR }}
username: ${{ secrets.DEV_SERVER_USER }}
key: ${{ secrets.DEV_SSH_PRIVATE_KEY }}
port: ${{ secrets.DEV_SERVER_PORT }}
source: ${{ env.STACK_FILE }}
target: "/tmp"
- name: Deploy Stack
uses: appleboy/[email protected]
with:
host: ${{ secrets.DEV_SERVER_ADDR }}
username: ${{ secrets.DEV_SERVER_USER }}
key: ${{ secrets.DEV_SSH_PRIVATE_KEY }}
port: ${{ secrets.DEV_SERVER_PORT }}
script: docker stack deploy --prune --resolve-image=changed --with-registry-auth -c /tmp/${{ env.STACK_FILE }} ${{ env.DEV_STACK_NAME }}
deploy_staging:
name: Deploy to Staging Server
runs-on: ubuntu-latest
if: github.event.ref == 'refs/heads/master'
needs:
- run-tests
env:
IMAGE_ID: ${{ needs.run-tests.outputs.image_id }}
environment:
name: Staging
url: https://${{ env.STAGE_DOMAIN }}
steps:
- name: Git Checkout
uses: actions/checkout@v2
- name: Set Envars
run: |
echo "STACK_FILE=docker-stack-${{ env.STAGE_STACK_NAME }}-${{ github.sha }}.yml" >> $GITHUB_ENV
- name: Prepare Stack File
run: >
ENVIRONMENT=${{ env.STAGING }} DOMAIN=${{ env.STAGE_DOMAIN }} CONTAINER_IMAGE=${IMAGE_ID} STACK_NAME=${{ env.STAGE_STACK_NAME }}
docker-compose -f ${{ env.DOCKER_COMPOSE_PATH }} -f ${{ env.DOCKER_STACK_PATH }} config
> ${{ env.STACK_FILE }}
- name: Move Stack File to Server
uses: appleboy/[email protected]
with:
host: ${{ secrets.STAGE_SERVER_ADDR }}
username: ${{ secrets.STAGE_SERVER_USER }}
key: ${{ secrets.STAGE_SSH_PRIVATE_KEY }}
port: ${{ secrets.STAGE_SERVER_PORT }}
source: ${{ env.STACK_FILE }}
target: "/tmp"
- name: Deploy Stack
uses: appleboy/[email protected]
with:
host: ${{ secrets.STAGE_SERVER_ADDR }}
username: ${{ secrets.STAGE_SERVER_USER }}
key: ${{ secrets.STAGE_SSH_PRIVATE_KEY }}
port: ${{ secrets.STAGE_SERVER_PORT }}
script: docker stack deploy --prune --resolve-image=changed --with-registry-auth -c /tmp/${{ env.STACK_FILE }} ${{ env.STAGE_STACK_NAME }}
deploy_production:
name: Deploy to Production Server
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/heads/release')
needs:
- run-tests
env:
IMAGE_ID: ${{ needs.run-tests.outputs.image_id }}
environment:
name: Production
url: https://${{ env.PROD_DOMAIN }}
steps:
- name: Git Checkout
uses: actions/checkout@v2
- name: Set Envars
run: |
echo "STACK_FILE=docker-stack-${{ env.PROD_STACK_NAME }}-${{ github.sha }}.yml" >> $GITHUB_ENV
# config needs to have the published port as an integer + creats anextra line at the rendered file so we fix all with "sed" command
- name: Prepare Stack File
run: >
ENVIRONMENT=${{ env.PRODUCTION }} DOMAIN=${{ env.PROD_DOMAIN }} CONTAINER_IMAGE=${IMAGE_ID} STACK_NAME=${{ env.PROD_STACK_NAME }}
docker compose -f ${{ env.DOCKER_COMPOSE_PATH }} -f ${{ env.DOCKER_STACK_PATH }} ${{ env.OVERRIDE_STACK_FILE }}
config | sed "s/published:.*/published: 35432/g" | sed 's/^name:.*/version: "3.6"/' > ${{ env.STACK_FILE }}
- name: Move Stack File to Server
uses: appleboy/[email protected]
with:
host: ${{ secrets.PROD_SERVER_ADDR }}
username: ${{ secrets.PROD_SERVER_USER }}
key: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
port: ${{ secrets.PROD_SERVER_PORT }}
source: ${{ env.STACK_FILE }}
target: "/tmp"
- name: Deploy Stack
uses: appleboy/[email protected]
with:
host: ${{ secrets.PROD_SERVER_ADDR }}
username: ${{ secrets.PROD_SERVER_USER }}
key: ${{ secrets.PROD_SSH_PRIVATE_KEY }}
port: ${{ secrets.PROD_SERVER_PORT }}
script: docker stack deploy --prune --resolve-image=changed --with-registry-auth -c /tmp/${{ env.STACK_FILE }} ${{ env.PROD_STACK_NAME }}