Package and qualify standalone macOS designer with bundled runtime
This commit is contained in:
@@ -163,3 +163,7 @@ The [reliability follow-up](ide-host-reliability.md) closes the generated-ViewMo
|
||||
## Reviewed FXML View generation
|
||||
|
||||
The [reviewed generation slice](reviewed-view-generation.md) adds a shared metadata-driven form setup, structural/FXML preview, target validation and non-overwriting creation in both hosts. Explicit field, Component, Converter and Table/Column choices produce a new normal editable View. Approval is invalidated by changed drafts or choices and checked against the current build before creation. Broader scaffolding, generation settings and product packaging retain their follow-up scope. Automated qualification is recorded in the slice document.
|
||||
|
||||
## Bundled standalone packaging
|
||||
|
||||
The [first distribution slice](standalone-distribution.md) adds a macOS app image/ZIP with a linked Java runtime, pinned Kit/JavaFX, a native project-aware CLI and separate worker tools. Automated qualification runs the relocated production launcher with classpath/module-path applications and checks setup failures, source editing and cleanup. Context-choice UI, signed installation, public artifact delivery and other platforms remain later work.
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# Bundled standalone distribution
|
||||
|
||||
The first packaging slice produces a relocatable macOS `NeitzelFXDesigner.app`, a ZIP containing that app, and a SHA-256 file inventory. The application carries a Java 25 runtime, JavaFX 26, Kit 26 and the shared designer modules. It does not use `JAVA_HOME` to choose its host JVM. Application builds and previews still use the explicitly configured application JDKs and dependencies.
|
||||
|
||||
## Build and launch
|
||||
|
||||
On the qualified macOS workstation, with JDK 25 and the recorded local NeitzelLib artifacts installed:
|
||||
|
||||
```sh
|
||||
python3 scripts/package-standalone.py --java-home "$JAVA_HOME"
|
||||
```
|
||||
|
||||
The script verifies the runtime artifact baseline, builds/tests the standalone dependency reactor and target tooling, resolves production dependencies, creates a runtime with `jlink`, and builds the native app image with `jpackage`. It refuses to replace existing package outputs; use `--destination` for another output directory. Default output is `target/distribution/`.
|
||||
|
||||
Launch the bundled executable directly, including from an IDE external-tool command:
|
||||
|
||||
```sh
|
||||
"/path/to/NeitzelFXDesigner.app/Contents/MacOS/NeitzelFXDesigner" \
|
||||
--configuration /project/neitzel-fx-designer.json \
|
||||
--settings /project/.neitzel-fx-designer/runtimes.json \
|
||||
--context desktop \
|
||||
/project/app/src/main/resources/example/Person.fxml
|
||||
```
|
||||
|
||||
`--context` can be omitted when exactly one context exists. The active context appears in each editor window title and Component navigation inherits it. For multiple contexts this slice requires an explicit selection; it does not yet provide the graphical selection/remembering flow. `--maven /path/to/mvnw` provides a fallback when the project has no Maven wrapper. See [configuration and runtimes](configuration-and-protocol.md) for the shared configuration and machine-local JDK mappings. No target JDK is silently substituted with the bundled host JVM.
|
||||
|
||||
Omit the FXML argument to select a View in a file chooser. `--help` and `--version` run without opening JavaFX; unknown, duplicate or incomplete options fail with usage and exit status 2. The prior `host.properties View.fxml` invocation and the explicit `--launch host.properties [View.fxml]` form remain supported. The project-options form obtains worker tooling from the bundle; legacy launch settings retain their explicit tool paths.
|
||||
|
||||
This slice is command-line launched. Finder project selection, file associations, install/update flows and remembered context selection remain follow-ups. There is no claim that double-clicking an unconfigured app opens a project.
|
||||
|
||||
## Package boundaries and provenance
|
||||
|
||||
The launcher manifest orders the patched shared Kit classes before upstream Kit. Production JARs retain their embedded license/notice resources, the app includes `THIRD-PARTY-NOTICES.md`, and the linked JDK retains its legal files. The package inventory records the source commit and dirty-tree flag, JDK release metadata, architecture and every bundled file hash. It identifies a development artifact, not a published release or a reproducible-build claim.
|
||||
|
||||
`jpackage` adds nested input JARs to its generated host classpath. Worker tools are therefore copied to `Contents/app/tools` after launcher creation; an assembly assertion rejects leaked tool paths. The host package includes no IntelliJ SDK, target application library or test JARs. Target tools, contracts and preview API are supplied separately to the target JVM, which resolves application dependencies from the immutable build snapshot.
|
||||
|
||||
The application version remains `0.1.0-SNAPSHOT`. The macOS bundle uses numeric version `1.0` because this JDK's `jpackage` rejects a zero leading version component; that bundle value is not a product 1.0 release. The archive is a local development distribution, without Developer ID signing or notarization. Public distribution still needs the product license decision, release/provenance review and separately published project-facing tools/runtime artifacts. Application building still requires its configured JDK, Maven and dependency access; bundling the designer does not make builds offline.
|
||||
|
||||
## Automated qualification
|
||||
|
||||
```sh
|
||||
python3 scripts/check-standalone-package.py \
|
||||
--app target/distribution/NeitzelFXDesigner.app \
|
||||
--java-home "$JAVA_HOME" --target-java-home "$TARGET_JAVA_HOME"
|
||||
```
|
||||
|
||||
The test verifies the inventory, extracts the ZIP into a path containing spaces, verifies the extracted files against the inventory, and launches its native executable with an invalid `JAVA_HOME` and a restricted `PATH`. An external Java agent observes the real production application, drives the shared authoring suite, and verifies runtime identity, JavaFX version, patched Kit origin and absence of the preview API from the host classloader. Each run extracts JavaFX natives into a fresh cache and verifies their hashes against the bundled JARs. Test classes are never included in the distribution. Agent options are added only to the disposable copy's launcher configuration, so they do not propagate into Maven or target JVMs.
|
||||
|
||||
The classpath and named-module fixtures exercise Build and Refresh, rendering, binding/structure edits, diagnostics, reviewed generation, navigation, exact source/history/save behavior and target loading. Tests close actual application windows and check worker termination. Invalid configuration exercises source-only editing and saving; missing application-JDK setup must fail the build without disabling source editing. A native crash guard checks for new JVM crash reports. `--mode` selects one scenario for focused regression runs.
|
||||
|
||||
The optional-FXML file chooser is implemented but native chooser interaction is not part of this automated qualification. Existing skipped human-input checks stay skipped. Other CPU architectures, Windows/Linux, quarantined downloads and signed/notarized installation remain unqualified.
|
||||
|
||||
## Qualification record — 2026-11-13
|
||||
|
||||
Qualified on macOS 27.2 arm64 with Homebrew Java 25.0.5.0.3 as the bundled host and the existing Java 21 / JavaFX 21.0.7 target fixtures. The full bootstrap passed 160 unit/adapter tests with zero failures/errors/skips, 38 target processes with 548 checks, both native standalone workflows, 48 lifecycle cycles, abrupt owner death, bytecode/dependency boundaries, plugin packaging and documentation checks. No registered IntelliJ GUI rerun was needed for this standalone-only change; its document adapters are included in the bootstrap.
|
||||
|
||||
The relocated production app passed complete classpath and module-path authoring workflows, then invalid-configuration source editing/saving and missing-JDK failure/source-availability scenarios. Every case verified bundled runtime identity, Kit patch origin, target-API exclusion, fresh native-library hashes and worker shutdown. The final ZIP was extracted into another path with spaces; every extracted file matched the qualified app inventory, and its startup/source-only save/cleanup smoke passed. Output-collision refusal and CLI usage/version/error checks passed.
|
||||
|
||||
Initial assembly caught manifest-line folding and macOS numeric bundle-version requirements. Launcher inspection caught `jpackage`'s recursive tool-JAR classpath inclusion, corrected before qualification. Two early harness runs were invalidated: environment-wide agent injection reached Maven, and a concurrent clean build removed a test copy under `target`. The final harness uses host-only launcher options and disposable copies outside the build tree. Neither invalid run is counted as a pass.
|
||||
|
||||
Local evidence: `/tmp/standalone-package-build-qualified.log`, `/tmp/standalone-package-bootstrap.log`, `/tmp/standalone-package-qualified.log`, `/tmp/standalone-package-archive.log`, and the `designer-package-check-b46en3a8` / `designer-package-check-wq50e0ct` temporary directories reported by those logs. The archive is `target/distribution/NeitzelFXDesigner-macos.zip`, SHA-256 `dcbb95c4d80371daca612b863701cb120a1a922a114984c3f0683c9edb176fa1`; the sibling `package-manifest.json` records individual file hashes and the pre-commit working-tree build provenance. These local outputs are not committed or published releases. No manual testing was used.
|
||||
Reference in New Issue
Block a user