Skip to content
JDesk
Guides

Signing & distributing

Sign, notarize, verify, and publish native JDesk application packages.

Build an OS-native installer from your packaged app image and understand what signing requires. This guide continues from Package your app: you should already have a working jdeskPackage app image before building an installer.

Build a native installer#

./gradlew jdeskInstaller

jdeskInstaller runs jpackage on the jdeskPackage app image to build the OS's native installer into build/jdesk/installer. It runs on the target OS only — the same cross-packaging rule as jdeskPackage.

The installer type defaults to the OS default; override it with -PjdeskInstallerType:

OSFormatsExample
macOSdmg, pkg./gradlew jdeskInstaller -PjdeskInstallerType=pkg
Windowsmsi, exe./gradlew jdeskInstaller -PjdeskInstallerType=msi
Linuxdeb, rpm./gradlew jdeskInstaller -PjdeskInstallerType=deb

The macOS DMG path is verified end-to-end locally (a real 34 MB DMG); Windows MSI and Linux DEB are built in the CI package jobs. See packaging and signing for the current per-platform status.

Installers are UNSIGNED without an identity#

jdeskInstaller produces a real but UNSIGNED installer unless a signing identity is configured for the current OS. Unsigned packages are fine for development and internal verification, but they are labeled UNSIGNED and do not satisfy a signed-release gate. Signing itself is delegated to the OS toolchains (signtool, codesign + notarytool, dpkg-sig/rpmsign); the plugin only invokes them from the values you set.

Configure the signing hooks#

The signing surface is the jdesk { signing { } } block. Set the identities for the platforms you distribute:

jdesk {
    signing {
        // Windows — Authenticode
        windowsCertificate.set("<certificate subject or thumbprint>")
        windowsTimestampUrl.set("http://timestamp.example/rfc3161")

        // macOS — Developer ID + notarization
        macSigningIdentity.set("Developer ID Application: Acme Inc (TEAMID)")
        macNotarizationProfile.set("<notarytool keychain profile name>")

        // Linux — package signing
        linuxSigningKey.set("<GPG key id>")
    }
}
PropertyToolchainPurpose
windowsCertificatesigntoolAuthenticode identity (certificate subject or thumbprint).
windowsTimestampUrlsigntoolRFC 3161 timestamp URL.
macSigningIdentitycodesignDeveloper ID Application identity.
macNotarizationProfilenotarytoolNotarization keychain profile (--keychain-profile).
linuxSigningKeydpkg-sig / rpmsignGPG package-signing key id.

When at least one identity is set for the current OS, the installer step signs using it; otherwise the artifact is UNSIGNED.

A signed pipeline needs your credentials#

The signing hooks are a configuration surface, not a turnkey signed pipeline. A fully wired, signed-and-notarized end-to-end release is Phase-7 work and is not yet demonstrated. It also requires credentials that only you can supply and that are never checked in:

  • Windows — an Authenticode code-signing certificate.
  • macOS — a Developer ID Application certificate plus an Apple notarization profile; the flow is codesignnotarytool submitstapler.
  • Linux — a GPG key for package/repository signing.

CI packages are UNSIGNED because these credentials are not present in CI. Do not treat any current artifact as signed. See the verification report and packaging and signing for exactly what is proven, and implementation status for the Phase-7 gate list.

Publish the framework and npm packages#

Distributing your app is the installer above. If you are also publishing JDesk itself or its JS packages, the flows are:

# Framework artifacts — local verification, no credentials:
./gradlew publishToMavenLocal

# Real publish (credentials supplied at invocation, never checked in):
./gradlew publish \
  -PjdeskPublishUrl=https://maven.pkg.github.com/tuanworlddev/jdesk \
  -PjdeskPublishUser=<user> -PjdeskPublishToken=<token>

# The two npm packages:
npm --prefix js/create-jdesk-app publish --access public   # the scaffolder
npm --prefix js/jdesk-client publish --access public       # jdesk-client runtime

A signed Maven release adds an in-memory PGP key (-PsigningKey=... -PsigningPassword=...). Publishing to a public repository requires repository credentials and an npm token that only the account owner can supply. See scaffolding and publishing for the full publish → consume chain.

Next steps#

  • Package your app — build the app image these installers wrap.
  • Packaging and signing — the pipeline and SBOM details.
  • Scaffolding and publishing — framework and npm publishing.