Commit Graph
415 Commits
Author SHA1 Message Date
Zane Schepke e01e71027f fix(linux): address review feedback on install/remove scripts
Per kdroidFilter's review on #664:

- Drop jdk.jlink filtering from AbstractJLinkTask (JEP 493 fix) — unrelated
  to this PR, belongs in its own change.
- Drop nativeDistributions.appContent / jpackage --app-content — incomplete
  API (no KDoc, no tests, JVM-only, flattens subdirectories) and redundant
  with appResourcesRootDir + afterInstall for the systemd-unit use case this
  was meant for.
- Expand KDoc on the four linux { afterInstall/afterRemove/beforeInstall/
  beforeRemove } properties to document, on the properties themselves
  rather than only in CLAUDE.md: electron-builder's single-quote-only macro
  substitution for afterInstall/afterRemove, that beforeInstall/beforeRemove
  get no macro substitution at all (raw fpm args), and the Pacman pre_remove
  upgrade-detection caveat.
2026-09-17 13:51:47 -04:00
Zane Schepke 6a81fcb9e6 Merge remote-tracking branch 'upstream/main' into feat/linux-install-scripts
# Conflicts:
#	CLAUDE.md
2026-09-17 13:47:19 -04:00
Zane Schepke 525cbabeea feat(linux): after/before install/remove scripts
Wire the after-install/after-remove/before-install/before-remove scripts
for the GraalVM native-image packaging path too, matching the JVM/jpackage
path (previously only JVM was wired).
2026-09-08 03:13:17 -04:00
Zane Schepke 076291b0df feat: graalvm headless optimization
Add docs for changes
2026-09-08 03:12:51 -04:00
takke 82c6131ff3 feat(nsis): add menuCategory and shortcutName to the NSIS targets
Follow-up to #629. The NSIS targets already expose most installer
settings, but not menuCategory / shortcutName, so a start menu group
could not be declared at all: the shortcut always landed in the start
menu root. This blocked projects that are migrating their MSI packaging
to the recommended NSIS format while keeping the start menu folder
they had under jpackage.

Add the two remaining CommonWindowsInstallerConfiguration options to
NsisSettings and emit them for nsis and nsis-web. Both default to null
(nothing emitted), so generated installers are unchanged unless a
project opts in - with the same intended exception as the MSI target:
windows.menuGroup, the jpackage-era name for the same concept, acts as
the default for nsis.menuCategory.

The "nsis target is unaffected by the msi settings" test asserted that
menuCategory never appears for NSIS; it now asserts the actual concern,
that msi {} values do not leak into the nsis block.
2026-09-01 00:55:49 +09:00
takke 7e7363cbe6 fix(msi): forward the Windows installer settings to electron-builder
The MSI target only passed upgradeCode and perMachine to
electron-builder, so every other Windows installer setting fell back to
an electron-builder default: windows.menuGroup was ignored and the
shortcut landed in the start menu root, oneClick defaulted to true so
the installer ran without showing any UI, and runAfterFinish defaulted
to true so the app was launched as soon as the install finished.
Projects migrating from jpackage-based packaging lost all three
silently, with no way to set them from a build script.

Add the remaining CommonWindowsInstallerConfiguration options to
MsiSettings and emit them. Each defaults to the electron-builder
default so generated MSIs are unchanged unless a project opts in,
except that windows.menuGroup - the jpackage-era name for the same
concept - now acts as the default for msi.menuCategory, restoring the
start menu folder for projects that already declare one.

windows.menu / windows.shortcut are deliberately not mapped: their
jpackage defaults (false) are the opposite of electron-builder's
(true), so mapping them would silently drop shortcuts from MSIs that
are fine today. msi.createStartMenuShortcut / createDesktopShortcut
give explicit control instead.

