Skip to content

Commit

Permalink
WIP: Automate release tasks
Browse files Browse the repository at this point in the history
  • Loading branch information
apyrgio committed Nov 20, 2024
1 parent a54a8f2 commit 8e05000
Show file tree
Hide file tree
Showing 4 changed files with 341 additions and 2 deletions.
293 changes: 293 additions & 0 deletions dodo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
import os
import platform
import shutil
from pathlib import Path

from doit import task_params
from doit.action import CmdAction

if platform.system() in ["Darwin", "Windows"]:
CONTAINER_RUNTIME = "docker"
elif platform.system() == "Linux":
CONTAINER_RUNTIME = "podman"

VERSION = open("share/version.txt").read().strip()
RELEASE_DIR = Path.home() / "release" / VERSION
FEDORA_VERSIONS = ["39", "40", "41"]
DEBIAN_VERSIONS = ["bullseye", "focal", "jammy", "mantic", "noble", "trixie"]


def list_files(path):
filepaths = []
for root, _, files in os.walk(path):
for f in files:
if f.endswith(".pyc"):
continue
filepaths.append(Path(root) / f)
return filepaths


def copy_dz_dir(src, dst):
shutil.rmtree(dst)
dst.mkdir(exist_ok=True)
shutil.copytree(src, dst)


def cmd_build_linux_pkg(distro, version, cwd, qubes=False):
pkg = "rpm" if distro == "fedora" else "deb"
cmd = [
"python3",
"./dev_scripts/env.py",
"--distro",
distro,
"--version",
version,
"run",
"--dev"
f"./dangerzone/install/linux/build-{pkg}.py"
]
if qubes:
cmd += ["--qubes"]
return CmdAction(cmd, cwd=cwd)


def task_check_python():
def check_python():
# FIXME: Check that Python 3.12 is installed.
return True

return {
"actions": [check_python],
}


def task_container_runtime():
return {
"actions": [
["which", CONTAINER_RUNTIME],
[CONTAINER_RUNTIME, "ps"],
],
}


def task_system_checks():
return {
"actions": None,
"task_dep": [
"check_python",
"container_runtime",
],
}


def task_download_tessdata():
return {
"actions": [["python", "install/common/download-tessdata.py"]],
"file_dep": [
"install/common/download-tessdata.py",
"share/ocr-languages.json",
],
"targets": ["share/tessdata"]
}


def task_build_container():
return {
"actions": ["python install/common/build-image.py --use-cache=%(use_cache)s"],
"params": [
{
"name": "use_cache",
"long": "use-cache",
"default": False,
}
],
"file_dep": [
"Dockerfile",
"poetry.lock",
*list_files("dangerzone/conversion"),
"dangerzone/gvisor_wrapper/entrypoint.py",
],
"targets": ["share/container.tar.gz", "share/image-id.txt"],
"task_dep": ["container_runtime"],
}


def task_poetry_install():
return {
"actions": ["poetry install --sync"],
}


def task_app():
return {
"actions": [["poetry", "run", "install/macos/build-app.py"]],
"file_dep": [
*list_files("share"),
*list_files("dangerzone"),
],
"task_dep": ["poetry_install"],
"targets": ["dist/Dangerzone.app"]
}


def task_codesign():
return {
"actions": [
["poetry", "run", "install/macos/build-app.py"],
[
"xcrun",
"notarytool",
"submit",
"--wait",
"--apple-id",
"<email>",
"--keychain-profile",
"dz-notarytool-release-key",
"dist/Dangerzone.dmg",
],
],
"file_dep": ["dist/Dangerzone.app"],
"targets": ["dist/Dangerzone.dmg"]
}


def task_init_release_dir():
def create_release_dir():
RELEASE_DIR.mkdir(parents=True, exist_ok=True)
(RELEASE_DIR / "github").mkdir(exist_ok=True)
(RELEASE_DIR / "tmp").mkdir(exist_ok=True)

return {
"actions": [create_release_dir],
"targets": [RELEASE_DIR, RELEASE_DIR / "github", RELEASE_DIR / "tmp"],
}


def task_debian_env():
return {
"actions": [
[
"python3",
"./dev_scripts/env.py",
"--distro",
"debian",
"--version",
"bookworm",
"build-dev",
]
],
}


def task_debian_deb():
dz_dir = RELEASE_DIR / "tmp" / "debian"
deb_name = f"dangerzone_{VERSION}-1_amd64.deb"
deb_src = dz_dir / "deb_dist" / deb_name
deb_dst = RELEASE_DIR / deb_name

