@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
|
@@ -23,19 +23,20 @@ module.exports = defineCases({
|
|
|
23
23
|
},
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
|
-
name: 'isTesting() returns true (
|
|
26
|
+
name: 'isTesting() returns true (this lane named OMEGA_ENVIRONMENT=testing)',
|
|
27
27
|
run: (ctx) => {
|
|
28
28
|
ctx.expect(window.__emTestManager.isTesting()).toBe(true);
|
|
29
29
|
},
|
|
30
30
|
},
|
|
31
31
|
{
|
|
32
|
-
name: 'isDevelopment()
|
|
32
|
+
name: 'isDevelopment() answers the one input, with no renderer-specific sniff',
|
|
33
33
|
run: (ctx) => {
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
34
|
+
// Nothing here reads app.isPackaged or NODE_ENV any more (#817): the
|
|
35
|
+
// preload has a process, so the lane's OMEGA_ENVIRONMENT answers, and a
|
|
36
|
+
// real renderer bundle answers from the baked config.environment.
|
|
37
37
|
const v = window.__emTestManager.isDevelopment();
|
|
38
38
|
ctx.expect(typeof v).toBe('boolean');
|
|
39
|
+
ctx.expect(v).toBe(false);
|
|
39
40
|
},
|
|
40
41
|
},
|
|
41
42
|
{
|
|
@@ -44,7 +45,7 @@ module.exports = defineCases({
|
|
|
44
45
|
const dev = window.__emTestManager.isDevelopment();
|
|
45
46
|
const test = window.__emTestManager.isTesting();
|
|
46
47
|
const prod = window.__emTestManager.isProduction();
|
|
47
|
-
//
|
|
48
|
+
// This lane named testing; dev and prod are both false.
|
|
48
49
|
ctx.expect(test).toBe(true);
|
|
49
50
|
ctx.expect(dev).toBe(false);
|
|
50
51
|
ctx.expect(prod).toBe(false);
|
|
@@ -62,16 +63,18 @@ module.exports = defineCases({
|
|
|
62
63
|
},
|
|
63
64
|
},
|
|
64
65
|
{
|
|
65
|
-
name: 'getEnvironment():
|
|
66
|
+
name: 'getEnvironment(): the lane variable wins over the baked config.environment',
|
|
66
67
|
run: (ctx) => {
|
|
67
|
-
// The test runner
|
|
68
|
-
//
|
|
69
|
-
|
|
68
|
+
// The test runner names OMEGA_ENVIRONMENT=testing, and this preload has a
|
|
69
|
+
// process to read it from, so it wins over whatever the artifact was
|
|
70
|
+
// baked as (#817). A real renderer bundle has no process and takes the
|
|
71
|
+
// baked word, which is the other half of the same one-input rule.
|
|
72
|
+
window.__emTestManager.setConfig('environment', 'production');
|
|
70
73
|
ctx.expect(window.__emTestManager.getEnvironment()).toBe('testing');
|
|
71
|
-
window.__emTestManager.setConfig('
|
|
74
|
+
window.__emTestManager.setConfig('environment', 'development');
|
|
72
75
|
ctx.expect(window.__emTestManager.getEnvironment()).toBe('testing');
|
|
73
76
|
// Reset.
|
|
74
|
-
window.__emTestManager.setConfig('
|
|
77
|
+
window.__emTestManager.setConfig('environment', 'production');
|
|
75
78
|
},
|
|
76
79
|
},
|
|
77
80
|
{
|
|
@@ -104,7 +107,7 @@ module.exports = defineCases({
|
|
|
104
107
|
},
|
|
105
108
|
},
|
|
106
109
|
{
|
|
107
|
-
name: 'getWebsiteUrl: dev →
|
|
110
|
+
name: 'getWebsiteUrl: dev → https://localhost:4000, from the baked classic map',
|
|
108
111
|
run: (ctx) => {
|
|
109
112
|
ctx.expect(window.__emTestManager.getWebsiteUrl('development')).toBe('https://localhost:4000');
|
|
110
113
|
},
|
|
@@ -118,9 +121,9 @@ module.exports = defineCases({
|
|
|
118
121
|
{
|
|
119
122
|
name: 'getWebsiteUrl: no-arg resolves local under testing; explicit arg overrides',
|
|
120
123
|
run: (ctx) => {
|
|
121
|
-
//
|
|
122
|
-
//
|
|
123
|
-
window.__emTestManager.setConfig('
|
|
124
|
+
// This lane is testing, so the no-arg form resolves LOCAL regardless of
|
|
125
|
+
// what the artifact was baked as: that's the safety guarantee.
|
|
126
|
+
window.__emTestManager.setConfig('environment', 'production');
|
|
124
127
|
ctx.expect(window.__emTestManager.getWebsiteUrl()).toBe('https://localhost:4000');
|
|
125
128
|
// An explicit env arg bypasses the current environment and pins the mapping.
|
|
126
129
|
ctx.expect(window.__emTestManager.getWebsiteUrl('production')).toBe('https://example.com');
|
|
@@ -18,18 +18,18 @@ function gulpCommand(task) {
|
|
|
18
18
|
// loads the whole command surface.
|
|
19
19
|
//
|
|
20
20
|
// There is no `setup` step any more (#675): the local half runs inside the gulp
|
|
21
|
-
// `defaults` task, which is the first step of every gulp build.
|
|
22
|
-
//
|
|
21
|
+
// `defaults` task, which is the first step of every gulp build. There is no
|
|
22
|
+
// `certs` copy step either ([#891](https://github.com/Omega-JS-Stack/omega/issues/891)):
|
|
23
|
+
// signing material is READ IN PLACE from the signing tree, and the env load
|
|
24
|
+
// derives the paths to it once (utils/load-env.js).
|
|
23
25
|
const RUNNERS = {
|
|
24
26
|
clean: (options) => require('../commands/clean.js')(options),
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
},
|
|
32
|
-
'validate-certs': (options) => require('../commands/validate-certs.js')(options),
|
|
27
|
+
// The credentials the brand's DECLARED formats cannot ship without (#867),
|
|
28
|
+
// refused before a minute of build time. Publish declares this step; a bare
|
|
29
|
+
// build does not, because a build puts nothing in front of users.
|
|
30
|
+
'ship-keys': () => require('./ship-keys.js').assertShipKeys(),
|
|
31
|
+
// `strict` rides the STEP: publish declares it (#891), a bare verb does not.
|
|
32
|
+
'validate-certs': (options, step) => require('../commands/validate-certs.js')({ ...options, strict: step.strict === true || options.strict === true }),
|
|
33
33
|
gulp: (options, step) => execute(gulpCommand(step.task), { log: true }),
|
|
34
34
|
};
|
|
35
35
|
|
package/dist/utils/github.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
//
|
|
1
|
+
// The Octokit factory for the release pipeline (uploads, the draft flip).
|
|
2
2
|
//
|
|
3
|
-
// WHICH repo a verb addresses is not decided here: the
|
|
4
|
-
// @omega.js/config's `
|
|
5
|
-
// config/omega.json5 alone (#799). The old package.json/git-remote
|
|
6
|
-
// gone: a brand nested in another repo (a target inside a brand
|
|
7
|
-
// playground inside the framework monorepo) resolved to the
|
|
3
|
+
// WHICH repo a verb addresses is not decided here: the source repo is
|
|
4
|
+
// @omega.js/config's `sourceRepo` and the releases repo its `releasesRepo`,
|
|
5
|
+
// from config/omega.json5 alone (#799). The old package.json/git-remote
|
|
6
|
+
// discovery is gone: a brand nested in another repo (a target inside a brand
|
|
7
|
+
// monorepo, the playground inside the framework monorepo) resolved to the
|
|
8
|
+
// ENCLOSING repo.
|
|
9
|
+
//
|
|
10
|
+
// CREATING a repo is not decided here either (#883): every repo a brand owns
|
|
11
|
+
// is created and reconciled by `@omega.js/devkit/github-repo`'s ensureRepo, the
|
|
12
|
+
// one home the manage walk and the web deploy use too. This file's own copy is
|
|
13
|
+
// gone with it.
|
|
8
14
|
//
|
|
9
15
|
// Octokit factory: returns an authenticated client when GH_TOKEN is set. Returns null otherwise so
|
|
10
16
|
// callers can choose to no-op or bail with a friendly message.
|
|
11
|
-
//
|
|
12
|
-
// Repo ensure: idempotently create a repo under <owner> if it doesn't exist. Used by the
|
|
13
|
-
// deploy precheck to auto-provision the brand's public releases repo.
|
|
14
17
|
|
|
15
18
|
// silent: true — pass a no-op logger so transient 404s during polling (e.g. fetching
|
|
16
19
|
// in-progress job logs) don't spam the console. Errors still surface via thrown rejections.
|
|
@@ -26,48 +29,6 @@ function getOctokit(opts = {}) {
|
|
|
26
29
|
return new Octokit(config);
|
|
27
30
|
}
|
|
28
31
|
|
|
29
|
-
// Idempotent: returns true if the repo exists (created or already there), false on failure.
|
|
30
|
-
// Honors the `owner` distinction between user vs. org — the API endpoints differ.
|
|
31
|
-
async function ensureRepo(octokit, owner, repo, opts = {}) {
|
|
32
|
-
const description = opts.description || '';
|
|
33
|
-
const isPrivate = opts.private === true;
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
await octokit.rest.repos.get({ owner, repo });
|
|
37
|
-
return { created: false, exists: true };
|
|
38
|
-
} catch (err) {
|
|
39
|
-
if (err.status !== 404) throw err;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Need to create. Check if owner is the authenticated user or an org.
|
|
43
|
-
let isOrg = false;
|
|
44
|
-
try {
|
|
45
|
-
const { data: me } = await octokit.rest.users.getAuthenticated();
|
|
46
|
-
isOrg = me.login.toLowerCase() !== owner.toLowerCase();
|
|
47
|
-
} catch (e) {
|
|
48
|
-
isOrg = true;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const params = {
|
|
52
|
-
name: repo,
|
|
53
|
-
description,
|
|
54
|
-
private: isPrivate,
|
|
55
|
-
has_issues: true,
|
|
56
|
-
has_projects: false,
|
|
57
|
-
has_wiki: false,
|
|
58
|
-
auto_init: true,
|
|
59
|
-
};
|
|
60
|
-
|
|
61
|
-
if (isOrg) {
|
|
62
|
-
await octokit.rest.repos.createInOrg({ org: owner, ...params });
|
|
63
|
-
} else {
|
|
64
|
-
await octokit.rest.repos.createForAuthenticatedUser(params);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return { created: true, exists: true };
|
|
68
|
-
}
|
|
69
|
-
|
|
70
32
|
module.exports = {
|
|
71
33
|
getOctokit,
|
|
72
|
-
ensureRepo,
|
|
73
34
|
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The desktop target's ONE env load
|
|
3
|
+
* ([#891](https://github.com/Omega-JS-Stack/omega/issues/891)).
|
|
4
|
+
*
|
|
5
|
+
* Two boots populate `process.env` for a desktop target: the CLI (`src/cli.js`)
|
|
6
|
+
* and gulp (`src/gulp/main.js`, which runs as its own process and is invoked
|
|
7
|
+
* directly by `npm start`). Both call HERE, so a signing path is derived once,
|
|
8
|
+
* by one rule, and every reader after it (the build, `validate-certs`, the
|
|
9
|
+
* deploy precheck's secrets publish) reads the answer instead of deriving its
|
|
10
|
+
* own. The derivation itself is `@omega.js/devkit/signing-env`: the signing
|
|
11
|
+
* tree, company tier first.
|
|
12
|
+
*
|
|
13
|
+
* The lines it prints name PATHS, never contents: `CSC_LINK derived from
|
|
14
|
+
* <path>` is exactly what a signing failure is diagnosed from. WHEN they print
|
|
15
|
+
* is the caller's (gulp holds them until its log tee is attached, so build.log
|
|
16
|
+
* carries them); the SHAPE of them is here, once.
|
|
17
|
+
*/
|
|
18
|
+
const { loadEnv } = require('../vendor/config/index.js');
|
|
19
|
+
const { deriveSigningEnv } = require('../vendor/devkit/signing-env.js');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Load the `.env` cascade for a desktop target and derive its signing paths.
|
|
23
|
+
*
|
|
24
|
+
* @param {string} projectRoot - The target root.
|
|
25
|
+
* @param {object} [options]
|
|
26
|
+
* @param {object} [options.logger] - `{ log, warn }`; the result is reported at
|
|
27
|
+
* once when given, and handed back for the caller to report otherwise.
|
|
28
|
+
* @param {object} [options.env] - The env map to populate (default process.env).
|
|
29
|
+
* @returns {{ derived: Array<{ key: string, value: string }>, problems: Array<{ key: string, reason: string }> }}
|
|
30
|
+
*/
|
|
31
|
+
function loadDesktopEnv(projectRoot, options = {}) {
|
|
32
|
+
const env = options.env || process.env;
|
|
33
|
+
|
|
34
|
+
// The cascade first (shell > target .env > brand .env > company .env). The
|
|
35
|
+
// target name delivers the schema's `deliverAs` renames (#678).
|
|
36
|
+
loadEnv(projectRoot, { target: 'desktop' });
|
|
37
|
+
|
|
38
|
+
const result = deriveSigningEnv({ env, targetDir: projectRoot });
|
|
39
|
+
|
|
40
|
+
if (options.logger) {
|
|
41
|
+
reportSigningEnv(result, options.logger);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Say what the derivation answered: one line per key, paths only.
|
|
49
|
+
*
|
|
50
|
+
* @param {{ derived: Array, problems: Array }} result - What loadDesktopEnv returned.
|
|
51
|
+
* @param {object} logger - `{ log, warn }`.
|
|
52
|
+
*/
|
|
53
|
+
function reportSigningEnv({ derived, problems }, logger) {
|
|
54
|
+
for (const { key, value } of derived) {
|
|
55
|
+
logger.log(`${key} derived from ${value}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// A file that is THERE and cannot be used is never silent: the key stays
|
|
59
|
+
// unset (Keychain discovery stays the default), and the reason is said out
|
|
60
|
+
// loud so the next rung's error is not the first anyone hears of it.
|
|
61
|
+
for (const { key, reason } of problems) {
|
|
62
|
+
logger.warn(`${key} not derived: ${reason}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = { loadDesktopEnv, reportSigningEnv };
|
|
@@ -1,106 +1,43 @@
|
|
|
1
|
-
// Runtime mode helpers
|
|
2
|
-
//
|
|
1
|
+
// Runtime mode helpers, shared across all three context Managers (main /
|
|
2
|
+
// renderer / preload) and the build-time Manager.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// isProduction() — app packaged & distributed to users (`app.isPackaged === true`),
|
|
13
|
-
// and NOT testing. A real positive check — NOT `!isDevelopment()`.
|
|
4
|
+
// The environment half is NOT implemented here any more
|
|
5
|
+
// ([#817](https://github.com/Omega-JS-Stack/omega/issues/817)). It is
|
|
6
|
+
// @omega.js/config's `environment.js`, the ONE module every OMEGA target
|
|
7
|
+
// answers from, and this file only re-exports it beside desktop's own
|
|
8
|
+
// getVersion(). The four copies this replaced each carried their own signal
|
|
9
|
+
// list and their own default, and they disagreed: desktop's answered
|
|
10
|
+
// `production` with no signal while the extension's answered `development`, so
|
|
11
|
+
// a desktop dev boot bundled itself as a production artifact.
|
|
14
12
|
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
13
|
+
// The contract, in full, is the shared module's:
|
|
14
|
+
// getEnvironment() reads ONE input, the `OMEGA_ENVIRONMENT` variable in Node
|
|
15
|
+
// and the baked `OMEGA_BUILD_JSON.config.environment` in a renderer (which
|
|
16
|
+
// has no process.env), and a context with neither throws by name. Nothing
|
|
17
|
+
// sniffs `app.isPackaged` or NODE_ENV any more: the lane that boots or builds
|
|
18
|
+
// this app names the environment, once, where it resolves its config
|
|
19
|
+
// (src/build.js's getConfig for the build lane, main.js's initialize for the
|
|
20
|
+
// packaged runtime).
|
|
18
21
|
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
22
|
+
// isDevelopment() / isProduction() / isTesting() DERIVE from it, so they can
|
|
23
|
+
// never disagree with it and exactly one is true. isProduction() is a real
|
|
24
|
+
// positive check, never `!isDevelopment()`. Gate "anything non-production"
|
|
25
|
+
// with `!isProduction()` or `isDevelopment() || isTesting()` intentionally.
|
|
23
26
|
//
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
// config.em.environment. To get a renderer-truthful signal, the consumer can have
|
|
28
|
-
// main inject the value into `OMEGA_BUILD_JSON.runtime` at build time (future
|
|
29
|
-
// enhancement); for now, NODE_ENV being inherited from the parent process is the
|
|
30
|
-
// pragmatic answer.
|
|
31
|
-
//
|
|
32
|
-
// In plain Node (gulp tasks, CLI commands), `require('electron')` returns the
|
|
33
|
-
// binary path as a string — no `app` object — so the same `app && typeof
|
|
34
|
-
// app.isPackaged === 'boolean'` check naturally falls through to NODE_ENV.
|
|
35
|
-
|
|
36
|
-
// The three environment checks are MUTUALLY EXCLUSIVE — exactly one is true:
|
|
37
|
-
// isDevelopment() — app run from source / being developed (unpackaged, NOT testing).
|
|
38
|
-
// isTesting() — app being tested (OMEGA_TEST_MODE=true). Takes precedence over dev.
|
|
39
|
-
// isProduction() — app packaged & distributed to users (real positive check, NOT testing).
|
|
40
|
-
// Testing wins first: a test run is unpackaged, but it's a TEST, not development.
|
|
41
|
-
|
|
42
|
-
// getEnvironment() — the SINGLE SOURCE OF TRUTH. Reads every raw signal and resolves to
|
|
43
|
-
// exactly ONE of 'development' | 'testing' | 'production' (mutually exclusive; testing wins).
|
|
44
|
-
// Precedence: testing → explicit config override → Electron app.isPackaged → build-time signal.
|
|
45
|
-
function getEnvironment() {
|
|
46
|
-
// 1. Testing wins — set by @omega.js/desktop's test runners (OMEGA_TEST_MODE=true), regardless of packaged state.
|
|
47
|
-
if (process.env.OMEGA_TEST_MODE === 'true') return 'testing';
|
|
48
|
-
|
|
49
|
-
// 2. An explicit config.em.environment override — the consumer's deliberate decision. It beats
|
|
50
|
-
// the auto-detected app.isPackaged (e.g. a packaged app the consumer wants to treat as dev).
|
|
51
|
-
const cfgEnv = this?.config?.em?.environment;
|
|
52
|
-
if (cfgEnv === 'development' || cfgEnv === 'testing' || cfgEnv === 'production') return cfgEnv;
|
|
53
|
-
|
|
54
|
-
// 3. In Electron main, `app.isPackaged` is the authoritative runtime signal (more accurate
|
|
55
|
-
// than env vars). In renderer/preload, `electron` has no `app`; from plain Node (gulp/CLI),
|
|
56
|
-
// `require('electron')` returns the binary path string — `.app` is undefined in both, so we
|
|
57
|
-
// fall through to the build signals below.
|
|
58
|
-
// In renderer bundles (target: 'web'), require is not available — skip entirely.
|
|
59
|
-
if (typeof require !== 'undefined') {
|
|
60
|
-
try {
|
|
61
|
-
const { app } = require('electron');
|
|
62
|
-
if (app && typeof app.isPackaged === 'boolean') return app.isPackaged ? 'production' : 'development';
|
|
63
|
-
} catch (_) {}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// 4. Build-time / Node signals. OMEGA_BUILD_MODE=true is set during a production build
|
|
67
|
-
// (npm run build / npm run release); NODE_ENV=development is the dev fallback.
|
|
68
|
-
if (process.env.OMEGA_BUILD_MODE === 'true') return 'production';
|
|
69
|
-
if (process.env.NODE_ENV === 'development') return 'development';
|
|
70
|
-
|
|
71
|
-
// 5. Default: production. @omega.js/desktop's deployed RUNTIME can reach here without a dev signal — a
|
|
72
|
-
// packaged app whose `app.isPackaged` somehow didn't resolve is still a shipped binary,
|
|
73
|
-
// so production is the safe assumption for a distributed artifact. (Contrast UJM/BXM,
|
|
74
|
-
// whose deployed artifacts always carry their signal, so they default to development —
|
|
75
|
-
// a bare context there is just build tooling.)
|
|
76
|
-
return 'production';
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// The three checks DERIVE from getEnvironment() — they never read raw signals, so they can
|
|
80
|
-
// never disagree with it. isDevelopment() is NOT true in testing; isProduction() is a real
|
|
81
|
-
// positive check (never `!isDevelopment()`).
|
|
82
|
-
function isDevelopment() {
|
|
83
|
-
return getEnvironment.call(this) === 'development';
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function isProduction() {
|
|
87
|
-
return getEnvironment.call(this) === 'production';
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function isTesting() {
|
|
91
|
-
return getEnvironment.call(this) === 'testing';
|
|
92
|
-
}
|
|
27
|
+
// The shared module requires nothing, so it rides the renderer bundle (a
|
|
28
|
+
// browser context with no Node built-ins) exactly as this file always has.
|
|
29
|
+
const environment = require('../vendor/config/environment.js');
|
|
93
30
|
|
|
94
|
-
// `getVersion()`
|
|
95
|
-
// 1. `electron.app.getVersion()` when running inside Electron (main process
|
|
31
|
+
// `getVersion()` returns the app's version string. Sources, in priority order:
|
|
32
|
+
// 1. `electron.app.getVersion()` when running inside Electron (main process,
|
|
96
33
|
// authoritative; reads from the packaged app's package.json baked into asar).
|
|
97
34
|
// 2. `<cwd>/package.json#version` for build-time scripts / non-Electron contexts.
|
|
98
35
|
// 3. null when neither resolves.
|
|
99
36
|
//
|
|
100
|
-
// Renderer caveat:
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
// `OMEGA_BUILD_JSON.package.version` (baked in by the bundle task
|
|
37
|
+
// Renderer caveat: `electron.app` isn't available in renderer, so the fallback to
|
|
38
|
+
// `process.cwd()/package.json` won't find anything useful in a packaged app.
|
|
39
|
+
// Renderers that need the version should ask main via IPC, or read
|
|
40
|
+
// `OMEGA_BUILD_JSON.package.version` (baked in by the bundle task).
|
|
104
41
|
function getVersion() {
|
|
105
42
|
if (typeof require !== 'undefined') {
|
|
106
43
|
try {
|
|
@@ -121,27 +58,22 @@ function getVersion() {
|
|
|
121
58
|
}
|
|
122
59
|
|
|
123
60
|
// Mix the helpers into a Manager constructor's prototype + the constructor itself
|
|
124
|
-
// (so `Manager.isTesting()` works statically too
|
|
125
|
-
//
|
|
126
|
-
//
|
|
61
|
+
// (so `Manager.isTesting()` works statically too). The environment four come from
|
|
62
|
+
// the shared module's own attachTo(), so every desktop entry point and every
|
|
63
|
+
// sibling framework hangs the identical functions; getVersion() is desktop's and
|
|
64
|
+
// is attached beside them. The URL helpers in url-helpers.js depend on
|
|
65
|
+
// this.getEnvironment() existing, so this attachTo() runs first.
|
|
127
66
|
function attachTo(Manager) {
|
|
128
|
-
Manager
|
|
129
|
-
Manager.prototype.
|
|
130
|
-
Manager.
|
|
131
|
-
Manager.prototype.getEnvironment = getEnvironment;
|
|
132
|
-
Manager.prototype.getVersion = getVersion;
|
|
133
|
-
Manager.isDevelopment = isDevelopment;
|
|
134
|
-
Manager.isProduction = isProduction;
|
|
135
|
-
Manager.isTesting = isTesting;
|
|
136
|
-
Manager.getEnvironment = getEnvironment;
|
|
137
|
-
Manager.getVersion = getVersion;
|
|
67
|
+
environment.attachTo(Manager);
|
|
68
|
+
Manager.prototype.getVersion = getVersion;
|
|
69
|
+
Manager.getVersion = getVersion;
|
|
138
70
|
}
|
|
139
71
|
|
|
140
72
|
module.exports = {
|
|
141
73
|
attachTo,
|
|
142
|
-
isDevelopment,
|
|
143
|
-
isProduction,
|
|
144
|
-
isTesting,
|
|
145
|
-
getEnvironment,
|
|
74
|
+
isDevelopment: environment.isDevelopment,
|
|
75
|
+
isProduction: environment.isProduction,
|
|
76
|
+
isTesting: environment.isTesting,
|
|
77
|
+
getEnvironment: environment.getEnvironment,
|
|
146
78
|
getVersion,
|
|
147
79
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// The ONE translation of Node's platform word into OMEGA's platform
|
|
2
|
+
// vocabulary ([#867](https://github.com/Omega-JS-Stack/omega/issues/867)).
|
|
3
|
+
//
|
|
4
|
+
// OMEGA says `mac`, `windows`, `linux` everywhere it speaks for itself: the
|
|
5
|
+
// config declaration (`platforms.windows.formats.nsis`), the icon dirs
|
|
6
|
+
// (`config/icons/mac/`), the workflow's `platforms` input, the site's
|
|
7
|
+
// `/download/<platform>/<format>` links, and a stored login record. Node says
|
|
8
|
+
// `darwin`/`win32`/`linux`, and electron-builder says `mac`/`win`/`linux`.
|
|
9
|
+
// Those are FOREIGN vocabularies: each is translated at exactly one point, and
|
|
10
|
+
// for Node's that point is here.
|
|
11
|
+
//
|
|
12
|
+
// A bare OS branch (`if (process.platform === 'darwin')`) needs no translation
|
|
13
|
+
// and stays as it is: it reads Node's word to decide Node's behavior and never
|
|
14
|
+
// produces a name anything else consumes. This function is for the places that
|
|
15
|
+
// turn the OS into a NAME: an icon directory, a release directory, the platform
|
|
16
|
+
// a deploy reports building.
|
|
17
|
+
|
|
18
|
+
// Node's process.platform → OMEGA's word. Electron runs on exactly these three.
|
|
19
|
+
const NODE_PLATFORMS = {
|
|
20
|
+
darwin: 'mac',
|
|
21
|
+
win32: 'windows',
|
|
22
|
+
linux: 'linux',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* This machine's platform in OMEGA's vocabulary.
|
|
27
|
+
*
|
|
28
|
+
* @param {string} [nodePlatform] - A `process.platform` value (defaults to this
|
|
29
|
+
* process's own).
|
|
30
|
+
* @returns {string|null} 'mac' | 'windows' | 'linux', or null for an OS OMEGA
|
|
31
|
+
* has no word for (the caller decides whether that is fatal).
|
|
32
|
+
*/
|
|
33
|
+
function desktopPlatform(nodePlatform = process.platform) {
|
|
34
|
+
return NODE_PLATFORMS[nodePlatform] || null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = { desktopPlatform, NODE_PLATFORMS };
|
package/dist/utils/runner-env.js
CHANGED
|
@@ -226,7 +226,8 @@ function runnerLogFile(home) {
|
|
|
226
226
|
|
|
227
227
|
// Is this process a TEST run? `OMEGA_TEST_RUNNER` is set by `omega test` for the
|
|
228
228
|
// whole run (and inherited by the electron/boot children); `OMEGA_TEST_MODE` is
|
|
229
|
-
// the
|
|
229
|
+
// the marker a sibling framework's runner or a consumer's own test script sets
|
|
230
|
+
// (desktop's runners name the environment instead, #925). Either one means: no
|
|
230
231
|
// command here may touch the machine's real runner home.
|
|
231
232
|
//
|
|
232
233
|
// It reads process.env, ALWAYS, and takes no environment argument. An injected
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// The box's half of "a self-hosted signer refuses any job that is not a trusted
|
|
2
|
+
// dispatch" ([#875](https://github.com/Omega-JS-Stack/omega/issues/875)): the
|
|
3
|
+
// three files `omega runner install` writes beside the runner, so the guard the
|
|
4
|
+
// listener runs before every job is CONFIGURATION on the box rather than a list
|
|
5
|
+
// baked into the shared desktop template.
|
|
6
|
+
//
|
|
7
|
+
// A runner is registered to ONE owner and serves only that owner's repos, so
|
|
8
|
+
// the guard is per box, configured by the box owner (Ian 2026-09-10). The files:
|
|
9
|
+
//
|
|
10
|
+
// <runner home>\job-started.js the hook itself, a copy of src/runner/job-started.js
|
|
11
|
+
// <runner home>\allowed-repos.txt one `owner/name` (or `owner/*`) per line
|
|
12
|
+
// <runner home>\allowed-actors.txt one GitHub login per line
|
|
13
|
+
//
|
|
14
|
+
// and the path of the first one is delivered to each registered runner through
|
|
15
|
+
// its own `<runner dir>\.env` as `ACTIONS_RUNNER_HOOK_JOB_STARTED`, the same
|
|
16
|
+
// file the private HOME travels in
|
|
17
|
+
// ([#807](https://github.com/Omega-JS-Stack/omega/issues/807)).
|
|
18
|
+
//
|
|
19
|
+
// Where the lists COME from at setup: the orgs this box registered against
|
|
20
|
+
// (`<org>/*`, which is exactly the scope a registration already has) and the
|
|
21
|
+
// `GH_TOKEN` user's own login. Narrowing `<org>/*` to individual repos, or
|
|
22
|
+
// adding a second account, is an edit of the file, which is why an org already
|
|
23
|
+
// answered for, by a wildcard or by any repo line, is never appended again.
|
|
24
|
+
const path = require('path');
|
|
25
|
+
const jetpack = require('fs-jetpack');
|
|
26
|
+
|
|
27
|
+
// The hook owns the names of its own list files and the way it READS them, so
|
|
28
|
+
// the writer imports both rather than restating either: what this appends is
|
|
29
|
+
// what the hook sees, by construction. Requiring the hook here runs nothing
|
|
30
|
+
// (its work sits behind `require.main === module`), and the hook file itself
|
|
31
|
+
// stays builtins-only for the runner home it is copied into.
|
|
32
|
+
const { readList, REPOS_FILE, ACTORS_FILE } = require('../runner/job-started.js');
|
|
33
|
+
|
|
34
|
+
const HOOK_FILE = 'job-started.js';
|
|
35
|
+
|
|
36
|
+
const REPOS_HEADER = [
|
|
37
|
+
'# The repositories this box will sign for (#875).',
|
|
38
|
+
'# One `owner/name` per line; `owner/*` is every repo of one owner.',
|
|
39
|
+
'# `npx omega runner install` appends a line for an org it registered and has',
|
|
40
|
+
'# no line for yet, so narrowing one to single repos by hand sticks.',
|
|
41
|
+
'',
|
|
42
|
+
].join('\n');
|
|
43
|
+
|
|
44
|
+
const ACTORS_HEADER = [
|
|
45
|
+
'# The GitHub logins this box will sign for (#875): GITHUB_ACTOR must be one.',
|
|
46
|
+
'# One login per line. A `workflow_dispatch` carries the deploy token\'s user,',
|
|
47
|
+
'# which is the same account, so one line normally answers for every deploy.',
|
|
48
|
+
'',
|
|
49
|
+
].join('\n');
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The three files, by absolute path.
|
|
53
|
+
*
|
|
54
|
+
* @param {string} home - The runner home.
|
|
55
|
+
* @returns {{hook: string, repos: string, actors: string}} The paths.
|
|
56
|
+
*/
|
|
57
|
+
function jobGuardPaths(home) {
|
|
58
|
+
return {
|
|
59
|
+
hook: path.join(home, HOOK_FILE),
|
|
60
|
+
repos: path.join(home, REPOS_FILE),
|
|
61
|
+
actors: path.join(home, ACTORS_FILE),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The two allow lists, which are the box's CONFIGURATION: an uninstall keeps
|
|
67
|
+
* them the way it keeps the box's `.env`, so a re-install never asks again and
|
|
68
|
+
* a hand-narrowed list is never destroyed. The hook script is install state and
|
|
69
|
+
* goes with the rest.
|
|
70
|
+
*
|
|
71
|
+
* @param {string} home - The runner home.
|
|
72
|
+
* @returns {string[]} The two list paths.
|
|
73
|
+
*/
|
|
74
|
+
function jobGuardListFiles(home) {
|
|
75
|
+
const { repos, actors } = jobGuardPaths(home);
|
|
76
|
+
return [repos, actors];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Append the lines the file does not answer for yet, and nothing else: a file
|
|
80
|
+
// that already answers for every line is not rewritten at all, so running the
|
|
81
|
+
// setup twice writes the same bytes once.
|
|
82
|
+
function appendMissing(file, header, wanted, answered) {
|
|
83
|
+
const existing = readList(file);
|
|
84
|
+
const missing = wanted.filter((line) => !existing.some((entry) => answered(entry, line)));
|
|
85
|
+
if (missing.length === 0 && jetpack.exists(file) === 'file') return [];
|
|
86
|
+
|
|
87
|
+
const body = existing.length === 0 && jetpack.exists(file) !== 'file'
|
|
88
|
+
? `${header}${missing.join('\n')}\n`
|
|
89
|
+
: `${(jetpack.read(file) || '').replace(/\n*$/, '\n')}${missing.join('\n')}\n`;
|
|
90
|
+
jetpack.write(file, body);
|
|
91
|
+
return missing;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Lay the guard down beside the runner, idempotently.
|
|
96
|
+
*
|
|
97
|
+
* The hook script is COPIED from this package on every run, so a box picks up a
|
|
98
|
+
* framework update the next time it installs or starts; the allow lists are the
|
|
99
|
+
* operator's and are only ever appended to.
|
|
100
|
+
*
|
|
101
|
+
* @param {string} home - The runner home.
|
|
102
|
+
* @param {object} [options]
|
|
103
|
+
* @param {string[]} [options.orgs] - The orgs this box is registered against.
|
|
104
|
+
* @param {string} [options.actor] - The GH_TOKEN user's login (absent = leave the actors file alone).
|
|
105
|
+
* @param {object} [options.logger] - Logger for the one line each write prints.
|
|
106
|
+
* @returns {{hook: string, repos: string, actors: string, added: {repos: string[], actors: string[]}}} The paths, and what was appended.
|
|
107
|
+
*/
|
|
108
|
+
function ensureRunnerJobGuard(home, options) {
|
|
109
|
+
const { orgs = [], actor, logger } = options || {};
|
|
110
|
+
const paths = jobGuardPaths(home);
|
|
111
|
+
|
|
112
|
+
jetpack.copy(path.join(__dirname, '..', 'runner', HOOK_FILE), paths.hook, { overwrite: true });
|
|
113
|
+
|
|
114
|
+
// An org is answered for by a `<org>/*` line OR by any single repo of it: a
|
|
115
|
+
// person who narrowed `Omega-JS-Stack/*` to one repo does not get the
|
|
116
|
+
// wildcard back on the next install.
|
|
117
|
+
const addedRepos = appendMissing(
|
|
118
|
+
paths.repos,
|
|
119
|
+
REPOS_HEADER,
|
|
120
|
+
orgs.map((org) => `${org}/*`),
|
|
121
|
+
(entry, line) => entry.split('/')[0].toLowerCase() === line.split('/')[0].toLowerCase(),
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
// No actor (an offline heal, or a `GET /user` that did not answer) writes the
|
|
125
|
+
// file's header and nothing else: the operator sees the file the hook names,
|
|
126
|
+
// and an empty list refuses every job rather than passing one.
|
|
127
|
+
const addedActors = appendMissing(
|
|
128
|
+
paths.actors,
|
|
129
|
+
ACTORS_HEADER,
|
|
130
|
+
actor ? [actor] : [],
|
|
131
|
+
(entry, line) => entry.toLowerCase() === line.toLowerCase(),
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
if (logger) {
|
|
135
|
+
if (addedRepos.length > 0) logger.log(` Job guard: added ${addedRepos.join(', ')} to ${paths.repos}`);
|
|
136
|
+
if (addedActors.length > 0) logger.log(` Job guard: added ${addedActors.join(', ')} to ${paths.actors}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return { ...paths, added: { repos: addedRepos, actors: addedActors } };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
module.exports = {
|
|
143
|
+
HOOK_FILE,
|
|
144
|
+
REPOS_FILE,
|
|
145
|
+
ACTORS_FILE,
|
|
146
|
+
jobGuardPaths,
|
|
147
|
+
jobGuardListFiles,
|
|
148
|
+
ensureRunnerJobGuard,
|
|
149
|
+
};
|