generateWindowsConfig becomes internal so the rendered YAML can be
asserted in unit tests, matching generateLinuxConfig which is already
internal for the same reason.
2026-08-31 22:48:12 +09:00
Elie Gambache 1c5d9d6553 test(plugin): expect AOT training to disable the Tao fatal dialog
buildAotJavaArgs now injects -Dnucleus.tao.fatalErrorDialog=false so a
training crash cannot hang in the #622 native dialog. Update the
argument-order assertions to match.
2026-08-30 19:49:36 +03:00
Elie Gambache 1712f2af25 feat(tao): Linux GTK fatal dialog and Compose crash routing (#622)
Show a modal GtkMessageDialog after the loop exits, install a shared
coroutine exception handler on every scene, and recheck pending fatals
before exitProcess(0) so a composition-side crash cannot quit with 0.
Unattended runs (headful tests, AOT training) disable the dialog via
-Dnucleus.tao.fatalErrorDialog=false.
2026-08-30 18:49:35 +03:00
Elie G. 43048155b0 fix(tao): add Windows native-image JNI metadata for tray popup DnD 2026-08-27 20:23:38 +03:00
Elie G. ef6c3d824d fix(tao): register inbound DnD on standalone tray popups 2026-08-27 20:12:19 +03:00
Elie G. e911f11ec5 feat(graalvm): default the innovation channel to GraalVM 25.3 2026-08-27 15:28:55 +03:00
Elie Gambache f0d66a870f fix(plugin): stop Linux update helper leaking a gpg-agent into the app's systemd scope
gpg --import/--verify daemonize a gpg-agent for the throwaway homedir; with
no idle timeout it inherits the app's systemd scope and keeps it reported as
running forever, and the trailing exec bypassed the EXIT trap so the
root-owned work dir leaked too.

Verify with gpgv (never starts an agent) against a gpg --dearmor'd keyring
(pure filter), and drop the execs so the EXIT trap cleans the work dir —
set -e still propagates dpkg/rpm exit codes unchanged.

Fixes #567
2026-08-26 12:46:09 +03:00
Elie GambacheandClaude Opus 4.8 b2311e29bf fix(updater): close TOCTOU and downgrade in the root Linux update helper
The passwordless self-update helper runs as root via pkexec but takes a
caller-supplied package path that is writable by the unprivileged invoking
user. It verified the detached signature and then re-opened the same path
for `dpkg -i` / `rpm -U` — two separate opens, so the bytes could be swapped
between verify and install, giving a local user root code execution.

The helper now copies the package and its signature into a root-owned 0700
working dir first, then verifies and installs the copies, so the verified
bytes cannot be replaced. The deb path additionally refuses anything that is
not a strict version increase (`dpkg --compare-versions ... gt`), blocking a
rollback to an older, still-validly-signed, vulnerable release; `rpm -U`
already refuses downgrades.

The bash is exercised on real distros in packaging; a new unit test locks the
security-relevant structure (copy-before-verify, verify-the-copy, refuse
non-upgrade) so a refactor cannot silently drop it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-19 20:24:19 +03:00
Elie Gambache e7407ca4cc fix(plugin): install electron-builder from a pinned lock file instead of npx
Packaging invoked `npx --yes electron-builder@26.15.5`, which pinned only
the top-level version: the ~275 transitive packages were re-resolved from
the registry on every build, with no lock state to check them against and
with install scripts enabled. That runs on the machine holding the
code-signing certificates and notarization credentials, so a compromise
anywhere in that tree executed with those.

The plugin now embeds a package.json / package-lock.json pair pinning 277
packages (all from registry.npmjs.org, each with a sha512 integrity hash),
stages it into a build-local directory, installs with
`npm ci --ignore-scripts`, and runs the CLI directly through
`node node_modules/electron-builder/cli.js`. A tarball whose bytes do not
match the recorded hash now fails the build (EINTEGRITY), and no
pre/postinstall hook from that tree runs at all.

node and npm still come from the build machine; only the dependency tree is
pinned. electron-builder's own run-time downloads (app-builder, 7-Zip, NSIS,
snap/AppImage templates) remain outside any npm lock file — they are
verified by its own checksums.

Also in this change:

  - NodeJsDetector.detectNpm(), plus a shared detectSibling() helper for the
    nodePath override; the task now requires both node and npm and says
    what each is for when one is missing.
  - MacDmgLzma.locateAppBuilder searched the npx cache, which no longer
    exists, and never looked in ELECTRON_BUILDER_CACHE where
    electron-builder 26 actually downloads app-builder. It now checks that
    first, so the differential-update blockmap is no longer silently
    dropped after the DMG is recompressed with LZMA.
  - scripts/update-electron-builder-lock.sh regenerates the lock file,
    resolving against the public registry explicitly and refusing to run
    when certificate verification has been switched off — a lock file
    resolved over an unverified connection would record hashes for bytes
    nothing authenticated.
  - ElectronBuilderToolchainLockTest guards the boundary offline: version
    pinned in step with the Kotlin constant, lockfileVersion 3, every
    package from the public registry, every one carrying a sha512 hash.

Verified end to end against a minimal consumer project (TargetFormat.Zip):
the nominal path provisions the toolchain and produces the signed .app zip
plus its blockmap, and tampering with a single integrity hash in the
embedded lock file fails the build as intended.
2026-08-18 12:43:17 +03:00
Elie Gambache 0d179d2e94 chore: complete third-party attribution and fill in the LICENSE holder
The repository is MIT-licensed but redistributes Apache-2.0 code whose
attribution was not carried:

  - 127 Kotlin files under plugin-build/plugin/src retain the
    "Copyright 20xx JetBrains s.r.o. ... Apache 2.0" header — the Gradle
    plugin is a fork of the Compose Multiplatform Gradle plugin — yet no
    Apache-2.0 text accompanied them and the notices did not mention it.
  - The vendored tao fork (Apache-2.0) and the three AccessKit crates
    (MIT OR Apache-2.0) compile into libnucleus_tao, which ships inside
    the decorated-window-tao JAR. accesskit_windows was also the only
    vendored crate not keeping its upstream LICENSE-APACHE/LICENSE-MIT.
  - LICENSE still carried the unfilled template line
    "Copyright (c) 2020 <Source Code Author>".

