diff --git a/.github/workflows/docker_cleanup.yml b/.github/workflows/docker_cleanup.yml new file mode 100644 index 0000000..adade49 --- /dev/null +++ b/.github/workflows/docker_cleanup.yml @@ -0,0 +1,23 @@ +name: Cleanup Untagged Images + +on: + # every sunday at 00:00 + schedule: + - cron: "0 0 * * SUN" + # or manually + workflow_dispatch: + +jobs: + delete-untagged-images: + name: Delete Untagged Images + runs-on: ubuntu-latest + steps: + - uses: bots-house/ghcr-delete-image-action@v1.1.0 # nosemgrep: yaml.github-actions.security.third-party-action-not-pinned-to-commit-sha.third-party-action-not-pinned-to-commit-sha + with: + # NOTE: at now only orgs is supported + owner: airtai + name: test-chat-app + + token: ${{ secrets.GITHUB_TOKEN }} + # Keep latest N untagged images + untagged-keep-latest: 1 diff --git a/.github/workflows/pipeline.yml b/.github/workflows/pipeline.yml new file mode 100644 index 0000000..07f661d --- /dev/null +++ b/.github/workflows/pipeline.yml @@ -0,0 +1,81 @@ +name: Pipeline +on: [push, workflow_dispatch] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + PORT: ${{ vars.PORT }} + WASP_WEB_CLIENT_URL: ${{ vars.WASP_WEB_CLIENT_URL }} + DATABASE_URL: ${{ secrets.DATABASE_URL }} + JWT_SECRET: ${{ secrets.JWT_SECRET }} + BACKEND_DOMAIN: ${{ vars.BACKEND_DOMAIN }} + +jobs: + docker_build_push: + runs-on: ubuntu-22.04 + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - uses: actions/setup-node@v3 + with: + node-version: 18 + + - name: Install wasp + run: curl -sSL https://get.wasp-lang.dev/installer.sh | sh + + - name: Log in to the Container registry + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - run: docker pull ghcr.io/$GITHUB_REPOSITORY:$GITHUB_REF_NAME || docker pull ghcr.io/$GITHUB_REPOSITORY || true + - name: Build wasp + run: wasp build + - run: docker build --build-arg PORT=$PORT -t ghcr.io/$GITHUB_REPOSITORY:$GITHUB_REF_NAME ./.wasp/build/ + - name: Add tag latest if branch is main + if: github.ref_name == 'main' + run: docker tag ghcr.io/$GITHUB_REPOSITORY:$GITHUB_REF_NAME ghcr.io/$GITHUB_REPOSITORY:latest + - name: Push only if branch name is main + if: github.ref_name == 'main' + run: docker push ghcr.io/$GITHUB_REPOSITORY --all-tags + + deploy_backend: + runs-on: ubuntu-22.04 + defaults: + run: + shell: bash + needs: [docker_build_push] + if: github.ref_name == 'main' + container: + image: python:3.7-stretch + env: + GITHUB_USERNAME: ${{ github.actor }} + GITHUB_PASSWORD: ${{ secrets.GITHUB_TOKEN }} + PROD_SSH_KEY: ${{ secrets.PROD_SSH_KEY }} + steps: + - uses: actions/checkout@v3 + # This is to fix GIT not liking owner of the checkout dir - https://github.com/actions/runner/issues/2033#issuecomment-1204205989 + - run: chown -R $(id -u):$(id -g) $PWD + - run: echo "TAG=latest" >> $GITHUB_ENV + # - run: if [[ $GITHUB_REF_NAME == "main" ]]; then printenv PROD_CONFIG > "$(pwd)/.env" ; else printenv STAGING_CONFIG > "$(pwd)/.env" ; fi; + - run: sed 's/\"//g' .env >> $GITHUB_ENV + - run: echo "PATH=$PATH:/github/home/.local/bin" >> $GITHUB_ENV + - run: 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client git -y )' + - run: eval $(ssh-agent -s) + - run: mkdir -p ~/.ssh + - run: chmod 700 ~/.ssh + - run: ssh-keyscan "$DOMAIN" >> ~/.ssh/known_hosts + - run: chmod 644 ~/.ssh/known_hosts + - run: echo "$SSH_KEY" | base64 --decode > key.pem + - run: chmod 600 key.pem + + # - run: if [[ $GITHUB_REF_NAME == "main" ]]; then echo "DOMAIN=api.airt.ai" >> $GITHUB_ENV ; else echo "DOMAIN=api.staging.airt.ai" >> $GITHUB_ENV ; fi; + - run: ssh -o StrictHostKeyChecking=no -i key.pem azureuser@"$BACKEND_DOMAIN" "docker images" + - run: sh scripts/deploy_backend.sh + + - run: rm key.pem diff --git a/scripts/deploy_backend.sh b/scripts/deploy_backend.sh new file mode 100755 index 0000000..cbd9bb7 --- /dev/null +++ b/scripts/deploy_backend.sh @@ -0,0 +1,72 @@ +#!/bin/bash + + +if test -z "$TAG" +then + echo "ERROR: TAG variable must be defined, exiting" + exit -1 +fi + +if test -z "$GITHUB_USERNAME" +then + echo "ERROR: GITHUB_USERNAME variable must be defined, exiting" + exit -1 +fi + +if test -z "$GITHUB_PASSWORD" +then + echo "ERROR: GITHUB_PASSWORD variable must be defined, exiting" + exit -1 +fi + + +if [ ! -f key.pem ]; then + echo "ERROR: key.pem file not found" + exit -1 +fi + + +if test -z "$BACKEND_DOMAIN" +then + echo "ERROR: BACKEND_DOMAIN variable must be defined, exiting" + exit -1 +fi + +if test -z "$PORT" +then + echo "ERROR: PORT variable must be defined, exiting" + exit -1 +fi + +if test -z "$DATABASE_URL" +then + echo "ERROR: DATABASE_URL variable must be defined, exiting" + exit -1 +fi + +if test -z "$WASP_WEB_CLIENT_URL" +then + echo "ERROR: WASP_WEB_CLIENT_URL variable must be defined, exiting" + exit -1 +fi + +if test -z "$JWT_SECRET" +then + echo "ERROR: JWT_SECRET variable must be defined, exiting" + exit -1 +fi + +echo "INFO: stopping already running docker container" +ssh -o StrictHostKeyChecking=no -i key.pem azureuser@"$BACKEND_DOMAIN" "docker stop wasp-backend || echo 'No containers available to stop'" +ssh -o StrictHostKeyChecking=no -i key.pem azureuser@"$BACKEND_DOMAIN" "docker container prune -f || echo 'No stopped containers to delete'" + +echo "INFO: pulling docker image" +ssh -o StrictHostKeyChecking=no -i key.pem azureuser@"$BACKEND_DOMAIN" "echo $GITHUB_PASSWORD | docker login -u '$GITHUB_USERNAME' --password-stdin '$REGISTRY'" +ssh -o StrictHostKeyChecking=no -i key.pem azureuser@"$BACKEND_DOMAIN" "docker pull ghcr.io/$GITHUB_REPOSITORY:'$TAG'" +sleep 10 + +echo "Deleting old image" +ssh -o StrictHostKeyChecking=no -i key.pem azureuser@"$BACKEND_DOMAIN" "docker system prune -f || echo 'No images to delete'" + +echo "INFO: starting docker container" +ssh -o StrictHostKeyChecking=no -i key.pem azureuser@"$BACKEND_DOMAIN" "docker run --rm --name wasp-backend -e PORT -e DATABASE_URL -e WASP_WEB_CLIENT_URL -e JWT_SECRET ghcr.io/$GITHUB_REPOSITORY:$TAG -d"