@quenty/nevermore-cli 4.41.1 → 4.42.1-canary.783.30683193716.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.
Files changed (207) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/args/global-args.d.ts +13 -0
  3. package/dist/args/global-args.d.ts.map +1 -1
  4. package/dist/commands/batch-command/batch-deploy-command.d.ts +3 -0
  5. package/dist/commands/batch-command/batch-deploy-command.d.ts.map +1 -1
  6. package/dist/commands/batch-command/batch-deploy-command.js +90 -1
  7. package/dist/commands/batch-command/batch-deploy-command.js.map +1 -1
  8. package/dist/commands/batch-command/batch-test-command.d.ts.map +1 -1
  9. package/dist/commands/batch-command/batch-test-command.js +25 -4
  10. package/dist/commands/batch-command/batch-test-command.js.map +1 -1
  11. package/dist/commands/deploy-command/deploy-init.js +1 -1
  12. package/dist/commands/deploy-command/deploy-init.js.map +1 -1
  13. package/dist/commands/deploy-command/index.d.ts +3 -0
  14. package/dist/commands/deploy-command/index.d.ts.map +1 -1
  15. package/dist/commands/deploy-command/index.js +297 -60
  16. package/dist/commands/deploy-command/index.js.map +1 -1
  17. package/dist/commands/deploy-command/select-target.js +1 -1
  18. package/dist/commands/deploy-command/select-target.js.map +1 -1
  19. package/dist/commands/deploy-command/version-command.d.ts.map +1 -1
  20. package/dist/commands/deploy-command/version-command.js +138 -12
  21. package/dist/commands/deploy-command/version-command.js.map +1 -1
  22. package/dist/commands/test-command/test-command.d.ts.map +1 -1
  23. package/dist/commands/test-command/test-command.js +23 -11
  24. package/dist/commands/test-command/test-command.js.map +1 -1
  25. package/dist/nevermore.js +17 -0
  26. package/dist/nevermore.js.map +1 -1
  27. package/dist/utils/batch/changed-packages-utils.d.ts +1 -1
  28. package/dist/utils/batch/changed-packages-utils.d.ts.map +1 -1
  29. package/dist/utils/batch/changed-packages-utils.js +1 -1
  30. package/dist/utils/batch/changed-packages-utils.js.map +1 -1
  31. package/dist/utils/build/base-place-resolver-factory.d.ts +25 -0
  32. package/dist/utils/build/base-place-resolver-factory.d.ts.map +1 -0
  33. package/dist/utils/build/base-place-resolver-factory.js +40 -0
  34. package/dist/utils/build/base-place-resolver-factory.js.map +1 -0
  35. package/dist/utils/build/build.d.ts +13 -2
  36. package/dist/utils/build/build.d.ts.map +1 -1
  37. package/dist/utils/build/build.js.map +1 -1
  38. package/dist/utils/build/upload.d.ts +1 -1
  39. package/dist/utils/build/upload.d.ts.map +1 -1
  40. package/dist/utils/deploy/deploy-metadata.d.ts +1 -1
  41. package/dist/utils/deploy/deploy-metadata.d.ts.map +1 -1
  42. package/dist/utils/job-context/base-job-context.d.ts +3 -1
  43. package/dist/utils/job-context/base-job-context.d.ts.map +1 -1
  44. package/dist/utils/job-context/base-job-context.js +45 -6
  45. package/dist/utils/job-context/base-job-context.js.map +1 -1
  46. package/dist/utils/job-context/batch-script-job-context.d.ts +6 -0
  47. package/dist/utils/job-context/batch-script-job-context.d.ts.map +1 -1
  48. package/dist/utils/job-context/batch-script-job-context.js +13 -0
  49. package/dist/utils/job-context/batch-script-job-context.js.map +1 -1
  50. package/dist/utils/job-context/cloud-job-context.d.ts +2 -1
  51. package/dist/utils/job-context/cloud-job-context.d.ts.map +1 -1
  52. package/dist/utils/job-context/cloud-job-context.js +2 -2
  53. package/dist/utils/job-context/cloud-job-context.js.map +1 -1
  54. package/dist/utils/job-context/local-job-context.d.ts +2 -1
  55. package/dist/utils/job-context/local-job-context.d.ts.map +1 -1
  56. package/dist/utils/job-context/local-job-context.js +2 -2
  57. package/dist/utils/job-context/local-job-context.js.map +1 -1
  58. package/dist/utils/open-cloud/open-cloud-client.d.ts +20 -2
  59. package/dist/utils/open-cloud/open-cloud-client.d.ts.map +1 -1
  60. package/dist/utils/open-cloud/open-cloud-client.js +78 -21
  61. package/dist/utils/open-cloud/open-cloud-client.js.map +1 -1
  62. package/dist/utils/open-cloud/open-cloud-client.test.js +89 -12
  63. package/dist/utils/open-cloud/open-cloud-client.test.js.map +1 -1
  64. package/dist/utils/testing/parsers/batch-log-parser.d.ts +13 -5
  65. package/dist/utils/testing/parsers/batch-log-parser.d.ts.map +1 -1
  66. package/dist/utils/testing/parsers/batch-log-parser.js +114 -68
  67. package/dist/utils/testing/parsers/batch-log-parser.js.map +1 -1
  68. package/dist/utils/testing/parsers/batch-log-parser.test.js +57 -5
  69. package/dist/utils/testing/parsers/batch-log-parser.test.js.map +1 -1
  70. package/dist/utils/testing/parsers/traceback-parser.d.ts +31 -0
  71. package/dist/utils/testing/parsers/traceback-parser.d.ts.map +1 -0
  72. package/dist/utils/testing/parsers/traceback-parser.js +91 -0
  73. package/dist/utils/testing/parsers/traceback-parser.js.map +1 -0
  74. package/dist/utils/testing/parsers/traceback-parser.test.d.ts +2 -0
  75. package/dist/utils/testing/parsers/traceback-parser.test.d.ts.map +1 -0
  76. package/dist/utils/testing/parsers/traceback-parser.test.js +45 -0
  77. package/dist/utils/testing/parsers/traceback-parser.test.js.map +1 -0
  78. package/dist/utils/testing/runner/combined-project-generator.d.ts +1 -1
  79. package/dist/utils/testing/runner/combined-project-generator.d.ts.map +1 -1
  80. package/dist/utils/testing/runner/test-runner.d.ts +9 -1
  81. package/dist/utils/testing/runner/test-runner.d.ts.map +1 -1
  82. package/dist/utils/testing/runner/test-runner.js +28 -3
  83. package/dist/utils/testing/runner/test-runner.js.map +1 -1
  84. package/dist/utils/testing/runner/test-runner.test.d.ts +2 -0
  85. package/dist/utils/testing/runner/test-runner.test.d.ts.map +1 -0
  86. package/dist/utils/testing/runner/test-runner.test.js +18 -0
  87. package/dist/utils/testing/runner/test-runner.test.js.map +1 -0
  88. package/dist/utils/testing/test-log-parser.d.ts +32 -1
  89. package/dist/utils/testing/test-log-parser.d.ts.map +1 -1
  90. package/dist/utils/testing/test-log-parser.js +53 -9
  91. package/dist/utils/testing/test-log-parser.js.map +1 -1
  92. package/dist/utils/testing/test-log-parser.test.d.ts +2 -0
  93. package/dist/utils/testing/test-log-parser.test.d.ts.map +1 -0
  94. package/dist/utils/testing/test-log-parser.test.js +56 -0
  95. package/dist/utils/testing/test-log-parser.test.js.map +1 -0
  96. package/dist/utils/watch/github-context.d.ts +50 -0
  97. package/dist/utils/watch/github-context.d.ts.map +1 -0
  98. package/dist/utils/watch/github-context.js +125 -0
  99. package/dist/utils/watch/github-context.js.map +1 -0
  100. package/dist/utils/watch/github-context.test.d.ts +2 -0
  101. package/dist/utils/watch/github-context.test.d.ts.map +1 -0
  102. package/dist/utils/watch/github-context.test.js +112 -0
  103. package/dist/utils/watch/github-context.test.js.map +1 -0
  104. package/dist/utils/watch/http-watch-registry.d.ts +40 -0
  105. package/dist/utils/watch/http-watch-registry.d.ts.map +1 -0
  106. package/dist/utils/watch/http-watch-registry.js +262 -0
  107. package/dist/utils/watch/http-watch-registry.js.map +1 -0
  108. package/dist/utils/watch/http-watch-registry.test.d.ts +2 -0
  109. package/dist/utils/watch/http-watch-registry.test.d.ts.map +1 -0
  110. package/dist/utils/watch/http-watch-registry.test.js +211 -0
  111. package/dist/utils/watch/http-watch-registry.test.js.map +1 -0
  112. package/dist/utils/watch/local-watch-loop.d.ts +50 -0
  113. package/dist/utils/watch/local-watch-loop.d.ts.map +1 -0
  114. package/dist/utils/watch/local-watch-loop.js +103 -0
  115. package/dist/utils/watch/local-watch-loop.js.map +1 -0
  116. package/dist/utils/watch/local-watch-loop.test.d.ts +2 -0
  117. package/dist/utils/watch/local-watch-loop.test.d.ts.map +1 -0
  118. package/dist/utils/watch/local-watch-loop.test.js +170 -0
  119. package/dist/utils/watch/local-watch-loop.test.js.map +1 -0
  120. package/dist/utils/watch/register-notify-watches.d.ts +41 -0
  121. package/dist/utils/watch/register-notify-watches.d.ts.map +1 -0
  122. package/dist/utils/watch/register-notify-watches.js +159 -0
  123. package/dist/utils/watch/register-notify-watches.js.map +1 -0
  124. package/dist/utils/watch/register-notify-watches.test.d.ts +2 -0
  125. package/dist/utils/watch/register-notify-watches.test.d.ts.map +1 -0
  126. package/dist/utils/watch/register-notify-watches.test.js +225 -0
  127. package/dist/utils/watch/register-notify-watches.test.js.map +1 -0
  128. package/dist/utils/watch/register-watches.d.ts +68 -0
  129. package/dist/utils/watch/register-watches.d.ts.map +1 -0
  130. package/dist/utils/watch/register-watches.js +221 -0
  131. package/dist/utils/watch/register-watches.js.map +1 -0
  132. package/dist/utils/watch/register-watches.test.d.ts +2 -0
  133. package/dist/utils/watch/register-watches.test.d.ts.map +1 -0
  134. package/dist/utils/watch/register-watches.test.js +576 -0
  135. package/dist/utils/watch/register-watches.test.js.map +1 -0
  136. package/dist/utils/watch/stream-watch-loop.d.ts +54 -0
  137. package/dist/utils/watch/stream-watch-loop.d.ts.map +1 -0
  138. package/dist/utils/watch/stream-watch-loop.js +282 -0
  139. package/dist/utils/watch/stream-watch-loop.js.map +1 -0
  140. package/dist/utils/watch/stream-watch-loop.test.d.ts +2 -0
  141. package/dist/utils/watch/stream-watch-loop.test.d.ts.map +1 -0
  142. package/dist/utils/watch/stream-watch-loop.test.js +392 -0
  143. package/dist/utils/watch/stream-watch-loop.test.js.map +1 -0
  144. package/dist/utils/watch/websocket-watch-stream.d.ts +25 -0
  145. package/dist/utils/watch/websocket-watch-stream.d.ts.map +1 -0
  146. package/dist/utils/watch/websocket-watch-stream.js +306 -0
  147. package/dist/utils/watch/websocket-watch-stream.js.map +1 -0
  148. package/dist/utils/watch/websocket-watch-stream.test.d.ts +2 -0
  149. package/dist/utils/watch/websocket-watch-stream.test.d.ts.map +1 -0
  150. package/dist/utils/watch/websocket-watch-stream.test.js +475 -0
  151. package/dist/utils/watch/websocket-watch-stream.test.js.map +1 -0
  152. package/package.json +7 -4
  153. package/src/args/global-args.ts +13 -0
  154. package/src/commands/batch-command/batch-deploy-command.ts +105 -1
  155. package/src/commands/batch-command/batch-test-command.ts +86 -60
  156. package/src/commands/deploy-command/deploy-init.ts +1 -1
  157. package/src/commands/deploy-command/index.ts +327 -32
  158. package/src/commands/deploy-command/select-target.ts +1 -1
  159. package/src/commands/deploy-command/version-command.ts +215 -21
  160. package/src/commands/test-command/test-command.ts +31 -22
  161. package/src/nevermore.ts +19 -0
  162. package/src/utils/batch/changed-packages-utils.ts +1 -1
  163. package/src/utils/build/base-place-resolver-factory.ts +49 -0
  164. package/src/utils/build/build.ts +13 -2
  165. package/src/utils/build/upload.ts +1 -1
  166. package/src/utils/deploy/deploy-metadata.ts +1 -1
  167. package/src/utils/job-context/base-job-context.ts +68 -6
  168. package/src/utils/job-context/batch-script-job-context.ts +18 -0
  169. package/src/utils/job-context/cloud-job-context.ts +7 -2
  170. package/src/utils/job-context/local-job-context.ts +7 -2
  171. package/src/utils/open-cloud/open-cloud-client.test.ts +133 -14
  172. package/src/utils/open-cloud/open-cloud-client.ts +131 -35
  173. package/src/utils/testing/parsers/batch-log-parser.test.ts +70 -5
  174. package/src/utils/testing/parsers/batch-log-parser.ts +141 -80
  175. package/src/utils/testing/parsers/traceback-parser.test.ts +64 -0
  176. package/src/utils/testing/parsers/traceback-parser.ts +122 -0
  177. package/src/utils/testing/runner/combined-project-generator.ts +1 -1
  178. package/src/utils/testing/runner/test-runner.test.ts +29 -0
  179. package/src/utils/testing/runner/test-runner.ts +36 -4
  180. package/src/utils/testing/test-log-parser.test.ts +70 -0
  181. package/src/utils/testing/test-log-parser.ts +80 -10
  182. package/src/utils/watch/github-context.test.ts +154 -0
  183. package/src/utils/watch/github-context.ts +184 -0
  184. package/src/utils/watch/http-watch-registry.test.ts +330 -0
  185. package/src/utils/watch/http-watch-registry.ts +341 -0
  186. package/src/utils/watch/local-watch-loop.test.ts +197 -0
  187. package/src/utils/watch/local-watch-loop.ts +190 -0
  188. package/src/utils/watch/register-notify-watches.test.ts +282 -0
  189. package/src/utils/watch/register-notify-watches.ts +226 -0
  190. package/src/utils/watch/register-watches.test.ts +696 -0
  191. package/src/utils/watch/register-watches.ts +369 -0
  192. package/src/utils/watch/stream-watch-loop.test.ts +625 -0
  193. package/src/utils/watch/stream-watch-loop.ts +411 -0
  194. package/src/utils/watch/websocket-watch-stream.test.ts +581 -0
  195. package/src/utils/watch/websocket-watch-stream.ts +403 -0
  196. package/tsconfig.json +19 -6
  197. package/tsconfig.tsbuildinfo +1 -1
  198. package/dist/utils/build/deploy-config.d.ts +0 -71
  199. package/dist/utils/build/deploy-config.d.ts.map +0 -1
  200. package/dist/utils/build/deploy-config.js +0 -164
  201. package/dist/utils/build/deploy-config.js.map +0 -1
  202. package/dist/utils/build/deploy-config.test.d.ts +0 -2
  203. package/dist/utils/build/deploy-config.test.d.ts.map +0 -1
  204. package/dist/utils/build/deploy-config.test.js +0 -126
  205. package/dist/utils/build/deploy-config.test.js.map +0 -1
  206. package/src/utils/build/deploy-config.test.ts +0 -149
  207. package/src/utils/build/deploy-config.ts +0 -259
