# Building, Running, and Packaging WireShare

This is the practical contributor and release-builder entrypoint for
WireShare. Hosted ecosystem builders are the primary Linux distribution path.
The local Flatpak remains a manual GitHub Releases fallback.

## Requirements

- JDK 21 with `java`, `javac`, `jlink`, and `jpackage` available from the active `JAVA_HOME`
- The Gradle wrapper included in this repository: `./gradlew`
- macOS packaging: macOS host with the JDK 21 `jpackage` tool
- Windows packaging: Windows x64 host with the JDK 21 `jpackage` tool
- Linux Flatpak fallback packaging: Linux x86_64 host with `flatpak` and `flatpak-builder`
- Linux rollout orchestration: Elixir 1.19+; Python is only needed for Launchpad-backed Snap/PPA automation

Local release packaging is allowed to produce unsigned artifacts. If signing
credentials are missing, Gradle logs a warning and continues where the platform
task supports unsigned output.

## Build

Build only the Compose desktop app:

```bash
./gradlew :desktop-compose-app:build
```

Build the full project and show all Gradle warnings:

```bash
./gradlew build --console=plain --warning-mode all
```

Build the canonical runnable jar:

```bash
./gradlew wireShareJar
```

The jar is written to:

```text
WireShare.jar
```

Build the canonical hosted-builder Linux release inputs:

```bash
./gradlew packageLinuxReleaseInputs
```

`packageSourceTarball` archives the current `HEAD` commit, so run the
release-input tasks from the committed release state you actually intend to
publish.

Generated release-input outputs:

```text
build/release-artifacts/WireShare-<version>-source.tar.gz
build/release-artifacts/SHA256SUMS
build/release-artifacts/DEPENDENCY_INVENTORY.txt
WireShare.jar
```

The Linux packaging source of truth lives under `packaging/`, with the
single-edit manifest in `packaging/release_manifest.yaml` and target metadata in
`packaging/targets.yaml`.

## Run

Run the Compose desktop app through Gradle during development:

```bash
./gradlew :desktop-compose-app:run
```

Run the canonical jar after `wireShareJar` has been built:

```bash
java -jar WireShare.jar
```

On Apple Silicon, prefer the Gradle `run` task for development because the
build wires in the runtime payload and JVM options used by the Compose desktop
path.

## Package Desktop Releases

Build the host-specific desktop package:

```bash
./gradlew packageDesktopRelease
```

`packageDesktopRelease` dispatches by host:

- macOS builds a DMG
- Windows x64 builds an MSI
- Linux x86_64 builds the fallback Flatpak bundle

Package outputs:

```text
build/macos/dmg/WireShare-*.dmg
build/windows/msi/WireShare-*.msi
build/distributions/WireShare-<version>-linux-x64.flatpak
```

Direct platform tasks are also available:

```bash
./gradlew packageMacAppImage
./gradlew packageMacDmg
./gradlew packageWindowsMsi
./gradlew signWindowsMsi
./gradlew packageLinuxFlatpak
```

Use `signWindowsMsi` only when Windows signing credentials are configured.
macOS signing and notarization are covered in more detail in
[MACOS_SIGNING.md](MACOS_SIGNING.md).

## Linux Distribution Paths

Hosted Linux distribution is centered on the checked-in recipes under
`packaging/` and the orchestrator entrypoint:

```bash
scripts/release_linux_rollout.sh prepare
scripts/release_linux_rollout.sh validate
scripts/release_linux_rollout.sh doctor
scripts/release_linux_rollout.sh auth status
scripts/release_linux_rollout.sh config status
scripts/release_linux_rollout.sh install-tools --headless-only
scripts/release_linux_rollout.sh render
scripts/release_linux_rollout.sh submit --dry-run
scripts/release_linux_rollout.sh submit --headless-only --dry-run
scripts/release_linux_rollout.sh status
```

The target map is split by workflow:

- `human_gate`: Flathub review packet generation with explicit human sign-off before outward submission
- `launchpad_api`: Launchpad-backed Snap and PPA targets managed through `launchpadlib`
- `git_submit`: forge-backed headless submission flows such as AUR, Homebrew, HaikuPorts, nixpkgs, Void, Solus, Gentoo, and Alpine
- `service_cli`: hosted-builder CLIs such as OBS and Copr
- `mail_submit`: official email-based flows such as Guix patch threads and OpenBSD ports mail
- `bugzilla_api`: project-hosted Bugzilla REST submission flows such as Mageia package requests and FreeBSD ports tickets
- `conditional_git_submit`: targets such as pkgsrc-wip that are fully headless only when maintainer-specific downstream access is configured
- `manual_handoff`: source-first distro and ports ecosystems that need a generated packet but not direct automation

