name: Zulip production suite

on:
  push: {}
  pull_request:
    paths:
      - .github/workflows/production-suite.yml
      - "**/migrations/**"
      - babel.config.js
      - manage.py
      - postcss.config.js
      - puppet/**
      - requirements/**
      - scripts/**
      - static/assets/**
      - static/third/**
      - tools/**
      - webpack.config.ts
      - yarn.lock
      - zerver/worker/queue_processors.py
      - zerver/lib/push_notifications.py
      - zerver/decorator.py
      - zproject/**

defaults:
  run:
    shell: bash

jobs:
  production_build:
    # This job builds a release tarball from the current commit, which
    # will be used for all of the following install/upgrade tests.
    name: Debian 10 production build
    runs-on: ubuntu-latest

    # Docker images are built from 'tools/ci/Dockerfile'; the comments at
    # the top explain how to build and upload these images.
    # Debian 10 ships with Python 3.7.3.
    container: zulip/ci:buster
    steps:
      - name: Add required permissions
        run: |
          # The checkout actions doesn't clone to ~/zulip or allow
          # us to use the path option to clone outside the current
          # /__w/zulip/zulip directory. Since this directory is owned
          # by root we need to change it's ownership to allow the
          # github user to clone the code here.
          # Note: /__w/ is a docker volume mounted to $GITHUB_WORKSPACE
          # which is /home/runner/work/.
          sudo chown -R github .

          # This is the GitHub Actions specific cache directory the
          # the current github user must be able to access for the
          # cache action to work. It is owned by root currently.
          sudo chmod -R 0777 /__w/_temp/

      - uses: actions/checkout@v2

      - name: Create cache directories
        run: |
          dirs=(/srv/zulip-{npm,venv,emoji}-cache)
          sudo mkdir -p "${dirs[@]}"
          sudo chown -R github "${dirs[@]}"

      - name: Restore node_modules cache
        uses: actions/cache@v2
        with:
          path: /srv/zulip-npm-cache
          key: v1-yarn-deps-buster-${{ hashFiles('package.json') }}-${{ hashFiles('yarn.lock') }}
          restore-keys: v1-yarn-deps-buster

      - name: Restore python cache
        uses: actions/cache@v2
        with:
          path: /srv/zulip-venv-cache
          key: v1-venv-buster-${{ hashFiles('requirements/dev.txt') }}
          restore-keys: v1-venv-buster

      - name: Restore emoji cache
        uses: actions/cache@v2
        with:
          path: /srv/zulip-emoji-cache
          key: v1-emoji-buster-${{ hashFiles('tools/setup/emoji/emoji_map.json') }}-${{ hashFiles('tools/setup/emoji/build_emoji') }}-${{ hashFiles('tools/setup/emoji/emoji_setup_utils.py') }}-${{ hashFiles('tools/setup/emoji/emoji_names.py') }}-${{ hashFiles('package.json') }}
          restore-keys: v1-emoji-buster

      - name: Build production tarball
        run: ./tools/ci/production-build

      - name: Upload production build artifacts for install jobs
        uses: actions/upload-artifact@v2
        with:
          name: production-tarball
          path: /tmp/production-build
          retention-days: 14

      - name: Report status
        if: failure()
        env:
          ZULIP_BOT_KEY: ${{ secrets.ZULIP_BOT_KEY }}
        run: tools/ci/send-failure-message

  production_install:
    # This job installs the server release tarball built above on a
    # range of platforms, and does some basic health checks on the
    # resulting installer Zulip server.
    strategy:
      fail-fast: false
      matrix:
        include:
          # Docker images are built from 'tools/ci/Dockerfile'; the comments at
          # the top explain how to build and upload these images.
          - docker_image: zulip/ci:focal
            name: Ubuntu 20.04 production install
            os: focal
            extra_args: ""

          - docker_image: zulip/ci:buster
            name: Debian 10 production install with custom db name and user
            os: buster
            extra_args: --test-custom-db

          - docker_image: zulip/ci:bullseye
            name: Debian 11 production install
            os: bullseye
            extra_args: ""

    name: ${{ matrix.name  }}
    container:
      image: ${{ matrix.docker_image }}
      options: --init
    runs-on: ubuntu-latest
    needs: production_build

    steps:
      - name: Download built production tarball
        uses: actions/download-artifact@v2
        with:
          name: production-tarball
          path: /tmp

      - name: Add required permissions and setup
        run: |
          # This is the GitHub Actions specific cache directory the
          # the current github user must be able to access for the
          # cache action to work. It is owned by root currently.
          sudo chmod -R 0777 /__w/_temp/

          # Since actions/download-artifact@v2 loses all the permissions
          # of the tarball uploaded by the upload artifact fix those.
          chmod +x /tmp/production-upgrade-pg
          chmod +x /tmp/production-pgroonga
          chmod +x /tmp/production-install
          chmod +x /tmp/production-verify
          chmod +x /tmp/send-failure-message

      - name: Create cache directories
        run: |
          dirs=(/srv/zulip-{npm,venv,emoji}-cache)
          sudo mkdir -p "${dirs[@]}"
          sudo chown -R github "${dirs[@]}"

      - name: Restore node_modules cache
        uses: actions/cache@v2
        with:
          path: /srv/zulip-npm-cache
          key: v1-yarn-deps-${{ matrix.os }}-${{ hashFiles('/tmp/package.json') }}-${{ hashFiles('/tmp/yarn.lock') }}
          restore-keys: v1-yarn-deps-${{ matrix.os }}

      - name: Install production
        run: |
          sudo service rabbitmq-server restart
          sudo /tmp/production-install ${{ matrix.extra-args }}

      - name: Verify install
        run: sudo /tmp/production-verify ${{ matrix.extra-args }}

      - name: Install pgroonga
        if: ${{ matrix.os == 'focal' }}
        run: sudo /tmp/production-pgroonga

      - name: Verify install after installing pgroonga
        if: ${{ matrix.os == 'focal' }}
        run: sudo /tmp/production-verify ${{ matrix.extra-args }}

      - name: Upgrade postgresql
        if: ${{ matrix.os == 'focal' }}
        run: sudo /tmp/production-upgrade-pg

      - name: Verify install after upgrading postgresql
        if: ${{ matrix.os == 'focal' }}
        run: sudo /tmp/production-verify ${{ matrix.extra-args }}

      - name: Report status
        if: failure()
        env:
          ZULIP_BOT_KEY: ${{ secrets.ZULIP_BOT_KEY }}
        run: /tmp/send-failure-message

  production_upgrade:
    # The production upgrade job starts with a container with a
    # previous Zulip release installed, and attempts to upgrade it to
    # the release tarball built for the current commit being tested.
    #
    # This is intended to catch bugs that result in the upgrade
    # process failing.
    strategy:
      fail-fast: false
      matrix:
        include:
          # Docker images are built from 'tools/ci/Dockerfile'; the comments at
          # the top explain how to build and upload these images.
          - docker_image: zulip/ci:buster-3.4
            name: 3.4 Version Upgrade
            os: buster

          - docker_image: zulip/ci:bullseye-4.11
            name: 4.11 Version Upgrade
            os: bullseye
          - docker_image: zulip/ci:bullseye-5.1
            name: 5.1 Version Upgrade
            os: bullseye

    name: ${{ matrix.name  }}
    container:
      image: ${{ matrix.docker_image }}
      options: --init
    runs-on: ubuntu-latest
    needs: production_build

    steps:
      - name: Download built production tarball
        uses: actions/download-artifact@v2
        with:
          name: production-tarball
          path: /tmp

      - name: Add required permissions and setup
        run: |
          # This is the GitHub Actions specific cache directory the
          # the current github user must be able to access for the
          # cache action to work. It is owned by root currently.
          sudo chmod -R 0777 /__w/_temp/

          # Since actions/download-artifact@v2 loses all the permissions
          # of the tarball uploaded by the upload artifact fix those.
          chmod +x /tmp/production-upgrade
          chmod +x /tmp/production-verify
          chmod +x /tmp/send-failure-message

      - name: Create cache directories
        run: |
          dirs=(/srv/zulip-{npm,venv,emoji}-cache)
          sudo mkdir -p "${dirs[@]}"
          sudo chown -R github "${dirs[@]}"

      - name: Upgrade production
        run: sudo /tmp/production-upgrade

        # TODO: We should be running production-verify here, but it
        # doesn't pass yet.
        #
        # - name: Verify install
        #   run: sudo /tmp/production-verify

      - name: Report status
        if: failure()
        env:
          ZULIP_BOT_KEY: ${{ secrets.ZULIP_BOT_KEY }}
        run: /tmp/send-failure-message
