mirror of
https://github.com/freedomofpress/dangerzone.git
synced 2025-05-07 14:01:49 +02:00
Compare commits
38 commits
e6380f793b
...
1c0a99fcd2
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1c0a99fcd2 | ||
![]() |
4b5f4b27d7 | ||
![]() |
f537d54ed2 | ||
![]() |
32641603ee | ||
![]() |
a915ae8442 | ||
![]() |
38a803085f | ||
![]() |
2053c98c09 | ||
![]() |
3db1ca1fbb | ||
![]() |
3fff16cc7e | ||
![]() |
8bd9c05832 | ||
![]() |
41e78c907f | ||
![]() |
265c1dde97 | ||
![]() |
ccb302462d | ||
![]() |
4eadc30605 | ||
![]() |
abb71e0fe5 | ||
![]() |
4638444290 | ||
![]() |
68da50a6b2 | ||
![]() |
cc5ba29455 | ||
![]() |
180b9442ab | ||
![]() |
f349e16523 | ||
![]() |
adddb1ecb7 | ||
![]() |
8e57d81a74 | ||
![]() |
3bcf5fc147 | ||
![]() |
60df4f7e35 | ||
![]() |
9fa3c80404 | ||
![]() |
4bf7f9cbb4 | ||
![]() |
fdc27c4d3b | ||
![]() |
23f5f96220 | ||
![]() |
5744215d99 | ||
![]() |
c89988654c | ||
![]() |
7eaa0cfe50 | ||
![]() |
9d69e3b261 | ||
![]() |
1d2a91e8c5 | ||
![]() |
82c29b2098 | ||
![]() |
ce5aca4ba1 | ||
![]() |
13f38cc8a9 | ||
![]() |
57df6fdfe5 | ||
![]() |
20354e7c11 |
19 changed files with 795 additions and 669 deletions
2
.github/ISSUE_TEMPLATE/bug_report_linux.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report_linux.yml
vendored
|
@ -36,7 +36,7 @@ body:
|
||||||
attributes:
|
attributes:
|
||||||
label: Podman info
|
label: Podman info
|
||||||
description: |
|
description: |
|
||||||
If the bug occurs during document conversion, or is otherwise related with Podman, please copy and paste the following commands in your terminal, and provide us with the output:
|
Please copy and paste the following commands in your terminal, and provide us with the output:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
podman version
|
podman version
|
||||||
|
|
3
.github/ISSUE_TEMPLATE/bug_report_macos.yml
vendored
3
.github/ISSUE_TEMPLATE/bug_report_macos.yml
vendored
|
@ -48,8 +48,7 @@ body:
|
||||||
attributes:
|
attributes:
|
||||||
label: Docker info
|
label: Docker info
|
||||||
description: |
|
description: |
|
||||||
If the bug occurs during document conversion, or is otherwise related
|
Please copy and paste the following commands in your
|
||||||
with Docker, please copy and paste the following commands in your
|
|
||||||
terminal, and provide us with the output:
|
terminal, and provide us with the output:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
|
|
@ -35,8 +35,7 @@ body:
|
||||||
attributes:
|
attributes:
|
||||||
label: Docker info
|
label: Docker info
|
||||||
description: |
|
description: |
|
||||||
If the bug occurs during document conversion, or is otherwise related
|
Please copy and paste the following commands in your
|
||||||
with Docker, please copy and paste the following commands in your
|
|
||||||
terminal, and provide us with the output:
|
terminal, and provide us with the output:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
|
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -47,8 +47,6 @@ jobs:
|
||||||
version: bookworm
|
version: bookworm
|
||||||
- distro: debian
|
- distro: debian
|
||||||
version: trixie
|
version: trixie
|
||||||
- distro: fedora
|
|
||||||
version: "39"
|
|
||||||
- distro: fedora
|
- distro: fedora
|
||||||
version: "40"
|
version: "40"
|
||||||
- distro: fedora
|
- distro: fedora
|
||||||
|
|
35
.github/workflows/check_pr.yml
vendored
Normal file
35
.github/workflows/check_pr.yml
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
name: Check branch conformity
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
prevent-fixup-commits:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
target: debian-bookworm
|
||||||
|
distro: debian
|
||||||
|
version: bookworm
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: prevent fixup commits
|
||||||
|
run: |
|
||||||
|
git fetch origin
|
||||||
|
git status
|
||||||
|
git log --pretty=format:%s origin/main..HEAD | grep -ie '^fixup\|^wip' && exit 1 || true
|
||||||
|
|
||||||
|
check-changelog:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: ensure CHANGELOG.md is populated
|
||||||
|
env:
|
||||||
|
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
if git diff --exit-code "origin/${BASE_REF}" -- CHANGELOG.md; then
|
||||||
|
echo "::warning::No CHANGELOG.md modifications were found in this pull request."
|
||||||
|
fi
|
19
.github/workflows/check_push.yml
vendored
19
.github/workflows/check_push.yml
vendored
|
@ -1,19 +0,0 @@
|
||||||
name: Check branch conformity
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
prevent-fixup-commits:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
target: debian-bookworm
|
|
||||||
distro: debian
|
|
||||||
version: bookworm
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: prevent fixup commits
|
|
||||||
run: |
|
|
||||||
git fetch origin
|
|
||||||
git status
|
|
||||||
git log --pretty=format:%s origin/main..HEAD | grep -ie '^fixup\|^wip' && exit 1 || true
|
|
53
.github/workflows/ci.yml
vendored
53
.github/workflows/ci.yml
vendored
|
@ -68,6 +68,12 @@ jobs:
|
||||||
sudo apt-get install -y python3-poetry
|
sudo apt-get install -y python3-poetry
|
||||||
python3 ./install/common/build-image.py
|
python3 ./install/common/build-image.py
|
||||||
|
|
||||||
|
- name: Upload container image
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: container.tar.gz
|
||||||
|
path: share/container.tar.gz
|
||||||
|
|
||||||
download-tessdata:
|
download-tessdata:
|
||||||
name: Download and cache Tesseract data
|
name: Download and cache Tesseract data
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -113,13 +119,24 @@ jobs:
|
||||||
key: v1-tessdata-${{ hashFiles('./install/common/download-tessdata.py') }}
|
key: v1-tessdata-${{ hashFiles('./install/common/download-tessdata.py') }}
|
||||||
- name: Run CLI tests
|
- name: Run CLI tests
|
||||||
run: poetry run make test
|
run: poetry run make test
|
||||||
# Taken from: https://github.com/orgs/community/discussions/27149#discussioncomment-3254829
|
- name: Set up .NET CLI environment
|
||||||
- name: Set path for candle and light
|
uses: actions/setup-dotnet@v4
|
||||||
run: echo "C:\Program Files (x86)\WiX Toolset v3.14\bin" >> $GITHUB_PATH
|
with:
|
||||||
shell: bash
|
dotnet-version: "8.x"
|
||||||
|
- name: Install WiX Toolset
|
||||||
|
run: dotnet tool install --global wix
|
||||||
|
- name: Add WiX UI extension
|
||||||
|
run: wix extension add --global WixToolset.UI.wixext
|
||||||
- name: Build the MSI installer
|
- name: Build the MSI installer
|
||||||
# NOTE: This also builds the .exe internally.
|
# NOTE: This also builds the .exe internally.
|
||||||
run: poetry run .\install\windows\build-app.bat
|
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:
|
macOS:
|
||||||
name: "macOS (${{ matrix.arch }})"
|
name: "macOS (${{ matrix.arch }})"
|
||||||
|
@ -151,7 +168,15 @@ jobs:
|
||||||
- run: poetry install
|
- run: poetry install
|
||||||
- name: Run CLI tests
|
- name: Run CLI tests
|
||||||
run: poetry run make test
|
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:
|
build-deb:
|
||||||
needs:
|
needs:
|
||||||
- build-container-image
|
- build-container-image
|
||||||
|
@ -216,7 +241,7 @@ jobs:
|
||||||
if: matrix.distro == 'debian' && matrix.version == 'bookworm'
|
if: matrix.distro == 'debian' && matrix.version == 'bookworm'
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: dangerzone-${{ matrix.distro }}-${{ matrix.version }}.deb
|
name: dangerzone.deb
|
||||||
path: "deb_dist/dangerzone_*_*.deb"
|
path: "deb_dist/dangerzone_*_*.deb"
|
||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
compression-level: 0
|
compression-level: 0
|
||||||
|
@ -255,7 +280,7 @@ jobs:
|
||||||
- name: Download Dangerzone .deb
|
- name: Download Dangerzone .deb
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: dangerzone-debian-bookworm.deb
|
name: dangerzone.deb
|
||||||
path: "deb_dist/"
|
path: "deb_dist/"
|
||||||
|
|
||||||
- name: Build end-user environment
|
- name: Build end-user environment
|
||||||
|
@ -284,7 +309,7 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
distro: ["fedora"]
|
distro: ["fedora"]
|
||||||
version: ["39", "40", "41"]
|
version: ["40", "41"]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
@ -318,6 +343,14 @@ jobs:
|
||||||
./dev_scripts/env.py --distro ${{ matrix.distro }} --version ${{ matrix.version }} \
|
./dev_scripts/env.py --distro ${{ matrix.distro }} --version ${{ matrix.version }} \
|
||||||
run --dev --no-gui ./dangerzone/install/linux/build-rpm.py
|
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
|
# Reclaim some space in this step, now that the dev environment is no
|
||||||
# longer necessary. Previously, we encountered out-of-space issues while
|
# longer necessary. Previously, we encountered out-of-space issues while
|
||||||
# running this CI job.
|
# running this CI job.
|
||||||
|
@ -328,7 +361,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
./dev_scripts/env.py --distro ${{ matrix.distro }} \
|
./dev_scripts/env.py --distro ${{ matrix.distro }} \
|
||||||
--version ${{ matrix.version }} \
|
--version ${{ matrix.version }} \
|
||||||
build --download-pyside6
|
build
|
||||||
|
|
||||||
- name: Run a test command
|
- name: Run a test command
|
||||||
run: |
|
run: |
|
||||||
|
@ -363,8 +396,6 @@ jobs:
|
||||||
version: bookworm
|
version: bookworm
|
||||||
- distro: debian
|
- distro: debian
|
||||||
version: trixie
|
version: trixie
|
||||||
- distro: fedora
|
|
||||||
version: "39"
|
|
||||||
- distro: fedora
|
- distro: fedora
|
||||||
version: "40"
|
version: "40"
|
||||||
- distro: fedora
|
- distro: fedora
|
||||||
|
|
7
.github/workflows/scan_released.yml
vendored
7
.github/workflows/scan_released.yml
vendored
|
@ -11,15 +11,16 @@ jobs:
|
||||||
include:
|
include:
|
||||||
- runs-on: ubuntu-latest
|
- runs-on: ubuntu-latest
|
||||||
arch: i686
|
arch: i686
|
||||||
- runs-on: macos-latest
|
# Do not scan Silicon mac for now to avoid masking release scan results for other plaforms.
|
||||||
arch: arm64
|
# - runs-on: macos-latest
|
||||||
|
# arch: arm64
|
||||||
runs-on: ${{ matrix.runs-on }}
|
runs-on: ${{ matrix.runs-on }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Download container image for the latest release and load it
|
- name: Download container image for the latest release and load it
|
||||||
run: |
|
run: |
|
||||||
VERSION=$(curl https://api.github.com/repos/freedomofpress/dangerzone/releases/latest | jq -r '.tag_name')
|
VERSION=$(curl https://api.github.com/repos/freedomofpress/dangerzone/releases/latest | grep "tag_name" | cut -d '"' -f 4)
|
||||||
CONTAINER_FILENAME=container-${VERSION:1}-${{ matrix.arch }}.tar.gz
|
CONTAINER_FILENAME=container-${VERSION:1}-${{ matrix.arch }}.tar.gz
|
||||||
wget https://github.com/freedomofpress/dangerzone/releases/download/${VERSION}/${CONTAINER_FILENAME} -O ${CONTAINER_FILENAME}
|
wget https://github.com/freedomofpress/dangerzone/releases/download/${VERSION}/${CONTAINER_FILENAME} -O ${CONTAINER_FILENAME}
|
||||||
docker load -i ${CONTAINER_FILENAME}
|
docker load -i ${CONTAINER_FILENAME}
|
||||||
|
|
36
BUILD.md
36
BUILD.md
|
@ -260,11 +260,17 @@ The following instructions require typing commands in a terminal in dom0.
|
||||||
|
|
||||||
```
|
```
|
||||||
qvm-create --class AppVM --label red --template fedora-40-dz dz
|
qvm-create --class AppVM --label red --template fedora-40-dz dz
|
||||||
|
qvm-volume resize dz:private $(numfmt --from=auto 20Gi)
|
||||||
```
|
```
|
||||||
|
|
||||||
> :bulb: Alternatively, you can use a different app qube for Dangerzone
|
> :bulb: Alternatively, you can use a different app qube for Dangerzone
|
||||||
> development. In that case, replace `dz` with the qube of your choice in the
|
> development. In that case, replace `dz` with the qube of your choice in the
|
||||||
> steps below.
|
> steps below.
|
||||||
|
>
|
||||||
|
> In the commands above, we also resize the private volume of the `dz` qube
|
||||||
|
> to 20GiB, since you may need some extra storage space when developing on
|
||||||
|
> Dangerzone (e.g., for container images, Tesseract data, and Python
|
||||||
|
> virtualenvs).
|
||||||
|
|
||||||
4. Add an RPC policy (`/etc/qubes/policy.d/50-dangerzone.policy`) that will
|
4. Add an RPC policy (`/etc/qubes/policy.d/50-dangerzone.policy`) that will
|
||||||
allow launching a disposable qube (`dz-dvm`) when Dangerzone converts a
|
allow launching a disposable qube (`dz-dvm`) when Dangerzone converts a
|
||||||
|
@ -308,18 +314,9 @@ test it.
|
||||||
1. Install the `.rpm` package you just copied
|
1. Install the `.rpm` package you just copied
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo dnf install 'dnf-command(config-manager)'
|
|
||||||
sudo dnf-3 config-manager --add-repo=https://packages.freedom.press/yum-tools-prod/dangerzone/dangerzone.repo
|
|
||||||
sudo dnf install ~/QubesIncoming/dz/*.rpm
|
sudo dnf install ~/QubesIncoming/dz/*.rpm
|
||||||
```
|
```
|
||||||
|
|
||||||
In the above steps, we add the Dangerzone repo because it includes the
|
|
||||||
necessary PySide6 RPM in order to make Dangerzone work.
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> During the installation, you will be asked to
|
|
||||||
> [verify the Dangerzone GPG key](INSTALL.md#verifying-dangerzone-gpg-key).
|
|
||||||
|
|
||||||
2. Shutdown the `fedora-40-dz` template
|
2. Shutdown the `fedora-40-dz` template
|
||||||
|
|
||||||
### Developing Dangerzone
|
### Developing Dangerzone
|
||||||
|
@ -474,11 +471,24 @@ poetry shell
|
||||||
.\dev_scripts\dangerzone.bat
|
.\dev_scripts\dangerzone.bat
|
||||||
```
|
```
|
||||||
|
|
||||||
### If you want to build the installer
|
### If you want to build the Windows installer
|
||||||
|
|
||||||
* Go to https://dotnet.microsoft.com/download/dotnet-framework and download and install .NET Framework 3.5 SP1 Runtime. I downloaded `dotnetfx35.exe`.
|
Install [.NET SDK](https://dotnet.microsoft.com/en-us/download) version 6 or later. Then, open a terminal and install the latest version of [WiX Toolset .NET tool](https://wixtoolset.org/) **v5** with:
|
||||||
* Go to https://wixtoolset.org/releases/ and download and install WiX toolset. I downloaded `wix314.exe`.
|
|
||||||
* Add `C:\Program Files (x86)\WiX Toolset v3.14\bin` to the path ([instructions](https://web.archive.org/web/20230221104142/https://windowsloop.com/how-to-add-to-windows-path/)).
|
```sh
|
||||||
|
dotnet tool install --global wix --version 5.*
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the WiX UI extension. You may need to open a new terminal in order to use the newly installed `wix` .NET tool:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
wix extension add --global WixToolset.UI.wixext/5.x.y
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> To avoid compatibility issues, ensure the WiX UI extension version matches the version of the WiX Toolset.
|
||||||
|
>
|
||||||
|
> Run `wix --version` to check the version of WiX Toolset you have installed and replace `5.x.y` with the full version number without the Git revision.
|
||||||
|
|
||||||
### If you want to sign binaries with Authenticode
|
### If you want to sign binaries with Authenticode
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,15 @@ since 0.4.1, and this project adheres to [Semantic Versioning](https://semver.or
|
||||||
- Disable gVisor's DirectFS feature ([#226](https://github.com/freedomofpress/dangerzone/issues/226)).
|
- Disable gVisor's DirectFS feature ([#226](https://github.com/freedomofpress/dangerzone/issues/226)).
|
||||||
Thanks [EtiennePerot](https://github.com/EtiennePerot) for the contribution.
|
Thanks [EtiennePerot](https://github.com/EtiennePerot) for the contribution.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Platform support: Drop support for Fedora 39, since it's end-of-life ([#999](https://github.com/freedomofpress/dangerzone/pull/999))
|
||||||
|
|
||||||
|
### Development changes
|
||||||
|
|
||||||
|
- Build Dangerzone MSI with Wix Toolset 5 ([#929](https://github.com/freedomofpress/dangerzone/pull/929)).
|
||||||
|
Thanks [@jkarasti](https://github.com/jkarasti) for the contribution.
|
||||||
|
|
||||||
## [0.8.0](https://github.com/freedomofpress/dangerzone/compare/v0.8.0...0.7.1)
|
## [0.8.0](https://github.com/freedomofpress/dangerzone/compare/v0.8.0...0.7.1)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
35
INSTALL.md
35
INSTALL.md
|
@ -1,8 +1,21 @@
|
||||||
## MacOS
|
## MacOS
|
||||||
See instructions in [README.md](README.md#macos).
|
|
||||||
|
- Download [Dangerzone 0.8.0 for Mac (Apple Silicon CPU)](https://github.com/freedomofpress/dangerzone/releases/download/v0.8.0/Dangerzone-0.8.0-arm64.dmg)
|
||||||
|
- Download [Dangerzone 0.8.0 for Mac (Intel CPU)](https://github.com/freedomofpress/dangerzone/releases/download/v0.8.0/Dangerzone-0.8.0-i686.dmg)
|
||||||
|
|
||||||
|
You can also install Dangerzone for Mac using [Homebrew](https://brew.sh/): `brew install --cask dangerzone`
|
||||||
|
|
||||||
|
> **Note**: you will also need to install [Docker Desktop](https://www.docker.com/products/docker-desktop/).
|
||||||
|
> This program needs to run alongside Dangerzone at all times, since it is what allows Dangerzone to
|
||||||
|
> create the secure environment.
|
||||||
|
|
||||||
## Windows
|
## Windows
|
||||||
See instructions in [README.md](README.md#windows).
|
|
||||||
|
- Download [Dangerzone 0.8.0 for Windows](https://github.com/freedomofpress/dangerzone/releases/download/v0.8.0/Dangerzone-0.8.0.msi)
|
||||||
|
|
||||||
|
> **Note**: you will also need to install [Docker Desktop](https://www.docker.com/products/docker-desktop/).
|
||||||
|
> This program needs to run alongside Dangerzone at all times, since it is what allows Dangerzone to
|
||||||
|
> create the secure environment.
|
||||||
|
|
||||||
## Linux
|
## Linux
|
||||||
On Linux, Dangerzone uses [Podman](https://podman.io/) instead of Docker Desktop for creating
|
On Linux, Dangerzone uses [Podman](https://podman.io/) instead of Docker Desktop for creating
|
||||||
|
@ -18,7 +31,6 @@ Dangerzone is available for:
|
||||||
- Debian 11 (bullseye)
|
- Debian 11 (bullseye)
|
||||||
- Fedora 41
|
- Fedora 41
|
||||||
- Fedora 40
|
- Fedora 40
|
||||||
- Fedora 39
|
|
||||||
- Tails
|
- Tails
|
||||||
- Qubes OS (beta support)
|
- Qubes OS (beta support)
|
||||||
|
|
||||||
|
@ -125,23 +137,6 @@ sudo apt install -y dangerzone
|
||||||
|
|
||||||
### Fedora
|
### Fedora
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<details>
|
|
||||||
<summary><i>:information_source: Backport notice for Fedora users regarding the <code>python3-pyside6</code> package</i></summary>
|
|
||||||
</br>
|
|
||||||
|
|
||||||
Fedora 39+ onwards does not provide official Python bindings for Qt. For
|
|
||||||
this reason, we provide our own `python3-pyside6` package (see
|
|
||||||
[build instructions](https://github.com/freedomofpress/maint-dangerzone-pyside6))
|
|
||||||
from our YUM repo. For a deeper dive on this subject, you may read
|
|
||||||
[this issue](https://github.com/freedomofpress/dangerzone/issues/211#issuecomment-1827777122).
|
|
||||||
</details>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
Type the following commands in a terminal:
|
Type the following commands in a terminal:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
197
QA.md
Normal file
197
QA.md
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
## QA
|
||||||
|
|
||||||
|
To ensure that new releases do not introduce regressions, and support existing
|
||||||
|
and newer platforms, we have to test that the produced packages work as expected.
|
||||||
|
|
||||||
|
Check the following:
|
||||||
|
|
||||||
|
- [ ] Make sure that the tip of the `main` branch passes the CI tests.
|
||||||
|
- [ ] Make sure that the Apple account has a valid application password and has
|
||||||
|
agreed to the latest Apple terms (see [macOS release](#macos-release)
|
||||||
|
section).
|
||||||
|
|
||||||
|
Because it is repetitive, we wrote a script to help with the QA.
|
||||||
|
It can run the tasks for you, pausing when it needs manual intervention.
|
||||||
|
|
||||||
|
You can run it with a command like:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
poetry run ./dev_scripts/qa.py {distro}-{version}
|
||||||
|
```
|
||||||
|
|
||||||
|
### The checklist
|
||||||
|
|
||||||
|
- [ ] Create a test build in Windows and make sure it works:
|
||||||
|
- [ ] Check if the suggested Python version is still supported.
|
||||||
|
- [ ] Create a new development environment with Poetry.
|
||||||
|
- [ ] Build the container image and ensure the development environment uses
|
||||||
|
the new image.
|
||||||
|
- [ ] Download the OCR language data using `./install/common/download-tessdata.py`
|
||||||
|
- [ ] Run the Dangerzone tests.
|
||||||
|
- [ ] Build and run the Dangerzone .exe
|
||||||
|
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
||||||
|
- [ ] Create a test build in macOS (Intel CPU) and make sure it works:
|
||||||
|
- [ ] Check if the suggested Python version is still supported.
|
||||||
|
- [ ] Create a new development environment with Poetry.
|
||||||
|
- [ ] Build the container image and ensure the development environment uses
|
||||||
|
the new image.
|
||||||
|
- [ ] Download the OCR language data using `./install/common/download-tessdata.py`
|
||||||
|
- [ ] Run the Dangerzone tests.
|
||||||
|
- [ ] Create and run an app bundle.
|
||||||
|
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
||||||
|
- [ ] Create a test build in macOS (M1/2 CPU) and make sure it works:
|
||||||
|
- [ ] Check if the suggested Python version is still supported.
|
||||||
|
- [ ] Create a new development environment with Poetry.
|
||||||
|
- [ ] Build the container image and ensure the development environment uses
|
||||||
|
the new image.
|
||||||
|
- [ ] Download the OCR language data using `./install/common/download-tessdata.py`
|
||||||
|
- [ ] Run the Dangerzone tests.
|
||||||
|
- [ ] Create and run an app bundle.
|
||||||
|
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
||||||
|
- [ ] Create a test build in the most recent Ubuntu LTS platform (Ubuntu 24.04
|
||||||
|
as of writing this) and make sure it works:
|
||||||
|
- [ ] Create a new development environment with Poetry.
|
||||||
|
- [ ] Build the container image and ensure the development environment uses
|
||||||
|
the new image.
|
||||||
|
- [ ] Download the OCR language data using `./install/common/download-tessdata.py`
|
||||||
|
- [ ] Run the Dangerzone tests.
|
||||||
|
- [ ] Create a .deb package and install it system-wide.
|
||||||
|
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
||||||
|
- [ ] Create a test build in the most recent Fedora platform (Fedora 41 as of
|
||||||
|
writing this) and make sure it works:
|
||||||
|
- [ ] Create a new development environment with Poetry.
|
||||||
|
- [ ] Build the container image and ensure the development environment uses
|
||||||
|
the new image.
|
||||||
|
- [ ] Download the OCR language data using `./install/common/download-tessdata.py`
|
||||||
|
- [ ] Run the Dangerzone tests.
|
||||||
|
- [ ] Create an .rpm package and install it system-wide.
|
||||||
|
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
||||||
|
- [ ] Create a test build in the most recent Qubes Fedora template (Fedora 40 as
|
||||||
|
of writing this) and make sure it works:
|
||||||
|
- [ ] Create a new development environment with Poetry.
|
||||||
|
- [ ] Run the Dangerzone tests.
|
||||||
|
- [ ] Create a Qubes .rpm package and install it system-wide.
|
||||||
|
- [ ] Ensure that the Dangerzone application appears in the "Applications"
|
||||||
|
tab.
|
||||||
|
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below) and make sure
|
||||||
|
they spawn disposable qubes.
|
||||||
|
|
||||||
|
### Scenarios
|
||||||
|
|
||||||
|
#### 1. Dangerzone correctly identifies that Docker/Podman is not installed
|
||||||
|
|
||||||
|
_(Only for MacOS / Windows)_
|
||||||
|
|
||||||
|
Temporarily hide the Docker/Podman binaries, e.g., rename the `docker` /
|
||||||
|
`podman` binaries to something else. Then run Dangerzone. Dangerzone should
|
||||||
|
prompt the user to install Docker/Podman.
|
||||||
|
|
||||||
|
#### 2. Dangerzone correctly identifies that Docker is not running
|
||||||
|
|
||||||
|
_(Only for MacOS / Windows)_
|
||||||
|
|
||||||
|
Stop the Docker Desktop application. Then run Dangerzone. Dangerzone should
|
||||||
|
prompt the user to start Docker Desktop.
|
||||||
|
|
||||||
|
|
||||||
|
#### 3. Updating Dangerzone handles external state correctly.
|
||||||
|
|
||||||
|
_(Applies to Windows/MacOS)_
|
||||||
|
|
||||||
|
Install the previous version of Dangerzone, downloaded from the website.
|
||||||
|
|
||||||
|
Open the Dangerzone application and enable some non-default settings.
|
||||||
|
**If there are new settings, make sure to change those as well**.
|
||||||
|
|
||||||
|
Close the Dangerzone application and get the container image for that
|
||||||
|
version. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ docker images dangerzone.rocks/dangerzone:latest
|
||||||
|
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||||
|
dangerzone.rocks/dangerzone latest <image ID> <date> <size>
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run the version under QA and ensure that the settings remain changed.
|
||||||
|
|
||||||
|
Afterwards check that new docker image was installed by running the same command
|
||||||
|
and seeing the following differences:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ docker images dangerzone.rocks/dangerzone:latest
|
||||||
|
REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||||
|
dangerzone.rocks/dangerzone latest <different ID> <newer date> <different size>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 4. Dangerzone successfully installs the container image
|
||||||
|
|
||||||
|
_(Only for Linux)_
|
||||||
|
|
||||||
|
Remove the Dangerzone container image from Docker/Podman. Then run Dangerzone.
|
||||||
|
Dangerzone should install the container image successfully.
|
||||||
|
|
||||||
|
#### 5. Dangerzone retains the settings of previous runs
|
||||||
|
|
||||||
|
Run Dangerzone and make some changes in the settings (e.g., change the OCR
|
||||||
|
language, toggle whether to open the document after conversion, etc.). Restart
|
||||||
|
Dangerzone. Dangerzone should show the settings that the user chose.
|
||||||
|
|
||||||
|
#### 6. Dangerzone reports failed conversions
|
||||||
|
|
||||||
|
Run Dangerzone and convert the `tests/test_docs/sample_bad_pdf.pdf` document.
|
||||||
|
Dangerzone should fail gracefully, by reporting that the operation failed, and
|
||||||
|
showing the following error message:
|
||||||
|
|
||||||
|
> The document format is not supported
|
||||||
|
|
||||||
|
#### 7. Dangerzone succeeds in converting multiple documents
|
||||||
|
|
||||||
|
Run Dangerzone against a list of documents, and tick all options. Ensure that:
|
||||||
|
* Conversions take place sequentially.
|
||||||
|
* Attempting to close the window while converting asks the user if they want to
|
||||||
|
abort the conversions.
|
||||||
|
* Conversions are completed successfully.
|
||||||
|
* Conversions show individual progress in real-time (double-check for Qubes).
|
||||||
|
* _(Only for Linux)_ The resulting files open with the PDF viewer of our choice.
|
||||||
|
* OCR seems to have detected characters in the PDF files.
|
||||||
|
* The resulting files have been saved with the proper suffix, in the proper
|
||||||
|
location.
|
||||||
|
* The original files have been saved in the `unsafe/` directory.
|
||||||
|
|
||||||
|
#### 8. Dangerzone is able to handle drag-n-drop
|
||||||
|
|
||||||
|
Run Dangerzone against a set of documents that you drag-n-drop. Files should be
|
||||||
|
added and conversion should run without issue.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> On our end-user container environments for Linux, we can start a file manager
|
||||||
|
> with `thunar &`.
|
||||||
|
|
||||||
|
#### 9. Dangerzone CLI succeeds in converting multiple documents
|
||||||
|
|
||||||
|
_(Only for Windows and Linux)_
|
||||||
|
|
||||||
|
Run Dangerzone CLI against a list of documents. Ensure that conversions happen
|
||||||
|
sequentially, are completed successfully, and we see their progress.
|
||||||
|
|
||||||
|
#### 10. Dangerzone can open a document for conversion via right-click -> "Open With"
|
||||||
|
|
||||||
|
_(Only for Windows, MacOS and Qubes)_
|
||||||
|
|
||||||
|
Go to a directory with office documents, right-click on one, and click on "Open
|
||||||
|
With". We should be able to open the file with Dangerzone, and then convert it.
|
||||||
|
|
||||||
|
#### 11. Dangerzone shows helpful errors for setup issues on Qubes
|
||||||
|
|
||||||
|
_(Only for Qubes)_
|
||||||
|
|
||||||
|
Check what errors does Dangerzone throw in the following scenarios. The errors
|
||||||
|
should point the user to the Qubes notifications in the top-right corner:
|
||||||
|
|
||||||
|
1. The `dz-dvm` template does not exist. We can trigger this scenario by
|
||||||
|
temporarily renaming this template.
|
||||||
|
2. The Dangerzone RPC policy does not exist. We can trigger this scenario by
|
||||||
|
temporarily renaming the `dz.Convert` policy.
|
||||||
|
3. The `dz-dvm` disposable Qube cannot start due to insufficient resources. We
|
||||||
|
can trigger this scenario by temporarily increasing the minimum required RAM
|
||||||
|
of the `dz-dvm` template to more than the available amount.
|
30
README.md
30
README.md
|
@ -6,33 +6,21 @@ Take potentially dangerous PDFs, office documents, or images and convert them to
|
||||||
|  | 
|
|  | 
|
||||||
|--|--|
|
|--|--|
|
||||||
|
|
||||||
Dangerzone works like this: You give it a document that you don't know if you can trust (for example, an email attachment). Inside of a sandbox, Dangerzone converts the document to a PDF (if it isn't already one), and then converts the PDF into raw pixel data: a huge list of RGB color values for each page. Then, in a separate sandbox, Dangerzone takes this pixel data and converts it back into a PDF.
|
Dangerzone works like this: You give it a document that you don't know if you can trust (for example, an email attachment). Inside of a sandbox, Dangerzone converts the document to a PDF (if it isn't already one), and then converts the PDF into raw pixel data: a huge list of RGB color values for each page. Then, outside of the sandbox, Dangerzone takes this pixel data and converts it back into a PDF.
|
||||||
|
|
||||||
_Read more about Dangerzone in the [official site](https://dangerzone.rocks/about/)._
|
_Read more about Dangerzone in the [official site](https://dangerzone.rocks/about/)._
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
### MacOS
|
Follow the instructions for each platform:
|
||||||
- Download [Dangerzone 0.8.0 for Mac (Apple Silicon CPU)](https://github.com/freedomofpress/dangerzone/releases/download/v0.8.0/Dangerzone-0.8.0-arm64.dmg)
|
|
||||||
- Download [Dangerzone 0.8.0 for Mac (Intel CPU)](https://github.com/freedomofpress/dangerzone/releases/download/v0.8.0/Dangerzone-0.8.0-i686.dmg)
|
|
||||||
|
|
||||||
You can also install Dangerzone for Mac using [Homebrew](https://brew.sh/): `brew install --cask dangerzone`
|
* [macOS](https://github.com/freedomofpress/dangerzone/blob/v0.8.0//INSTALL.md#macos)
|
||||||
|
* [Windows](https://github.com/freedomofpress/dangerzone/blob/v0.8.0//INSTALL.md#windows)
|
||||||
> **Note**: you will also need to install [Docker Desktop](https://www.docker.com/products/docker-desktop/).
|
* [Ubuntu Linux](https://github.com/freedomofpress/dangerzone/blob/v0.8.0/INSTALL.md#ubuntu-debian)
|
||||||
> This program needs to run alongside Dangerzone at all times, since it is what allows Dangerzone to
|
* [Debian Linux](https://github.com/freedomofpress/dangerzone/blob/v0.8.0/INSTALL.md#ubuntu-debian)
|
||||||
> create the secure environment.
|
* [Fedora Linux](https://github.com/freedomofpress/dangerzone/blob/v0.8.0/INSTALL.md#fedora)
|
||||||
|
* [Qubes OS (beta)](https://github.com/freedomofpress/dangerzone/blob/v0.8.0/INSTALL.md#qubes-os)
|
||||||
### Windows
|
* [Tails](https://github.com/freedomofpress/dangerzone/blob/v0.8.0/INSTALL.md#tails)
|
||||||
|
|
||||||
- Download [Dangerzone 0.8.0 for Windows](https://github.com/freedomofpress/dangerzone/releases/download/v0.8.0/Dangerzone-0.8.0.msi)
|
|
||||||
|
|
||||||
> **Note**: you will also need to install [Docker Desktop](https://www.docker.com/products/docker-desktop/).
|
|
||||||
> This program needs to run alongside Dangerzone at all times, since it is what allows Dangerzone to
|
|
||||||
> create the secure environment.
|
|
||||||
|
|
||||||
### Linux
|
|
||||||
|
|
||||||
See [installing Dangerzone](INSTALL.md#linux) for adding the Linux repositories to your system.
|
|
||||||
|
|
||||||
## Some features
|
## Some features
|
||||||
|
|
||||||
|
|
400
RELEASE.md
400
RELEASE.md
|
@ -1,21 +1,23 @@
|
||||||
# Release instructions
|
# Release instructions
|
||||||
|
|
||||||
This section documents the release process. Unless you're a dangerzone developer making a release, you'll probably never need to follow it.
|
This section documents how we currently release Dangerzone for the different distributions we support.
|
||||||
|
|
||||||
## Pre-release
|
## Pre-release
|
||||||
|
|
||||||
Before making a release, all of these should be complete:
|
Here is a list of tasks that should be done before issuing the release:
|
||||||
|
|
||||||
- [ ] Copy the checkboxes from these instructions onto a new issue and call it **QA and Release version \<VERSION\>**
|
- [ ] Create a new issue named **QA and Release for version \<VERSION\>**, to track the general progress.
|
||||||
|
You can generate its content with the the `poetry run ./dev_scripts/generate-release-tasks.py` command.
|
||||||
- [ ] [Add new Linux platforms and remove obsolete ones](https://github.com/freedomofpress/dangerzone/blob/main/RELEASE.md#add-new-platforms-and-remove-obsolete-ones)
|
- [ ] [Add new Linux platforms and remove obsolete ones](https://github.com/freedomofpress/dangerzone/blob/main/RELEASE.md#add-new-platforms-and-remove-obsolete-ones)
|
||||||
- [ ] Bump the Python dependencies using `poetry lock`
|
- [ ] Bump the Python dependencies using `poetry lock`
|
||||||
- [ ] [Check for official PySide6 versions](https://github.com/freedomofpress/dangerzone/blob/main/RELEASE.md#check-for-official-pyside6-versions)
|
|
||||||
- [ ] Update `version` in `pyproject.toml`
|
- [ ] Update `version` in `pyproject.toml`
|
||||||
- [ ] Update `share/version.txt`
|
- [ ] Update `share/version.txt`
|
||||||
- [ ] Update the "Version" field in `install/linux/dangerzone.spec`
|
- [ ] Update the "Version" field in `install/linux/dangerzone.spec`
|
||||||
- [ ] Bump the Debian version by adding a new changelog entry in `debian/changelog`
|
- [ ] Bump the Debian version by adding a new changelog entry in `debian/changelog`
|
||||||
- [ ] Update screenshot in `README.md`, if necessary
|
- [ ] Update screenshot in `README.md`, if necessary
|
||||||
- [ ] CHANGELOG.md should be updated to include a list of all major changes since the last release
|
- [ ] CHANGELOG.md should be updated to include a list of all major changes since the last release
|
||||||
|
- [ ] A draft release should be created. Copy the release notes text from the template at [`docs/templates/release-notes`](https://github.com/freedomofpress/dangerzone/tree/main/docs/templates/)
|
||||||
|
- [ ] Do the QA tasks
|
||||||
|
|
||||||
## Add new Linux platforms and remove obsolete ones
|
## Add new Linux platforms and remove obsolete ones
|
||||||
|
|
||||||
|
@ -38,22 +40,12 @@ In case of a new version (beta, RC, or official release):
|
||||||
`BUILD.md` files where necessary.
|
`BUILD.md` files where necessary.
|
||||||
4. Send a PR with the above changes.
|
4. Send a PR with the above changes.
|
||||||
|
|
||||||
In case of an EOL version:
|
In case of the removal of a version:
|
||||||
|
|
||||||
1. Remove any mention to this version from our repo.
|
1. Remove any mention to this version from our repo.
|
||||||
* Consult the previous paragraph, but also `grep` your way around.
|
* Consult the previous paragraph, but also `grep` your way around.
|
||||||
2. Add a notice in our `CHANGELOG.md` about the version removal.
|
2. Add a notice in our `CHANGELOG.md` about the version removal.
|
||||||
|
|
||||||
## Check for official PySide6 versions
|
|
||||||
|
|
||||||
PySide6 6.7.0 is available from the Fedora Rawhide repo, and we expect that a
|
|
||||||
similar version will be pushed soon to the rest of the stable releases. Prior to
|
|
||||||
a release, we should check if this has happened already. Once this happens, we
|
|
||||||
should update our CI tests accordingly, and remove this notice.
|
|
||||||
|
|
||||||
For more info, read:
|
|
||||||
https://github.com/freedomofpress/maint-dangerzone-pyside6/issues/5
|
|
||||||
|
|
||||||
## Large Document Testing
|
## Large Document Testing
|
||||||
|
|
||||||
Parallel to the QA process, the release candidate should be put through the large document tests in a dedicated machine to run overnight.
|
Parallel to the QA process, the release candidate should be put through the large document tests in a dedicated machine to run overnight.
|
||||||
|
@ -62,192 +54,13 @@ Follow the instructions in `docs/developer/TESTING.md` to run the tests.
|
||||||
|
|
||||||
These tests will identify any regressions or progression in terms of document coverage.
|
These tests will identify any regressions or progression in terms of document coverage.
|
||||||
|
|
||||||
## QA
|
|
||||||
|
|
||||||
To ensure that new releases do not introduce regressions, and support existing
|
|
||||||
and newer platforms, we have to do the following:
|
|
||||||
|
|
||||||
- [ ] Make sure that the tip of the `main` branch passes the CI tests.
|
|
||||||
- [ ] Make sure that the Apple account has a valid application password and has
|
|
||||||
agreed to the latest Apple terms (see [macOS release](#macos-release)
|
|
||||||
section).
|
|
||||||
- [ ] Create a test build in Windows and make sure it works:
|
|
||||||
- [ ] Check if the suggested Python version is still supported.
|
|
||||||
- [ ] Create a new development environment with Poetry.
|
|
||||||
- [ ] Build the container image and ensure the development environment uses
|
|
||||||
the new image.
|
|
||||||
- [ ] Run the Dangerzone tests.
|
|
||||||
- [ ] Build and run the Dangerzone .exe
|
|
||||||
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
|
||||||
- [ ] Create a test build in macOS (Intel CPU) and make sure it works:
|
|
||||||
- [ ] Check if the suggested Python version is still supported.
|
|
||||||
- [ ] Create a new development environment with Poetry.
|
|
||||||
- [ ] Build the container image and ensure the development environment uses
|
|
||||||
the new image.
|
|
||||||
- [ ] Run the Dangerzone tests.
|
|
||||||
- [ ] Create and run an app bundle.
|
|
||||||
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
|
||||||
- [ ] Create a test build in macOS (M1/2 CPU) and make sure it works:
|
|
||||||
- [ ] Check if the suggested Python version is still supported.
|
|
||||||
- [ ] Create a new development environment with Poetry.
|
|
||||||
- [ ] Build the container image and ensure the development environment uses
|
|
||||||
the new image.
|
|
||||||
- [ ] Run the Dangerzone tests.
|
|
||||||
- [ ] Create and run an app bundle.
|
|
||||||
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
|
||||||
- [ ] Create a test build in the most recent Ubuntu LTS platform (Ubuntu 24.04
|
|
||||||
as of writing this) and make sure it works:
|
|
||||||
- [ ] Create a new development environment with Poetry.
|
|
||||||
- [ ] Build the container image and ensure the development environment uses
|
|
||||||
the new image.
|
|
||||||
- [ ] Run the Dangerzone tests.
|
|
||||||
- [ ] Create a .deb package and install it system-wide.
|
|
||||||
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
|
||||||
- [ ] Create a test build in the most recent Fedora platform (Fedora 41 as of
|
|
||||||
writing this) and make sure it works:
|
|
||||||
- [ ] Create a new development environment with Poetry.
|
|
||||||
- [ ] Build the container image and ensure the development environment uses
|
|
||||||
the new image.
|
|
||||||
- [ ] Run the Dangerzone tests.
|
|
||||||
- [ ] Create an .rpm package and install it system-wide.
|
|
||||||
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
|
||||||
- [ ] Create a test build in the most recent Qubes Fedora template (Fedora 40 as
|
|
||||||
of writing this) and make sure it works:
|
|
||||||
- [ ] Create a new development environment with Poetry.
|
|
||||||
- [ ] Run the Dangerzone tests.
|
|
||||||
- [ ] Create a Qubes .rpm package and install it system-wide.
|
|
||||||
- [ ] Ensure that the Dangerzone application appears in the "Applications"
|
|
||||||
tab.
|
|
||||||
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below) and make sure
|
|
||||||
they spawn disposable qubes.
|
|
||||||
|
|
||||||
### Scenarios
|
|
||||||
|
|
||||||
#### 1. Dangerzone correctly identifies that Docker/Podman is not installed
|
|
||||||
|
|
||||||
_(Only for MacOS / Windows)_
|
|
||||||
|
|
||||||
Temporarily hide the Docker/Podman binaries, e.g., rename the `docker` /
|
|
||||||
`podman` binaries to something else. Then run Dangerzone. Dangerzone should
|
|
||||||
prompt the user to install Docker/Podman.
|
|
||||||
|
|
||||||
#### 2. Dangerzone correctly identifies that Docker is not running
|
|
||||||
|
|
||||||
_(Only for MacOS / Windows)_
|
|
||||||
|
|
||||||
Stop the Docker Desktop application. Then run Dangerzone. Dangerzone should
|
|
||||||
prompt the user to start Docker Desktop.
|
|
||||||
|
|
||||||
|
|
||||||
#### 3. Updating Dangerzone handles external state correctly.
|
|
||||||
|
|
||||||
_(Applies to Windows/MacOS)_
|
|
||||||
|
|
||||||
Install the previous version of Dangerzone, downloaded from the website.
|
|
||||||
|
|
||||||
Open the Dangerzone application and enable some non-default settings.
|
|
||||||
**If there are new settings, make sure to change those as well**.
|
|
||||||
|
|
||||||
Close the Dangerzone application and get the container image for that
|
|
||||||
version. For example:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ docker images dangerzone.rocks/dangerzone:latest
|
|
||||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
|
||||||
dangerzone.rocks/dangerzone latest <image ID> <date> <size>
|
|
||||||
```
|
|
||||||
|
|
||||||
Then run the version under QA and ensure that the settings remain changed.
|
|
||||||
|
|
||||||
Afterwards check that new docker image was installed by running the same command
|
|
||||||
and seeing the following differences:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ docker images dangerzone.rocks/dangerzone:latest
|
|
||||||
REPOSITORY TAG IMAGE ID CREATED SIZE
|
|
||||||
dangerzone.rocks/dangerzone latest <different ID> <newer date> <different size>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 4. Dangerzone successfully installs the container image
|
|
||||||
|
|
||||||
_(Only for Linux)_
|
|
||||||
|
|
||||||
Remove the Dangerzone container image from Docker/Podman. Then run Dangerzone.
|
|
||||||
Dangerzone should install the container image successfully.
|
|
||||||
|
|
||||||
#### 5. Dangerzone retains the settings of previous runs
|
|
||||||
|
|
||||||
Run Dangerzone and make some changes in the settings (e.g., change the OCR
|
|
||||||
language, toggle whether to open the document after conversion, etc.). Restart
|
|
||||||
Dangerzone. Dangerzone should show the settings that the user chose.
|
|
||||||
|
|
||||||
#### 6. Dangerzone reports failed conversions
|
|
||||||
|
|
||||||
Run Dangerzone and convert the `tests/test_docs/sample_bad_pdf.pdf` document.
|
|
||||||
Dangerzone should fail gracefully, by reporting that the operation failed, and
|
|
||||||
showing the following error message:
|
|
||||||
|
|
||||||
> The document format is not supported
|
|
||||||
|
|
||||||
#### 7. Dangerzone succeeds in converting multiple documents
|
|
||||||
|
|
||||||
Run Dangerzone against a list of documents, and tick all options. Ensure that:
|
|
||||||
* Conversions take place sequentially.
|
|
||||||
* Attempting to close the window while converting asks the user if they want to
|
|
||||||
abort the conversions.
|
|
||||||
* Conversions are completed successfully.
|
|
||||||
* Conversions show individual progress in real-time (double-check for Qubes).
|
|
||||||
* _(Only for Linux)_ The resulting files open with the PDF viewer of our choice.
|
|
||||||
* OCR seems to have detected characters in the PDF files.
|
|
||||||
* The resulting files have been saved with the proper suffix, in the proper
|
|
||||||
location.
|
|
||||||
* The original files have been saved in the `unsafe/` directory.
|
|
||||||
|
|
||||||
#### 8. Dangerzone is able to handle drag-n-drop
|
|
||||||
|
|
||||||
Run Dangerzone against a set of documents that you drag-n-drop. Files should be
|
|
||||||
added and conversion should run without issue.
|
|
||||||
|
|
||||||
> [!TIP]
|
|
||||||
> On our end-user container environments for Linux, we can start a file manager
|
|
||||||
> with `thunar &`.
|
|
||||||
|
|
||||||
#### 9. Dangerzone CLI succeeds in converting multiple documents
|
|
||||||
|
|
||||||
_(Only for Windows and Linux)_
|
|
||||||
|
|
||||||
Run Dangerzone CLI against a list of documents. Ensure that conversions happen
|
|
||||||
sequentially, are completed successfully, and we see their progress.
|
|
||||||
|
|
||||||
#### 10. Dangerzone can open a document for conversion via right-click -> "Open With"
|
|
||||||
|
|
||||||
_(Only for Windows, MacOS and Qubes)_
|
|
||||||
|
|
||||||
Go to a directory with office documents, right-click on one, and click on "Open
|
|
||||||
With". We should be able to open the file with Dangerzone, and then convert it.
|
|
||||||
|
|
||||||
#### 11. Dangerzone shows helpful errors for setup issues on Qubes
|
|
||||||
|
|
||||||
_(Only for Qubes)_
|
|
||||||
|
|
||||||
Check what errors does Dangerzone throw in the following scenarios. The errors
|
|
||||||
should point the user to the Qubes notifications in the top-right corner:
|
|
||||||
|
|
||||||
1. The `dz-dvm` template does not exist. We can trigger this scenario by
|
|
||||||
temporarily renaming this template.
|
|
||||||
2. The Dangerzone RPC policy does not exist. We can trigger this scenario by
|
|
||||||
temporarily renaming the `dz.Convert` policy.
|
|
||||||
3. The `dz-dvm` disposable Qube cannot start due to insufficient resources. We
|
|
||||||
can trigger this scenario by temporarily increasing the minimum required RAM
|
|
||||||
of the `dz-dvm` template to more than the available amount.
|
|
||||||
|
|
||||||
## Release
|
## Release
|
||||||
|
|
||||||
Once we are confident that the release will be out shortly, and doesn't need any more changes:
|
Once we are confident that the release will be out shortly, and doesn't need any more changes:
|
||||||
|
|
||||||
- [ ] Create a PGP-signed git tag for the version, e.g., for dangerzone `v0.1.0`:
|
- [ ] Create a PGP-signed git tag for the version, e.g., for dangerzone `v0.1.0`:
|
||||||
|
|
||||||
```
|
```bash
|
||||||
git tag -s v0.1.0
|
git tag -s v0.1.0
|
||||||
git push origin v0.1.0
|
git push origin v0.1.0
|
||||||
```
|
```
|
||||||
|
@ -263,6 +76,8 @@ Once we are confident that the release will be out shortly, and doesn't need any
|
||||||
|
|
||||||
### macOS Release
|
### macOS Release
|
||||||
|
|
||||||
|
This needs to happen for both Silicon and Intel chipsets.
|
||||||
|
|
||||||
#### Initial Setup
|
#### Initial Setup
|
||||||
|
|
||||||
- Build machine must have:
|
- Build machine must have:
|
||||||
|
@ -277,48 +92,85 @@ Once we are confident that the release will be out shortly, and doesn't need any
|
||||||
|
|
||||||
#### Releasing and Signing
|
#### Releasing and Signing
|
||||||
|
|
||||||
|
Here is what you need to do:
|
||||||
|
|
||||||
- [ ] Verify and install the latest supported Python version from
|
- [ ] Verify and install the latest supported Python version from
|
||||||
[python.org](https://www.python.org/downloads/macos/) (do not use the one from
|
[python.org](https://www.python.org/downloads/macos/) (do not use the one from
|
||||||
brew as it is known to [cause issues](https://github.com/freedomofpress/dangerzone/issues/471))
|
brew as it is known to [cause issues](https://github.com/freedomofpress/dangerzone/issues/471))
|
||||||
* In case of a new Python installation or minor version upgrade, e.g., from
|
|
||||||
3.11 to 3.12 , reinstall Poetry with `python3 -m pip install poetry`
|
- [ ] Checkout the dependencies, and clean your local copy:
|
||||||
* You can verify the correct Python version is used with `poetry debug info`
|
|
||||||
- [ ] Verify and checkout the git tag for this release
|
```bash
|
||||||
- [ ] Run `poetry install --sync`
|
|
||||||
- [ ] On the silicon mac, build the container image:
|
# In case of a new Python installation or minor version upgrade, e.g., from
|
||||||
|
# 3.11 to 3.12, reinstall Poetry
|
||||||
|
python3 -m pip install poetry
|
||||||
|
|
||||||
|
# You can verify the correct Python version is used
|
||||||
|
poetry debug info
|
||||||
|
|
||||||
|
# Replace with the actual version
|
||||||
|
export DZ_VERSION=$(cat share/version.txt)
|
||||||
|
|
||||||
|
# Verify and checkout the git tag for this release:
|
||||||
|
git checkout -f v$VERSION
|
||||||
|
|
||||||
|
# Clean the git repository
|
||||||
|
git clean -df
|
||||||
|
|
||||||
|
# Clean up the environment
|
||||||
|
poetry env remove --all
|
||||||
|
|
||||||
|
# Install the dependencies
|
||||||
|
poetry install --sync
|
||||||
```
|
```
|
||||||
python3 ./install/common/build-image.py
|
|
||||||
|
- [ ] Build the container image and the OCR language data
|
||||||
|
|
||||||
|
```bash
|
||||||
|
poetry run ./install/common/build-image.py
|
||||||
|
poetry run ./install/common/download-tessdata.py
|
||||||
|
|
||||||
|
# Copy the container image to the assets folder
|
||||||
|
cp share/container.tar.gz ~dz/release-assets/$VERSION/dangerzone-$VERSION-arm64.tar.gz
|
||||||
|
cp share/image-id.txt ~dz/release-assets/$VERSION/.
|
||||||
```
|
```
|
||||||
Then copy the `share/container.tar.gz` to the assets folder on `dangerzone-$VERSION-arm64.tar.gz`, along with the `share/image-id.txt` file.
|
|
||||||
- [ ] Run `poetry run ./install/macos/build-app.py`; this will make `dist/Dangerzone.app`
|
- [ ] Build the app bundle
|
||||||
|
|
||||||
|
```bash
|
||||||
|
poetry run ./install/macos/build-app.py
|
||||||
|
```
|
||||||
|
|
||||||
- [ ] Make sure that the build application works with the containerd graph
|
- [ ] Make sure that the build application works with the containerd graph
|
||||||
driver (see [#933](https://github.com/freedomofpress/dangerzone/issues/933))
|
driver (see [#933](https://github.com/freedomofpress/dangerzone/issues/933))
|
||||||
- [ ] Run `poetry run ./install/macos/build-app.py --only-codesign`; this will make `dist/Dangerzone.dmg`
|
- [ ] Sign the application bundle, and notarize it
|
||||||
* You need to run this command as the account that has access to the code signing certificate
|
|
||||||
* You must run this command from the MacOS UI, from a terminal application.
|
You need to run this command as the account that has access to the code signing certificate
|
||||||
- [ ] Notarize it: `xcrun notarytool submit --wait --apple-id "<email>" --keychain-profile "dz-notarytool-release-key" dist/Dangerzone.dmg`
|
|
||||||
* You need to change the `<email>` in the above command with the email
|
This command assumes that you have created, and stored in the Keychain, an
|
||||||
associated with the Apple Developer ID.
|
application password associated with your Apple Developer ID, which will be
|
||||||
* This command assumes that you have created, and stored in the Keychain, an
|
used specifically for `notarytool`.
|
||||||
application password associated with your Apple Developer ID, which will be
|
|
||||||
used specifically for `notarytool`.
|
|
||||||
- [ ] Wait for it to get approved:
|
|
||||||
* If it gets rejected, you should be able to see why with the same command
|
|
||||||
(or use the `log` option for a more verbose JSON output)
|
|
||||||
* You will also receive an update in your email.
|
|
||||||
- [ ] After it's approved, staple the ticket: `xcrun stapler staple dist/Dangerzone.dmg`
|
|
||||||
|
|
||||||
This process ends up with the final file:
|
```bash
|
||||||
|
# Sign the .App and make it a .dmg
|
||||||
|
poetry run ./install/macos/build-app.py --only-codesign
|
||||||
|
|
||||||
```
|
# Notarize it. You must run this command from the MacOS UI
|
||||||
dist/Dangerzone.dmg
|
# from a terminal application.
|
||||||
```
|
xcrun notarytool submit ./dist/Dangerzone.dmg --apple-id $APPLE_ID --keychain-profile "dz-notarytool-release-key" --wait && xcrun stapler staple dist/Dangerzone.dmg
|
||||||
|
|
||||||
Rename `Dangerzone.dmg` to `Dangerzone-$VERSION.dmg`.
|
# Copy the .dmg to the assets folder
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
if [ "$ARCH" = "x86_64" ]; then
|
||||||
|
ARCH="i686"
|
||||||
|
fi
|
||||||
|
cp dist/Dangerzone.dmg ~dz/release-assets/$VERSION/Dangerzone-$VERSION-$ARCH.dmg
|
||||||
|
```
|
||||||
|
|
||||||
### Windows Release
|
### Windows Release
|
||||||
|
|
||||||
The Windows release is performed in a Windows 11 virtual machine as opposed to a physical one.
|
The Windows release is performed in a Windows 11 virtual machine (as opposed to a physical one).
|
||||||
|
|
||||||
#### Initial Setup
|
#### Initial Setup
|
||||||
|
|
||||||
|
@ -332,8 +184,31 @@ The Windows release is performed in a Windows 11 virtual machine as opposed to a
|
||||||
|
|
||||||
#### Releasing and Signing
|
#### Releasing and Signing
|
||||||
|
|
||||||
- [ ] Verify and checkout the git tag for this release
|
- [ ] Checkout the dependencies, and clean your local copy:
|
||||||
- [ ] Run `poetry install --sync`
|
```bash
|
||||||
|
# In case of a new Python installation or minor version upgrade, e.g., from
|
||||||
|
# 3.11 to 3.12, reinstall Poetry
|
||||||
|
python3 -m pip install poetry
|
||||||
|
|
||||||
|
# You can verify the correct Python version is used
|
||||||
|
poetry debug info
|
||||||
|
|
||||||
|
# Replace with the actual version
|
||||||
|
export DZ_VERSION=$(cat share/version.txt)
|
||||||
|
|
||||||
|
# Verify and checkout the git tag for this release:
|
||||||
|
git checkout -f v$VERSION
|
||||||
|
|
||||||
|
# Clean the git repository
|
||||||
|
git clean -df
|
||||||
|
|
||||||
|
# Clean up the environment
|
||||||
|
poetry env remove --all
|
||||||
|
|
||||||
|
# Install the dependencies
|
||||||
|
poetry install --sync
|
||||||
|
```
|
||||||
|
|
||||||
- [ ] Copy the container image into the VM
|
- [ ] Copy the container image into the VM
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> Instead of running `python .\install\windows\build-image.py` in the VM, run the build image script on the host (making sure to build for `linux/amd64`). Copy `share/container.tar.gz` and `share/image-id.txt` from the host into the `share` folder in the VM.
|
> Instead of running `python .\install\windows\build-image.py` in the VM, run the build image script on the host (making sure to build for `linux/amd64`). Copy `share/container.tar.gz` and `share/image-id.txt` from the host into the `share` folder in the VM.
|
||||||
|
@ -365,21 +240,15 @@ instructions in our build section](https://github.com/freedomofpress/dangerzone/
|
||||||
or create your own locally with:
|
or create your own locally with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
# Create and run debian bookworm development environment
|
||||||
./dev_scripts/env.py --distro debian --version bookworm build-dev
|
./dev_scripts/env.py --distro debian --version bookworm build-dev
|
||||||
./dev_scripts/env.py --distro debian --version bookworm run --dev bash
|
./dev_scripts/env.py --distro debian --version bookworm run --dev bash
|
||||||
cd dangerzone
|
|
||||||
```
|
|
||||||
|
|
||||||
Build the latest container:
|
# Build the latest container
|
||||||
|
./dev_scripts/env.py --distro debian --version bookworm run --dev bash -c "cd dangerzone && poetry run ./install/common/build-image.py"
|
||||||
|
|
||||||
```sh
|
# Create a .deb
|
||||||
python3 ./install/common/build-image.py
|
./dev_scripts/env.py --distro debian --version bookworm run --dev bash -c "cd dangerzone && ./install/linux/build-deb.py"
|
||||||
```
|
|
||||||
|
|
||||||
Create a .deb:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./install/linux/build-deb.py
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Publish the .deb under `./deb_dist` to the
|
Publish the .deb under `./deb_dist` to the
|
||||||
|
@ -398,22 +267,12 @@ or create your own locally with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./dev_scripts/env.py --distro fedora --version 41 build-dev
|
./dev_scripts/env.py --distro fedora --version 41 build-dev
|
||||||
./dev_scripts/env.py --distro fedora --version 41 run --dev bash
|
|
||||||
cd dangerzone
|
|
||||||
```
|
|
||||||
|
|
||||||
Build the latest container:
|
# Build the latest container (skip if already built):
|
||||||
|
./dev_scripts/env.py --distro fedora --version 41 run --dev bash -c "cd dangerzone && poetry run ./install/common/build-image.py"
|
||||||
|
|
||||||
```sh
|
# Create a .rpm:
|
||||||
python3 ./install/common/build-image.py
|
./dev_scripts/env.py --distro fedora --version 41 run --dev bash -c "cd dangerzone && ./install/linux/build-rpm.py"
|
||||||
```
|
|
||||||
|
|
||||||
Copy the container image to the assets folder on `dangerzone-$VERSION-i686.tar.gz`.
|
|
||||||
|
|
||||||
Create a .rpm:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
./install/linux/build-rpm.py
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Publish the .rpm under `./dist` to the
|
Publish the .rpm under `./dist` to the
|
||||||
|
@ -424,7 +283,7 @@ Publish the .rpm under `./dist` to the
|
||||||
Create a .rpm for Qubes:
|
Create a .rpm for Qubes:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./install/linux/build-rpm.py --qubes
|
./dev_scripts/env.py --distro fedora --version 41 run --dev bash -c "cd dangerzone && ./install/linux/build-rpm.py --qubes"
|
||||||
```
|
```
|
||||||
|
|
||||||
and similarly publish it to the [`freedomofpress/yum-tools-prod`](https://github.com/freedomofpress/yum-tools-prod)
|
and similarly publish it to the [`freedomofpress/yum-tools-prod`](https://github.com/freedomofpress/yum-tools-prod)
|
||||||
|
@ -432,36 +291,37 @@ repo.
|
||||||
|
|
||||||
## Publishing the Release
|
## Publishing the Release
|
||||||
|
|
||||||
To publish the release:
|
To publish the release, you can follow these steps:
|
||||||
|
|
||||||
- [ ] Create an archive of the Dangerzone source in `tar.gz` format:
|
- [ ] Create an archive of the Dangerzone source in `tar.gz` format:
|
||||||
* You can use the following command:
|
```bash
|
||||||
|
export VERSION=$(cat share/version.txt)
|
||||||
```
|
git archive --format=tar.gz -o dangerzone-${VERSION:?}.tar.gz --prefix=dangerzone/ v${VERSION:?}
|
||||||
export DZ_VERSION=$(cat share/version.txt)
|
```
|
||||||
git archive --format=tar.gz -o dangerzone-${DZ_VERSION:?}.tar.gz --prefix=dangerzone/ v${DZ_VERSION:?}
|
|
||||||
```
|
|
||||||
|
|
||||||
- [ ] Run container scan on the produced container images (some time may have passed since the artifacts were built)
|
- [ ] Run container scan on the produced container images (some time may have passed since the artifacts were built)
|
||||||
```
|
```bash
|
||||||
gunzip --keep -c ./share/container.tar.gz > /tmp/container.tar
|
gunzip --keep -c ./share/container.tar.gz > /tmp/container.tar
|
||||||
docker pull anchore/grype:latest
|
docker pull anchore/grype:latest
|
||||||
docker run --rm -v /tmp/container.tar:/container.tar anchore/grype:latest /container.tar
|
docker run --rm -v /tmp/container.tar:/container.tar anchore/grype:latest /container.tar
|
||||||
```
|
```
|
||||||
|
|
||||||
- [ ] Collect the assets in a single directory, calculate their SHA-256 hashes, and sign them.
|
- [ ] Collect the assets in a single directory, calculate their SHA-256 hashes, and sign them.
|
||||||
* You can use `./dev_scripts/sign-assets.py`, if you want to automate this
|
There is an `./dev_scripts/sign-assets.py` script to automate this task.
|
||||||
task.
|
|
||||||
- [ ] Create a new **draft** release on GitHub and upload the macOS and Windows installers.
|
|
||||||
* Copy the release notes text from the template at [`docs/templates/release-notes`](https://github.com/freedomofpress/dangerzone/tree/main/docs/templates/)
|
|
||||||
* You can use `./dev_scripts/upload-asset.py`, if you want to upload an asset
|
|
||||||
using an access token.
|
|
||||||
- [ ] Upload the `container-$VERSION-i686.tar.gz` and `container-$VERSION-arm64.tar.gz` images that were created in the previous step
|
|
||||||
|
|
||||||
**Important:** Make sure that it's the same container images as the ones that
|
**Important:** Before running the script, make sure that it's the same container images as
|
||||||
are shipped in other platforms (see our [Pre-release](#Pre-release) section)
|
the ones that are shipped in other platforms (see our [Pre-release](#Pre-release) section)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Sign all the assets
|
||||||
|
./dev_scripts/sign-assets.py ~/release-assets/$VERSION/github --version $VERSION
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] Upload all the assets to the draft release on GitHub.
|
||||||
|
```bash
|
||||||
|
find ~/release-assets/$VERSION/github | xargs -n1 ./dev_scripts/upload-asset.py --token ~/token --draft
|
||||||
|
```
|
||||||
|
|
||||||
- [ ] Upload the detached signatures (.asc) and checksum file.
|
|
||||||
- [ ] Update the [Dangerzone website](https://github.com/freedomofpress/dangerzone.rocks) to link to the new installers.
|
- [ ] Update the [Dangerzone website](https://github.com/freedomofpress/dangerzone.rocks) to link to the new installers.
|
||||||
- [ ] Update the brew cask release of Dangerzone with a [PR like this one](https://github.com/Homebrew/homebrew-cask/pull/116319)
|
- [ ] Update the brew cask release of Dangerzone with a [PR like this one](https://github.com/Homebrew/homebrew-cask/pull/116319)
|
||||||
- [ ] Update version and download links in `README.md`
|
- [ ] Update version and download links in `README.md`
|
||||||
|
|
|
@ -16,42 +16,6 @@ DEFAULT_USER = "user"
|
||||||
DEFAULT_DRY = False
|
DEFAULT_DRY = False
|
||||||
DEFAULT_DEV = False
|
DEFAULT_DEV = False
|
||||||
DEFAULT_SHOW_DOCKERFILE = False
|
DEFAULT_SHOW_DOCKERFILE = False
|
||||||
DEFAULT_DOWNLOAD_PYSIDE6 = False
|
|
||||||
|
|
||||||
PYSIDE6_VERSION = "6.7.1"
|
|
||||||
PYSIDE6_RPM = "python3-pyside6-{pyside6_version}-1.fc{fedora_version}.x86_64.rpm"
|
|
||||||
PYSIDE6_URL = (
|
|
||||||
"https://packages.freedom.press/yum-tools-prod/dangerzone/f{fedora_version}/%s"
|
|
||||||
% PYSIDE6_RPM
|
|
||||||
)
|
|
||||||
|
|
||||||
PYSIDE6_DL_MESSAGE = """\
|
|
||||||
Downloading PySide6 RPM from:
|
|
||||||
|
|
||||||
{pyside6_url}
|
|
||||||
|
|
||||||
into the following local path:
|
|
||||||
|
|
||||||
{pyside6_local_path}
|
|
||||||
|
|
||||||
The RPM is over 100 MB, so this operation may take a while...
|
|
||||||
"""
|
|
||||||
|
|
||||||
PYSIDE6_NOT_FOUND_ERROR = """\
|
|
||||||
The following package is not present in your system:
|
|
||||||
|
|
||||||
{pyside6_local_path}
|
|
||||||
|
|
||||||
You can build it locally and copy it in the expected path, following the instructions
|
|
||||||
in:
|
|
||||||
|
|
||||||
https://github.com/freedomofpress/python3-pyside6-rpm
|
|
||||||
|
|
||||||
Alternatively, you can rerun the command adding the '--download-pyside6' flag, which
|
|
||||||
will download it from:
|
|
||||||
|
|
||||||
{pyside6_url}
|
|
||||||
"""
|
|
||||||
|
|
||||||
# The Linux distributions that we currently support.
|
# The Linux distributions that we currently support.
|
||||||
# FIXME: Add a version mapping to avoid mistakes.
|
# FIXME: Add a version mapping to avoid mistakes.
|
||||||
|
@ -232,11 +196,6 @@ RUN apt-get update \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
"""
|
"""
|
||||||
|
|
||||||
DOCKERFILE_BUILD_FEDORA_39_DEPS = r"""
|
|
||||||
COPY {pyside6_rpm} /tmp/pyside6.rpm
|
|
||||||
RUN dnf install -y /tmp/pyside6.rpm
|
|
||||||
"""
|
|
||||||
|
|
||||||
DOCKERFILE_BUILD_FEDORA_DEPS = r"""
|
DOCKERFILE_BUILD_FEDORA_DEPS = r"""
|
||||||
RUN dnf install -y mupdf thunar && dnf clean all
|
RUN dnf install -y mupdf thunar && dnf clean all
|
||||||
|
|
||||||
|
@ -390,74 +349,6 @@ def get_files_in(*folders: list[str]) -> list[pathlib.Path]:
|
||||||
return files
|
return files
|
||||||
|
|
||||||
|
|
||||||
class PySide6Manager:
|
|
||||||
"""Provision PySide6 RPMs in our Dangerzone environments.
|
|
||||||
|
|
||||||
This class holds all the logic around checking and downloading PySide RPMs. It can
|
|
||||||
check if the required RPM version is present under "/dist", and optionally download
|
|
||||||
it.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, distro_name, distro_version):
|
|
||||||
if distro_name != "fedora":
|
|
||||||
raise RuntimeError("Managing PySide6 RPMs is available only in Fedora")
|
|
||||||
self.distro_name = distro_name
|
|
||||||
self.distro_version = distro_version
|
|
||||||
|
|
||||||
@property
|
|
||||||
def version(self):
|
|
||||||
"""The version of the PySide6 RPM."""
|
|
||||||
return PYSIDE6_VERSION
|
|
||||||
|
|
||||||
@property
|
|
||||||
def rpm_name(self):
|
|
||||||
"""The name of the PySide6 RPM."""
|
|
||||||
return PYSIDE6_RPM.format(
|
|
||||||
pyside6_version=self.version, fedora_version=self.distro_version
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def rpm_url(self):
|
|
||||||
"""The URL of the PySide6 RPM, as hosted in FPF's RPM repo."""
|
|
||||||
return PYSIDE6_URL.format(
|
|
||||||
pyside6_version=self.version,
|
|
||||||
fedora_version=self.distro_version,
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def rpm_local_path(self):
|
|
||||||
"""The local path where this script will look for the PySide6 RPM."""
|
|
||||||
return git_root() / "dist" / self.rpm_name
|
|
||||||
|
|
||||||
@property
|
|
||||||
def is_rpm_present(self):
|
|
||||||
"""Check if PySide6 RPM is present in the user's system."""
|
|
||||||
return self.rpm_local_path.exists()
|
|
||||||
|
|
||||||
def download_rpm(self):
|
|
||||||
"""Download PySide6 from FPF's RPM repo."""
|
|
||||||
print(
|
|
||||||
PYSIDE6_DL_MESSAGE.format(
|
|
||||||
pyside6_url=self.rpm_url,
|
|
||||||
pyside6_local_path=self.rpm_local_path,
|
|
||||||
),
|
|
||||||
file=sys.stderr,
|
|
||||||
)
|
|
||||||
try:
|
|
||||||
with (
|
|
||||||
urllib.request.urlopen(self.rpm_url) as r,
|
|
||||||
open(self.rpm_local_path, "wb") as f,
|
|
||||||
):
|
|
||||||
shutil.copyfileobj(r, f)
|
|
||||||
except:
|
|
||||||
# NOTE: We purposefully catch all exceptions, since we want to catch Ctrl-C
|
|
||||||
# as well.
|
|
||||||
print("Download interrupted, removing file", file=sys.stderr)
|
|
||||||
self.rpm_local_path.unlink()
|
|
||||||
raise
|
|
||||||
print("PySide6 was downloaded successfully", file=sys.stderr)
|
|
||||||
|
|
||||||
|
|
||||||
class Env:
|
class Env:
|
||||||
"""A class that implements actions on Dangerzone environments"""
|
"""A class that implements actions on Dangerzone environments"""
|
||||||
|
|
||||||
|
@ -736,7 +627,6 @@ class Env:
|
||||||
def build(
|
def build(
|
||||||
self,
|
self,
|
||||||
show_dockerfile=DEFAULT_SHOW_DOCKERFILE,
|
show_dockerfile=DEFAULT_SHOW_DOCKERFILE,
|
||||||
download_pyside6=DEFAULT_DOWNLOAD_PYSIDE6,
|
|
||||||
):
|
):
|
||||||
"""Build a Linux environment and install Dangerzone in it."""
|
"""Build a Linux environment and install Dangerzone in it."""
|
||||||
build_dir = distro_build(self.distro, self.version)
|
build_dir = distro_build(self.distro, self.version)
|
||||||
|
@ -749,28 +639,6 @@ class Env:
|
||||||
package = package_src.name
|
package = package_src.name
|
||||||
package_dst = build_dir / package
|
package_dst = build_dir / package
|
||||||
install_cmd = "dnf install -y"
|
install_cmd = "dnf install -y"
|
||||||
|
|
||||||
# NOTE: For Fedora 39, we check if a PySide6 RPM package exists in
|
|
||||||
# the user's system. If not, we either throw an error or download it from
|
|
||||||
# FPF's repo, according to the user's choice.
|
|
||||||
if self.version == "39":
|
|
||||||
pyside6 = PySide6Manager(self.distro, self.version)
|
|
||||||
if not pyside6.is_rpm_present:
|
|
||||||
if download_pyside6:
|
|
||||||
pyside6.download_rpm()
|
|
||||||
else:
|
|
||||||
print(
|
|
||||||
PYSIDE6_NOT_FOUND_ERROR.format(
|
|
||||||
pyside6_local_path=pyside6.rpm_local_path,
|
|
||||||
pyside6_url=pyside6.rpm_url,
|
|
||||||
),
|
|
||||||
file=sys.stderr,
|
|
||||||
)
|
|
||||||
return 1
|
|
||||||
shutil.copy(pyside6.rpm_local_path, build_dir / pyside6.rpm_name)
|
|
||||||
install_deps = (
|
|
||||||
DOCKERFILE_BUILD_FEDORA_DEPS + DOCKERFILE_BUILD_FEDORA_39_DEPS
|
|
||||||
).format(pyside6_rpm=pyside6.rpm_name)
|
|
||||||
else:
|
else:
|
||||||
install_deps = DOCKERFILE_BUILD_DEBIAN_DEPS
|
install_deps = DOCKERFILE_BUILD_DEBIAN_DEPS
|
||||||
if self.distro == "ubuntu" and self.version in ("20.04", "focal"):
|
if self.distro == "ubuntu" and self.version in ("20.04", "focal"):
|
||||||
|
@ -844,7 +712,6 @@ def env_build(args):
|
||||||
env = Env.from_args(args)
|
env = Env.from_args(args)
|
||||||
return env.build(
|
return env.build(
|
||||||
show_dockerfile=args.show_dockerfile,
|
show_dockerfile=args.show_dockerfile,
|
||||||
download_pyside6=args.download_pyside6,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -941,12 +808,6 @@ def parse_args():
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="Do not build, only show the Dockerfile",
|
help="Do not build, only show the Dockerfile",
|
||||||
)
|
)
|
||||||
parser_build.add_argument(
|
|
||||||
"--download-pyside6",
|
|
||||||
default=DEFAULT_DOWNLOAD_PYSIDE6,
|
|
||||||
action="store_true",
|
|
||||||
help="Download PySide6 from FPF's RPM repo",
|
|
||||||
)
|
|
||||||
|
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
67
dev_scripts/generate-release-tasks.py
Executable file
67
dev_scripts/generate-release-tasks.py
Executable file
|
@ -0,0 +1,67 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
import pathlib
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
RELEASE_FILE = "RELEASE.md"
|
||||||
|
QA_FILE = "QA.md"
|
||||||
|
|
||||||
|
|
||||||
|
def git_root():
|
||||||
|
"""Get the root directory of the Git repo."""
|
||||||
|
# FIXME: Use a Git Python binding for this.
|
||||||
|
# FIXME: Make this work if called outside the repo.
|
||||||
|
path = (
|
||||||
|
subprocess.run(
|
||||||
|
["git", "rev-parse", "--show-toplevel"],
|
||||||
|
check=True,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
)
|
||||||
|
.stdout.decode()
|
||||||
|
.strip("\n")
|
||||||
|
)
|
||||||
|
return pathlib.Path(path)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_checkboxes(filename):
|
||||||
|
headers = []
|
||||||
|
result = []
|
||||||
|
|
||||||
|
with open(filename, "r") as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
|
||||||
|
current_level = 0
|
||||||
|
for line in lines:
|
||||||
|
line = line.rstrip()
|
||||||
|
|
||||||
|
# If it's a header, store it
|
||||||
|
if line.startswith("#"):
|
||||||
|
# Count number of # to determine header level
|
||||||
|
level = len(line) - len(line.lstrip("#"))
|
||||||
|
if level < current_level or not current_level:
|
||||||
|
headers.extend(["", line, ""])
|
||||||
|
current_level = level
|
||||||
|
elif level > current_level:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
headers = ["", line, ""]
|
||||||
|
|
||||||
|
# If it's a checkbox
|
||||||
|
elif "- [ ]" in line or "- [x]" in line or "- [X]" in line:
|
||||||
|
# Print the last header if we haven't already
|
||||||
|
if headers:
|
||||||
|
result.extend(headers)
|
||||||
|
headers = []
|
||||||
|
current_level = 0
|
||||||
|
|
||||||
|
# If this is the "Do the QA tasks" line, recursively get QA tasks
|
||||||
|
if "Do the QA tasks" in line:
|
||||||
|
result.append(line)
|
||||||
|
qa_tasks = extract_checkboxes(git_root() / QA_FILE)
|
||||||
|
result.append(qa_tasks)
|
||||||
|
else:
|
||||||
|
result.append(line)
|
||||||
|
return "\n".join(result)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(extract_checkboxes(git_root() / RELEASE_FILE))
|
|
@ -3,28 +3,49 @@
|
||||||
import abc
|
import abc
|
||||||
import argparse
|
import argparse
|
||||||
import difflib
|
import difflib
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import selectors
|
import selectors
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import urllib.request
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
PYTHON_VERSION = "3.12"
|
||||||
|
EOL_PYTHON_URL = "https://endoflife.date/api/python.json"
|
||||||
|
|
||||||
CONTENT_QA = r"""## QA
|
CONTENT_QA = r"""## QA
|
||||||
|
|
||||||
To ensure that new releases do not introduce regressions, and support existing
|
To ensure that new releases do not introduce regressions, and support existing
|
||||||
and newer platforms, we have to do the following:
|
and newer platforms, we have to test that the produced packages work as expected.
|
||||||
|
|
||||||
|
Check the following:
|
||||||
|
|
||||||
- [ ] Make sure that the tip of the `main` branch passes the CI tests.
|
- [ ] Make sure that the tip of the `main` branch passes the CI tests.
|
||||||
- [ ] Make sure that the Apple account has a valid application password and has
|
- [ ] Make sure that the Apple account has a valid application password and has
|
||||||
agreed to the latest Apple terms (see [macOS release](#macos-release)
|
agreed to the latest Apple terms (see [macOS release](#macos-release)
|
||||||
section).
|
section).
|
||||||
|
|
||||||
|
Because it is repetitive, we wrote a script to help with the QA.
|
||||||
|
It can run the tasks for you, pausing when it needs manual intervention.
|
||||||
|
|
||||||
|
You can run it with a command like:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
poetry run ./dev_scripts/qa.py {distro}-{version}
|
||||||
|
```
|
||||||
|
|
||||||
|
### The checklist
|
||||||
|
|
||||||
- [ ] Create a test build in Windows and make sure it works:
|
- [ ] Create a test build in Windows and make sure it works:
|
||||||
- [ ] Check if the suggested Python version is still supported.
|
- [ ] Check if the suggested Python version is still supported.
|
||||||
- [ ] Create a new development environment with Poetry.
|
- [ ] Create a new development environment with Poetry.
|
||||||
- [ ] Build the container image and ensure the development environment uses
|
- [ ] Build the container image and ensure the development environment uses
|
||||||
the new image.
|
the new image.
|
||||||
|
- [ ] Download the OCR language data using `./install/common/download-tessdata.py`
|
||||||
- [ ] Run the Dangerzone tests.
|
- [ ] Run the Dangerzone tests.
|
||||||
- [ ] Build and run the Dangerzone .exe
|
- [ ] Build and run the Dangerzone .exe
|
||||||
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
||||||
|
@ -33,6 +54,7 @@ and newer platforms, we have to do the following:
|
||||||
- [ ] Create a new development environment with Poetry.
|
- [ ] Create a new development environment with Poetry.
|
||||||
- [ ] Build the container image and ensure the development environment uses
|
- [ ] Build the container image and ensure the development environment uses
|
||||||
the new image.
|
the new image.
|
||||||
|
- [ ] Download the OCR language data using `./install/common/download-tessdata.py`
|
||||||
- [ ] Run the Dangerzone tests.
|
- [ ] Run the Dangerzone tests.
|
||||||
- [ ] Create and run an app bundle.
|
- [ ] Create and run an app bundle.
|
||||||
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
||||||
|
@ -41,6 +63,7 @@ and newer platforms, we have to do the following:
|
||||||
- [ ] Create a new development environment with Poetry.
|
- [ ] Create a new development environment with Poetry.
|
||||||
- [ ] Build the container image and ensure the development environment uses
|
- [ ] Build the container image and ensure the development environment uses
|
||||||
the new image.
|
the new image.
|
||||||
|
- [ ] Download the OCR language data using `./install/common/download-tessdata.py`
|
||||||
- [ ] Run the Dangerzone tests.
|
- [ ] Run the Dangerzone tests.
|
||||||
- [ ] Create and run an app bundle.
|
- [ ] Create and run an app bundle.
|
||||||
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
||||||
|
@ -49,6 +72,7 @@ and newer platforms, we have to do the following:
|
||||||
- [ ] Create a new development environment with Poetry.
|
- [ ] Create a new development environment with Poetry.
|
||||||
- [ ] Build the container image and ensure the development environment uses
|
- [ ] Build the container image and ensure the development environment uses
|
||||||
the new image.
|
the new image.
|
||||||
|
- [ ] Download the OCR language data using `./install/common/download-tessdata.py`
|
||||||
- [ ] Run the Dangerzone tests.
|
- [ ] Run the Dangerzone tests.
|
||||||
- [ ] Create a .deb package and install it system-wide.
|
- [ ] Create a .deb package and install it system-wide.
|
||||||
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
||||||
|
@ -57,6 +81,7 @@ and newer platforms, we have to do the following:
|
||||||
- [ ] Create a new development environment with Poetry.
|
- [ ] Create a new development environment with Poetry.
|
||||||
- [ ] Build the container image and ensure the development environment uses
|
- [ ] Build the container image and ensure the development environment uses
|
||||||
the new image.
|
the new image.
|
||||||
|
- [ ] Download the OCR language data using `./install/common/download-tessdata.py`
|
||||||
- [ ] Run the Dangerzone tests.
|
- [ ] Run the Dangerzone tests.
|
||||||
- [ ] Create an .rpm package and install it system-wide.
|
- [ ] Create an .rpm package and install it system-wide.
|
||||||
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
- [ ] Test some QA scenarios (see [Scenarios](#Scenarios) below).
|
||||||
|
@ -547,7 +572,7 @@ class Reference:
|
||||||
# Convert spaces to dashes
|
# Convert spaces to dashes
|
||||||
anchor = anchor.replace(" ", "-")
|
anchor = anchor.replace(" ", "-")
|
||||||
# Remove non-alphanumeric (except dash and underscore)
|
# Remove non-alphanumeric (except dash and underscore)
|
||||||
anchor = re.sub("[^a-zA-Z\-_]", "", anchor)
|
anchor = re.sub("[^a-zA-Z-_]", "", anchor)
|
||||||
|
|
||||||
return anchor
|
return anchor
|
||||||
|
|
||||||
|
@ -566,8 +591,8 @@ class QABase(abc.ABC):
|
||||||
|
|
||||||
platforms = {}
|
platforms = {}
|
||||||
|
|
||||||
REF_QA = Reference("RELEASE.md", content=CONTENT_QA)
|
REF_QA = Reference("QA.md", content=CONTENT_QA)
|
||||||
REF_QA_SCENARIOS = Reference("RELEASE.md", content=CONTENT_QA_SCENARIOS)
|
REF_QA_SCENARIOS = Reference("QA.md", content=CONTENT_QA_SCENARIOS)
|
||||||
|
|
||||||
# The following class method is available since Python 3.6. For more details, see:
|
# The following class method is available since Python 3.6. For more details, see:
|
||||||
# https://docs.python.org/3.6/whatsnew/3.6.html#pep-487-simpler-customization-of-class-creation
|
# https://docs.python.org/3.6/whatsnew/3.6.html#pep-487-simpler-customization-of-class-creation
|
||||||
|
@ -776,6 +801,10 @@ class QABase(abc.ABC):
|
||||||
self.prompt("Does it pass?", choices=["y", "n"])
|
self.prompt("Does it pass?", choices=["y", "n"])
|
||||||
logger.info("Successfully completed QA scenarios")
|
logger.info("Successfully completed QA scenarios")
|
||||||
|
|
||||||
|
@task("Download Tesseract data", auto=True)
|
||||||
|
def download_tessdata(self):
|
||||||
|
self.run("python", str(Path("install", "common", "download-tessdata.py")))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
def get_id(cls):
|
def get_id(cls):
|
||||||
|
@ -802,6 +831,40 @@ class QAWindows(QABase):
|
||||||
while msvcrt.kbhit():
|
while msvcrt.kbhit():
|
||||||
msvcrt.getch()
|
msvcrt.getch()
|
||||||
|
|
||||||
|
def get_latest_python_release(self):
|
||||||
|
with urllib.request.urlopen(EOL_PYTHON_URL) as f:
|
||||||
|
resp = f.read()
|
||||||
|
releases = json.loads(resp)
|
||||||
|
for release in releases:
|
||||||
|
if release["cycle"] == PYTHON_VERSION:
|
||||||
|
# Transform the Python version string (e.g., "3.12.7") into a list
|
||||||
|
# (e.g., [3, 12, 7]), and return it
|
||||||
|
return [int(num) for num in release["latest"].split(".")]
|
||||||
|
|
||||||
|
raise RuntimeError(
|
||||||
|
f"Could not find a Python release for version {PYTHON_VERSION}"
|
||||||
|
)
|
||||||
|
|
||||||
|
@QABase.task(
|
||||||
|
f"Install the latest version of Python {PYTHON_VERSION}", ref=REF_BUILD
|
||||||
|
)
|
||||||
|
def install_python(self):
|
||||||
|
logger.info("Getting latest Python release")
|
||||||
|
try:
|
||||||
|
latest_version = self.get_latest_python_release()
|
||||||
|
except Exception:
|
||||||
|
logger.error("Could not verify that the latest Python version is installed")
|
||||||
|
|
||||||
|
cur_version = list(sys.version_info[:3])
|
||||||
|
if latest_version > cur_version:
|
||||||
|
self.prompt(
|
||||||
|
f"You need to install the latest Python version ({latest_version})"
|
||||||
|
)
|
||||||
|
elif latest_version == cur_version:
|
||||||
|
logger.info(
|
||||||
|
f"Verified that the latest Python version ({latest_version}) is installed"
|
||||||
|
)
|
||||||
|
|
||||||
@QABase.task("Install and Run Docker Desktop", ref=REF_BUILD)
|
@QABase.task("Install and Run Docker Desktop", ref=REF_BUILD)
|
||||||
def install_docker(self):
|
def install_docker(self):
|
||||||
logger.info("Checking if Docker Desktop is installed and running")
|
logger.info("Checking if Docker Desktop is installed and running")
|
||||||
|
@ -816,7 +879,7 @@ class QAWindows(QABase):
|
||||||
)
|
)
|
||||||
def install_poetry(self):
|
def install_poetry(self):
|
||||||
self.run("python", "-m", "pip", "install", "poetry")
|
self.run("python", "-m", "pip", "install", "poetry")
|
||||||
self.run("poetry", "install")
|
self.run("poetry", "install", "--sync")
|
||||||
|
|
||||||
@QABase.task("Build Dangerzone container image", ref=REF_BUILD, auto=True)
|
@QABase.task("Build Dangerzone container image", ref=REF_BUILD, auto=True)
|
||||||
def build_image(self):
|
def build_image(self):
|
||||||
|
@ -838,9 +901,11 @@ class QAWindows(QABase):
|
||||||
return "windows"
|
return "windows"
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
self.install_python()
|
||||||
self.install_docker()
|
self.install_docker()
|
||||||
self.install_poetry()
|
self.install_poetry()
|
||||||
self.build_image()
|
self.build_image()
|
||||||
|
self.download_tessdata()
|
||||||
self.run_tests()
|
self.run_tests()
|
||||||
self.build_dangerzone_exe()
|
self.build_dangerzone_exe()
|
||||||
|
|
||||||
|
@ -915,7 +980,6 @@ class QALinux(QABase):
|
||||||
"--version",
|
"--version",
|
||||||
self.VERSION,
|
self.VERSION,
|
||||||
"build",
|
"build",
|
||||||
"--download-pyside6",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -933,6 +997,7 @@ class QALinux(QABase):
|
||||||
def start(self):
|
def start(self):
|
||||||
self.build_dev_image()
|
self.build_dev_image()
|
||||||
self.build_container_image()
|
self.build_container_image()
|
||||||
|
self.download_tessdata()
|
||||||
self.run_tests()
|
self.run_tests()
|
||||||
self.build_package()
|
self.build_package()
|
||||||
self.build_qa_image()
|
self.build_qa_image()
|
||||||
|
@ -1005,14 +1070,14 @@ class QAFedora(QALinux):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class QAFedora41(QAFedora):
|
||||||
|
VERSION = "41"
|
||||||
|
|
||||||
|
|
||||||
class QAFedora40(QAFedora):
|
class QAFedora40(QAFedora):
|
||||||
VERSION = "40"
|
VERSION = "40"
|
||||||
|
|
||||||
|
|
||||||
class QAFedora39(QAFedora):
|
|
||||||
VERSION = "39"
|
|
||||||
|
|
||||||
|
|
||||||
def parse_args():
|
def parse_args():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
prog=sys.argv[0],
|
prog=sys.argv[0],
|
||||||
|
|
|
@ -17,22 +17,23 @@ signtool.exe sign /v /d "Dangerzone" /a /n "Freedom of the Press Foundation" /fd
|
||||||
REM verify the signature of dangerzone-cli.exe
|
REM verify the signature of dangerzone-cli.exe
|
||||||
signtool.exe verify /pa build\exe.win-amd64-3.12\dangerzone-cli.exe
|
signtool.exe verify /pa build\exe.win-amd64-3.12\dangerzone-cli.exe
|
||||||
|
|
||||||
REM build the wix file
|
REM build the wxs file
|
||||||
python install\windows\build-wxs.py > build\Dangerzone.wxs
|
python install\windows\build-wxs.py
|
||||||
|
|
||||||
REM build the msi package
|
REM build the msi package
|
||||||
cd build
|
cd build
|
||||||
candle.exe Dangerzone.wxs
|
wix build -arch x64 -ext WixToolset.UI.wixext .\Dangerzone.wxs -out Dangerzone.msi
|
||||||
light.exe -ext WixUIExtension Dangerzone.wixobj
|
|
||||||
|
REM validate Dangerzone.msi
|
||||||
|
wix msi validate Dangerzone.msi
|
||||||
|
|
||||||
REM code sign Dangerzone.msi
|
REM code sign Dangerzone.msi
|
||||||
insignia.exe -im Dangerzone.msi
|
|
||||||
signtool.exe sign /v /d "Dangerzone" /a /n "Freedom of the Press Foundation" /fd sha256 /t http://time.certum.pl/ Dangerzone.msi
|
signtool.exe sign /v /d "Dangerzone" /a /n "Freedom of the Press Foundation" /fd sha256 /t http://time.certum.pl/ Dangerzone.msi
|
||||||
|
|
||||||
REM verify the signature of Dangerzone.msi
|
REM verify the signature of Dangerzone.msi
|
||||||
signtool.exe verify /pa Dangerzone.msi
|
signtool.exe verify /pa Dangerzone.msi
|
||||||
|
|
||||||
REM moving Dangerzone.msi to dist
|
REM move Dangerzone.msi to dist
|
||||||
cd ..
|
cd ..
|
||||||
mkdir dist
|
mkdir dist
|
||||||
move build\Dangerzone.msi dist
|
move build\Dangerzone.msi dist
|
||||||
|
|
|
@ -4,114 +4,75 @@ import uuid
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
|
|
||||||
def build_data(dirname, dir_prefix, id_, name):
|
def build_data(base_path, path_prefix, dir_id, dir_name):
|
||||||
data = {
|
data = {
|
||||||
"id": id_,
|
"directory_name": dir_name,
|
||||||
"name": name,
|
"directory_id": dir_id,
|
||||||
"files": [],
|
"files": [],
|
||||||
"dirs": [],
|
"dirs": [],
|
||||||
}
|
}
|
||||||
|
|
||||||
for basename in os.listdir(dirname):
|
if dir_id == "INSTALLFOLDER":
|
||||||
filename = os.path.join(dirname, basename)
|
data["component_id"] = "ApplicationFiles"
|
||||||
if os.path.isfile(filename):
|
else:
|
||||||
data["files"].append(os.path.join(dir_prefix, basename))
|
data["component_id"] = "Component" + dir_id
|
||||||
elif os.path.isdir(filename):
|
data["component_guid"] = str(uuid.uuid4()).upper()
|
||||||
if id_ == "INSTALLDIR":
|
|
||||||
id_prefix = "Folder"
|
for entry in os.listdir(base_path):
|
||||||
|
entry_path = os.path.join(base_path, entry)
|
||||||
|
if os.path.isfile(entry_path):
|
||||||
|
data["files"].append(os.path.join(path_prefix, entry))
|
||||||
|
elif os.path.isdir(entry_path):
|
||||||
|
if dir_id == "INSTALLFOLDER":
|
||||||
|
next_dir_prefix = "Folder"
|
||||||
else:
|
else:
|
||||||
id_prefix = id_
|
next_dir_prefix = dir_id
|
||||||
|
|
||||||
# Skip lib/PySide6/examples folder due to ilegal file names
|
# Skip lib/PySide6/examples folder due to ilegal file names
|
||||||
if "\\build\\exe.win-amd64-3.12\\lib\\PySide6\\examples" in dirname:
|
if "\\build\\exe.win-amd64-3.12\\lib\\PySide6\\examples" in base_path:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Skip lib/PySide6/qml/QtQuick folder due to ilegal file names
|
# Skip lib/PySide6/qml/QtQuick folder due to ilegal file names
|
||||||
# XXX Since we're not using Qml it should be no problem
|
# XXX Since we're not using Qml it should be no problem
|
||||||
if "\\build\\exe.win-amd64-3.12\\lib\\PySide6\\qml\\QtQuick" in dirname:
|
if "\\build\\exe.win-amd64-3.12\\lib\\PySide6\\qml\\QtQuick" in base_path:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
id_value = f"{id_prefix}{basename.capitalize().replace('-', '_')}"
|
next_dir_id = next_dir_prefix + entry.capitalize().replace("-", "_")
|
||||||
data["dirs"].append(
|
subdata = build_data(
|
||||||
build_data(
|
os.path.join(base_path, entry),
|
||||||
os.path.join(dirname, basename),
|
os.path.join(path_prefix, entry),
|
||||||
os.path.join(dir_prefix, basename),
|
next_dir_id,
|
||||||
id_value,
|
entry,
|
||||||
basename,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if len(data["files"]) > 0:
|
# Add the subdirectory only if it contains files or subdirectories
|
||||||
if id_ == "INSTALLDIR":
|
if subdata["files"] or subdata["dirs"]:
|
||||||
data["component_id"] = "ApplicationFiles"
|
data["dirs"].append(subdata)
|
||||||
else:
|
|
||||||
data["component_id"] = "FolderComponent" + id_[len("Folder") :]
|
|
||||||
data["component_guid"] = str(uuid.uuid4())
|
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
def build_dir_xml(root, data):
|
def build_directory_xml(root, data):
|
||||||
attrs = {}
|
attrs = {}
|
||||||
if "id" in data:
|
attrs["Id"] = data["directory_id"]
|
||||||
attrs["Id"] = data["id"]
|
attrs["Name"] = data["directory_name"]
|
||||||
if "name" in data:
|
directory_el = ET.SubElement(root, "Directory", attrs)
|
||||||
attrs["Name"] = data["name"]
|
|
||||||
el = ET.SubElement(root, "Directory", attrs)
|
|
||||||
for subdata in data["dirs"]:
|
for subdata in data["dirs"]:
|
||||||
build_dir_xml(el, subdata)
|
build_directory_xml(directory_el, subdata)
|
||||||
|
|
||||||
# If this is the ProgramMenuFolder, add the menu component
|
|
||||||
if "id" in data and data["id"] == "ProgramMenuFolder":
|
|
||||||
component_el = ET.SubElement(
|
|
||||||
el,
|
|
||||||
"Component",
|
|
||||||
Id="ApplicationShortcuts",
|
|
||||||
Guid="539e7de8-a124-4c09-aa55-0dd516aad7bc",
|
|
||||||
)
|
|
||||||
ET.SubElement(
|
|
||||||
component_el,
|
|
||||||
"Shortcut",
|
|
||||||
Id="ApplicationShortcut1",
|
|
||||||
Name="Dangerzone",
|
|
||||||
Description="Dangerzone",
|
|
||||||
Target="[INSTALLDIR]dangerzone.exe",
|
|
||||||
WorkingDirectory="INSTALLDIR",
|
|
||||||
)
|
|
||||||
ET.SubElement(
|
|
||||||
component_el,
|
|
||||||
"RegistryValue",
|
|
||||||
Root="HKCU",
|
|
||||||
Key="Software\Freedom of the Press Foundation\Dangerzone",
|
|
||||||
Name="installed",
|
|
||||||
Type="integer",
|
|
||||||
Value="1",
|
|
||||||
KeyPath="yes",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def build_components_xml(root, data):
|
def build_components_xml(root, data):
|
||||||
component_ids = []
|
component_el = ET.SubElement(
|
||||||
if "component_id" in data:
|
root,
|
||||||
component_ids.append(data["component_id"])
|
"Component",
|
||||||
|
Id=data["component_id"],
|
||||||
|
Guid=data["component_guid"],
|
||||||
|
Directory=data["directory_id"],
|
||||||
|
)
|
||||||
|
for filename in data["files"]:
|
||||||
|
ET.SubElement(component_el, "File", Source=filename)
|
||||||
for subdata in data["dirs"]:
|
for subdata in data["dirs"]:
|
||||||
if "component_guid" in subdata:
|
build_components_xml(root, subdata)
|
||||||
dir_ref_el = ET.SubElement(root, "DirectoryRef", Id=subdata["id"])
|
|
||||||
component_el = ET.SubElement(
|
|
||||||
dir_ref_el,
|
|
||||||
"Component",
|
|
||||||
Id=subdata["component_id"],
|
|
||||||
Guid=subdata["component_guid"],
|
|
||||||
)
|
|
||||||
for filename in subdata["files"]:
|
|
||||||
file_el = ET.SubElement(
|
|
||||||
component_el, "File", Source=filename, Id="file_" + uuid.uuid4().hex
|
|
||||||
)
|
|
||||||
|
|
||||||
component_ids += build_components_xml(root, subdata)
|
|
||||||
|
|
||||||
return component_ids
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
@ -125,120 +86,188 @@ def main():
|
||||||
# -rc markers.
|
# -rc markers.
|
||||||
version = f.read().strip().split("-")[0]
|
version = f.read().strip().split("-")[0]
|
||||||
|
|
||||||
dist_dir = os.path.join(
|
build_dir = os.path.join(
|
||||||
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
|
os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))),
|
||||||
"build",
|
"build",
|
||||||
"exe.win-amd64-3.12",
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cx_freeze_dir = "exe.win-amd64-3.12"
|
||||||
|
|
||||||
|
dist_dir = os.path.join(build_dir, cx_freeze_dir)
|
||||||
|
|
||||||
if not os.path.exists(dist_dir):
|
if not os.path.exists(dist_dir):
|
||||||
print("You must build the dangerzone binary before running this")
|
print("You must build the dangerzone binary before running this")
|
||||||
return
|
return
|
||||||
|
|
||||||
data = {
|
# Prepare data for WiX file harvesting from the output of cx_Freeze
|
||||||
"id": "TARGETDIR",
|
data = build_data(
|
||||||
"name": "SourceDir",
|
dist_dir,
|
||||||
"dirs": [
|
cx_freeze_dir,
|
||||||
{
|
"INSTALLFOLDER",
|
||||||
"id": "ProgramFilesFolder",
|
"Dangerzone",
|
||||||
"dirs": [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "ProgramMenuFolder",
|
|
||||||
"dirs": [],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
|
||||||
|
|
||||||
data["dirs"][0]["dirs"].append(
|
|
||||||
build_data(
|
|
||||||
dist_dir,
|
|
||||||
"exe.win-amd64-3.12",
|
|
||||||
"INSTALLDIR",
|
|
||||||
"Dangerzone",
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
root_el = ET.Element("Wix", xmlns="http://schemas.microsoft.com/wix/2006/wi")
|
# Add the Wix root element
|
||||||
product_el = ET.SubElement(
|
wix_el = ET.Element(
|
||||||
root_el,
|
"Wix",
|
||||||
"Product",
|
{
|
||||||
|
"xmlns": "http://wixtoolset.org/schemas/v4/wxs",
|
||||||
|
"xmlns:ui": "http://wixtoolset.org/schemas/v4/wxs/ui",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the Package element
|
||||||
|
package_el = ET.SubElement(
|
||||||
|
wix_el,
|
||||||
|
"Package",
|
||||||
Name="Dangerzone",
|
Name="Dangerzone",
|
||||||
Manufacturer="Freedom of the Press Foundation",
|
Manufacturer="Freedom of the Press Foundation",
|
||||||
Id="*",
|
UpgradeCode="12B9695C-965B-4BE0-BC33-21274E809576",
|
||||||
UpgradeCode="$(var.ProductUpgradeCode)",
|
|
||||||
Language="1033",
|
Language="1033",
|
||||||
Codepage="1252",
|
|
||||||
Version="$(var.ProductVersion)",
|
|
||||||
)
|
|
||||||
ET.SubElement(
|
|
||||||
product_el,
|
|
||||||
"Package",
|
|
||||||
Id="*",
|
|
||||||
Keywords="Installer",
|
|
||||||
Description="Dangerzone $(var.ProductVersion) Installer",
|
|
||||||
Manufacturer="Freedom of the Press Foundation",
|
|
||||||
InstallerVersion="100",
|
|
||||||
Languages="1033",
|
|
||||||
Compressed="yes",
|
Compressed="yes",
|
||||||
SummaryCodepage="1252",
|
Codepage="1252",
|
||||||
|
Version=version,
|
||||||
)
|
)
|
||||||
ET.SubElement(product_el, "Media", Id="1", Cabinet="product.cab", EmbedCab="yes")
|
|
||||||
ET.SubElement(
|
ET.SubElement(
|
||||||
product_el, "Icon", Id="ProductIcon", SourceFile="..\\share\\dangerzone.ico"
|
package_el,
|
||||||
|
"SummaryInformation",
|
||||||
|
Keywords="Installer",
|
||||||
|
Description="Dangerzone " + version + " Installer",
|
||||||
|
Codepage="1252",
|
||||||
)
|
)
|
||||||
ET.SubElement(product_el, "Property", Id="ARPPRODUCTICON", Value="ProductIcon")
|
ET.SubElement(package_el, "MediaTemplate", EmbedCab="yes")
|
||||||
ET.SubElement(
|
ET.SubElement(
|
||||||
product_el,
|
package_el, "Icon", Id="ProductIcon", SourceFile="..\\share\\dangerzone.ico"
|
||||||
|
)
|
||||||
|
ET.SubElement(package_el, "Property", Id="ARPPRODUCTICON", Value="ProductIcon")
|
||||||
|
ET.SubElement(
|
||||||
|
package_el,
|
||||||
"Property",
|
"Property",
|
||||||
Id="ARPHELPLINK",
|
Id="ARPHELPLINK",
|
||||||
Value="https://dangerzone.rocks",
|
Value="https://dangerzone.rocks",
|
||||||
)
|
)
|
||||||
ET.SubElement(
|
ET.SubElement(
|
||||||
product_el,
|
package_el,
|
||||||
"Property",
|
"Property",
|
||||||
Id="ARPURLINFOABOUT",
|
Id="ARPURLINFOABOUT",
|
||||||
Value="https://freedom.press",
|
Value="https://freedom.press",
|
||||||
)
|
)
|
||||||
ET.SubElement(
|
ET.SubElement(
|
||||||
product_el,
|
package_el, "ui:WixUI", Id="WixUI_InstallDir", InstallDirectory="INSTALLFOLDER"
|
||||||
"Property",
|
|
||||||
Id="WIXUI_INSTALLDIR",
|
|
||||||
Value="INSTALLDIR",
|
|
||||||
)
|
)
|
||||||
ET.SubElement(product_el, "UIRef", Id="WixUI_InstallDir")
|
ET.SubElement(package_el, "UIRef", Id="WixUI_ErrorProgressText")
|
||||||
ET.SubElement(product_el, "UIRef", Id="WixUI_ErrorProgressText")
|
|
||||||
ET.SubElement(
|
ET.SubElement(
|
||||||
product_el,
|
package_el,
|
||||||
"WixVariable",
|
"WixVariable",
|
||||||
Id="WixUILicenseRtf",
|
Id="WixUILicenseRtf",
|
||||||
Value="..\\install\\windows\\license.rtf",
|
Value="..\\install\\windows\\license.rtf",
|
||||||
)
|
)
|
||||||
ET.SubElement(
|
ET.SubElement(
|
||||||
product_el,
|
package_el,
|
||||||
"WixVariable",
|
"WixVariable",
|
||||||
Id="WixUIDialogBmp",
|
Id="WixUIDialogBmp",
|
||||||
Value="..\\install\\windows\\dialog.bmp",
|
Value="..\\install\\windows\\dialog.bmp",
|
||||||
)
|
)
|
||||||
ET.SubElement(
|
ET.SubElement(
|
||||||
product_el,
|
package_el,
|
||||||
"MajorUpgrade",
|
"MajorUpgrade",
|
||||||
AllowSameVersionUpgrades="yes",
|
|
||||||
DowngradeErrorMessage="A newer version of [ProductName] is already installed. If you are sure you want to downgrade, remove the existing installation via Programs and Features.",
|
DowngradeErrorMessage="A newer version of [ProductName] is already installed. If you are sure you want to downgrade, remove the existing installation via Programs and Features.",
|
||||||
)
|
)
|
||||||
|
|
||||||
build_dir_xml(product_el, data)
|
# Workaround for an issue after upgrading from WiX Toolset v3 to v5 where the previous
|
||||||
component_ids = build_components_xml(product_el, data)
|
# version of Dangerzone is not uninstalled during the upgrade by checking if the older installation
|
||||||
|
# exists in "C:\Program Files (x86)\Dangerzone".
|
||||||
|
#
|
||||||
|
# Also handle a special case for Dangerzone 0.8.0 which allows choosing the install location
|
||||||
|
# during install by checking if the registry key for it exists.
|
||||||
|
#
|
||||||
|
# Note that this seems to allow installing Dangerzone 0.8.0 after installing Dangerzone from this branch.
|
||||||
|
# In this case the installer errors until Dangerzone 0.8.0 is uninstalled again
|
||||||
|
#
|
||||||
|
# TODO: Revert this once we are reasonably certain there aren't too many affected Dangerzone installations.
|
||||||
|
find_old_el = ET.SubElement(package_el, "Property", Id="OLDDANGERZONEFOUND")
|
||||||
|
directory_search_el = ET.SubElement(
|
||||||
|
find_old_el,
|
||||||
|
"DirectorySearch",
|
||||||
|
Id="dangerzone_install_folder",
|
||||||
|
Path="C:\\Program Files (x86)\\Dangerzone",
|
||||||
|
)
|
||||||
|
ET.SubElement(directory_search_el, "FileSearch", Name="dangerzone.exe")
|
||||||
|
registry_search_el = ET.SubElement(package_el, "Property", Id="DANGERZONE080FOUND")
|
||||||
|
ET.SubElement(
|
||||||
|
registry_search_el,
|
||||||
|
"RegistrySearch",
|
||||||
|
Root="HKLM",
|
||||||
|
Key="SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{03C2D2B2-9955-4AED-831F-DA4E67FC0FDB}",
|
||||||
|
Name="DisplayName",
|
||||||
|
Type="raw",
|
||||||
|
)
|
||||||
|
ET.SubElement(
|
||||||
|
package_el,
|
||||||
|
"Launch",
|
||||||
|
Condition="NOT OLDDANGERZONEFOUND AND NOT DANGERZONE080FOUND",
|
||||||
|
Message="A previous version of [ProductName] is already installed. Please uninstall it from Programs and Features before proceeding with the installation.",
|
||||||
|
)
|
||||||
|
|
||||||
feature_el = ET.SubElement(product_el, "Feature", Id="DefaultFeature", Level="1")
|
# Add the ProgramMenuFolder StandardDirectory
|
||||||
for component_id in component_ids:
|
programmenufolder_el = ET.SubElement(
|
||||||
ET.SubElement(feature_el, "ComponentRef", Id=component_id)
|
package_el,
|
||||||
|
"StandardDirectory",
|
||||||
|
Id="ProgramMenuFolder",
|
||||||
|
)
|
||||||
|
# Add a shortcut for Dangerzone in the Start menu
|
||||||
|
shortcut_el = ET.SubElement(
|
||||||
|
programmenufolder_el,
|
||||||
|
"Component",
|
||||||
|
Id="ApplicationShortcuts",
|
||||||
|
Guid="539E7DE8-A124-4C09-AA55-0DD516AAD7BC",
|
||||||
|
)
|
||||||
|
ET.SubElement(
|
||||||
|
shortcut_el,
|
||||||
|
"Shortcut",
|
||||||
|
Id="DangerzoneStartMenuShortcut",
|
||||||
|
Name="Dangerzone",
|
||||||
|
Description="Dangerzone",
|
||||||
|
Target="[INSTALLFOLDER]dangerzone.exe",
|
||||||
|
WorkingDirectory="INSTALLFOLDER",
|
||||||
|
)
|
||||||
|
ET.SubElement(
|
||||||
|
shortcut_el,
|
||||||
|
"RegistryValue",
|
||||||
|
Root="HKCU",
|
||||||
|
Key="Software\\Freedom of the Press Foundation\\Dangerzone",
|
||||||
|
Name="installed",
|
||||||
|
Type="integer",
|
||||||
|
Value="1",
|
||||||
|
KeyPath="yes",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the ProgramFilesFolder StandardDirectory
|
||||||
|
programfilesfolder_el = ET.SubElement(
|
||||||
|
package_el,
|
||||||
|
"StandardDirectory",
|
||||||
|
Id="ProgramFiles64Folder",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create the directory structure for the installed product
|
||||||
|
build_directory_xml(programfilesfolder_el, data)
|
||||||
|
|
||||||
|
# Create a component group for application components
|
||||||
|
applicationcomponents_el = ET.SubElement(
|
||||||
|
package_el, "ComponentGroup", Id="ApplicationComponents"
|
||||||
|
)
|
||||||
|
# Populate the application components group with components for the installed package
|
||||||
|
build_components_xml(applicationcomponents_el, data)
|
||||||
|
|
||||||
|
# Add the Feature element
|
||||||
|
feature_el = ET.SubElement(package_el, "Feature", Id="DefaultFeature", Level="1")
|
||||||
|
ET.SubElement(feature_el, "ComponentGroupRef", Id="ApplicationComponents")
|
||||||
ET.SubElement(feature_el, "ComponentRef", Id="ApplicationShortcuts")
|
ET.SubElement(feature_el, "ComponentRef", Id="ApplicationShortcuts")
|
||||||
|
|
||||||
print('<?xml version="1.0" encoding="windows-1252"?>')
|
ET.indent(wix_el, space=" ")
|
||||||
print(f'<?define ProductVersion = "{version}"?>')
|
|
||||||
print('<?define ProductUpgradeCode = "12b9695c-965b-4be0-bc33-21274e809576"?>')
|
with open(os.path.join(build_dir, "Dangerzone.wxs"), "w") as wxs_file:
|
||||||
ET.indent(root_el)
|
wxs_file.write(ET.tostring(wix_el).decode())
|
||||||
print(ET.tostring(root_el).decode())
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in a new issue