name: ci

on:
  push:
    tags:
      - ngx-*
      - beta-*
    branches-ignore:
      - 'translations**'
  pull_request:
    branches-ignore:
      - 'translations**'

jobs:
  documentation:
    runs-on: ubuntu-20.04
    steps:
      -
        name: Checkout
        uses: actions/checkout@v2
      -
        name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: 3.9
      -
        name: Get pip cache dir
        id: pip-cache
        run: |
          echo "::set-output name=dir::$(pip cache dir)"
      -
        name: Persistent Github pip cache
        uses: actions/cache@v2
        with:
          path: ${{ steps.pip-cache.outputs.dir }}
          key: ${{ runner.os }}-pip3.8}
      -
        name: Install dependencies
        run: |
          pip install --upgrade pipenv
          pipenv install --system --dev --ignore-pipfile
      -
        name: Make documentation
        run: |
          cd docs/
          make html
      -
        name: Upload artifact
        uses: actions/upload-artifact@v2
        with:
          name: documentation
          path: docs/_build/html/

  codestyle:
    runs-on: ubuntu-20.04
    steps:
      -
        name: Checkout
        uses: actions/checkout@v2
      -
        name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: 3.9
      -
        name: Get pip cache dir
        id: pip-cache
        run: |
          echo "::set-output name=dir::$(pip cache dir)"
      -
        name: Persistent Github pip cache
        uses: actions/cache@v2
        with:
          path: ${{ steps.pip-cache.outputs.dir }}
          key: ${{ runner.os }}-pip${{ matrix.python-version }}
      -
        name: Install dependencies
        run: |
          pip install --upgrade pipenv
          pipenv install --system --dev --ignore-pipfile
      -
        name: Codestyle
        run: |
          cd src/
          pycodestyle --max-line-length=88 --ignore=E121,E123,E126,E226,E24,E704,W503,W504,E203
  codeformatting:
    runs-on: ubuntu-20.04
    steps:
      -
        name: Checkout
        uses: actions/checkout@v2
      -
        name: Run black
        uses: psf/black@stable
        with:
          options: "--check --diff"
          version: "22.3.0"

  tests:
    runs-on: ubuntu-20.04
    strategy:
      matrix:
        python-version: ['3.8', '3.9']
      fail-fast: false
    steps:
      -
        name: Checkout
        uses: actions/checkout@v2
      -
        name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: "${{ matrix.python-version }}"
      -
        name: Get pip cache dir
        id: pip-cache
        run: |
          echo "::set-output name=dir::$(pip cache dir)"
      -
        name: Persistent Github pip cache
        uses: actions/cache@v2
        with:
          path: ${{ steps.pip-cache.outputs.dir }}
          key: ${{ runner.os }}-pip${{ matrix.python-version }}
      -
        name: Install dependencies
        run: |
          sudo apt-get update -qq
          sudo apt-get install -qq --no-install-recommends unpaper tesseract-ocr imagemagick ghostscript optipng
          pip install --upgrade pipenv
          pipenv install --system --dev --ignore-pipfile
      -
        name: Tests
        run: |
          cd src/
          pytest
      -
        name: Publish coverage results
        if: matrix.python-version == '3.9'
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        # https://github.com/coveralls-clients/coveralls-python/issues/251
        run: |
          cd src/
          coveralls --service=github

  # build and push image to docker hub.
  build-docker-image:
    if: github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/beta' || startsWith(github.ref, 'refs/tags/ngx-') || startsWith(github.ref, 'refs/tags/beta-'))
    runs-on: ubuntu-latest
    needs: [tests, codeformatting, codestyle]
    steps:
      -
        name: Prepare
        id: prepare
        run: |
          IMAGE_NAME=ghcr.io/${{ github.repository }}
          if [[ $GITHUB_REF == refs/tags/ngx-* ]]; then
            TAGS=${IMAGE_NAME}:${GITHUB_REF#refs/tags/ngx-},${IMAGE_NAME}:latest
            INSPECT_TAG=${IMAGE_NAME}:latest
          elif [[ $GITHUB_REF == refs/tags/beta-* ]]; then
            TAGS=${IMAGE_NAME}:beta
            INSPECT_TAG=${TAGS}
          elif [[ $GITHUB_REF == refs/heads/* ]]; then
            TAGS=${IMAGE_NAME}:${GITHUB_REF#refs/heads/}
            INSPECT_TAG=${TAGS}
          else
            exit 1
          fi
          echo ::set-output name=tags::${TAGS}
          echo ::set-output name=inspect_tag::${INSPECT_TAG}
      -
        name: Checkout
        uses: actions/checkout@v2
      -
        name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1
      -
        name: Set up QEMU
        uses: docker/setup-qemu-action@v1
      -
        name: Login to Github Container Registry
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      -
        name: Build and push
        uses: docker/build-push-action@v2
        with:
          context: .
          file: ./Dockerfile
          platforms: linux/amd64,linux/arm/v7,linux/arm64
          push: true
          tags: ${{ steps.prepare.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
      -
        name: Inspect image
        run: |
          docker buildx imagetools inspect ${{ steps.prepare.outputs.inspect_tag }}
      -
        name: Export frontend artifact from docker
        run: |
          docker run -d --name frontend-extract ${{ steps.prepare.outputs.inspect_tag }}
          docker cp frontend-extract:/usr/src/paperless/src/documents/static/frontend src/documents/static/frontend/
      -
        name: Upload frontend artifact
        uses: actions/upload-artifact@v2
        with:
          name: frontend-compiled
          path: src/documents/static/frontend/

  build-release:
    needs: [build-docker-image, documentation, tests, codeformatting, codestyle]
    runs-on: ubuntu-20.04
    steps:
      -
        name: Checkout
        uses: actions/checkout@v2
      -
        name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: 3.9
      -
        name: Install dependencies
        run: |
          sudo apt-get update -qq
          sudo apt-get install -qq --no-install-recommends gettext liblept5
          pip3 install --upgrade pip setuptools wheel
          pip3 install -r requirements.txt
      -
        name: Download frontend artifact
        uses: actions/download-artifact@v2
        with:
          name: frontend-compiled
          path: src/documents/static/frontend/
      -
        name: Download documentation artifact
        uses: actions/download-artifact@v2
        with:
          name: documentation
          path: docs/_build/html/
      -
        name: Move files
        run: |
          mkdir dist
          mkdir dist/paperless-ngx
          mkdir dist/paperless-ngx/scripts
          cp .dockerignore .env Dockerfile Pipfile Pipfile.lock LICENSE README.md requirements.txt dist/paperless-ngx/
          cp paperless.conf.example dist/paperless-ngx/paperless.conf
          cp gunicorn.conf.py dist/paperless-ngx/gunicorn.conf.py
          cp docker/ dist/paperless-ngx/docker -r
          cp scripts/*.service scripts/*.sh dist/paperless-ngx/scripts/
          cp src/ dist/paperless-ngx/src -r
          cp docs/_build/html/ dist/paperless-ngx/docs -r
      -
        name: Compile messages
        run: |
          cd dist/paperless-ngx/src
          python3 manage.py compilemessages
      -
        name: Collect static files
        run: |
          cd dist/paperless-ngx/src
          python3 manage.py collectstatic --no-input
      -
        name: Make release package
        run: |
          cd dist
          find . -name __pycache__ | xargs rm -r
          tar -cJf paperless-ngx.tar.xz paperless-ngx/
      -
        name: Upload release artifact
        uses: actions/upload-artifact@v2
        with:
          name: release
          path: dist/paperless-ngx.tar.xz

  publish-release:
    runs-on: ubuntu-latest
    needs: build-release
    if: contains(github.ref, 'refs/tags/ngx-') || contains(github.ref, 'refs/tags/beta-')
    steps:
      -
        name: Download release artifact
        uses: actions/download-artifact@v2
        with:
          name: release
          path: ./
      -
        name: Get version
        id: get_version
        run: |
          if [[ $GITHUB_REF == refs/tags/ngx-* ]]; then
            echo ::set-output name=version::${GITHUB_REF#refs/tags/ngx-}
            echo ::set-output name=prerelease::false
            echo ::set-output name=body::"For a complete list of changes, see the changelog at https://paperless-ngx.readthedocs.io/en/latest/changelog.html"
          elif [[ $GITHUB_REF == refs/tags/beta-* ]]; then
            echo ::set-output name=version::${GITHUB_REF#refs/tags/beta-}
            echo ::set-output name=prerelease::true
            echo ::set-output name=body::"For a complete list of changes, see the changelog at https://github.com/paperless-ngx/paperless-ngx/blob/beta/docs/changelog.rst"
          fi
      -
        name: Create release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ngx-${{ steps.get_version.outputs.version }}
          release_name: Paperless-ngx ${{ steps.get_version.outputs.version }}
          draft: false
          prerelease: ${{ steps.get_version.outputs.prerelease }}
          body: ${{ steps.get_version.outputs.body }}
      -
        name: Upload release archive
        id: upload-release-asset
        uses: actions/upload-release-asset@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
          asset_path: ./paperless-ngx.tar.xz
          asset_name: paperless-ngx-${{ steps.get_version.outputs.version }}.tar.xz
          asset_content_type: application/x-xz
