name: ci on: push: tags: - ngx-* - beta-* branches-ignore: - 'translations**' pull_request: branches-ignore: - 'translations**' jobs: documentation: name: "Build Documentation" runs-on: ubuntu-20.04 steps: - name: Checkout uses: actions/checkout@v3 - name: Install pipenv run: pipx install pipenv - name: Set up Python uses: actions/setup-python@v3 with: python-version: 3.9 cache: "pipenv" cache-dependency-path: 'Pipfile.lock' - name: Install dependencies run: | pipenv sync --dev - name: Make documentation run: | cd docs/ pipenv run make html - name: Upload artifact uses: actions/upload-artifact@v3 with: name: documentation path: docs/_build/html/ ci-backend: uses: ./.github/workflows/reusable-ci-backend.yml ci-frontend: uses: ./.github/workflows/reusable-ci-frontend.yml prepare-docker-build: name: Prepare Docker Pipeline Data 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-20.04 needs: - documentation - ci-backend - ci-frontend steps: - name: Checkout uses: actions/checkout@v3 - name: Login to Github Container Registry uses: docker/login-action@v1 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Python uses: actions/setup-python@v3 with: python-version: "3.9" - name: Make script executable run: | chmod +x ${GITHUB_WORKSPACE}/docker-builders/get-build-json.py - name: Setup qpdf image id: qpdf-setup run: | build_json=$(python ${GITHUB_WORKSPACE}/docker-builders/get-build-json.py qpdf) echo ${build_json} echo ::set-output name=qpdf-json::${build_json} - name: Setup psycopg2 image id: psycopg2-setup run: | build_json=$(python ${GITHUB_WORKSPACE}/docker-builders/get-build-json.py psycopg2) echo ${build_json} echo ::set-output name=psycopg2-json::${build_json} - name: Setup pikepdf image id: pikepdf-setup run: | build_json=$(python ${GITHUB_WORKSPACE}/docker-builders/get-build-json.py pikepdf) echo ${build_json} echo ::set-output name=pikepdf-json::${build_json} - name: Setup jbig2enc image id: jbig2enc-setup run: | build_json=$(python ${GITHUB_WORKSPACE}/docker-builders/get-build-json.py jbig2enc) echo ${build_json} echo ::set-output name=jbig2enc-json::${build_json} - name: Setup frontend image id: frontend-setup run: | build_json=$(python ${GITHUB_WORKSPACE}/docker-builders/get-build-json.py frontend) echo ${build_json} echo ::set-output name=frontend-json::${build_json} outputs: qpdf-json: ${{ steps.qpdf-setup.outputs.qpdf-json }} pikepdf-json: ${{ steps.pikepdf-setup.outputs.pikepdf-json }} psycopg2-json: ${{ steps.psycopg2-setup.outputs.psycopg2-json }} jbig2enc-json: ${{ steps.jbig2enc-setup.outputs.jbig2enc-json}} frontend-json: ${{ steps.frontend-setup.outputs.frontend-json}} build-qpdf-debs: name: qpdf needs: - prepare-docker-build uses: ./.github/workflows/reusable-workflow-builder.yml with: dockerfile: ./docker-builders/Dockerfile.qpdf build-json: ${{ needs.prepare-docker-build.outputs.qpdf-json }} build-args: | QPDF_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.qpdf-json).version }} build-jbig2enc: name: jbig2enc needs: - prepare-docker-build uses: ./.github/workflows/reusable-workflow-builder.yml with: dockerfile: ./docker-builders/Dockerfile.jbig2enc build-json: ${{ needs.prepare-docker-build.outputs.jbig2enc-json }} build-args: | JBIG2ENC_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.jbig2enc-json).version }} build-psycopg2-wheel: name: psycopg2 needs: - prepare-docker-build uses: ./.github/workflows/reusable-workflow-builder.yml with: dockerfile: ./docker-builders/Dockerfile.psycopg2 build-json: ${{ needs.prepare-docker-build.outputs.psycopg2-json }} build-args: | PSYCOPG2_GIT_TAG=${{ fromJSON(needs.prepare-docker-build.outputs.psycopg2-json).git_tag }} PSYCOPG2_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.psycopg2-json).version }} build-pikepdf-wheel: name: pikepdf needs: - prepare-docker-build - build-qpdf-debs uses: ./.github/workflows/reusable-workflow-builder.yml with: dockerfile: ./docker-builders/Dockerfile.pikepdf build-json: ${{ needs.prepare-docker-build.outputs.pikepdf-json }} build-args: | REPO=${{ github.repository }} QPDF_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.qpdf-json).version }} PIKEPDF_GIT_TAG=${{ fromJSON(needs.prepare-docker-build.outputs.pikepdf-json).git_tag }} PIKEPDF_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.pikepdf-json).version }} build-frontend: name: Compile frontend concurrency: group: ${{ github.workflow }}-build-frontend-${{ github.ref_name }} cancel-in-progress: false needs: - prepare-docker-build runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 with: fetch-depth: 2 - name: Get changed frontend files id: changed-files-specific uses: tj-actions/changed-files@v18.1 with: files: | src-ui/** - name: Login to Github Container Registry uses: docker/login-action@v1 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Determine if build needed id: build-skip-check # Skip building the frontend if the tag exists and no src-ui files changed run: | if ! docker manifest inspect ${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).image_tag }} &> /dev/null ; then echo "Build required, no existing image" echo ::set-output name=frontend-build-needed::true elif ${{ steps.changed-files-specific.outputs.any_changed }} == 'true' ; then echo "Build required, src-ui changes" echo ::set-output name=frontend-build-needed::true else echo "No build required" echo ::set-output name=frontend-build-needed::false fi - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 if: ${{ steps.build-skip-check.outputs.frontend-build-needed == 'true' }} - name: Set up QEMU uses: docker/setup-qemu-action@v1 if: ${{ steps.build-skip-check.outputs.frontend-build-needed == 'true' }} - name: Compile frontend uses: docker/build-push-action@v2 if: ${{ steps.build-skip-check.outputs.frontend-build-needed == 'true' }} with: context: . file: ./docker-builders/Dockerfile.frontend tags: ${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).image_tag }} # The compilation is identical between different platforms # The buildx and QEMU setup is left, just in case that ever changes # But the platform is set to the runner's native for speedup platforms: linux/amd64 push: true cache-from: type=gha cache-to: type=gha,mode=max - name: Export frontend artifact from docker run: | docker create --name frontend-extract ${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).image_tag }} docker cp frontend-extract:/src/src/documents/static/frontend src/documents/static/frontend/ - name: Upload frontend artifact uses: actions/upload-artifact@v3 with: name: frontend-compiled path: src/documents/static/frontend/ # build and push image to docker hub. build-docker-image: runs-on: ubuntu-20.04 concurrency: group: ${{ github.workflow }}-build-docker-image-${{ github.ref_name }} cancel-in-progress: true needs: - prepare-docker-build - build-psycopg2-wheel - build-jbig2enc - build-qpdf-debs - build-pikepdf-wheel - build-frontend steps: - name: Gather Docker metadata id: docker-meta uses: docker/metadata-action@v3 with: images: ghcr.io/${{ github.repository }} tags: | type=ref,event=branch type=ref,event=tag - name: Checkout uses: actions/checkout@v3 - 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: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.docker-meta.outputs.tags }} labels: ${{ steps.docker-meta.outputs.labels }} build-args: | REPO=${{ github.repository }} JBIG2ENC_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.jbig2enc-json).version }} QPDF_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.qpdf-json).version }} PIKEPDF_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.pikepdf-json).version }} PSYCOPG2_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.psycopg2-json).version }} FRONTEND_VERSION=${{ fromJSON(needs.prepare-docker-build.outputs.frontend-json).version }} cache-from: type=gha cache-to: type=gha,mode=max - name: Inspect image run: | docker buildx imagetools inspect ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }} build-release: needs: - build-docker-image runs-on: ubuntu-20.04 steps: - name: Checkout uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v3 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@v3 with: name: frontend-compiled path: src/documents/static/frontend/ - name: Download documentation artifact uses: actions/download-artifact@v3 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@v3 with: name: release path: dist/paperless-ngx.tar.xz publish-release: runs-on: ubuntu-20.04 needs: - build-release if: github.ref_type == 'tag' && (startsWith(github.ref_name, 'ngx-') || startsWith(github.ref_name, 'beta-')) steps: - name: Download release artifact uses: actions/download-artifact@v3 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 elif [[ $GITHUB_REF == refs/tags/beta-* ]]; then echo ::set-output name=version::${GITHUB_REF#refs/tags/beta-} echo ::set-output name=prerelease::true fi - name: Create Release and Changelog id: create-release uses: release-drafter/release-drafter@v5 with: name: Paperless-ngx ${{ steps.get_version.outputs.version }} tag: ngx-${{ steps.get_version.outputs.version }} version: ${{ steps.get_version.outputs.version }} prerelease: ${{ steps.get_version.outputs.prerelease }} publish: true # ensures release is not marked as draft env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - 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 }} asset_path: ./paperless-ngx.tar.xz asset_name: paperless-ngx-${{ steps.get_version.outputs.version }}.tar.xz asset_content_type: application/x-xz