@@ -0,0 +1,159 @@
1
+ import { OutputHelper } from '@quenty/cli-output-helpers';
2
+ import { WATCH_BASELINE_KIND, WATCH_INPUT_NAME, sanitizeWatchName, } from '@quenty/nevermore-deploy';
3
+ import { HttpWatchRegistry } from './http-watch-registry.js';
4
+ import { tryResolveGithubDispatchContext } from './github-context.js';
5
+ /**
6
+ * Register a monitor that notifies this process instead of dispatching CI.
7
+ *
8
+ * Best-effort on purpose. Every way this can fail — no GitHub identity to
9
+ * register under, no token, a `"saved"` base place the service cannot poll, a
10
+ * service that is unreachable — has a working answer already: poll Open Cloud
11
+ * from here. So a failure downgrades the watch rather than the run, and the
12
+ * caller falls back.
13
+ */
14
+ export async function tryRegisterNotifyWatchesAsync(options) {
15
+ const { option, entries } = options;
16
+ if (entries.length === 0) {
17
+ return { success: false, reason: 'no_entries' };
18
+ }
19
+ // Without a shared key the service reads asset delivery, which reports
20
+ // published content only — it refuses `"saved"` at registration, and one
21
+ // refusal fails the whole request. Rather than watch some places one way and
22
+ // some the other, the whole run falls back to polling, which handles every
23
+ // version type this machine has credentials for.
24
+ const credentialed = options.robloxApiKey != null;
25
+ const unwatchable = credentialed
26
+ ? []
27
+ : entries.filter((e) => e.versionType !== 'published');
28
+ if (unwatchable.length > 0) {
29
+ return {
30
+ success: false,
31
+ reason: 'unwatchable_version_type',
32
+ detail: unwatchable.map((e) => e.label).join(', '),
33
+ };
34
+ }
35
+ const contextResult = tryResolveGithubDispatchContext({
36
+ useGhAuth: options.useGhAuth,
37
+ });
38
+ if (!contextResult.success) {
39
+ return { success: false, reason: 'no_github_context' };
40
+ }
41
+ const context = contextResult.context;
42
+ // Registration needs a write-scoped PAT even though a notify never spends it:
43
+ // the repository is the only identity this service has, and it is what a
44
+ // monitor's leases and caps are counted against.
45
+ if (!context.token) {
46
+ return { success: false, reason: 'no_token' };
47
+ }
48
+ const streamEntries = entries.map((entry) => ({
49
+ ...entry,
50
+ watchName: sanitizeWatchName(entry.label),
51
+ }));
52
+ _disambiguateWatchNames(streamEntries);
53
+ const watches = streamEntries.map((entry) => ({
54
+ name: entry.watchName,
55
+ source: {
56
+ type: 'roblox-place',
57
+ universeId: entry.universeId,
58
+ placeId: entry.placeId,
59
+ versionType: entry.versionType,
60
+ },
61
+ // Only when a key is shared do the two sides speak the same language; the
62
+ // `ready` reconcile covers this either way, by re-checking every watch
63
+ // against Open Cloud on connect.
64
+ ...(credentialed && entry.baseline != null
65
+ ? {
66
+ baselineVersion: String(entry.baseline),
67
+ baselineVersionKind: WATCH_BASELINE_KIND,
68
+ }
69
+ : {}),
70
+ action: {
71
+ type: 'notify',
72
+ // Same key a dispatching watch puts the selector under, so the two modes
73
+ // describe a change the same way even though only one crosses into CI.
74
+ payload: { [WATCH_INPUT_NAME]: entry.label },
75
+ },
76
+ }));
77
+ const registry = (options.createRegistry ?? _defaultRegistry)(option.registerUrl);
78
+ let result;
79
+ try {
80
+ result = await registry.registerAsync({
81
+ // Distinct from the dispatching monitor's name. They hold different
82
+ // actions, and re-registering replaces a monitor's whole watch list — so
83
+ // sharing a name would mean a local watch silently disarming CI's.
84
+ monitorName: sanitizeWatchName(`${options.monitorName}/local`),
85
+ repository: context.repository,
86
+ githubToken: context.token,
87
+ robloxApiKey: options.robloxApiKey,
88
+ watches,
89
+ });
90
+ }
91
+ catch (err) {
92
+ return {
93
+ success: false,
94
+ reason: 'register_failed',
95
+ detail: err instanceof Error ? err.message : String(err),
96
+ };
97
+ }
98
+ if (!result.monitorId) {
99
+ return { success: false, reason: 'no_monitor_id' };
100
+ }
101
+ OutputHelper.verbose(`Registered a notify monitor (${result.monitorId}), lease ${option.lease}.`);
102
+ return {
103
+ success: true,
104
+ monitorId: result.monitorId,
105
+ credential: context.token,
106
+ entries: streamEntries,
107
+ };
108
+ }
109
+ /** Why the run is polling instead, in words a user can act on. */
110
+ export function describeNotifyWatchFallback(result) {
111
+ switch (result.reason) {
112
+ case 'no_entries':
113
+ return 'nothing to watch';
114
+ case 'unwatchable_version_type':
115
+ return (`${result.detail} tracks "saved", which the service can only see ` +
116
+ 'with a shared Open Cloud key (--watch-share-api-key)');
117
+ case 'no_github_context':
118
+ return 'this checkout has no GitHub repository to register under';
119
+ case 'no_token':
120
+ return ('no GitHub token — set NEVERMORE_WATCH_TOKEN, or pass ' +
121
+ '--watch-use-gh-auth to use the one `gh` already holds');
122
+ case 'no_monitor_id':
123
+ return 'the service registered the monitor but returned no id';
124
+ case 'register_failed':
125
+ return `the watch service refused the registration — ${result.detail}`;
126
+ }
127
+ }
128
+ function _defaultRegistry(registerUrl) {
129
+ return new HttpWatchRegistry({ registerUrl });
130
+ }
131
+ /**
132
+ * Make every watch name unique within the monitor.
133
+ *
134
+ * Names come from selectors, which are unique per target — except that an
135
+ * unnamed place in a multi-place target has no name to contribute, so two of
136
+ * them produce the same selector. Appending the place id separates them without
137
+ * failing a deploy that already shipped.
138
+ */
139
+ function _disambiguateWatchNames(entries) {
140
+ const byName = new Map();
141
+ for (const entry of entries) {
142
+ const group = byName.get(entry.watchName);
143
+ if (group) {
144
+ group.push(entry);
145
+ }
146
+ else {
147
+ byName.set(entry.watchName, [entry]);
148
+ }
149
+ }
150
+ for (const group of byName.values()) {
151
+ if (group.length === 1) {
152
+ continue;
153
+ }
154
+ for (const entry of group) {
155
+ entry.watchName = sanitizeWatchName(`${entry.watchName}/${entry.placeId}`);
156
+ }
157
+ }
158
+ }
159
+ //# sourceMappingURL=register-notify-watches.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-notify-watches.js","sourceRoot":"","sources":["../../../src/utils/watch/register-notify-watches.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=register-notify-watches.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-notify-watches.test.d.ts","sourceRoot":"","sources":["../../../src/utils/watch/register-notify-watches.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,225 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { parseWatchOption, } from '@quenty/nevermore-deploy';
3
+ import { describeNotifyWatchFallback, tryRegisterNotifyWatchesAsync, } from './register-notify-watches.js';
4
+ const REGISTER_BASE = 'https://watch.example.com/v1/register/';
5
+ const watchOption = () => parseWatchOption(`${REGISTER_BASE}30m`);
6
+ beforeEach(() => {
7
+ vi.stubEnv('GITHUB_REPOSITORY', 'Quenty/egg-hunt-2026');
8
+ vi.stubEnv('GITHUB_REF_NAME', 'release');
9
+ vi.stubEnv('NEVERMORE_WATCH_TOKEN', 'token-value');
10
+ });
11
+ afterEach(() => {
12
+ vi.unstubAllEnvs();
13
+ });
14
+ function makeEntry(overrides = {}) {
15
+ return {
16
+ label: 'integration.places.hub',
17
+ universeId: 10,
18
+ placeId: 20,
19
+ versionType: 'published',
20
+ ...overrides,
21
+ };
22
+ }
23
+ function makeRecordingRegistry(monitorId) {
24
+ const requests = [];
25
+ const create = () => ({
26
+ registerAsync: async (request) => {
27
+ requests.push(request);
28
+ return { monitorId: monitorId ?? 'mon_1', changed: true };
29
+ },
30
+ triggerAsync: async () => ({ results: [] }),
31
+ });
32
+ return { requests, create };
33
+ }
34
+ function notifyAction(request, index = 0) {
35
+ const action = request.watches[index].action;
36
+ expect(action.type).toBe('notify');
37
+ return action;
38
+ }
39
+ describe('tryRegisterNotifyWatchesAsync', () => {
40
+ it('registers notify actions carrying the selector', async () => {
41
+ const registry = makeRecordingRegistry();
42
+ const result = await tryRegisterNotifyWatchesAsync({
43
+ option: watchOption(),
44
+ monitorName: 'egg-hunt/integration',
45
+ entries: [makeEntry({ baseline: 158 })],
46
+ createRegistry: registry.create,
47
+ });
48
+ expect(result.success).toBe(true);
49
+ const request = registry.requests[0];
50
+ // No baseline: the service compares its own token (an asset-delivery
51
+ // content hash) by string equality, so the lock's Open Cloud version number
52
+ // would read as drift on the first poll. The `ready` reconcile covers it.
53
+ expect(request.watches[0].baselineVersion).toBeUndefined();
54
+ expect(request.watches[0].baselineVersionKind).toBeUndefined();
55
+ expect(request.watches[0].source).toEqual({
56
+ type: 'roblox-place',
57
+ universeId: 10,
58
+ placeId: 20,
59
+ versionType: 'published',
60
+ });
61
+ expect(notifyAction(request).payload).toEqual({
62
+ target: 'integration.places.hub',
63
+ });
64
+ });
65
+ // Re-registering replaces a monitor's whole watch list, so a local watch that
66
+ // shared CI's monitor name would silently disarm the workflow dispatch.
67
+ it('registers under a monitor name distinct from the dispatching one', async () => {
68
+ const registry = makeRecordingRegistry();
69
+ await tryRegisterNotifyWatchesAsync({
70
+ option: watchOption(),
71
+ monitorName: 'egg-hunt/integration',
72
+ entries: [makeEntry()],
73
+ createRegistry: registry.create,
74
+ });
75
+ expect(registry.requests[0].monitorName).toBe('egg-hunt/integration/local');
76
+ });
77
+ it('hands back stream entries keyed by the registered watch name', async () => {
78
+ const registry = makeRecordingRegistry();
79
+ const result = await tryRegisterNotifyWatchesAsync({
80
+ option: watchOption(),
81
+ monitorName: 'egg-hunt/integration',
82
+ entries: [makeEntry()],
83
+ createRegistry: registry.create,
84
+ });
85
+ expect(result.success && result.entries[0].watchName).toBe(registry.requests[0].watches[0].name);
86
+ expect(result.success && result.monitorId).toBe('mon_1');
87
+ expect(result.success && result.credential).toBe('token-value');
88
+ });
89
+ // Places are only optionally named, so a multi-place target with unnamed
90
+ // places produces the same selector twice. The service resolves a duplicate
91
+ // name by dropping a watch rather than failing.
92
+ it('separates watches that would share a name', async () => {
93
+ const registry = makeRecordingRegistry();
94
+ await tryRegisterNotifyWatchesAsync({
95
+ option: watchOption(),
96
+ monitorName: 'egg-hunt/integration',
97
+ entries: [makeEntry({ placeId: 20 }), makeEntry({ placeId: 21 })],
98
+ createRegistry: registry.create,
99
+ });
100
+ const names = registry.requests[0].watches.map((w) => w.name);
101
+ expect(new Set(names).size).toBe(2);
102
+ expect(names).toEqual([
103
+ 'integration.places.hub/20',
104
+ 'integration.places.hub/21',
105
+ ]);
106
+ });
107
+ it('shares the Open Cloud key only when asked', async () => {
108
+ const registry = makeRecordingRegistry();
109
+ await tryRegisterNotifyWatchesAsync({
110
+ option: watchOption(),
111
+ monitorName: 'egg-hunt/integration',
112
+ entries: [makeEntry()],
113
+ createRegistry: registry.create,
114
+ });
115
+ expect(registry.requests[0].robloxApiKey).toBeUndefined();
116
+ await tryRegisterNotifyWatchesAsync({
117
+ option: watchOption(),
118
+ monitorName: 'egg-hunt/integration',
119
+ entries: [makeEntry()],
120
+ robloxApiKey: 'secret',
121
+ createRegistry: registry.create,
122
+ });
123
+ expect(registry.requests[1].robloxApiKey).toBe('secret');
124
+ });
125
+ });
126
+ describe('tryRegisterNotifyWatchesAsync falling back', () => {
127
+ // Every failure here has a working answer already — poll Open Cloud from this
128
+ // machine — so none of them may throw.
129
+ it('watches a "saved" place when a key is shared', async () => {
130
+ const registry = makeRecordingRegistry();
131
+ const result = await tryRegisterNotifyWatchesAsync({
132
+ option: watchOption(),
133
+ monitorName: 'egg-hunt/integration',
134
+ entries: [makeEntry({ versionType: 'saved', baseline: 158 })],
135
+ robloxApiKey: 'secret',
136
+ createRegistry: registry.create,
137
+ });
138
+ expect(result.success).toBe(true);
139
+ const watch = registry.requests[0].watches[0];
140
+ expect(watch.source.versionType).toBe('saved');
141
+ // Same vocabulary once a key is in play, so the lock value is sendable.
142
+ expect(watch.baselineVersion).toBe('158');
143
+ expect(watch.baselineVersionKind).toBe('roblox-place-version');
144
+ });
145
+ it('declines a "saved" base place the service cannot poll', async () => {
146
+ const registry = makeRecordingRegistry();
147
+ const result = await tryRegisterNotifyWatchesAsync({
148
+ option: watchOption(),
149
+ monitorName: 'egg-hunt/integration',
150
+ entries: [makeEntry({ versionType: 'saved' })],
151
+ createRegistry: registry.create,
152
+ });
153
+ expect(result).toMatchObject({
154
+ success: false,
155
+ reason: 'unwatchable_version_type',
156
+ });
157
+ expect(registry.requests).toEqual([]);
158
+ });
159
+ // Splitting the run — streaming the published places and polling the saved
160
+ // one — would leave two watch loops disagreeing about what is current.
161
+ it('declines the whole run when only some places are unwatchable', async () => {
162
+ const result = await tryRegisterNotifyWatchesAsync({
163
+ option: watchOption(),
164
+ monitorName: 'egg-hunt/integration',
165
+ entries: [
166
+ makeEntry({ label: 'integration.places.hub' }),
167
+ makeEntry({ label: 'integration.places.lobby', versionType: 'saved' }),
168
+ ],
169
+ createRegistry: makeRecordingRegistry().create,
170
+ });
171
+ expect(result).toMatchObject({ success: false });
172
+ expect(result.success === false && describeNotifyWatchFallback(result)).toMatch(/integration\.places\.lobby/);
173
+ });
174
+ it('declines without a token, since registration has no identity', async () => {
175
+ vi.stubEnv('NEVERMORE_WATCH_TOKEN', '');
176
+ vi.stubEnv('GITHUB_TOKEN', '');
177
+ const result = await tryRegisterNotifyWatchesAsync({
178
+ option: watchOption(),
179
+ monitorName: 'egg-hunt/integration',
180
+ entries: [makeEntry()],
181
+ createRegistry: makeRecordingRegistry().create,
182
+ });
183
+ expect(result).toMatchObject({ success: false, reason: 'no_token' });
184
+ });
185
+ it('declines when the service refuses the registration', async () => {
186
+ const result = await tryRegisterNotifyWatchesAsync({
187
+ option: watchOption(),
188
+ monitorName: 'egg-hunt/integration',
189
+ entries: [makeEntry()],
190
+ createRegistry: () => ({
191
+ registerAsync: async () => {
192
+ throw new Error('503 Service Unavailable');
193
+ },
194
+ triggerAsync: async () => ({ results: [] }),
195
+ }),
196
+ });
197
+ expect(result).toMatchObject({
198
+ success: false,
199
+ reason: 'register_failed',
200
+ });
201
+ expect(result.success === false && describeNotifyWatchFallback(result)).toMatch(/503 Service Unavailable/);
202
+ });
203
+ it('declines when the service returns no monitor to stream', async () => {
204
+ const result = await tryRegisterNotifyWatchesAsync({
205
+ option: watchOption(),
206
+ monitorName: 'egg-hunt/integration',
207
+ entries: [makeEntry()],
208
+ createRegistry: () => ({
209
+ registerAsync: async () => ({ changed: true }),
210
+ triggerAsync: async () => ({ results: [] }),
211
+ }),
212
+ });
213
+ expect(result).toMatchObject({ success: false, reason: 'no_monitor_id' });
214
+ });
215
+ it('declines when there is nothing to watch', async () => {
216
+ const result = await tryRegisterNotifyWatchesAsync({
217
+ option: watchOption(),
218
+ monitorName: 'egg-hunt/integration',
219
+ entries: [],
220
+ createRegistry: makeRecordingRegistry().create,
221
+ });
222
+ expect(result).toMatchObject({ success: false, reason: 'no_entries' });
223
+ });
224
+ });
225
+ //# sourceMappingURL=register-notify-watches.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-notify-watches.test.js","sourceRoot":"","sources":["../../../src/utils/watch/register-notify-watches.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ import { type BasePlaceResolver, type DeployTarget, type WatchOption, type WatchRegistry } from '@quenty/nevermore-deploy';
2
+ /** One place `--watch` should consider registering. */
3
+ export interface WatchCandidate {
4
+ /**
5
+ * Deploy target the place belongs to. A selector (`integration.places.hub`)
6
+ * is accepted and narrowed to its target, since the dispatch selector is
7
+ * rebuilt from the target and the place — appending to a selector that
8
+ * already names a place would produce `integration.places.hub.places.hub`,
9
+ * which nothing can re-resolve.
10
+ */
11
+ targetName: string;
12
+ /** npm package name, used to keep watch names unique across a batch. */
13
+ packageName: string;
14
+ /** Package directory, used to read the base place version out of the lock. */
15
+ packagePath: string;
16
+ place: DeployTarget;
17
+ }
18
+ export interface RegisterWatchesOptions {
19
+ option: WatchOption;
20
+ /**
21
+ * Lease key within the repository. Every watch this invocation is
22
+ * responsible for goes under this one name, and re-registering replaces the
23
+ * whole list — so the candidates must be the complete set, not just what
24
+ * deployed.
25
+ */
26
+ monitorName: string;
27
+ candidates: WatchCandidate[];
28
+ /**
29
+ * Open Cloud key to share, so the service can read private base places, see
30
+ * `"saved"` versions, and report versions in the same vocabulary as the lock.
31
+ */
32
+ robloxApiKey?: string;
33
+ /** Reads base place versions out of the lock, for baselines. */
34
+ resolver: BasePlaceResolver;
35
+ /** Let the GitHub CLI supply the token when no env var does. */
36
+ useGhAuth?: boolean;
37
+ /**
38
+ * Force a dispatch immediately after registering, ignoring drift.
39
+ *
40
+ * Registering only proves the service accepted the config. Firing proves the
41
+ * workflow actually receives the selector, which is the half that has
42
+ * historically broken — so a dryrun asks for it.
43
+ */
44
+ triggerAfterRegister?: boolean;
45
+ /** Injected in tests; defaults to the HTTP registry. */
46
+ createRegistry?: (registerUrl: string) => WatchRegistry;
47
+ }
48
+ export interface RegisterWatchesResult {
49
+ /** Watches in the registered monitor. Zero means nothing was sent. */
50
+ registered: number;
51
+ /** True when the service reported the config differing from what it held. */
52
+ changed?: boolean;
53
+ /** Watches that dispatched, when a trigger was requested. */
54
+ triggered?: number;
55
+ }
56
+ /**
57
+ * Register every watch this invocation owns, in one call.
58
+ *
59
+ * One call is not just an efficiency: the service replaces a monitor's entire
60
+ * watch list on re-apply, so splitting a run across several registrations under
61
+ * one name would leave only the last one standing. The caller decides what the
62
+ * complete set is; this turns it into a request.
63
+ *
64
+ * Runs after the deploy so the monitor only exists once the build it is meant
65
+ * to keep fresh has actually shipped.
66
+ */
67
+ export declare function registerWatchesAsync(options: RegisterWatchesOptions): Promise<RegisterWatchesResult>;
68
+ //# sourceMappingURL=register-watches.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-watches.d.ts","sourceRoot":"","sources":["../../../src/utils/watch/register-watches.ts"],"names":[],"mappings":"AACA,OAAO,EAOL,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAEjB,KAAK,WAAW,EAEhB,KAAK,aAAa,EAEnB,MAAM,0BAA0B,CAAC;AAiBlC,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAC7B;;;;;;OAMG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,WAAW,EAAE,MAAM,CAAC;IACpB,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,YAAY,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,WAAW,CAAC;IACpB;;;;;OAKG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,cAAc,EAAE,CAAC;IAC7B;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gEAAgE;IAChE,QAAQ,EAAE,iBAAiB,CAAC;IAC5B,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;OAMG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,wDAAwD;IACxD,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,aAAa,CAAC;CACzD;AAED,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CA2HhC"}