diff --git a/.github/workflows/jdeploy.yml b/.github/workflows/jdeploy.yml new file mode 100644 index 0000000..876fb68 --- /dev/null +++ b/.github/workflows/jdeploy.yml @@ -0,0 +1,64 @@ +# Builds the native installers for Windows, macOS and Linux and publishes them as GitHub release assets. +# +# Two channels, distinguished by what was pushed: +# * a `v*` tag -> a versioned release; the tag name minus the leading `v` becomes the app version. +# * a `*-snapshot` branch -> a rolling prerelease named after the branch, replaced on every push. +# +# Auto-update needs nothing else from us. The jDeploy action writes a package-info.json to a `jdeploy` tag in +# this repository, and the native launcher installed on a user's machine reads it on startup to notice a newer +# release. That only works while the repository is public — a private repository needs a separate public +# release-only repository passed as `target_repository`. +name: jdeploy + +on: + push: + tags: + - 'v*' + branches: + - '*-snapshot' + # Lets the pipeline be exercised without cutting a tag. Running it on a branch produces the snapshot + # prerelease for that branch, exactly as a push would. + workflow_dispatch: + +# The action rewrites a shared `jdeploy` tag, so two runs must never overlap. Queued rather than cancelled: +# cancelling mid-upload is what leaves that tag half written. +concurrency: + group: jdeploy-release-${{ github.repository }} + cancel-in-progress: false + +jobs: + bundle: + runs-on: ubuntu-latest + permissions: + # Needed to create the release and to push the `jdeploy` tag that carries package-info.json. + contents: write + + steps: + - uses: actions/checkout@v4 + + # Zulu rather than Temurin: the JavaFX dependencies are pinned to a Zulu FX build locally, and Azul + # publishes non-LTS feature releases, which Java 26 is. + - name: Set up JDK 26 + uses: actions/setup-java@v4 + with: + java-version: '26' + distribution: 'zulu' + cache: maven + + # The -Pjdeploy profile synchronises package.json by shelling out to `npm pkg set`, so Node has to be on + # PATH before Maven runs, not just before the jDeploy action. + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: '22' + + - name: Build + run: ./mvnw -B --no-transfer-progress -Pjdeploy package + + - name: Build app installer bundles + uses: shannah/jdeploy@v6.1.5 + with: + github_token: ${{ github.token }} + # Kept in step with jdeploy.cli.version in pom.xml. The action's own default lags its release tag. + jdeploy_version: '6.1.5' + diff --git a/.gitignore b/.gitignore index b683da0..65a6dfd 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,9 @@ logs/ *.mv.db *.trace.db +### jDeploy +# Generated by the jDeploy CLI: the npm-shaped launcher bundle and the installer/release staging directory. +jdeploy-bundle/ +jdeploy/ +node_modules/ + diff --git a/CLAUDE.md b/CLAUDE.md index eda6a17..6800bf9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -11,6 +11,35 @@ This project is a desktop application for images / pictures management. Like col * For packaging, use spring boot generated jar, and jdeploy to create OS package (jdk/jre included) * Use lombok when applicable (Constructor and getter / setter) +## Packaging & distribution (jDeploy) + +Native installers with a bundled JRE are produced by jDeploy, driven from two files: `package.json` at the +repository root (the descriptor) and `.github/workflows/jdeploy.yml` (the release pipeline). + +* **Entry point.** jDeploy has no main-class setting — it runs the jar. So the entry point is declared once, as + `spring-boot-maven-plugin`'s `${main.class}`, which lands in the repackaged jar's + manifest as `Start-Class`. `jdeploy.jar` in `package.json` points at `target/pholio.jar`; `` is + version-free precisely so that path never needs updating. +* **Runtime.** `jdeploy.javaVersion: "26"` with `jdeploy.javafx: true` provisions an Azul Zulu FX **JRE** per + platform. `windows-arm64` is deliberately absent from `downloadPage.platforms`: Azul publishes no FX build for + it at 26, so listing it would produce an installer that cannot start. +* **Syncing the descriptor.** `mvn -Pjdeploy package` runs `jdeploy-maven-plugin:sync-package-json`, which + copies version, name, description, title, jar path, Java version and the JavaFX flag from the POM into + `package.json`. It works by shelling out to `npm pkg set`, which is why it sits behind a profile — a plain + `mvn package` must not require Node. Every other key in `package.json` is hand-maintained. +* **Releasing.** Push a `v` tag (the leading `v` is stripped to form the app version); the workflow + builds the bundles and attaches them to that release. Pushing a `*-snapshot` branch publishes a rolling + prerelease instead. Branch and tag names must be at most 16 characters of `[A-Za-z0-9._-]` — the jDeploy + action silently skips anything else. +* **Auto-update.** Handled entirely by the native launcher: it reads a `package-info.json` that the action + writes to a `jdeploy` tag in this repository, and picks up a newer release on next start. This requires the + repository to stay public; a private one needs a separate public release repository passed to the action as + `target_repository`. +* **Do not add `documentTypes`, `urlSchemes` or `singleton` without changing the launcher first.** jDeploy + passes opened files and URIs to `main`, and `LaunchOptions` reads any unrecognised argument as a subcommand + and switches to `HEADLESS`. File associations would therefore make a double-clicked photo start Pholio with + no window. + ## Testing * for unit test use AssertJ with SoftAssertion diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..3669a2e Binary files /dev/null and b/icon.png differ diff --git a/package.json b/package.json new file mode 100644 index 0000000..e07f9c3 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "pholio", + "version": "0.1.0-SNAPSHOT", + "description": "High-volume desktop photo and media library manager", + "author": "Christophe Lallement", + "repository": "https://github.com/Imag-In/pholio", + "bin": { + "pholio": "jdeploy-bundle/jdeploy.js" + }, + "files": [ + "jdeploy-bundle" + ], + "preferGlobal": true, + "jdeploy": { + "jar": "target/pholio.jar", + "javaVersion": "26", + "javafx": true, + "jdk": false, + "title": "Pholio", + "args": [ + "-Djdeploy.file.limit=8192" + ], + "downloadPage": { + "platforms": [ + "mac-arm64", + "mac-x64", + "windows-x64", + "linux-x64", + "linux-arm64", + "debian-x64", + "debian-arm64" + ] + } + } +} diff --git a/pom.xml b/pom.xml index 7ecc6a1..9776e67 100644 --- a/pom.xml +++ b/pom.xml @@ -43,6 +43,16 @@ io.pholio.PholioApplication + + + 1.0.8 + + 6.1.5 @@ -162,10 +172,22 @@ + + pholio org.springframework.boot spring-boot-maven-plugin + ${main.class} @@ -188,4 +210,48 @@ + + + + + jdeploy + + + + ca.weblite + jdeploy-maven-plugin + ${jdeploy-maven-plugin.version} + + ${jdeploy.cli.version} + + + + sync-package-json + + package + + sync-package-json + + + + + + + +