mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-10-03 06:40:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d8d3882dc | ||
|
|
8707faba29 | ||
|
|
bd84394bf2 |
@@ -80,7 +80,7 @@ jobs:
|
||||
needs: changes
|
||||
if: needs.changes.outputs.backend_changed == 'true'
|
||||
name: "Python ${{ matrix.python-version }}"
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
contents: read
|
||||
strategy:
|
||||
@@ -115,7 +115,7 @@ jobs:
|
||||
unpaper tesseract-ocr imagemagick ghostscript poppler-utils
|
||||
- name: Configure ImageMagick
|
||||
run: |
|
||||
sudo cp docker/rootfs/etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-6/policy.xml
|
||||
sudo cp docker/rootfs/etc/ImageMagick-6/paperless-policy.xml /etc/ImageMagick-7/policy.xml
|
||||
- name: Install Python dependencies
|
||||
env:
|
||||
PYTHON_VERSION: ${{ steps.setup-python.outputs.python-version }}
|
||||
@@ -159,7 +159,7 @@ jobs:
|
||||
needs: changes
|
||||
if: needs.changes.outputs.backend_changed == 'true'
|
||||
name: Check project typing
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
|
||||
@@ -24,10 +24,10 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- runner: ubuntu-24.04
|
||||
- runner: ubuntu-26.04
|
||||
arch: amd64
|
||||
platform: linux/amd64
|
||||
- runner: ubuntu-24.04-arm
|
||||
- runner: ubuntu-26.04-arm
|
||||
arch: arm64
|
||||
platform: linux/arm64
|
||||
runs-on: ${{ matrix.runner }}
|
||||
@@ -163,7 +163,7 @@ jobs:
|
||||
archive: false
|
||||
merge-and-push:
|
||||
name: Merge and Push Manifest
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
needs: build-arch
|
||||
if: needs.build-arch.outputs.should-push == 'true'
|
||||
environment: image-publishing
|
||||
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
needs: changes
|
||||
if: needs.changes.outputs.docs_changed == 'true'
|
||||
name: Build Documentation
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
steps:
|
||||
- uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
|
||||
- name: Checkout
|
||||
@@ -102,7 +102,7 @@ jobs:
|
||||
name: Deploy Documentation
|
||||
needs: [changes, build]
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.changes.outputs.docs_changed == 'true'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
needs: changes
|
||||
if: needs.changes.outputs.frontend_changed == 'true'
|
||||
name: Install Dependencies
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
@@ -104,7 +104,7 @@ jobs:
|
||||
name: Lint
|
||||
needs: [changes, install-dependencies]
|
||||
if: needs.changes.outputs.frontend_changed == 'true'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
name: "Unit Tests (${{ matrix.shard-index }}/${{ matrix.shard-count }})"
|
||||
needs: [changes, install-dependencies]
|
||||
if: needs.changes.outputs.frontend_changed == 'true'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
contents: read
|
||||
strategy:
|
||||
@@ -188,10 +188,10 @@ jobs:
|
||||
name: E2E Tests
|
||||
needs: [changes, install-dependencies]
|
||||
if: needs.changes.outputs.frontend_changed == 'true'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
contents: read
|
||||
container: mcr.microsoft.com/playwright:v1.62.1-noble
|
||||
container: mcr.microsoft.com/playwright:v1.62.1-resolute
|
||||
env:
|
||||
PLAYWRIGHT_BROWSERS_PATH: /ms-playwright
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||
@@ -245,7 +245,7 @@ jobs:
|
||||
name: Frontend Build
|
||||
needs: [changes, unit-tests, e2e-tests]
|
||||
if: needs.changes.outputs.frontend_changed == 'true'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
|
||||
@@ -14,7 +14,7 @@ permissions: {}
|
||||
jobs:
|
||||
wait-for-docker:
|
||||
name: Wait for Docker Build
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
checks: read
|
||||
statuses: read
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
build-release:
|
||||
name: Build Release
|
||||
needs: wait-for-docker
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
@@ -72,7 +72,7 @@ jobs:
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt-get update -qq
|
||||
sudo apt-get install -qq --no-install-recommends gettext liblept5
|
||||
sudo apt-get install -qq --no-install-recommends gettext libleptonica6
|
||||
# ---- Build Documentation ----
|
||||
- name: Build documentation
|
||||
env:
|
||||
@@ -144,7 +144,7 @@ jobs:
|
||||
publish-release:
|
||||
name: Publish Release
|
||||
needs: build-release
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
@@ -196,7 +196,7 @@ jobs:
|
||||
name: Append Changelog
|
||||
needs: publish-release
|
||||
if: needs.publish-release.outputs.prerelease == 'false'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
@@ -15,7 +15,7 @@ permissions:
|
||||
jobs:
|
||||
zizmor:
|
||||
name: Run zizmor
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
contents: read
|
||||
actions: read
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
uses: zizmorcore/zizmor-action@cc914d7f3750a2d13d75c7f184a1060aa0e9d482 # v0.6.4
|
||||
semgrep:
|
||||
name: Semgrep CE
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
container:
|
||||
image: semgrep/semgrep:1.155.0@sha256:cc869c685dcc0fe497c86258da9f205397d8108e56d21a86082ea4886e52784d
|
||||
if: github.actor != 'dependabot[bot]'
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
cleanup-images:
|
||||
name: Cleanup Image Tags for ${{ matrix.primary-name }}
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
environment: registry-maintenance
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -42,7 +42,7 @@ jobs:
|
||||
cleanup-untagged-images:
|
||||
name: Cleanup Untagged Images Tags for ${{ matrix.primary-name }}
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
needs:
|
||||
- cleanup-images
|
||||
environment: registry-maintenance
|
||||
|
||||
@@ -21,7 +21,7 @@ on:
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
synchronize-with-crowdin:
|
||||
name: Crowdin Sync
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
environment: translation-sync
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
||||
@@ -7,7 +7,7 @@ jobs:
|
||||
# Note: peakoss/anti-slop does not support the `issues` event yet (all of its
|
||||
# issue inputs are still commented out upstream), so the checks that the PR Bot
|
||||
# workflow gets from the action are implemented manually here.
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-slim
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
|
||||
@@ -4,7 +4,7 @@ on:
|
||||
types: [opened]
|
||||
jobs:
|
||||
Anti-slop:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-slim
|
||||
permissions:
|
||||
contents: read
|
||||
issues: read
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
ASLOP-PR-VERIFY
|
||||
pr-bot:
|
||||
name: Automated PR Bot
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-slim
|
||||
# Runs after Anti-slop so the welcome comment can see whether the PR was closed
|
||||
# instead of racing it. Still runs if that job fails, so labeling is not lost.
|
||||
needs: Anti-slop
|
||||
|
||||
@@ -12,7 +12,7 @@ permissions:
|
||||
jobs:
|
||||
pr_opened_or_reopened:
|
||||
name: pr_opened_or_reopened
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-slim
|
||||
permissions:
|
||||
# write permission is required for autolabeler
|
||||
pull-requests: write
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
stale:
|
||||
name: 'Stale'
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
lock-threads:
|
||||
name: 'Lock Old Threads'
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-26.04
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
close-answered-discussions:
|
||||
name: 'Close Answered Discussions'
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-slim
|
||||
permissions:
|
||||
discussions: write
|
||||
steps:
|
||||
@@ -117,7 +117,7 @@ jobs:
|
||||
close-outdated-discussions:
|
||||
name: 'Close Outdated Discussions'
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-slim
|
||||
permissions:
|
||||
discussions: write
|
||||
steps:
|
||||
@@ -211,7 +211,7 @@ jobs:
|
||||
close-unsupported-feature-requests:
|
||||
name: 'Close Unsupported Feature Requests'
|
||||
if: github.repository_owner == 'paperless-ngx'
|
||||
runs-on: ubuntu-24.04
|
||||
runs-on: ubuntu-slim
|
||||
permissions:
|
||||
discussions: write
|
||||
steps:
|
||||
|
||||
@@ -8,7 +8,7 @@ env:
|
||||
jobs:
|
||||
generate-translate-strings:
|
||||
name: Generate Translation Strings
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-26.04
|
||||
environment: translation-sync
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
@@ -137,9 +137,20 @@ class TestNginxService:
|
||||
reason="No Gotenberg/Tika servers to test with",
|
||||
)
|
||||
class TestParserLive:
|
||||
@staticmethod
|
||||
def imagehash(file: Path, hash_size: int = 18) -> str:
|
||||
return f"{average_hash(Image.open(file), hash_size)}"
|
||||
# Rasterizer versions shift a few pixels, so compare perceptual hashes by
|
||||
# Hamming distance (out of 18 * 18 = 324 bits) rather than for equality
|
||||
MAX_HASH_DISTANCE = 8
|
||||
|
||||
@classmethod
|
||||
def assert_thumbnails_similar(cls, generated: Path, expected: Path) -> None:
|
||||
distance = average_hash(Image.open(generated), 18) - average_hash(
|
||||
Image.open(expected),
|
||||
18,
|
||||
)
|
||||
assert distance <= cls.MAX_HASH_DISTANCE, (
|
||||
f"Thumbnail {generated} differs from {expected} by {distance} bits "
|
||||
f"(max {cls.MAX_HASH_DISTANCE})"
|
||||
)
|
||||
|
||||
def test_get_thumbnail(
|
||||
self,
|
||||
@@ -168,12 +179,7 @@ class TestParserLive:
|
||||
assert thumb.exists()
|
||||
assert thumb.is_file()
|
||||
|
||||
assert self.imagehash(thumb) == self.imagehash(
|
||||
simple_txt_email_thumbnail_file,
|
||||
), (
|
||||
f"Created thumbnail {thumb} differs from expected file "
|
||||
f"{simple_txt_email_thumbnail_file}"
|
||||
)
|
||||
self.assert_thumbnails_similar(thumb, simple_txt_email_thumbnail_file)
|
||||
|
||||
def test_tika_parse_successful(self, mail_parser: MailDocumentParser) -> None:
|
||||
"""
|
||||
@@ -255,7 +261,7 @@ class TestParserLive:
|
||||
THEN:
|
||||
- Gotenberg shall be called to generate the PDF
|
||||
- The archive PDF shall contain the expected content
|
||||
- The generated thumbnail shall match the expected image hash
|
||||
- The generated thumbnail shall be perceptually close to the expected image
|
||||
"""
|
||||
util_call_with_backoff(mail_parser.parse, [html_email_file, "message/rfc822"])
|
||||
|
||||
@@ -272,14 +278,4 @@ class TestParserLive:
|
||||
html_email_file,
|
||||
"message/rfc822",
|
||||
)
|
||||
generated_thumbnail_hash = self.imagehash(generated_thumbnail)
|
||||
|
||||
# The created PDF is not reproducible, but the converted image
|
||||
# should always look the same
|
||||
expected_hash = self.imagehash(html_email_thumbnail_file)
|
||||
|
||||
assert generated_thumbnail_hash == expected_hash, (
|
||||
f"PDF thumbnail differs from expected. "
|
||||
f"Generated: {generated_thumbnail}, "
|
||||
f"Hash: {generated_thumbnail_hash} vs {expected_hash}"
|
||||
)
|
||||
self.assert_thumbnails_similar(generated_thumbnail, html_email_thumbnail_file)
|
||||
|
||||
Reference in New Issue
Block a user