name: Test and lint

on:
  push:

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - name: Check out repo
        uses: actions/checkout@v3

      - name: Install poetry
        run: pipx install poetry

      - uses: actions/setup-python@v4
        with:
          python-version: '3.10'
          cache: 'poetry'

      - name: Install OS dependencies
        if: ${{ matrix.python-version }} == '3.10'
        run: |
          sudo apt update
          sudo apt install -y libre2-dev libpq-dev

      - name: Install dependencies
        if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
        run: poetry install --no-interaction

      - name: Check formatting & linting
        run: |
          poetry run pre-commit run --all-files


  test:
    runs-on: ubuntu-latest
    strategy:
      max-parallel: 4
      matrix:
        python-version: ["3.10"]

    # service containers to run with `postgres-job`
    services:
      # label used to access the service container
      postgres:
        # Docker Hub image
        image: postgres:13
        # service environment variables
        # `POSTGRES_HOST` is `postgres`
        env:
          # optional (defaults to `postgres`)
          POSTGRES_DB: test
          # required
          POSTGRES_PASSWORD: test
          # optional (defaults to `5432`)
          POSTGRES_PORT: 5432
          # optional (defaults to `postgres`)
          POSTGRES_USER: test
        ports:
          - 15432:5432
        # set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - name: Check out repo
        uses: actions/checkout@v3

      - name: Install poetry
        run: pipx install poetry

      - uses: actions/setup-python@v4
        with:
          python-version: ${{ matrix.python-version }}
          cache: 'poetry'

      - name: Install OS dependencies
        if: ${{ matrix.python-version }} == '3.10'
        run: |
          sudo apt update
          sudo apt install -y libre2-dev libpq-dev

      - name: Install dependencies
        if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
        run: poetry install --no-interaction


      - name: Start Redis v6
        uses: superchargejs/redis-github-action@1.1.0
        with:
          redis-version: 6

      - name: Run db migration
        run: |
          CONFIG=tests/test.env poetry run alembic upgrade head

      - name: Prepare version file
        run: |
          scripts/generate-build-info.sh ${{ github.sha }}
          cat app/build_info.py

      - name: Test with pytest
        run: |
          poetry run pytest
        env:
          GITHUB_ACTIONS_TEST: true

      - name: Archive code coverage results
        uses: actions/upload-artifact@v2
        with:
          name: code-coverage-report
          path: htmlcov

  build:
    runs-on: ubuntu-latest
    needs: ['test', 'lint']
    if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/v'))

    steps:
      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: simplelogin/app-ci

      - name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      # We need to checkout the repository in order for the "Create Sentry release" to work
      - name: Checkout repository
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Create Sentry release
        uses: getsentry/action-release@v1
        env:
          SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
          SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
          SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
        with:
          ignore_missing: true
          ignore_empty: true

      - name: Prepare version file
        run: |
          scripts/generate-build-info.sh ${{ github.sha }}
          cat app/build_info.py

      - name: Build image and publish to Docker Registry
        uses: docker/build-push-action@v3
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}


      #- name: Send Telegram message
      #  uses: appleboy/telegram-action@master
      #  with:
      #    to: ${{ secrets.TELEGRAM_TO }}
      #    token: ${{ secrets.TELEGRAM_TOKEN }}
      #    args: Docker image pushed on ${{ github.ref }}

      # If we have generated a tag, generate the changelog, send a notification to slack and create the GitHub release
      - name: Build Changelog
        id: build_changelog
        if: startsWith(github.ref, 'refs/tags/v')
        uses: mikepenz/release-changelog-builder-action@v3
        with:
          configuration: ".github/changelog_configuration.json"
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Prepare Slack notification contents
        if: startsWith(github.ref, 'refs/tags/v')
        run: |
          changelog=$(cat << EOH
          ${{ steps.build_changelog.outputs.changelog }}
          EOH
          )
          messageWithoutNewlines=$(echo "${changelog}" | awk '{printf "%s\\n", $0}')
          messageWithoutDoubleQuotes=$(echo "${messageWithoutNewlines}" | sed "s/\"/'/g")
          echo "${messageWithoutDoubleQuotes}"

          echo "SLACK_CHANGELOG=${messageWithoutDoubleQuotes}" >> $GITHUB_ENV

      - name: Post notification to Slack
        uses: slackapi/slack-github-action@v1.19.0
        if: startsWith(github.ref, 'refs/tags/v')
        with:
          channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
          payload: |
            {
              "blocks": [
                {
                  "type": "header",
                  "text": {
                    "type": "plain_text",
                    "text": "New tag created",
                    "emoji": true
                  }
                },
                {
                  "type": "section",
                  "text": {
                      "type": "mrkdwn",
                      "text": "*Tag: ${{ github.ref_name }}* (${{ github.sha }})"
                    }
                },
                {
                  "type": "section",
                  "text": {
                    "type": "mrkdwn",
                    "text": "*Changelog:*\n${{ env.SLACK_CHANGELOG }}"
                  }
                }
              ]
            }
        env:
          SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

      - name: Create GitHub Release
        if: startsWith(github.ref, 'refs/tags/v')
        uses: actions/create-release@v1
        with:
          tag_name: ${{ github.ref }}
          release_name: ${{ github.ref }}
          body: ${{ steps.build_changelog.outputs.changelog }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
