name: Tests on: pull_request: push: branches: - main - "test/**" schedule: - cron: "2 0 * * *" # Run every day at 02:00 UTC. workflow_dispatch: permissions: packages: write actions: read # for detecting the Github Actions environment. id-token: write # for creating OIDC tokens for signing. env: QT_SELECT: "qt6" # Disable multiple concurrent runs on the same branch # When a new CI build is triggered, it will cancel the # other in-progress ones (for the same branch) concurrency: group: ${{ github.head_ref || github.run_id }} cancel-in-progress: true jobs: run-lint: runs-on: ubuntu-latest container: image: debian:bookworm steps: - uses: actions/checkout@v4 - name: Install dev. dependencies run: |- apt-get update apt-get install -y git make python3 python3-poetry --no-install-recommends poetry install --only lint,test - name: Run linters to enforce code style run: poetry run make lint - name: Check that the QA script is up to date with the docs run: "./dev_scripts/qa.py --check-refs" # This is already built daily by the "build.yml" file # But we also want to include this in the checks that run on each push. build-container-image: name: Build, push and sign container image uses: ./.github/workflows/build-push-image.yml with: registry: "ghcr.io/${{ github.repository_owner }}" registry_user: ${{ github.actor }} image_name: "dangerzone/dangerzone-staging" reproduce: false sign: true key_name: "dangerzone-tests" key_cache: "v1-test-keypair-${{ github.ref_name }}" secrets: registry_token: ${{ secrets.GITHUB_TOKEN }} download-tessdata: name: Download and cache Tesseract data runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Cache Tessdata id: cache-tessdata uses: actions/cache@v4 with: path: share/tessdata/ key: v1-tessdata-${{ hashFiles('./install/common/download-tessdata.py') }} enableCrossOsArchive: true - uses: actions/setup-python@v5 with: python-version: '3.11' - name: Download Tessdata run: |- if [ -f "share/tessdata" ]; then echo "Already cached, skipping" else python3 ./install/common/download-tessdata.py fi windows: runs-on: windows-latest needs: - download-tessdata env: DUMMY_CONVERSION: 1 steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - run: pip install poetry - run: poetry install - name: Restore cached tessdata uses: actions/cache/restore@v4 with: path: share/tessdata/ enableCrossOsArchive: true fail-on-cache-miss: true key: v1-tessdata-${{ hashFiles('./install/common/download-tessdata.py') }} - name: Run CLI tests run: poetry run make test - name: Set up .NET CLI environment uses: actions/setup-dotnet@v4 with: dotnet-version: "8.x" - name: Install WiX Toolset run: dotnet tool install --global wix --version 5.0.2 - name: Add WiX UI extension run: wix extension add --global WixToolset.UI.wixext/5.0.2 - name: Build the MSI installer # NOTE: This also builds the .exe internally. run: poetry run .\install\windows\build-app.bat - name: Upload MSI installer uses: actions/upload-artifact@v4 with: name: Dangerzone.msi path: "dist/Dangerzone.msi" if-no-files-found: error compression-level: 0 macOS: name: "macOS (${{ matrix.arch }})" runs-on: ${{ matrix.runner }} needs: - download-tessdata strategy: matrix: include: - runner: macos-latest # CPU type: Apple Silicon (M1) arch: arch64 - runner: macos-13 # CPU type: Intel x86_64 arch: x86_64 env: DUMMY_CONVERSION: 1 steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - name: Restore cached tessdata uses: actions/cache/restore@v4 with: path: share/tessdata/ enableCrossOsArchive: true fail-on-cache-miss: true key: v1-tessdata-${{ hashFiles('./install/common/download-tessdata.py') }} - run: pip install poetry - run: poetry install - name: Run CLI tests run: poetry run make test - name: Build macOS app run: poetry run python ./install/macos/build-app.py - name: Upload macOS app uses: actions/upload-artifact@v4 with: name: Dangerzone-${{ matrix.arch }}.app path: "dist/Dangerzone.app" if-no-files-found: error compression-level: 0 build-deb: needs: - build-container-image name: "build-deb (${{ matrix.distro }} ${{ matrix.version }})" runs-on: ubuntu-latest strategy: matrix: include: - distro: ubuntu version: "22.04" - distro: ubuntu version: "24.04" - distro: ubuntu version: "24.10" - distro: ubuntu version: "25.04" - distro: debian version: bullseye - distro: debian version: bookworm - distro: debian version: trixie steps: - name: Checkout uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.10" - name: Login to GHCR run: | echo ${{ github.token }} | podman login ghcr.io -u USERNAME --password-stdin - name: Get the dev environment run: | ./dev_scripts/env.py \ --distro ${{ matrix.distro }} \ --version ${{ matrix.version }} \ build-dev --sync - name: Get current date id: date run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT - name: Restore container cache uses: actions/cache/restore@v4 with: key: v5-${{ steps.date.outputs.date }}-${{ hashFiles('Dockerfile', 'dangerzone/conversion/*.py', 'dangerzone/container_helpers/*', 'install/common/build-image.py') }} path: share/container.tar fail-on-cache-miss: true - name: Build Dangerzone .deb run: | ./dev_scripts/env.py --distro ${{ matrix.distro }} \ --version ${{ matrix.version }} \ run --dev --no-gui ./dangerzone/install/linux/build-deb.py - name: Upload Dangerzone .deb if: matrix.distro == 'debian' && matrix.version == 'bookworm' uses: actions/upload-artifact@v4 with: name: dangerzone.deb path: "deb_dist/dangerzone_*_*.deb" if-no-files-found: error compression-level: 0 install-deb: name: "install-deb (${{ matrix.distro }} ${{ matrix.version }})" runs-on: ubuntu-latest needs: - build-deb strategy: matrix: include: - distro: ubuntu version: "22.04" - distro: ubuntu version: "24.04" - distro: ubuntu version: "24.10" - distro: ubuntu version: "25.04" - distro: debian version: bullseye - distro: debian version: bookworm - distro: debian version: trixie steps: - name: Checkout uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.10" - name: Download Dangerzone .deb uses: actions/download-artifact@v4 with: name: dangerzone.deb path: "deb_dist/" - name: Build end-user environment run: | ./dev_scripts/env.py --distro ${{ matrix.distro }} \ --version ${{ matrix.version }} \ build - name: Run a test command run: | ./dev_scripts/env.py --distro ${{ matrix.distro }} \ --version ${{ matrix.version }} \ run dangerzone-cli dangerzone/tests/test_docs/sample-pdf.pdf --ocr-lang eng - name: Check that the Dangerzone GUI imports work run: | ./dev_scripts/env.py --distro ${{ matrix.distro }} \ --version ${{ matrix.version }} \ run dangerzone --help build-install-rpm: name: "build-install-rpm (${{ matrix.distro }} ${{matrix.version}})" runs-on: ubuntu-latest needs: - build-container-image strategy: matrix: distro: ["fedora"] version: ["40", "41", "42"] steps: - name: Checkout uses: actions/checkout@v4 - name: Login to GHCR run: | echo ${{ github.token }} | podman login ghcr.io -u USERNAME --password-stdin - name: Get the dev environment run: | ./dev_scripts/env.py \ --distro ${{ matrix.distro }} \ --version ${{ matrix.version }} \ build-dev --sync - name: Get current date id: date run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT - name: Restore container image uses: actions/cache/restore@v4 with: key: v5-${{ steps.date.outputs.date }}-${{ hashFiles('Dockerfile', 'dangerzone/conversion/*.py', 'dangerzone/container_helpers/*', 'install/common/build-image.py') }} path: |- share/container.tar fail-on-cache-miss: true - name: Build Dangerzone .rpm run: | ./dev_scripts/env.py --distro ${{ matrix.distro }} --version ${{ matrix.version }} \ run --dev --no-gui ./dangerzone/install/linux/build-rpm.py - name: Upload Dangerzone .rpm uses: actions/upload-artifact@v4 with: name: dangerzone-${{ matrix.distro }}-${{ matrix.version }}.rpm path: "dist/dangerzone-*.x86_64.rpm" if-no-files-found: error compression-level: 0 # Reclaim some space in this step, now that the dev environment is no # longer necessary. Previously, we encountered out-of-space issues while # running this CI job. - name: Reclaim some storage space run: podman system reset -f - name: Build end-user environment run: | ./dev_scripts/env.py --distro ${{ matrix.distro }} \ --version ${{ matrix.version }} \ build - name: Run a test command run: | ./dev_scripts/env.py --distro ${{ matrix.distro }} --version ${{ matrix.version }} \ run dangerzone-cli dangerzone/tests/test_docs/sample-pdf.pdf --ocr-lang eng - name: Check that the Dangerzone GUI imports work run: | ./dev_scripts/env.py --distro ${{ matrix.distro }} --version ${{ matrix.version }} \ run dangerzone --help run-tests: name: "run tests (${{ matrix.distro }} ${{ matrix.version }})" runs-on: ubuntu-latest needs: - build-container-image - download-tessdata strategy: matrix: include: - distro: ubuntu version: "22.04" - distro: ubuntu version: "24.04" - distro: ubuntu version: "24.10" - distro: ubuntu version: "25.04" - distro: debian version: bullseye - distro: debian version: bookworm - distro: debian version: trixie - distro: fedora version: "40" - distro: fedora version: "41" - distro: fedora version: "42" steps: - name: Checkout uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.10" - name: Login to GHCR run: | echo ${{ github.token }} | podman login ghcr.io -u USERNAME --password-stdin - name: Get current date id: date run: echo "date=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT - name: Get the dev environment run: | ./dev_scripts/env.py \ --distro ${{ matrix.distro }} \ --version ${{ matrix.version }} \ build-dev --sync - name: Restore container image uses: actions/cache/restore@v4 with: key: v5-${{ steps.date.outputs.date }}-${{ hashFiles('Dockerfile', 'dangerzone/conversion/*.py', 'dangerzone/container_helpers/*', 'install/common/build-image.py') }} path: |- share/container.tar fail-on-cache-miss: true - name: Restore cached tessdata uses: actions/cache/restore@v4 with: path: share/tessdata/ enableCrossOsArchive: true fail-on-cache-miss: true key: v1-tessdata-${{ hashFiles('./install/common/download-tessdata.py') }} - name: Setup xvfb (Linux) run: | sudo apt update # Stuff copied wildly from several stackoverflow posts sudo apt-get install -y xvfb libxkbcommon-x11-0 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-xinerama0 libxcb-xinput0 libxcb-xfixes0 libxcb-shape0 libglib2.0-0 libgl1-mesa-dev '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev # start xvfb in the background sudo /usr/bin/Xvfb $DISPLAY -screen 0 1280x1024x24 & - name: Run CI tests run: |- # Pass the -ac Xserver flag, to disable host-based access controls. # This should be used ONLY for testing [1]. If we don't pass this # flag, the Podman container is not authorized [2] to access the Xvfb # server. # # [1] From https://www.x.org/releases/X11R6.7.0/doc/Xserver.1.html#sect4: # # disables host-based access control mechanisms. Enables access by # any host, and permits any host to modify the access control # list. Use with extreme caution. This option exists primarily for # running test suites remotely. # # [2] Fails with "Authorization required, but no authorization # protocol specified". However, we have verified with strace(1) # that the command in the Podman container can read the Xauthority # file successfully. xvfb-run -s '-ac' ./dev_scripts/env.py --distro ${{ matrix.distro }} --version ${{ matrix.version }} run --dev \ bash -c 'cd dangerzone; poetry run make test' - name: Upload PDF diffs uses: actions/upload-artifact@v4 with: name: pdf-diffs-${{ matrix.distro }}-${{ matrix.version }} path: tests/test_docs/diffs/*.jpeg # Always run this step to publish test results, even on failures if: ${{ always() }}