@omega.js/desktop 0.50.0 → 0.52.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 +2 -2
- 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 +176 -42
- 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 +146 -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 +635 -5
- 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 +125 -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 +249 -103
- 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 +425 -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 +505 -75
- package/dist/vendor/devkit/git-auth.js +73 -0
- package/dist/vendor/devkit/git-remote.js +172 -0
- package/dist/vendor/devkit/github-repo.js +290 -0
- package/dist/vendor/devkit/local.js +98 -3
- package/dist/vendor/devkit/lockfile.js +127 -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 +388 -0
- package/dist/vendor/devkit/preludes/index.js +120 -0
- package/dist/vendor/devkit/preludes/origin-heal.js +142 -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 +231 -57
- 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 +29 -19
- package/docs/runner.md +51 -14
- package/docs/shared/brands.md +12 -6
- package/docs/shared/breaking-changes.md +375 -21
- package/docs/shared/config.md +764 -199
- package/docs/shared/deploys.md +217 -91
- package/docs/shared/icons.md +18 -0
- package/docs/shared/local-dev.md +28 -8
- 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 +60 -34
- 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/dist/commands/release.js
CHANGED
|
@@ -1,50 +1,64 @@
|
|
|
1
|
-
// release
|
|
1
|
+
// release: trigger the GitHub Actions Build & Release workflow, then follow the
|
|
2
|
+
// run it started.
|
|
2
3
|
//
|
|
3
4
|
// Replaces the old "do it from my laptop" release flow with "let CI do it, but make it
|
|
4
5
|
// feel local." User runs `npm run release` (or `npx omega release`) and gets:
|
|
5
|
-
// 1.
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
6
|
+
// 1. The ONE deploy lane every target takes (`@omega.js/devkit/deploy`'s
|
|
7
|
+
// deployViaDispatch, #872, #915): the composed workflow files reach the
|
|
8
|
+
// default branch when they differ there (GitHub registers a workflow from
|
|
9
|
+
// that branch), the brand folder is force-pushed to `omega-deploy` (packed
|
|
10
|
+
// when it is linked), and the workflow is dispatched on that ref (the
|
|
11
|
+
// brand's own repo and the composed workflow name: devkit's
|
|
12
|
+
// dispatchTarget, #847).
|
|
13
|
+
// 2. The ONE run follower every dispatched deploy uses
|
|
14
|
+
// (`@omega.js/devkit/deploy-follow`, [#873](https://github.com/Omega-JS-Stack/omega/issues/873)):
|
|
15
|
+
// it finds the run, polls it, prints each job's log with the job's name in
|
|
16
|
+
// front, and exits 1 on any conclusion but success. This file owned that
|
|
17
|
+
// follower alone until #873 gave the other three targets the same one.
|
|
18
|
+
// 3. Everything teed to <root>/logs/deploy.log, the one name every target's
|
|
19
|
+
// deploy writes (docs/shared/logging.md), ANSI stripped from the file.
|
|
17
20
|
|
|
18
21
|
const path = require('path');
|
|
19
|
-
const fs = require('fs');
|
|
20
|
-
const jetpack = require('fs-jetpack');
|
|
21
22
|
|
|
22
|
-
const
|
|
23
|
-
const {
|
|
23
|
+
const attachLogFile = require('../utils/attach-log-file.js');
|
|
24
|
+
const { deployViaDispatch, dispatchTarget, laneLabel, resolveToken } = require('../vendor/devkit/deploy.js');
|
|
25
|
+
const { followRun } = require('../vendor/devkit/deploy-follow.js');
|
|
26
|
+
const { targetNameFromDir } = require('../vendor/config/index.js');
|
|
24
27
|
const Manager = new (require('../build.js'));
|
|
25
28
|
|
|
26
29
|
const logger = Manager.logger('release');
|
|
27
30
|
|
|
28
|
-
const POLL_INTERVAL_MS = 5000;
|
|
29
|
-
|
|
30
31
|
module.exports = async function release(options = {}) {
|
|
31
32
|
const projectRoot = process.cwd();
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
// The DRY RUN arrives here too ([#895](https://github.com/Omega-JS-Stack/omega/issues/895)):
|
|
34
|
+
// this verb is desktop's one dispatch call site, so the plan a preview prints
|
|
35
|
+
// is built by the very call a real run sends, threading the ref and the
|
|
36
|
+
// snapshot sha the same way.
|
|
37
|
+
const dryRun = !!(options.dryRun || options['dry-run']);
|
|
38
|
+
|
|
39
|
+
// The whole verb in one file, from its first line (#873), the token refusal
|
|
40
|
+
// below included: a caller that hands the writers back afterwards then pops
|
|
41
|
+
// THIS layer, never the one under it. A no-op when `omega deploy` delegated
|
|
42
|
+
// here and already attached this exact path.
|
|
43
|
+
const logPath = path.join(projectRoot, 'logs', 'deploy.log');
|
|
44
|
+
attachLogFile(logPath);
|
|
45
|
+
|
|
46
|
+
// The ONE token chain devkit resolves for every target, `GH_TOKEN` →
|
|
47
|
+
// `GITHUB_TOKEN` → `gh auth token`, and the very one the follower below is
|
|
48
|
+
// handed: testing the bare variable refused a machine signed in with `gh`
|
|
49
|
+
// and holding no variable at all, which is most of them. A dry run needs
|
|
50
|
+
// none: every step under it is a read or a plan.
|
|
51
|
+
if (!dryRun && !resolveToken()) {
|
|
52
|
+
throw new Error('No GitHub token: set GH_TOKEN in .env (or GITHUB_TOKEN in the shell), or sign in with `gh auth login`, so we can dispatch the workflow.');
|
|
42
53
|
}
|
|
43
54
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
//
|
|
47
|
-
|
|
55
|
+
// The CI dispatch address, from the config and the scaffold: the brand's own
|
|
56
|
+
// repo and the workflow file the target's ensure-target pass actually wrote
|
|
57
|
+
// (composed as `desktop-build.yml` at the brand root inside a monorepo, plain
|
|
58
|
+
// `build.yml` standalone). ONE helper for all four targets
|
|
59
|
+
// ([#847](https://github.com/Omega-JS-Stack/omega/issues/847)), where this
|
|
60
|
+
// file used to keep desktop's own copy of it.
|
|
61
|
+
const { owner, repo, workflow: WORKFLOW_FILE } = dispatchTarget({ projectRoot, config: Manager.getConfig(), workflow: 'build.yml' });
|
|
48
62
|
|
|
49
63
|
// Optional --platforms / --platform flag forwarded as a workflow input. Accepts a
|
|
50
64
|
// single value ('windows') or comma-separated list ('mac,linux'). Special value
|
|
@@ -53,234 +67,67 @@ module.exports = async function release(options = {}) {
|
|
|
53
67
|
// workflows (without a `platforms` input declared) keep working unchanged.
|
|
54
68
|
const platforms = options.platforms || options.platform || null;
|
|
55
69
|
|
|
56
|
-
const dispatchArgs = { owner, repo, workflow_id: WORKFLOW_FILE, ref };
|
|
57
|
-
if (platforms) dispatchArgs.inputs = { platforms: String(platforms) };
|
|
58
|
-
|
|
59
70
|
const platformsLabel = platforms ? ` (platforms=${platforms})` : '';
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// 1. Mark a "before" timestamp so we can identify the new run we just dispatched.
|
|
63
|
-
const before = new Date();
|
|
64
|
-
|
|
65
|
-
// 2. Dispatch.
|
|
66
|
-
await octokit.rest.actions.createWorkflowDispatch(dispatchArgs);
|
|
67
|
-
|
|
68
|
-
// 3. Wait for the new run to appear (GH Actions takes a few seconds to register it).
|
|
69
|
-
const run = await waitForNewRun({ octokit, owner, repo, after: before, workflowFile: WORKFLOW_FILE });
|
|
70
|
-
if (!run) {
|
|
71
|
-
throw new Error('Workflow dispatch succeeded but no new run appeared after 60s. Check GitHub Actions UI.');
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
logger.log(`Run started: ${run.html_url}`);
|
|
75
|
-
require('../vendor/devkit/deploy-record.js').recordDeploy({ dir: projectRoot, target: 'desktop', detail: { method: 'release-dispatch' } });
|
|
76
|
-
|
|
77
|
-
// 4. Set up the CI log tee.
|
|
78
|
-
const logsDir = path.join(projectRoot, 'logs');
|
|
79
|
-
jetpack.dir(logsDir);
|
|
80
|
-
const ciLogPath = path.join(logsDir, 'ci.log');
|
|
81
|
-
// Truncate so each release run starts fresh.
|
|
82
|
-
fs.writeFileSync(ciLogPath, `# release run ${run.html_url}\n# started ${new Date().toISOString()}\n\n`);
|
|
83
|
-
const logFile = fs.createWriteStream(ciLogPath, { flags: 'a' });
|
|
84
|
-
|
|
85
|
-
// Spinner state. We tick every 250ms even between polls so the terminal feels alive.
|
|
86
|
-
// The spinner line uses \r to overwrite itself; before printing real content we clear
|
|
87
|
-
// the line, write content, then re-render the spinner. File output is unaffected.
|
|
88
|
-
const startedAt = Date.now();
|
|
89
|
-
const isTty = process.stdout.isTTY === true;
|
|
90
|
-
const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
91
|
-
let spinnerFrame = 0;
|
|
92
|
-
let pollCount = 0;
|
|
93
|
-
let latestState = null;
|
|
94
|
-
let latestJobs = [];
|
|
95
|
-
|
|
96
|
-
function clearSpinner() {
|
|
97
|
-
if (!isTty) return;
|
|
98
|
-
process.stdout.write('\r\x1b[2K');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function renderSpinner() {
|
|
102
|
-
if (!isTty || !latestState) return;
|
|
103
|
-
const frame = SPINNER_FRAMES[spinnerFrame % SPINNER_FRAMES.length];
|
|
104
|
-
const elapsed = formatElapsed(Date.now() - startedAt);
|
|
105
|
-
const status = `${latestState.status}${latestState.conclusion ? ` (${latestState.conclusion})` : ''}`;
|
|
106
|
-
const jobBits = latestJobs.map((j) => `${jobSymbol(j)} ${j.name}`).join(' ');
|
|
107
|
-
const line = `${frame} ${status} · ${elapsed} · ${pollCount} polls · ${jobBits}`;
|
|
108
|
-
// Truncate so we never wrap (which breaks the \r overwrite).
|
|
109
|
-
const cols = process.stdout.columns || 120;
|
|
110
|
-
const safe = line.length > cols - 1 ? line.slice(0, cols - 2) + '…' : line;
|
|
111
|
-
process.stdout.write(`\r${safe}`);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Print line(s) to stdout AND tee to file. Clears spinner first; spinner re-renders next tick.
|
|
115
|
-
function print(line) {
|
|
116
|
-
clearSpinner();
|
|
117
|
-
process.stdout.write(line);
|
|
118
|
-
logFile.write(stripAnsi(line));
|
|
71
|
+
if (!dryRun) {
|
|
72
|
+
logger.log(`Triggering ${owner}/${repo} workflow ${WORKFLOW_FILE}${platformsLabel}...`);
|
|
119
73
|
}
|
|
120
74
|
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
renderSpinner();
|
|
125
|
-
}, 250) : null;
|
|
75
|
+
// 1. Mark a "before" timestamp so the follower identifies the run we just
|
|
76
|
+
// dispatched rather than the one before it.
|
|
77
|
+
const since = new Date();
|
|
126
78
|
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
pollCount += 1;
|
|
134
|
-
const { data: state } = await octokit.rest.actions.getWorkflowRun({
|
|
135
|
-
owner, repo, run_id: run.id,
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// Pull all jobs. Each job has steps; each step has a step-level status.
|
|
139
|
-
const { data: jobsResp } = await octokit.rest.actions.listJobsForWorkflowRun({
|
|
140
|
-
owner, repo, run_id: run.id, per_page: 100,
|
|
141
|
-
});
|
|
142
|
-
const jobs = jobsResp.jobs || [];
|
|
143
|
-
latestState = state;
|
|
144
|
-
latestJobs = jobs;
|
|
145
|
-
|
|
146
|
-
// For each job, fetch its logs (only available once steps complete; for in-progress
|
|
147
|
-
// jobs, GH returns 404 or partial — we tolerate both).
|
|
148
|
-
for (const job of jobs) {
|
|
149
|
-
// Skip queued jobs entirely (no logs yet).
|
|
150
|
-
if (job.status === 'queued') continue;
|
|
151
|
-
|
|
152
|
-
let logsText = '';
|
|
153
|
-
try {
|
|
154
|
-
const { data } = await octokit.request('GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs', {
|
|
155
|
-
owner, repo, job_id: job.id,
|
|
156
|
-
});
|
|
157
|
-
// Octokit returns the raw text content here.
|
|
158
|
-
logsText = typeof data === 'string' ? data : Buffer.from(data || '').toString('utf8');
|
|
159
|
-
} catch (e) {
|
|
160
|
-
// 404 = logs not ready yet. Other errors we just skip until next tick.
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
const printed = printedByJob.get(job.id) || 0;
|
|
165
|
-
if (logsText.length > printed) {
|
|
166
|
-
const fresh = logsText.slice(printed);
|
|
167
|
-
// Prefix each line with the job name so interleaved output is readable.
|
|
168
|
-
const prefix = `[${job.name}] `;
|
|
169
|
-
for (const rawLine of fresh.split('\n')) {
|
|
170
|
-
if (!rawLine) continue;
|
|
171
|
-
print(`${prefix}${rawLine}\n`);
|
|
172
|
-
}
|
|
173
|
-
printedByJob.set(job.id, logsText.length);
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Print a one-line status banner if it changed (no spam — only on transition).
|
|
178
|
-
const banner = formatStatusBanner(state, jobs);
|
|
179
|
-
if (banner !== lastStatusLine) {
|
|
180
|
-
print(`\n${banner}\n`);
|
|
181
|
-
lastStatusLine = banner;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
if (state.status === 'completed') {
|
|
185
|
-
clearSpinner();
|
|
186
|
-
logFile.end();
|
|
187
|
-
const success = state.conclusion === 'success';
|
|
188
|
-
const symbol = success ? '✓' : '✗';
|
|
189
|
-
logger.log(`${symbol} Run ${state.conclusion} — ${state.html_url}`);
|
|
190
|
-
logger.log(`Logs: ${path.relative(projectRoot, ciLogPath)}`);
|
|
191
|
-
if (!success) {
|
|
192
|
-
process.exitCode = 1;
|
|
193
|
-
throw new Error(`Release run failed (conclusion=${state.conclusion}). See ${ciLogPath} or ${state.html_url}.`);
|
|
194
|
-
}
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
await sleep(POLL_INTERVAL_MS);
|
|
199
|
-
}
|
|
200
|
-
} finally {
|
|
201
|
-
if (spinnerTimer) clearInterval(spinnerTimer);
|
|
202
|
-
clearSpinner();
|
|
203
|
-
}
|
|
204
|
-
};
|
|
205
|
-
|
|
206
|
-
// The CI dispatch address, from the config and the scaffold: the brand's APP
|
|
207
|
-
// repo (`@omega.js/devkit/deploy`'s dispatchRepo, the one call web and the
|
|
208
|
-
// extension deploy verbs make too) and the workflow file the target's
|
|
209
|
-
// ensure-target pass actually wrote (composed as `desktop-build.yml` at the
|
|
210
|
-
// brand root inside a monorepo, plain `build.yml` standalone:
|
|
211
|
-
// `@omega.js/devkit/ci-workflows` owns that name for all four frameworks).
|
|
212
|
-
// Never the git remote: a brand nested in another repo would dispatch on the
|
|
213
|
-
// enclosing one, which for the playground is the framework monorepo itself.
|
|
214
|
-
// Exported for tests.
|
|
215
|
-
function dispatchTarget({ projectRoot, config }) {
|
|
216
|
-
const { composedWorkflowName } = require('../vendor/devkit/ci-workflows.js');
|
|
217
|
-
const { resolveSeedMode } = require('../vendor/config/index.js');
|
|
218
|
-
const { owner, repo } = dispatchRepo(config);
|
|
219
|
-
|
|
220
|
-
return {
|
|
79
|
+
// 2. Deliver the brand and dispatch, through the ONE lane (#872, #915): the
|
|
80
|
+
// composed workflows to the repo's default branch when they differ, the brand
|
|
81
|
+
// folder to `omega-deploy`, which is the ref this dispatches. An explicit
|
|
82
|
+
// `--ref` still wins.
|
|
83
|
+
const { plan, lane, sha } = await deployViaDispatch({
|
|
84
|
+
workflow: WORKFLOW_FILE,
|
|
221
85
|
owner,
|
|
222
86
|
repo,
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
if (j.status === 'queued') return '·';
|
|
242
|
-
return '?';
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
async function waitForNewRun({ octokit, owner, repo, after, workflowFile }) {
|
|
246
|
-
const deadline = Date.now() + 60_000;
|
|
247
|
-
while (Date.now() < deadline) {
|
|
248
|
-
const { data } = await octokit.rest.actions.listWorkflowRuns({
|
|
249
|
-
owner, repo, workflow_id: workflowFile, per_page: 5, event: 'workflow_dispatch',
|
|
250
|
-
});
|
|
251
|
-
const runs = data.workflow_runs || [];
|
|
252
|
-
// The newest run created strictly after our dispatch timestamp.
|
|
253
|
-
const fresh = runs.find((r) => new Date(r.created_at).getTime() >= after.getTime() - 1000);
|
|
254
|
-
if (fresh) return fresh;
|
|
255
|
-
await sleep(2000);
|
|
87
|
+
dir: projectRoot,
|
|
88
|
+
ref: options.ref,
|
|
89
|
+
inputs: platforms ? { platforms: String(platforms) } : undefined,
|
|
90
|
+
// The brand root's one snapshot for the whole fan-out, when a brand-root
|
|
91
|
+
// deploy spawned this verb (#901): the push is done, so this run
|
|
92
|
+
// dispatches against that sha instead of pushing over it. Nobody types it.
|
|
93
|
+
snapshot: options.snapshot,
|
|
94
|
+
dryRun,
|
|
95
|
+
logger,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// The plan IS the dry run: what would be sent, and nothing sent.
|
|
99
|
+
if (dryRun) {
|
|
100
|
+
logger.log(`DRY RUN (${laneLabel(lane)}), would send:`);
|
|
101
|
+
logger.log(` ${plan.method} ${plan.url}`);
|
|
102
|
+
logger.log(` body: ${JSON.stringify(plan.body)}`);
|
|
103
|
+
logger.log(` then watch: ${plan.runsUrl}`);
|
|
104
|
+
return;
|
|
256
105
|
}
|
|
257
|
-
return null;
|
|
258
|
-
}
|
|
259
106
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
107
|
+
logger.log(`Dispatched ${WORKFLOW_FILE} (${laneLabel(lane, sha)}): CI builds, signs, and publishes the release artifacts.`);
|
|
108
|
+
// The ONE runs-url formula is the plan's (`buildDispatch`), the same line
|
|
109
|
+
// backend, web and the extension print: rebuilt by hand here, it was a second
|
|
110
|
+
// copy of an address the dispatch already answered.
|
|
111
|
+
logger.log(`Watch: ${plan.runsUrl}`);
|
|
264
112
|
|
|
265
|
-
|
|
266
|
-
try {
|
|
267
|
-
const { execute } = require('node-powertools');
|
|
268
|
-
const out = await execute('git rev-parse --abbrev-ref HEAD', { cwd: projectRoot, log: false });
|
|
269
|
-
return String(out || '').trim();
|
|
270
|
-
} catch (e) {
|
|
271
|
-
return null;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
113
|
+
require('../vendor/devkit/deploy-record.js').recordDeploy({ dir: projectRoot, target: targetNameFromDir(projectRoot) || 'desktop', detail: { method: 'release-dispatch' } });
|
|
274
114
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
115
|
+
// 3. Follow the run to its verdict: the jobs' logs stream in here, and a red
|
|
116
|
+
// run throws, so this verb exits 1 on anything but success (#873). The run
|
|
117
|
+
// also has to be building the tree this deploy pushed (#902): on the push
|
|
118
|
+
// lane there is no sha and the check is off, because that lane's run head is
|
|
119
|
+
// the developer's own commit.
|
|
120
|
+
const { conclusion } = await followRun({
|
|
121
|
+
owner,
|
|
122
|
+
repo,
|
|
123
|
+
workflow: WORKFLOW_FILE,
|
|
124
|
+
since,
|
|
125
|
+
headSha: sha,
|
|
126
|
+
token: resolveToken(),
|
|
127
|
+
logger,
|
|
128
|
+
});
|
|
278
129
|
|
|
279
|
-
|
|
280
|
-
// Minimal ANSI stripper — handles CSI sequences (colors, cursor moves).
|
|
281
|
-
return String(s).replace(/\x1b\[[0-9;]*[A-Za-z]/g, '');
|
|
282
|
-
}
|
|
130
|
+
logger.log(`Logs: ${path.relative(projectRoot, logPath)}`);
|
|
283
131
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
module.exports.dispatchTarget = dispatchTarget;
|
|
132
|
+
return conclusion;
|
|
133
|
+
};
|