From 352cab55deabce35fb57130350c7bb00d43da37f Mon Sep 17 00:00:00 2001 From: "Josef (kwart) Cacek" Date: Tue, 22 Sep 2026 17:24:18 +0200 Subject: [PATCH 1/4] Align local Flatpak manifests with the Flathub one - add pcsc-lite and opensc modules, --socket=pcsc, --device=all and --share=ipc, so the bundled Flatpak supports smartcards and YubiKeys - add explicit `command: jsignpdf`, cleanup rules and the openjdk license - drop --socket=pulseaudio - install the 512x512 icon into hicolor/512x512 instead of 256x256 - pin -Dlibdir=lib for pcsc-lite; meson otherwise installs to lib64 and opensc configure fails with "winscard.h is required for pcsc" - replace the stale JSignPdf 2.3.0 SourceForge placeholder URL with a staged `path: jsignpdf-full.zip`; the release workflow and build-local.sh now copy the zip into place instead of rewriting url and sha256 with sed, which would have clobbered the new module hashes - build-local.sh --release looked for jsignpdf-.zip, which the build never produces; use jsignpdf--full.zip --- .github/workflows/package-release.yml | 18 +----- distribution/linux/flatpak/build-local.sh | 12 ++-- ....github.intoolswetrust.JSignPdf.Devel.yaml | 52 ++++++++++++++++- .../io.github.intoolswetrust.JSignPdf.yaml | 56 +++++++++++++++++-- 4 files changed, 109 insertions(+), 29 deletions(-) diff --git a/.github/workflows/package-release.yml b/.github/workflows/package-release.yml index bdd7f471..6446d827 100644 --- a/.github/workflows/package-release.yml +++ b/.github/workflows/package-release.yml @@ -440,23 +440,11 @@ jobs: org.freedesktop.Sdk//25.08 \ org.freedesktop.Sdk.Extension.openjdk21//25.08 - - name: Patch manifest to use local zip + - name: Stage the release zip next to the manifest run: | set -euo pipefail - MANIFEST=distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml - ZIP_NAME=jsignpdf-${VERSION}-full.zip - SHA256=$(sha256sum "flatpak-input/${ZIP_NAME}" | awk '{print $1}') - cp "flatpak-input/${ZIP_NAME}" distribution/linux/flatpak/ - sed -i \ - "s|^ url:.*\.zip| path: ${ZIP_NAME}|" \ - "${MANIFEST}" - grep -q "path: ${ZIP_NAME}" "${MANIFEST}" \ - || { echo "::error::URL sed patch did not match — check manifest indentation"; exit 1; } - sed -i \ - "s|sha256: [a-f0-9]\{64\}|sha256: ${SHA256}|" \ - "${MANIFEST}" - grep -q "sha256: ${SHA256}" "${MANIFEST}" \ - || { echo "::error::sha256 sed patch did not match"; exit 1; } + cp "flatpak-input/jsignpdf-${VERSION}-full.zip" \ + distribution/linux/flatpak/jsignpdf-full.zip - name: Build Flatpak bundle run: | diff --git a/distribution/linux/flatpak/build-local.sh b/distribution/linux/flatpak/build-local.sh index 465b4224..59aa3aac 100755 --- a/distribution/linux/flatpak/build-local.sh +++ b/distribution/linux/flatpak/build-local.sh @@ -34,7 +34,7 @@ Usage: $(basename "$0") [--release|--devel] [--skip-maven] [--keep-build] [-h] offline maven-dependencies.json. Slower (Maven runs inside the SDK) but exercises the offline manifest end-to-end. - --skip-maven Reuse an existing distribution/target/jsignpdf-.zip + --skip-maven Reuse an existing distribution/target/jsignpdf--full.zip (release mode only). The script falls back to running mvn if no matching zip is found. @@ -108,7 +108,7 @@ METAINFO_ABS="$REPO_ROOT/distribution/linux/io.github.intoolswetrust.JSignPdf.me case "$MODE" in release) APP_ID="io.github.intoolswetrust.JSignPdf" - ZIP_NAME="jsignpdf-${VERSION}.zip" + ZIP_NAME="jsignpdf-${VERSION}-full.zip" ZIP_PATH="$REPO_ROOT/distribution/target/$ZIP_NAME" if (( SKIP_MVN == 0 )) || [[ ! -f "$ZIP_PATH" ]]; then @@ -119,20 +119,16 @@ case "$MODE" in fi [[ -f "$ZIP_PATH" ]] || { echo "missing zip: $ZIP_PATH" >&2; exit 1; } - SHA256=$(sha256sum "$ZIP_PATH" | awk '{print $1}') - cp "$ZIP_PATH" "$STAGE_DIR/" + cp "$ZIP_PATH" "$STAGE_DIR/jsignpdf-full.zip" cp "$SCRIPT_DIR/jsignpdf-flatpak.in" "$STAGE_DIR/" cp "$SCRIPT_DIR/jsignpdf.png" "$STAGE_DIR/" STAGED="$STAGE_DIR/${APP_ID}.local.yaml" sed \ - -e "s| url: https://downloads\\.sourceforge\\.net.*\\.zip| path: ${ZIP_NAME}|" \ - -e "s|sha256: [a-f0-9]\\{64\\}|sha256: ${SHA256}|" \ -e "s|path: \\.\\./jsignpdf\\.desktop|path: ${DESKTOP_ABS}|" \ -e "s|path: \\.\\./io\\.github\\.intoolswetrust\\.JSignPdf\\.metainfo\\.xml|path: ${METAINFO_ABS}|" \ "$RELEASE_MANIFEST" > "$STAGED" - grep -q "path: ${ZIP_NAME}" "$STAGED" || { echo "patch failed (zip path)" >&2; exit 1; } - grep -q "sha256: ${SHA256}" "$STAGED" || { echo "patch failed (sha256)" >&2; exit 1; } + grep -q "path: jsignpdf-full.zip" "$STAGED" || { echo "patch failed (zip path)" >&2; exit 1; } BUNDLE="$BUILD_DIR/JSignPdf-${VERSION}-linux-x86_64.flatpak" ;; diff --git a/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.Devel.yaml b/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.Devel.yaml index 8385d02d..af80980c 100644 --- a/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.Devel.yaml +++ b/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.Devel.yaml @@ -7,17 +7,65 @@ sdk: org.freedesktop.Sdk sdk-extensions: - org.freedesktop.Sdk.Extension.openjdk21 +command: jsignpdf + finish-args: +# Network is required for TSA (timestamps) functionality - --env=PATH=/app/jre/bin:/app/bin:/usr/bin - --share=network + - --share=ipc +# Requires X11 to run - --socket=x11 - - --socket=pulseaudio +# Access to smart cards and YubiKey via pcscd + - --socket=pcsc +# Access to USB devices (for YubiKey) + - --device=all + +cleanup: + - /etc/bash_completion.d + - /include + - /share/doc + - /share/man modules: + - name: pcsc-lite + # pcsc-lite 2.4+ is Meson-only; the autotools build is gone. + buildsystem: meson + cleanup: + - /bin + - /lib/pkgconfig + - /lib/*.a + - /lib/*.la + - /sbin + sources: + - type: archive + url: https://pcsclite.apdu.fr/files/pcsc-lite-2.5.1.tar.xz + sha256: bfcfe38a20afc49849c6bf55325e38f449fc4b26d3923fdc32b969ae41a8741b + config-opts: + # Without an explicit libdir meson picks lib64, and opensc's configure + # then cannot find libpcsclite.pc. + - -Dlibdir=lib + - -Ddefault_library=shared + - -Dlibsystemd=false + - -Dpolkit=false + + - name: opensc + sources: + - type: archive + url: https://github.com/OpenSC/OpenSC/releases/download/0.26.0/opensc-0.26.0.tar.gz + sha256: 837baead45e1505260d868871056150ede6e73d35460a470f2595a9e5e75f82b + config-opts: + - --disable-static + - --enable-pcsc + - --enable-openssl + - --disable-strict + - name: openjdk buildsystem: simple build-commands: - /usr/lib/sdk/openjdk21/install.sh + - mkdir -p ${FLATPAK_DEST}/share/licenses/${FLATPAK_ID}/openjdk + - cp -r /usr/lib/sdk/openjdk21/jvm/openjdk-21/legal/java.base/LICENSE ${FLATPAK_DEST}/share/licenses/${FLATPAK_ID}/openjdk/ - name: jsignpdf buildsystem: simple @@ -51,6 +99,6 @@ modules: - install -Dm755 jsignpdf-flatpak.in ${FLATPAK_DEST}/bin/jsignpdf - sed 's/io\.github\.intoolswetrust\.JSignPdf/io.github.intoolswetrust.JSignPdf.Devel/g' jsignpdf.desktop | install -Dm644 /dev/stdin ${FLATPAK_DEST}/share/applications/io.github.intoolswetrust.JSignPdf.Devel.desktop - sed 's/io\.github\.intoolswetrust\.JSignPdf/io.github.intoolswetrust.JSignPdf.Devel/g' io.github.intoolswetrust.JSignPdf.metainfo.xml | install -Dm644 /dev/stdin ${FLATPAK_DEST}/share/metainfo/io.github.intoolswetrust.JSignPdf.Devel.metainfo.xml - - install -Dm644 jsignpdf.png ${FLATPAK_DEST}/share/icons/hicolor/256x256/apps/io.github.intoolswetrust.JSignPdf.Devel.png + - install -Dm644 jsignpdf.png ${FLATPAK_DEST}/share/icons/hicolor/512x512/apps/io.github.intoolswetrust.JSignPdf.Devel.png - mkdir -p ${FLATPAK_DEST}/share/licenses/io.github.intoolswetrust.JSignPdf.Devel - cp -r distro/jsignpdf-*/licenses/* ${FLATPAK_DEST}/share/licenses/io.github.intoolswetrust.JSignPdf.Devel/ diff --git a/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml b/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml index 042eca89..d3f57df0 100644 --- a/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml +++ b/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml @@ -7,24 +7,72 @@ sdk: org.freedesktop.Sdk sdk-extensions: - org.freedesktop.Sdk.Extension.openjdk21 +command: jsignpdf + finish-args: +# Network is required for TSA (timestamps) functionality - --env=PATH=/app/jre/bin:/app/bin:/usr/bin - --share=network + - --share=ipc +# Requires X11 to run - --socket=x11 - - --socket=pulseaudio +# Access to smart cards and YubiKey via pcscd + - --socket=pcsc +# Access to USB devices (for YubiKey) + - --device=all + +cleanup: + - /etc/bash_completion.d + - /include + - /share/doc + - /share/man modules: + - name: pcsc-lite + # pcsc-lite 2.4+ is Meson-only; the autotools build is gone. + buildsystem: meson + cleanup: + - /bin + - /lib/pkgconfig + - /lib/*.a + - /lib/*.la + - /sbin + sources: + - type: archive + url: https://pcsclite.apdu.fr/files/pcsc-lite-2.5.1.tar.xz + sha256: bfcfe38a20afc49849c6bf55325e38f449fc4b26d3923fdc32b969ae41a8741b + config-opts: + # Without an explicit libdir meson picks lib64, and opensc's configure + # then cannot find libpcsclite.pc. + - -Dlibdir=lib + - -Ddefault_library=shared + - -Dlibsystemd=false + - -Dpolkit=false + + - name: opensc + sources: + - type: archive + url: https://github.com/OpenSC/OpenSC/releases/download/0.26.0/opensc-0.26.0.tar.gz + sha256: 837baead45e1505260d868871056150ede6e73d35460a470f2595a9e5e75f82b + config-opts: + - --disable-static + - --enable-pcsc + - --enable-openssl + - --disable-strict + - name: openjdk buildsystem: simple build-commands: - /usr/lib/sdk/openjdk21/install.sh + - mkdir -p ${FLATPAK_DEST}/share/licenses/${FLATPAK_ID}/openjdk + - cp -r /usr/lib/sdk/openjdk21/jvm/openjdk-21/legal/java.base/LICENSE ${FLATPAK_DEST}/share/licenses/${FLATPAK_ID}/openjdk/ - name: jsignpdf buildsystem: simple sources: + # Staged next to this manifest by build-local.sh / the release workflow. - type: archive - url: https://downloads.sourceforge.net/project/jsignpdf/stable/JSignPdf-2.3.0/jsignpdf-2.3.0.zip - sha256: 8ea04172287296b4db63553751122149ad34ad0474e3a0cdbc6e32fbb77a5833 + path: jsignpdf-full.zip # Shared desktop file from parent directory - type: file path: ../jsignpdf.desktop @@ -45,6 +93,6 @@ modules: - install -Dm755 jsignpdf-flatpak.in ${FLATPAK_DEST}/bin/jsignpdf - install -Dm644 jsignpdf.desktop ${FLATPAK_DEST}/share/applications/io.github.intoolswetrust.JSignPdf.desktop - install -Dm644 io.github.intoolswetrust.JSignPdf.metainfo.xml ${FLATPAK_DEST}/share/metainfo/io.github.intoolswetrust.JSignPdf.metainfo.xml - - install -Dm644 jsignpdf.png ${FLATPAK_DEST}/share/icons/hicolor/256x256/apps/io.github.intoolswetrust.JSignPdf.png + - install -Dm644 jsignpdf.png ${FLATPAK_DEST}/share/icons/hicolor/512x512/apps/io.github.intoolswetrust.JSignPdf.png - mkdir -p ${FLATPAK_DEST}/share/licenses/io.github.intoolswetrust.JSignPdf - cp -r licenses/* ${FLATPAK_DEST}/share/licenses/io.github.intoolswetrust.JSignPdf/ From b7e7dbce3a134c46990da368b365a3dd9c93c92b Mon Sep 17 00:00:00 2001 From: "Josef (kwart) Cacek" Date: Tue, 22 Sep 2026 17:35:44 +0200 Subject: [PATCH 2/4] Open the Flathub update PR from the release workflow - new flathub-pr job, final releases only, runs after publish-release so a failure never blocks the release - takes maven-dependencies.json from the release tag, not master, so the offline Maven repo matches the poms in the pinned tarball - idempotent: re-running force-pushes the branch and reuses the open PR, and exits early once Flathub is already at the version - needs a FLATHUB_TOKEN secret; GITHUB_TOKEN cannot push to another org --- .github/workflows/package-release.yml | 98 ++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/.github/workflows/package-release.yml b/.github/workflows/package-release.yml index 6446d827..6975f0a3 100644 --- a/.github/workflows/package-release.yml +++ b/.github/workflows/package-release.yml @@ -8,7 +8,8 @@ name: Package Release # downloaded full ZIP (no source rebuild — the published bits are # packaged verbatim), # 3. builds the Flatpak bundles, -# 4. mirrors everything to SourceForge and creates the GitHub Release. +# 4. mirrors everything to SourceForge and creates the GitHub Release, +# 5. opens the Flathub update PR (final releases only). # # It is idempotent: re-dispatching it with the same release-version # re-downloads from Central and recreates the GitHub Release. Use this to @@ -646,3 +647,98 @@ jobs: --notes-file "$NOTES_FILE" \ "${prerelease_flag[@]}" \ "${assets[@]}" + + flathub-pr: + # Opens the Flathub update PR for final releases. Flathub builds from the + # source tarball of the release tag, so the offline Maven manifest must be + # the one committed in that same tag — not the one on master, which may + # already have moved on. + # + # Needs FLATHUB_TOKEN: a PAT with `public_repo` on + # flathub/io.github.intoolswetrust.JSignPdf. GITHUB_TOKEN cannot push to + # another org. The job runs after the release is published, so a failure + # here never blocks the release — re-run just this job once the token is + # fixed. + runs-on: ubuntu-24.04 + needs: [setup, publish-release] + if: needs.setup.outputs.is-prerelease == 'false' + env: + VERSION: ${{ inputs.release-version }} + FLATHUB_REPO: flathub/io.github.intoolswetrust.JSignPdf + GH_TOKEN: ${{ secrets.FLATHUB_TOKEN }} + steps: + - name: Check the Flathub token is present + run: | + set -euo pipefail + if [ -z "${GH_TOKEN}" ]; then + echo "::error::FLATHUB_TOKEN is not set — cannot open the Flathub PR." + exit 1 + fi + + - name: Compute release tag + id: tag + run: echo "tag=JSignPdf_${VERSION//./_}" >> "$GITHUB_OUTPUT" + + - name: Checkout release tag + uses: actions/checkout@v7 + with: + ref: ${{ steps.tag.outputs.tag }} + path: upstream + + - name: Checkout the Flathub repo + run: | + set -euo pipefail + git clone "https://github.com/${FLATHUB_REPO}.git" flathub + # Keeps the token out of .git/config; gh reads it from GH_TOKEN. + git -C flathub config credential.helper '!gh auth git-credential' + + - name: Update the manifest and the offline Maven manifest + run: | + set -euo pipefail + TAG="${{ steps.tag.outputs.tag }}" + TARBALL="https://github.com/${{ github.repository }}/archive/refs/tags/${TAG}.tar.gz" + curl -fsSL "$TARBALL" -o source.tar.gz + SHA256=$(sha256sum source.tar.gz | awk '{print $1}') + cp upstream/distribution/linux/flatpak/maven-dependencies.json flathub/ + python3 - "$TAG" "$SHA256" <<'PY' + import re, sys + tag, sha = sys.argv[1], sys.argv[2] + path = "flathub/io.github.intoolswetrust.JSignPdf.yaml" + s = open(path).read() + pattern = re.compile( + r"(url: https://github\.com/[^\s]+/archive/refs/tags/)[^\s]+" + r"(\n\s*sha256: )[0-9a-f]{64}") + s, n = pattern.subn(lambda m: m.group(1) + tag + ".tar.gz" + m.group(2) + sha, s) + if n != 1: + sys.exit(f"expected one jsignpdf archive source, patched {n}") + open(path, "w").write(s) + PY + MANIFEST=flathub/io.github.intoolswetrust.JSignPdf.yaml + grep -qx " url: ${TARBALL}" "$MANIFEST" + grep -qx " sha256: ${SHA256}" "$MANIFEST" + + - name: Open or update the Flathub PR + working-directory: flathub + run: | + set -euo pipefail + BRANCH="update-${VERSION}" + if git diff --quiet; then + echo "Flathub is already at ${VERSION}; nothing to do." + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + git checkout -b "$BRANCH" + git commit -qam "Update to JSignPdf ${VERSION}" + git push -f -u origin "$BRANCH" + if gh pr view "$BRANCH" --repo "$FLATHUB_REPO" >/dev/null 2>&1; then + echo "PR for ${BRANCH} already open; pushed the updated commit." + exit 0 + fi + gh pr create --repo "$FLATHUB_REPO" --base master --head "$BRANCH" \ + --title "Update to JSignPdf ${VERSION}" \ + --body "Automated update from the \`package-release\` workflow. + + - source archive bumped to tag \`${{ steps.tag.outputs.tag }}\` + - \`maven-dependencies.json\` taken from that same tag, so the offline + Maven repo matches the poms in the pinned tarball" From 02075438cf2dc30479a03b3b08910c22cc5c0b96 Mon Sep 17 00:00:00 2001 From: "Josef (kwart) Cacek" Date: Wed, 23 Sep 2026 17:41:44 +0200 Subject: [PATCH 3/4] Use build-options libdir for pcsc-lite -Dlibdir collides with the --libdir that newer flatpak-builder passes: "Got argument libdir as both -Dlibdir and --libdir. Pick one." --- .../flatpak/io.github.intoolswetrust.JSignPdf.Devel.yaml | 7 ++++--- .../linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.Devel.yaml b/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.Devel.yaml index af80980c..da6d2ad4 100644 --- a/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.Devel.yaml +++ b/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.Devel.yaml @@ -41,10 +41,11 @@ modules: - type: archive url: https://pcsclite.apdu.fr/files/pcsc-lite-2.5.1.tar.xz sha256: bfcfe38a20afc49849c6bf55325e38f449fc4b26d3923fdc32b969ae41a8741b + # Older flatpak-builder does not pass --libdir, meson then picks lib64 and + # opensc's configure cannot find libpcsclite.pc. + build-options: + libdir: /app/lib config-opts: - # Without an explicit libdir meson picks lib64, and opensc's configure - # then cannot find libpcsclite.pc. - - -Dlibdir=lib - -Ddefault_library=shared - -Dlibsystemd=false - -Dpolkit=false diff --git a/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml b/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml index d3f57df0..ea63323f 100644 --- a/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml +++ b/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml @@ -41,10 +41,11 @@ modules: - type: archive url: https://pcsclite.apdu.fr/files/pcsc-lite-2.5.1.tar.xz sha256: bfcfe38a20afc49849c6bf55325e38f449fc4b26d3923fdc32b969ae41a8741b + # Older flatpak-builder does not pass --libdir, meson then picks lib64 and + # opensc's configure cannot find libpcsclite.pc. + build-options: + libdir: /app/lib config-opts: - # Without an explicit libdir meson picks lib64, and opensc's configure - # then cannot find libpcsclite.pc. - - -Dlibdir=lib - -Ddefault_library=shared - -Dlibsystemd=false - -Dpolkit=false From 3ca75bae4452c96b086dc6360a3b29469f47250d Mon Sep 17 00:00:00 2001 From: "Josef (kwart) Cacek" Date: Wed, 23 Sep 2026 22:27:55 +0200 Subject: [PATCH 4/4] Address review findings on the Flatpak/Flathub changes flathub-pr job: - only an OPEN PR short-circuits PR creation; `gh pr view ` also resolves closed and merged PRs, so a re-run after a closed PR pushed the branch and exited without ever opening one - `git add -A` + `git diff --cached --quiet`: a manifest that grows a new file left it untracked, and the tree looked clean ("already at version") - the url/sha256 assertion moved into the rewrite itself, so a reindented Flathub manifest fails loudly instead of matching no grep - timeout-minutes, `permissions: contents: read`, and `${{ }}` in `run:` routed through env like the rest of the workflow - `flatpak` added to `needs`: pcsc-lite/opensc/openjdk are shared with the Flathub manifest, so a failure there predicts a failing Flathub build build-local.sh: guard the two sed rewrites that can silently no-op (desktop, metainfo) instead of grepping for the zip path, which sed never touches. Manifests: move the TSA comment onto the --share=network line it describes, making finish-args byte-identical to the Flathub manifest. Also drop the stale claim that aarch64 falls through to Swing -- the full ZIP ships javafx-*-linux-aarch64.jar and Bootstrap.detectFxClassifier picks it up, so both Flatpak arches get the JavaFX UI and its XDG portal file chooser. Release tag is now derived once in `setup` and consumed by the four jobs that checked it out, instead of being recomputed in each. --- .github/workflows/package-release.yml | 98 +++++++++++-------- distribution/linux/flatpak/build-local.sh | 6 +- ....github.intoolswetrust.JSignPdf.Devel.yaml | 2 +- .../io.github.intoolswetrust.JSignPdf.yaml | 2 +- 4 files changed, 62 insertions(+), 46 deletions(-) diff --git a/.github/workflows/package-release.yml b/.github/workflows/package-release.yml index 6975f0a3..2949d018 100644 --- a/.github/workflows/package-release.yml +++ b/.github/workflows/package-release.yml @@ -49,13 +49,15 @@ env: jobs: setup: - # Classify the version once. Pre-releases (ALPHA/BETA/RC/MILESTONE) skip - # Windows code signing entirely and are flagged --prerelease on GitHub. + # Classify the version once and derive the release tag once. Pre-releases + # (ALPHA/BETA/RC/MILESTONE) skip Windows code signing entirely, are flagged + # --prerelease on GitHub, and do not get a Flathub PR. runs-on: ubuntu-24.04 outputs: is-prerelease: ${{ steps.check.outputs.is-prerelease }} + tag: ${{ steps.check.outputs.tag }} steps: - - name: Classify release version + - name: Classify release version and derive the tag id: check shell: bash env: @@ -69,6 +71,7 @@ jobs: else echo "is-prerelease=false" >> "$GITHUB_OUTPUT" fi + echo "tag=JSignPdf_${VERSION//./_}" >> "$GITHUB_OUTPUT" fetch-zips: # Pull the published full/minimal ZIPs from Maven Central. release:perform @@ -189,15 +192,10 @@ jobs: env: VERSION: ${{ inputs.release-version }} steps: - - name: Compute release tag - id: tag - shell: bash - run: echo "tag=JSignPdf_${VERSION//./_}" >> "$GITHUB_OUTPUT" - - name: Checkout release tag uses: actions/checkout@v7 with: - ref: ${{ steps.tag.outputs.tag }} + ref: ${{ needs.setup.outputs.tag }} # jpackage runs need JavaFX modules in the bundled runtime image, so we # consume Azul Zulu+FX (java-package: jdk+fx). Temurin does not ship JFX. @@ -393,10 +391,10 @@ jobs: flatpak: # Builds Flatpak bundles for both x86_64 and aarch64 from the Central full - # ZIP. JavaFX lives inside the ZIP for the x86_64 case; aarch64 falls - # through to Swing because OpenJFX 21 does not publish linux-aarch64 - # classifier jars on Maven Central. - needs: fetch-zips + # ZIP. The ZIP carries the JavaFX linux and linux-aarch64 classifier jars in + # lib/javafx/, so Bootstrap loads the JavaFX UI (and with it the XDG portal + # file chooser) on both architectures. + needs: [setup, fetch-zips] strategy: fail-fast: false matrix: @@ -409,14 +407,10 @@ jobs: env: VERSION: ${{ inputs.release-version }} steps: - - name: Compute release tag - id: tag - run: echo "tag=JSignPdf_${VERSION//./_}" >> "$GITHUB_OUTPUT" - - name: Checkout release tag uses: actions/checkout@v7 with: - ref: ${{ steps.tag.outputs.tag }} + ref: ${{ needs.setup.outputs.tag }} - name: Download full ZIP from Maven Central job uses: actions/download-artifact@v8 @@ -490,14 +484,13 @@ jobs: - name: Compute version-derived names id: vars run: | - echo "tag=JSignPdf_${VERSION//./_}" >> "$GITHUB_OUTPUT" echo "base=${VERSION%%-*}" >> "$GITHUB_OUTPUT" echo "full=JSignPdf-${VERSION}" >> "$GITHUB_OUTPUT" - name: Checkout release tag uses: actions/checkout@v7 with: - ref: ${{ steps.vars.outputs.tag }} + ref: ${{ needs.setup.outputs.tag }} - name: Download cross-platform ZIPs from Maven Central job uses: actions/download-artifact@v8 @@ -618,9 +611,9 @@ jobs: - name: Create GitHub release with all assets env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TAG: ${{ needs.setup.outputs.tag }} run: | set -euo pipefail - TAG="${{ steps.vars.outputs.tag }}" NOTES_FILE="distribution/doc/release-notes/${{ steps.vars.outputs.base }}.md" if [ ! -f "$NOTES_FILE" ]; then echo "::error::Release notes file not found at $NOTES_FILE" @@ -659,11 +652,20 @@ jobs: # another org. The job runs after the release is published, so a failure # here never blocks the release — re-run just this job once the token is # fixed. + # + # `flatpak` is in `needs` so a broken manifest stops here: the pcsc-lite, + # opensc and openjdk modules are shared with the Flathub manifest, so a + # failure there predicts a failing Flathub build. Drop it from `needs` if + # you want the PR opened regardless. runs-on: ubuntu-24.04 - needs: [setup, publish-release] + timeout-minutes: 30 + needs: [setup, flatpak, publish-release] if: needs.setup.outputs.is-prerelease == 'false' + permissions: + contents: read env: VERSION: ${{ inputs.release-version }} + TAG: ${{ needs.setup.outputs.tag }} FLATHUB_REPO: flathub/io.github.intoolswetrust.JSignPdf GH_TOKEN: ${{ secrets.FLATHUB_TOKEN }} steps: @@ -675,14 +677,10 @@ jobs: exit 1 fi - - name: Compute release tag - id: tag - run: echo "tag=JSignPdf_${VERSION//./_}" >> "$GITHUB_OUTPUT" - - name: Checkout release tag uses: actions/checkout@v7 with: - ref: ${{ steps.tag.outputs.tag }} + ref: ${{ needs.setup.outputs.tag }} path: upstream - name: Checkout the Flathub repo @@ -693,45 +691,59 @@ jobs: git -C flathub config credential.helper '!gh auth git-credential' - name: Update the manifest and the offline Maven manifest + env: + REPO: ${{ github.repository }} run: | set -euo pipefail - TAG="${{ steps.tag.outputs.tag }}" - TARBALL="https://github.com/${{ github.repository }}/archive/refs/tags/${TAG}.tar.gz" + TARBALL="https://github.com/${REPO}/archive/refs/tags/${TAG}.tar.gz" curl -fsSL "$TARBALL" -o source.tar.gz SHA256=$(sha256sum source.tar.gz | awk '{print $1}') cp upstream/distribution/linux/flatpak/maven-dependencies.json flathub/ - python3 - "$TAG" "$SHA256" <<'PY' + # The rewrite asserts on the result itself rather than grepping for a + # fixed indentation afterwards, so a reindented Flathub manifest fails + # loudly instead of silently matching nothing. + python3 - "$TARBALL" "$SHA256" <<'PY' import re, sys - tag, sha = sys.argv[1], sys.argv[2] + tarball, sha = sys.argv[1], sys.argv[2] path = "flathub/io.github.intoolswetrust.JSignPdf.yaml" s = open(path).read() pattern = re.compile( - r"(url: https://github\.com/[^\s]+/archive/refs/tags/)[^\s]+" - r"(\n\s*sha256: )[0-9a-f]{64}") - s, n = pattern.subn(lambda m: m.group(1) + tag + ".tar.gz" + m.group(2) + sha, s) + r"(?P[ \t]*)url: https://github\.com/\S+/archive/refs/tags/\S+" + r"\n(?P=indent)sha256: [0-9a-f]{64}") + replacement = lambda m: ( + f"{m.group('indent')}url: {tarball}\n" + f"{m.group('indent')}sha256: {sha}") + s, n = pattern.subn(replacement, s) if n != 1: sys.exit(f"expected one jsignpdf archive source, patched {n}") open(path, "w").write(s) + if f"url: {tarball}\n" not in s or f"sha256: {sha}\n" not in s: + sys.exit("rewrite did not land the expected url/sha256") PY - MANIFEST=flathub/io.github.intoolswetrust.JSignPdf.yaml - grep -qx " url: ${TARBALL}" "$MANIFEST" - grep -qx " sha256: ${SHA256}" "$MANIFEST" - name: Open or update the Flathub PR working-directory: flathub run: | set -euo pipefail BRANCH="update-${VERSION}" - if git diff --quiet; then + git config user.name "github-actions[bot]" + git config user.email "41898282+github-actions[bot]@users.noreply.github.com" + # -A, not `git diff`: a manifest that grows a new file would otherwise + # leave it untracked and report the tree as clean. + git add -A + if git diff --cached --quiet; then echo "Flathub is already at ${VERSION}; nothing to do." exit 0 fi - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" git checkout -b "$BRANCH" - git commit -qam "Update to JSignPdf ${VERSION}" + git commit -qm "Update to JSignPdf ${VERSION}" git push -f -u origin "$BRANCH" - if gh pr view "$BRANCH" --repo "$FLATHUB_REPO" >/dev/null 2>&1; then + # Only an OPEN PR counts: `gh pr view ` also resolves closed and + # merged ones, which would make a re-run push the branch and then exit + # without ever opening a PR. + open_pr=$(gh pr list --repo "$FLATHUB_REPO" --state open \ + --head "$BRANCH" --json number --jq 'length') + if [ "$open_pr" != "0" ]; then echo "PR for ${BRANCH} already open; pushed the updated commit." exit 0 fi @@ -739,6 +751,6 @@ jobs: --title "Update to JSignPdf ${VERSION}" \ --body "Automated update from the \`package-release\` workflow. - - source archive bumped to tag \`${{ steps.tag.outputs.tag }}\` + - source archive bumped to tag \`${TAG}\` - \`maven-dependencies.json\` taken from that same tag, so the offline Maven repo matches the poms in the pinned tarball" diff --git a/distribution/linux/flatpak/build-local.sh b/distribution/linux/flatpak/build-local.sh index 59aa3aac..bd260ec9 100755 --- a/distribution/linux/flatpak/build-local.sh +++ b/distribution/linux/flatpak/build-local.sh @@ -128,7 +128,11 @@ case "$MODE" in -e "s|path: \\.\\./jsignpdf\\.desktop|path: ${DESKTOP_ABS}|" \ -e "s|path: \\.\\./io\\.github\\.intoolswetrust\\.JSignPdf\\.metainfo\\.xml|path: ${METAINFO_ABS}|" \ "$RELEASE_MANIFEST" > "$STAGED" - grep -q "path: jsignpdf-full.zip" "$STAGED" || { echo "patch failed (zip path)" >&2; exit 1; } + # Only the desktop/metainfo rewrites can silently no-op; the zip is already + # a relative `path:` in the committed manifest and needs no patching. + grep -qF "path: $DESKTOP_ABS" "$STAGED" || { echo "patch failed (desktop path)" >&2; exit 1; } + grep -qF "path: $METAINFO_ABS" "$STAGED" || { echo "patch failed (metainfo path)" >&2; exit 1; } + grep -qF "path: jsignpdf-full.zip" "$STAGED" || { echo "manifest lost the staged zip path" >&2; exit 1; } BUNDLE="$BUILD_DIR/JSignPdf-${VERSION}-linux-x86_64.flatpak" ;; diff --git a/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.Devel.yaml b/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.Devel.yaml index da6d2ad4..399d4c60 100644 --- a/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.Devel.yaml +++ b/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.Devel.yaml @@ -10,8 +10,8 @@ sdk-extensions: command: jsignpdf finish-args: -# Network is required for TSA (timestamps) functionality - --env=PATH=/app/jre/bin:/app/bin:/usr/bin +# Network is required for TSA (timestamps) functionality - --share=network - --share=ipc # Requires X11 to run diff --git a/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml b/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml index ea63323f..df480f09 100644 --- a/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml +++ b/distribution/linux/flatpak/io.github.intoolswetrust.JSignPdf.yaml @@ -10,8 +10,8 @@ sdk-extensions: command: jsignpdf finish-args: -# Network is required for TSA (timestamps) functionality - --env=PATH=/app/jre/bin:/app/bin:/usr/bin +# Network is required for TSA (timestamps) functionality - --share=network - --share=ipc # Requires X11 to run