THIRD_PARTY_NOTICES.md now covers all four components plus the build-time
tools and a pointer to Cargo.lock for the transitive Rust tree, with the
license texts collected once under licenses/. The LICENSE year follows the
git history (first commit 2026-02-08); the 2020 came from the JetBrains
headers, not from this project.

Apache-2.0 §4(a) requires the license copy to travel with binary
distributions too, so the jar tasks of plugin-build/plugin and
decorated-window-tao now stage the notices and licenses/ into META-INF/.
2026-08-18 12:42:53 +03:00
Elie G. 2c2033f504 chore(plugin): include jdk.unsupported in default runtime modules
sun.misc.Unsafe is required by JNA, Jewel and many common libraries;
without it packaged distributions crash at runtime. jewel-demo no longer
needs its --add-opens workaround.
2026-08-17 17:04:16 +03:00
Elie Gambache 5d5cfc438b chore(tao): migrate decorated-window-tao to Compose 1.12.0-rc01
Rebased PR #354 on main and bumped Compose from 1.12.0-beta02 to the
latest RC. Scene create/render/dispose lives in TaoSceneBundle so the
1.12 FrameRecomposer + measureAndLayout + draw split is in one place.
Material3 moves to 1.12.0-alpha03 (Expressive APIs) and hot-reload to
1.2.0 to match the RC plugin bundle.
2026-08-16 14:51:53 +03:00
Elie G. a30f72977b fix(graalvm): copy appResources into native packages and agent runs
prepareAppResources was only wired for JVM run/jpackage. Native packaging
and runWithNativeAgent never set compose.application.resources.dir, so
sidecars such as Dawn's dxil.dll were missing.
2026-08-13 19:13:10 +03:00
Elie G. b97a8e24f5 feat(plugin): add windows.msi DSL block, deprecate perUserInstall
Introduce msi { perMachine } mirroring nsis { perMachine } (1:1 mapping
to electron-builder msi.perMachine, no inversion). The deprecated
windows.perUserInstall keeps working when msi.perMachine is not set
explicitly; defaults are unchanged (MSI installs per-machine).

Closes #225
2026-08-08 22:31:58 +03:00
Elie Gambache 08252cb45d Merge pull request #470 from NucleusFramework/fix/graalvm-l1-ktor-noise-sqlite
fix(graalvm): expand L1 metadata and always drop Kotlin agent noise
2026-08-06 15:15:21 +03:00
Elie Gambache b412741d33 Merge pull request #468 from NucleusFramework/feat/per-format-compression
feat(plugin): per-format compression for AppImage and portable
2026-08-06 14:53:51 +03:00
Elie Gambache f789e7f1c8 fix(graalvm): expand L1 metadata and always drop Kotlin agent noise
- Always remove tracing-agent phantoms (kotlin.Any/Int/FunctionN/collections
  mapped types) during cleanupGraalvmMetadata without removeUnresolvable.
- Expand L1 ktor.json with client plugins, server, and websocket types used
  by real apps (e.g. Flocon).
- Add androidx-sqlite-bundled L1 pack; enrich jdk-core FFM/VarHandle/Module
  coverage; register AtomicInt/AtomicRef and kotlin.kotlin_builtins.
2026-08-06 14:16:12 +03:00
Elie Gambache aad419be13 feat(plugin): per-format compression for AppImage and portable
Allow overriding root compressionLevel for AppImage and Windows portable so Ultra can stay on DEB/DMG while those formats use Normal/Store.
2026-08-06 14:01:42 +03:00
Elie Gambache f53fc8f9f5 fix(graalvm): resolve project class dirs for KMP named JVM targets
Wire orphan/project-class detection to the application target's
compilation outputs (e.g. jvm("desktop") → desktopMainClasses) instead
of hardcoded jvm/main paths, and ignore nest-internal reference edges so
real Room AppDatabase_Impl classes with nested types are still detected.
2026-08-06 13:47:37 +03:00
Elie Gambache bdde5ff202 Merge pull request #457 from NucleusFramework/feat/linux-silent-update-deb-rpm
fix(linux): make silent DEB/RPM self-update work
2026-08-06 08:03:49 +03:00