Compare commits

...

6 commits

Author SHA1 Message Date
Alex Pyrgiotis
10be85b9f2
container: Add workarounds for Podman Desktop support on Windows
In case we run on Windows and use Podman Desktop (for which we currently
offer experimental support), we must not pass some Podman flags in order
to avoid conversion errors.

Refs #1127
2025-04-08 16:36:08 +03:00
Alexis Métaireau
47d732e603
Document the Makefile targets
It now outputs the following:

```
build-linux                  Build linux packages (.rpm and .deb)
build-macos-arm              Build macOS Apple Silicon package (.dmg)
build-macos-intel            Build macOS intel package (.dmg)
Dockerfile                   Regenerate the Dockerfile from its template
fix                          apply all the suggestions from ruff
help                         Print this message and exit.
lint                         Check the code for linting, formatting, and typing issues with ruff and mypy
regenerate-reference-pdfs    Regenerate the reference PDFs
test                         Run the tests
test-large                   Run large test set
```
2025-04-08 16:34:34 +03:00
Alexis Métaireau
d6451290db
Move multithreading patch up so that it's working in the GUI 2025-04-08 16:34:34 +03:00
Alex Pyrgiotis
f0bb65cb4e
Bypass a cx-freeze issue for fitz._wxcolors
Bypass an issue with `cx-freeze` that fails to include the
`fitz._wxcolors` module in the final Windows artifact.

Refs #1128
2025-04-08 16:34:34 +03:00
Alex Pyrgiotis
0c741359cc
Make our build-image.py script runable on Windows 2025-04-08 16:34:34 +03:00
Alex Pyrgiotis
8c61894e25
Handle the case where Docker is not installed
Refs #1132
2025-04-08 16:33:15 +03:00
6 changed files with 37 additions and 17 deletions

View file

@ -22,7 +22,7 @@ fix: ## apply all the suggestions from ruff
ruff format ruff format
.PHONY: test .PHONY: test
test: test: ## Run the tests
# Make each GUI test run as a separate process, to avoid segfaults due to # Make each GUI test run as a separate process, to avoid segfaults due to
# shared state. # shared state.
# See more in https://github.com/freedomofpress/dangerzone/issues/493 # See more in https://github.com/freedomofpress/dangerzone/issues/493
@ -47,11 +47,11 @@ test-large: test-large-init ## Run large test set
python -m pytest --tb=no tests/test_large_set.py::TestLargeSet -v $(JUNIT_FLAGS) --junitxml=$(TEST_LARGE_RESULTS) python -m pytest --tb=no tests/test_large_set.py::TestLargeSet -v $(JUNIT_FLAGS) --junitxml=$(TEST_LARGE_RESULTS)
python $(TEST_LARGE_RESULTS)/report.py $(TEST_LARGE_RESULTS) python $(TEST_LARGE_RESULTS)/report.py $(TEST_LARGE_RESULTS)
Dockerfile: Dockerfile.env Dockerfile.in Dockerfile: Dockerfile.env Dockerfile.in ## Regenerate the Dockerfile from its template
poetry run jinja2 Dockerfile.in Dockerfile.env > Dockerfile poetry run jinja2 Dockerfile.in Dockerfile.env > Dockerfile
.PHONY: poetry-install .PHONY: poetry-install
poetry-install: poetry-install: ## Install project dependencies
poetry install poetry install
.PHONY: build-clean .PHONY: build-clean
@ -59,19 +59,19 @@ build-clean:
poetry run doit clean poetry run doit clean
.PHONY: build-macos-intel .PHONY: build-macos-intel
build-macos-intel: build-clean poetry-install build-macos-intel: build-clean poetry-install ## Build macOS intel package (.dmg)
poetry run doit -n 8 poetry run doit -n 8
.PHONY: build-macos-arm .PHONY: build-macos-arm
build-macos-arm: build-clean poetry-install build-macos-arm: build-clean poetry-install ## Build macOS Apple Silicon package (.dmg)
poetry run doit -n 8 macos_build_dmg poetry run doit -n 8 macos_build_dmg
.PHONY: build-linux .PHONY: build-linux
build-linux: build-clean poetry-install build-linux: build-clean poetry-install ## Build linux packages (.rpm and .deb)
poetry run doit -n 8 fedora_rpm debian_deb poetry run doit -n 8 fedora_rpm debian_deb
.PHONY: regenerate-reference-pdfs .PHONY: regenerate-reference-pdfs
regenerate-reference-pdfs: regenerate-reference-pdfs: ## Regenerate the reference PDFs
pytest tests/test_cli.py -k regenerate --generate-reference-pdfs pytest tests/test_cli.py -k regenerate --generate-reference-pdfs
# Makefile self-help borrowed from the securedrop-client project # Makefile self-help borrowed from the securedrop-client project
# Explaination of the below shell command should it ever break. # Explaination of the below shell command should it ever break.

View file

@ -4,6 +4,12 @@ import sys
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# Call freeze_support() to avoid passing unknown options to the subprocess.
# See https://github.com/freedomofpress/dangerzone/issues/873
import multiprocessing
multiprocessing.freeze_support()
try: try:
from . import vendor # type: ignore [attr-defined] from . import vendor # type: ignore [attr-defined]

View file

