# Build web app and deploy it
name: web

on:
  push:
    branches: [ "master", "release" ]

  repository_dispatch:
    types: web

  workflow_dispatch:

  workflow_call:

concurrency:
  group: web-${{ github.workflow }}-${{ github.ref_type }}-${{ github.event.pull_request.number || github.ref || github.run_id }}
  cancel-in-progress: true

defaults:
  run:
    shell: bash -euxo pipefail {0}

env:
  GITHUB_REPOSITORY_URL: ${{ github.server_url }}/${{ github.repository }}
  AWS_MAX_ATTEMPTS: 10
  PROD_ENABLE_TYPE_CHECKS: 0
  VERBOSE: 1

jobs:
  build-web:
    name: "build-web"
    runs-on: ubuntu-22.04
    environment:
      name: ${{ github.ref }}

    steps:
      - name: "[init] Check disk space"
        run: |
          echo ""

          df -Th | awk 'NR == 1; NR > 1 {print $0 | "sort -n"}'

          echo ""

          lsblk -o MOUNTPOINT,FSTYPE,FSSIZE,FSAVAIL,FSUSE%,TYPE,NAME,ROTA,SIZE,MODEL,UUID

      - name: "[init] Checkout code"
        uses: actions/checkout@v4
        with:
          fetch-depth: 1
          submodules: true

      - name: "[build] Setup environment (release)"
        if: endsWith(github.ref, '/release')
        run: |
          echo "ENV_NAME=release" >> $GITHUB_ENV
          echo "FULL_DOMAIN=https://covariants.org" >> $GITHUB_ENV
          echo "PLAUSIBLE_IO_DOMAIN=covariants.org" >> $GITHUB_ENV

      - name: "[build] Setup environment (master)"
        if: endsWith(github.ref, '/master')
        run: |
          echo "ENV_NAME=master" >> $GITHUB_ENV
          echo "FULL_DOMAIN=https://covariants.org" >> $GITHUB_ENV
          echo "PLAUSIBLE_IO_DOMAIN=master.covariants.org" >> $GITHUB_ENV

      - name: "[build] Setup Node.js"
        uses: actions/setup-node@v4
        with:
          node-version-file: ".nvmrc"
          cache: "yarn"
          cache-dependency-path: "web/yarn.lock"

      - name: "[build] Setup cache for web app"
        uses: actions/cache@v4
        with:
          path: |
            web/.cache
            web/.build/production/tmp/cache
          key: cache-v1-web-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            cache-v1-web-${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
            cache-v1-web-${{ runner.os }}-

      - name: "[build] Prepare .env file"
        run: |
          cd web/
          cp .env.example .env
          sed -i -e "s|FULL_DOMAIN=autodetect|FULL_DOMAIN=${FULL_DOMAIN}|g" .env

      - name: "[build] Install Node.js packages"
        run: |
          cd web
          yarn install --frozen-lockfile

      - name: "[build] Build web application"
        run: |
          cd web
          yarn prod:build

      - name: "[deployment] Setup environment (release)"
        if: endsWith(github.ref, '/release')
        run: |
          echo "AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }}" >> $GITHUB_ENV
          echo "AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}" >> $GITHUB_ENV
          echo "AWS_CLOUDFRONT_DISTRIBUTION_ID=${{ secrets.AWS_CLOUDFRONT_DISTRIBUTION_ID }}" >> $GITHUB_ENV
          echo "AWS_DEFAULT_REGION=${{ secrets.AWS_DEFAULT_REGION }}" >> $GITHUB_ENV
          echo "AWS_S3_BUCKET=${{ secrets.AWS_S3_BUCKET }}" >> $GITHUB_ENV

      - name: "[deployment] Setup environment (master)"
        if: endsWith(github.ref, '/master')
        run: |
          echo "AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }}" >> $GITHUB_ENV
          echo "AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}" >> $GITHUB_ENV
          echo "AWS_CLOUDFRONT_DISTRIBUTION_ID=${{ secrets.AWS_CLOUDFRONT_DISTRIBUTION_ID }}" >> $GITHUB_ENV
          echo "AWS_DEFAULT_REGION=${{ secrets.AWS_DEFAULT_REGION }}" >> $GITHUB_ENV
          echo "AWS_S3_BUCKET=${{ secrets.AWS_S3_BUCKET }}" >> $GITHUB_ENV

      - name: "[deployment] Install dependencies"
        run: |
          pushd /tmp >/dev/null
            curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
            unzip -oqq awscliv2.zip
            sudo ./aws/install --update
          popd >/dev/null
          aws --version

      - name: "[deployment] Clear AWS S3 bucket: html files, web root, app bundle"
        run: |
          aws s3 rm s3://${AWS_S3_BUCKET} --recursive --exclude "proteins/*" --exclude "acknowledgements/*"

      - name: "[deployment] Copy to AWS S3: app bundle"
        run: |
          cd web/.build/production/web
          aws s3 cp --recursive --cache-control "max-age=2592000, public" "_next/" "s3://${AWS_S3_BUCKET}/_next/"

      - name: "[deployment] Copy to AWS S3: web root"
        run: |
          cd web/.build/production/web
          aws s3 cp --recursive \
            --exclude "_next/*" \
            --exclude "*.html" \
            --exclude "acknowledgements/*" \
            --exclude "proteins/*" \
          "./" "s3://${AWS_S3_BUCKET}/"

      - name: "[deployment] Copy to AWS S3: html files"
        run: |
          cd web/.build/production/web
          find * -type f -name "*.html" -print0 | xargs -0 -P4 -n1 -I '{}' -- bash -c '\
            file={}; \
            aws s3 cp \
              --content-type "text/html" \
              --cache-control "no-cache" \
              --metadata-directive REPLACE \
                $file \
                s3://${AWS_S3_BUCKET}/${file%.html}'

      - name: "[deployment] Invalidate AWS Cloudfront cache: html files, web root, app bundle"
        run: |
          aws cloudfront create-invalidation \
            --distribution-id ${AWS_CLOUDFRONT_DISTRIBUTION_ID} \
            --paths "/*"

      - name: "[deployment] Clear AWS S3 bucket: large static files"
        run: |
          aws s3 rm s3://${AWS_S3_BUCKET} --recursive --exclude "*" --include "proteins/" --include "acknowledgements/"

      - name: "[deployment] Copy to AWS S3: large static files "
        run: |
          cd web/.build/production/web
          aws s3 cp --recursive --cache-control "max-age=7200, public" --metadata-directive REPLACE "proteins/" "s3://${AWS_S3_BUCKET}/proteins/"
          aws s3 cp --recursive --cache-control "max-age=7200, public" --metadata-directive REPLACE "acknowledgements/" "s3://${AWS_S3_BUCKET}/acknowledgements/"

      - name: "[deployment] Invalidate AWS Cloudfront cache: large static files"
        run: |
          aws cloudfront create-invalidation \
            --distribution-id ${AWS_CLOUDFRONT_DISTRIBUTION_ID} \
            --paths "/acknowledgements/*" "/proteins/*"