Publish the canonical release inputs to GitHub Releases first, then let each
hosted builder or ecosystem recipe consume the source tarball, `WireShare.jar`,
`SHA256SUMS`, and `DEPENDENCY_INVENTORY.txt` according to that recipe's policy.

The rollout tool stays headless by default. Pass `--open` only when you want it
to open downstream browser pages for guided or manual submission targets. Use
`doctor` before `submit` when you want a CLI/auth/config readiness check for the
currently enabled targets, and use `auth status` when you want the same
readiness view focused specifically on credentials. `auth login --target snap`
and `auth login --target ppa` bootstrap the Launchpad OAuth cache and now store
`accounts.launchpad_owner` in `~/.local/share/linux_rollout/config.yaml` when
that local override is blank. `auth login --target obs` does the same for
`accounts.obs_owner` and a derived `accounts.obs_project`. Use
`config set`, `config unset`, and `config status` when you want to manage those
non-secret local overrides directly. `install-tools` installs the supported
local helper CLIs and target-specific managed runtimes. The Launchpad
`launchpadlib` Python environment is only installed for Snap/PPA targets, and
the rollout wrapper adds `~/.local/bin` to `PATH` automatically.
When local overrides are blank, the workspace also auto-discovers `pkgsrc_wip_user`
from `ssh -G wip.pkgsrc.org` and derives OBS owner/project from `~/.oscrc` when
that file already exists.

`submit --headless-only` now includes `full`, `conditional`, and `gated`
targets. In practice, that means Flathub participates in headless-first runs as
a terminal-driven review packet plus explicit human sign-off step, while
conditional targets still render a manual fallback packet when the required
downstream access is absent rather than failing silently.

Mail-backed targets stay terminal-first as well. Guix patch replies now fall
back to the managed `sendmail` path when `git send-email` is unavailable, and
OpenBSD submissions continue to use rendered `.eml` payloads plus the local
mail transport.

For Flathub specifically, the tool can generate the review packet and a
human-ready submission payload, but the final PR still has to be human-run.
After review, acknowledge that boundary explicitly with:

```bash
scripts/release_linux_rollout.sh resume --target flathub --acknowledge
```

That acknowledgement step writes `APPROVED_NEXT_STEPS.md` and `PR_BODY.md`
into the Flathub bundle. The orchestrator also prints a ready-to-run
`gh pr create` command targeting `flathub/flathub` on the `new-pr` base branch,
with the resolved fork owner filled in. It does not run that final PR command
for you.

## Linux Flatpak Fallback

Install the Flatpak tools and Freedesktop runtime/SDK:

```bash
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
flatpak install flathub org.freedesktop.Platform//25.08 org.freedesktop.Sdk//25.08
```

Build the fallback Flatpak bundle:

```bash
./gradlew packageLinuxFlatpak
```

Install and run the local bundle:

```bash
flatpak install --user build/distributions/WireShare-<version>-linux-x64.flatpak
flatpak run cx.hermes.WireShare
```

The fallback Flatpak bundles a Java 21 runtime image generated with `jlink`
from the active `JAVA_HOME`. It is for manual GitHub Releases fallback use, not
the primary Linux distribution path.

## Signing Notes

Signing is optional for local packaging.

- macOS signing/notarization properties and release flow are documented in [MACOS_SIGNING.md](MACOS_SIGNING.md)
- Windows signing can use either a certificate file or certificate thumbprint plus `signtool`; see [RELEASE_PACKAGING.md](RELEASE_PACKAGING.md) for the property names
- Unsigned macOS artifacts may require the usual local Gatekeeper override when opened outside a notarized release flow

## Troubleshooting

- If `java -jar WireShare.jar` runs old code, rebuild with `./gradlew wireShareJar`
- If packaging cannot find `jpackage` or `jlink`, verify `JAVA_HOME` points at a full JDK 21, not a JRE
- If `packageDesktopRelease` fails with an unsupported host error, use a supported release host: macOS, Windows x64, or Linux x86_64 for the Flatpak fallback
- If `packageLinuxFlatpak` cannot resolve the runtime, install `org.freedesktop.Platform//25.08` and `org.freedesktop.Sdk//25.08` from Flathub
- If `scripts/release_linux_rollout.sh prepare` fails without `--skip-gradle`, confirm the Gradle release-input tasks succeed first
- If an unsigned package is produced, that is expected unless signing credentials are configured
