This document captures the decisions, conventions, and workflow setup used to build multi‑arch packages for the Crypta Daemon (cryptad).
It now covers both Snap (amd64, arm64) and Flatpak (x86_64, aarch64).
- Produce amd64 and arm64 snaps from upstream https://github.com/crypta-network/cryptad.
- Produce x86_64 and aarch64 Flatpak bundles from the same upstream artifacts.
- Build on native GitHub runners (no LXD) using per‑platform packaging.
- Keep size lean by trimming non‑target assets during package prime/install stages.
- Upload each arch artifact separately for validation.
.github/workflows/build-cryptad-snap.yml— GitHub Actions pipeline (Snap)..github/workflows/build-cryptad-flatpak.yml— GitHub Actions pipeline (Flatpak)..github/workflows/build-cryptad-jar.yml— GitHub Actions pipeline (plain JAR)..github/scripts/upsert_sha256_section.py— helper used by the release manager to merge checksum sections..github/actions/prepare-cryptad/— composite for upstream checkout + version resolve + Gradle dist..github/actions/repack-payload/— composite to extract upstream tarball and re‑tar into targetlocal/dir..github/actions/render-desktop/— composite to render shared desktop template (Exec/Icon substitutions)..github/actions/render-manifest/— composite to render templates with KEY=VALUE substitutions.snap/snapcraft.yaml.template— Snapcraft template rendered with the resolved version.snap/snapshots.yaml— Snap snapshots exclusions included in the snap atmeta/snapshots.yaml.flatpak/cryptad.yaml.template— Flatpak manifest template rendered with the resolved version.flatpak/network.crypta.cryptad.metainfo.xml.template— AppStream metadata template (rendered and included in Flatpak).desktop/cryptad.desktop.template— shared desktop entry template used by both Snap and Flatpak workflows.desktop/icons/cryptad.pnganddesktop/icons/cryptad-512.png— shared app icons (Snap uses the PNG; Flatpak installs 512×512 to hicolor)..gitignore— ignores generated artifacts, build dirs, and rendered files for both packaging flows.
Path: snap/snapcraft.yaml.template
Key points:
base: core24version: "v__VERSION__"(snap names include a leadingv, e.g.v1.2.3).grade: stable,confinement: strict.license: GPL-3.0.platforms(native‑only build plans):amd64: build-on [amd64], build-for [amd64]arm64: build-on [arm64], build-for [arm64]
parts.cryptad:plugin: dumpsource: snap/local/cryptad-jlink-v__VERSION__.tar.gz(workflow creates this)stage-packagesincludes a minimal desktop/X stack plus fonts for Swing UIs and ascriptprovider. Current set:bsdutils(binds/usr/bin/scriptvialayout:)libx11-6,libxext6,libxrender1,libxtst6,libxi6,libxcb1,libxau6,libxdmcp6libfontconfig1,libfreetype6,fonts-dejavu-core
prime:trims docs/manpages/locales to keep size lean.
override-prime:- Runs
craftctl default. - Ensures
bin/cryptad,bin/cryptad-launcher, nativewrapper*are0755. - Ensures any bundled JRE entrypoint (
*/bin/java) and*/lib/jspawnhelperare0755. - Removes macOS binaries.
- Do not copy the
.desktopor icon manually. We shipsnap/gui/cryptad.desktopandsnap/gui/cryptad.png, which Snapcraft includes undermeta/gui/automatically. - Trims the opposite Linux wrapper using
CRAFT_TARGET_ARCH:- On amd64, remove
wrapper-linux-arm-64and its.so. - On arm64, remove
wrapper-linux-x86-64and its.so.
- On amd64, remove
- Runs
- Additional part
snapshot-exclusions(plugin: nil) installsmeta/snapshots.yamlfromsnap/snapshots.yamlto exclude sensitive/cache data from Snap snapshots. layout:binds/usr/bin/scriptinside the snap to the packaged binary for compatibility.apps.cryptad:command: bin/cryptadenvironment:setsCRYPTAD_ALLOW_ROOT=1, extendsPATH, and configuresJAVA_TOOL_OPTIONS(tmp dirs, user.home to$SNAP_USER_COMMON).plugs:includeshome,removable-media,network,network-bind.
apps.cryptad-launcher(GUI entry):command: bin/cryptad-launcher,extensions: [ gnome ](nodesktop:key; using a.desktopinsnap/gui/avoids duplication).environment:same ascryptad.plugs:adds GUI integration (wayland,x11,desktop,desktop-legacy) plushome,network,network-bind, and optionalremovable-media.
Path: .github/workflows/build-cryptad-snap.yml
High‑level flow:
workflow_dispatchinputs:version(optional): when set, checkoutrelease/<version>from upstream.branch(defaultmain): branch/tag for upstream whenversionis empty.
- Matrix builds on native runners:
amd64onubuntu-latestarm64onubuntu-24.04-arm
- Refactor note (2025‑09‑01): this workflow now calls composite actions to deduplicate the upstream build, repack, and template rendering.
- Steps per job:
- Checkout this repository
- Decide upstream ref (
release/<version>orbranch) - Checkout upstream
crypta-network/cryptadto./upstream - Java setup (Temurin 25) for Gradle
- Resolve version (in order):
- Use
inputs.versionif provided - If Gradle task
printVersionexists: use its output - Else
./gradlew -q properties→version:value (if notunspecified) - Else
git describe --tags(strip leadingv)
- Use
- Build dist:
./gradlew -S -x test build; expectbuild/distributions/cryptad-jlink-v<version>.tar.gz- If not present, auto‑discover
cryptad-*.tar.gz - Write absolute tarball path to
.tarball-path
- If not present, auto‑discover
- Prepare payload:
- Extract tarball to a work dir; no pruning here (trimming happens in Snapcraft
override-prime). - Repack as
snap/local/cryptad-jlink-v<version>.tar.gz.
- Extract tarball to a work dir; no pruning here (trimming happens in Snapcraft
- Prepare desktop assets:
- Copy shared icon
desktop/icons/cryptad.pngtosnap/gui/cryptad.png. - Render
snap/gui/cryptad.desktopfrom the shared template withExec=cryptad.cryptad-launcher.
- Copy shared icon
- Generate
snap/snapcraft.yamlfrom template (substitute__VERSION__). - Install Snapcraft (
samuelmeuli/action-snapcraft@v3). - Build snap natively (no LXD):
- Set
SNAPCRAFT_BUILD_ENVIRONMENT=host. - Run
sudo -E snapcraft pack --platform ${{ matrix.arch }}.
- Set
- Upload artifact per arch:
cryptad-snap-<version>-amd64orcryptad-snap-<version>-arm64.
Diagnostics:
- Uses GitHub Actions
::debug::and::group::/::endgroup::for concise logs. - Prints Java/Gradle versions, tarball size/SHA256, and generated
snapcraft.yamlheader.
Path: flatpak/cryptad.yaml.template
Key points:
id: network.crypta.cryptad,branch: stable.runtime: org.freedesktop.Platform,runtime-version: '24.08',sdk: org.freedesktop.Sdk.command: cryptad-launcher(GUI entry) withfinish-argsfor network, wayland/x11, IPC, DRI, andenv: CRYPTAD_ALLOW_ROOT=1.- Single
modulesentry unpackscryptad-jlink-v__VERSION__.tar.gzto/appwith--strip-components=1to ensure/app/bin/cryptadexists. - Post‑install fixes mirror Snap trim logic:
chmod 0755forbin/cryptad,bin/cryptad-launcher, any*/bin/java, and*/lib/jspawnhelper.- Remove macOS binaries and non‑target wrappers based on
FLATPAK_ARCH.
- Installs desktop entry
cryptad.desktopand 512×512 icon to hicolor, plus AppStream metadata.
Path: .github/workflows/build-cryptad-flatpak.yml
High‑level flow:
workflow_dispatchinputs mirror Snap (versionorbranch).- Matrix on native runners:
x86_64onubuntu-latestaarch64onubuntu-24.04-arm
- Refactor note (2025‑09‑01): this workflow now calls composite actions for upstream prep, repack, and template rendering.
./.github/actions/prepare-cryptad- Inputs:
version,branch,upstream_repository?,upstream_path?. - Outputs:
version,tarball_path(absolute). Builds upstream with Gradle and locates the dist tarball.
- Inputs:
./.github/actions/repack-payload- Inputs:
tarball_path,version,output_dir. - Outputs:
output_tarball. Re‑tars upstream payload tosnap/local/orflatpak/local/.
- Inputs:
./.github/actions/render-desktop- Inputs:
template_path,exec_name,icon_name,output_path. - Purpose: Renders
.desktopfrom shared template for Snap/Flatpak.
- Inputs:
./.github/actions/render-manifest- Inputs:
template_path,output_path,substitutions(newline KEY=VALUE),preview_lines?. - Purpose: Generic token substitution for
snapcraft.yaml, Flatpak manifest, and metainfo.
- Inputs:
- Steps per job:
- Checkout this repo and select upstream ref.
- Checkout upstream
crypta-network/cryptadto./upstream. - Java setup (Temurin 25), resolve version (same heuristics as Snap).
- Build upstream dist; write absolute tarball path to
.tarball-path. - Repack payload to
flatpak/local/cryptad-jlink-v<version>.tar.gz. - Render
flatpak/cryptad.yamlandflatpak/network.crypta.cryptad.metainfo.xmlfrom templates.- Assert with
yqthat the rendered manifest branch isstable.
- Assert with
- Render shared desktop file (
Exec=cryptad-launcher,Icon=network.crypta.cryptad). - Install Flatpak tooling; add Flathub remote to the user scope; install freedesktop runtime+SDK 24.08.
- Build with
flatpak-builder --user --arch=<matrix>.
- Export repo to branch
stable, verify the exported ref, and bundle ascryptad-v<version>-<arch>.flatpak. - Upload artifact per arch:
cryptad-flatpak-<version>-amd64or...-arm64.
- Avoid cross‑arch Snapcraft builds with LXD in CI for this project:
- We observed platform mis‑selection of JRE and LXD network/permission issues.
- Building per‑arch on native runners with
pack --platformandSNAPCRAFT_BUILD_ENVIRONMENT=hostis more reliable.
- Keep trimming logic in one place:
- Only Snapcraft
override-primeremoves macOS files and the opposite Linux wrapper. - The workflow no longer performs any file pruning.
- Only Snapcraft
- Deduplicate CI logic via composites:
- Upstream prep, payload repack, and template rendering are shared across Snap/Flatpak workflows.
- Keeps jobs small, declarative, and easier to evolve per‑platform.
- Versioning:
- Snap and Flatpak versions are prefixed with
vto match artifact naming expectations and branch naming in Flatpak bundles.
- Snap and Flatpak versions are prefixed with
- Confinement:
- Snap uses
confinement: strictwith GNOME extension on the GUI app.
- Snap uses
- Desktop integration:
- A shared
.desktoptemplate is rendered differently per platform (ExecandIcondiffer between Snap and Flatpak). - Use a 512×512 icon for Flatpak to satisfy export/validation. Snap reuses the same artwork under
meta/gui/. - For Flatpak, extracting with
--strip-components=1ensures/app/bin/cryptadexists; earlier wrapper hacks are no longer needed.
- A shared
- Triggering builds:
- Use the workflow dispatch UI with either:
version = 1.2.3(checks out upstreamrelease/1.2.3), orbranch = some-branch(whenversionis empty)
- Use the workflow dispatch UI with either:
- Artifacts:
- Snap: two separate artifacts per run (
cryptad-snap-<version>-amd64and...-arm64). - Flatpak: two separate artifacts per run (
cryptad-flatpak-<version>-x86_64and...-aarch64). - JAR: one file named
cryptad.jar(no version in filename) included in the drafted upstream release and checksums.
- Snap: two separate artifacts per run (
- Upstream dist expectations:
- Tarball contains
bin/cryptad,bin/wrapper-*,lib/*,conf/wrapper.conf. - The upstream launcher rejects root unless
CRYPTAD_ALLOW_ROOTis set; the snap sets this env var. - Flatpak sets the same env var via
finish-args.
- Tarball contains
- A manager workflow
.github/workflows/release-cryptad-manager.ymlcalls allbuild-cryptad-*workflows (snap, flatpak, linux-packages, macos, windows, jar) and then drafts a release in the upstream repocrypta-network/cryptad. - All
build-cryptad-*workflows remain manually callable (workflow_dispatch) and are also reusable (workflow_call) so the manager can invoke them. - The manager accepts the same
version/branchinputs and resolves a finalversionfrom the child workflows ifversionis empty. - To publish the draft release in the upstream repository, add a repository secret
UPSTREAM_REPO_TOKENwithreposcope (PAT) that has permission to create releases incrypta-network/cryptad.
- Optionally run as a daemon:
apps.cryptad.daemon: simple- Provide
restart-conditionand appropriate plugs/slots as needed.
- Auto‑publish to Snap Store:
- Add
snapcore/action-publishand store credentials when ready.
- Add
- Enrich version detection if upstream adds explicit Gradle
versionfields. - Auto‑publish Flatpak to Flathub when ready (add release job and credentials).
- Review/trim
stage-packagesonce GUI dependencies are validated across desktops.
- macOS specific: GitHub Actions macOS runners are prone to out‑of‑memory
errors when executing
gradle test. For this reason, unit tests are intentionally disabled in the macOS DMG workflow (see.github/workflows/build-cryptad-macos.yml), whereprepare-cryptadis invoked withrun_tests=falseand Gradle is run with-x test. Rely on Linux/Windows CI for test execution; the macOS job is focused on packaging only. - Don’t use
snapcore/action-buildor LXD cross‑build for this project; it led to wrong JRE arch or network issues. - Don’t trim platform assets in the workflow; prefer Snapcraft
override-primeas the single source of truth. - If Gradle
printVersionis absent, the workflow falls back togradle.properties→version:, thengit describe. - Flatpak specific:
- Ensure Flathub remote is added to the user scope and freedesktop 24.08 runtime+SDK are installed before building.
- Use a 512×512 icon; smaller icons fail certain
build-exportvalidations. - Use
--strip-components=1when extracting the payload so/app/bin/cryptadexists; otherwise fixups are required.
- Snapcraft docs (core24 platforms): https://documentation.ubuntu.com/snapcraft/stable/reference/project-file/snapcraft-yaml/
- Architectures / build plans: https://documentation.ubuntu.com/snapcraft/stable/explanation/architectures/
- Flatpak docs: https://docs.flatpak.org/en/latest/
- Never create a new branch or open a pull request without explicit user permission.
- Always ask before running any
git pushto any remote or branch. - Never set
git user.nameorgit user.emailyourself. If they are missing, remind the user to configure them.