@ -3,7 +3,6 @@ import os
import platform import platform
import tempfile import tempfile
import typing import typing
from multiprocessing import freeze_support
from multiprocessing.pool import ThreadPool from multiprocessing.pool import ThreadPool
from pathlib import Path from pathlib import Path
from typing import List, Optional from typing import List, Optional
@ -228,7 +227,9 @@ class MainWindow(QtWidgets.QMainWindow):
if not is_version_valid: if not is_version_valid:
self.handle_docker_desktop_version_check(is_version_valid, version) self.handle_docker_desktop_version_check(is_version_valid, version)
except errors.UnsupportedContainerRuntime as e: except errors.UnsupportedContainerRuntime as e:
pass # It's catched later in the flow. pass # It's caught later in the flow.
except errors.NoContainerTechException as e:
pass # It's caught later in the flow.
self.show() self.show()
@ -1236,9 +1237,6 @@ class DocumentsListWidget(QtWidgets.QListWidget):
def start_conversion(self) -> None: def start_conversion(self) -> None:
if not self.thread_pool_initized: if not self.thread_pool_initized:
max_jobs = self.dangerzone.isolation_provider.get_max_parallel_conversions() max_jobs = self.dangerzone.isolation_provider.get_max_parallel_conversions()
# Call freeze_support() to avoid passing unknown options to the subprocess.
# See https://github.com/freedomofpress/dangerzone/issues/873
freeze_support()
self.thread_pool = ThreadPool(max_jobs) self.thread_pool = ThreadPool(max_jobs)
for doc in self.docs_list: for doc in self.docs_list:

View file

@ -56,7 +56,14 @@ class Container(IsolationProvider):
security_args = ["--log-driver", "none"] security_args = ["--log-driver", "none"]
security_args += ["--security-opt", "no-new-privileges"] security_args += ["--security-opt", "no-new-privileges"]
if container_utils.get_runtime_version() >= (4, 1): if container_utils.get_runtime_version() >= (4, 1):
security_args += ["--userns", "nomap"] # We perform a platform check to avoid the following Podman Desktop
# error on Windows:
#
# Error: nomap is only supported in rootless mode
#
# See also: https://github.com/freedomofpress/dangerzone/issues/1127
if platform.system() != "Windows":
security_args += ["--userns", "nomap"]
else: else:
security_args = ["--security-opt=no-new-privileges:true"] security_args = ["--security-opt=no-new-privileges:true"]
@ -67,7 +74,15 @@ class Container(IsolationProvider):
# [1] https://github.com/freedomofpress/dangerzone/issues/846 # [1] https://github.com/freedomofpress/dangerzone/issues/846
# [2] https://github.com/containers/common/blob/d3283f8401eeeb21f3c59a425b5461f069e199a7/pkg/seccomp/seccomp.json # [2] https://github.com/containers/common/blob/d3283f8401eeeb21f3c59a425b5461f069e199a7/pkg/seccomp/seccomp.json
seccomp_json_path = str(get_resource_path("seccomp.gvisor.json")) seccomp_json_path = str(get_resource_path("seccomp.gvisor.json"))
security_args += ["--security-opt", f"seccomp={seccomp_json_path}"] # We perform a platform check to avoid the following Podman Desktop
# error on Windows:
#
# Error: opening seccomp profile failed: open
# C:\[...]\dangerzone\share\seccomp.gvisor.json: no such file or directory
#
# See also: https://github.com/freedomofpress/dangerzone/issues/1127
if runtime.name == "podman" and platform.system() != "Windows":
security_args += ["--security-opt", f"seccomp={seccomp_json_path}"]
security_args += ["--cap-drop", "all"] security_args += ["--cap-drop", "all"]
security_args += ["--cap-add", "SYS_CHROOT"] security_args += ["--cap-add", "SYS_CHROOT"]

View file

@ -5,7 +5,7 @@ import subprocess
import sys import sys
from pathlib import Path from pathlib import Path
BUILD_CONTEXT = "dangerzone/" BUILD_CONTEXT = "dangerzone"
IMAGE_NAME = "dangerzone.rocks/dangerzone" IMAGE_NAME = "dangerzone.rocks/dangerzone"
if platform.system() in ["Darwin", "Windows"]: if platform.system() in ["Darwin", "Windows"]:
CONTAINER_RUNTIME = "docker" CONTAINER_RUNTIME = "docker"
@ -122,7 +122,8 @@ def main():
subprocess.run( subprocess.run(
[ [
"./dev_scripts/repro-build.py", sys.executable,
str(Path("dev_scripts") / "repro-build.py"),
"build", "build",
"--runtime", "--runtime",
args.runtime, args.runtime,

View file

@ -13,7 +13,7 @@ setup(
description="Dangerzone", description="Dangerzone",
options={ options={
"build_exe": { "build_exe": {
"packages": ["dangerzone", "dangerzone.gui"], "packages": ["dangerzone", "dangerzone.gui", "pymupdf._wxcolors"],
"excludes": ["test", "tkinter"], "excludes": ["test", "tkinter"],
"include_files": [("share", "share"), ("LICENSE", "LICENSE")], "include_files": [("share", "share"), ("LICENSE", "LICENSE")],
"include_msvcr": True, "include_msvcr": True,