mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-01-12 21:44:21 -06:00
Chore: Re-work CI into multiple workflows (#11719)
This commit is contained in:
104
.github/workflows/ci-backend.yml
vendored
Normal file
104
.github/workflows/ci-backend.yml
vendored
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
name: Backend Tests
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches-ignore:
|
||||||
|
- 'translations**'
|
||||||
|
paths:
|
||||||
|
- 'src/**'
|
||||||
|
- 'pyproject.toml'
|
||||||
|
- 'uv.lock'
|
||||||
|
- 'docker/compose/docker-compose.ci-test.yml'
|
||||||
|
- '.github/workflows/ci-backend.yml'
|
||||||
|
pull_request:
|
||||||
|
branches-ignore:
|
||||||
|
- 'translations**'
|
||||||
|
paths:
|
||||||
|
- 'src/**'
|
||||||
|
- 'pyproject.toml'
|
||||||
|
- 'uv.lock'
|
||||||
|
- 'docker/compose/docker-compose.ci-test.yml'
|
||||||
|
- '.github/workflows/ci-backend.yml'
|
||||||
|
workflow_dispatch:
|
||||||
|
concurrency:
|
||||||
|
group: backend-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
env:
|
||||||
|
DEFAULT_UV_VERSION: "0.9.x"
|
||||||
|
NLTK_DATA: "/usr/share/nltk_data"
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: "Python ${{ matrix.python-version }}"
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: ['3.10', '3.11', '3.12']
|
||||||
|
fail-fast: false
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: Start containers
|
||||||
|
run: |
|
||||||
|
docker compose --file docker/compose/docker-compose.ci-test.yml pull --quiet
|
||||||
|
docker compose --file docker/compose/docker-compose.ci-test.yml up --detach
|
||||||
|
- name: Set up Python
|
||||||
|
id: setup-python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: "${{ matrix.python-version }}"
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v7
|
||||||
|
with:
|
||||||
|
version: ${{ env.DEFAULT_UV_VERSION }}
|
||||||
|
enable-cache: true
|
||||||
|
python-version: ${{ steps.setup-python.outputs.python-version }}
|
||||||
|
- name: Install system dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -qq --no-install-recommends \
|
||||||
|
unpaper tesseract-ocr imagemagick ghostscript libzbar0 poppler-utils
|
||||||
|
- name: Configure ImageMagick
|
||||||
|
run: |
|
||||||
|
sudo cp docker/rootfs/etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-6/policy.xml
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
uv sync \
|
||||||
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
|
--group testing \
|
||||||
|
--frozen
|
||||||
|
- name: List installed Python dependencies
|
||||||
|
run: |
|
||||||
|
uv pip list
|
||||||
|
- name: Install NLTK data
|
||||||
|
run: |
|
||||||
|
uv run python -m nltk.downloader punkt punkt_tab snowball_data stopwords -d ${{ env.NLTK_DATA }}
|
||||||
|
- name: Run tests
|
||||||
|
env:
|
||||||
|
NLTK_DATA: ${{ env.NLTK_DATA }}
|
||||||
|
PAPERLESS_CI_TEST: 1
|
||||||
|
PAPERLESS_MAIL_TEST_HOST: ${{ secrets.TEST_MAIL_HOST }}
|
||||||
|
PAPERLESS_MAIL_TEST_USER: ${{ secrets.TEST_MAIL_USER }}
|
||||||
|
PAPERLESS_MAIL_TEST_PASSWD: ${{ secrets.TEST_MAIL_PASSWD }}
|
||||||
|
run: |
|
||||||
|
uv run \
|
||||||
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
|
--dev \
|
||||||
|
--frozen \
|
||||||
|
pytest
|
||||||
|
- name: Upload test results to Codecov
|
||||||
|
if: always()
|
||||||
|
uses: codecov/codecov-action@v5
|
||||||
|
with:
|
||||||
|
flags: backend-python-${{ matrix.python-version }}
|
||||||
|
files: junit.xml
|
||||||
|
report_type: test_results
|
||||||
|
- name: Upload coverage to Codecov
|
||||||
|
uses: codecov/codecov-action@v5
|
||||||
|
with:
|
||||||
|
flags: backend-python-${{ matrix.python-version }}
|
||||||
|
files: coverage.xml
|
||||||
|
report_type: coverage
|
||||||
|
- name: Stop containers
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
docker compose --file docker/compose/docker-compose.ci-test.yml logs
|
||||||
|
docker compose --file docker/compose/docker-compose.ci-test.yml down
|
||||||
114
.github/workflows/ci-docker.yml
vendored
Normal file
114
.github/workflows/ci-docker.yml
vendored
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
name: Docker Build
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||||
|
- 'v[0-9]+.[0-9]+.[0-9]+-beta.rc[0-9]+'
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
- beta
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
- main
|
||||||
|
workflow_dispatch:
|
||||||
|
concurrency:
|
||||||
|
group: docker-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
jobs:
|
||||||
|
build-docker-image:
|
||||||
|
name: Build Docker Image
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
env:
|
||||||
|
CAN_PUSH: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: Determine ref name
|
||||||
|
id: ref
|
||||||
|
run: |
|
||||||
|
echo "name=${GITHUB_HEAD_REF:-$GITHUB_REF_NAME}" >> $GITHUB_OUTPUT
|
||||||
|
- name: Check external registry push
|
||||||
|
id: push-external
|
||||||
|
env:
|
||||||
|
REF_NAME: ${{ steps.ref.outputs.name }}
|
||||||
|
run: |
|
||||||
|
# If we cannot push (e.g. fork PR), explicitly disable external push and exit
|
||||||
|
if [[ "$CAN_PUSH" != "true" ]]; then
|
||||||
|
echo "enable=false" >> $GITHUB_OUTPUT
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Only push to Docker Hub / Quay from main repo on specific branches/tags
|
||||||
|
if [[ "${{ github.repository_owner }}" == "paperless-ngx" ]]; then
|
||||||
|
case "$REF_NAME" in
|
||||||
|
dev|beta)
|
||||||
|
echo "enable=true" >> $GITHUB_OUTPUT
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
case "$GITHUB_REF" in
|
||||||
|
refs/tags/v*|*beta.rc*)
|
||||||
|
echo "enable=true" >> $GITHUB_OUTPUT
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
echo "enable=false" >> $GITHUB_OUTPUT
|
||||||
|
- name: Docker metadata
|
||||||
|
id: docker-meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
ghcr.io/${{ github.repository }}
|
||||||
|
name=paperlessngx/paperless-ngx,enable=${{ steps.push-external.outputs.enable }}
|
||||||
|
name=quay.io/paperlessngx/paperless-ngx,enable=${{ steps.push-external.outputs.enable }}
|
||||||
|
tags: |
|
||||||
|
type=ref,event=branch
|
||||||
|
type=raw,value=${{ steps.ref.outputs.name }},enable=${{ github.event_name == 'pull_request' }}
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
with:
|
||||||
|
platforms: arm64
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
if: steps.push-external.outputs.enable == 'true'
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Login to Quay.io
|
||||||
|
if: steps.push-external.outputs.enable == 'true'
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: quay.io
|
||||||
|
username: ${{ secrets.QUAY_USERNAME }}
|
||||||
|
password: ${{ secrets.QUAY_ROBOT_TOKEN }}
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: ${{ env.CAN_PUSH == 'true' }}
|
||||||
|
tags: ${{ steps.docker-meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.docker-meta.outputs.labels }}
|
||||||
|
build-args: |
|
||||||
|
PNGX_TAG_VERSION=${{ steps.docker-meta.outputs.version }}
|
||||||
|
cache-from: |
|
||||||
|
type=registry,ref=ghcr.io/${{ github.repository }}/cache/app:${{ steps.ref.outputs.name }}
|
||||||
|
type=registry,ref=ghcr.io/${{ github.repository }}/cache/app:dev
|
||||||
|
cache-to: ${{ env.CAN_PUSH == 'true' && format('type=registry,mode=max,ref=ghcr.io/{0}/cache/app:{1}', github.repository, steps.ref.outputs.name) || '' }}
|
||||||
|
- name: Inspect image
|
||||||
|
if: env.CAN_PUSH == 'true'
|
||||||
|
run: |
|
||||||
|
docker buildx imagetools inspect ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
||||||
88
.github/workflows/ci-docs.yml
vendored
Normal file
88
.github/workflows/ci-docs.yml
vendored
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
name: Documentation
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- dev
|
||||||
|
paths:
|
||||||
|
- 'docs/**'
|
||||||
|
- 'mkdocs.yml'
|
||||||
|
- '.github/workflows/ci-docs.yml'
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'docs/**'
|
||||||
|
- 'mkdocs.yml'
|
||||||
|
- '.github/workflows/ci-docs.yml'
|
||||||
|
workflow_dispatch:
|
||||||
|
concurrency:
|
||||||
|
group: docs-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
env:
|
||||||
|
DEFAULT_UV_VERSION: "0.9.x"
|
||||||
|
DEFAULT_PYTHON_VERSION: "3.11"
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build Documentation
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: Set up Python
|
||||||
|
id: setup-python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v7
|
||||||
|
with:
|
||||||
|
version: ${{ env.DEFAULT_UV_VERSION }}
|
||||||
|
enable-cache: true
|
||||||
|
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
uv sync --python ${{ steps.setup-python.outputs.python-version }} --dev --frozen
|
||||||
|
- name: Build documentation
|
||||||
|
run: |
|
||||||
|
uv run \
|
||||||
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
|
--dev \
|
||||||
|
--frozen \
|
||||||
|
mkdocs build --config-file ./mkdocs.yml
|
||||||
|
- name: Upload artifact
|
||||||
|
uses: actions/upload-artifact@v6
|
||||||
|
with:
|
||||||
|
name: documentation
|
||||||
|
path: site/
|
||||||
|
retention-days: 7
|
||||||
|
deploy:
|
||||||
|
name: Deploy Documentation
|
||||||
|
needs: build
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: Set up Python
|
||||||
|
id: setup-python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v7
|
||||||
|
with:
|
||||||
|
version: ${{ env.DEFAULT_UV_VERSION }}
|
||||||
|
enable-cache: true
|
||||||
|
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
uv sync --python ${{ steps.setup-python.outputs.python-version }} --dev --frozen
|
||||||
|
- name: Deploy documentation
|
||||||
|
run: |
|
||||||
|
echo "docs.paperless-ngx.com" > "${{ github.workspace }}/docs/CNAME"
|
||||||
|
git config --global user.name "${{ github.actor }}"
|
||||||
|
git config --global user.email "${{ github.actor }}@users.noreply.github.com"
|
||||||
|
uv run \
|
||||||
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
|
--dev \
|
||||||
|
--frozen \
|
||||||
|
mkdocs gh-deploy --force --no-history
|
||||||
189
.github/workflows/ci-frontend.yml
vendored
Normal file
189
.github/workflows/ci-frontend.yml
vendored
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
name: Frontend Tests
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches-ignore:
|
||||||
|
- 'translations**'
|
||||||
|
paths:
|
||||||
|
- 'src-ui/**'
|
||||||
|
- '.github/workflows/ci-frontend.yml'
|
||||||
|
pull_request:
|
||||||
|
branches-ignore:
|
||||||
|
- 'translations**'
|
||||||
|
paths:
|
||||||
|
- 'src-ui/**'
|
||||||
|
- '.github/workflows/ci-frontend.yml'
|
||||||
|
workflow_dispatch:
|
||||||
|
concurrency:
|
||||||
|
group: frontend-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
jobs:
|
||||||
|
install-dependencies:
|
||||||
|
name: Install Dependencies
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
- name: Use Node.js 20
|
||||||
|
uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: 20.x
|
||||||
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
|
||||||
|
- name: Cache frontend dependencies
|
||||||
|
id: cache-frontend-deps
|
||||||
|
uses: actions/cache@v5
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.pnpm-store
|
||||||
|
~/.cache
|
||||||
|
key: ${{ runner.os }}-frontend-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
|
||||||
|
- name: Install dependencies
|
||||||
|
run: cd src-ui && pnpm install
|
||||||
|
lint:
|
||||||
|
name: Lint
|
||||||
|
needs: install-dependencies
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
- name: Use Node.js 20
|
||||||
|
uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: 20.x
|
||||||
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
|
||||||
|
- name: Cache frontend dependencies
|
||||||
|
uses: actions/cache@v5
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.pnpm-store
|
||||||
|
~/.cache
|
||||||
|
key: ${{ runner.os }}-frontend-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
|
||||||
|
- name: Re-link Angular CLI
|
||||||
|
run: cd src-ui && pnpm link @angular/cli
|
||||||
|
- name: Run lint
|
||||||
|
run: cd src-ui && pnpm run lint
|
||||||
|
unit-tests:
|
||||||
|
name: "Unit Tests (${{ matrix.shard-index }}/${{ matrix.shard-count }})"
|
||||||
|
needs: install-dependencies
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
node-version: [20.x]
|
||||||
|
shard-index: [1, 2, 3, 4]
|
||||||
|
shard-count: [4]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
- name: Use Node.js 20
|
||||||
|
uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: 20.x
|
||||||
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
|
||||||
|
- name: Cache frontend dependencies
|
||||||
|
uses: actions/cache@v5
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.pnpm-store
|
||||||
|
~/.cache
|
||||||
|
key: ${{ runner.os }}-frontend-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
|
||||||
|
- name: Re-link Angular CLI
|
||||||
|
run: cd src-ui && pnpm link @angular/cli
|
||||||
|
- name: Run Jest unit tests
|
||||||
|
run: cd src-ui && pnpm run test --max-workers=2 --shard=${{ matrix.shard-index }}/${{ matrix.shard-count }}
|
||||||
|
- name: Upload test results to Codecov
|
||||||
|
if: always()
|
||||||
|
uses: codecov/codecov-action@v5
|
||||||
|
with:
|
||||||
|
flags: frontend-node-${{ matrix.node-version }}
|
||||||
|
directory: src-ui/
|
||||||
|
report_type: test_results
|
||||||
|
- name: Upload coverage to Codecov
|
||||||
|
uses: codecov/codecov-action@v5
|
||||||
|
with:
|
||||||
|
flags: frontend-node-${{ matrix.node-version }}
|
||||||
|
directory: src-ui/coverage/
|
||||||
|
e2e-tests:
|
||||||
|
name: "E2E Tests (${{ matrix.shard-index }}/${{ matrix.shard-count }})"
|
||||||
|
needs: install-dependencies
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
container: mcr.microsoft.com/playwright:v1.57.0-noble
|
||||||
|
env:
|
||||||
|
PLAYWRIGHT_BROWSERS_PATH: /ms-playwright
|
||||||
|
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
node-version: [20.x]
|
||||||
|
shard-index: [1, 2]
|
||||||
|
shard-count: [2]
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
- name: Use Node.js 20
|
||||||
|
uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: 20.x
|
||||||
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
|
||||||
|
- name: Cache frontend dependencies
|
||||||
|
uses: actions/cache@v5
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.pnpm-store
|
||||||
|
~/.cache
|
||||||
|
key: ${{ runner.os }}-frontend-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
|
||||||
|
- name: Re-link Angular CLI
|
||||||
|
run: cd src-ui && pnpm link @angular/cli
|
||||||
|
- name: Install dependencies
|
||||||
|
run: cd src-ui && pnpm install --no-frozen-lockfile
|
||||||
|
- name: Run Playwright E2E tests
|
||||||
|
run: cd src-ui && pnpm exec playwright test --shard ${{ matrix.shard-index }}/${{ matrix.shard-count }}
|
||||||
|
bundle-analysis:
|
||||||
|
name: Bundle Analysis
|
||||||
|
needs: [unit-tests, e2e-tests]
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
- name: Use Node.js 20
|
||||||
|
uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: 20.x
|
||||||
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
|
||||||
|
- name: Cache frontend dependencies
|
||||||
|
uses: actions/cache@v5
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.pnpm-store
|
||||||
|
~/.cache
|
||||||
|
key: ${{ runner.os }}-frontend-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
|
||||||
|
- name: Re-link Angular CLI
|
||||||
|
run: cd src-ui && pnpm link @angular/cli
|
||||||
|
- name: Build and analyze
|
||||||
|
env:
|
||||||
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
run: cd src-ui && pnpm run build --configuration=production
|
||||||
24
.github/workflows/ci-lint.yml
vendored
Normal file
24
.github/workflows/ci-lint.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
name: Lint
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches-ignore:
|
||||||
|
- 'translations**'
|
||||||
|
pull_request:
|
||||||
|
branches-ignore:
|
||||||
|
- 'translations**'
|
||||||
|
concurrency:
|
||||||
|
group: lint-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
jobs:
|
||||||
|
pre-commit:
|
||||||
|
name: Pre-commit Checks
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: Install Python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: "3.11"
|
||||||
|
- name: Run pre-commit
|
||||||
|
uses: pre-commit/action@v3.0.1
|
||||||
237
.github/workflows/ci-release.yml
vendored
Normal file
237
.github/workflows/ci-release.yml
vendored
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
name: Release
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||||
|
- 'v[0-9]+.[0-9]+.[0-9]+-beta.rc[0-9]+'
|
||||||
|
concurrency:
|
||||||
|
group: release-${{ github.ref }}
|
||||||
|
cancel-in-progress: false
|
||||||
|
env:
|
||||||
|
DEFAULT_UV_VERSION: "0.9.x"
|
||||||
|
DEFAULT_PYTHON_VERSION: "3.11"
|
||||||
|
jobs:
|
||||||
|
wait-for-docker:
|
||||||
|
name: Wait for Docker Build
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Wait for Docker build
|
||||||
|
uses: lewagon/wait-on-check-action@v1.4.1
|
||||||
|
with:
|
||||||
|
ref: ${{ github.sha }}
|
||||||
|
check-name: 'Build Docker Image'
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
wait-interval: 60
|
||||||
|
build-release:
|
||||||
|
name: Build Release
|
||||||
|
needs: wait-for-docker
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
# ---- Frontend Build ----
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
- name: Use Node.js 20
|
||||||
|
uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: 20.x
|
||||||
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
|
||||||
|
- name: Install frontend dependencies
|
||||||
|
run: cd src-ui && pnpm install
|
||||||
|
- name: Build frontend
|
||||||
|
run: cd src-ui && pnpm run build --configuration production
|
||||||
|
# ---- Backend Setup ----
|
||||||
|
- name: Set up Python
|
||||||
|
id: setup-python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v7
|
||||||
|
with:
|
||||||
|
version: ${{ env.DEFAULT_UV_VERSION }}
|
||||||
|
enable-cache: true
|
||||||
|
python-version: ${{ steps.setup-python.outputs.python-version }}
|
||||||
|
- name: Install Python dependencies
|
||||||
|
run: |
|
||||||
|
uv sync --python ${{ steps.setup-python.outputs.python-version }} --dev --frozen
|
||||||
|
- name: Install system dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -qq --no-install-recommends gettext liblept5
|
||||||
|
# ---- Build Documentation ----
|
||||||
|
- name: Build documentation
|
||||||
|
run: |
|
||||||
|
uv run \
|
||||||
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
|
--dev \
|
||||||
|
--frozen \
|
||||||
|
mkdocs build --config-file ./mkdocs.yml
|
||||||
|
# ---- Prepare Release ----
|
||||||
|
- name: Generate requirements file
|
||||||
|
run: |
|
||||||
|
uv export --quiet --no-dev --all-extras --format requirements-txt --output-file requirements.txt
|
||||||
|
- name: Compile messages
|
||||||
|
run: |
|
||||||
|
cd src/
|
||||||
|
uv run \
|
||||||
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
|
manage.py compilemessages
|
||||||
|
- name: Collect static files
|
||||||
|
run: |
|
||||||
|
cd src/
|
||||||
|
uv run \
|
||||||
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
|
manage.py collectstatic --no-input --clear
|
||||||
|
- name: Assemble release package
|
||||||
|
run: |
|
||||||
|
mkdir -p dist/paperless-ngx/scripts
|
||||||
|
|
||||||
|
for file_name in .dockerignore \
|
||||||
|
.env \
|
||||||
|
Dockerfile \
|
||||||
|
pyproject.toml \
|
||||||
|
uv.lock \
|
||||||
|
requirements.txt \
|
||||||
|
LICENSE \
|
||||||
|
README.md \
|
||||||
|
paperless.conf.example
|
||||||
|
do
|
||||||
|
cp --verbose ${file_name} dist/paperless-ngx/
|
||||||
|
done
|
||||||
|
mv dist/paperless-ngx/paperless.conf.example dist/paperless-ngx/paperless.conf
|
||||||
|
|
||||||
|
cp --recursive docker/ dist/paperless-ngx/docker
|
||||||
|
cp scripts/*.service scripts/*.sh scripts/*.socket dist/paperless-ngx/scripts/
|
||||||
|
cp --recursive src/ dist/paperless-ngx/src
|
||||||
|
cp --recursive site/ dist/paperless-ngx/docs
|
||||||
|
mv static dist/paperless-ngx/
|
||||||
|
|
||||||
|
find dist/paperless-ngx -name "__pycache__" -type d -exec rm -rf {} +
|
||||||
|
- name: Create release archive
|
||||||
|
run: |
|
||||||
|
cd dist
|
||||||
|
sudo chown -R 1000:1000 paperless-ngx/
|
||||||
|
tar -cJf paperless-ngx.tar.xz paperless-ngx/
|
||||||
|
- name: Upload release artifact
|
||||||
|
uses: actions/upload-artifact@v6
|
||||||
|
with:
|
||||||
|
name: release
|
||||||
|
path: dist/paperless-ngx.tar.xz
|
||||||
|
retention-days: 7
|
||||||
|
publish-release:
|
||||||
|
name: Publish Release
|
||||||
|
needs: build-release
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
outputs:
|
||||||
|
prerelease: ${{ steps.get-version.outputs.prerelease }}
|
||||||
|
changelog: ${{ steps.create-release.outputs.body }}
|
||||||
|
version: ${{ steps.get-version.outputs.version }}
|
||||||
|
steps:
|
||||||
|
- name: Download release artifact
|
||||||
|
uses: actions/download-artifact@v7
|
||||||
|
with:
|
||||||
|
name: release
|
||||||
|
path: ./
|
||||||
|
- name: Get version info
|
||||||
|
id: get-version
|
||||||
|
run: |
|
||||||
|
echo "version=${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
||||||
|
if [[ "${{ github.ref_name }}" == *"-beta.rc"* ]]; then
|
||||||
|
echo "prerelease=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "prerelease=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
- name: Create release and changelog
|
||||||
|
id: create-release
|
||||||
|
uses: release-drafter/release-drafter@v6
|
||||||
|
with:
|
||||||
|
name: Paperless-ngx ${{ steps.get-version.outputs.version }}
|
||||||
|
tag: ${{ steps.get-version.outputs.version }}
|
||||||
|
version: ${{ steps.get-version.outputs.version }}
|
||||||
|
prerelease: ${{ steps.get-version.outputs.prerelease }}
|
||||||
|
publish: true
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Upload release archive
|
||||||
|
uses: shogo82148/actions-upload-release-asset@v1
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
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
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Append changelog to docs (only on non-prerelease)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
append-changelog:
|
||||||
|
name: Append Changelog
|
||||||
|
needs: publish-release
|
||||||
|
if: needs.publish-release.outputs.prerelease == 'false'
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
with:
|
||||||
|
ref: main
|
||||||
|
- name: Set up Python
|
||||||
|
id: setup-python
|
||||||
|
uses: actions/setup-python@v6
|
||||||
|
with:
|
||||||
|
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v7
|
||||||
|
with:
|
||||||
|
version: ${{ env.DEFAULT_UV_VERSION }}
|
||||||
|
enable-cache: true
|
||||||
|
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
||||||
|
- name: Update changelog
|
||||||
|
working-directory: docs
|
||||||
|
run: |
|
||||||
|
git branch ${{ needs.publish-release.outputs.version }}-changelog
|
||||||
|
git checkout ${{ needs.publish-release.outputs.version }}-changelog
|
||||||
|
|
||||||
|
echo -e "# Changelog\n\n${{ needs.publish-release.outputs.changelog }}\n" > changelog-new.md
|
||||||
|
|
||||||
|
echo "Manually linking usernames"
|
||||||
|
sed -i -r 's|@([a-zA-Z0-9_]+) \(\[#|[@\1](https://github.com/\1) ([#|g' changelog-new.md
|
||||||
|
|
||||||
|
echo "Removing unneeded comment tags"
|
||||||
|
sed -i -r 's|@<!---->|@|g' changelog-new.md
|
||||||
|
|
||||||
|
CURRENT_CHANGELOG=$(tail --lines +2 changelog.md)
|
||||||
|
echo -e "$CURRENT_CHANGELOG" >> changelog-new.md
|
||||||
|
mv changelog-new.md changelog.md
|
||||||
|
|
||||||
|
uv run \
|
||||||
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
|
--dev \
|
||||||
|
pre-commit run --files changelog.md || true
|
||||||
|
|
||||||
|
git config --global user.name "github-actions"
|
||||||
|
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
|
git commit -am "Changelog ${{ needs.publish-release.outputs.version }} - GHA"
|
||||||
|
git push origin ${{ needs.publish-release.outputs.version }}-changelog
|
||||||
|
- name: Create pull request
|
||||||
|
uses: actions/github-script@v8
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const { repo, owner } = context.repo;
|
||||||
|
const result = await github.rest.pulls.create({
|
||||||
|
title: 'Documentation: Add ${{ needs.publish-release.outputs.version }} changelog',
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
head: '${{ needs.publish-release.outputs.version }}-changelog',
|
||||||
|
base: 'main',
|
||||||
|
body: 'This PR is auto-generated by CI.'
|
||||||
|
});
|
||||||
|
github.rest.issues.addLabels({
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
issue_number: result.data.number,
|
||||||
|
labels: ['documentation', 'skip-changelog']
|
||||||
|
});
|
||||||
693
.github/workflows/ci.yml
vendored
693
.github/workflows/ci.yml
vendored
@@ -1,693 +0,0 @@
|
|||||||
name: ci
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
# https://semver.org/#spec-item-2
|
|
||||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
|
||||||
# https://semver.org/#spec-item-9
|
|
||||||
- 'v[0-9]+.[0-9]+.[0-9]+-beta.rc[0-9]+'
|
|
||||||
branches-ignore:
|
|
||||||
- 'translations**'
|
|
||||||
pull_request:
|
|
||||||
branches-ignore:
|
|
||||||
- 'translations**'
|
|
||||||
env:
|
|
||||||
DEFAULT_UV_VERSION: "0.9.x"
|
|
||||||
# This is the default version of Python to use in most steps which aren't specific
|
|
||||||
DEFAULT_PYTHON_VERSION: "3.11"
|
|
||||||
NLTK_DATA: "/usr/share/nltk_data"
|
|
||||||
jobs:
|
|
||||||
detect-duplicate:
|
|
||||||
name: Detect Duplicate Run
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
outputs:
|
|
||||||
should_run: ${{ steps.check.outputs.should_run }}
|
|
||||||
steps:
|
|
||||||
- name: Check if workflow should run
|
|
||||||
id: check
|
|
||||||
uses: actions/github-script@v8
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
script: |
|
|
||||||
if (context.eventName !== 'push') {
|
|
||||||
core.info('Not a push event; running workflow.');
|
|
||||||
core.setOutput('should_run', 'true');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ref = context.ref || '';
|
|
||||||
if (!ref.startsWith('refs/heads/')) {
|
|
||||||
core.info('Push is not to a branch; running workflow.');
|
|
||||||
core.setOutput('should_run', 'true');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const branch = ref.substring('refs/heads/'.length);
|
|
||||||
const { owner, repo } = context.repo;
|
|
||||||
const prs = await github.paginate(github.rest.pulls.list, {
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
state: 'open',
|
|
||||||
head: `${owner}:${branch}`,
|
|
||||||
per_page: 100,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (prs.length === 0) {
|
|
||||||
core.info(`No open PR found for ${branch}; running workflow.`);
|
|
||||||
core.setOutput('should_run', 'true');
|
|
||||||
} else {
|
|
||||||
core.info(`Found ${prs.length} open PR(s) for ${branch}; skipping duplicate push run.`);
|
|
||||||
core.setOutput('should_run', 'false');
|
|
||||||
}
|
|
||||||
pre-commit:
|
|
||||||
needs:
|
|
||||||
- detect-duplicate
|
|
||||||
if: needs.detect-duplicate.outputs.should_run == 'true'
|
|
||||||
name: Linting Checks
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: Install python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
|
||||||
- name: Check files
|
|
||||||
uses: pre-commit/action@v3.0.1
|
|
||||||
documentation:
|
|
||||||
name: "Build & Deploy Documentation"
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs:
|
|
||||||
- pre-commit
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: Set up Python
|
|
||||||
id: setup-python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
|
||||||
- name: Install uv
|
|
||||||
uses: astral-sh/setup-uv@v7
|
|
||||||
with:
|
|
||||||
version: ${{ env.DEFAULT_UV_VERSION }}
|
|
||||||
enable-cache: true
|
|
||||||
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: |
|
|
||||||
uv sync --python ${{ steps.setup-python.outputs.python-version }} --dev --frozen
|
|
||||||
- name: Make documentation
|
|
||||||
run: |
|
|
||||||
uv run \
|
|
||||||
--python ${{ steps.setup-python.outputs.python-version }} \
|
|
||||||
--dev \
|
|
||||||
--frozen \
|
|
||||||
mkdocs build --config-file ./mkdocs.yml
|
|
||||||
- name: Deploy documentation
|
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
||||||
run: |
|
|
||||||
echo "docs.paperless-ngx.com" > "${{ github.workspace }}/docs/CNAME"
|
|
||||||
git config --global user.name "${{ github.actor }}"
|
|
||||||
git config --global user.email "${{ github.actor }}@users.noreply.github.com"
|
|
||||||
uv run \
|
|
||||||
--python ${{ steps.setup-python.outputs.python-version }} \
|
|
||||||
--dev \
|
|
||||||
--frozen \
|
|
||||||
mkdocs gh-deploy --force --no-history
|
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-artifact@v6
|
|
||||||
with:
|
|
||||||
name: documentation
|
|
||||||
path: site/
|
|
||||||
retention-days: 7
|
|
||||||
tests-backend:
|
|
||||||
name: "Backend Tests (Python ${{ matrix.python-version }})"
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs:
|
|
||||||
- pre-commit
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
python-version: ['3.10', '3.11', '3.12']
|
|
||||||
fail-fast: false
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: Start containers
|
|
||||||
run: |
|
|
||||||
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml pull --quiet
|
|
||||||
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml up --detach
|
|
||||||
- name: Set up Python
|
|
||||||
id: setup-python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: "${{ matrix.python-version }}"
|
|
||||||
- name: Install uv
|
|
||||||
uses: astral-sh/setup-uv@v7
|
|
||||||
with:
|
|
||||||
version: ${{ env.DEFAULT_UV_VERSION }}
|
|
||||||
enable-cache: true
|
|
||||||
python-version: ${{ steps.setup-python.outputs.python-version }}
|
|
||||||
- name: Install system dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update -qq
|
|
||||||
sudo apt-get install -qq --no-install-recommends unpaper tesseract-ocr imagemagick ghostscript libzbar0 poppler-utils
|
|
||||||
- name: Configure ImageMagick
|
|
||||||
run: |
|
|
||||||
sudo cp docker/rootfs/etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-6/policy.xml
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: |
|
|
||||||
uv sync \
|
|
||||||
--python ${{ steps.setup-python.outputs.python-version }} \
|
|
||||||
--group testing \
|
|
||||||
--frozen
|
|
||||||
- name: List installed Python dependencies
|
|
||||||
run: |
|
|
||||||
uv pip list
|
|
||||||
- name: Install or update NLTK dependencies
|
|
||||||
run: uv run python -m nltk.downloader punkt punkt_tab snowball_data stopwords -d ${{ env.NLTK_DATA }}
|
|
||||||
- name: Tests
|
|
||||||
env:
|
|
||||||
NLTK_DATA: ${{ env.NLTK_DATA }}
|
|
||||||
PAPERLESS_CI_TEST: 1
|
|
||||||
# Enable paperless_mail testing against real server
|
|
||||||
PAPERLESS_MAIL_TEST_HOST: ${{ secrets.TEST_MAIL_HOST }}
|
|
||||||
PAPERLESS_MAIL_TEST_USER: ${{ secrets.TEST_MAIL_USER }}
|
|
||||||
PAPERLESS_MAIL_TEST_PASSWD: ${{ secrets.TEST_MAIL_PASSWD }}
|
|
||||||
run: |
|
|
||||||
uv run \
|
|
||||||
--python ${{ steps.setup-python.outputs.python-version }} \
|
|
||||||
--dev \
|
|
||||||
--frozen \
|
|
||||||
pytest
|
|
||||||
- name: Upload backend test results to Codecov
|
|
||||||
if: always()
|
|
||||||
uses: codecov/codecov-action@v5
|
|
||||||
with:
|
|
||||||
flags: backend-python-${{ matrix.python-version }}
|
|
||||||
files: junit.xml
|
|
||||||
report_type: test_results
|
|
||||||
- name: Upload backend coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v5
|
|
||||||
with:
|
|
||||||
flags: backend-python-${{ matrix.python-version }}
|
|
||||||
files: coverage.xml
|
|
||||||
- name: Stop containers
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml logs
|
|
||||||
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml down
|
|
||||||
install-frontend-dependencies:
|
|
||||||
name: "Install Frontend Dependencies"
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs:
|
|
||||||
- pre-commit
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 10
|
|
||||||
- name: Use Node.js 20
|
|
||||||
uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: 20.x
|
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
|
|
||||||
- name: Cache frontend dependencies
|
|
||||||
id: cache-frontend-deps
|
|
||||||
uses: actions/cache@v5
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.pnpm-store
|
|
||||||
~/.cache
|
|
||||||
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
|
|
||||||
- name: Install dependencies
|
|
||||||
run: cd src-ui && pnpm install
|
|
||||||
tests-frontend:
|
|
||||||
name: "Frontend Unit Tests (Node ${{ matrix.node-version }} - ${{ matrix.shard-index }}/${{ matrix.shard-count }})"
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs:
|
|
||||||
- install-frontend-dependencies
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
node-version: [20.x]
|
|
||||||
shard-index: [1, 2, 3, 4]
|
|
||||||
shard-count: [4]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 10
|
|
||||||
- name: Use Node.js 20
|
|
||||||
uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: 20.x
|
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
|
|
||||||
- name: Cache frontend dependencies
|
|
||||||
id: cache-frontend-deps
|
|
||||||
uses: actions/cache@v5
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.pnpm-store
|
|
||||||
~/.cache
|
|
||||||
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
|
|
||||||
- name: Re-link Angular cli
|
|
||||||
run: cd src-ui && pnpm link @angular/cli
|
|
||||||
- name: Linting checks
|
|
||||||
run: cd src-ui && pnpm run lint
|
|
||||||
- name: Run Jest unit tests
|
|
||||||
run: cd src-ui && pnpm run test --max-workers=2 --shard=${{ matrix.shard-index }}/${{ matrix.shard-count }}
|
|
||||||
- name: Upload frontend test results to Codecov
|
|
||||||
if: always()
|
|
||||||
uses: codecov/codecov-action@v5
|
|
||||||
with:
|
|
||||||
flags: frontend-node-${{ matrix.node-version }}
|
|
||||||
directory: src-ui/
|
|
||||||
report_type: test_results
|
|
||||||
- name: Upload frontend coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v5
|
|
||||||
with:
|
|
||||||
flags: frontend-node-${{ matrix.node-version }}
|
|
||||||
directory: src-ui/coverage/
|
|
||||||
tests-frontend-e2e:
|
|
||||||
name: "Frontend E2E Tests (Node ${{ matrix.node-version }} - ${{ matrix.shard-index }}/${{ matrix.shard-count }})"
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
container: mcr.microsoft.com/playwright:v1.57.0-noble
|
|
||||||
needs:
|
|
||||||
- install-frontend-dependencies
|
|
||||||
env:
|
|
||||||
PLAYWRIGHT_BROWSERS_PATH: /ms-playwright
|
|
||||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
node-version: [20.x]
|
|
||||||
shard-index: [1, 2]
|
|
||||||
shard-count: [2]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 10
|
|
||||||
- name: Use Node.js 20
|
|
||||||
uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: 20.x
|
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
|
|
||||||
- name: Cache frontend dependencies
|
|
||||||
id: cache-frontend-deps
|
|
||||||
uses: actions/cache@v5
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.pnpm-store
|
|
||||||
~/.cache
|
|
||||||
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
|
|
||||||
- name: Re-link Angular cli
|
|
||||||
run: cd src-ui && pnpm link @angular/cli
|
|
||||||
- name: Install dependencies
|
|
||||||
run: cd src-ui && pnpm install --no-frozen-lockfile
|
|
||||||
- name: Run Playwright e2e tests
|
|
||||||
run: cd src-ui && pnpm exec playwright test --shard ${{ matrix.shard-index }}/${{ matrix.shard-count }}
|
|
||||||
frontend-bundle-analysis:
|
|
||||||
name: "Frontend Bundle Analysis"
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs:
|
|
||||||
- tests-frontend
|
|
||||||
- tests-frontend-e2e
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
- name: Install pnpm
|
|
||||||
uses: pnpm/action-setup@v4
|
|
||||||
with:
|
|
||||||
version: 10
|
|
||||||
- name: Use Node.js 20
|
|
||||||
uses: actions/setup-node@v6
|
|
||||||
with:
|
|
||||||
node-version: 20.x
|
|
||||||
cache: 'pnpm'
|
|
||||||
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
|
|
||||||
- name: Cache frontend dependencies
|
|
||||||
id: cache-frontend-deps
|
|
||||||
uses: actions/cache@v5
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
~/.pnpm-store
|
|
||||||
~/.cache
|
|
||||||
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/package-lock.json') }}
|
|
||||||
- name: Re-link Angular cli
|
|
||||||
run: cd src-ui && pnpm link @angular/cli
|
|
||||||
- name: Build frontend and upload analysis
|
|
||||||
env:
|
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
run: cd src-ui && pnpm run build --configuration=production
|
|
||||||
build-docker-image:
|
|
||||||
name: Build Docker image for ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }}
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
if: (github.event_name == 'push' && (startsWith(github.ref, 'refs/heads/feature-') || startsWith(github.ref, 'refs/heads/fix-') || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/beta' || contains(github.ref, 'beta.rc') || startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/heads/l10n_'))) || (github.event_name == 'pull_request' && (startsWith(github.head_ref, 'feature-') || startsWith(github.head_ref, 'fix-') || github.head_ref == 'dev' || github.head_ref == 'beta' || contains(github.head_ref, 'beta.rc') || startsWith(github.head_ref, 'l10n_')))
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-build-docker-image-${{ github.ref_name }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
needs:
|
|
||||||
- tests-backend
|
|
||||||
- tests-frontend
|
|
||||||
- tests-frontend-e2e
|
|
||||||
steps:
|
|
||||||
- name: Prepare build variables
|
|
||||||
id: build-vars
|
|
||||||
uses: actions/github-script@v8
|
|
||||||
with:
|
|
||||||
result-encoding: string
|
|
||||||
script: |
|
|
||||||
const isPR = context.eventName === 'pull_request';
|
|
||||||
const defaultRefName = context.ref.replace('refs/heads/', '');
|
|
||||||
const headRef = isPR ? context.payload.pull_request.head.ref : defaultRefName;
|
|
||||||
const buildRef = isPR ? `refs/heads/${headRef}` : context.ref;
|
|
||||||
const buildCacheKey = headRef.split('/').join('-');
|
|
||||||
const canPush = context.eventName === 'push' || (isPR && context.payload.pull_request.head.repo.full_name === `${context.repo.owner}/${context.repo.repo}`);
|
|
||||||
|
|
||||||
core.setOutput('build-ref', buildRef);
|
|
||||||
core.setOutput('build-ref-name', headRef);
|
|
||||||
core.setOutput('build-cache-key', buildCacheKey);
|
|
||||||
core.setOutput('can-push', canPush ? 'true' : 'false');
|
|
||||||
- name: Check pushing to Docker Hub
|
|
||||||
id: push-other-places
|
|
||||||
# Only push to Dockerhub from the main repo AND the ref is either:
|
|
||||||
# main
|
|
||||||
# dev
|
|
||||||
# beta
|
|
||||||
# a tag
|
|
||||||
# Otherwise forks would require a Docker Hub account and secrets setup
|
|
||||||
env:
|
|
||||||
BUILD_REF: ${{ steps.build-vars.outputs.build-ref }}
|
|
||||||
BUILD_REF_NAME: ${{ steps.build-vars.outputs.build-ref-name }}
|
|
||||||
run: |
|
|
||||||
if [[ ${{ github.repository_owner }} == "paperless-ngx" && ( "$BUILD_REF_NAME" == "dev" || "$BUILD_REF_NAME" == "beta" || $BUILD_REF == refs/tags/v* || $BUILD_REF == *beta.rc* ) ]] ; then
|
|
||||||
echo "Enabling DockerHub image push"
|
|
||||||
echo "enable=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "Not pushing to DockerHub"
|
|
||||||
echo "enable=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
- name: Set ghcr repository name
|
|
||||||
id: set-ghcr-repository
|
|
||||||
run: |
|
|
||||||
ghcr_name=$(echo "${{ github.repository }}" | awk '{ print tolower($0) }')
|
|
||||||
echo "Name is ${ghcr_name}"
|
|
||||||
echo "ghcr-repository=${ghcr_name}" >> $GITHUB_OUTPUT
|
|
||||||
- name: Gather Docker metadata
|
|
||||||
id: docker-meta
|
|
||||||
uses: docker/metadata-action@v5
|
|
||||||
with:
|
|
||||||
images: |
|
|
||||||
ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}
|
|
||||||
name=paperlessngx/paperless-ngx,enable=${{ steps.push-other-places.outputs.enable }}
|
|
||||||
name=quay.io/paperlessngx/paperless-ngx,enable=${{ steps.push-other-places.outputs.enable }}
|
|
||||||
tags: |
|
|
||||||
# Tag branches with branch name
|
|
||||||
type=ref,event=branch
|
|
||||||
# Pull requests need a sanitized branch tag for pushing images
|
|
||||||
type=raw,value=${{ steps.build-vars.outputs.build-cache-key }},enable=${{ github.event_name == 'pull_request' }}
|
|
||||||
# Process semver tags
|
|
||||||
# For a tag x.y.z or vX.Y.Z, output an x.y.z and x.y image tag
|
|
||||||
type=semver,pattern={{version}}
|
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
# If https://github.com/docker/buildx/issues/1044 is resolved,
|
|
||||||
# the append input with a native arm64 arch could be used to
|
|
||||||
# significantly speed up building
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
with:
|
|
||||||
platforms: arm64
|
|
||||||
- name: Login to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: ghcr.io
|
|
||||||
username: ${{ github.actor }}
|
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
# Don't attempt to login if not pushing to Docker Hub
|
|
||||||
if: steps.push-other-places.outputs.enable == 'true'
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
- name: Login to Quay.io
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
# Don't attempt to login if not pushing to Quay.io
|
|
||||||
if: steps.push-other-places.outputs.enable == 'true'
|
|
||||||
with:
|
|
||||||
registry: quay.io
|
|
||||||
username: ${{ secrets.QUAY_USERNAME }}
|
|
||||||
password: ${{ secrets.QUAY_ROBOT_TOKEN }}
|
|
||||||
- name: Build and push
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
file: ./Dockerfile
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: ${{ steps.build-vars.outputs.can-push == 'true' }}
|
|
||||||
tags: ${{ steps.docker-meta.outputs.tags }}
|
|
||||||
labels: ${{ steps.docker-meta.outputs.labels }}
|
|
||||||
build-args: |
|
|
||||||
PNGX_TAG_VERSION=${{ steps.docker-meta.outputs.version }}
|
|
||||||
# Get cache layers from this branch, then dev
|
|
||||||
# This allows new branches to get at least some cache benefits, generally from dev
|
|
||||||
cache-from: |
|
|
||||||
type=registry,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:${{ steps.build-vars.outputs.build-cache-key }}
|
|
||||||
type=registry,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:dev
|
|
||||||
cache-to: ${{ steps.build-vars.outputs.can-push == 'true' && format('type=registry,mode=max,ref=ghcr.io/{0}/builder/cache/app:{1}', steps.set-ghcr-repository.outputs.ghcr-repository, steps.build-vars.outputs.build-cache-key) || '' }}
|
|
||||||
- name: Inspect image
|
|
||||||
if: steps.build-vars.outputs.can-push == 'true'
|
|
||||||
run: |
|
|
||||||
docker buildx imagetools inspect ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
|
||||||
- name: Export frontend artifact from docker
|
|
||||||
if: steps.build-vars.outputs.can-push == 'true'
|
|
||||||
run: |
|
|
||||||
docker create --name frontend-extract ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
|
||||||
docker cp frontend-extract:/usr/src/paperless/src/documents/static/frontend src/documents/static/frontend/
|
|
||||||
- name: Upload frontend artifact
|
|
||||||
if: steps.build-vars.outputs.can-push == 'true'
|
|
||||||
uses: actions/upload-artifact@v6
|
|
||||||
with:
|
|
||||||
name: frontend-compiled
|
|
||||||
path: src/documents/static/frontend/
|
|
||||||
retention-days: 7
|
|
||||||
build-release:
|
|
||||||
name: "Build Release"
|
|
||||||
needs:
|
|
||||||
- build-docker-image
|
|
||||||
- documentation
|
|
||||||
if: github.event_name == 'push'
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
- name: Set up Python
|
|
||||||
id: setup-python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
|
||||||
- name: Install uv
|
|
||||||
uses: astral-sh/setup-uv@v7
|
|
||||||
with:
|
|
||||||
version: ${{ env.DEFAULT_UV_VERSION }}
|
|
||||||
enable-cache: true
|
|
||||||
python-version: ${{ steps.setup-python.outputs.python-version }}
|
|
||||||
- name: Install Python dependencies
|
|
||||||
run: |
|
|
||||||
uv sync --python ${{ steps.setup-python.outputs.python-version }} --dev --frozen
|
|
||||||
- name: Install system dependencies
|
|
||||||
run: |
|
|
||||||
sudo apt-get update -qq
|
|
||||||
sudo apt-get install -qq --no-install-recommends gettext liblept5
|
|
||||||
- name: Download frontend artifact
|
|
||||||
uses: actions/download-artifact@v7
|
|
||||||
with:
|
|
||||||
name: frontend-compiled
|
|
||||||
path: src/documents/static/frontend/
|
|
||||||
- name: Download documentation artifact
|
|
||||||
uses: actions/download-artifact@v7
|
|
||||||
with:
|
|
||||||
name: documentation
|
|
||||||
path: docs/_build/html/
|
|
||||||
- name: Generate requirements file
|
|
||||||
run: |
|
|
||||||
uv export --quiet --no-dev --all-extras --format requirements-txt --output-file requirements.txt
|
|
||||||
- name: Compile messages
|
|
||||||
run: |
|
|
||||||
cd src/
|
|
||||||
uv run \
|
|
||||||
--python ${{ steps.setup-python.outputs.python-version }} \
|
|
||||||
manage.py compilemessages
|
|
||||||
- name: Collect static files
|
|
||||||
run: |
|
|
||||||
cd src/
|
|
||||||
uv run \
|
|
||||||
--python ${{ steps.setup-python.outputs.python-version }} \
|
|
||||||
manage.py collectstatic --no-input
|
|
||||||
- name: Move files
|
|
||||||
run: |
|
|
||||||
echo "Making dist folders"
|
|
||||||
for directory in dist \
|
|
||||||
dist/paperless-ngx \
|
|
||||||
dist/paperless-ngx/scripts;
|
|
||||||
do
|
|
||||||
mkdir --verbose --parents ${directory}
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Copying basic files"
|
|
||||||
for file_name in .dockerignore \
|
|
||||||
.env \
|
|
||||||
Dockerfile \
|
|
||||||
pyproject.toml \
|
|
||||||
uv.lock \
|
|
||||||
requirements.txt \
|
|
||||||
LICENSE \
|
|
||||||
README.md \
|
|
||||||
paperless.conf.example
|
|
||||||
do
|
|
||||||
cp --verbose ${file_name} dist/paperless-ngx/
|
|
||||||
done
|
|
||||||
mv --verbose dist/paperless-ngx/paperless.conf.example dist/paperless-ngx/paperless.conf
|
|
||||||
|
|
||||||
echo "Copying Docker related files"
|
|
||||||
cp --recursive docker/ dist/paperless-ngx/docker
|
|
||||||
|
|
||||||
echo "Copying startup scripts"
|
|
||||||
cp --verbose scripts/*.service scripts/*.sh scripts/*.socket dist/paperless-ngx/scripts/
|
|
||||||
|
|
||||||
echo "Copying source files"
|
|
||||||
cp --recursive src/ dist/paperless-ngx/src
|
|
||||||
echo "Copying documentation"
|
|
||||||
cp --recursive docs/_build/html/ dist/paperless-ngx/docs
|
|
||||||
|
|
||||||
mv --verbose static dist/paperless-ngx
|
|
||||||
- name: Make release package
|
|
||||||
run: |
|
|
||||||
echo "Creating release archive"
|
|
||||||
cd dist
|
|
||||||
sudo chown -R 1000:1000 paperless-ngx/
|
|
||||||
tar -cJf paperless-ngx.tar.xz paperless-ngx/
|
|
||||||
- name: Upload release artifact
|
|
||||||
uses: actions/upload-artifact@v6
|
|
||||||
with:
|
|
||||||
name: release
|
|
||||||
path: dist/paperless-ngx.tar.xz
|
|
||||||
retention-days: 7
|
|
||||||
publish-release:
|
|
||||||
name: "Publish Release"
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
outputs:
|
|
||||||
prerelease: ${{ steps.get_version.outputs.prerelease }}
|
|
||||||
changelog: ${{ steps.create-release.outputs.body }}
|
|
||||||
version: ${{ steps.get_version.outputs.version }}
|
|
||||||
needs:
|
|
||||||
- build-release
|
|
||||||
if: github.ref_type == 'tag' && (startsWith(github.ref_name, 'v') || contains(github.ref_name, '-beta.rc'))
|
|
||||||
steps:
|
|
||||||
- name: Download release artifact
|
|
||||||
uses: actions/download-artifact@v7
|
|
||||||
with:
|
|
||||||
name: release
|
|
||||||
path: ./
|
|
||||||
- name: Get version
|
|
||||||
id: get_version
|
|
||||||
run: |
|
|
||||||
echo "version=${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
|
||||||
if [[ ${{ contains(github.ref_name, '-beta.rc') }} == 'true' ]]; then
|
|
||||||
echo "prerelease=true" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "prerelease=false" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
- name: Create Release and Changelog
|
|
||||||
id: create-release
|
|
||||||
uses: release-drafter/release-drafter@v6
|
|
||||||
with:
|
|
||||||
name: Paperless-ngx ${{ steps.get_version.outputs.version }}
|
|
||||||
tag: ${{ 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: shogo82148/actions-upload-release-asset@v1
|
|
||||||
with:
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
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
|
|
||||||
append-changelog:
|
|
||||||
name: "Append Changelog"
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs:
|
|
||||||
- publish-release
|
|
||||||
if: needs.publish-release.outputs.prerelease == 'false'
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
with:
|
|
||||||
ref: main
|
|
||||||
- name: Set up Python
|
|
||||||
id: setup-python
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
|
||||||
- name: Install uv
|
|
||||||
uses: astral-sh/setup-uv@v7
|
|
||||||
with:
|
|
||||||
version: ${{ env.DEFAULT_UV_VERSION }}
|
|
||||||
enable-cache: true
|
|
||||||
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
|
||||||
- name: Append Changelog to docs
|
|
||||||
id: append-Changelog
|
|
||||||
working-directory: docs
|
|
||||||
run: |
|
|
||||||
git branch ${{ needs.publish-release.outputs.version }}-changelog
|
|
||||||
git checkout ${{ needs.publish-release.outputs.version }}-changelog
|
|
||||||
echo -e "# Changelog\n\n${{ needs.publish-release.outputs.changelog }}\n" > changelog-new.md
|
|
||||||
echo "Manually linking usernames"
|
|
||||||
sed -i -r 's|@([a-zA-Z0-9_]+) \(\[#|[@\1](https://github.com/\1) ([#|g' changelog-new.md
|
|
||||||
echo "Removing unneeded comment tags"
|
|
||||||
sed -i -r 's|@<!---->|@|g' changelog-new.md
|
|
||||||
CURRENT_CHANGELOG=`tail --lines +2 changelog.md`
|
|
||||||
echo -e "$CURRENT_CHANGELOG" >> changelog-new.md
|
|
||||||
mv changelog-new.md changelog.md
|
|
||||||
uv run \
|
|
||||||
--python ${{ steps.setup-python.outputs.python-version }} \
|
|
||||||
--dev \
|
|
||||||
pre-commit run --files changelog.md || true
|
|
||||||
git config --global user.name "github-actions"
|
|
||||||
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
||||||
git commit -am "Changelog ${{ needs.publish-release.outputs.version }} - GHA"
|
|
||||||
git push origin ${{ needs.publish-release.outputs.version }}-changelog
|
|
||||||
- name: Create Pull Request
|
|
||||||
uses: actions/github-script@v8
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
const { repo, owner } = context.repo;
|
|
||||||
const result = await github.rest.pulls.create({
|
|
||||||
title: 'Documentation: Add ${{ needs.publish-release.outputs.version }} changelog',
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
head: '${{ needs.publish-release.outputs.version }}-changelog',
|
|
||||||
base: 'main',
|
|
||||||
body: 'This PR is auto-generated by CI.'
|
|
||||||
});
|
|
||||||
github.rest.issues.addLabels({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
issue_number: result.data.number,
|
|
||||||
labels: ['documentation', 'skip-changelog']
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user