mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-27 10:59:27 -05:00
Compare commits
281 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7236b8b682 | ||
![]() |
a3b85c64ca | ||
![]() |
0cefdc8475 | ||
![]() |
915584551c | ||
![]() |
855c9aa28d | ||
![]() |
e277a8e1ea | ||
![]() |
6d8c507169 | ||
![]() |
00050f7c7b | ||
![]() |
5a278381e3 | ||
![]() |
af95963c5f | ||
![]() |
c724436fc4 | ||
![]() |
e288824963 | ||
![]() |
312bb743b9 | ||
![]() |
7436a97684 | ||
![]() |
cbaceb95af | ||
![]() |
2abf38f98e | ||
![]() |
b40e1f7d01 | ||
![]() |
15d4ac8ba2 | ||
![]() |
fcb7349e8e | ||
![]() |
648cfd9d05 | ||
![]() |
c3df7d3439 | ||
![]() |
a5cd545a1b | ||
![]() |
96227f785a | ||
![]() |
7f98c4b794 | ||
![]() |
d914a82dea | ||
![]() |
1a72efa3c9 | ||
![]() |
aa6c58103f | ||
![]() |
ba6976bdbb | ||
![]() |
7a1be6bff2 | ||
![]() |
c3bd587cbf | ||
![]() |
a57a3dbb30 | ||
![]() |
f52ebc7bf0 | ||
![]() |
abf910fd93 | ||
![]() |
1b0aa193bd | ||
![]() |
eac12fe031 | ||
![]() |
62f46b706e | ||
![]() |
df5af5c8ad | ||
![]() |
67a97ffc4d | ||
![]() |
45b39f36d6 | ||
![]() |
a339853bc5 | ||
![]() |
6c2e06d40b | ||
![]() |
2d6a4d108f | ||
![]() |
703db0f01f | ||
![]() |
8b5d6bf3db | ||
![]() |
2d93e95848 | ||
![]() |
ab8c75958d | ||
![]() |
9db3923d35 | ||
![]() |
e2860ed36d | ||
![]() |
82a5680217 | ||
![]() |
588fd0207d | ||
![]() |
6dea158de9 | ||
![]() |
d956269d5f | ||
![]() |
f269919410 | ||
![]() |
5f00066dff | ||
![]() |
705f542129 | ||
![]() |
f036292b72 | ||
![]() |
f8a43d5dab | ||
![]() |
53c106d448 | ||
![]() |
0f37186c88 | ||
![]() |
0fb55f3ae8 | ||
![]() |
78822f6121 | ||
![]() |
2ee1d7540e | ||
![]() |
43b2527275 | ||
![]() |
248b573c03 | ||
![]() |
b9f7428f2f | ||
![]() |
e35dad81d9 | ||
![]() |
7d40eb2e24 | ||
![]() |
d2783a3fbe | ||
![]() |
8ad794e189 | ||
![]() |
358db10fe3 | ||
![]() |
556f47fe12 | ||
![]() |
0d5a2b4382 | ||
![]() |
c9bc9acd1a | ||
![]() |
e9e209d290 | ||
![]() |
2e593a0022 | ||
![]() |
3526a4cf23 | ||
![]() |
f4791cac2d | ||
![]() |
fdafd4eefb | ||
![]() |
87a8847a8d | ||
![]() |
7c31c79bbc | ||
![]() |
bf2a9b02c6 | ||
![]() |
348858780c | ||
![]() |
eb481ac1c0 | ||
![]() |
9a2d7a64ac | ||
![]() |
32a7f9cd5a | ||
![]() |
92431b2f4b | ||
![]() |
b4b2a92225 | ||
![]() |
fd45e81a83 | ||
![]() |
97d59dce9c | ||
![]() |
f3479d982c | ||
![]() |
b3ba673d9a | ||
![]() |
68b7427640 | ||
![]() |
9c68100dc0 | ||
![]() |
6e694ad9ff | ||
![]() |
5db511afdf | ||
![]() |
a8de26f88a | ||
![]() |
7a07f1e81d | ||
![]() |
92524ae97a | ||
![]() |
1c89f6da24 | ||
![]() |
d1a3e3b859 | ||
![]() |
79ae594d54 | ||
![]() |
f753f6dc46 | ||
![]() |
97fe5c4176 | ||
![]() |
1f5086164b | ||
![]() |
e60bd3a132 | ||
![]() |
b4047e73bb | ||
![]() |
4263d2196c | ||
![]() |
ac780134fb | ||
![]() |
5d6cfa7349 | ||
![]() |
3105317137 | ||
![]() |
1d9482acc3 | ||
![]() |
1456169d7f | ||
![]() |
22a6fe5e10 | ||
![]() |
caa3c13edd | ||
![]() |
24e863b298 | ||
![]() |
0c9d615f56 | ||
![]() |
4c49da9ece | ||
![]() |
a0c1a19263 | ||
![]() |
1f5d1b6f26 | ||
![]() |
3b19a727b8 | ||
![]() |
7146a5f4fc | ||
![]() |
6babc61ba2 | ||
![]() |
db5e54c6e5 | ||
![]() |
4ef5fbfb6e | ||
![]() |
b0390a92ea | ||
![]() |
70898a5064 | ||
![]() |
d07d425618 | ||
![]() |
1f60f4a636 | ||
![]() |
b29395cde7 | ||
![]() |
2f70d58219 | ||
![]() |
9944f81512 | ||
![]() |
f4413e0a08 | ||
![]() |
169aa8c8bd | ||
![]() |
94556a2607 | ||
![]() |
dcd50d5359 | ||
![]() |
376823598e | ||
![]() |
54bcbfa546 | ||
![]() |
5421e54cb0 | ||
![]() |
032bada221 | ||
![]() |
670ee6c5b0 | ||
![]() |
309fb199f2 | ||
![]() |
79328b1cec | ||
![]() |
5570d20625 | ||
![]() |
ba2cb1dec8 | ||
![]() |
4d15544a3e | ||
![]() |
955ff32dcd | ||
![]() |
b746b6f2d6 | ||
![]() |
b4b0f802e1 | ||
![]() |
5f16d5f5f1 | ||
![]() |
8db04398c7 | ||
![]() |
485dad01b7 | ||
![]() |
cf48f47a8c | ||
![]() |
f2667f5afa | ||
![]() |
d73118d226 | ||
![]() |
dd9e9a8c56 | ||
![]() |
76d363f22d | ||
![]() |
aaaa6c1393 | ||
![]() |
bed82215a0 | ||
![]() |
f8aaa5cb32 | ||
![]() |
1e489a0666 | ||
![]() |
edc7181843 | ||
![]() |
89e5c08a1f | ||
![]() |
0faa9e8865 | ||
![]() |
f205c4d0e2 | ||
![]() |
344b2bc0eb | ||
![]() |
817aad7c8b | ||
![]() |
d82555e644 | ||
![]() |
f3e6ed56b9 | ||
![]() |
780d1c67e9 | ||
![]() |
2b72397a4d | ||
![]() |
6c13ffaa01 | ||
![]() |
eb8e124971 | ||
![]() |
1bc77546eb | ||
![]() |
5a453653e2 | ||
![]() |
16f17829b6 | ||
![]() |
3cf1c04a83 | ||
![]() |
bc90ccc555 | ||
![]() |
90a332a02c | ||
![]() |
0098d1bdd5 | ||
![]() |
f6fef18a73 | ||
![]() |
6563ec6770 | ||
![]() |
755cf8619f | ||
![]() |
c6d389100c | ||
![]() |
20c4b65273 | ||
![]() |
86c94c7508 | ||
![]() |
798ece411e | ||
![]() |
654c9ca273 | ||
![]() |
628d85080f | ||
![]() |
865e9fe233 | ||
![]() |
0eb765c3e8 | ||
![]() |
ddeb741a85 | ||
![]() |
b9bcff22f8 | ||
![]() |
2d52226732 | ||
![]() |
ec34197b59 | ||
![]() |
edc0e6f859 | ||
![]() |
61cb5103ed | ||
![]() |
d364436817 | ||
![]() |
827fcba277 | ||
![]() |
90561857e8 | ||
![]() |
3104417076 | ||
![]() |
047f7c3619 | ||
![]() |
a548c32c1f | ||
![]() |
ea911e73c6 | ||
![]() |
6b7fb286f7 | ||
![]() |
b40479632b | ||
![]() |
c122c60d3f | ||
![]() |
4f08b5fa20 | ||
![]() |
3bf64ae7da | ||
![]() |
822c2d2d56 | ||
![]() |
98e0a934ac | ||
![]() |
ceffcd6360 | ||
![]() |
37442ff829 | ||
![]() |
de5f66b3a0 | ||
![]() |
e37096f66f | ||
![]() |
e49ecd4dfe | ||
![]() |
4718df271f | ||
![]() |
17bb3ebbf5 | ||
![]() |
5e00c1c676 | ||
![]() |
fc68f55d1a | ||
![]() |
a9ef7ff58e | ||
![]() |
518091f856 | ||
![]() |
feb30f36df | ||
![]() |
bbad36717f | ||
![]() |
329ef7aef3 | ||
![]() |
2b2115e5f0 | ||
![]() |
ba5705a54f | ||
![]() |
ea94626b82 | ||
![]() |
fdfea68576 | ||
![]() |
4e61c2b2e6 | ||
![]() |
7c959754a0 | ||
![]() |
fed16974dd | ||
![]() |
ea3303aa76 | ||
![]() |
1dc80f04cb | ||
![]() |
c316ae369b | ||
![]() |
d94b284815 | ||
![]() |
63bb3644f6 | ||
![]() |
6a8ec182fa | ||
![]() |
880f08599a | ||
![]() |
71472a6a82 | ||
![]() |
7f36163c3b | ||
![]() |
e560fa3be0 | ||
![]() |
b274665e21 | ||
![]() |
a499905605 | ||
![]() |
b8bdc10f25 | ||
![]() |
e08606af6e | ||
![]() |
52ab07c673 | ||
![]() |
046d8456e2 | ||
![]() |
3314c59828 | ||
![]() |
2103a499eb | ||
![]() |
7ab779e78a | ||
![]() |
49390c9427 | ||
![]() |
6f29d64325 | ||
![]() |
69541546ea | ||
![]() |
065724befb | ||
![]() |
e877beea4e | ||
![]() |
3e848e6e0f | ||
![]() |
2e5656e1ce | ||
![]() |
438650bf17 | ||
![]() |
7df0b621a5 | ||
![]() |
4cd755f641 | ||
![]() |
8597911d85 | ||
![]() |
befb80bddf | ||
![]() |
7af6983cab | ||
![]() |
16d6bb7334 | ||
![]() |
49b658a944 | ||
![]() |
e1d8680698 | ||
![]() |
ee72e2d1fd | ||
![]() |
e0ea4a4625 | ||
![]() |
c2a9ac332a | ||
![]() |
bf368aadd0 | ||
![]() |
54e72d5b60 | ||
![]() |
cf7422346a | ||
![]() |
5b8c9ef5fc | ||
![]() |
f56974f158 | ||
![]() |
427508edf1 | ||
![]() |
311b259cff | ||
![]() |
fce7b03324 | ||
![]() |
79956d6a7b | ||
![]() |
978b072bff | ||
![]() |
9c6f695dbf | ||
![]() |
0100fcbb23 |
.codecov.yml
.devcontainer
.dockerignore.editorconfig.github
.gitignore.pre-commit-config.yaml.python-version.ruff.tomlCODEOWNERSCONTRIBUTING.mdDockerfilePipfilePipfile.lockREADME.mddocker
compose
docker-compose.ci-test.ymldocker-compose.mariadb-tika.ymldocker-compose.mariadb.ymldocker-compose.portainer.ymldocker-compose.postgres-tika.ymldocker-compose.postgres.ymldocker-compose.sqlite-tika.ymldocker-compose.sqlite.yml
docker-entrypoint.shdocker-prepare.shenv-from-file.shflower-conditional.shinit-flow.drawio.pnginstall_management_commands.shmanagement_script.shpaperless_cmd.shrootfs/etc
ImageMagick-6
s6-overlay/s6-rc.d
init-complete
dependencies.d
init-custom-initinit-env-fileinit-foldersinit-migrationsinit-modify-userinit-search-indexinit-startinit-superuserinit-system-checksinit-tesseract-langsinit-wait-for-dbinit-wait-for-redis
runtypeupinit-custom-init
init-env-file
init-folders
init-migrations
init-modify-user
init-search-index
init-start
init-superuser
init-system-checks/dependencies.d
16
.codecov.yml
16
.codecov.yml
@ -1,18 +1,18 @@
|
|||||||
codecov:
|
codecov:
|
||||||
require_ci_to_pass: true
|
require_ci_to_pass: true
|
||||||
# https://docs.codecov.com/docs/flags#recommended-automatic-flag-management
|
# https://docs.codecov.com/docs/components
|
||||||
# Require each flag to have 1 upload before notification
|
component_management:
|
||||||
flag_management:
|
individual_components:
|
||||||
individual_flags:
|
- component_id: backend
|
||||||
- name: backend
|
|
||||||
paths:
|
paths:
|
||||||
- src/
|
- src/**
|
||||||
- name: frontend
|
- component_id: frontend
|
||||||
paths:
|
paths:
|
||||||
- src-ui/
|
- src-ui/**
|
||||||
# https://docs.codecov.com/docs/pull-request-comments
|
# https://docs.codecov.com/docs/pull-request-comments
|
||||||
# codecov will only comment if coverage changes
|
# codecov will only comment if coverage changes
|
||||||
comment:
|
comment:
|
||||||
|
layout: "header, diff, components, flags, files"
|
||||||
require_changes: true
|
require_changes: true
|
||||||
# https://docs.codecov.com/docs/javascript-bundle-analysis
|
# https://docs.codecov.com/docs/javascript-bundle-analysis
|
||||||
require_bundle_changes: true
|
require_bundle_changes: true
|
||||||
|
@ -76,18 +76,15 @@ RUN set -eux \
|
|||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES}
|
&& apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES}
|
||||||
|
|
||||||
ARG PYTHON_PACKAGES="\
|
ARG PYTHON_PACKAGES="ca-certificates"
|
||||||
python3 \
|
|
||||||
python3-pip \
|
|
||||||
python3-wheel \
|
|
||||||
pipenv \
|
|
||||||
ca-certificates"
|
|
||||||
|
|
||||||
RUN set -eux \
|
RUN set -eux \
|
||||||
echo "Installing python packages" \
|
echo "Installing python packages" \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get install --yes --quiet ${PYTHON_PACKAGES}
|
&& apt-get install --yes --quiet ${PYTHON_PACKAGES}
|
||||||
|
|
||||||
|
COPY --from=ghcr.io/astral-sh/uv:0.6 /uv /bin/uv
|
||||||
|
|
||||||
RUN set -eux \
|
RUN set -eux \
|
||||||
&& echo "Installing pre-built updates" \
|
&& echo "Installing pre-built updates" \
|
||||||
&& echo "Installing qpdf ${QPDF_VERSION}" \
|
&& echo "Installing qpdf ${QPDF_VERSION}" \
|
||||||
@ -123,13 +120,15 @@ RUN set -eux \
|
|||||||
WORKDIR /usr/src/paperless/src/docker/
|
WORKDIR /usr/src/paperless/src/docker/
|
||||||
|
|
||||||
COPY [ \
|
COPY [ \
|
||||||
"docker/imagemagick-policy.xml", \
|
"docker/rootfs/etc/ImageMagick-6/paperless-policy.xml", \
|
||||||
"./" \
|
"./" \
|
||||||
]
|
]
|
||||||
|
|
||||||
RUN set -eux \
|
RUN set -eux \
|
||||||
&& echo "Configuring ImageMagick" \
|
&& echo "Configuring ImageMagick" \
|
||||||
&& mv imagemagick-policy.xml /etc/ImageMagick-6/policy.xml
|
&& mv paperless-policy.xml /etc/ImageMagick-6/policy.xml
|
||||||
|
|
||||||
|
COPY --from=ghcr.io/astral-sh/uv:0.6 /uv /bin/uv
|
||||||
|
|
||||||
# Packages needed only for building a few quick Python
|
# Packages needed only for building a few quick Python
|
||||||
# dependencies
|
# dependencies
|
||||||
@ -140,18 +139,17 @@ ARG BUILD_PACKAGES="\
|
|||||||
libpq-dev \
|
libpq-dev \
|
||||||
# https://github.com/PyMySQL/mysqlclient#linux
|
# https://github.com/PyMySQL/mysqlclient#linux
|
||||||
default-libmysqlclient-dev \
|
default-libmysqlclient-dev \
|
||||||
pkg-config \
|
pkg-config"
|
||||||
pre-commit"
|
|
||||||
|
|
||||||
# hadolint ignore=DL3042
|
# hadolint ignore=DL3042
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip/,id=pip-cache \
|
RUN --mount=type=cache,target=/root/.cache/uv,id=pip-cache \
|
||||||
set -eux \
|
set -eux \
|
||||||
&& echo "Installing build system packages" \
|
&& echo "Installing build system packages" \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get install --yes --quiet ${BUILD_PACKAGES}
|
&& apt-get install --yes --quiet ${BUILD_PACKAGES}
|
||||||
|
|
||||||
RUN set -eux \
|
RUN set -eux \
|
||||||
&& npm update npm -g
|
&& npm update -g pnpm
|
||||||
|
|
||||||
# add users, setup scripts
|
# add users, setup scripts
|
||||||
# Mount the compiled frontend to expected location
|
# Mount the compiled frontend to expected location
|
||||||
@ -169,9 +167,6 @@ RUN set -eux \
|
|||||||
&& mkdir --parents --verbose /usr/src/paperless/paperless-ngx/.venv \
|
&& mkdir --parents --verbose /usr/src/paperless/paperless-ngx/.venv \
|
||||||
&& echo "Adjusting all permissions" \
|
&& echo "Adjusting all permissions" \
|
||||||
&& chown --from root:root --changes --recursive paperless:paperless /usr/src/paperless
|
&& chown --from root:root --changes --recursive paperless:paperless /usr/src/paperless
|
||||||
# && echo "Collecting static files" \
|
|
||||||
# && gosu paperless python3 manage.py collectstatic --clear --no-input --link \
|
|
||||||
# && gosu paperless python3 manage.py compilemessages
|
|
||||||
|
|
||||||
VOLUME ["/usr/src/paperless/paperless-ngx/data", \
|
VOLUME ["/usr/src/paperless/paperless-ngx/data", \
|
||||||
"/usr/src/paperless/paperless-ngx/media", \
|
"/usr/src/paperless/paperless-ngx/media", \
|
||||||
|
117
.devcontainer/README.md
Normal file
117
.devcontainer/README.md
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
# Paperless-ngx Development Environment
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Welcome to the Paperless-ngx development environment! This setup uses VSCode DevContainers to provide a consistent and seamless development experience.
|
||||||
|
|
||||||
|
### What are DevContainers?
|
||||||
|
|
||||||
|
DevContainers are a feature in VSCode that allows you to develop within a Docker container. This ensures that your development environment is consistent across different machines and setups. By defining a containerized environment, you can eliminate the "works on my machine" problem.
|
||||||
|
|
||||||
|
### Advantages of DevContainers
|
||||||
|
|
||||||
|
- **Consistency**: Same environment for all developers.
|
||||||
|
- **Isolation**: Separate development environment from your local machine.
|
||||||
|
- **Reproducibility**: Easily recreate the environment on any machine.
|
||||||
|
- **Pre-configured Tools**: Include all necessary tools and dependencies in the container.
|
||||||
|
|
||||||
|
## DevContainer Setup
|
||||||
|
|
||||||
|
The DevContainer configuration provides up all the necessary services for Paperless-ngx, including:
|
||||||
|
|
||||||
|
- Redis
|
||||||
|
- Gotenberg
|
||||||
|
- Tika
|
||||||
|
|
||||||
|
Data is stored using Docker volumes to ensure persistence across container restarts.
|
||||||
|
|
||||||
|
## Configuration Files
|
||||||
|
|
||||||
|
The setup includes debugging configurations (`launch.json`) and tasks (`tasks.json`) to help you manage and debug various parts of the project:
|
||||||
|
|
||||||
|
- **Backend Debugging:**
|
||||||
|
- `manage.py runserver`
|
||||||
|
- `manage.py document-consumer`
|
||||||
|
- `celery`
|
||||||
|
- **Maintenance Tasks:**
|
||||||
|
- Create superuser
|
||||||
|
- Run migrations
|
||||||
|
- Recreate virtual environment (`.venv` with `uv`)
|
||||||
|
- Compile frontend assets
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Step 1: Running the DevContainer
|
||||||
|
|
||||||
|
To start the DevContainer:
|
||||||
|
|
||||||
|
1. Open VSCode.
|
||||||
|
2. Open the project folder.
|
||||||
|
3. Open the command palette:
|
||||||
|
- **Windows/Linux**: `Ctrl+Shift+P`
|
||||||
|
- **Mac**: `Cmd+Shift+P`
|
||||||
|
4. Type and select `Dev Containers: Rebuild and Reopen in Container`.
|
||||||
|
|
||||||
|
VSCode will build and start the DevContainer environment.
|
||||||
|
|
||||||
|
### Step 2: Initial Setup
|
||||||
|
|
||||||
|
Once the DevContainer is up and running, perform the following steps:
|
||||||
|
|
||||||
|
1. **Compile Frontend Assets**:
|
||||||
|
|
||||||
|
- Open the command palette:
|
||||||
|
- **Windows/Linux**: `Ctrl+Shift+P`
|
||||||
|
- **Mac**: `Cmd+Shift+P`
|
||||||
|
- Select `Tasks: Run Task`.
|
||||||
|
- Choose `Frontend Compile`.
|
||||||
|
|
||||||
|
2. **Run Database Migrations**:
|
||||||
|
|
||||||
|
- Open the command palette:
|
||||||
|
- **Windows/Linux**: `Ctrl+Shift+P`
|
||||||
|
- **Mac**: `Cmd+Shift+P`
|
||||||
|
- Select `Tasks: Run Task`.
|
||||||
|
- Choose `Migrate Database`.
|
||||||
|
|
||||||
|
3. **Create Superuser**:
|
||||||
|
- Open the command palette:
|
||||||
|
- **Windows/Linux**: `Ctrl+Shift+P`
|
||||||
|
- **Mac**: `Cmd+Shift+P`
|
||||||
|
- Select `Tasks: Run Task`.
|
||||||
|
- Choose `Create Superuser`.
|
||||||
|
|
||||||
|
### Debugging and Running Services
|
||||||
|
|
||||||
|
You can start and debug backend services either as debugging sessions via `launch.json` or as tasks.
|
||||||
|
|
||||||
|
#### Using `launch.json`
|
||||||
|
|
||||||
|
1. Press `F5` or go to the **Run and Debug** view in VSCode.
|
||||||
|
2. Select the desired configuration:
|
||||||
|
- `Runserver`
|
||||||
|
- `Document Consumer`
|
||||||
|
- `Celery`
|
||||||
|
|
||||||
|
#### Using Tasks
|
||||||
|
|
||||||
|
1. Open the command palette:
|
||||||
|
- **Windows/Linux**: `Ctrl+Shift+P`
|
||||||
|
- **Mac**: `Cmd+Shift+P`
|
||||||
|
2. Select `Tasks: Run Task`.
|
||||||
|
3. Choose the desired task:
|
||||||
|
- `Runserver`
|
||||||
|
- `Document Consumer`
|
||||||
|
- `Celery`
|
||||||
|
|
||||||
|
### Additional Maintenance Tasks
|
||||||
|
|
||||||
|
Additional tasks are available for common maintenance operations:
|
||||||
|
|
||||||
|
- **Recreate .venv**: For setting up the virtual environment using `uv`.
|
||||||
|
- **Migrate Database**: To apply database migrations.
|
||||||
|
- **Create Superuser**: To create an admin user for the application.
|
||||||
|
|
||||||
|
## Let's Get Started!
|
||||||
|
|
||||||
|
Follow the steps above to get your development environment up and running. Happy coding!
|
@ -3,7 +3,7 @@
|
|||||||
"dockerComposeFile": "docker-compose.devcontainer.sqlite-tika.yml",
|
"dockerComposeFile": "docker-compose.devcontainer.sqlite-tika.yml",
|
||||||
"service": "paperless-development",
|
"service": "paperless-development",
|
||||||
"workspaceFolder": "/usr/src/paperless/paperless-ngx",
|
"workspaceFolder": "/usr/src/paperless/paperless-ngx",
|
||||||
"postCreateCommand": "pipenv install --dev && pipenv run pre-commit install",
|
"postCreateCommand": "/bin/bash -c 'uv sync --group dev && uv run pre-commit install'",
|
||||||
"customizations": {
|
"customizations": {
|
||||||
"vscode": {
|
"vscode": {
|
||||||
"extensions": [
|
"extensions": [
|
||||||
|
@ -21,14 +21,12 @@
|
|||||||
# This file is intended only to be used through VSCOde devcontainers. See README.md
|
# This file is intended only to be used through VSCOde devcontainers. See README.md
|
||||||
# in the folder .devcontainer.
|
# in the folder .devcontainer.
|
||||||
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
broker:
|
broker:
|
||||||
image: docker.io/library/redis:7
|
image: docker.io/library/redis:7
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- ./redisdata:/data
|
- ./redisdata:/data
|
||||||
|
|
||||||
# No ports need to be exposed; the VSCode DevContainer plugin manages them.
|
# No ports need to be exposed; the VSCode DevContainer plugin manages them.
|
||||||
paperless-development:
|
paperless-development:
|
||||||
image: paperless-ngx
|
image: paperless-ngx
|
||||||
@ -43,7 +41,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ..:/usr/src/paperless/paperless-ngx:delegated
|
- ..:/usr/src/paperless/paperless-ngx:delegated
|
||||||
- ../.devcontainer/vscode:/usr/src/paperless/paperless-ngx/.vscode:delegated # VSCode config files
|
- ../.devcontainer/vscode:/usr/src/paperless/paperless-ngx/.vscode:delegated # VSCode config files
|
||||||
- pipenv:/usr/src/paperless/paperless-ngx/.venv
|
- virtualenv:/usr/src/paperless/paperless-ngx/.venv # Virtual environment persisted in volume
|
||||||
- /usr/src/paperless/paperless-ngx/src/documents/static/frontend # Static frontend files exist only in container
|
- /usr/src/paperless/paperless-ngx/src/documents/static/frontend # Static frontend files exist only in container
|
||||||
- /usr/src/paperless/paperless-ngx/src/.pytest_cache
|
- /usr/src/paperless/paperless-ngx/src/.pytest_cache
|
||||||
- /usr/src/paperless/paperless-ngx/.ruff_cache
|
- /usr/src/paperless/paperless-ngx/.ruff_cache
|
||||||
@ -60,24 +58,22 @@ services:
|
|||||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||||
PAPERLESS_STATICDIR: ./src/documents/static
|
PAPERLESS_STATICDIR: ./src/documents/static
|
||||||
PAPERLESS_DEBUG: true
|
PAPERLESS_DEBUG: true
|
||||||
|
|
||||||
# Overrides default command so things don't shut down after the process ends.
|
# Overrides default command so things don't shut down after the process ends.
|
||||||
command: /bin/sh -c "chown -R paperless:paperless /usr/src/paperless/paperless-ngx/src/documents/static/frontend && chown -R paperless:paperless /usr/src/paperless/paperless-ngx/.ruff_cache && while sleep 1000; do :; done"
|
command: /bin/sh -c "chown -R paperless:paperless /usr/src/paperless/paperless-ngx/src/documents/static/frontend && chown -R paperless:paperless /usr/src/paperless/paperless-ngx/.ruff_cache && while sleep 1000; do :; done"
|
||||||
|
|
||||||
gotenberg:
|
gotenberg:
|
||||||
image: docker.io/gotenberg/gotenberg:7.10
|
image: docker.io/gotenberg/gotenberg:8.17
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
# The Gotenberg Chromium route is used to convert .eml files. We do not
|
# The Gotenberg Chromium route is used to convert .eml files. We do not
|
||||||
# want to allow external content like tracking pixels or even JavaScript.
|
# want to allow external content like tracking pixels or even JavaScript.
|
||||||
command:
|
command:
|
||||||
- "gotenberg"
|
- "gotenberg"
|
||||||
- "--chromium-disable-javascript=true"
|
- "--chromium-disable-javascript=true"
|
||||||
- "--chromium-allow-list=file:///tmp/.*"
|
- "--chromium-allow-list=file:///tmp/.*"
|
||||||
|
|
||||||
tika:
|
tika:
|
||||||
image: docker.io/apache/tika:latest
|
image: docker.io/apache/tika:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
pipenv:
|
data:
|
||||||
|
media:
|
||||||
|
redisdata:
|
||||||
|
virtualenv:
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
"label": "Start: Celery Worker",
|
"label": "Start: Celery Worker",
|
||||||
"description": "Start the Celery Worker which processes background and consume tasks",
|
"description": "Start the Celery Worker which processes background and consume tasks",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "pipenv run celery --app paperless worker -l DEBUG",
|
"command": "uv run celery --app paperless worker -l DEBUG",
|
||||||
"isBackground": true,
|
"isBackground": true,
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}/src"
|
"cwd": "${workspaceFolder}/src"
|
||||||
@ -33,7 +33,7 @@
|
|||||||
"label": "Start: Frontend Angular",
|
"label": "Start: Frontend Angular",
|
||||||
"description": "Start the Frontend Angular Dev Server",
|
"description": "Start the Frontend Angular Dev Server",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "npm start",
|
"command": "pnpm start",
|
||||||
"isBackground": true,
|
"isBackground": true,
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}/src-ui"
|
"cwd": "${workspaceFolder}/src-ui"
|
||||||
@ -61,7 +61,7 @@
|
|||||||
"label": "Start: Consumer Service (manage.py document_consumer)",
|
"label": "Start: Consumer Service (manage.py document_consumer)",
|
||||||
"description": "Start the Consumer Service which processes files from a directory",
|
"description": "Start the Consumer Service which processes files from a directory",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "pipenv run python manage.py document_consumer",
|
"command": "uv run python manage.py document_consumer",
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"presentation": {
|
"presentation": {
|
||||||
"echo": true,
|
"echo": true,
|
||||||
@ -80,7 +80,7 @@
|
|||||||
"label": "Start: Backend Server (manage.py runserver)",
|
"label": "Start: Backend Server (manage.py runserver)",
|
||||||
"description": "Start the Backend Server which serves the Django API and the compiled Angular frontend",
|
"description": "Start the Backend Server which serves the Django API and the compiled Angular frontend",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "pipenv run python manage.py runserver",
|
"command": "uv run python manage.py runserver",
|
||||||
"group": "build",
|
"group": "build",
|
||||||
"presentation": {
|
"presentation": {
|
||||||
"echo": true,
|
"echo": true,
|
||||||
@ -99,7 +99,7 @@
|
|||||||
"label": "Maintenance: manage.py migrate",
|
"label": "Maintenance: manage.py migrate",
|
||||||
"description": "Apply database migrations",
|
"description": "Apply database migrations",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "pipenv run python manage.py migrate",
|
"command": "uv run python manage.py migrate",
|
||||||
"group": "none",
|
"group": "none",
|
||||||
"presentation": {
|
"presentation": {
|
||||||
"echo": true,
|
"echo": true,
|
||||||
@ -118,7 +118,7 @@
|
|||||||
"label": "Maintenance: Build Documentation",
|
"label": "Maintenance: Build Documentation",
|
||||||
"description": "Build the documentation with MkDocs",
|
"description": "Build the documentation with MkDocs",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "pipenv run mkdocs build --config-file mkdocs.yml && pipenv run mkdocs serve",
|
"command": "uv run mkdocs build --config-file mkdocs.yml && uv run mkdocs serve",
|
||||||
"group": "none",
|
"group": "none",
|
||||||
"presentation": {
|
"presentation": {
|
||||||
"echo": true,
|
"echo": true,
|
||||||
@ -137,7 +137,7 @@
|
|||||||
"label": "Maintenance: manage.py createsuperuser",
|
"label": "Maintenance: manage.py createsuperuser",
|
||||||
"description": "Create a superuser",
|
"description": "Create a superuser",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "pipenv run python manage.py createsuperuser",
|
"command": "uv run python manage.py createsuperuser",
|
||||||
"group": "none",
|
"group": "none",
|
||||||
"presentation": {
|
"presentation": {
|
||||||
"echo": true,
|
"echo": true,
|
||||||
@ -156,7 +156,7 @@
|
|||||||
"label": "Maintenance: recreate .venv",
|
"label": "Maintenance: recreate .venv",
|
||||||
"description": "Recreate the python virtual environment and install python dependencies",
|
"description": "Recreate the python virtual environment and install python dependencies",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "rm -R -v .venv/* || pipenv install --dev",
|
"command": "rm -R -v .venv/* || uv install --dev",
|
||||||
"group": "none",
|
"group": "none",
|
||||||
"presentation": {
|
"presentation": {
|
||||||
"echo": true,
|
"echo": true,
|
||||||
@ -173,8 +173,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "Maintenance: Install Frontend Dependencies",
|
"label": "Maintenance: Install Frontend Dependencies",
|
||||||
"description": "Install frontend (npm) dependencies",
|
"description": "Install frontend (pnpm) dependencies",
|
||||||
"type": "npm",
|
"type": "pnpm",
|
||||||
"script": "install",
|
"script": "install",
|
||||||
"path": "src-ui",
|
"path": "src-ui",
|
||||||
"group": "clean",
|
"group": "clean",
|
||||||
@ -185,7 +185,7 @@
|
|||||||
"description": "Clean install frontend dependencies and build the frontend for production",
|
"description": "Clean install frontend dependencies and build the frontend for production",
|
||||||
"label": "Maintenance: Compile frontend for production",
|
"label": "Maintenance: Compile frontend for production",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "npm ci && ./node_modules/.bin/ng build --configuration production",
|
"command": "pnpm install && ./node_modules/.bin/ng build --configuration production",
|
||||||
"group": "none",
|
"group": "none",
|
||||||
"presentation": {
|
"presentation": {
|
||||||
"echo": true,
|
"echo": true,
|
||||||
|
@ -26,3 +26,5 @@
|
|||||||
./dist
|
./dist
|
||||||
./scripts
|
./scripts
|
||||||
./resources
|
./resources
|
||||||
|
# Other stuff
|
||||||
|
**/*.drawio.png
|
||||||
|
@ -27,9 +27,6 @@ indent_style = space
|
|||||||
[*.md]
|
[*.md]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
|
|
||||||
[Pipfile.lock]
|
|
||||||
indent_style = space
|
|
||||||
|
|
||||||
# Tests don't get a line width restriction. It's still a good idea to follow
|
# Tests don't get a line width restriction. It's still a good idea to follow
|
||||||
# the 79 character rule, but in the interests of clarity, tests often need to
|
# the 79 character rule, but in the interests of clarity, tests often need to
|
||||||
# violate it.
|
# violate it.
|
||||||
|
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
github: [shamoon, stumpylog]
|
66
.github/dependabot.yml
vendored
66
.github/dependabot.yml
vendored
@ -1,12 +1,14 @@
|
|||||||
# https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates#package-ecosystem
|
# Please see the documentation for all configuration options:
|
||||||
|
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||||
|
|
||||||
version: 2
|
version: 2
|
||||||
|
# Required for uv support for now
|
||||||
|
enable-beta-ecosystems: true
|
||||||
updates:
|
updates:
|
||||||
|
# Enable version updates for pnpm
|
||||||
# Enable version updates for npm
|
|
||||||
- package-ecosystem: "npm"
|
- package-ecosystem: "npm"
|
||||||
target-branch: "dev"
|
target-branch: "dev"
|
||||||
# Look for `package.json` and `lock` files in the `/src-ui` directory
|
# Look for `pnpm-lock.yaml` file in the `/src-ui` directory
|
||||||
directory: "/src-ui"
|
directory: "/src-ui"
|
||||||
open-pull-requests-limit: 10
|
open-pull-requests-limit: 10
|
||||||
schedule:
|
schedule:
|
||||||
@ -32,11 +34,9 @@ updates:
|
|||||||
patterns:
|
patterns:
|
||||||
- "@typescript-eslint*"
|
- "@typescript-eslint*"
|
||||||
- "eslint"
|
- "eslint"
|
||||||
|
|
||||||
# Enable version updates for Python
|
# Enable version updates for Python
|
||||||
- package-ecosystem: "pip"
|
- package-ecosystem: "uv"
|
||||||
target-branch: "dev"
|
target-branch: "dev"
|
||||||
# Look for a `Pipfile` in the `root` directory
|
|
||||||
directory: "/"
|
directory: "/"
|
||||||
# Check for updates once a week
|
# Check for updates once a week
|
||||||
schedule:
|
schedule:
|
||||||
@ -47,17 +47,17 @@ updates:
|
|||||||
# Add reviewers
|
# Add reviewers
|
||||||
reviewers:
|
reviewers:
|
||||||
- "paperless-ngx/backend"
|
- "paperless-ngx/backend"
|
||||||
ignore:
|
|
||||||
- dependency-name: "uvicorn"
|
|
||||||
groups:
|
groups:
|
||||||
development:
|
development:
|
||||||
patterns:
|
patterns:
|
||||||
- "*pytest*"
|
- "*pytest*"
|
||||||
- "ruff"
|
- "ruff"
|
||||||
- "mkdocs-material"
|
- "mkdocs-material"
|
||||||
|
- "pre-commit*"
|
||||||
django:
|
django:
|
||||||
patterns:
|
patterns:
|
||||||
- "*django*"
|
- "*django*"
|
||||||
|
- "drf-*"
|
||||||
major-versions:
|
major-versions:
|
||||||
update-types:
|
update-types:
|
||||||
- "major"
|
- "major"
|
||||||
@ -65,7 +65,10 @@ updates:
|
|||||||
update-types:
|
update-types:
|
||||||
- "minor"
|
- "minor"
|
||||||
- "patch"
|
- "patch"
|
||||||
|
pre-built:
|
||||||
|
patterns:
|
||||||
|
- psycopg*
|
||||||
|
- zxing-cpp
|
||||||
# Enable updates for GitHub Actions
|
# Enable updates for GitHub Actions
|
||||||
- package-ecosystem: "github-actions"
|
- package-ecosystem: "github-actions"
|
||||||
target-branch: "dev"
|
target-branch: "dev"
|
||||||
@ -85,3 +88,46 @@ updates:
|
|||||||
- "major"
|
- "major"
|
||||||
- "minor"
|
- "minor"
|
||||||
- "patch"
|
- "patch"
|
||||||
|
# Update Dockerfile in root directory
|
||||||
|
- package-ecosystem: "docker"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
open-pull-requests-limit: 5
|
||||||
|
reviewers:
|
||||||
|
- "paperless-ngx/ci-cd"
|
||||||
|
labels:
|
||||||
|
- "dependencies"
|
||||||
|
commit-message:
|
||||||
|
prefix: "docker"
|
||||||
|
include: "scope"
|
||||||
|
# Update Docker Compose files in docker/compose directory
|
||||||
|
- package-ecosystem: "docker-compose"
|
||||||
|
directory: "/docker/compose/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
open-pull-requests-limit: 5
|
||||||
|
reviewers:
|
||||||
|
- "paperless-ngx/ci-cd"
|
||||||
|
labels:
|
||||||
|
- "dependencies"
|
||||||
|
commit-message:
|
||||||
|
prefix: "docker-compose"
|
||||||
|
include: "scope"
|
||||||
|
groups:
|
||||||
|
# Individual groups for each image
|
||||||
|
gotenberg:
|
||||||
|
patterns:
|
||||||
|
- "docker.io/gotenberg/gotenberg*"
|
||||||
|
tika:
|
||||||
|
patterns:
|
||||||
|
- "docker.io/apache/tika*"
|
||||||
|
redis:
|
||||||
|
patterns:
|
||||||
|
- "docker.io/library/redis*"
|
||||||
|
mariadb:
|
||||||
|
patterns:
|
||||||
|
- "docker.io/library/mariadb*"
|
||||||
|
postgres:
|
||||||
|
patterns:
|
||||||
|
- "docker.io/library/postgres*"
|
||||||
|
19
.github/labeler.yml
vendored
Normal file
19
.github/labeler.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
backend:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-any-file:
|
||||||
|
- 'src/**'
|
||||||
|
- 'pyproject.toml'
|
||||||
|
- 'uv.lock'
|
||||||
|
- 'requirements.txt'
|
||||||
|
frontend:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-any-file:
|
||||||
|
- 'src-ui/**'
|
||||||
|
documentation:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-any-file:
|
||||||
|
- 'docs/**'
|
||||||
|
ci-cd:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-any-file:
|
||||||
|
- '.github/**'
|
460
.github/workflows/ci.yml
vendored
460
.github/workflows/ci.yml
vendored
@ -1,5 +1,4 @@
|
|||||||
name: ci
|
name: ci
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
@ -12,87 +11,73 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
branches-ignore:
|
branches-ignore:
|
||||||
- 'translations**'
|
- 'translations**'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
# This is the version of pipenv all the steps will use
|
DEFAULT_UV_VERSION: "0.6.x"
|
||||||
# If changing this, change Dockerfile
|
|
||||||
DEFAULT_PIP_ENV_VERSION: "2024.4.1"
|
|
||||||
# This is the default version of Python to use in most steps which aren't specific
|
# This is the default version of Python to use in most steps which aren't specific
|
||||||
DEFAULT_PYTHON_VERSION: "3.11"
|
DEFAULT_PYTHON_VERSION: "3.11"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pre-commit:
|
pre-commit:
|
||||||
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
# We want to run on external PRs, but not on our own internal PRs as they'll be run
|
||||||
# by the push to the branch. Without this if check, checks are duplicated since
|
# by the push to the branch. Without this if check, checks are duplicated since
|
||||||
# internal PRs match both the push and pull_request events.
|
# internal PRs match both the push and pull_request events.
|
||||||
if:
|
if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository
|
||||||
github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
|
|
||||||
github.repository
|
|
||||||
|
|
||||||
name: Linting Checks
|
name: Linting Checks
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Checkout repository
|
||||||
name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
-
|
- name: Install python
|
||||||
name: Install python
|
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
||||||
-
|
- name: Check files
|
||||||
name: Check files
|
|
||||||
uses: pre-commit/action@v3.0.1
|
uses: pre-commit/action@v3.0.1
|
||||||
|
|
||||||
documentation:
|
documentation:
|
||||||
name: "Build & Deploy Documentation"
|
name: "Build & Deploy Documentation"
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs:
|
needs:
|
||||||
- pre-commit
|
- pre-commit
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Checkout
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
-
|
- name: Set up Python
|
||||||
name: Set up Python
|
|
||||||
id: setup-python
|
id: setup-python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
||||||
cache: "pipenv"
|
- name: Install uv
|
||||||
cache-dependency-path: 'Pipfile.lock'
|
uses: astral-sh/setup-uv@v5
|
||||||
-
|
with:
|
||||||
name: Install pipenv
|
version: ${{ env.DEFAULT_UV_VERSION }}
|
||||||
|
enable-cache: true
|
||||||
|
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
||||||
|
- name: Install Python dependencies
|
||||||
run: |
|
run: |
|
||||||
pip install --user pipenv==${{ env.DEFAULT_PIP_ENV_VERSION }}
|
uv sync --python ${{ steps.setup-python.outputs.python-version }} --dev --frozen
|
||||||
-
|
- name: Make documentation
|
||||||
name: Install dependencies
|
|
||||||
run: |
|
run: |
|
||||||
pipenv --python ${{ steps.setup-python.outputs.python-version }} sync --dev
|
uv run \
|
||||||
-
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
name: List installed Python dependencies
|
--dev \
|
||||||
run: |
|
--frozen \
|
||||||
pipenv --python ${{ steps.setup-python.outputs.python-version }} run pip list
|
mkdocs build --config-file ./mkdocs.yml
|
||||||
-
|
- name: Deploy documentation
|
||||||
name: Make documentation
|
|
||||||
run: |
|
|
||||||
pipenv --python ${{ steps.setup-python.outputs.python-version }} run mkdocs build --config-file ./mkdocs.yml
|
|
||||||
-
|
|
||||||
name: Deploy documentation
|
|
||||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
run: |
|
run: |
|
||||||
echo "docs.paperless-ngx.com" > "${{ github.workspace }}/docs/CNAME"
|
echo "docs.paperless-ngx.com" > "${{ github.workspace }}/docs/CNAME"
|
||||||
git config --global user.name "${{ github.actor }}"
|
git config --global user.name "${{ github.actor }}"
|
||||||
git config --global user.email "${{ github.actor }}@users.noreply.github.com"
|
git config --global user.email "${{ github.actor }}@users.noreply.github.com"
|
||||||
pipenv --python ${{ steps.setup-python.outputs.python-version }} run mkdocs gh-deploy --force --no-history
|
uv run \
|
||||||
-
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
name: Upload artifact
|
--dev \
|
||||||
|
--frozen \
|
||||||
|
mkdocs gh-deploy --force --no-history
|
||||||
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: documentation
|
name: documentation
|
||||||
path: site/
|
path: site/
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|
||||||
tests-backend:
|
tests-backend:
|
||||||
name: "Backend Tests (Python ${{ matrix.python-version }})"
|
name: "Backend Tests (Python ${{ matrix.python-version }})"
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
@ -103,46 +88,40 @@ jobs:
|
|||||||
python-version: ['3.10', '3.11', '3.12']
|
python-version: ['3.10', '3.11', '3.12']
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Checkout
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
-
|
- name: Start containers
|
||||||
name: Start containers
|
|
||||||
run: |
|
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 pull --quiet
|
||||||
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml up --detach
|
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml up --detach
|
||||||
-
|
- name: Set up Python
|
||||||
name: Set up Python
|
|
||||||
id: setup-python
|
id: setup-python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: "${{ matrix.python-version }}"
|
python-version: "${{ matrix.python-version }}"
|
||||||
cache: "pipenv"
|
- name: Install uv
|
||||||
cache-dependency-path: 'Pipfile.lock'
|
uses: astral-sh/setup-uv@v5
|
||||||
-
|
with:
|
||||||
name: Install pipenv
|
version: ${{ env.DEFAULT_UV_VERSION }}
|
||||||
run: |
|
enable-cache: true
|
||||||
pip install --user pipenv==${{ env.DEFAULT_PIP_ENV_VERSION }}
|
python-version: ${{ steps.setup-python.outputs.python-version }}
|
||||||
-
|
- name: Install system dependencies
|
||||||
name: Install system dependencies
|
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update -qq
|
sudo apt-get update -qq
|
||||||
sudo apt-get install -qq --no-install-recommends unpaper tesseract-ocr imagemagick ghostscript libzbar0 poppler-utils
|
sudo apt-get install -qq --no-install-recommends unpaper tesseract-ocr imagemagick ghostscript libzbar0 poppler-utils
|
||||||
-
|
- name: Configure ImageMagick
|
||||||
name: Configure ImageMagick
|
|
||||||
run: |
|
run: |
|
||||||
sudo cp docker/imagemagick-policy.xml /etc/ImageMagick-6/policy.xml
|
sudo cp docker/rootfs/etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-6/policy.xml
|
||||||
-
|
- name: Install Python dependencies
|
||||||
name: Install Python dependencies
|
|
||||||
run: |
|
run: |
|
||||||
pipenv --python ${{ steps.setup-python.outputs.python-version }} run python --version
|
uv sync \
|
||||||
pipenv --python ${{ steps.setup-python.outputs.python-version }} sync --dev
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
-
|
--group testing \
|
||||||
name: List installed Python dependencies
|
--frozen
|
||||||
|
- name: List installed Python dependencies
|
||||||
run: |
|
run: |
|
||||||
pipenv --python ${{ steps.setup-python.outputs.python-version }} run pip list
|
uv pip list
|
||||||
-
|
- name: Tests
|
||||||
name: Tests
|
|
||||||
env:
|
env:
|
||||||
PAPERLESS_CI_TEST: 1
|
PAPERLESS_CI_TEST: 1
|
||||||
# Enable paperless_mail testing against real server
|
# Enable paperless_mail testing against real server
|
||||||
@ -150,60 +129,65 @@ jobs:
|
|||||||
PAPERLESS_MAIL_TEST_USER: ${{ secrets.TEST_MAIL_USER }}
|
PAPERLESS_MAIL_TEST_USER: ${{ secrets.TEST_MAIL_USER }}
|
||||||
PAPERLESS_MAIL_TEST_PASSWD: ${{ secrets.TEST_MAIL_PASSWD }}
|
PAPERLESS_MAIL_TEST_PASSWD: ${{ secrets.TEST_MAIL_PASSWD }}
|
||||||
run: |
|
run: |
|
||||||
cd src/
|
uv run \
|
||||||
pipenv --python ${{ steps.setup-python.outputs.python-version }} run pytest -ra
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
-
|
--dev \
|
||||||
name: Upload coverage
|
--frozen \
|
||||||
if: ${{ matrix.python-version == env.DEFAULT_PYTHON_VERSION }}
|
pytest
|
||||||
uses: actions/upload-artifact@v4
|
- name: Upload backend test results to Codecov
|
||||||
|
if: always()
|
||||||
|
uses: codecov/test-results-action@v1
|
||||||
with:
|
with:
|
||||||
name: backend-coverage-report
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
path: src/coverage.xml
|
flags: backend-python-${{ matrix.python-version }}
|
||||||
retention-days: 7
|
files: junit.xml
|
||||||
if-no-files-found: warn
|
- name: Upload backend coverage to Codecov
|
||||||
-
|
uses: codecov/codecov-action@v5
|
||||||
name: Stop containers
|
with:
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
flags: backend-python-${{ matrix.python-version }}
|
||||||
|
files: coverage.xml
|
||||||
|
- name: Stop containers
|
||||||
if: always()
|
if: always()
|
||||||
run: |
|
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 logs
|
||||||
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml down
|
docker compose --file ${{ github.workspace }}/docker/compose/docker-compose.ci-test.yml down
|
||||||
|
install-frontend-dependencies:
|
||||||
install-frontend-depedendencies:
|
|
||||||
name: "Install Frontend Dependencies"
|
name: "Install Frontend Dependencies"
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs:
|
needs:
|
||||||
- pre-commit
|
- pre-commit
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
-
|
- name: Install pnpm
|
||||||
name: Use Node.js 20
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
- name: Use Node.js 20
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version: 20.x
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: 'src-ui/package-lock.json'
|
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
|
||||||
- name: Cache frontend dependencies
|
- name: Cache frontend dependencies
|
||||||
id: cache-frontend-deps
|
id: cache-frontend-deps
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.npm
|
~/.pnpm-store
|
||||||
~/.cache
|
~/.cache
|
||||||
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/package-lock.json') }}
|
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
|
||||||
-
|
- name: Install dependencies
|
||||||
name: Install dependencies
|
|
||||||
if: steps.cache-frontend-deps.outputs.cache-hit != 'true'
|
if: steps.cache-frontend-deps.outputs.cache-hit != 'true'
|
||||||
run: cd src-ui && npm ci
|
run: cd src-ui && pnpm install
|
||||||
-
|
- name: Install Playwright
|
||||||
name: Install Playwright
|
|
||||||
if: steps.cache-frontend-deps.outputs.cache-hit != 'true'
|
if: steps.cache-frontend-deps.outputs.cache-hit != 'true'
|
||||||
run: cd src-ui && npx playwright install --with-deps
|
run: cd src-ui && pnpm playwright install --with-deps
|
||||||
|
|
||||||
tests-frontend:
|
tests-frontend:
|
||||||
name: "Frontend Tests (Node ${{ matrix.node-version }} - ${{ matrix.shard-index }}/${{ matrix.shard-count }})"
|
name: "Frontend Tests (Node ${{ matrix.node-version }} - ${{ matrix.shard-index }}/${{ matrix.shard-count }})"
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs:
|
needs:
|
||||||
- install-frontend-depedendencies
|
- install-frontend-dependencies
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@ -212,125 +196,76 @@ jobs:
|
|||||||
shard-count: [4]
|
shard-count: [4]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
-
|
- name: Install pnpm
|
||||||
name: Use Node.js 20
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
- name: Use Node.js 20
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version: 20.x
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: 'src-ui/package-lock.json'
|
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
|
||||||
- name: Cache frontend dependencies
|
- name: Cache frontend dependencies
|
||||||
id: cache-frontend-deps
|
id: cache-frontend-deps
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.npm
|
~/.pnpm-store
|
||||||
~/.cache
|
~/.cache
|
||||||
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/package-lock.json') }}
|
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
|
||||||
- name: Re-link Angular cli
|
- name: Re-link Angular cli
|
||||||
run: cd src-ui && npm link @angular/cli
|
run: cd src-ui && pnpm link @angular/cli
|
||||||
-
|
- name: Linting checks
|
||||||
name: Linting checks
|
run: cd src-ui && pnpm run lint
|
||||||
run: cd src-ui && npm 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: Run Jest unit tests
|
- name: Run Playwright e2e tests
|
||||||
run: cd src-ui && npm run test -- --max-workers=2 --shard=${{ matrix.shard-index }}/${{ matrix.shard-count }}
|
run: cd src-ui && pnpm exec playwright test --shard ${{ matrix.shard-index }}/${{ matrix.shard-count }}
|
||||||
-
|
- name: Upload frontend test results to Codecov
|
||||||
name: Upload Jest coverage
|
uses: codecov/test-results-action@v1
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: jest-coverage-report-${{ matrix.shard-index }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
path: |
|
flags: frontend-node-${{ matrix.node-version }}
|
||||||
src-ui/coverage/coverage-final.json
|
directory: src-ui/
|
||||||
src-ui/coverage/lcov.info
|
- name: Upload frontend coverage to Codecov
|
||||||
src-ui/coverage/clover.xml
|
uses: codecov/codecov-action@v5
|
||||||
retention-days: 7
|
|
||||||
if-no-files-found: warn
|
|
||||||
-
|
|
||||||
name: Run Playwright e2e tests
|
|
||||||
run: cd src-ui && npx playwright test --shard ${{ matrix.shard-index }}/${{ matrix.shard-count }}
|
|
||||||
-
|
|
||||||
name: Upload Playwright test results
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: playwright-report-${{ matrix.shard-index }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
path: src-ui/playwright-report
|
flags: frontend-node-${{ matrix.node-version }}
|
||||||
retention-days: 7
|
directory: src-ui/coverage/
|
||||||
|
frontend-bundle-analysis:
|
||||||
tests-coverage-upload:
|
name: "Frontend Bundle Analysis"
|
||||||
name: "Upload to Codecov"
|
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs:
|
needs:
|
||||||
- tests-backend
|
|
||||||
- tests-frontend
|
- tests-frontend
|
||||||
steps:
|
steps:
|
||||||
-
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v4
|
- name: Install pnpm
|
||||||
-
|
uses: pnpm/action-setup@v4
|
||||||
name: Download frontend jest coverage
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
path: src-ui/coverage/
|
version: 10
|
||||||
pattern: jest-coverage-report-*
|
- name: Use Node.js 20
|
||||||
-
|
|
||||||
name: Download frontend playwright coverage
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
path: src-ui/coverage/
|
|
||||||
pattern: playwright-report-*
|
|
||||||
merge-multiple: true
|
|
||||||
-
|
|
||||||
name: Upload frontend coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v5
|
|
||||||
with:
|
|
||||||
# not required for public repos, but intermittently fails otherwise
|
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
flags: frontend
|
|
||||||
directory: src-ui/coverage/
|
|
||||||
# dont include backend coverage files here
|
|
||||||
files: '!coverage.xml'
|
|
||||||
-
|
|
||||||
name: Download backend coverage
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: backend-coverage-report
|
|
||||||
path: src/
|
|
||||||
-
|
|
||||||
name: Upload coverage to Codecov
|
|
||||||
uses: codecov/codecov-action@v5
|
|
||||||
with:
|
|
||||||
# not required for public repos, but intermittently fails otherwise
|
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
# future expansion
|
|
||||||
flags: backend
|
|
||||||
directory: src/
|
|
||||||
-
|
|
||||||
name: Use Node.js 20
|
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20.x
|
node-version: 20.x
|
||||||
cache: 'npm'
|
cache: 'pnpm'
|
||||||
cache-dependency-path: 'src-ui/package-lock.json'
|
cache-dependency-path: 'src-ui/pnpm-lock.yaml'
|
||||||
-
|
- name: Cache frontend dependencies
|
||||||
name: Cache frontend dependencies
|
|
||||||
id: cache-frontend-deps
|
id: cache-frontend-deps
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.npm
|
~/.pnpm-store
|
||||||
~/.cache
|
~/.cache
|
||||||
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/package-lock.json') }}
|
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/package-lock.json') }}
|
||||||
-
|
- name: Re-link Angular cli
|
||||||
name: Re-link Angular cli
|
run: cd src-ui && pnpm link @angular/cli
|
||||||
run: cd src-ui && npm link @angular/cli
|
- name: Build frontend and upload analysis
|
||||||
-
|
|
||||||
name: Build frontend and upload analysis
|
|
||||||
env:
|
env:
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||||
run: cd src-ui && ng build --configuration=production
|
run: cd src-ui && pnpm run build --configuration=production
|
||||||
|
|
||||||
build-docker-image:
|
build-docker-image:
|
||||||
name: Build Docker image for ${{ github.ref_name }}
|
name: Build Docker image for ${{ github.ref_name }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
@ -342,8 +277,7 @@ jobs:
|
|||||||
- tests-backend
|
- tests-backend
|
||||||
- tests-frontend
|
- tests-frontend
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Check pushing to Docker Hub
|
||||||
name: Check pushing to Docker Hub
|
|
||||||
id: push-other-places
|
id: push-other-places
|
||||||
# Only push to Dockerhub from the main repo AND the ref is either:
|
# Only push to Dockerhub from the main repo AND the ref is either:
|
||||||
# main
|
# main
|
||||||
@ -359,15 +293,13 @@ jobs:
|
|||||||
echo "Not pushing to DockerHub"
|
echo "Not pushing to DockerHub"
|
||||||
echo "enable=false" >> $GITHUB_OUTPUT
|
echo "enable=false" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
-
|
- name: Set ghcr repository name
|
||||||
name: Set ghcr repository name
|
|
||||||
id: set-ghcr-repository
|
id: set-ghcr-repository
|
||||||
run: |
|
run: |
|
||||||
ghcr_name=$(echo "${{ github.repository }}" | awk '{ print tolower($0) }')
|
ghcr_name=$(echo "${{ github.repository }}" | awk '{ print tolower($0) }')
|
||||||
echo "Name is ${ghcr_name}"
|
echo "Name is ${ghcr_name}"
|
||||||
echo "ghcr-repository=${ghcr_name}" >> $GITHUB_OUTPUT
|
echo "ghcr-repository=${ghcr_name}" >> $GITHUB_OUTPUT
|
||||||
-
|
- name: Gather Docker metadata
|
||||||
name: Gather Docker metadata
|
|
||||||
id: docker-meta
|
id: docker-meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
@ -382,37 +314,31 @@ jobs:
|
|||||||
# For a tag x.y.z or vX.Y.Z, output an x.y.z and x.y image tag
|
# 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={{version}}
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
-
|
- name: Checkout
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
# If https://github.com/docker/buildx/issues/1044 is resolved,
|
# If https://github.com/docker/buildx/issues/1044 is resolved,
|
||||||
# the append input with a native arm64 arch could be used to
|
# the append input with a native arm64 arch could be used to
|
||||||
# significantly speed up building
|
# significantly speed up building
|
||||||
-
|
- name: Set up Docker Buildx
|
||||||
name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
-
|
- name: Set up QEMU
|
||||||
name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
with:
|
with:
|
||||||
platforms: arm64
|
platforms: arm64
|
||||||
-
|
- name: Login to GitHub Container Registry
|
||||||
name: Login to GitHub Container Registry
|
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
-
|
- name: Login to Docker Hub
|
||||||
name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
# Don't attempt to login if not pushing to Docker Hub
|
# Don't attempt to login if not pushing to Docker Hub
|
||||||
if: steps.push-other-places.outputs.enable == 'true'
|
if: steps.push-other-places.outputs.enable == 'true'
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
-
|
- name: Login to Quay.io
|
||||||
name: Login to Quay.io
|
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
# Don't attempt to login if not pushing to Quay.io
|
# Don't attempt to login if not pushing to Quay.io
|
||||||
if: steps.push-other-places.outputs.enable == 'true'
|
if: steps.push-other-places.outputs.enable == 'true'
|
||||||
@ -420,8 +346,7 @@ jobs:
|
|||||||
registry: quay.io
|
registry: quay.io
|
||||||
username: ${{ secrets.QUAY_USERNAME }}
|
username: ${{ secrets.QUAY_USERNAME }}
|
||||||
password: ${{ secrets.QUAY_ROBOT_TOKEN }}
|
password: ${{ secrets.QUAY_ROBOT_TOKEN }}
|
||||||
-
|
- name: Build and push
|
||||||
name: Build and push
|
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
@ -439,23 +364,19 @@ jobs:
|
|||||||
type=registry,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:dev
|
type=registry,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:dev
|
||||||
cache-to: |
|
cache-to: |
|
||||||
type=registry,mode=max,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:${{ github.ref_name }}
|
type=registry,mode=max,ref=ghcr.io/${{ steps.set-ghcr-repository.outputs.ghcr-repository }}/builder/cache/app:${{ github.ref_name }}
|
||||||
-
|
- name: Inspect image
|
||||||
name: Inspect image
|
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools inspect ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
docker buildx imagetools inspect ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
||||||
-
|
- name: Export frontend artifact from docker
|
||||||
name: Export frontend artifact from docker
|
|
||||||
run: |
|
run: |
|
||||||
docker create --name frontend-extract ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
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/
|
docker cp frontend-extract:/usr/src/paperless/src/documents/static/frontend src/documents/static/frontend/
|
||||||
-
|
- name: Upload frontend artifact
|
||||||
name: Upload frontend artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: frontend-compiled
|
name: frontend-compiled
|
||||||
path: src/documents/static/frontend/
|
path: src/documents/static/frontend/
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|
||||||
build-release:
|
build-release:
|
||||||
name: "Build Release"
|
name: "Build Release"
|
||||||
needs:
|
needs:
|
||||||
@ -463,58 +384,52 @@ jobs:
|
|||||||
- documentation
|
- documentation
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Checkout
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
-
|
- name: Set up Python
|
||||||
name: Set up Python
|
|
||||||
id: setup-python
|
id: setup-python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
||||||
cache: "pipenv"
|
- name: Install uv
|
||||||
cache-dependency-path: 'Pipfile.lock'
|
uses: astral-sh/setup-uv@v5
|
||||||
-
|
with:
|
||||||
name: Install pipenv + tools
|
version: ${{ env.DEFAULT_UV_VERSION }}
|
||||||
|
enable-cache: true
|
||||||
|
python-version: ${{ steps.setup-python.outputs.python-version }}
|
||||||
|
- name: Install Python dependencies
|
||||||
run: |
|
run: |
|
||||||
pip install --upgrade --user pipenv==${{ env.DEFAULT_PIP_ENV_VERSION }} setuptools wheel
|
uv sync --python ${{ steps.setup-python.outputs.python-version }} --dev --frozen
|
||||||
-
|
- name: Install system dependencies
|
||||||
name: Install Python dependencies
|
|
||||||
run: |
|
|
||||||
pipenv --python ${{ steps.setup-python.outputs.python-version }} sync --dev
|
|
||||||
-
|
|
||||||
name: Install system dependencies
|
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update -qq
|
sudo apt-get update -qq
|
||||||
sudo apt-get install -qq --no-install-recommends gettext liblept5
|
sudo apt-get install -qq --no-install-recommends gettext liblept5
|
||||||
-
|
- name: Download frontend artifact
|
||||||
name: Download frontend artifact
|
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: frontend-compiled
|
name: frontend-compiled
|
||||||
path: src/documents/static/frontend/
|
path: src/documents/static/frontend/
|
||||||
-
|
- name: Download documentation artifact
|
||||||
name: Download documentation artifact
|
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: documentation
|
name: documentation
|
||||||
path: docs/_build/html/
|
path: docs/_build/html/
|
||||||
-
|
- name: Generate requirements file
|
||||||
name: Generate requirements file
|
|
||||||
run: |
|
run: |
|
||||||
pipenv --python ${{ steps.setup-python.outputs.python-version }} requirements > requirements.txt
|
uv export --quiet --no-dev --all-extras --format requirements-txt --output-file requirements.txt
|
||||||
-
|
- name: Compile messages
|
||||||
name: Compile messages
|
|
||||||
run: |
|
run: |
|
||||||
cd src/
|
cd src/
|
||||||
pipenv --python ${{ steps.setup-python.outputs.python-version }} run python3 manage.py compilemessages
|
uv run \
|
||||||
-
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
name: Collect static files
|
manage.py compilemessages
|
||||||
|
- name: Collect static files
|
||||||
run: |
|
run: |
|
||||||
cd src/
|
cd src/
|
||||||
pipenv --python ${{ steps.setup-python.outputs.python-version }} run python3 manage.py collectstatic --no-input
|
uv run \
|
||||||
-
|
--python ${{ steps.setup-python.outputs.python-version }} \
|
||||||
name: Move files
|
manage.py collectstatic --no-input
|
||||||
|
- name: Move files
|
||||||
run: |
|
run: |
|
||||||
echo "Making dist folders"
|
echo "Making dist folders"
|
||||||
for directory in dist \
|
for directory in dist \
|
||||||
@ -528,13 +443,12 @@ jobs:
|
|||||||
for file_name in .dockerignore \
|
for file_name in .dockerignore \
|
||||||
.env \
|
.env \
|
||||||
Dockerfile \
|
Dockerfile \
|
||||||
Pipfile \
|
pyproject.toml \
|
||||||
Pipfile.lock \
|
uv.lock \
|
||||||
requirements.txt \
|
requirements.txt \
|
||||||
LICENSE \
|
LICENSE \
|
||||||
README.md \
|
README.md \
|
||||||
paperless.conf.example \
|
paperless.conf.example
|
||||||
gunicorn.conf.py
|
|
||||||
do
|
do
|
||||||
cp --verbose ${file_name} dist/paperless-ngx/
|
cp --verbose ${file_name} dist/paperless-ngx/
|
||||||
done
|
done
|
||||||
@ -552,21 +466,18 @@ jobs:
|
|||||||
cp --recursive docs/_build/html/ dist/paperless-ngx/docs
|
cp --recursive docs/_build/html/ dist/paperless-ngx/docs
|
||||||
|
|
||||||
mv --verbose static dist/paperless-ngx
|
mv --verbose static dist/paperless-ngx
|
||||||
-
|
- name: Make release package
|
||||||
name: Make release package
|
|
||||||
run: |
|
run: |
|
||||||
echo "Creating release archive"
|
echo "Creating release archive"
|
||||||
cd dist
|
cd dist
|
||||||
sudo chown -R 1000:1000 paperless-ngx/
|
sudo chown -R 1000:1000 paperless-ngx/
|
||||||
tar -cJf paperless-ngx.tar.xz paperless-ngx/
|
tar -cJf paperless-ngx.tar.xz paperless-ngx/
|
||||||
-
|
- name: Upload release artifact
|
||||||
name: Upload release artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release
|
name: release
|
||||||
path: dist/paperless-ngx.tar.xz
|
path: dist/paperless-ngx.tar.xz
|
||||||
retention-days: 7
|
retention-days: 7
|
||||||
|
|
||||||
publish-release:
|
publish-release:
|
||||||
name: "Publish Release"
|
name: "Publish Release"
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
@ -578,14 +489,12 @@ jobs:
|
|||||||
- build-release
|
- build-release
|
||||||
if: github.ref_type == 'tag' && (startsWith(github.ref_name, 'v') || contains(github.ref_name, '-beta.rc'))
|
if: github.ref_type == 'tag' && (startsWith(github.ref_name, 'v') || contains(github.ref_name, '-beta.rc'))
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Download release artifact
|
||||||
name: Download release artifact
|
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: release
|
name: release
|
||||||
path: ./
|
path: ./
|
||||||
-
|
- name: Get version
|
||||||
name: Get version
|
|
||||||
id: get_version
|
id: get_version
|
||||||
run: |
|
run: |
|
||||||
echo "version=${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
echo "version=${{ github.ref_name }}" >> $GITHUB_OUTPUT
|
||||||
@ -594,8 +503,7 @@ jobs:
|
|||||||
else
|
else
|
||||||
echo "prerelease=false" >> $GITHUB_OUTPUT
|
echo "prerelease=false" >> $GITHUB_OUTPUT
|
||||||
fi
|
fi
|
||||||
-
|
- name: Create Release and Changelog
|
||||||
name: Create Release and Changelog
|
|
||||||
id: create-release
|
id: create-release
|
||||||
uses: release-drafter/release-drafter@v6
|
uses: release-drafter/release-drafter@v6
|
||||||
with:
|
with:
|
||||||
@ -606,8 +514,7 @@ jobs:
|
|||||||
publish: true # ensures release is not marked as draft
|
publish: true # ensures release is not marked as draft
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
-
|
- name: Upload release archive
|
||||||
name: Upload release archive
|
|
||||||
id: upload-release-asset
|
id: upload-release-asset
|
||||||
uses: shogo82148/actions-upload-release-asset@v1
|
uses: shogo82148/actions-upload-release-asset@v1
|
||||||
with:
|
with:
|
||||||
@ -616,7 +523,6 @@ jobs:
|
|||||||
asset_path: ./paperless-ngx.tar.xz
|
asset_path: ./paperless-ngx.tar.xz
|
||||||
asset_name: paperless-ngx-${{ steps.get_version.outputs.version }}.tar.xz
|
asset_name: paperless-ngx-${{ steps.get_version.outputs.version }}.tar.xz
|
||||||
asset_content_type: application/x-xz
|
asset_content_type: application/x-xz
|
||||||
|
|
||||||
append-changelog:
|
append-changelog:
|
||||||
name: "Append Changelog"
|
name: "Append Changelog"
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
@ -624,24 +530,22 @@ jobs:
|
|||||||
- publish-release
|
- publish-release
|
||||||
if: needs.publish-release.outputs.prerelease == 'false'
|
if: needs.publish-release.outputs.prerelease == 'false'
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Checkout
|
||||||
name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: main
|
ref: main
|
||||||
-
|
- name: Set up Python
|
||||||
name: Set up Python
|
id: setup-python
|
||||||
uses: actions/setup-python@v5
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
||||||
cache: "pipenv"
|
- name: Install uv
|
||||||
cache-dependency-path: 'Pipfile.lock'
|
uses: astral-sh/setup-uv@v5
|
||||||
-
|
with:
|
||||||
name: Install pipenv + tools
|
version: ${{ env.DEFAULT_UV_VERSION }}
|
||||||
run: |
|
enable-cache: true
|
||||||
pip install --upgrade --user pipenv==${{ env.DEFAULT_PIP_ENV_VERSION }} setuptools wheel
|
python-version: ${{ env.DEFAULT_PYTHON_VERSION }}
|
||||||
-
|
- name: Append Changelog to docs
|
||||||
name: Append Changelog to docs
|
|
||||||
id: append-Changelog
|
id: append-Changelog
|
||||||
working-directory: docs
|
working-directory: docs
|
||||||
run: |
|
run: |
|
||||||
@ -655,13 +559,15 @@ jobs:
|
|||||||
CURRENT_CHANGELOG=`tail --lines +2 changelog.md`
|
CURRENT_CHANGELOG=`tail --lines +2 changelog.md`
|
||||||
echo -e "$CURRENT_CHANGELOG" >> changelog-new.md
|
echo -e "$CURRENT_CHANGELOG" >> changelog-new.md
|
||||||
mv changelog-new.md changelog.md
|
mv changelog-new.md changelog.md
|
||||||
pipenv run pre-commit run --files changelog.md || true
|
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.name "github-actions"
|
||||||
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||||
git commit -am "Changelog ${{ needs.publish-release.outputs.version }} - GHA"
|
git commit -am "Changelog ${{ needs.publish-release.outputs.version }} - GHA"
|
||||||
git push origin ${{ needs.publish-release.outputs.version }}-changelog
|
git push origin ${{ needs.publish-release.outputs.version }}-changelog
|
||||||
-
|
- name: Create Pull Request
|
||||||
name: Create Pull Request
|
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
|
14
.github/workflows/cleanup-tags.yml
vendored
14
.github/workflows/cleanup-tags.yml
vendored
@ -6,17 +6,14 @@
|
|||||||
# This workflow will not trigger runs on forked repos.
|
# This workflow will not trigger runs on forked repos.
|
||||||
|
|
||||||
name: Cleanup Image Tags
|
name: Cleanup Image Tags
|
||||||
|
|
||||||
on:
|
on:
|
||||||
delete:
|
delete:
|
||||||
push:
|
push:
|
||||||
paths:
|
paths:
|
||||||
- ".github/workflows/cleanup-tags.yml"
|
- ".github/workflows/cleanup-tags.yml"
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: registry-tags-cleanup
|
group: registry-tags-cleanup
|
||||||
cancel-in-progress: false
|
cancel-in-progress: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
cleanup-images:
|
cleanup-images:
|
||||||
name: Cleanup Image Tags for ${{ matrix.primary-name }}
|
name: Cleanup Image Tags for ${{ matrix.primary-name }}
|
||||||
@ -30,10 +27,9 @@ jobs:
|
|||||||
# Requires a personal access token with the OAuth scope delete:packages
|
# Requires a personal access token with the OAuth scope delete:packages
|
||||||
TOKEN: ${{ secrets.GHA_CONTAINER_DELETE_TOKEN }}
|
TOKEN: ${{ secrets.GHA_CONTAINER_DELETE_TOKEN }}
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Clean temporary images
|
||||||
name: Clean temporary images
|
|
||||||
if: "${{ env.TOKEN != '' }}"
|
if: "${{ env.TOKEN != '' }}"
|
||||||
uses: stumpylog/image-cleaner-action/ephemeral@v0.9.0
|
uses: stumpylog/image-cleaner-action/ephemeral@v0.10.0
|
||||||
with:
|
with:
|
||||||
token: "${{ env.TOKEN }}"
|
token: "${{ env.TOKEN }}"
|
||||||
owner: "${{ github.repository_owner }}"
|
owner: "${{ github.repository_owner }}"
|
||||||
@ -43,7 +39,6 @@ jobs:
|
|||||||
repo_name: "paperless-ngx"
|
repo_name: "paperless-ngx"
|
||||||
match_regex: "(feature|fix)"
|
match_regex: "(feature|fix)"
|
||||||
do_delete: "true"
|
do_delete: "true"
|
||||||
|
|
||||||
cleanup-untagged-images:
|
cleanup-untagged-images:
|
||||||
name: Cleanup Untagged Images Tags for ${{ matrix.primary-name }}
|
name: Cleanup Untagged Images Tags for ${{ matrix.primary-name }}
|
||||||
if: github.repository_owner == 'paperless-ngx'
|
if: github.repository_owner == 'paperless-ngx'
|
||||||
@ -58,10 +53,9 @@ jobs:
|
|||||||
# Requires a personal access token with the OAuth scope delete:packages
|
# Requires a personal access token with the OAuth scope delete:packages
|
||||||
TOKEN: ${{ secrets.GHA_CONTAINER_DELETE_TOKEN }}
|
TOKEN: ${{ secrets.GHA_CONTAINER_DELETE_TOKEN }}
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Clean untagged images
|
||||||
name: Clean untagged images
|
|
||||||
if: "${{ env.TOKEN != '' }}"
|
if: "${{ env.TOKEN != '' }}"
|
||||||
uses: stumpylog/image-cleaner-action/untagged@v0.9.0
|
uses: stumpylog/image-cleaner-action/untagged@v0.10.0
|
||||||
with:
|
with:
|
||||||
token: "${{ env.TOKEN }}"
|
token: "${{ env.TOKEN }}"
|
||||||
owner: "${{ github.repository_owner }}"
|
owner: "${{ github.repository_owner }}"
|
||||||
|
6
.github/workflows/codeql-analysis.yml
vendored
6
.github/workflows/codeql-analysis.yml
vendored
@ -10,7 +10,6 @@
|
|||||||
# supported CodeQL languages.
|
# supported CodeQL languages.
|
||||||
#
|
#
|
||||||
name: "CodeQL"
|
name: "CodeQL"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main, dev]
|
branches: [main, dev]
|
||||||
@ -19,7 +18,6 @@ on:
|
|||||||
branches: [dev]
|
branches: [dev]
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '28 13 * * 5'
|
- cron: '28 13 * * 5'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
analyze:
|
analyze:
|
||||||
name: Analyze
|
name: Analyze
|
||||||
@ -28,18 +26,15 @@ jobs:
|
|||||||
actions: read
|
actions: read
|
||||||
contents: read
|
contents: read
|
||||||
security-events: write
|
security-events: write
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
language: ['javascript', 'python']
|
language: ['javascript', 'python']
|
||||||
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
|
||||||
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
# Learn more about CodeQL language support at https://git.io/codeql-language-support
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v3
|
||||||
@ -49,6 +44,5 @@ jobs:
|
|||||||
# By default, queries listed here will override any specified in a config file.
|
# By default, queries listed here will override any specified in a config file.
|
||||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
# queries: ./path/to/local/query, your-org/your-repo/queries@main
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@v3
|
uses: github/codeql-action/analyze@v3
|
||||||
|
9
.github/workflows/crowdin.yml
vendored
9
.github/workflows/crowdin.yml
vendored
@ -1,23 +1,16 @@
|
|||||||
name: Crowdin Action
|
name: Crowdin Action
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '2 */12 * * *'
|
- cron: '2 */12 * * *'
|
||||||
push:
|
push:
|
||||||
paths: [
|
paths: ['src/locale/**', 'src-ui/messages.xlf', 'src-ui/src/locale/**']
|
||||||
'src/locale/**',
|
|
||||||
'src-ui/messages.xlf',
|
|
||||||
'src-ui/src/locale/**'
|
|
||||||
]
|
|
||||||
branches: [dev]
|
branches: [dev]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
synchronize-with-crowdin:
|
synchronize-with-crowdin:
|
||||||
name: Crowdin Sync
|
name: Crowdin Sync
|
||||||
if: github.repository_owner == 'paperless-ngx'
|
if: github.repository_owner == 'paperless-ngx'
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
86
.github/workflows/pr-bot.yml
vendored
Normal file
86
.github/workflows/pr-bot.yml
vendored
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
name: PR Bot
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [opened]
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
jobs:
|
||||||
|
pr-bot:
|
||||||
|
name: Automated PR Bot
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Label by file path
|
||||||
|
uses: actions/labeler@v5
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Label by size
|
||||||
|
uses: Gascon1/pr-size-labeler@v1.3.0
|
||||||
|
with:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
xs_label: 'small-change'
|
||||||
|
xs_diff: '9'
|
||||||
|
s_label: 'non-trivial'
|
||||||
|
s_diff: '99999'
|
||||||
|
fail_if_xl: 'false'
|
||||||
|
excluded_files: /\.lock$/ /\.txt$/ ^src-ui/pnpm-lock\.yaml$ ^src-ui/messages\.xlf$ ^src/locale/en_US/LC_MESSAGES/django\.po$
|
||||||
|
- name: Label bot-generated PRs
|
||||||
|
if: ${{ contains(github.actor, 'dependabot') || contains(github.actor, 'crowdin-bot') }}
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const pr = context.payload.pull_request;
|
||||||
|
const user = pr.user.login.toLowerCase();
|
||||||
|
const labels = [];
|
||||||
|
|
||||||
|
if (user.includes('dependabot')) {
|
||||||
|
labels.push('dependencies');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.includes('crowdin-bot')) {
|
||||||
|
labels.push('translation', 'skip-changelog');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (labels.length) {
|
||||||
|
await github.rest.issues.addLabels({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
issue_number: pr.number,
|
||||||
|
labels,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
- name: Welcome comment
|
||||||
|
if: ${{ !contains(github.actor, 'bot') }}
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const pr = context.payload.pull_request;
|
||||||
|
const user = pr.user.login;
|
||||||
|
|
||||||
|
const { data: members } = await github.rest.orgs.listMembers({
|
||||||
|
org: 'paperless-ngx',
|
||||||
|
});
|
||||||
|
|
||||||
|
const memberLogins = members.map(m => m.login.toLowerCase());
|
||||||
|
if (memberLogins.includes(user.toLowerCase())) {
|
||||||
|
core.info('Skipping comment: user is org member');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const body =
|
||||||
|
"Hello @" + user + ",\n\n" +
|
||||||
|
"Thank you very much for submitting this PR to us!\n\n" +
|
||||||
|
"This is what will happen next:\n\n" +
|
||||||
|
"1. CI tests will run against your PR to ensure quality and consistency.\n" +
|
||||||
|
"2. Next, human contributors from paperless-ngx review your changes.\n" +
|
||||||
|
"3. Please address any issues that come up during the review as soon as you are able to.\n" +
|
||||||
|
"4. If accepted, your pull request will be merged into the `dev` branch and changes there will be tested further.\n" +
|
||||||
|
"5. Eventually, changes from you and other contributors will be merged into `main` and a new release will be made.\n\n" +
|
||||||
|
"You'll be hearing from us soon, and thank you again for contributing to our project.";
|
||||||
|
|
||||||
|
await github.rest.issues.createComment({
|
||||||
|
issue_number: pr.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body,
|
||||||
|
});
|
3
.github/workflows/project-actions.yml
vendored
3
.github/workflows/project-actions.yml
vendored
@ -1,5 +1,4 @@
|
|||||||
name: Project Automations
|
name: Project Automations
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request_target: #_target allows access to secrets
|
pull_request_target: #_target allows access to secrets
|
||||||
types:
|
types:
|
||||||
@ -8,10 +7,8 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
- dev
|
- dev
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pr_opened_or_reopened:
|
pr_opened_or_reopened:
|
||||||
name: pr_opened_or_reopened
|
name: pr_opened_or_reopened
|
||||||
|
27
.github/workflows/repo-maintenance.yml
vendored
27
.github/workflows/repo-maintenance.yml
vendored
@ -1,18 +1,14 @@
|
|||||||
name: 'Repository Maintenance'
|
name: 'Repository Maintenance'
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 3 * * *'
|
- cron: '0 3 * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
issues: write
|
issues: write
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
discussions: write
|
discussions: write
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: lock
|
group: lock
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
stale:
|
stale:
|
||||||
name: 'Stale'
|
name: 'Stale'
|
||||||
@ -27,9 +23,8 @@ jobs:
|
|||||||
stale-issue-label: stale
|
stale-issue-label: stale
|
||||||
stale-pr-label: stale
|
stale-pr-label: stale
|
||||||
stale-issue-message: >
|
stale-issue-message: >
|
||||||
This issue has been automatically marked as stale because it has not had
|
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
|
||||||
recent activity. It will be closed if no further activity occurs. Thank you
|
|
||||||
for your contributions. See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
|
|
||||||
lock-threads:
|
lock-threads:
|
||||||
name: 'Lock Old Threads'
|
name: 'Lock Old Threads'
|
||||||
if: github.repository_owner == 'paperless-ngx'
|
if: github.repository_owner == 'paperless-ngx'
|
||||||
@ -42,20 +37,14 @@ jobs:
|
|||||||
discussion-inactive-days: '30'
|
discussion-inactive-days: '30'
|
||||||
log-output: true
|
log-output: true
|
||||||
issue-comment: >
|
issue-comment: >
|
||||||
This issue has been automatically locked since there
|
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new discussion or issue for related concerns. See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
|
||||||
has not been any recent activity after it was closed.
|
|
||||||
Please open a new discussion or issue for related concerns.
|
|
||||||
See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
|
|
||||||
pr-comment: >
|
pr-comment: >
|
||||||
This pull request has been automatically locked since there
|
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new discussion or issue for related concerns. See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
|
||||||
has not been any recent activity after it was closed.
|
|
||||||
Please open a new discussion or issue for related concerns.
|
|
||||||
See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
|
|
||||||
discussion-comment: >
|
discussion-comment: >
|
||||||
This discussion has been automatically locked since there
|
This discussion has been automatically locked since there has not been any recent activity after it was closed. Please open a new discussion for related concerns. See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
|
||||||
has not been any recent activity after it was closed.
|
|
||||||
Please open a new discussion for related concerns.
|
|
||||||
See our [contributing guidelines](https://github.com/paperless-ngx/paperless-ngx/blob/dev/CONTRIBUTING.md#automatic-repository-maintenance) for more details.
|
|
||||||
close-answered-discussions:
|
close-answered-discussions:
|
||||||
name: 'Close Answered Discussions'
|
name: 'Close Answered Discussions'
|
||||||
if: github.repository_owner == 'paperless-ngx'
|
if: github.repository_owner == 'paperless-ngx'
|
||||||
|
69
.github/workflows/translate-strings.yml
vendored
Normal file
69
.github/workflows/translate-strings.yml
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
name: Generate Translation Strings
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
jobs:
|
||||||
|
generate-translate-strings:
|
||||||
|
name: Generate Translation Strings
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.PNGX_BOT_PAT }}
|
||||||
|
ref: ${{ github.head_ref }}
|
||||||
|
- name: Set up Python
|
||||||
|
id: setup-python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
- name: Install system dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get update -qq
|
||||||
|
sudo apt-get install -qq --no-install-recommends gettext
|
||||||
|
- name: Install uv
|
||||||
|
uses: astral-sh/setup-uv@v5
|
||||||
|
with:
|
||||||
|
enable-cache: true
|
||||||
|
- name: Install backend python dependencies
|
||||||
|
run: |
|
||||||
|
uv sync \
|
||||||
|
--group dev \
|
||||||
|
--frozen
|
||||||
|
- name: Generate backend translation strings
|
||||||
|
run: cd src/ && uv run manage.py makemessages -l en_US -i "samples*"
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
- name: Use Node.js 20
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
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@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.pnpm-store
|
||||||
|
~/.cache
|
||||||
|
key: ${{ runner.os }}-frontenddeps-${{ hashFiles('src-ui/pnpm-lock.yaml') }}
|
||||||
|
- name: Install frontend dependencies
|
||||||
|
if: steps.cache-frontend-deps.outputs.cache-hit != 'true'
|
||||||
|
run: cd src-ui && pnpm install
|
||||||
|
- name: Re-link Angular cli
|
||||||
|
run: cd src-ui && pnpm link @angular/cli
|
||||||
|
- name: Generate frontend translation strings
|
||||||
|
run: |
|
||||||
|
cd src-ui
|
||||||
|
pnpm run ng extract-i18n
|
||||||
|
- name: Commit changes
|
||||||
|
uses: stefanzweifel/git-auto-commit-action@v5
|
||||||
|
with:
|
||||||
|
file_pattern: 'src-ui/messages.xlf src/locale/en_US/LC_MESSAGES/django.po'
|
||||||
|
commit_message: "Auto translate strings"
|
||||||
|
commit_user_name: "GitHub Actions"
|
||||||
|
commit_author: "GitHub Actions <41898282+github-actions[bot]@users.noreply.github.com>"
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -44,6 +44,7 @@ nosetests.xml
|
|||||||
coverage.xml
|
coverage.xml
|
||||||
*,cover
|
*,cover
|
||||||
.pytest_cache
|
.pytest_cache
|
||||||
|
junit.xml
|
||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
*.mo
|
*.mo
|
||||||
|
@ -32,7 +32,7 @@ repos:
|
|||||||
rev: v2.4.0
|
rev: v2.4.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: codespell
|
- id: codespell
|
||||||
exclude: "(^src-ui/src/locale/)|(^src-ui/e2e/)|(^src/paperless_mail/tests/samples/)"
|
exclude: "(^src-ui/src/locale/)|(^src-ui/pnpm-lock.yaml)|(^src-ui/e2e/)|(^src/paperless_mail/tests/samples/)"
|
||||||
exclude_types:
|
exclude_types:
|
||||||
- pofile
|
- pofile
|
||||||
- json
|
- json
|
||||||
@ -45,16 +45,19 @@ repos:
|
|||||||
- javascript
|
- javascript
|
||||||
- ts
|
- ts
|
||||||
- markdown
|
- markdown
|
||||||
exclude: "(^Pipfile\\.lock$)"
|
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
- prettier@3.3.3
|
- prettier@3.3.3
|
||||||
- 'prettier-plugin-organize-imports@4.1.0'
|
- 'prettier-plugin-organize-imports@4.1.0'
|
||||||
# Python hooks
|
# Python hooks
|
||||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
rev: v0.9.2
|
rev: v0.9.9
|
||||||
hooks:
|
hooks:
|
||||||
- id: ruff
|
- id: ruff
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
|
- repo: https://github.com/tox-dev/pyproject-fmt
|
||||||
|
rev: "v2.5.1"
|
||||||
|
hooks:
|
||||||
|
- id: pyproject-fmt
|
||||||
# Dockerfile hooks
|
# Dockerfile hooks
|
||||||
- repo: https://github.com/AleksaC/hadolint-py
|
- repo: https://github.com/AleksaC/hadolint-py
|
||||||
rev: v2.12.0.3
|
rev: v2.12.0.3
|
||||||
@ -73,3 +76,8 @@ repos:
|
|||||||
rev: "v0.10.0.1"
|
rev: "v0.10.0.1"
|
||||||
hooks:
|
hooks:
|
||||||
- id: shellcheck
|
- id: shellcheck
|
||||||
|
- repo: https://github.com/google/yamlfmt
|
||||||
|
rev: v0.14.0
|
||||||
|
hooks:
|
||||||
|
- id: yamlfmt
|
||||||
|
exclude: "^src-ui/pnpm-lock.yaml"
|
||||||
|
@ -1 +0,0 @@
|
|||||||
3.10.15
|
|
85
.ruff.toml
85
.ruff.toml
@ -1,85 +0,0 @@
|
|||||||
fix = true
|
|
||||||
line-length = 88
|
|
||||||
respect-gitignore = true
|
|
||||||
src = ["src"]
|
|
||||||
target-version = "py310"
|
|
||||||
output-format = "grouped"
|
|
||||||
show-fixes = true
|
|
||||||
|
|
||||||
# https://docs.astral.sh/ruff/settings/
|
|
||||||
# https://docs.astral.sh/ruff/rules/
|
|
||||||
[lint]
|
|
||||||
extend-select = [
|
|
||||||
"W", # https://docs.astral.sh/ruff/rules/#pycodestyle-e-w
|
|
||||||
"I", # https://docs.astral.sh/ruff/rules/#isort-i
|
|
||||||
"UP", # https://docs.astral.sh/ruff/rules/#pyupgrade-up
|
|
||||||
"COM", # https://docs.astral.sh/ruff/rules/#flake8-commas-com
|
|
||||||
"DJ", # https://docs.astral.sh/ruff/rules/#flake8-django-dj
|
|
||||||
"EXE", # https://docs.astral.sh/ruff/rules/#flake8-executable-exe
|
|
||||||
"ISC", # https://docs.astral.sh/ruff/rules/#flake8-implicit-str-concat-isc
|
|
||||||
"ICN", # https://docs.astral.sh/ruff/rules/#flake8-import-conventions-icn
|
|
||||||
"G201", # https://docs.astral.sh/ruff/rules/#flake8-logging-format-g
|
|
||||||
"INP", # https://docs.astral.sh/ruff/rules/#flake8-no-pep420-inp
|
|
||||||
"PIE", # https://docs.astral.sh/ruff/rules/#flake8-pie-pie
|
|
||||||
"Q", # https://docs.astral.sh/ruff/rules/#flake8-quotes-q
|
|
||||||
"RSE", # https://docs.astral.sh/ruff/rules/#flake8-raise-rse
|
|
||||||
"T20", # https://docs.astral.sh/ruff/rules/#flake8-print-t20
|
|
||||||
"SIM", # https://docs.astral.sh/ruff/rules/#flake8-simplify-sim
|
|
||||||
"TID", # https://docs.astral.sh/ruff/rules/#flake8-tidy-imports-tid
|
|
||||||
"TCH", # https://docs.astral.sh/ruff/rules/#flake8-type-checking-tch
|
|
||||||
"PLC", # https://docs.astral.sh/ruff/rules/#pylint-pl
|
|
||||||
"PLE", # https://docs.astral.sh/ruff/rules/#pylint-pl
|
|
||||||
"RUF", # https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf
|
|
||||||
"FLY", # https://docs.astral.sh/ruff/rules/#flynt-fly
|
|
||||||
"PTH", # https://docs.astral.sh/ruff/rules/#flake8-use-pathlib-pth
|
|
||||||
]
|
|
||||||
ignore = ["DJ001", "SIM105", "RUF012"]
|
|
||||||
|
|
||||||
[lint.per-file-ignores]
|
|
||||||
".github/scripts/*.py" = ["E501", "INP001", "SIM117"]
|
|
||||||
"docker/wait-for-redis.py" = ["INP001", "T201"]
|
|
||||||
"src/documents/consumer.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/file_handling.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/management/commands/document_consumer.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/management/commands/document_exporter.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/migrations/0012_auto_20160305_0040.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/migrations/0014_document_checksum.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/migrations/1003_mime_types.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/migrations/1012_fix_archive_files.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/models.py" = ["SIM115", "PTH"] # TODO PTH Enable & remove
|
|
||||||
"src/documents/parsers.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/signals/handlers.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tasks.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_api_app_config.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_api_bulk_download.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_api_documents.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_classifier.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_consumer.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_file_handling.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_management.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_management_consumer.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_management_exporter.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_management_thumbnails.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_migration_archive_files.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_migration_document_pages_count.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_migration_mime_type.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_sanity_check.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_tasks.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/tests/test_views.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/documents/views.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/paperless/checks.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/paperless/settings.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/paperless/tests/test_checks.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/paperless/urls.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/paperless/views.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/paperless_mail/mail.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/paperless_mail/preprocessor.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/paperless_tesseract/parsers.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/paperless_tesseract/tests/test_parser.py" = ["RUF001", "PTH"] # TODO PTH Enable & remove
|
|
||||||
"src/paperless_tika/tests/test_live_tika.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"src/paperless_tika/tests/test_tika_parser.py" = ["PTH"] # TODO Enable & remove
|
|
||||||
"*/tests/*.py" = ["E501", "SIM117"]
|
|
||||||
"*/migrations/*.py" = ["E501", "SIM", "T201"]
|
|
||||||
|
|
||||||
[lint.isort]
|
|
||||||
force-single-line = true
|
|
@ -5,5 +5,6 @@
|
|||||||
/src-ui/ @paperless-ngx/frontend
|
/src-ui/ @paperless-ngx/frontend
|
||||||
|
|
||||||
/src/ @paperless-ngx/backend
|
/src/ @paperless-ngx/backend
|
||||||
Pipfile* @paperless-ngx/backend
|
pyproject.toml @paperless-ngx/backend
|
||||||
|
uv.lock @paperless-ngx/backend
|
||||||
*.py @paperless-ngx/backend
|
*.py @paperless-ngx/backend
|
||||||
|
@ -81,7 +81,7 @@ Some notes about translation:
|
|||||||
|
|
||||||
If a language has already been added, and you would like to contribute new translations or change existing translations, please read the "Translation" section in the README.md file for further details on that.
|
If a language has already been added, and you would like to contribute new translations or change existing translations, please read the "Translation" section in the README.md file for further details on that.
|
||||||
|
|
||||||
If you would like the project to be translated to another language, first head over to https://crwd.in/paperless-ngx to check if that language has already been enabled for translation.
|
If you would like the project to be translated to another language, first head over to https://crowdin.com/project/paperless-ngx to check if that language has already been enabled for translation.
|
||||||
If not, please request the language to be added by creating an issue on GitHub. The issue should contain:
|
If not, please request the language to be added by creating an issue on GitHub. The issue should contain:
|
||||||
|
|
||||||
- English name of the language (the localized name can be added on Crowdin).
|
- English name of the language (the localized name can be added on Crowdin).
|
||||||
|
181
Dockerfile
181
Dockerfile
@ -4,15 +4,17 @@
|
|||||||
# Stage: compile-frontend
|
# Stage: compile-frontend
|
||||||
# Purpose: Compiles the frontend
|
# Purpose: Compiles the frontend
|
||||||
# Notes:
|
# Notes:
|
||||||
# - Does NPM stuff with Typescript and such
|
# - Does PNPM stuff with Typescript and such
|
||||||
FROM --platform=$BUILDPLATFORM docker.io/node:20-bookworm-slim AS compile-frontend
|
FROM --platform=$BUILDPLATFORM docker.io/node:20-bookworm-slim AS compile-frontend
|
||||||
|
|
||||||
COPY ./src-ui /src/src-ui
|
COPY ./src-ui /src/src-ui
|
||||||
|
|
||||||
WORKDIR /src/src-ui
|
WORKDIR /src/src-ui
|
||||||
RUN set -eux \
|
RUN set -eux \
|
||||||
&& npm update npm -g \
|
&& npm update -g pnpm \
|
||||||
&& npm ci
|
&& npm install -g corepack@latest \
|
||||||
|
&& corepack enable \
|
||||||
|
&& pnpm install
|
||||||
|
|
||||||
ARG PNGX_TAG_VERSION=
|
ARG PNGX_TAG_VERSION=
|
||||||
# Add the tag to the environment file if its a tagged dev build
|
# Add the tag to the environment file if its a tagged dev build
|
||||||
@ -26,28 +28,66 @@ esac
|
|||||||
RUN set -eux \
|
RUN set -eux \
|
||||||
&& ./node_modules/.bin/ng build --configuration production
|
&& ./node_modules/.bin/ng build --configuration production
|
||||||
|
|
||||||
# Stage: pipenv-base
|
# Stage: s6-overlay-base
|
||||||
# Purpose: Generates a requirements.txt file for building
|
# Purpose: Installs s6-overlay and rootfs
|
||||||
# Comments:
|
# Comments:
|
||||||
# - pipenv dependencies are not left in the final image
|
# - Don't leave anything extra in here either
|
||||||
# - pipenv can't touch the final image somehow
|
FROM ghcr.io/astral-sh/uv:0.6.16-python3.12-bookworm-slim AS s6-overlay-base
|
||||||
FROM --platform=$BUILDPLATFORM docker.io/python:3.12-alpine AS pipenv-base
|
|
||||||
|
|
||||||
WORKDIR /usr/src/pipenv
|
WORKDIR /usr/src/s6
|
||||||
|
|
||||||
COPY Pipfile* ./
|
# https://github.com/just-containers/s6-overlay#customizing-s6-overlay-behaviour
|
||||||
|
ENV \
|
||||||
|
S6_BEHAVIOUR_IF_STAGE2_FAILS=2 \
|
||||||
|
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
|
||||||
|
S6_VERBOSITY=1 \
|
||||||
|
PATH=/command:$PATH
|
||||||
|
|
||||||
|
# Buildx provided, must be defined to use though
|
||||||
|
ARG TARGETARCH
|
||||||
|
ARG TARGETVARIANT
|
||||||
|
# Lock this version
|
||||||
|
ARG S6_OVERLAY_VERSION=3.2.0.2
|
||||||
|
|
||||||
|
ARG S6_BUILD_TIME_PKGS="curl \
|
||||||
|
xz-utils"
|
||||||
|
|
||||||
RUN set -eux \
|
RUN set -eux \
|
||||||
&& echo "Installing pipenv" \
|
&& echo "Installing build time packages" \
|
||||||
&& python3 -m pip install --no-cache-dir --upgrade pipenv==2024.4.1 \
|
&& apt-get update \
|
||||||
&& echo "Generating requirement.txt" \
|
&& apt-get install --yes --quiet --no-install-recommends ${S6_BUILD_TIME_PKGS} \
|
||||||
&& pipenv requirements > requirements.txt
|
&& echo "Determining arch" \
|
||||||
|
&& S6_ARCH="" \
|
||||||
|
&& if [ "${TARGETARCH}${TARGETVARIANT}" = "amd64" ]; then S6_ARCH="x86_64"; \
|
||||||
|
elif [ "${TARGETARCH}${TARGETVARIANT}" = "arm64" ]; then S6_ARCH="aarch64"; fi\
|
||||||
|
&& if [ -z "${S6_ARCH}" ]; then { echo "Error: Not able to determine arch"; exit 1; }; fi \
|
||||||
|
&& echo "Installing s6-overlay for ${S6_ARCH}" \
|
||||||
|
&& curl --fail --silent --no-progress-meter --show-error --location --remote-name-all --parallel --parallel-max 4 \
|
||||||
|
"https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz" \
|
||||||
|
"https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz.sha256" \
|
||||||
|
"https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-${S6_ARCH}.tar.xz" \
|
||||||
|
"https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-${S6_ARCH}.tar.xz.sha256" \
|
||||||
|
&& echo "Validating s6-archive checksums" \
|
||||||
|
&& sha256sum --check ./*.sha256 \
|
||||||
|
&& echo "Unpacking archives" \
|
||||||
|
&& tar --directory / -Jxpf s6-overlay-noarch.tar.xz \
|
||||||
|
&& tar --directory / -Jxpf s6-overlay-${S6_ARCH}.tar.xz \
|
||||||
|
&& echo "Removing downloaded archives" \
|
||||||
|
&& rm ./*.tar.xz \
|
||||||
|
&& rm ./*.sha256 \
|
||||||
|
&& echo "Cleaning up image" \
|
||||||
|
&& apt-get --yes purge ${S6_BUILD_TIME_PKGS} \
|
||||||
|
&& apt-get --yes autoremove --purge \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Copy our service defs and filesystem
|
||||||
|
COPY ./docker/rootfs /
|
||||||
|
|
||||||
# Stage: main-app
|
# Stage: main-app
|
||||||
# Purpose: The final image
|
# Purpose: The final image
|
||||||
# Comments:
|
# Comments:
|
||||||
# - Don't leave anything extra in here
|
# - Don't leave anything extra in here
|
||||||
FROM docker.io/python:3.12-slim-bookworm AS main-app
|
FROM s6-overlay-base AS main-app
|
||||||
|
|
||||||
LABEL org.opencontainers.image.authors="paperless-ngx team <hello@paperless-ngx.com>"
|
LABEL org.opencontainers.image.authors="paperless-ngx team <hello@paperless-ngx.com>"
|
||||||
LABEL org.opencontainers.image.documentation="https://docs.paperless-ngx.com/"
|
LABEL org.opencontainers.image.documentation="https://docs.paperless-ngx.com/"
|
||||||
@ -61,16 +101,19 @@ ARG DEBIAN_FRONTEND=noninteractive
|
|||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
|
|
||||||
# Can be workflow provided, defaults set for manual building
|
# Can be workflow provided, defaults set for manual building
|
||||||
ARG JBIG2ENC_VERSION=0.29
|
ARG JBIG2ENC_VERSION=0.30
|
||||||
ARG QPDF_VERSION=11.9.0
|
ARG QPDF_VERSION=11.9.0
|
||||||
ARG GS_VERSION=10.03.1
|
ARG GS_VERSION=10.03.1
|
||||||
|
|
||||||
# Set Python environment variables
|
# Set Python environment variables
|
||||||
ENV PYTHONDONTWRITEBYTECODE=1 \
|
ENV PYTHONDONTWRITEBYTECODE=1 \
|
||||||
PYTHONUNBUFFERED=1 \
|
PYTHONUNBUFFERED=1 \
|
||||||
# Ignore warning from Whitenoise
|
# Ignore warning from Whitenoise about async iterators
|
||||||
PYTHONWARNINGS="ignore:::django.http.response:517" \
|
PYTHONWARNINGS="ignore:::django.http.response:517" \
|
||||||
PNGX_CONTAINERIZED=1
|
PNGX_CONTAINERIZED=1 \
|
||||||
|
# https://docs.astral.sh/uv/reference/settings/#link-mode
|
||||||
|
UV_LINK_MODE=copy \
|
||||||
|
UV_CACHE_DIR=/cache/uv/
|
||||||
|
|
||||||
#
|
#
|
||||||
# Begin installation and configuration
|
# Begin installation and configuration
|
||||||
@ -127,118 +170,51 @@ RUN set -eux \
|
|||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES} \
|
&& apt-get install --yes --quiet --no-install-recommends ${RUNTIME_PACKAGES} \
|
||||||
&& echo "Installing pre-built updates" \
|
&& echo "Installing pre-built updates" \
|
||||||
&& echo "Installing qpdf ${QPDF_VERSION}" \
|
&& curl --fail --silent --no-progress-meter --show-error --location --remote-name-all --parallel --parallel-max 4 \
|
||||||
&& curl --fail --silent --show-error --location \
|
|
||||||
--output libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
|
||||||
https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
||||||
&& curl --fail --silent --show-error --location \
|
|
||||||
--output qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
|
||||||
https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
https://github.com/paperless-ngx/builder/releases/download/qpdf-${QPDF_VERSION}/qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
||||||
|
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
||||||
|
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
||||||
|
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10-common_${GS_VERSION}.dfsg-1_all.deb \
|
||||||
|
https://github.com/paperless-ngx/builder/releases/download/jbig2enc-${JBIG2ENC_VERSION}/jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
|
||||||
|
&& echo "Installing qpdf ${QPDF_VERSION}" \
|
||||||
&& dpkg --install ./libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
&& dpkg --install ./libqpdf29_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
||||||
&& dpkg --install ./qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
&& dpkg --install ./qpdf_${QPDF_VERSION}-1_${TARGETARCH}.deb \
|
||||||
&& echo "Installing Ghostscript ${GS_VERSION}" \
|
&& echo "Installing Ghostscript ${GS_VERSION}" \
|
||||||
&& curl --fail --silent --show-error --location \
|
|
||||||
--output libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
|
||||||
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
|
||||||
&& curl --fail --silent --show-error --location \
|
|
||||||
--output ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
|
||||||
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
|
||||||
&& curl --fail --silent --show-error --location \
|
|
||||||
--output libgs10-common_${GS_VERSION}.dfsg-1_all.deb \
|
|
||||||
https://github.com/paperless-ngx/builder/releases/download/ghostscript-${GS_VERSION}/libgs10-common_${GS_VERSION}.dfsg-1_all.deb \
|
|
||||||
&& dpkg --install ./libgs10-common_${GS_VERSION}.dfsg-1_all.deb \
|
&& dpkg --install ./libgs10-common_${GS_VERSION}.dfsg-1_all.deb \
|
||||||
&& dpkg --install ./libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
&& dpkg --install ./libgs10_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
||||||
&& dpkg --install ./ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
&& dpkg --install ./ghostscript_${GS_VERSION}.dfsg-1_${TARGETARCH}.deb \
|
||||||
&& echo "Installing jbig2enc" \
|
&& echo "Installing jbig2enc" \
|
||||||
&& curl --fail --silent --show-error --location \
|
|
||||||
--output jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
|
|
||||||
https://github.com/paperless-ngx/builder/releases/download/jbig2enc-${JBIG2ENC_VERSION}/jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
|
|
||||||
&& dpkg --install ./jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
|
&& dpkg --install ./jbig2enc_${JBIG2ENC_VERSION}-1_${TARGETARCH}.deb \
|
||||||
|
&& echo "Configuring imagemagick" \
|
||||||
|
&& cp /etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-6/policy.xml \
|
||||||
&& echo "Cleaning up image layer" \
|
&& echo "Cleaning up image layer" \
|
||||||
&& rm --force --verbose *.deb \
|
&& rm --force --verbose *.deb \
|
||||||
&& rm --recursive --force --verbose /var/lib/apt/lists/* \
|
&& rm --recursive --force --verbose /var/lib/apt/lists/*
|
||||||
&& echo "Installing supervisor" \
|
|
||||||
&& python3 -m pip install --default-timeout=1000 --upgrade --no-cache-dir supervisor==4.2.5
|
|
||||||
|
|
||||||
# Copy gunicorn config
|
|
||||||
# Changes very infrequently
|
|
||||||
WORKDIR /usr/src/paperless/
|
|
||||||
|
|
||||||
COPY gunicorn.conf.py .
|
|
||||||
|
|
||||||
# setup docker-specific things
|
|
||||||
# These change sometimes, but rarely
|
|
||||||
WORKDIR /usr/src/paperless/src/docker/
|
|
||||||
|
|
||||||
COPY [ \
|
|
||||||
"docker/imagemagick-policy.xml", \
|
|
||||||
"docker/supervisord.conf", \
|
|
||||||
"docker/docker-entrypoint.sh", \
|
|
||||||
"docker/docker-prepare.sh", \
|
|
||||||
"docker/paperless_cmd.sh", \
|
|
||||||
"docker/wait-for-redis.py", \
|
|
||||||
"docker/env-from-file.sh", \
|
|
||||||
"docker/management_script.sh", \
|
|
||||||
"docker/flower-conditional.sh", \
|
|
||||||
"docker/install_management_commands.sh", \
|
|
||||||
"/usr/src/paperless/src/docker/" \
|
|
||||||
]
|
|
||||||
|
|
||||||
RUN set -eux \
|
|
||||||
&& echo "Configuring ImageMagick" \
|
|
||||||
&& mv imagemagick-policy.xml /etc/ImageMagick-6/policy.xml \
|
|
||||||
&& echo "Configuring supervisord" \
|
|
||||||
&& mkdir /var/log/supervisord /var/run/supervisord \
|
|
||||||
&& mv supervisord.conf /etc/supervisord.conf \
|
|
||||||
&& echo "Setting up Docker scripts" \
|
|
||||||
&& mv docker-entrypoint.sh /sbin/docker-entrypoint.sh \
|
|
||||||
&& chmod 755 /sbin/docker-entrypoint.sh \
|
|
||||||
&& mv docker-prepare.sh /sbin/docker-prepare.sh \
|
|
||||||
&& chmod 755 /sbin/docker-prepare.sh \
|
|
||||||
&& mv wait-for-redis.py /sbin/wait-for-redis.py \
|
|
||||||
&& chmod 755 /sbin/wait-for-redis.py \
|
|
||||||
&& mv env-from-file.sh /sbin/env-from-file.sh \
|
|
||||||
&& chmod 755 /sbin/env-from-file.sh \
|
|
||||||
&& mv paperless_cmd.sh /usr/local/bin/paperless_cmd.sh \
|
|
||||||
&& chmod 755 /usr/local/bin/paperless_cmd.sh \
|
|
||||||
&& mv flower-conditional.sh /usr/local/bin/flower-conditional.sh \
|
|
||||||
&& chmod 755 /usr/local/bin/flower-conditional.sh \
|
|
||||||
&& echo "Installing management commands" \
|
|
||||||
&& chmod +x install_management_commands.sh \
|
|
||||||
&& ./install_management_commands.sh
|
|
||||||
|
|
||||||
WORKDIR /usr/src/paperless/src/
|
WORKDIR /usr/src/paperless/src/
|
||||||
|
|
||||||
# Python dependencies
|
# Python dependencies
|
||||||
# Change pretty frequently
|
# Change pretty frequently
|
||||||
COPY --from=pipenv-base /usr/src/pipenv/requirements.txt ./
|
COPY --chown=1000:1000 ["pyproject.toml", "uv.lock", "/usr/src/paperless/src/"]
|
||||||
|
|
||||||
# Packages needed only for building a few quick Python
|
# Packages needed only for building a few quick Python
|
||||||
# dependencies
|
# dependencies
|
||||||
ARG BUILD_PACKAGES="\
|
ARG BUILD_PACKAGES="\
|
||||||
build-essential \
|
build-essential \
|
||||||
git \
|
|
||||||
# https://www.psycopg.org/docs/install.html#prerequisites
|
|
||||||
libpq-dev \
|
|
||||||
# https://github.com/PyMySQL/mysqlclient#linux
|
# https://github.com/PyMySQL/mysqlclient#linux
|
||||||
default-libmysqlclient-dev \
|
default-libmysqlclient-dev \
|
||||||
pkg-config"
|
pkg-config"
|
||||||
|
|
||||||
# hadolint ignore=DL3042
|
# hadolint ignore=DL3042
|
||||||
RUN --mount=type=cache,target=/root/.cache/pip/,id=pip-cache \
|
RUN --mount=type=cache,target=${UV_CACHE_DIR},id=python-cache \
|
||||||
set -eux \
|
set -eux \
|
||||||
&& echo "Installing build system packages" \
|
&& echo "Installing build system packages" \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get install --yes --quiet --no-install-recommends ${BUILD_PACKAGES} \
|
&& apt-get install --yes --quiet --no-install-recommends ${BUILD_PACKAGES} \
|
||||||
&& python3 -m pip install --no-cache-dir --upgrade wheel \
|
|
||||||
&& echo "Installing Python requirements" \
|
&& echo "Installing Python requirements" \
|
||||||
&& curl --fail --silent --show-error --location \
|
&& uv export --quiet --no-dev --all-extras --format requirements-txt --output-file requirements.txt \
|
||||||
--output psycopg_c-3.2.4-cp312-cp312-linux_x86_64.whl \
|
&& uv pip install --system --no-python-downloads --python-preference system --requirements requirements.txt \
|
||||||
https://github.com/paperless-ngx/builder/releases/download/psycopg-3.2.4/psycopg_c-3.2.4-cp312-cp312-linux_x86_64.whl \
|
|
||||||
&& curl --fail --silent --show-error --location \
|
|
||||||
--output psycopg_c-3.2.4-cp312-cp312-linux_aarch64.whl \
|
|
||||||
https://github.com/paperless-ngx/builder/releases/download/psycopg-3.2.4/psycopg_c-3.2.4-cp312-cp312-linux_aarch64.whl \
|
|
||||||
&& python3 -m pip install --default-timeout=1000 --find-links . --requirement requirements.txt \
|
|
||||||
&& echo "Installing NLTK data" \
|
&& echo "Installing NLTK data" \
|
||||||
&& python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" snowball_data \
|
&& python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" snowball_data \
|
||||||
&& python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" stopwords \
|
&& python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" stopwords \
|
||||||
@ -263,6 +239,7 @@ COPY --from=compile-frontend --chown=1000:1000 /src/src/documents/static/fronten
|
|||||||
# add users, setup scripts
|
# add users, setup scripts
|
||||||
# Mount the compiled frontend to expected location
|
# Mount the compiled frontend to expected location
|
||||||
RUN set -eux \
|
RUN set -eux \
|
||||||
|
&& sed -i '1s|^#!/usr/bin/env python3|#!/command/with-contenv python3|' manage.py \
|
||||||
&& echo "Setting up user/group" \
|
&& echo "Setting up user/group" \
|
||||||
&& addgroup --gid 1000 paperless \
|
&& addgroup --gid 1000 paperless \
|
||||||
&& useradd --uid 1000 --gid paperless --home-dir /usr/src/paperless paperless \
|
&& useradd --uid 1000 --gid paperless --home-dir /usr/src/paperless paperless \
|
||||||
@ -276,18 +253,16 @@ RUN set -eux \
|
|||||||
&& echo "Adjusting all permissions" \
|
&& echo "Adjusting all permissions" \
|
||||||
&& chown --from root:root --changes --recursive paperless:paperless /usr/src/paperless \
|
&& chown --from root:root --changes --recursive paperless:paperless /usr/src/paperless \
|
||||||
&& echo "Collecting static files" \
|
&& echo "Collecting static files" \
|
||||||
&& gosu paperless python3 manage.py collectstatic --clear --no-input --link \
|
&& s6-setuidgid paperless python3 manage.py collectstatic --clear --no-input --link \
|
||||||
&& gosu paperless python3 manage.py compilemessages
|
&& s6-setuidgid paperless python3 manage.py compilemessages
|
||||||
|
|
||||||
VOLUME ["/usr/src/paperless/data", \
|
VOLUME ["/usr/src/paperless/data", \
|
||||||
"/usr/src/paperless/media", \
|
"/usr/src/paperless/media", \
|
||||||
"/usr/src/paperless/consume", \
|
"/usr/src/paperless/consume", \
|
||||||
"/usr/src/paperless/export"]
|
"/usr/src/paperless/export"]
|
||||||
|
|
||||||
ENTRYPOINT ["/sbin/docker-entrypoint.sh"]
|
ENTRYPOINT ["/init"]
|
||||||
|
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
CMD ["/usr/local/bin/paperless_cmd.sh"]
|
|
||||||
|
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --retries=5 CMD [ "curl", "-fs", "-S", "--max-time", "2", "http://localhost:8000" ]
|
HEALTHCHECK --interval=30s --timeout=10s --retries=5 CMD [ "curl", "-fs", "-S", "--max-time", "2", "http://localhost:8000" ]
|
||||||
|
100
Pipfile
100
Pipfile
@ -1,100 +0,0 @@
|
|||||||
[[source]]
|
|
||||||
url = "https://pypi.python.org/simple"
|
|
||||||
verify_ssl = true
|
|
||||||
name = "pypi"
|
|
||||||
|
|
||||||
[packages]
|
|
||||||
dateparser = "~=1.2"
|
|
||||||
# WARNING: django does not use semver.
|
|
||||||
# Only patch versions are guaranteed to not introduce breaking changes.
|
|
||||||
django = "~=5.1.5"
|
|
||||||
django-allauth = {extras = ["mfa", "socialaccount"], version = "*"}
|
|
||||||
django-auditlog = "*"
|
|
||||||
django-celery-results = "*"
|
|
||||||
django-compression-middleware = "*"
|
|
||||||
django-cors-headers = "*"
|
|
||||||
django-extensions = "*"
|
|
||||||
django-filter = "~=24.3"
|
|
||||||
django-guardian = "*"
|
|
||||||
django-multiselectfield = "*"
|
|
||||||
django-soft-delete = "*"
|
|
||||||
djangorestframework = "~=3.15.2"
|
|
||||||
djangorestframework-guardian = "*"
|
|
||||||
drf-writable-nested = "*"
|
|
||||||
bleach = "*"
|
|
||||||
celery = {extras = ["redis"], version = "*"}
|
|
||||||
channels = "~=4.2"
|
|
||||||
channels-redis = "*"
|
|
||||||
concurrent-log-handler = "*"
|
|
||||||
filelock = "*"
|
|
||||||
flower = "*"
|
|
||||||
gotenberg-client = "*"
|
|
||||||
gunicorn = "*"
|
|
||||||
httpx-oauth = "*"
|
|
||||||
imap-tools = "*"
|
|
||||||
inotifyrecursive = "~=0.3"
|
|
||||||
jinja2 = "~=3.1"
|
|
||||||
langdetect = "*"
|
|
||||||
mysqlclient = "*"
|
|
||||||
nltk = "*"
|
|
||||||
ocrmypdf = "~=16.8"
|
|
||||||
pathvalidate = "*"
|
|
||||||
pdf2image = "*"
|
|
||||||
psycopg = {version = "*", extras = ["c"]}
|
|
||||||
python-dateutil = "*"
|
|
||||||
python-dotenv = "*"
|
|
||||||
python-gnupg = "*"
|
|
||||||
python-ipware = "*"
|
|
||||||
python-magic = "*"
|
|
||||||
pyzbar = "*"
|
|
||||||
rapidfuzz = "*"
|
|
||||||
redis = {extras = ["hiredis"], version = "*"}
|
|
||||||
scikit-learn = "~=1.6"
|
|
||||||
setproctitle = "*"
|
|
||||||
tika-client = "*"
|
|
||||||
tqdm = "*"
|
|
||||||
# See https://github.com/paperless-ngx/paperless-ngx/issues/5494
|
|
||||||
uvicorn = {extras = ["standard"], version = "==0.25.0"}
|
|
||||||
watchdog = "~=6.0"
|
|
||||||
whitenoise = "~=6.8"
|
|
||||||
whoosh = "~=2.7"
|
|
||||||
zxing-cpp = {version = "*", platform_machine = "== 'x86_64'"}
|
|
||||||
|
|
||||||
|
|
||||||
[dev-packages]
|
|
||||||
# Linting
|
|
||||||
pre-commit = "*"
|
|
||||||
ruff = "*"
|
|
||||||
factory-boy = "*"
|
|
||||||
# Testing
|
|
||||||
pytest = "*"
|
|
||||||
pytest-cov = "*"
|
|
||||||
pytest-django = "*"
|
|
||||||
pytest-httpx = "*"
|
|
||||||
pytest-env = "*"
|
|
||||||
pytest-sugar = "*"
|
|
||||||
pytest-xdist = "*"
|
|
||||||
pytest-mock = "*"
|
|
||||||
pytest-rerunfailures = "*"
|
|
||||||
imagehash = "*"
|
|
||||||
daphne = "*"
|
|
||||||
# Documentation
|
|
||||||
mkdocs-material = "*"
|
|
||||||
mkdocs-glightbox = "*"
|
|
||||||
|
|
||||||
[typing-dev]
|
|
||||||
mypy = "*"
|
|
||||||
types-Pillow = "*"
|
|
||||||
django-filter-stubs = "*"
|
|
||||||
types-python-dateutil = "*"
|
|
||||||
djangorestframework-stubs = {extras= ["compatible-mypy"], version="*"}
|
|
||||||
celery-types = "*"
|
|
||||||
django-stubs = {extras= ["compatible-mypy"], version="*"}
|
|
||||||
types-dateparser = "*"
|
|
||||||
types-bleach = "*"
|
|
||||||
types-redis = "*"
|
|
||||||
types-tqdm = "*"
|
|
||||||
types-Markdown = "*"
|
|
||||||
types-Pygments = "*"
|
|
||||||
types-colorama = "*"
|
|
||||||
types-setuptools = "*"
|
|
4806
Pipfile.lock
generated
4806
Pipfile.lock
generated
File diff suppressed because it is too large
Load Diff
@ -83,7 +83,7 @@ People interested in continuing the work on paperless-ngx are encouraged to reac
|
|||||||
|
|
||||||
## Translation
|
## Translation
|
||||||
|
|
||||||
Paperless-ngx is available in many languages that are coordinated on Crowdin. If you want to help out by translating paperless-ngx into your language, please head over to https://crwd.in/paperless-ngx, and thank you! More details can be found in [CONTRIBUTING.md](https://github.com/paperless-ngx/paperless-ngx/blob/main/CONTRIBUTING.md#translating-paperless-ngx).
|
Paperless-ngx is available in many languages that are coordinated on Crowdin. If you want to help out by translating paperless-ngx into your language, please head over to https://crowdin.com/project/paperless-ngx, and thank you! More details can be found in [CONTRIBUTING.md](https://github.com/paperless-ngx/paperless-ngx/blob/main/CONTRIBUTING.md#translating-paperless-ngx).
|
||||||
|
|
||||||
## Feature Requests
|
## Feature Requests
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
gotenberg:
|
gotenberg:
|
||||||
image: docker.io/gotenberg/gotenberg:8.7
|
image: docker.io/gotenberg/gotenberg:8.20
|
||||||
hostname: gotenberg
|
hostname: gotenberg
|
||||||
container_name: gotenberg
|
container_name: gotenberg
|
||||||
network_mode: host
|
network_mode: host
|
||||||
|
@ -24,8 +24,8 @@
|
|||||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||||
# and '.env' into a folder.
|
# and '.env' into a folder.
|
||||||
# - Run 'docker compose pull'.
|
# - Run 'docker compose pull'.
|
||||||
# - Run 'docker compose run --rm webserver createsuperuser' to create a user.
|
|
||||||
# - Run 'docker compose up -d'.
|
# - Run 'docker compose up -d'.
|
||||||
|
|
||||||
#
|
#
|
||||||
# For more extensive installation and update instructions, refer to the
|
# For more extensive installation and update instructions, refer to the
|
||||||
# documentation.
|
# documentation.
|
||||||
@ -36,7 +36,6 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- redisdata:/data
|
- redisdata:/data
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: docker.io/library/mariadb:11
|
image: docker.io/library/mariadb:11
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -48,7 +47,6 @@ services:
|
|||||||
MARIADB_USER: paperless
|
MARIADB_USER: paperless
|
||||||
MARIADB_PASSWORD: paperless
|
MARIADB_PASSWORD: paperless
|
||||||
MARIADB_ROOT_PASSWORD: paperless
|
MARIADB_ROOT_PASSWORD: paperless
|
||||||
|
|
||||||
webserver:
|
webserver:
|
||||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -75,9 +73,8 @@ services:
|
|||||||
PAPERLESS_TIKA_ENABLED: 1
|
PAPERLESS_TIKA_ENABLED: 1
|
||||||
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
||||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||||
|
|
||||||
gotenberg:
|
gotenberg:
|
||||||
image: docker.io/gotenberg/gotenberg:8.7
|
image: docker.io/gotenberg/gotenberg:8.20
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
# The gotenberg chromium route is used to convert .eml files. We do not
|
# The gotenberg chromium route is used to convert .eml files. We do not
|
||||||
# want to allow external content like tracking pixels or even javascript.
|
# want to allow external content like tracking pixels or even javascript.
|
||||||
@ -85,11 +82,9 @@ services:
|
|||||||
- "gotenberg"
|
- "gotenberg"
|
||||||
- "--chromium-disable-javascript=true"
|
- "--chromium-disable-javascript=true"
|
||||||
- "--chromium-allow-list=file:///tmp/.*"
|
- "--chromium-allow-list=file:///tmp/.*"
|
||||||
|
|
||||||
tika:
|
tika:
|
||||||
image: docker.io/apache/tika:latest
|
image: docker.io/apache/tika:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
data:
|
data:
|
||||||
media:
|
media:
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||||
# and '.env' into a folder.
|
# and '.env' into a folder.
|
||||||
# - Run 'docker compose pull'.
|
# - Run 'docker compose pull'.
|
||||||
# - Run 'docker compose run --rm webserver createsuperuser' to create a user.
|
|
||||||
# - Run 'docker compose up -d'.
|
# - Run 'docker compose up -d'.
|
||||||
#
|
#
|
||||||
# For more extensive installation and update instructions, refer to the
|
# For more extensive installation and update instructions, refer to the
|
||||||
@ -32,7 +31,6 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- redisdata:/data
|
- redisdata:/data
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: docker.io/library/mariadb:11
|
image: docker.io/library/mariadb:11
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -44,7 +42,6 @@ services:
|
|||||||
MARIADB_USER: paperless
|
MARIADB_USER: paperless
|
||||||
MARIADB_PASSWORD: paperless
|
MARIADB_PASSWORD: paperless
|
||||||
MARIADB_ROOT_PASSWORD: paperless
|
MARIADB_ROOT_PASSWORD: paperless
|
||||||
|
|
||||||
webserver:
|
webserver:
|
||||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -66,7 +63,6 @@ services:
|
|||||||
PAPERLESS_DBUSER: paperless # only needed if non-default username
|
PAPERLESS_DBUSER: paperless # only needed if non-default username
|
||||||
PAPERLESS_DBPASS: paperless # only needed if non-default password
|
PAPERLESS_DBPASS: paperless # only needed if non-default password
|
||||||
PAPERLESS_DBPORT: 3306
|
PAPERLESS_DBPORT: 3306
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
data:
|
data:
|
||||||
media:
|
media:
|
||||||
|
@ -22,10 +22,6 @@
|
|||||||
# - Upload 'docker-compose.env' by clicking on 'Load variables from .env file'
|
# - Upload 'docker-compose.env' by clicking on 'Load variables from .env file'
|
||||||
# - Modify the environment variables as needed
|
# - Modify the environment variables as needed
|
||||||
# - Click 'Deploy the stack' and wait for it to be deployed
|
# - Click 'Deploy the stack' and wait for it to be deployed
|
||||||
# - Open the list of containers, select paperless_webserver_1
|
|
||||||
# - Click 'Console' and then 'Connect' to open the command line inside the container
|
|
||||||
# - Run 'python3 manage.py createsuperuser' to create a user
|
|
||||||
# - Exit the console
|
|
||||||
#
|
#
|
||||||
# For more extensive installation and update instructions, refer to the
|
# For more extensive installation and update instructions, refer to the
|
||||||
# documentation.
|
# documentation.
|
||||||
@ -36,9 +32,8 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- redisdata:/data
|
- redisdata:/data
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: docker.io/library/postgres:16
|
image: docker.io/library/postgres:17
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- pgdata:/var/lib/postgresql/data
|
- pgdata:/var/lib/postgresql/data
|
||||||
@ -46,7 +41,6 @@ services:
|
|||||||
POSTGRES_DB: paperless
|
POSTGRES_DB: paperless
|
||||||
POSTGRES_USER: paperless
|
POSTGRES_USER: paperless
|
||||||
POSTGRES_PASSWORD: paperless
|
POSTGRES_PASSWORD: paperless
|
||||||
|
|
||||||
webserver:
|
webserver:
|
||||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -65,7 +59,6 @@ services:
|
|||||||
PAPERLESS_DBHOST: db
|
PAPERLESS_DBHOST: db
|
||||||
env_file:
|
env_file:
|
||||||
- stack.env
|
- stack.env
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
data:
|
data:
|
||||||
media:
|
media:
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||||
# and '.env' into a folder.
|
# and '.env' into a folder.
|
||||||
# - Run 'docker compose pull'.
|
# - Run 'docker compose pull'.
|
||||||
# - Run 'docker compose run --rm webserver createsuperuser' to create a user.
|
|
||||||
# - Run 'docker compose up -d'.
|
# - Run 'docker compose up -d'.
|
||||||
#
|
#
|
||||||
# For more extensive installation and update instructions, refer to the
|
# For more extensive installation and update instructions, refer to the
|
||||||
@ -36,9 +35,8 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- redisdata:/data
|
- redisdata:/data
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: docker.io/library/postgres:16
|
image: docker.io/library/postgres:17
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- pgdata:/var/lib/postgresql/data
|
- pgdata:/var/lib/postgresql/data
|
||||||
@ -46,7 +44,6 @@ services:
|
|||||||
POSTGRES_DB: paperless
|
POSTGRES_DB: paperless
|
||||||
POSTGRES_USER: paperless
|
POSTGRES_USER: paperless
|
||||||
POSTGRES_PASSWORD: paperless
|
POSTGRES_PASSWORD: paperless
|
||||||
|
|
||||||
webserver:
|
webserver:
|
||||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -69,22 +66,18 @@ services:
|
|||||||
PAPERLESS_TIKA_ENABLED: 1
|
PAPERLESS_TIKA_ENABLED: 1
|
||||||
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
||||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||||
|
|
||||||
gotenberg:
|
gotenberg:
|
||||||
image: docker.io/gotenberg/gotenberg:8.7
|
image: docker.io/gotenberg/gotenberg:8.20
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
# The gotenberg chromium route is used to convert .eml files. We do not
|
# The gotenberg chromium route is used to convert .eml files. We do not
|
||||||
# want to allow external content like tracking pixels or even javascript.
|
# want to allow external content like tracking pixels or even javascript.
|
||||||
command:
|
command:
|
||||||
- "gotenberg"
|
- "gotenberg"
|
||||||
- "--chromium-disable-javascript=true"
|
- "--chromium-disable-javascript=true"
|
||||||
- "--chromium-allow-list=file:///tmp/.*"
|
- "--chromium-allow-list=file:///tmp/.*"
|
||||||
|
|
||||||
tika:
|
tika:
|
||||||
image: docker.io/apache/tika:latest
|
image: docker.io/apache/tika:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
data:
|
data:
|
||||||
media:
|
media:
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||||
# and '.env' into a folder.
|
# and '.env' into a folder.
|
||||||
# - Run 'docker compose pull'.
|
# - Run 'docker compose pull'.
|
||||||
# - Run 'docker compose run --rm webserver createsuperuser' to create a user.
|
|
||||||
# - Run 'docker compose up -d'.
|
# - Run 'docker compose up -d'.
|
||||||
#
|
#
|
||||||
# For more extensive installation and update instructions, refer to the
|
# For more extensive installation and update instructions, refer to the
|
||||||
@ -32,9 +31,8 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- redisdata:/data
|
- redisdata:/data
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: docker.io/library/postgres:16
|
image: docker.io/library/postgres:17
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- pgdata:/var/lib/postgresql/data
|
- pgdata:/var/lib/postgresql/data
|
||||||
@ -42,7 +40,6 @@ services:
|
|||||||
POSTGRES_DB: paperless
|
POSTGRES_DB: paperless
|
||||||
POSTGRES_USER: paperless
|
POSTGRES_USER: paperless
|
||||||
POSTGRES_PASSWORD: paperless
|
POSTGRES_PASSWORD: paperless
|
||||||
|
|
||||||
webserver:
|
webserver:
|
||||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -60,7 +57,6 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
PAPERLESS_REDIS: redis://broker:6379
|
PAPERLESS_REDIS: redis://broker:6379
|
||||||
PAPERLESS_DBHOST: db
|
PAPERLESS_DBHOST: db
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
data:
|
data:
|
||||||
media:
|
media:
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||||
# and '.env' into a folder.
|
# and '.env' into a folder.
|
||||||
# - Run 'docker compose pull'.
|
# - Run 'docker compose pull'.
|
||||||
# - Run 'docker compose run --rm webserver createsuperuser' to create a user.
|
|
||||||
# - Run 'docker compose up -d'.
|
# - Run 'docker compose up -d'.
|
||||||
#
|
#
|
||||||
# For more extensive installation and update instructions, refer to the
|
# For more extensive installation and update instructions, refer to the
|
||||||
@ -36,7 +35,6 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- redisdata:/data
|
- redisdata:/data
|
||||||
|
|
||||||
webserver:
|
webserver:
|
||||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -57,22 +55,18 @@ services:
|
|||||||
PAPERLESS_TIKA_ENABLED: 1
|
PAPERLESS_TIKA_ENABLED: 1
|
||||||
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
PAPERLESS_TIKA_GOTENBERG_ENDPOINT: http://gotenberg:3000
|
||||||
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
PAPERLESS_TIKA_ENDPOINT: http://tika:9998
|
||||||
|
|
||||||
gotenberg:
|
gotenberg:
|
||||||
image: docker.io/gotenberg/gotenberg:8.7
|
image: docker.io/gotenberg/gotenberg:8.20
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
# The gotenberg chromium route is used to convert .eml files. We do not
|
# The gotenberg chromium route is used to convert .eml files. We do not
|
||||||
# want to allow external content like tracking pixels or even javascript.
|
# want to allow external content like tracking pixels or even javascript.
|
||||||
command:
|
command:
|
||||||
- "gotenberg"
|
- "gotenberg"
|
||||||
- "--chromium-disable-javascript=true"
|
- "--chromium-disable-javascript=true"
|
||||||
- "--chromium-allow-list=file:///tmp/.*"
|
- "--chromium-allow-list=file:///tmp/.*"
|
||||||
|
|
||||||
tika:
|
tika:
|
||||||
image: docker.io/apache/tika:latest
|
image: docker.io/apache/tika:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
data:
|
data:
|
||||||
media:
|
media:
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
# - Copy this file as 'docker-compose.yml' and the files 'docker-compose.env'
|
||||||
# and '.env' into a folder.
|
# and '.env' into a folder.
|
||||||
# - Run 'docker compose pull'.
|
# - Run 'docker compose pull'.
|
||||||
# - Run 'docker compose run --rm webserver createsuperuser' to create a user.
|
|
||||||
# - Run 'docker compose up -d'.
|
# - Run 'docker compose up -d'.
|
||||||
#
|
#
|
||||||
# For more extensive installation and update instructions, refer to the
|
# For more extensive installation and update instructions, refer to the
|
||||||
@ -29,7 +28,6 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- redisdata:/data
|
- redisdata:/data
|
||||||
|
|
||||||
webserver:
|
webserver:
|
||||||
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
image: ghcr.io/paperless-ngx/paperless-ngx:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -45,7 +43,6 @@ services:
|
|||||||
env_file: docker-compose.env
|
env_file: docker-compose.env
|
||||||
environment:
|
environment:
|
||||||
PAPERLESS_REDIS: redis://broker:6379
|
PAPERLESS_REDIS: redis://broker:6379
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
data:
|
data:
|
||||||
media:
|
media:
|
||||||
|
@ -1,179 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
# Source: https://github.com/sameersbn/docker-gitlab/
|
|
||||||
map_uidgid() {
|
|
||||||
local -r usermap_original_uid=$(id -u paperless)
|
|
||||||
local -r usermap_original_gid=$(id -g paperless)
|
|
||||||
local -r usermap_new_uid=${USERMAP_UID:-$usermap_original_uid}
|
|
||||||
local -r usermap_new_gid=${USERMAP_GID:-${usermap_original_gid:-$usermap_new_uid}}
|
|
||||||
if [[ ${usermap_new_uid} != "${usermap_original_uid}" || ${usermap_new_gid} != "${usermap_original_gid}" ]]; then
|
|
||||||
echo "Mapping UID and GID for paperless:paperless to $usermap_new_uid:$usermap_new_gid"
|
|
||||||
usermod --non-unique --uid "${usermap_new_uid}" paperless
|
|
||||||
groupmod --non-unique --gid "${usermap_new_gid}" paperless
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
map_folders() {
|
|
||||||
# Export these so they can be used in docker-prepare.sh
|
|
||||||
export DATA_DIR="${PAPERLESS_DATA_DIR:-/usr/src/paperless/data}"
|
|
||||||
export MEDIA_ROOT_DIR="${PAPERLESS_MEDIA_ROOT:-/usr/src/paperless/media}"
|
|
||||||
export CONSUME_DIR="${PAPERLESS_CONSUMPTION_DIR:-/usr/src/paperless/consume}"
|
|
||||||
}
|
|
||||||
|
|
||||||
custom_container_init() {
|
|
||||||
# Mostly borrowed from the LinuxServer.io base image
|
|
||||||
# https://github.com/linuxserver/docker-baseimage-ubuntu/tree/bionic/root/etc/cont-init.d
|
|
||||||
local -r custom_script_dir="/custom-cont-init.d"
|
|
||||||
# Tamper checking.
|
|
||||||
# Don't run files which are owned by anyone except root
|
|
||||||
# Don't run files which are writeable by others
|
|
||||||
if [ -d "${custom_script_dir}" ]; then
|
|
||||||
if [ -n "$(/usr/bin/find "${custom_script_dir}" -maxdepth 1 ! -user root)" ]; then
|
|
||||||
echo "**** Potential tampering with custom scripts detected ****"
|
|
||||||
echo "**** The folder '${custom_script_dir}' must be owned by root ****"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
if [ -n "$(/usr/bin/find "${custom_script_dir}" -maxdepth 1 -perm -o+w)" ]; then
|
|
||||||
echo "**** The folder '${custom_script_dir}' or some of contents have write permissions for others, which is a security risk. ****"
|
|
||||||
echo "**** Please review the permissions and their contents to make sure they are owned by root, and can only be modified by root. ****"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Make sure custom init directory has files in it
|
|
||||||
if [ -n "$(/bin/ls --almost-all "${custom_script_dir}" 2>/dev/null)" ]; then
|
|
||||||
echo "[custom-init] files found in ${custom_script_dir} executing"
|
|
||||||
# Loop over files in the directory
|
|
||||||
for SCRIPT in "${custom_script_dir}"/*; do
|
|
||||||
NAME="$(basename "${SCRIPT}")"
|
|
||||||
if [ -f "${SCRIPT}" ]; then
|
|
||||||
echo "[custom-init] ${NAME}: executing..."
|
|
||||||
/bin/bash "${SCRIPT}"
|
|
||||||
echo "[custom-init] ${NAME}: exited $?"
|
|
||||||
elif [ ! -f "${SCRIPT}" ]; then
|
|
||||||
echo "[custom-init] ${NAME}: is not a file"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
echo "[custom-init] no custom files found exiting..."
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
initialize() {
|
|
||||||
|
|
||||||
# Setup environment from secrets before anything else
|
|
||||||
# Check for a version of this var with _FILE appended
|
|
||||||
# and convert the contents to the env var value
|
|
||||||
# Source it so export is persistent
|
|
||||||
# shellcheck disable=SC1091
|
|
||||||
source /sbin/env-from-file.sh
|
|
||||||
|
|
||||||
# Change the user and group IDs if needed
|
|
||||||
map_uidgid
|
|
||||||
|
|
||||||
# Check for overrides of certain folders
|
|
||||||
map_folders
|
|
||||||
|
|
||||||
local -r export_dir="/usr/src/paperless/export"
|
|
||||||
|
|
||||||
for dir in \
|
|
||||||
"${export_dir}" \
|
|
||||||
"${DATA_DIR}" "${DATA_DIR}/index" \
|
|
||||||
"${MEDIA_ROOT_DIR}" "${MEDIA_ROOT_DIR}/documents" "${MEDIA_ROOT_DIR}/documents/originals" "${MEDIA_ROOT_DIR}/documents/thumbnails" \
|
|
||||||
"${CONSUME_DIR}"; do
|
|
||||||
if [[ ! -d "${dir}" ]]; then
|
|
||||||
echo "Creating directory ${dir}"
|
|
||||||
mkdir --parents --verbose "${dir}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
local -r tmp_dir="${PAPERLESS_SCRATCH_DIR:=/tmp/paperless}"
|
|
||||||
echo "Creating directory scratch directory ${tmp_dir}"
|
|
||||||
mkdir --parents --verbose "${tmp_dir}"
|
|
||||||
|
|
||||||
set +e
|
|
||||||
echo "Adjusting permissions of paperless files. This may take a while."
|
|
||||||
chown -R paperless:paperless "${tmp_dir}"
|
|
||||||
for dir in \
|
|
||||||
"${export_dir}" \
|
|
||||||
"${DATA_DIR}" \
|
|
||||||
"${MEDIA_ROOT_DIR}" \
|
|
||||||
"${CONSUME_DIR}"; do
|
|
||||||
find "${dir}" -not \( -user paperless -and -group paperless \) -exec chown --changes paperless:paperless {} +
|
|
||||||
done
|
|
||||||
set -e
|
|
||||||
|
|
||||||
"${gosu_cmd[@]}" /sbin/docker-prepare.sh
|
|
||||||
|
|
||||||
# Leave this last thing
|
|
||||||
custom_container_init
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
install_languages() {
|
|
||||||
echo "Installing languages..."
|
|
||||||
|
|
||||||
read -ra langs <<<"$1"
|
|
||||||
|
|
||||||
# Check that it is not empty
|
|
||||||
if [ ${#langs[@]} -eq 0 ]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Build list of packages to install
|
|
||||||
to_install=()
|
|
||||||
for lang in "${langs[@]}"; do
|
|
||||||
pkg="tesseract-ocr-$lang"
|
|
||||||
|
|
||||||
if dpkg --status "$pkg" &>/dev/null; then
|
|
||||||
echo "Package $pkg already installed!"
|
|
||||||
continue
|
|
||||||
else
|
|
||||||
to_install+=("$pkg")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# Use apt only when we install packages
|
|
||||||
if [ ${#to_install[@]} -gt 0 ]; then
|
|
||||||
apt-get update
|
|
||||||
|
|
||||||
for pkg in "${to_install[@]}"; do
|
|
||||||
|
|
||||||
if ! apt-cache show "$pkg" &>/dev/null; then
|
|
||||||
echo "Skipped $pkg: Package not found! :("
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Installing package $pkg..."
|
|
||||||
if ! apt-get --assume-yes install "$pkg" &>/dev/null; then
|
|
||||||
echo "Could not install $pkg"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
echo "Paperless-ngx docker container starting..."
|
|
||||||
|
|
||||||
gosu_cmd=(gosu paperless)
|
|
||||||
if [ "$(id --user)" == "$(id --user paperless)" ]; then
|
|
||||||
gosu_cmd=()
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install additional languages if specified
|
|
||||||
if [[ -n "$PAPERLESS_OCR_LANGUAGES" ]]; then
|
|
||||||
install_languages "$PAPERLESS_OCR_LANGUAGES"
|
|
||||||
fi
|
|
||||||
|
|
||||||
initialize
|
|
||||||
|
|
||||||
if [[ "$1" != "/"* ]]; then
|
|
||||||
echo Executing management command "$@"
|
|
||||||
exec "${gosu_cmd[@]}" python3 manage.py "$@"
|
|
||||||
else
|
|
||||||
echo Executing "$@"
|
|
||||||
exec "$@"
|
|
||||||
fi
|
|
@ -1,120 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
wait_for_postgres() {
|
|
||||||
local attempt_num=1
|
|
||||||
local -r max_attempts=5
|
|
||||||
|
|
||||||
echo "Waiting for PostgreSQL to start..."
|
|
||||||
|
|
||||||
local -r host="${PAPERLESS_DBHOST:-localhost}"
|
|
||||||
local -r port="${PAPERLESS_DBPORT:-5432}"
|
|
||||||
|
|
||||||
# Disable warning, host and port can't have spaces
|
|
||||||
# shellcheck disable=SC2086
|
|
||||||
while [ ! "$(pg_isready --host ${host} --port ${port})" ]; do
|
|
||||||
|
|
||||||
if [ $attempt_num -eq $max_attempts ]; then
|
|
||||||
echo "Unable to connect to database."
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "Attempt $attempt_num failed! Trying again in 5 seconds..."
|
|
||||||
fi
|
|
||||||
|
|
||||||
attempt_num=$(("$attempt_num" + 1))
|
|
||||||
sleep 5
|
|
||||||
done
|
|
||||||
echo "Connected to PostgreSQL"
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_for_mariadb() {
|
|
||||||
echo "Waiting for MariaDB to start..."
|
|
||||||
|
|
||||||
local -r host="${PAPERLESS_DBHOST:=localhost}"
|
|
||||||
local -r port="${PAPERLESS_DBPORT:=3306}"
|
|
||||||
|
|
||||||
local attempt_num=1
|
|
||||||
local -r max_attempts=5
|
|
||||||
|
|
||||||
# Disable warning, host and port can't have spaces
|
|
||||||
# shellcheck disable=SC2086
|
|
||||||
while ! true > /dev/tcp/$host/$port; do
|
|
||||||
|
|
||||||
if [ $attempt_num -eq $max_attempts ]; then
|
|
||||||
echo "Unable to connect to database."
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "Attempt $attempt_num failed! Trying again in 5 seconds..."
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
attempt_num=$(("$attempt_num" + 1))
|
|
||||||
sleep 5
|
|
||||||
done
|
|
||||||
echo "Connected to MariaDB"
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_for_redis() {
|
|
||||||
# We use a Python script to send the Redis ping
|
|
||||||
# instead of installing redis-tools just for 1 thing
|
|
||||||
if ! python3 /sbin/wait-for-redis.py; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
migrations() {
|
|
||||||
(
|
|
||||||
# flock is in place to prevent multiple containers from doing migrations
|
|
||||||
# simultaneously. This also ensures that the db is ready when the command
|
|
||||||
# of the current container starts.
|
|
||||||
flock 200
|
|
||||||
echo "Apply database migrations..."
|
|
||||||
python3 manage.py migrate --skip-checks --no-input
|
|
||||||
) 200>"${DATA_DIR}/migration_lock"
|
|
||||||
}
|
|
||||||
|
|
||||||
django_checks() {
|
|
||||||
# Explicitly run the Django system checks
|
|
||||||
echo "Running Django checks"
|
|
||||||
python3 manage.py check
|
|
||||||
}
|
|
||||||
|
|
||||||
search_index() {
|
|
||||||
|
|
||||||
local -r index_version=9
|
|
||||||
local -r index_version_file=${DATA_DIR}/.index_version
|
|
||||||
|
|
||||||
if [[ (! -f "${index_version_file}") || $(<"${index_version_file}") != "$index_version" ]]; then
|
|
||||||
echo "Search index out of date. Updating..."
|
|
||||||
python3 manage.py document_index reindex --no-progress-bar
|
|
||||||
echo ${index_version} | tee "${index_version_file}" >/dev/null
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
superuser() {
|
|
||||||
if [[ -n "${PAPERLESS_ADMIN_USER}" ]]; then
|
|
||||||
python3 manage.py manage_superuser
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
do_work() {
|
|
||||||
if [[ "${PAPERLESS_DBENGINE}" == "mariadb" ]]; then
|
|
||||||
wait_for_mariadb
|
|
||||||
elif [[ -n "${PAPERLESS_DBHOST}" ]]; then
|
|
||||||
wait_for_postgres
|
|
||||||
fi
|
|
||||||
|
|
||||||
wait_for_redis
|
|
||||||
|
|
||||||
migrations
|
|
||||||
|
|
||||||
django_checks
|
|
||||||
|
|
||||||
search_index
|
|
||||||
|
|
||||||
superuser
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
do_work
|
|
@ -1,42 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Scans the environment variables for those with the suffix _FILE
|
|
||||||
# When located, checks the file exists, and exports the contents
|
|
||||||
# of the file as the same name, minus the suffix
|
|
||||||
# This allows the use of Docker secrets or mounted files
|
|
||||||
# to fill in any of the settings configurable via environment
|
|
||||||
# variables
|
|
||||||
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
for line in $(printenv)
|
|
||||||
do
|
|
||||||
# Extract the name of the environment variable
|
|
||||||
env_name=${line%%=*}
|
|
||||||
# Check if it starts with "PAPERLESS_" and ends in "_FILE"
|
|
||||||
if [[ ${env_name} == PAPERLESS_*_FILE ]]; then
|
|
||||||
# This should have been named different..
|
|
||||||
if [[ ${env_name} == "PAPERLESS_OCR_SKIP_ARCHIVE_FILE" || ${env_name} == "PAPERLESS_MODEL_FILE" ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
# Extract the value of the environment
|
|
||||||
env_value=${line#*=}
|
|
||||||
|
|
||||||
# Check the file exists
|
|
||||||
if [[ -f ${env_value} ]]; then
|
|
||||||
|
|
||||||
# Trim off the _FILE suffix
|
|
||||||
non_file_env_name=${env_name%"_FILE"}
|
|
||||||
echo "Setting ${non_file_env_name} from file"
|
|
||||||
|
|
||||||
# Reads the value from th file
|
|
||||||
val="$(< "${!env_name}")"
|
|
||||||
|
|
||||||
# Sets the normal name to the read file contents
|
|
||||||
export "${non_file_env_name}"="${val}"
|
|
||||||
|
|
||||||
else
|
|
||||||
echo "File ${env_value} referenced by ${env_name} doesn't exist"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
@ -1,12 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
echo "Checking if we should start flower..."
|
|
||||||
|
|
||||||
if [[ -n "${PAPERLESS_ENABLE_FLOWER}" ]]; then
|
|
||||||
# Small delay to allow celery to be up first
|
|
||||||
echo "Starting flower in 5s"
|
|
||||||
sleep 5
|
|
||||||
celery --app paperless flower --conf=/usr/src/paperless/src/paperless/flowerconfig.py
|
|
||||||
else
|
|
||||||
echo "Not starting flower"
|
|
||||||
fi
|
|
BIN
docker/init-flow.drawio.png
Normal file
BIN
docker/init-flow.drawio.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 30 KiB |
@ -1,5 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# Run this script to generate the management commands again (for example if a new command is create or the template is updated)
|
||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
for command in decrypt_documents \
|
for command in decrypt_documents \
|
||||||
@ -16,9 +18,10 @@ for command in decrypt_documents \
|
|||||||
document_fuzzy_match \
|
document_fuzzy_match \
|
||||||
manage_superuser \
|
manage_superuser \
|
||||||
convert_mariadb_uuid \
|
convert_mariadb_uuid \
|
||||||
prune_audit_logs;
|
prune_audit_logs \
|
||||||
|
createsuperuser;
|
||||||
do
|
do
|
||||||
echo "installing $command..."
|
echo "installing $command..."
|
||||||
sed "s/management_command/$command/g" management_script.sh > /usr/local/bin/$command
|
sed "s/management_command/$command/g" management_script.sh >"$PWD/rootfs/usr/local/bin/$command"
|
||||||
chmod +x /usr/local/bin/$command
|
chmod u=rwx,g=rwx,o=rx "$PWD/rootfs/usr/local/bin/$command"
|
||||||
done
|
done
|
||||||
|
@ -1,17 +1,13 @@
|
|||||||
#!/usr/bin/env bash
|
#!/command/with-contenv /usr/bin/bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
cd /usr/src/paperless/src/
|
cd "${PAPERLESS_SRC_DIR}"
|
||||||
# This ensures environment is setup
|
|
||||||
# shellcheck disable=SC1091
|
|
||||||
source /sbin/env-from-file.sh
|
|
||||||
|
|
||||||
if [[ $(id -u) == 0 ]] ;
|
if [[ $(id -u) == 0 ]]; then
|
||||||
then
|
s6-setuidgid paperless python3 manage.py management_command "$@"
|
||||||
gosu paperless python3 manage.py management_command "$@"
|
elif [[ $(id -un) == "paperless" ]]; then
|
||||||
elif [[ $(id -un) == "paperless" ]] ;
|
|
||||||
then
|
|
||||||
python3 manage.py management_command "$@"
|
python3 manage.py management_command "$@"
|
||||||
else
|
else
|
||||||
echo "Unknown user."
|
echo "Unknown user."
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
SUPERVISORD_WORKING_DIR="${PAPERLESS_SUPERVISORD_WORKING_DIR:-$PWD}"
|
|
||||||
rootless_args=()
|
|
||||||
if [ "$(id -u)" == "$(id -u paperless)" ]; then
|
|
||||||
rootless_args=(
|
|
||||||
--user
|
|
||||||
paperless
|
|
||||||
--logfile
|
|
||||||
"${SUPERVISORD_WORKING_DIR}/supervisord.log"
|
|
||||||
--pidfile
|
|
||||||
"${SUPERVISORD_WORKING_DIR}/supervisord.pid"
|
|
||||||
)
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec /usr/local/bin/supervisord -c /etc/supervisord.conf "${rootless_args[@]}"
|
|
0
docker/rootfs/etc/s6-overlay/s6-rc.d/init-complete/dependencies.d/init-tesseract-langs
Normal file
0
docker/rootfs/etc/s6-overlay/s6-rc.d/init-complete/dependencies.d/init-tesseract-langs
Normal file
8
docker/rootfs/etc/s6-overlay/s6-rc.d/init-complete/run
Executable file
8
docker/rootfs/etc/s6-overlay/s6-rc.d/init-complete/run
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/command/with-contenv /usr/bin/bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
declare -r log_prefix="[init-complete]"
|
||||||
|
declare -r end_time=$(date +%s)
|
||||||
|
declare -r start_time=${PAPERLESS_START_TIME_S}
|
||||||
|
|
||||||
|
echo "${log_prefix} paperless-ngx docker container init completed in $(($end_time-$start_time)) seconds"
|
||||||
|
echo "${log_prefix} Starting services"
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-complete/type
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-complete/type
Normal file
@ -0,0 +1 @@
|
|||||||
|
oneshot
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-complete/up
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-complete/up
Normal file
@ -0,0 +1 @@
|
|||||||
|
/etc/s6-overlay/s6-rc.d/init-complete/run
|
0
docker/rootfs/etc/s6-overlay/s6-rc.d/init-custom-init/dependencies.d/init-search-index
Normal file
0
docker/rootfs/etc/s6-overlay/s6-rc.d/init-custom-init/dependencies.d/init-search-index
Normal file
0
docker/rootfs/etc/s6-overlay/s6-rc.d/init-custom-init/dependencies.d/init-system-checks
Normal file
0
docker/rootfs/etc/s6-overlay/s6-rc.d/init-custom-init/dependencies.d/init-system-checks
Normal file
0
docker/rootfs/etc/s6-overlay/s6-rc.d/init-custom-init/dependencies.d/init-tesseract-langs
Normal file
0
docker/rootfs/etc/s6-overlay/s6-rc.d/init-custom-init/dependencies.d/init-tesseract-langs
Normal file
0
docker/rootfs/etc/s6-overlay/s6-rc.d/init-custom-init/dependencies.d/init-wait-for-redis
Normal file
0
docker/rootfs/etc/s6-overlay/s6-rc.d/init-custom-init/dependencies.d/init-wait-for-redis
Normal file
44
docker/rootfs/etc/s6-overlay/s6-rc.d/init-custom-init/run
Executable file
44
docker/rootfs/etc/s6-overlay/s6-rc.d/init-custom-init/run
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
#!/command/with-contenv /usr/bin/bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
declare -r log_prefix="[custom-init]"
|
||||||
|
|
||||||
|
# Mostly borrowed from the LinuxServer.io base image
|
||||||
|
# https://github.com/linuxserver/docker-baseimage-ubuntu/tree/bionic/root/etc/cont-init.d
|
||||||
|
declare -r custom_script_dir="/custom-cont-init.d"
|
||||||
|
|
||||||
|
# Tamper checking.
|
||||||
|
# Don't run files which are owned by anyone except root
|
||||||
|
# Don't run files which are writeable by others
|
||||||
|
if [ -d "${custom_script_dir}" ]; then
|
||||||
|
if [ -n "$(/usr/bin/find "${custom_script_dir}" -maxdepth 1 ! -user root)" ]; then
|
||||||
|
echo "${log_prefix} **** Potential tampering with custom scripts detected ****"
|
||||||
|
echo "${log_prefix} **** The folder '${custom_script_dir}' must be owned by root ****"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [ -n "$(/usr/bin/find "${custom_script_dir}" -maxdepth 1 -perm -o+w)" ]; then
|
||||||
|
echo "${log_prefix} **** The folder '${custom_script_dir}' or some of contents have write permissions for others, which is a security risk. ****"
|
||||||
|
echo "${log_prefix} **** Please review the permissions and their contents to make sure they are owned by root, and can only be modified by root. ****"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make sure custom init directory has files in it
|
||||||
|
if [ -n "$(/bin/ls --almost-all "${custom_script_dir}" 2>/dev/null)" ]; then
|
||||||
|
echo "${log_prefix} files found in ${custom_script_dir} executing"
|
||||||
|
# Loop over files in the directory
|
||||||
|
for SCRIPT in "${custom_script_dir}"/*; do
|
||||||
|
NAME="$(basename "${SCRIPT}")"
|
||||||
|
if [ -f "${SCRIPT}" ]; then
|
||||||
|
echo "${log_prefix} ${NAME}: executing..."
|
||||||
|
/command/with-contenv /bin/bash "${SCRIPT}"
|
||||||
|
echo "${log_prefix} ${NAME}: exited $?"
|
||||||
|
elif [ ! -f "${SCRIPT}" ]; then
|
||||||
|
echo "${log_prefix} ${NAME}: is not a file"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "${log_prefix} no custom files found exiting..."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "${log_prefix} ${custom_script_dir} doesn't exist, nothing to do"
|
||||||
|
fi
|
@ -0,0 +1 @@
|
|||||||
|
oneshot
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-custom-init/up
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-custom-init/up
Normal file
@ -0,0 +1 @@
|
|||||||
|
/etc/s6-overlay/s6-rc.d/init-custom-init/run
|
33
docker/rootfs/etc/s6-overlay/s6-rc.d/init-env-file/run
Executable file
33
docker/rootfs/etc/s6-overlay/s6-rc.d/init-env-file/run
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/command/with-contenv /usr/bin/bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
declare -r log_prefix="[env-init]"
|
||||||
|
|
||||||
|
echo "${log_prefix} Checking for environment from files"
|
||||||
|
|
||||||
|
if find /run/s6/container_environment/*"_FILE" -maxdepth 1 > /dev/null 2>&1; then
|
||||||
|
for FILENAME in /run/s6/container_environment/*; do
|
||||||
|
if [[ "${FILENAME##*/}" == PAPERLESS_*_FILE ]]; then
|
||||||
|
# This should have been named different..
|
||||||
|
if [[ ${FILENAME} == "PAPERLESS_OCR_SKIP_ARCHIVE_FILE" || ${FILENAME} == "PAPERLESS_MODEL_FILE" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
SECRETFILE=$(cat "${FILENAME}")
|
||||||
|
# Check the file exists
|
||||||
|
if [[ -f ${SECRETFILE} ]]; then
|
||||||
|
# Trim off trailing _FILE
|
||||||
|
FILESTRIP=${FILENAME//_FILE/}
|
||||||
|
if [[ $(tail -n1 "${SECRETFILE}" | wc -l) != 0 ]]; then
|
||||||
|
echo "${log_prefix} Your secret: ${FILENAME##*/} contains a trailing newline and may not work as expected"
|
||||||
|
fi
|
||||||
|
# Set environment variable
|
||||||
|
cat "${SECRETFILE}" > "${FILESTRIP}"
|
||||||
|
echo "${log_prefix} ${FILESTRIP##*/} set from ${FILENAME##*/}"
|
||||||
|
else
|
||||||
|
echo "${log_prefix} cannot find secret in ${FILENAME##*/}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
echo "${log_prefix} No *_FILE environment found"
|
||||||
|
fi
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-env-file/type
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-env-file/type
Normal file
@ -0,0 +1 @@
|
|||||||
|
oneshot
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-env-file/up
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-env-file/up
Normal file
@ -0,0 +1 @@
|
|||||||
|
/etc/s6-overlay/s6-rc.d/init-env-file/run
|
65
docker/rootfs/etc/s6-overlay/s6-rc.d/init-folders/run
Executable file
65
docker/rootfs/etc/s6-overlay/s6-rc.d/init-folders/run
Executable file
@ -0,0 +1,65 @@
|
|||||||
|
#!/command/with-contenv /usr/bin/bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
declare -r log_prefix="[init-folders]"
|
||||||
|
|
||||||
|
declare -r export_dir="/usr/src/paperless/export"
|
||||||
|
declare -r data_dir="${PAPERLESS_DATA_DIR:-/usr/src/paperless/data}"
|
||||||
|
declare -r media_root_dir="${PAPERLESS_MEDIA_ROOT:-/usr/src/paperless/media}"
|
||||||
|
declare -r consume_dir="${PAPERLESS_CONSUMPTION_DIR:-/usr/src/paperless/consume}"
|
||||||
|
declare -r tmp_dir="${PAPERLESS_SCRATCH_DIR:=/tmp/paperless}"
|
||||||
|
|
||||||
|
declare -r main_dirs=(
|
||||||
|
"${export_dir}"
|
||||||
|
"${data_dir}"
|
||||||
|
"${media_root_dir}"
|
||||||
|
"${consume_dir}"
|
||||||
|
"${tmp_dir}"
|
||||||
|
)
|
||||||
|
|
||||||
|
declare -r extra_dirs=(
|
||||||
|
"${main_dirs[@]}"
|
||||||
|
"${data_dir}/index"
|
||||||
|
"${media_root_dir}/documents"
|
||||||
|
"${media_root_dir}/documents/originals"
|
||||||
|
"${media_root_dir}/documents/thumbnails"
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ -n "${USER_IS_NON_ROOT}" ]]; then
|
||||||
|
# Non-root mode: Create directories as current user, warn about permission issues
|
||||||
|
echo "${log_prefix} Running in non-root mode, checking directories"
|
||||||
|
current_uid=$(id --user)
|
||||||
|
current_gid=$(id --group)
|
||||||
|
|
||||||
|
for dir in "${extra_dirs[@]}"; do
|
||||||
|
if [[ ! -d "${dir}" ]]; then
|
||||||
|
mkdir --parents --verbose "${dir}" || echo "${log_prefix} WARNING: Could not create ${dir} - permission denied"
|
||||||
|
fi
|
||||||
|
# Check permissions on existing directories too
|
||||||
|
if [[ -d "${dir}" && ! -w "${dir}" ]]; then
|
||||||
|
echo "${log_prefix} WARNING: No write permission to ${dir}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Warn about ownership issues
|
||||||
|
for dir in "${main_dirs[@]}"; do
|
||||||
|
if [[ -d "${dir}" ]]; then
|
||||||
|
find "${dir}" -not \( -user ${current_uid} -and -group ${current_gid} \) -exec echo "${log_prefix} WARNING: Permission issue on {}: not owned by current user (${current_uid}:${current_gid})" \; 2>/dev/null || echo "${log_prefix} WARNING: Cannot check permissions on ${dir}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
# Root mode: Create and fix permissions as needed
|
||||||
|
echo "${log_prefix} Running with root privileges, adjusting directories and permissions"
|
||||||
|
|
||||||
|
# First create directories
|
||||||
|
for dir in "${extra_dirs[@]}"; do
|
||||||
|
if [[ ! -d "${dir}" ]]; then
|
||||||
|
mkdir --parents --verbose "${dir}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Then fix permissions on all directories
|
||||||
|
for dir in "${main_dirs[@]}"; do
|
||||||
|
find "${dir}" -not \( -user paperless -and -group paperless \) -exec chown --changes paperless:paperless {} +
|
||||||
|
done
|
||||||
|
fi
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-folders/type
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-folders/type
Normal file
@ -0,0 +1 @@
|
|||||||
|
oneshot
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-folders/up
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-folders/up
Normal file
@ -0,0 +1 @@
|
|||||||
|
/etc/s6-overlay/s6-rc.d/init-folders/run
|
18
docker/rootfs/etc/s6-overlay/s6-rc.d/init-migrations/run
Executable file
18
docker/rootfs/etc/s6-overlay/s6-rc.d/init-migrations/run
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
#!/command/with-contenv /usr/bin/bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
declare -r log_prefix="[init-migrations]"
|
||||||
|
|
||||||
|
declare -r data_dir="${PAPERLESS_DATA_DIR:-/usr/src/paperless/data}"
|
||||||
|
|
||||||
|
echo "${log_prefix} Apply database migrations..."
|
||||||
|
|
||||||
|
cd "${PAPERLESS_SRC_DIR}"
|
||||||
|
|
||||||
|
# The whole migrate, with flock, needs to run as the right user
|
||||||
|
if [[ -n "${USER_IS_NON_ROOT}" ]]; then
|
||||||
|
exec s6-setlock -n "${data_dir}/migration_lock" python3 manage.py migrate --skip-checks --no-input
|
||||||
|
else
|
||||||
|
exec s6-setuidgid paperless \
|
||||||
|
s6-setlock -n "${data_dir}/migration_lock" \
|
||||||
|
python3 manage.py migrate --skip-checks --no-input
|
||||||
|
fi
|
@ -0,0 +1 @@
|
|||||||
|
oneshot
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-migrations/up
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-migrations/up
Normal file
@ -0,0 +1 @@
|
|||||||
|
/etc/s6-overlay/s6-rc.d/init-migrations/run
|
22
docker/rootfs/etc/s6-overlay/s6-rc.d/init-modify-user/run
Executable file
22
docker/rootfs/etc/s6-overlay/s6-rc.d/init-modify-user/run
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/command/with-contenv /usr/bin/bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
declare -r log_prefix="[init-user]"
|
||||||
|
|
||||||
|
declare -r usermap_original_uid=$(id -u paperless)
|
||||||
|
declare -r usermap_original_gid=$(id -g paperless)
|
||||||
|
declare -r usermap_new_uid=${USERMAP_UID:-$usermap_original_uid}
|
||||||
|
declare -r usermap_new_gid=${USERMAP_GID:-${usermap_original_gid:-$usermap_new_uid}}
|
||||||
|
|
||||||
|
if [[ ${usermap_new_uid} != "${usermap_original_uid}" ]]; then
|
||||||
|
echo "${log_prefix} Mapping UID for paperless to $usermap_new_uid"
|
||||||
|
usermod --non-unique --uid "${usermap_new_uid}" paperless
|
||||||
|
else
|
||||||
|
echo "${log_prefix} No UID changes for paperless"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${usermap_new_gid} != "${usermap_original_gid}" ]]; then
|
||||||
|
echo "${log_prefix} Mapping GID for paperless to $usermap_new_gid"
|
||||||
|
groupmod --non-unique --gid "${usermap_new_gid}" paperless
|
||||||
|
else
|
||||||
|
echo "${log_prefix} No GID changes for paperless"
|
||||||
|
fi
|
@ -0,0 +1 @@
|
|||||||
|
oneshot
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-modify-user/up
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-modify-user/up
Normal file
@ -0,0 +1 @@
|
|||||||
|
/etc/s6-overlay/s6-rc.d/init-modify-user/run
|
28
docker/rootfs/etc/s6-overlay/s6-rc.d/init-search-index/run
Executable file
28
docker/rootfs/etc/s6-overlay/s6-rc.d/init-search-index/run
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
#!/command/with-contenv /usr/bin/bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
declare -r log_prefix="[init-index]"
|
||||||
|
|
||||||
|
declare -r index_version=9
|
||||||
|
declare -r data_dir="${PAPERLESS_DATA_DIR:-/usr/src/paperless/data}"
|
||||||
|
declare -r index_version_file="${data_dir}/.index_version"
|
||||||
|
|
||||||
|
update_index () {
|
||||||
|
echo "${log_prefix} Search index out of date. Updating..."
|
||||||
|
cd "${PAPERLESS_SRC_DIR}"
|
||||||
|
if [[ -n "${USER_IS_NON_ROOT}" ]]; then
|
||||||
|
python3 manage.py document_index reindex --no-progress-bar
|
||||||
|
echo ${index_version} | tee "${index_version_file}" > /dev/null
|
||||||
|
else
|
||||||
|
s6-setuidgid paperless python3 manage.py document_index reindex --no-progress-bar
|
||||||
|
echo ${index_version} | s6-setuidgid paperless tee "${index_version_file}" > /dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ (! -f "${index_version_file}") ]]; then
|
||||||
|
echo "${log_prefix} No index version file found"
|
||||||
|
update_index
|
||||||
|
elif [[ $(<"${index_version_file}") != "$index_version" ]]; then
|
||||||
|
echo "${log_prefix} index version updated"
|
||||||
|
update_index
|
||||||
|
fi
|
@ -0,0 +1 @@
|
|||||||
|
oneshot
|
@ -0,0 +1 @@
|
|||||||
|
/etc/s6-overlay/s6-rc.d/init-search-index/run
|
20
docker/rootfs/etc/s6-overlay/s6-rc.d/init-start/run
Executable file
20
docker/rootfs/etc/s6-overlay/s6-rc.d/init-start/run
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/command/with-contenv /usr/bin/bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
declare -r log_prefix="[init-start]"
|
||||||
|
|
||||||
|
echo "${log_prefix} paperless-ngx docker container starting..."
|
||||||
|
|
||||||
|
# Set some directories into environment for other steps to access via environment
|
||||||
|
# Sort of like variables for later
|
||||||
|
printf "/usr/src/paperless/src" > /var/run/s6/container_environment/PAPERLESS_SRC_DIR
|
||||||
|
echo $(date +%s) > /var/run/s6/container_environment/PAPERLESS_START_TIME_S
|
||||||
|
|
||||||
|
# Check if we're starting as a non-root user
|
||||||
|
if [ "$(id --user)" != "0" ]; then
|
||||||
|
printf "true" > /var/run/s6/container_environment/USER_IS_NON_ROOT
|
||||||
|
echo "${log_prefix} paperless-ngx docker container running under a user ($(id --user):$(id --group))"
|
||||||
|
else
|
||||||
|
printf "/usr/src/paperless" > /var/run/s6/container_environment/HOME
|
||||||
|
echo "${log_prefix} paperless-ngx docker container starting init as root"
|
||||||
|
fi
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-start/type
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-start/type
Normal file
@ -0,0 +1 @@
|
|||||||
|
oneshot
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-start/up
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-start/up
Normal file
@ -0,0 +1 @@
|
|||||||
|
/etc/s6-overlay/s6-rc.d/init-start/run
|
20
docker/rootfs/etc/s6-overlay/s6-rc.d/init-superuser/run
Executable file
20
docker/rootfs/etc/s6-overlay/s6-rc.d/init-superuser/run
Executable file
@ -0,0 +1,20 @@
|
|||||||
|
#!/command/with-contenv /usr/bin/bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
declare -r log_prefix="[init-superuser]"
|
||||||
|
|
||||||
|
if [[ -n "${PAPERLESS_ADMIN_USER}" ]]; then
|
||||||
|
echo "${log_prefix} Creating superuser..."
|
||||||
|
cd "${PAPERLESS_SRC_DIR}"
|
||||||
|
|
||||||
|
if [[ -n "${USER_IS_NON_ROOT}" ]]; then
|
||||||
|
python3 manage.py manage_superuser
|
||||||
|
else
|
||||||
|
s6-setuidgid paperless python3 manage.py manage_superuser
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${log_prefix} Superuser creation done"
|
||||||
|
|
||||||
|
else
|
||||||
|
echo "${log_prefix} Not creating superuser"
|
||||||
|
fi
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-superuser/type
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-superuser/type
Normal file
@ -0,0 +1 @@
|
|||||||
|
oneshot
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-superuser/up
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/init-superuser/up
Normal file
@ -0,0 +1 @@
|
|||||||
|
/etc/s6-overlay/s6-rc.d/init-superuser/run
|
0
docker/rootfs/etc/s6-overlay/s6-rc.d/init-system-checks/dependencies.d/init-tesseract-langs
Normal file
0
docker/rootfs/etc/s6-overlay/s6-rc.d/init-system-checks/dependencies.d/init-tesseract-langs
Normal file
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user