return {
"actions": [
(copy_dz_dir, [".", dz_dir]),
cmd_build_linux_pkg("debian", "bookworm", cwd=dz_dir),
["cp", deb_src, deb_dst],
["rm", "-r", dz_dir],
],
"file_dep": [
RELEASE_DIR,
"share/container.tar.gz",
"share/image-id.txt",
],
"task_dep": [
"debian_env",
],
"targets": [deb_dst]
}



def task_fedora_env():
for version in FEDORA_VERSIONS:
yield {
"name": version,
"actions": [
[
"python3",
"./dev_scripts/env.py",
"--distro",
"fedora",
"--version",
version,
"build-dev",
],
],
}

def task_fedora_rpm():
for version in FEDORA_VERSIONS:
dz_dir = RELEASE_DIR / "tmp" / f"f{version}"
rpm_names = [
f"dangerzone-{VERSION}-1.fc{version}.x86_64.rpm",
f"dangerzone-{VERSION}-1.fc{version}.src.rpm",
f"dangerzone-qubes-{VERSION}-1.fc{version}.x86_64.rpm",
f"dangerzone-qubes-{VERSION}-1.fc{version}.src.rpm",
]
rpm_src = [dz_dir / "dist" / rpm_name for rpm_name in rpm_names]
rpm_dst = [RELEASE_DIR / rpm_name for rpm_name in rpm_names]

yield {
"name": version,
"actions": [
(copy_dz_dir, [".", dz_dir]),
cmd_build_linux_pkg("fedora", version, cwd=dz_dir),
cmd_build_linux_pkg("fedora", version, cwd=dz_dir, qubes=True),
["cp", *rpm_src, RELEASE_DIR],
["rm", "-r", dz_dir],
],
"file_dep": [
RELEASE_DIR,
"share/container.tar.gz",
"share/image-id.txt",
],
"task_dep": [
f"fedora_env:{version}",
],
"targets": rpm_dst
}


@task_params([{
"name": "apt_tools_prod_dir",
"default": "~/release/apt-tools-prod"
}])
def task_apt_tools_prod_prep(apt_tools_prod_dir):
apt_dir = Path(apt_tools_prod_dir).expanduser()
dz_dir = apt_dir / "dangerzone"

src = task_debian_deb()["targets"][0]
deb_name = src.name
bookworm_deb = dz_dir / "bookworm" / deb_name
other_debs = [dz_dir / version / deb_name for version in DEBIAN_VERSIONS]

def copy_files():
# Delete previous Dangerzone files.
old_files = dz_dir.rglob("dangerzone_*j")
for f in old_files:
f.unlink()

# Delete DB entries.
shutil.rmtree(apt_dir / "db")
shutil.rmtree(apt_dir / "public" / "dists")
shutil.rmtree(apt_dir / "public" / "pool")

# Copy .deb to bookworm folder.
shutil.copy2(src, bookworm_deb)

# Create the necessary symlinks
for deb in other_debs:
deb.symlink_to(f"../bookworm/{deb_name}")

return {
"actions": [copy_files],
"file_dep": [src],
"targets": [bookworm_deb, *other_debs]
}
15 changes: 14 additions & 1 deletion install/common/build-image.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@

ARCH = platform.machine()

def str2bool(v):
if isinstance(v, bool):
return v
if v.lower() in ('yes', 'true', 't', 'y', '1'):
return True
elif v.lower() in ('no', 'false', 'f', 'n', '0'):
return False
else:
raise argparse.ArgumentTypeError('Boolean value expected.')


def main():
parser = argparse.ArgumentParser()
Expand All @@ -39,7 +49,10 @@ def main():
)
parser.add_argument(
"--use-cache",
action="store_true",
type=str2bool,
nargs='?',
default=False,
const=True,
help="Use the builder's cache to speed up the builds (not suitable for release builds)",
)
args = parser.parse_args()
Expand Down
31 changes: 30 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pyxdg = {version = "*", platform = "linux"}
requests = "*"
markdown = "*"
packaging = "*"
doit = "^0.36.0"

[tool.poetry.scripts]
dangerzone = 'dangerzone:main'
Expand Down Expand Up @@ -62,6 +63,9 @@ skip_gitignore = true
# This is necessary due to https://github.com/PyCQA/isort/issues/1835
follow_links = false

[tool.doit.tasks.build_container]
use_cache = true

[build-system]
requires = ["poetry-core>=1.2.0"]
build-backend = "poetry.core.masonry.api"

0 comments on commit 8e05000

Please sign in to comment.