@omega.js/desktop 0.50.0 → 0.51.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/assets/css/tokens/_index.scss +1 -1
- package/dist/assets/themes/base/_includes/frontend/sections/account-section-header.html +4 -1
- package/dist/assets/themes/base/_includes/frontend/sections/footer.html +13 -6
- package/dist/assets/themes/base/_includes/frontend/sections/nav.html +10 -8
- package/dist/assets/themes/base/_includes/global/sections/account.html +3 -1
- package/dist/assets/themes/base/_includes/global/sections/app-sidebar.html +12 -8
- package/dist/assets/themes/base/_includes/global/sections/app-topbar.html +10 -6
- package/dist/assets/themes/base/_includes/global/sections/page-header.html +8 -4
- package/dist/assets/themes/base/_layouts/backend/pages/dashboard/index.html +24 -24
- package/dist/assets/themes/base/_layouts/frontend/pages/about.html +10 -10
- package/dist/assets/themes/base/_layouts/frontend/pages/account/index.html +35 -35
- package/dist/assets/themes/base/_layouts/frontend/pages/alternatives/index.html +4 -4
- package/dist/assets/themes/base/_layouts/frontend/pages/auth/signin.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/auth/signup.html +4 -4
- package/dist/assets/themes/base/_layouts/frontend/pages/contact.html +3 -3
- package/dist/assets/themes/base/_layouts/frontend/pages/download.html +34 -33
- package/dist/assets/themes/base/_layouts/frontend/pages/extension/index.html +11 -11
- package/dist/assets/themes/base/_layouts/frontend/pages/legal/document.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/status.html +1 -1
- package/dist/assets/themes/base/_layouts/frontend/pages/team/index.html +9 -7
- package/dist/assets/themes/base/_layouts/frontend/pages/team/member.html +5 -3
- package/dist/assets/themes/base/_sections/about/letter/section.html +1 -1
- package/dist/assets/themes/base/_sections/about/letter/section.json5 +4 -4
- package/dist/assets/themes/base/_sections/marketing/bento/section.html +1 -1
- package/dist/assets/themes/base/_sections/marketing/bento/section.json5 +15 -15
- package/dist/assets/themes/base/_sections/marketing/cta/section.json5 +1 -1
- package/dist/assets/themes/base/_sections/marketing/hero/section.html +6 -6
- package/dist/assets/themes/base/_sections/marketing/hero/section.json5 +10 -10
- package/dist/assets/themes/base/_sections/marketing/product-demo/section.html +1 -1
- package/dist/assets/themes/base/_sections/marketing/product-demo/section.json5 +2 -2
- package/dist/assets/themes/base/_sections/marketing/stats/section.html +1 -1
- package/dist/assets/themes/base/_sections/marketing/stats/section.json5 +5 -5
- package/dist/assets/themes/base/_sections/marketing/trusted-by/section.html +1 -1
- package/dist/assets/themes/base/_sections/marketing/trusted-by/section.json5 +2 -2
- package/dist/assets/themes/neobrutalism/_layouts/frontend/pages/index.html +10 -10
- package/dist/assets/themes/newsflash/_layouts/frontend/pages/index.html +10 -10
- package/dist/assets/themes/newsflash/_sections/marketing/desks/section.html +2 -2
- package/dist/assets/themes/newsflash/_sections/marketing/desks/section.json5 +4 -4
- package/dist/build.js +69 -28
- package/dist/cli-run.js +20 -13
- package/dist/cli.js +12 -7
- package/dist/commands/build.js +0 -2
- package/dist/commands/deploy.js +116 -44
- package/dist/commands/finalize-release.js +5 -4
- package/dist/commands/launch.js +12 -7
- package/dist/commands/lib/deploy-precheck.js +66 -34
- package/dist/commands/lib/ensure-target.js +71 -11
- package/dist/commands/package.js +0 -1
- package/dist/commands/publish.js +11 -4
- package/dist/commands/release.js +99 -252
- package/dist/commands/runner.js +42 -5
- package/dist/commands/sign-windows.js +46 -15
- package/dist/commands/test.js +4 -3
- package/dist/commands/validate-certs.js +291 -115
- package/dist/config/page-template.html +4 -0
- package/dist/defaults/.github/workflows/build.yml +144 -64
- package/dist/defaults/AGENTS.md +3 -2
- package/dist/defaults/_.gitignore +4 -2
- package/dist/defaults/config/certs/README.md +25 -45
- package/dist/defaults/config/omega.json5 +66 -32
- package/dist/defaults/hooks/deploy/pre.js +10 -0
- package/dist/defaults/src/assets/scss/main.scss +12 -2
- package/dist/defaults/src/integrations/tray/index.js +1 -1
- package/dist/gulp/main.js +13 -25
- package/dist/gulp/tasks/audit.js +18 -6
- package/dist/gulp/tasks/build-config.js +181 -60
- package/dist/gulp/tasks/bundle.js +108 -36
- package/dist/gulp/tasks/release.js +86 -4
- package/dist/gulp/tasks/sass.js +11 -0
- package/dist/hooks/lib/notarize-tools.js +137 -0
- package/dist/hooks/notarize-artifacts.js +57 -0
- package/dist/hooks/notarize.js +59 -8
- package/dist/lib/auth-persistence.js +25 -0
- package/dist/lib/client-bridge.js +11 -8
- package/dist/lib/deep-link.js +15 -8
- package/dist/lib/protocol.js +7 -1
- package/dist/lib/restart-manager/install.js +6 -3
- package/dist/lib/sign-helpers/auto-unlock.js +65 -27
- package/dist/lib/sign-helpers/console-lock.js +34 -0
- package/dist/lib/sign-helpers/exec-with-limit.js +68 -0
- package/dist/lib/sign-helpers/resolve-icons.js +6 -4
- package/dist/lib/tray.js +7 -6
- package/dist/main.js +16 -0
- package/dist/preload.js +8 -0
- package/dist/renderer.js +16 -4
- package/dist/runner/job-started.js +104 -0
- package/dist/test/fixtures/consumer-app/config/omega.json5 +7 -0
- package/dist/test/fixtures/consumer-app/package.json +1 -1
- package/dist/test/fixtures/consumer-app/src/assets/js/components/main/index.js +7 -1
- package/dist/test/harness/main-entry.js +2 -1
- package/dist/test/harness/renderer-preload.js +12 -3
- package/dist/test/runners/boot.js +101 -11
- package/dist/test/runners/electron.js +1 -1
- package/dist/test/suites/boot/consumer-app-boots.test.js +54 -0
- package/dist/test/suites/build/audit.test.js +45 -6
- package/dist/test/suites/build/auth-persistence-resolve.test.js +119 -0
- package/dist/test/suites/build/auto-unlock.test.js +105 -0
- package/dist/test/suites/build/boot-runner-timeout.test.js +253 -0
- package/dist/test/suites/build/brand-scss.test.js +106 -0
- package/dist/test/suites/build/build-config.test.js +146 -36
- package/dist/test/suites/build/build-json-bake.test.js +245 -0
- package/dist/test/suites/build/build-verbs.test.js +48 -15
- package/dist/test/suites/build/build-workflow-jobs.test.js +190 -0
- package/dist/test/suites/build/cli.test.js +32 -10
- package/dist/test/suites/build/config-schema.test.js +4 -4
- package/dist/test/suites/build/console-lock.test.js +51 -0
- package/dist/test/suites/build/defaults-scaffold.test.js +71 -2
- package/dist/test/suites/build/deploy-direct.test.js +241 -0
- package/dist/test/suites/build/deploy-dispatch.test.js +287 -0
- package/dist/test/suites/build/deploy-hook.test.js +169 -0
- package/dist/test/suites/build/ensure-target.test.js +14 -2
- package/dist/test/suites/build/env-delivery.test.js +19 -10
- package/dist/test/suites/build/env-watch.test.js +18 -7
- package/dist/test/suites/build/esm-only-dependency.test.js +127 -0
- package/dist/test/suites/build/exec-with-limit.test.js +53 -0
- package/dist/test/suites/build/finalize-release.test.js +2 -2
- package/dist/test/suites/build/get-config.test.js +120 -8
- package/dist/test/suites/build/github-utils.test.js +12 -6
- package/dist/test/suites/build/license-stamp.test.js +6 -4
- package/dist/test/suites/build/manager.test.js +88 -68
- package/dist/test/suites/build/manifest-deps.test.js +116 -0
- package/dist/test/suites/build/merge-line-files.test.js +27 -4
- package/dist/test/suites/build/notarize-artifacts.test.js +135 -0
- package/dist/test/suites/build/notarize-tools.test.js +38 -0
- package/dist/test/suites/build/notarize.test.js +207 -0
- package/dist/test/suites/build/release-pipeline.test.js +38 -60
- package/dist/test/suites/build/release-skipped-upload.test.js +107 -0
- package/dist/test/suites/build/resolve-icons.test.js +35 -35
- package/dist/test/suites/build/runner-job-guard.test.js +182 -0
- package/dist/test/suites/build/runner.test.js +25 -2
- package/dist/test/suites/build/sentry.test.js +8 -3
- package/dist/test/suites/build/setup-scripts.test.js +3 -0
- package/dist/test/suites/build/sign-windows.test.js +92 -8
- package/dist/test/suites/build/test-stealth.test.js +17 -11
- package/dist/test/suites/build/url-helpers.test.js +37 -17
- package/dist/test/suites/build/validate-certs.test.js +428 -55
- package/dist/test/suites/build/validate-config.test.js +3 -3
- package/dist/test/suites/main/auth-flow.test.js +12 -0
- package/dist/test/suites/main/auth-persistence.test.js +14 -17
- package/dist/test/suites/main/auto-updater.test.js +2 -2
- package/dist/test/suites/main/boot-sequence.test.js +1 -1
- package/dist/test/suites/main/client-bridge.integration.test.js +5 -82
- package/dist/test/suites/main/client-bridge.test.js +19 -6
- package/dist/test/suites/main/deep-link.test.js +54 -0
- package/dist/test/suites/main/startup-paths-and-ua.test.js +1 -1
- package/dist/test/suites/main/url-helpers.test.js +81 -72
- package/dist/test/suites/renderer/cross-context-helpers.test.js +19 -16
- package/dist/utils/build-pipeline.js +10 -10
- package/dist/utils/github.js +12 -51
- package/dist/utils/load-env.js +66 -0
- package/dist/utils/mode-helpers.js +43 -111
- package/dist/utils/platform.js +37 -0
- package/dist/utils/runner-env.js +2 -1
- package/dist/utils/runner-job-guard.js +149 -0
- package/dist/utils/ship-keys.js +52 -0
- package/dist/utils/test-stealth.js +5 -3
- package/dist/utils/url-helpers.js +33 -17
- package/dist/vendor/config/bundle-id.js +53 -0
- package/dist/vendor/config/client-config.js +141 -0
- package/dist/vendor/config/company.js +334 -15
- package/dist/vendor/config/dev-facts.js +48 -0
- package/dist/vendor/config/env-delivery.js +231 -9
- package/dist/vendor/config/env-retired.js +137 -0
- package/dist/vendor/config/env-rules.js +22 -3
- package/dist/vendor/config/env-schema.js +234 -117
- package/dist/vendor/config/env.js +55 -26
- package/dist/vendor/config/environment.js +189 -0
- package/dist/vendor/config/hooks.js +13 -11
- package/dist/vendor/config/index.js +121 -44
- package/dist/vendor/config/load.js +366 -115
- package/dist/vendor/config/merge.js +2 -2
- package/dist/vendor/config/order.js +3 -3
- package/dist/vendor/config/platforms.js +276 -0
- package/dist/vendor/config/repo.js +226 -104
- package/dist/vendor/config/retired-keys.js +232 -27
- package/dist/vendor/config/schema.js +525 -99
- package/dist/vendor/config/site-global.js +63 -53
- package/dist/vendor/config/targets.js +187 -0
- package/dist/vendor/config/validate.js +119 -59
- package/dist/vendor/devkit/argv.js +118 -0
- package/dist/vendor/devkit/attach-log-file.js +21 -13
- package/dist/vendor/devkit/brand-tokens.js +278 -0
- package/dist/vendor/devkit/brand-version.js +264 -0
- package/dist/vendor/devkit/build-json.js +91 -0
- package/dist/vendor/devkit/bundle.js +48 -0
- package/dist/vendor/devkit/certificate-expiry.js +108 -0
- package/dist/vendor/devkit/certs.js +16 -194
- package/dist/vendor/devkit/ci-workflows.js +124 -8
- package/dist/vendor/devkit/cli-router.js +3 -3
- package/dist/vendor/devkit/defaults-engine.js +69 -7
- package/dist/vendor/devkit/deploy-follow.js +297 -0
- package/dist/vendor/devkit/deploy-precheck.js +23 -8
- package/dist/vendor/devkit/deploy-record.js +11 -27
- package/dist/vendor/devkit/deploy-snapshot.js +661 -0
- package/dist/vendor/devkit/deploy.js +445 -75
- package/dist/vendor/devkit/git-auth.js +73 -0
- package/dist/vendor/devkit/git-remote.js +95 -0
- package/dist/vendor/devkit/github-repo.js +290 -0
- package/dist/vendor/devkit/local.js +47 -0
- package/dist/vendor/devkit/merge-line-files.js +23 -16
- package/dist/vendor/devkit/omega-bin.js +18 -3
- package/dist/vendor/devkit/pack-local.js +391 -0
- package/dist/vendor/devkit/preludes/index.js +120 -0
- package/dist/vendor/devkit/preludes/origin-heal.js +156 -0
- package/dist/vendor/devkit/service-account.js +43 -0
- package/dist/vendor/devkit/ship-plan.js +112 -0
- package/dist/vendor/devkit/signing-env.js +180 -0
- package/dist/vendor/devkit/signing-tree.js +92 -0
- package/dist/vendor/devkit/target-seams.js +142 -0
- package/dist/vendor/devkit/target-secrets.js +235 -50
- package/dist/vendor/devkit/test/esm-only-fixture.js +48 -0
- package/dist/vendor/devkit/test/fixtures/esm-only-package/browser.js +19 -0
- package/dist/vendor/devkit/test/fixtures/esm-only-package/index.js +20 -0
- package/dist/vendor/devkit/test/fixtures/esm-only-package/package.json +13 -0
- package/dist/vendor/monitoring/env.js +20 -10
- package/dist/vendor/monitoring/main.js +1 -1
- package/dist/vendor/monitoring/preload.js +1 -1
- package/dist/vendor/monitoring/renderer.js +1 -1
- package/docs/analytics.md +1 -1
- package/docs/auto-updater.md +5 -5
- package/docs/boot-sequence.md +1 -1
- package/docs/build-system.md +15 -7
- package/docs/client-bridge.md +9 -7
- package/docs/config-schema.md +4 -4
- package/docs/css.md +8 -2
- package/docs/deep-link.md +12 -4
- package/docs/environment-detection.md +32 -24
- package/docs/hooks.md +3 -1
- package/docs/icons.md +7 -7
- package/docs/index.md +61 -23
- package/docs/installer-options.md +24 -21
- package/docs/logging.md +5 -5
- package/docs/releasing.md +25 -17
- package/docs/runner.md +40 -5
- package/docs/shared/brands.md +12 -6
- package/docs/shared/breaking-changes.md +375 -21
- package/docs/shared/config.md +757 -199
- package/docs/shared/deploys.md +194 -91
- package/docs/shared/icons.md +18 -0
- package/docs/shared/local-dev.md +24 -6
- package/docs/shared/logging.md +9 -6
- package/docs/shared/monitoring.md +27 -13
- package/docs/shared/publishing.md +3 -3
- package/docs/shared/rulings.md +2 -2
- package/docs/shared/testing.md +1 -1
- package/docs/shared/theming.md +26 -1
- package/docs/shared/translation.md +49 -7
- package/docs/shared/updates.md +1 -1
- package/docs/signing.md +59 -33
- package/docs/test-framework.md +10 -5
- package/docs/themes.md +15 -1
- package/package.json +18 -12
- package/bin/omega-desktop +0 -2
- package/dist/commands/push-secrets.js +0 -141
- package/dist/test/suites/build/deliver-certs.test.js +0 -95
- package/dist/test/suites/build/derive-signing-env.test.js +0 -122
- package/dist/test/suites/build/push-secrets.test.js +0 -226
- package/dist/test/suites/build/resolve-signing-cert.test.js +0 -342
- package/dist/utils/deliver-certs.js +0 -69
- package/dist/utils/derive-signing-env.js +0 -56
- package/dist/utils/resolve-signing-cert.js +0 -175
- package/dist/vendor/config/desktop-artifacts.js +0 -110
- package/dist/vendor/config/instances.js +0 -208
- /package/dist/defaults/config/icons/{macos → mac}/dmg.png +0 -0
- /package/dist/defaults/config/icons/{macos → mac}/icon.png +0 -0
- /package/dist/defaults/config/icons/{macos → mac}/tray.png +0 -0
package/docs/index.md
CHANGED
|
@@ -30,7 +30,7 @@ OMEGA Desktop (@omega.js/desktop) is a comprehensive framework for building mode
|
|
|
30
30
|
3. `npm start` — dev (gulp → esbuild → electron .)
|
|
31
31
|
4. `npm run build` — local production build (compiles bundles only, no installer)
|
|
32
32
|
5. `npm run package:quick` — fast packaged build for the host platform/arch only (~30s, skips DMG/zip/universal/notarize). Smoke-test packaged-mode behavior locally. Quick mode runs end-to-end (#117) and means exactly ONE thing since [#737](https://github.com/Omega-JS-Stack/omega/issues/737): the trimmed electron-builder phase. `clean` no longer keeps `dist/` and `release/` for it — the "next run is incremental" that justified keeping them was never true (every bundle was rebuilt anyway), and a cold esbuild bundle of all three targets is ~1s.
|
|
33
|
-
6. `npm run package
|
|
33
|
+
6. `npm run package`: full local production package, of whatever the `platforms` declaration says the brand ships (by default DMG/zip on mac, NSIS on windows, deb+AppImage+snap on linux). ~3min on mac.
|
|
34
34
|
7. `npm run release` — signed + published release (requires certs)
|
|
35
35
|
8. `npx omega test` — runs the project's test suites (bare consumer runs never include the framework corpus)
|
|
36
36
|
- `npx omega test build/config` — run project tests by path (relative to `test/`)
|
|
@@ -108,37 +108,74 @@ All three ship sensible default templates and share a unified id-path API (`.fin
|
|
|
108
108
|
|
|
109
109
|
### Icons
|
|
110
110
|
|
|
111
|
-
Convention-only. Drop PNGs at `config/icons/<platform>/<slot>.png` (
|
|
111
|
+
Convention-only. Drop PNGs at `config/icons/<platform>/<slot>.png` (`mac`, `windows`, `linux`: the one vocabulary, #867) or `config/icons/global/<slot>.png` (universal fallback). Resolution per slot: platform → global → (Linux only) windows → bundled default. Ship @2x native size only; @omega.js/desktop downscales the @1x sibling via sharp. macOS tray input is `tray.png` (consumer-friendly); @omega.js/desktop renames the dist output to `trayTemplate.png` for OS dark-mode auto-inversion. No `app.icons` config block. See [docs/shared/icons.md](../docs/icons.md).
|
|
112
112
|
|
|
113
113
|
### Build system
|
|
114
114
|
|
|
115
|
-
prepare-package copies `src/` → `dist/`; gulp orchestrates esbuild (3 bundles, all bundled) + electron-builder. The bundler is @omega.js/devkit's ONE `bundle()` wrapper since [#737](https://github.com/Omega-JS-Stack/omega/issues/737)
|
|
115
|
+
prepare-package copies `src/` → `dist/`; gulp orchestrates esbuild (3 bundles, all bundled) + electron-builder. The bundler is @omega.js/devkit's ONE `bundle()` wrapper since [#737](https://github.com/Omega-JS-Stack/omega/issues/737): webpack and its loaders are gone from desktop, and the task went with the name: `src/gulp/tasks/bundle.js`, gulp task `bundle`, log tag `[@omega.js/desktop:bundle]`. An ESM-only dependency bundles into main and preload like any other: both are CommonJS output, where the wrapper keeps `import.meta.url` answering ([#906](https://github.com/Omega-JS-Stack/omega/issues/906)), so a package that opens a require of its own with `createRequire(import.meta.url)` runs bundled instead of throwing at boot. `gulp/build-config` generates `dist/electron-builder.yml` + `dist/config/entitlements.mac.plist` from @omega.js/desktop defaults + consumer config. What the app SHIPS is one declaration, `platforms.<mac|windows|linux>.formats.<dmg|nsis|deb|appimage|snap>` ([#867](https://github.com/Omega-JS-Stack/omega/issues/867)): presence = enabled, every format defaults on, `false` drops one, and the electron-builder target lists derive from it. Artifact names carry NO version (`<Product>-mac-dmg.dmg`) and come from @omega.js/config's `platforms.js`: the ONE table the website's `/download/<platform>/<format>` URLs read too ([#620](https://github.com/Omega-JS-Stack/omega/issues/620)), so `/releases/latest/download/<asset>` is permanent and a desktop release never touches the site. The `.deb` target's two required metadata facts come from the BRAND ([#872](https://github.com/Omega-JS-Stack/omega/issues/872)): `linux.maintainer` from `brand.name` plus `brand.contact.email`, and the homepage from `brand.url` through `extraMetadata` (electron-builder reads it off the app manifest, never off its own config); a brand missing either fails at config generation, naming the key, instead of at package time after the AppImage has already uploaded. Strategy-pluggable Windows signing (`platforms.windows.signing.strategy`: `self-hosted` | `cloud` | `local`), whose value is also what the env schema gates each signing credential on, so the walk asks for one strategy's set and no other's. See [docs/releasing.md](../docs/releasing.md) for the whole release contract (one public repo, always `<brand.id>-releases`, the survivor + never-reuse rules, the asset table), [docs/build-system.md](../docs/build-system.md), [docs/installer-options.md](../docs/installer-options.md), [docs/signing.md](../docs/signing.md).
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
The ACCENT comes from the config, not from a literal a consumer keeps in sync
|
|
118
|
+
([#912](https://github.com/Omega-JS-Stack/omega/issues/912)): `gulp/sass` renders
|
|
119
|
+
`dist/assets/scss/_brand.scss` from `brand.color` before every compile, carrying
|
|
120
|
+
`$primary` (what Bootstrap's color ramp derives from) plus a `ramp` mixin of the
|
|
121
|
+
runtime `--omega-accent` family, and the scaffold's `main.scss` reads both,
|
|
122
|
+
`@use 'brand';` above the framework import and `@include brand.ramp;` below it
|
|
123
|
+
(below, because a used module's css emits at its load position, ahead of the
|
|
124
|
+
token sheet the ramp has to beat). A deliberate divergence puts a literal back in
|
|
125
|
+
place of `brand.$primary`. Same renderer @omega.js/extension writes and the same
|
|
126
|
+
ramp web inlines into its `<head>`: [shared/theming.md](shared/theming.md).
|
|
118
127
|
|
|
119
|
-
|
|
128
|
+
### Signing material is READ IN PLACE, and the paths derive ONCE ([#891](https://github.com/Omega-JS-Stack/omega/issues/891))
|
|
120
129
|
|
|
121
|
-
|
|
130
|
+
Nothing copies signing material into a target. The signing tree is read where it lives, in TWO tiers ([#892](https://github.com/Omega-JS-Stack/omega/issues/892), `@omega.js/devkit/signing-tree`): the COMPANY's `<company tree>/.omega/certificates/apple/` first when the brand names one with `company: { id }` and that company is on this machine ([#677](https://github.com/Omega-JS-Stack/omega/issues/677)), the brand's own second, so a brand of a company signs with the company's material and falls back to its own only for a file the company tree does not hold. The manager's disperse `certs` operation, devkit's `deliverCerts()` and desktop's `deliver-certs.js` are all gone with the copy: one fact, one home, and no dispersed duplicate a build could silently sign with after the tree moved on.
|
|
131
|
+
|
|
132
|
+
`CSC_LINK` and `APPLE_API_KEY` DERIVE from that tree, ONCE, at the desktop env load ([src/utils/load-env.js](../src/utils/load-env.js), over `@omega.js/devkit/signing-env`), which both boots call: the CLI (`src/cli.js`) and gulp (`src/gulp/main.js`, its own process under `npm start`). `CSC_LINK` takes the tree's `certificates/DEVELOPER_ID_APPLICATION_G2.p12` when `CSC_KEY_PASSWORD` OPENS it, `APPLE_API_KEY` takes its `AuthKey_<APPLE_API_KEY_ID>.p8`, and both are ABSOLUTE paths. An explicit env value always wins, a file that exists and cannot be used prints one line and leaves the key unset (electron-builder's Keychain discovery stays the default), and no provisioning profile derives at all: Developer ID is direct distribution and needs none. The build, `validate-certs` and the deploy precheck's secret publish then READ that one answer, which is what ended the split where the build signed fine and `validate-certs` stopped the deploy on `Found .p12 in config/certs/ but CSC_LINK env var is not set`.
|
|
133
|
+
|
|
134
|
+
`CSC_LINK` and `APPLE_API_KEY` each take three shapes, a path, an https URL, or the file itself as inline base64, and the `validate-certs` precheck reports the non-file shapes instead of statting them ([#872](https://github.com/Omega-JS-Stack/omega/issues/872)). ON THE RUNNER the target's `config/certs/` is still the decode target: the generated `build.yml` writes the pushed base64 secrets back to disk there and points both keys at the files. It decodes each mac secret only when that secret EXISTS, and a MISSING one exits 1 naming `omega deploy` (whose precheck pushes them): a mac build `omega deploy` ships is always signed and notarized, so the leg stops instead of publishing an unsigned app. The linux and windows legs blank both keys outright, and their `validate-certs` run skips the mac rungs entirely with one line ([#891](https://github.com/Omega-JS-Stack/omega/issues/891)), because no leg but the mac one signs for mac: rungs about credentials that leg deliberately blanked are two warnings nobody can act on.
|
|
135
|
+
|
|
136
|
+
**Signing, and then the PROOF** ([#891](https://github.com/Omega-JS-Stack/omega/issues/891)). Every rung of the mac lane fails loudly, and the last two prove their work instead of assuming it:
|
|
137
|
+
|
|
138
|
+
| Rung | What it refuses to pass |
|
|
139
|
+
|---|---|
|
|
140
|
+
| `validate-certs` (deploy precheck, and inside `publish`) | STRICT on macOS: an unset `CSC_LINK` or `APPLE_API_KEY` (which means the signing TREE holds no such file, and the line names both tier paths it looked in), a `CSC_LINK` pointing at a missing file, no `CSC_KEY_PASSWORD`, a `.p12` the password will not open, no Keychain `Developer ID Application` identity on a run whose `CSC_LINK` names no certificate (electron-builder imports a `CSC_LINK` `.p12` into its OWN temporary keychain, so the login keychain is only asked when discovery is what will sign), or an EXPIRED certificate. Under 30 days is a warning: it still signs. The unsigned findings are ERRORS only when the config declares `certificates.providers.apple`, the same gate the env schema's `requiredWhen` uses |
|
|
141
|
+
| `push-secrets` (the precheck step, never a verb) | A signing key the schema marks required for this brand (the mac set once `certificates.providers.apple` is declared) that the `.env` cascade resolves EMPTY stops the deploy listing every one, and publishes NOTHING: the step is `fatal` on all four frameworks. `CSC_LINK` and `APPLE_API_KEY` are DERIVED from the signing tree first, so the refusal means the artifact is missing, and its line names both tier paths plus `omega manage --service certificates` rather than a path to paste |
|
|
142
|
+
| `afterSign` hook ([src/hooks/notarize.js](../src/hooks/notarize.js)) | A non-darwin build is the ONE skip. Missing `APPLE_API_*` THROWS; an app whose `codesign -dv` report carries no `Developer ID Application` authority THROWS (notarytool rejects the ad-hoc signature an identity-less build leaves behind). After notarizing it runs `xcrun stapler staple`, then PROVES it with `xcrun stapler validate` and `spctl --assess --type execute -vv`, and throws unless both accept |
|
|
143
|
+
| `artifactBuildCompleted` hook ([src/hooks/notarize-artifacts.js](../src/hooks/notarize-artifacts.js)) | Each `.dmg`, BEFORE electron-builder uploads it (this hook is awaited before the `artifactCreated` the publisher listens on; `afterAllArtifactBuild` fires after every upload is queued, and run 34738410986 published an unstapled image from there): `xcrun notarytool submit --wait` with the same API key triple, `stapler staple`, `stapler validate`, `spctl --assess --type open --context context:primary-signature -vv`. The ticket stapled to the app INSIDE an image is not stapled to the image, and a user's Mac assesses the image first, by the image's OWN signature: the generated config sets electron-builder's `dmg.sign`, so the image carries the Developer ID signature that assessment reads (an unsigned image is refused after a clean notarize and staple) |
|
|
144
|
+
|
|
145
|
+
Both hooks run every command through one small runner (`src/hooks/lib/notarize-tools.js`) that a test replaces with a fake `xcrun`/`spctl`, and each one reads the tool's own report, stdout and stderr whatever the exit code: anything but the words that mean success throws with the tool's own verdict in the message, so the release step never runs on an artifact Gatekeeper would refuse.
|
|
122
146
|
|
|
123
147
|
All three bundles strip `@dev-only` blocks in production builds — code between `/* @dev-only:start */` and `/* @dev-only:end */` is cut from the bundle, so dev warnings and simulation hooks (@omega.js/client's and the vendored themes' included) never ship. Dev builds keep them. The markers and the cut are one home, `@omega.js/devkit/strip-dev-blocks`; desktop, web and @omega.js/extension all reach it through the same `bundle()` composition (production builds only).
|
|
124
148
|
|
|
125
149
|
### Config flow
|
|
126
150
|
|
|
127
|
-
`config/omega.json5` (JSON5, in consumer; shared sections top-level + desktop settings under `targets.desktop`) → `Manager.getConfig()` (resolves via `@omega.js/config
|
|
151
|
+
`config/omega.json5` (JSON5, in consumer; shared sections top-level + desktop settings under `targets.desktop`) → `Manager.getConfig()` (resolves via `@omega.js/config`: `targets.desktop` overlays the top level, brand-monorepo walk-up included), then applies derived defaults: `app.appId` ← `<certificates.providers.apple.bundleIdPrefix>.<brand.id>` with the brand id's dashes as dots, the very id the certificates service registers ([#909](https://github.com/Omega-JS-Stack/omega/issues/909); no prefix declared, and it falls back to the reverse-domain of `brand.url`, then `app.<brand.id>`), `app.productName` ← `brand.name`) → injected into the NODE bundles (main, preload) at build time as an esbuild `define` of `OMEGA_BUILD_JSON` plus a banner that assigns the same literal to `globalThis`, and written for the RENDERER as the ONE `dist/build.js` every view's shell loads with its first script tag ([#743](https://github.com/Omega-JS-Stack/omega/issues/743), the same file and the same load order web and the extension use). Runtime reads `OMEGA_BUILD_JSON.config` first (authoritative in packaged apps); dev falls back to resolving from disk.
|
|
152
|
+
|
|
153
|
+
The wrapper is the ONE shape every OMEGA browser surface bakes ([#894](https://github.com/Omega-JS-Stack/omega/issues/894)): `{ config, package, mode, license, builtAt }`, with the build's own facts outside `config` and never part of the client contract. What goes INSIDE `config` differs by who reads the bundle:
|
|
154
|
+
|
|
155
|
+
| Bundle | `config` |
|
|
156
|
+
|---|---|
|
|
157
|
+
| main, preload | the WHOLE resolved config, as a `define` + banner in their own bundles. The main process BOOTS from it (a packaged app's `config/omega.json5` is inside the asar), so `platforms`, `startup`, `autoUpdate`, `releases` and the rest have to be there. Both are Node, neither is a public surface |
|
|
158
|
+
| renderer | the browser subset, `clientConfig(resolved)` from `@omega.js/config` (the config guide's "The browser subset"), written to `dist/build.js` and loaded by the page template as `../../build.js` ahead of the view's own bundle. A renderer is a public surface: its bundle is readable from DevTools, so the GCP account facts, the signing certificates and the account admins are not in it, and the bundle itself carries no copy of the snapshot at all |
|
|
159
|
+
|
|
160
|
+
The build facts include `runtime: 'electron'` ([#896](https://github.com/Omega-JS-Stack/omega/issues/896)): a packaged renderer is a browser with no Electron globals of its own, so @omega.js/client's sniff would answer `'web'` without the baked fact. `mode` is the three keys every surface records, `{ environment, build, publish }`; desktop's own `server` verdict stays inside `Manager.getMode()`.
|
|
161
|
+
|
|
162
|
+
Both halves carry the same name, so `renderer.js` hands `OMEGA_BUILD_JSON.config` to `@omega.js/client` exactly as an extension page and a web page do.
|
|
128
163
|
|
|
129
164
|
Required fields: `brand.id` + `brand.name`. Everything else has defaults. See [docs/installer-options.md](../docs/installer-options.md) for the full defaults table.
|
|
130
165
|
|
|
131
166
|
### Schema validation
|
|
132
167
|
|
|
133
|
-
Every field in `config/omega.json5` is declared in `@omega.js/config
|
|
168
|
+
Every field in `config/omega.json5` is declared in `@omega.js/config`: the shared OMEGA schema plus the desktop refinements (`TARGET_SCHEMAS.desktop`), vendored into `dist/vendor/config/` and exposed to consumers as `require('@omega.js/desktop/config')`. Runs at boot (hard-fails `manager.initialize()` if invalid) AND in `gulp/audit` (plus build-pipeline extras). The audit reports the validator's WARNINGS too ([#911](https://github.com/Omega-JS-Stack/omega/issues/911)): `omega build` prints each one and counts it (`audit ok (1 warning)`), so a key the schema does not declare, which is exactly what a typo looks like, is seen at build time instead of dropped. See [docs/config-schema.md](../docs/config-schema.md).
|
|
134
169
|
|
|
135
170
|
### Cross-context helpers
|
|
136
171
|
|
|
137
|
-
Four Managers (main / renderer / preload / build-time) all mix in shared helpers via `attachTo(Manager)`: `isDevelopment()`, `isProduction()`, `isTesting()`, `getWebsiteUrl()`, `getEnvironment()`, `getFunctionsUrl()`, `getApiUrl()`, `getAuthUrl()` (the sign-in URL that round-trips an auth token back into the app via the `auth/token` deep link
|
|
172
|
+
Four Managers (main / renderer / preload / build-time) all mix in shared helpers via `attachTo(Manager)`: `isDevelopment()`, `isProduction()`, `isTesting()`, `getWebsiteUrl()`, `getEnvironment()`, `getFunctionsUrl()`, `getApiUrl()`, `getAuthUrl()` (the sign-in URL that round-trips an auth token back into the app via the `auth/token` deep link; never link the bare `/signin` page; apps launch it via **`manager.openAuthFlow()`** (main), which opens the user's REAL default browser and, in dev/test where the custom scheme isn't OS-registered, swaps the final hop for a one-shot nonce-checked loopback listener (RFC 8252) feeding the same deep-link pipeline, `lib/auth-flow.js`). Use these instead of grepping `process.env` ad-hoc. `getEnvironment()` returns `'development' | 'testing' | 'production'` (mutually exclusive), and the three `is*()` checks DERIVE from it; gate side effects on the INTENTIONAL check (`isProduction()` for prod-only, `isDevelopment() || isTesting()` for local-or-test); never `!isDevelopment()`.
|
|
173
|
+
|
|
174
|
+
**The environment four are `@omega.js/config`'s ONE module** ([#817](https://github.com/Omega-JS-Stack/omega/issues/817), the contract in full: [docs/shared/config.md](shared/config.md)): `src/utils/mode-helpers.js` re-exports them beside desktop's own `getVersion()`, so all four frameworks hang the identical functions. They read ONE input and never guess: `OMEGA_ENVIRONMENT` in Node, and the baked `OMEGA_BUILD_JSON.config.environment` in a renderer (which has none). Nothing sniffs `app.isPackaged` or `NODE_ENV` any more, and a context with neither input throws by name rather than defaulting; the old default here was `production`, so a plain `npm start` bundled itself as a production artifact while @omega.js/extension's copy of the same function answered `development`. `src/build.js` names the input at load, from the lane (`OMEGA_BUILD_MODE` is production and wins over an inherited value; the test runners name `testing`; a bare dev boot is `development`), and `main.js` names it from the baked config for a packaged app that has no parent lane: a FALLBACK for the context with no input, never an override of a lane that named one ([#925](https://github.com/Omega-JS-Stack/omega/issues/925)). A renderer has no `process` either, so the preload hands it the running word on `window.desktop.environment` and the renderer bootstrap applies it over the bake, which is how a test lane booting a production artifact answers `testing` in every context of that app. See [docs/environment-detection.md](../docs/environment-detection.md).
|
|
138
175
|
|
|
139
176
|
### Test framework
|
|
140
177
|
|
|
141
|
-
`npx omega test` discovers + runs framework suites (`<@omega.js/desktop>/dist/test/suites/**`) plus consumer suites (`<cwd>/test/**`). Four layers: **build** (plain Node), **main** (spawned Electron), **renderer** (hidden BrowserWindow), **boot** (consumer's actual built bundle for end-to-end smoke tests). The worked CONSUMER example is the playground desktop target's [`test/`](../../brands/omega
|
|
178
|
+
`npx omega test` discovers + runs framework suites (`<@omega.js/desktop>/dist/test/suites/**`) plus consumer suites (`<cwd>/test/**`). Four layers: **build** (plain Node), **main** (spawned Electron), **renderer** (hidden BrowserWindow), **boot** (consumer's actual built bundle for end-to-end smoke tests). The worked CONSUMER example is the playground desktop target's [`test/`](../../brands/playground-omega/targets/desktop/test) ([#811](https://github.com/Omega-JS-Stack/omega/issues/811)): a build suite over its resolved config and a boot suite over its real bundle, each asserting only what that project declares or wires. A renderer suite reaches the project's OWN views by declaring `view: '<name>'`, which runs it on the boot lane's built app so the page carries the project's real preload, IPC handlers and config ([#813](https://github.com/Omega-JS-Stack/omega/issues/813)). A test run never touches the OS keychain (auth persistence is `none` on every layer, whatever the brand declares) and a boot that produces no harness output inside the budget fails with the last `runtime.log` line instead of hanging the runner ([#907](https://github.com/Omega-JS-Stack/omega/issues/907)). See [docs/test-framework.md](../docs/test-framework.md), [docs/test-boot-layer.md](../docs/test-boot-layer.md).
|
|
142
179
|
|
|
143
180
|
### Test coverage
|
|
144
181
|
|
|
@@ -146,7 +183,7 @@ Every feature ships with tests at EVERY layer it has a surface in — logic (`bu
|
|
|
146
183
|
|
|
147
184
|
### Dev logs
|
|
148
185
|
|
|
149
|
-
Every gulp invocation tees stdout+stderr to `<projectRoot>/logs/dev.log` on `npm start` or `logs/build.log` on a production build/package (`OMEGA_BUILD_MODE=true`)
|
|
186
|
+
Every gulp invocation tees stdout+stderr to `<projectRoot>/logs/dev.log` on `npm start` or `logs/build.log` on a production build/package (`OMEGA_BUILD_MODE=true`), chosen by build mode, path via `OMEGA_LOG_FILE`; disable with `OMEGA_LOG_FILE=false`. `npx omega test` likewise tees its output to `<projectRoot>/logs/test.log`, and `omega deploy` (with `npm run release`, the dispatch it delegates to) streams the GH Actions run to `logs/deploy.log`. The packaged app's own `logs/runtime.log` (main + preload + renderer) sits beside them, and Windows signing appends `logs/signing.log`. When debugging via Claude, prefer `cat logs/dev.log` / `cat logs/test.log` over copy-pasting terminal scrollback; never restart the app to see output it already wrote. The runtime logger: [docs/logging.md](../docs/logging.md); the cross-framework tee contract and the full path table: [docs/shared/logging.md](shared/logging.md).
|
|
150
187
|
|
|
151
188
|
### CDP debugging (Claude ↔ Electron)
|
|
152
189
|
|
|
@@ -163,14 +200,13 @@ Every gulp invocation tees stdout+stderr to `<projectRoot>/logs/dev.log` on `npm
|
|
|
163
200
|
| `version` | print versions |
|
|
164
201
|
| `test` | run the project's test suites (`framework:` / `full:` reach the framework suite) |
|
|
165
202
|
| `update` | dependency freshness report (installed/wanted/latest + patch/minor/major, < 7-day releases QUARANTINED); `--apply` installs the safe set via npu, `--major` explicit. Aliases: `outdated`, `out`. See docs/shared/updates.md in the Omega repo |
|
|
166
|
-
| `deploy` |
|
|
203
|
+
| `deploy` | the deliberate-deploy verb (see docs/shared/deploys.md in the Omega repo): dispatch the composed `build.yml`, or with `--direct` run `omega publish --local` right here for the HOST platform, pinned by test to CI's own `release:local` step ([#865](https://github.com/Omega-JS-Stack/omega/issues/865)). A `--platforms` value the host cannot build refuses under `--direct`, because a cross-platform build is CI-only ([#872](https://github.com/Omega-JS-Stack/omega/issues/872)). A DISPATCH runs the NETWORK prechecks first: framework freshness, `validate-certs`, repo provisioning, the secrets push, the two SIGNING ones fatal ([#891](https://github.com/Omega-JS-Stack/omega/issues/891)); `--no-secrets` skips them all, and `--direct` never reaches them (a local deploy publishes no signing certs to the repo, #872). `--dry-run` RUNS the precheck too and sends nothing: the plan names the secret keys it would publish ([#895](https://github.com/Omega-JS-Stack/omega/issues/895)). |
|
|
167
204
|
| `logs [runtime|dev|build|test]` | read one of the project's log files, `runtime` by default (alias `log`) |
|
|
168
205
|
| `help` | command listing (router built-in; also `-h`/`--help`) |
|
|
169
|
-
| `build` | clean +
|
|
170
|
-
| `package` | clean +
|
|
171
|
-
| `publish` | certs
|
|
172
|
-
| `validate-certs` | check
|
|
173
|
-
| `push-secrets` | publish the schema's delivered set for desktop (values from the composed env, file-path secrets base64'd from disk) as GH Actions secrets, through the shared `gh` boundary web and the extension use — values on stdin, never logged, `gh auth login` the only credential. A CI run, an empty cascade, no remote, or a checkout that is not the brand's declared repo skips loudly. `--only=KEY,KEY` narrows; auto-runs as an `omega deploy` precheck |
|
|
206
|
+
| `build` | clean + `gulp build`, with `OMEGA_BUILD_MODE=true` set in-process |
|
|
207
|
+
| `package` | clean + the electron-builder package (`--quick` for host platform/arch only) |
|
|
208
|
+
| `publish` | ship-credential check + `validate-certs` (strict) + full sign + notarize + GH release upload (`OMEGA_IS_PUBLISH=true`); `--local` cleans first |
|
|
209
|
+
| `validate-certs` | check the derived signing env, the cert file and its expiry, the notarization key, the Keychain identity. The mac rungs run on the mac leg only (#891). Auto-runs as an `omega deploy` precheck |
|
|
174
210
|
| `sign-windows` | strategy-aware EV/cloud/local signer; emits JSONL events for `runner monitor` |
|
|
175
211
|
| `runner monitor` | tails `omega-signing.log` and pretty-prints signing events |
|
|
176
212
|
| `launch` | launch a packaged app with clean env (strips `ELECTRON_RUN_AS_NODE`); auto-discovers `release/<platform>-<arch>/<App>.app`. Aliases: `mgr open` |
|
|
@@ -179,7 +215,9 @@ Every gulp invocation tees stdout+stderr to `<projectRoot>/logs/dev.log` on `npm
|
|
|
179
215
|
|
|
180
216
|
See [docs/releasing.md](../docs/releasing.md) for the end-to-end flow.
|
|
181
217
|
|
|
182
|
-
**
|
|
218
|
+
**A publish refuses a declared format it has no credential for, before it builds** ([#867](https://github.com/Omega-JS-Stack/omega/issues/867)). `omega publish` (which CI runs too, as `npm run release:local`) opens with a `ship-keys` step: the brand's declaration says what ships, @omega.js/config's format table says what each format needs, and anything empty stops the verb in a second instead of after a build. The wording is the extension publish's, to the letter (both read devkit's `ship-plan`): the key, the declaration that requires it (`platforms.linux.formats.snap`), and the ONE walk that collects it, `omega manage --service publishing`. What is OWED is gated by the brand's own config, so a brand that never mentions the snap is never refused for `SNAPCRAFT_STORE_CREDENTIALS`, and the Windows set narrows to the configured `platforms.windows.signing.strategy`. A BUILD keeps its clean skip (`build-config` drops the snap target when the login is absent): a build puts nothing in front of users. Every `asset` format rides the releases repo; the snap is the one desktop `store` format, and the Snap Store registers its name with the same credentials that publish, so desktop has no listing id to collect and no manual step to print.
|
|
219
|
+
|
|
220
|
+
**The release verbs read the repo from CONFIG** ([#799](https://github.com/Omega-JS-Stack/omega/issues/799), [#883](https://github.com/Omega-JS-Stack/omega/issues/883)): `release` and `deploy` dispatch on the brand's SOURCE repo (`@omega.js/config`'s `sourceRepo`: `<brand.id>-omega` under `repo.org`), and `finalize-release`, the deploy precheck's provisioning and the electron-builder publish block all address the brand's ONE public releases repo (`releasesRepo`: always `<brand.id>-releases` under that same org, since `targets.desktop.releases.owner/repo` are retired and `releases: {}` is a presence switch alone). The precheck creates it public, with a first commit, through the ONE repo helper every OMEGA lane uses (`@omega.js/devkit/github-repo`'s `ensureRepo`). No git remote is read anywhere, so a target inside a brand monorepo stops targeting the repo it is nested in. The dispatched workflow is the one the scaffold wrote: `desktop-build.yml` at the brand root, `build.yml` standalone, named by the same `@omega.js/devkit/ci-workflows` helper web and the extension use. The `downloads:` mirror lane retired with it.
|
|
183
221
|
|
|
184
222
|
**`finalize-release` finds the release by LISTING, drafts included** ([#810](https://github.com/Omega-JS-Stack/omega/issues/810)): a draft carries no tag ref, so `repos.getReleaseByTag` answers with PUBLISHED releases only and 404'd on the very draft electron-builder had just created. Every run then made another draft for the same version (two v0.0.1 drafts on the playground's releases repo), and a full run would have split its assets across two of them while the `--publish` flip found neither. Both call sites (the signed-Windows upload and the flip) now read through one `findRelease` helper that paginates `repos.listReleases` and matches `tag_name`: the newest draft wins, since that is the one this run's publish step created; a published release answers when no draft carries the tag; and only a tag with neither leaves the upload step creating the draft a partial-platform run needs. Uploading an asset whose name is already on the release deletes the old one first, with one line naming the replacement, so re-running a version never collides.
|
|
185
223
|
|
|
@@ -194,14 +232,14 @@ See [docs/releasing.md](../docs/releasing.md) for the end-to-end flow.
|
|
|
194
232
|
|
|
195
233
|
## Development Workflow
|
|
196
234
|
|
|
197
|
-
- **🚫 NEVER use `npx omega ...` from the framework repo
|
|
235
|
+
- **🚫 NEVER use `npx omega ...` from the framework repo**: `npx omega` is for CONSUMER projects only (where the bin lives in `node_modules/.bin/`). From the framework repo, use `npm test`, `npm start`, etc. The `scripts` in `package.json` call `node bin/omega` directly. This applies to ALL four OMEGA frameworks (@omega.js/backend, UJM, @omega.js/extension, @omega.js/desktop).
|
|
198
236
|
- **🚫 NEVER run `npm start`** (consumer projects) — it's the user's long-running dev process. Assume it's already running; if it isn't, **instruct the user to run it** rather than running it yourself (running it again kills theirs). To see output, **read the `logs/*.log` files** (`dev.log`, `runtime.log`, `test.log`) — never tail/attach to the process. Running `npx omega test` is fine.
|
|
199
237
|
- **After editing files**, verify the gulp watcher recompiled successfully. Check for esbuild/sass errors in the console output. A change that breaks the build is not a completed change.
|
|
200
238
|
- **Live-test UI changes via CDP.** After code changes compile, use the `chrome-devtools-electron` MCP tools (screenshots, click, evaluate JS, console logs) to verify the change works in the running app. This is the primary way to confirm UI/renderer changes — type-checking and test suites verify code correctness, not feature correctness. See [docs/cdp-debugging.md](../docs/cdp-debugging.md) and `~/.claude/mcp-server/servers/chrome-devtools-electron/CLAUDE.md`.
|
|
201
239
|
|
|
202
240
|
## Supply-Chain Security
|
|
203
241
|
|
|
204
|
-
All `npm install` calls in CLI commands (`npx omega i`, `npx omega runner`, the peer-dependency step of every verb's `ensureTarget()`) route through the `safeInstall()` helper (`src/utils/safe-install.js`). It prefixes `sfw` (Socket Firewall) when installed — blocking confirmed malware at the network level before packages reach disk. Falls back to plain npm if sfw isn't available. CI workflows
|
|
242
|
+
All `npm install` calls in CLI commands (`npx omega i`, `npx omega runner`, the peer-dependency step of every verb's `ensureTarget()`) route through the `safeInstall()` helper (`src/utils/safe-install.js`). It prefixes `sfw` (Socket Firewall) when installed — blocking confirmed malware at the network level before packages reach disk. Falls back to plain npm if sfw isn't available. CI workflows get the firewall from Socket's own GitHub Action (`SocketDev/action`, firewall mode, pinned; it downloads the binary with the job's token and caches it, so a hosted runner's shared anonymous API quota never fails the step, [#871](https://github.com/Omega-JS-Stack/omega/issues/871)) and run `sfw npm ci`. The template carries only the `{{ installFirewall }}` token; the composer renders the step, once, from devkit's one pinned constant ([#872](https://github.com/Omega-JS-Stack/omega/issues/872)). It renders a Windows shim beside it, because the windows legs of the build force `shell: cmd` and cmd cannot execute the extension-less `sfw` the action caches ([docs/shared/deploys.md](shared/deploys.md)). Installs will **fail if sfw detects confirmed malware** in any package in the dependency tree; non-critical CVEs and quality warnings pass through.
|
|
205
243
|
|
|
206
244
|
## File Conventions
|
|
207
245
|
|
|
@@ -215,7 +253,7 @@ All `npm install` calls in CLI commands (`npx omega i`, `npx omega runner`, the
|
|
|
215
253
|
- **Lib structure — flat file vs directory split.** Default to flat `src/lib/<name>.js`. Split into a directory (`src/lib/<name>/{index,core,main,renderer,preload}.js`) ONLY when each Electron context has materially different logic. No lib is split today — `lib/sentry/` was the one, and it moved WHOLE into `@omega.js/monitoring` (#380) once the backend and the client needed the same policy. Don't split prophylactically.
|
|
216
254
|
- **Use `app.getAppPath()`, not `process.cwd()`, for runtime path resolution.** In a packaged app, `process.cwd()` is `/`. Use `require('./utils/app-root.js')()` — tries `app.getAppPath()` first, falls back to `process.cwd()` for tests/non-Electron contexts.
|
|
217
255
|
- **Zero-trust URL handling — `sanitizeURL` for `shell.openExternal` and friends.** Any dynamic URL passed to `shell.openExternal`, `BrowserWindow.loadURL`, `window.location.href =`, etc. MUST be gated through `require('./utils/sanitize-url.js')` first. Returns the URL unchanged when its protocol is `http:`/`https:`, and `''` for anything else (`javascript:`, `data:`, `file:`, `vbscript:`, `chrome:`, custom schemes). Canonical pattern: `const safe = sanitizeURL(url); if (safe) shell.openExternal(safe);`. Hardcoded URLs constructed entirely from internal constants (e.g. the restart-manager feed URLs built from schema-validated config in `lib/restart-manager/install.js`) bypass — not attacker-controllable. See `src/utils/sanitize-url.js` and the `js:patterns/xss-escaping` skill.
|
|
218
|
-
- **`ELECTRON_RUN_AS_NODE` is stripped at the CLI boundary.** When set, Electron silently runs as plain Node
|
|
256
|
+
- **`ELECTRON_RUN_AS_NODE` is stripped at the CLI boundary.** When set, Electron silently runs as plain Node: `app` is undefined, no BrowserWindow. The variable leaks from common parent processes (VS Code's Claude Code extension runs as a `node.mojom.NodeService` utility process with the var set). `src/cli-run.js` (the bin body every `bin/omega` invocation and every cross-framework dispatch runs) and `src/gulp/main.js` both `delete process.env.ELECTRON_RUN_AS_NODE` at the top.
|
|
219
257
|
|
|
220
258
|
## Doc-update parity
|
|
221
259
|
|
|
@@ -260,14 +298,14 @@ API references for each subsystem live in `docs/`. **Whenever you make a behavio
|
|
|
260
298
|
- [docs/themes.md](../docs/themes.md) — vendored classy + bootstrap themes, per-page CSS bundles, system-aware appearance (`manager.theme`)
|
|
261
299
|
- [docs/tooltips.md](../docs/tooltips.md) — Bootstrap JS ships in @omega.js/desktop (prebuilt bundle, Popper inlined): zero-setup auto-initialized tooltips, `window.bootstrap` namespace
|
|
262
300
|
- [docs/css.md](../docs/css.md) — SCSS architecture: main entry, theme `@use` config, per-window bundles, Bootstrap-first
|
|
263
|
-
- [docs/hooks.md](../docs/hooks.md)
|
|
301
|
+
- [docs/hooks.md](../docs/hooks.md): lifecycle hooks (build/pre, build/post, release/pre, release/post, notarize/post, deploy/pre)
|
|
264
302
|
- [docs/shared/icons.md](../docs/icons.md) — convention-only icon resolution (`global/` + per-platform), retina derivation, macOS Template magic
|
|
265
303
|
- [docs/fontawesome.md](../docs/fontawesome.md) — Font Awesome Free served from the npm dep (icon semantics shared with web via @omega.js/client's icon-core): `<i class="fa-solid fa-*">` auto-render, `manager.fontawesome.get`
|
|
266
304
|
- [docs/verts.md](../docs/verts.md) — `[data-omega-vert]` auto-bind to @omega.js/client's verts module (live via MutationObserver): house/company lane ONLY (type pinned 'house' — no AdSense in desktop surfaces)
|
|
267
305
|
- [docs/installer-options.md](../docs/installer-options.md) — per-target installer config, defaults table
|
|
268
306
|
- [docs/signing.md](../docs/signing.md) — code signing for macOS + Windows
|
|
269
307
|
- [docs/releasing.md](../docs/releasing.md) — end-to-end release walkthrough
|
|
270
|
-
- [docs/runner.md](../docs/runner.md): Windows EV-token signing runner. The listener runs with a private HOME (`%LOCALAPPDATA%\omega-runner\home`, holding a real `.gitconfig`), written at install and healed by `start`/`restart`, so a job's `actions/checkout` never copies the box's symlinked `~/.gitconfig` into a junction it cannot read ([#807](https://github.com/Omega-JS-Stack/omega/issues/807))
|
|
308
|
+
- [docs/runner.md](../docs/runner.md): Windows EV-token signing runner. The listener runs with a private HOME (`%LOCALAPPDATA%\omega-runner\home`, holding a real `.gitconfig`), written at install and healed by `start`/`restart`, so a job's `actions/checkout` never copies the box's symlinked `~/.gitconfig` into a junction it cannot read ([#807](https://github.com/Omega-JS-Stack/omega/issues/807)). The same install writes the box's JOB GUARD ([#875](https://github.com/Omega-JS-Stack/omega/issues/875)): a job-started hook beside the runner, pointed at through each registration's `ACTIONS_RUNNER_HOOK_JOB_STARTED`, that fails any job whose event is not a dispatch or whose repository or actor is not on the box's own allow lists
|
|
271
309
|
- [docs/test-framework.md](../docs/test-framework.md) — writing tests, running them, layers
|
|
272
310
|
- [docs/test-boot-layer.md](../docs/test-boot-layer.md) — the `boot` test layer: consumer end-to-end smoke + @omega.js/desktop's framework self-test from the repo via the bundled fixture (`src/test/fixtures/consumer-app/`) + `OMEGA_TEST_BOOT_PROJECT` (@omega.js/desktop's analog of @omega.js/backend/BXM/UJM `*_TEST_BOOT_PROJECT`)
|
|
273
311
|
- [docs/build-system.md](../docs/build-system.md) — gulp, esbuild, electron-builder pipeline
|
|
@@ -38,16 +38,16 @@ These apply identically on every OS — set them once.
|
|
|
38
38
|
|
|
39
39
|
If you need a per-platform value not in the table, use the raw `electronBuilder.mac.category` / `electronBuilder.linux.category` override.
|
|
40
40
|
|
|
41
|
-
## Windows (`platforms.
|
|
41
|
+
## Windows (`platforms.windows.*`)
|
|
42
42
|
|
|
43
43
|
| Field | Default | What it does |
|
|
44
44
|
|---|---|---|
|
|
45
|
-
| `platforms.
|
|
46
|
-
| `platforms.
|
|
47
|
-
| `platforms.
|
|
48
|
-
| `platforms.
|
|
49
|
-
| `platforms.
|
|
50
|
-
| `platforms.
|
|
45
|
+
| `platforms.windows.arch` | `['x64', 'ia32']` | Architectures. Single multi-arch NSIS installer ships both. |
|
|
46
|
+
| `platforms.windows.oneClick` | `true` | Slack-style: no installer wizard, just installs immediately to `%LocalAppData%\Programs\<App>`. Set to `false` for a standard "Next, Next, Finish" wizard. |
|
|
47
|
+
| `platforms.windows.desktopShortcut` | `true` | Create desktop shortcut. |
|
|
48
|
+
| `platforms.windows.startMenuShortcut` | `true` | Create Start menu entry. |
|
|
49
|
+
| `platforms.windows.runAfterFinish` | `true` | Auto-launch the app when the install completes. |
|
|
50
|
+
| `platforms.windows.perMachine` | `false` | Install for current user. Set `true` to install for all users (requires UAC elevation; **incompatible with `oneClick: true`**). |
|
|
51
51
|
|
|
52
52
|
### Why `oneClick: true` by default
|
|
53
53
|
|
|
@@ -61,7 +61,7 @@ If your app needs enterprise deployment, set `oneClick: false` to opt into the w
|
|
|
61
61
|
|
|
62
62
|
### `ia32` (32-bit Windows)
|
|
63
63
|
|
|
64
|
-
@omega.js/desktop ships `ia32` alongside `x64` in a single multi-arch installer. Real-world 32-bit Windows usage is <3%, but the cost of including it is just ~2x installer size + ~2x signing time
|
|
64
|
+
@omega.js/desktop ships `ia32` alongside `x64` in a single multi-arch installer. Real-world 32-bit Windows usage is <3%, but the cost of including it is just ~2x installer size + ~2x signing time, no separate code path. Worth keeping for the long-tail user on an old Win 10 machine. To drop, set `platforms.windows.arch: ['x64']`.
|
|
65
65
|
|
|
66
66
|
## macOS (`platforms.mac.*`)
|
|
67
67
|
|
|
@@ -87,32 +87,35 @@ Reference plists from a working MAS-published Electron app (Slapform) are archiv
|
|
|
87
87
|
| Field | Default | What it does |
|
|
88
88
|
|---|---|---|
|
|
89
89
|
| `platforms.linux.arch` | `['x64']` | Architectures. ia32 is essentially extinct on modern Linux. |
|
|
90
|
-
| `platforms.linux.
|
|
91
|
-
| `platforms.linux.
|
|
92
|
-
| `platforms.linux.snap
|
|
93
|
-
| `platforms.linux.snap.
|
|
94
|
-
| `platforms.linux.snap.
|
|
90
|
+
| `platforms.linux.formats.deb` | on | The Debian package. `false` drops it. |
|
|
91
|
+
| `platforms.linux.formats.appimage` | on | The AppImage. `false` drops it. |
|
|
92
|
+
| `platforms.linux.formats.snap` | on | Snap Store publishing. Presence is the switch ([#867](https://github.com/Omega-JS-Stack/omega/issues/867)): `false` drops it, and a BUILD auto-skips it when `SNAPCRAFT_STORE_CREDENTIALS` is unset. A publish refuses instead when the brand WROTE the format down. |
|
|
93
|
+
| `platforms.linux.formats.snap.confinement` | `'strict'` | `strict` (sandboxed) or `classic` (unrestricted, requires Snap Store approval). |
|
|
94
|
+
| `platforms.linux.formats.snap.grade` | `'stable'` | `stable` or `devel`. |
|
|
95
|
+
| `platforms.linux.formats.snap.autoStart` | `true` | Register the snap to auto-start on login. |
|
|
96
|
+
| `platforms.linux.formats.snap.channels` | `['stable']` | Snap Store channels to publish to. |
|
|
95
97
|
|
|
96
98
|
### Snap Store publishing
|
|
97
99
|
|
|
98
|
-
|
|
100
|
+
Behavior, since the snap became a declared FORMAT (#867):
|
|
99
101
|
|
|
100
|
-
- **
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
-
|
|
102
|
+
- **Nothing declared** → the snap SHIPS, like every other format: presence is the switch and the default is on.
|
|
103
|
+
- **Defaulted (nothing written) + no `SNAPCRAFT_STORE_CREDENTIALS`** → skipped, with a build-time log line naming the credential and how to get it. A fresh scaffold produces a working `.deb + .AppImage` build out of the box without failing on a missing publish credential.
|
|
104
|
+
- **WRITTEN in config + no `SNAPCRAFT_STORE_CREDENTIALS`** → a BUILD still skips it as above, but `omega publish` REFUSES in its first step, naming the credential, `platforms.linux.formats.snap` and `omega manage --service publishing` ([#867](https://github.com/Omega-JS-Stack/omega/issues/867)). Writing the format down is saying this brand ships it, and a release that silently drops it is the failure this replaced.
|
|
105
|
+
- **Declared + `SNAPCRAFT_STORE_CREDENTIALS` set** → the snap target emits and publishes on release.
|
|
106
|
+
- **`platforms.linux.formats.snap: false`** → off, regardless of credentials. The explicit opt-out.
|
|
104
107
|
|
|
105
|
-
To turn snap publishing on for a project that
|
|
108
|
+
To turn snap publishing on for a project that ships the format:
|
|
106
109
|
|
|
107
110
|
1. Mint store credentials locally:
|
|
108
111
|
```bash
|
|
109
112
|
snapcraft export-login - # writes a credentials blob to stdout
|
|
110
113
|
```
|
|
111
114
|
2. Paste the entire blob (multi-line) into `.env` as `SNAPCRAFT_STORE_CREDENTIALS=...`.
|
|
112
|
-
3. Run `npx omega
|
|
115
|
+
3. Run `npx omega deploy` (its precheck flows the secret to GitHub Actions).
|
|
113
116
|
4. Next `npm run release` builds + uploads the snap automatically. No config flip needed.
|
|
114
117
|
|
|
115
|
-
Reference: the workflow's Linux step conditionally installs `snapcraft` (`sudo snap install snapcraft --classic`) only when both (a)
|
|
118
|
+
Reference: the workflow's Linux step conditionally installs `snapcraft` (`sudo snap install snapcraft --classic`) only when both (a) the brand still ships the snap format (read through `@omega.js/config`'s own `enabledFormats`, so the check cannot drift from the build's) AND (b) the `SNAPCRAFT_STORE_CREDENTIALS` secret is present.
|
|
116
119
|
|
|
117
120
|
## File associations + custom protocols (uncommon)
|
|
118
121
|
|
package/docs/logging.md
CHANGED
|
@@ -87,7 +87,7 @@ npx omega logs test --lines=100 # last 100 lines of the previous test run
|
|
|
87
87
|
npx omega logs build --path # just the path, for piping
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
Anything else fails naming the four surfaces. (The four files themselves are described in the lifetime table below; `
|
|
90
|
+
Anything else fails naming the four surfaces. (The four files themselves are described in the lifetime table below; `deploy.log` and `signing.log` are not tail targets.)
|
|
91
91
|
|
|
92
92
|
`mgr logs` only resolves the dev path (`<cwd>/logs/<surface>.log`). To find the production runtime log on a user's machine, use the table above or call `getLogFilePath()` from app code.
|
|
93
93
|
|
|
@@ -173,7 +173,7 @@ window "main": closed (destroyed)
|
|
|
173
173
|
activate (macOS) — surfacing main (visible=false, minimized=false)
|
|
174
174
|
_ensureDockVisible — calling dock.show()
|
|
175
175
|
_ensureDockVisible — dock already visible
|
|
176
|
-
second-instance
|
|
176
|
+
second-instance argv=["..."] eventArgv=["..."] cwd=/...
|
|
177
177
|
second-instance — surfacing main (visible=false, minimized=false)
|
|
178
178
|
```
|
|
179
179
|
|
|
@@ -209,7 +209,7 @@ File path resolution in main:
|
|
|
209
209
|
|
|
210
210
|
The transport is set up lazily on first `log()` call, so importing `LoggerLite` in build/CLI contexts that have no Electron is harmless.
|
|
211
211
|
|
|
212
|
-
## Coexisting with `dev.log`, `build.log`, `test.log`, and `
|
|
212
|
+
## Coexisting with `dev.log`, `build.log`, `test.log`, and `deploy.log`
|
|
213
213
|
|
|
214
214
|
Five separate logs in `<projectRoot>/logs/`:
|
|
215
215
|
|
|
@@ -219,11 +219,11 @@ Five separate logs in `<projectRoot>/logs/`:
|
|
|
219
219
|
| `dev.log` | Gulp pipeline + spawned Electron child stdout (`npm start`) | Truncated each `npm start` |
|
|
220
220
|
| `build.log` | Gulp pipeline output for production builds/packages (`npm run build` / `package` / `publish`, i.e. `OMEGA_BUILD_MODE=true`) | Truncated each build |
|
|
221
221
|
| `test.log` | `npx omega test` runner output (suite names, pass/fail states, harness boot lines) | Truncated each test run |
|
|
222
|
-
| `
|
|
222
|
+
| `deploy.log` | GH Actions run output, streamed locally by the follower every target's deploy uses (`omega deploy`, `npm run release`) ([#873](https://github.com/Omega-JS-Stack/omega/issues/873); this was `ci.log`) | Truncated each deploy |
|
|
223
223
|
| `signing.log` | JSONL signing events from Windows code-signing (local dev fallback; on CI this writes to the runner home as `omega-signing.log` instead) | Appended (not truncated) |
|
|
224
224
|
|
|
225
225
|
`dev.log` and `build.log` are the same gulp tee — which one it writes is chosen by `OMEGA_BUILD_MODE`, so they never both fill up in one run. (Disable the tee with `OMEGA_LOG_FILE=false`; override its path with `OMEGA_LOG_FILE=<path>`.)
|
|
226
226
|
|
|
227
|
-
They serve different purposes and don't overlap
|
|
227
|
+
They serve different purposes and don't overlap: `dev.log`/`build.log` show you "is the build still running?", `test.log` shows you "which test failed on the last run?", `deploy.log` shows you "did the release workflow pass?", `runtime.log` shows you "is my app's auto-updater finding the right release feed?". All useful.
|
|
228
228
|
|
|
229
229
|
In production: only `runtime.log` exists (no project, no gulp, no GH Actions stream).
|
package/docs/releasing.md
CHANGED
|
@@ -31,15 +31,16 @@ releases: {
|
|
|
31
31
|
|
|
32
32
|
Every artifact name is **stable across releases** — no version in it:
|
|
33
33
|
|
|
34
|
-
| Platform |
|
|
34
|
+
| Platform | Format | Asset name |
|
|
35
35
|
|---|---|---|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
36
|
+
| mac | `dmg` | `<Product>-mac-dmg.dmg` |
|
|
37
|
+
| mac | auto-update zip (not a declared format) | `<Product>-mac.zip` |
|
|
38
|
+
| windows | `nsis` | `<Product>-windows-nsis.exe` |
|
|
39
|
+
| linux | `deb` | `<Product>-linux-deb.deb` |
|
|
40
|
+
| linux | `appimage` | `<Product>-linux-appimage.AppImage` |
|
|
41
|
+
| linux | `snap` | none: the Snap Store holds the file, so it is never a release asset |
|
|
41
42
|
|
|
42
|
-
`<Product>` is `app.productName` (← `brand.name`) with non-filename characters hyphenated. The rule has ONE home
|
|
43
|
+
`<Product>` is `app.productName` (← `brand.name`) with non-filename characters hyphenated. The platform and format words are the ONE vocabulary ([#867](https://github.com/Omega-JS-Stack/omega/issues/867)) and the rule has ONE home, `@omega.js/config`'s `platforms.js`, which `gulp/build-config` writes into `dist/electron-builder.yml`'s artifactName templates and the website reads to build its buttons. Never spell an asset name anywhere else.
|
|
43
44
|
|
|
44
45
|
Because the names never change, GitHub's latest-release redirect is a permanent direct-download URL:
|
|
45
46
|
|
|
@@ -47,7 +48,7 @@ Because the names never change, GitHub's latest-release redirect is a permanent
|
|
|
47
48
|
https://github.com/<owner>/<brand.id>-releases/releases/latest/download/<asset>
|
|
48
49
|
```
|
|
49
50
|
|
|
50
|
-
That is what `site.targets.desktop.downloads[platform][
|
|
51
|
+
That is what `site.targets.desktop.downloads[platform][format]` derives (see [docs/shared/config.md](../../../docs/shared/config.md#the-site-global-the-curated-targets-view-85-610) in the Omega repo), what the `/download` page's buttons link, and what every `/download/<platform>[/<format>]` shortlink redirects to. **Releasing a desktop version never touches the website**, and the published URLs never change.
|
|
51
52
|
|
|
52
53
|
Auto-update is unaffected: `electron-updater` reads the feed files (`latest-mac.yml`, `latest.yml`, `latest-linux.yml`), which name whatever artifact the build produced.
|
|
53
54
|
|
|
@@ -59,7 +60,7 @@ If the releases repo has to move (rename or transfer), the rules are:
|
|
|
59
60
|
|
|
60
61
|
- **The existing repo is the survivor** — transfer it, never build a fresh one. GitHub keeps redirects for the web pages, git remotes, the API and release-asset URLs, and `electron-updater` follows them, so every already-installed app (its feed URL is baked into `app-update.yml` at build time) keeps updating.
|
|
61
62
|
- **Never reuse the old org/name.** A new repo created at the old path takes the redirect over and silently steals every installed app's update feed and every published download link.
|
|
62
|
-
-
|
|
63
|
+
- The repo NAME is not configurable ([#883](https://github.com/Omega-JS-Stack/omega/issues/883)): it is always `<brand.id>-releases` under `repo.org`, so a move means renaming the repo to match (or, if the brand itself is renaming, changing `brand.id` / `repo.org` once). The website's URLs re-derive on its next build; the asset names do not change.
|
|
63
64
|
- **Fallback only** — if the surviving repo were a *different* repo, installed apps would need a bridge release: build once with the new feed baked in and publish it to the OLD repo, so clients update themselves onto the new feed before it is retired.
|
|
64
65
|
|
|
65
66
|
> The `downloads:` block (the `download-server` mirror at tag `installer`, `gulp/mirror-downloads`) predated this: it existed only to give marketing a fixed filename, which the versionless names made free. It is GONE ([#799](https://github.com/Omega-JS-Stack/omega/issues/799)): the task, the `publish` step, the finalize-release mirror and the second repo's provisioning are deleted, and `downloads.enabled|owner|repo|tag` are retired config keys a brand still carrying them fails validation on. One public repo, one set of assets.
|
|
@@ -104,7 +105,6 @@ Edit `.env`:
|
|
|
104
105
|
|
|
105
106
|
```bash
|
|
106
107
|
GH_TOKEN="ghp_..."
|
|
107
|
-
OMEGA_ADMIN_KEY="..."
|
|
108
108
|
|
|
109
109
|
CSC_LINK="config/certs/developer-id-application.p12"
|
|
110
110
|
CSC_KEY_PASSWORD="<password>"
|
|
@@ -147,12 +147,20 @@ A successful release on macOS prints something like:
|
|
|
147
147
|
[notarize] Notarizing MyApp via App Store Connect API key (XXXXXXXXXX)...
|
|
148
148
|
[notarize] Done in 84s.
|
|
149
149
|
[release] Released 2 artifact(s):
|
|
150
|
-
• release/MyApp-mac-
|
|
151
|
-
• release/MyApp-mac
|
|
150
|
+
• release/MyApp-mac-dmg.dmg
|
|
151
|
+
• release/MyApp-mac.zip
|
|
152
152
|
```
|
|
153
153
|
|
|
154
154
|
The release will appear on the GitHub repo's Releases page (as a draft if `releaseType: draft` is set in `electron-builder.yml`, or published if `release`).
|
|
155
155
|
|
|
156
|
+
A release that uploaded NOTHING fails the task ([#891](https://github.com/Omega-JS-Stack/omega/issues/891)). electron-builder resolves its build promise with the local artifact paths whether or not a byte was published, and it reports a skipped upload only as a warning on its own logger, so the task reads that logger for the length of the build. Any `skipped publishing` / `GitHub release not created` warning ends the run with electron-builder's own reason and tag instead of the `Released N artifact(s)` line:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
[release] Nothing was uploaded: electron-builder skipped publishing 4 artifact(s) (...) to v0.0.1
|
|
160
|
+
(existing release published more than 2 hours ago). Bump the version in package.json: a release
|
|
161
|
+
that already exists is never re-uploaded.
|
|
162
|
+
```
|
|
163
|
+
|
|
156
164
|
## Multi-platform release via CI
|
|
157
165
|
|
|
158
166
|
CI handles the cross-platform matrix. The scaffolded workflow is `build.yml`, dispatched by `npx omega release` / `npx omega deploy`:
|
|
@@ -167,7 +175,7 @@ build needs setup; matrix over the resolved OSes: npm ci, then
|
|
|
167
175
|
electron-builder publishes the DRAFT release in the brand's releases
|
|
168
176
|
repo), and `npm run package` on windows, whose unsigned output uploads
|
|
169
177
|
as the `windows-unsigned` artifact
|
|
170
|
-
windows-strategy needs [setup, build]; reads platforms.
|
|
178
|
+
windows-strategy needs [setup, build]; reads platforms.windows.signing.strategy from config
|
|
171
179
|
(only when windows is in the matrix)
|
|
172
180
|
windows-sign the self-hosted EV-token box, hosted windows-latest for the cloud
|
|
173
181
|
strategy, skipped for local: `omega sign-windows`, then
|
|
@@ -179,9 +187,9 @@ finalize needs [setup, build, windows-sign] under always(), gated on th
|
|
|
179
187
|
draft standing for the next one to fill in)
|
|
180
188
|
```
|
|
181
189
|
|
|
182
|
-
The macOS step decodes `secrets.CSC_LINK` and `secrets.APPLE_API_KEY` (uploaded by `
|
|
190
|
+
The macOS step decodes `secrets.CSC_LINK` and `secrets.APPLE_API_KEY` (uploaded by `omega deploy`'s precheck as base64-encoded file contents) back to disk before running `npm run release:local`.
|
|
183
191
|
|
|
184
|
-
**Dispatch only, never a push trigger** ([#802](https://github.com/Omega-JS-Stack/omega/issues/802)): the workflow declares `workflow_dispatch
|
|
192
|
+
**Dispatch only, never a push trigger** ([#802](https://github.com/Omega-JS-Stack/omega/issues/802)): the workflow declares the one dispatch trigger (`workflow_dispatch`, [#880](https://github.com/Omega-JS-Stack/omega/issues/880), [#923](https://github.com/Omega-JS-Stack/omega/issues/923)) and nothing else, so no commit and no tag releases anything ([docs/shared/deploys.md](../../../docs/shared/deploys.md) in the Omega repo is the contract for all four frameworks). It runs no tests either: the suites run on the developer's machine and the commit gate runs the battery at ship.
|
|
185
193
|
|
|
186
194
|
To release:
|
|
187
195
|
1. Bump the version in `package.json`.
|
|
@@ -190,7 +198,7 @@ To release:
|
|
|
190
198
|
|
|
191
199
|
## Windows signing strategies
|
|
192
200
|
|
|
193
|
-
Set `platforms.
|
|
201
|
+
Set `platforms.windows.signing.strategy` in `config/omega.json5`:
|
|
194
202
|
|
|
195
203
|
| Strategy | What runs | When to use |
|
|
196
204
|
|---|---|---|
|
|
@@ -220,7 +228,7 @@ For details see [`docs/signing.md`](signing.md#windows-setup).
|
|
|
220
228
|
|
|
221
229
|
### CI: GitHub Releases upload fails
|
|
222
230
|
- Verify `GH_TOKEN` secret is set. The auto-injected `GITHUB_TOKEN` won't work for cross-repo writes.
|
|
223
|
-
- Confirm the config addresses the right repo: `repo.
|
|
231
|
+
- Confirm the config addresses the right repo: `repo.org` + `brand.id` derive both the source repo (`<brand.id>-omega`) and the artifacts' repo (`<brand.id>-releases`), and `targets.desktop.releases` is the presence switch alone.
|
|
224
232
|
|
|
225
233
|
## Related docs
|
|
226
234
|
|