@humanbased/crosscheck 1.2.0-beta.2 โ†’ 1.2.0-beta.35

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 (103) hide show
  1. package/crosscheck.config.example.yml +42 -0
  2. package/dist/__tests__/can-write-verdict.test.d.ts +2 -0
  3. package/dist/__tests__/can-write-verdict.test.d.ts.map +1 -0
  4. package/dist/__tests__/can-write-verdict.test.js +31 -0
  5. package/dist/__tests__/can-write-verdict.test.js.map +1 -0
  6. package/dist/__tests__/linear-client.test.d.ts +2 -0
  7. package/dist/__tests__/linear-client.test.d.ts.map +1 -0
  8. package/dist/__tests__/linear-client.test.js +120 -0
  9. package/dist/__tests__/linear-client.test.js.map +1 -0
  10. package/dist/__tests__/linear-comment.test.d.ts +2 -0
  11. package/dist/__tests__/linear-comment.test.d.ts.map +1 -0
  12. package/dist/__tests__/linear-comment.test.js +151 -0
  13. package/dist/__tests__/linear-comment.test.js.map +1 -0
  14. package/dist/__tests__/linear-identity.test.d.ts +2 -0
  15. package/dist/__tests__/linear-identity.test.d.ts.map +1 -0
  16. package/dist/__tests__/linear-identity.test.js +253 -0
  17. package/dist/__tests__/linear-identity.test.js.map +1 -0
  18. package/dist/__tests__/linear-notify.test.d.ts +2 -0
  19. package/dist/__tests__/linear-notify.test.d.ts.map +1 -0
  20. package/dist/__tests__/linear-notify.test.js +144 -0
  21. package/dist/__tests__/linear-notify.test.js.map +1 -0
  22. package/dist/__tests__/linear-ref.test.d.ts +2 -0
  23. package/dist/__tests__/linear-ref.test.d.ts.map +1 -0
  24. package/dist/__tests__/linear-ref.test.js +261 -0
  25. package/dist/__tests__/linear-ref.test.js.map +1 -0
  26. package/dist/__tests__/linear-verify.test.d.ts +2 -0
  27. package/dist/__tests__/linear-verify.test.d.ts.map +1 -0
  28. package/dist/__tests__/linear-verify.test.js +113 -0
  29. package/dist/__tests__/linear-verify.test.js.map +1 -0
  30. package/dist/__tests__/linear-worker.test.d.ts +2 -0
  31. package/dist/__tests__/linear-worker.test.d.ts.map +1 -0
  32. package/dist/__tests__/linear-worker.test.js +83 -0
  33. package/dist/__tests__/linear-worker.test.js.map +1 -0
  34. package/dist/__tests__/linear-write-possible.test.d.ts +2 -0
  35. package/dist/__tests__/linear-write-possible.test.d.ts.map +1 -0
  36. package/dist/__tests__/linear-write-possible.test.js +30 -0
  37. package/dist/__tests__/linear-write-possible.test.js.map +1 -0
  38. package/dist/__tests__/optimize.test.js +1 -0
  39. package/dist/__tests__/optimize.test.js.map +1 -1
  40. package/dist/__tests__/runner.test.js +29 -1
  41. package/dist/__tests__/runner.test.js.map +1 -1
  42. package/dist/commands/review.d.ts.map +1 -1
  43. package/dist/commands/review.js +48 -1
  44. package/dist/commands/review.js.map +1 -1
  45. package/dist/commands/run.d.ts.map +1 -1
  46. package/dist/commands/run.js +23 -3
  47. package/dist/commands/run.js.map +1 -1
  48. package/dist/commands/status.d.ts.map +1 -1
  49. package/dist/commands/status.js +40 -1
  50. package/dist/commands/status.js.map +1 -1
  51. package/dist/commands/watch.d.ts.map +1 -1
  52. package/dist/commands/watch.js +52 -6
  53. package/dist/commands/watch.js.map +1 -1
  54. package/dist/config/loader.d.ts +3 -1
  55. package/dist/config/loader.d.ts.map +1 -1
  56. package/dist/config/loader.js +13 -0
  57. package/dist/config/loader.js.map +1 -1
  58. package/dist/config/schema.d.ts +208 -0
  59. package/dist/config/schema.d.ts.map +1 -1
  60. package/dist/config/schema.js +39 -0
  61. package/dist/config/schema.js.map +1 -1
  62. package/dist/issues/ticket-ref.d.ts.map +1 -1
  63. package/dist/issues/ticket-ref.js +6 -5
  64. package/dist/issues/ticket-ref.js.map +1 -1
  65. package/dist/lib/clone.d.ts.map +1 -1
  66. package/dist/lib/clone.js +6 -2
  67. package/dist/lib/clone.js.map +1 -1
  68. package/dist/lib/runner.d.ts +12 -0
  69. package/dist/lib/runner.d.ts.map +1 -1
  70. package/dist/lib/runner.js +81 -23
  71. package/dist/lib/runner.js.map +1 -1
  72. package/dist/lib/workflow.d.ts +9 -0
  73. package/dist/lib/workflow.d.ts.map +1 -1
  74. package/dist/lib/workflow.js +20 -0
  75. package/dist/lib/workflow.js.map +1 -1
  76. package/dist/linear/client.d.ts +18 -0
  77. package/dist/linear/client.d.ts.map +1 -0
  78. package/dist/linear/client.js +67 -0
  79. package/dist/linear/client.js.map +1 -0
  80. package/dist/linear/comment.d.ts +20 -0
  81. package/dist/linear/comment.d.ts.map +1 -0
  82. package/dist/linear/comment.js +53 -0
  83. package/dist/linear/comment.js.map +1 -0
  84. package/dist/linear/identity.d.ts +47 -0
  85. package/dist/linear/identity.d.ts.map +1 -0
  86. package/dist/linear/identity.js +151 -0
  87. package/dist/linear/identity.js.map +1 -0
  88. package/dist/linear/notify.d.ts +35 -0
  89. package/dist/linear/notify.d.ts.map +1 -0
  90. package/dist/linear/notify.js +65 -0
  91. package/dist/linear/notify.js.map +1 -0
  92. package/dist/linear/ref.d.ts +13 -0
  93. package/dist/linear/ref.d.ts.map +1 -0
  94. package/dist/linear/ref.js +90 -0
  95. package/dist/linear/ref.js.map +1 -0
  96. package/dist/linear/verify.d.ts +21 -0
  97. package/dist/linear/verify.d.ts.map +1 -0
  98. package/dist/linear/verify.js +65 -0
  99. package/dist/linear/verify.js.map +1 -0
  100. package/docs/linear-identity-contract.md +133 -0
  101. package/docs/linear-identity.md +224 -0
  102. package/get-started.md +39 -0
  103. package/package.json +1 -1
@@ -0,0 +1,253 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { renderSignature, mintAppToken, normalizeScopes, resolveLinearAuth, isLinearConfigError } from '../linear/identity.js';
3
+ import { LinearConfigSchema } from '../config/schema.js';
4
+ const SECRET = 'super-secret-value';
5
+ const CLIENT_ID = 'client-abc';
6
+ const MINTED = 'minted-app-token';
7
+ function cfg(overrides = {}) {
8
+ return LinearConfigSchema.parse({ enabled: true, ...overrides });
9
+ }
10
+ function okMint() {
11
+ return vi.fn(async () => new Response(JSON.stringify({ access_token: MINTED }), { status: 200 }));
12
+ }
13
+ describe('renderSignature', () => {
14
+ it('expands {actor} and {product}', () => {
15
+ expect(renderSignature('๐Ÿค– {actor} ยท {product}', 'crosscheck', 'crosscheck')).toBe('๐Ÿค– crosscheck ยท crosscheck');
16
+ });
17
+ it('expands repeated placeholders', () => {
18
+ expect(renderSignature('{actor}/{actor} on {product}', 'cc', 'p')).toBe('cc/cc on p');
19
+ });
20
+ it('leaves unknown placeholders untouched', () => {
21
+ expect(renderSignature('{actor} {nope}', 'cc', 'p')).toBe('cc {nope}');
22
+ });
23
+ });
24
+ describe('mintAppToken', () => {
25
+ it('posts client_credentials as a form body and returns the access token', async () => {
26
+ const fetchImpl = okMint();
27
+ const token = await mintAppToken({ clientId: CLIENT_ID, clientSecret: SECRET, scopes: 'read write' }, { fetchImpl });
28
+ expect(token).toBe(MINTED);
29
+ const [url, init] = fetchImpl.mock.calls[0];
30
+ expect(url).toBe('https://api.linear.app/oauth/token');
31
+ expect(init.method).toBe('POST');
32
+ expect(init.headers['Content-Type']).toBe('application/x-www-form-urlencoded');
33
+ // The secret travels in the request body โ€” never a URL parameter, never argv.
34
+ expect(String(url)).not.toContain(SECRET);
35
+ const body = new URLSearchParams(init.body);
36
+ expect(body.get('grant_type')).toBe('client_credentials');
37
+ expect(body.get('client_id')).toBe(CLIENT_ID);
38
+ expect(body.get('client_secret')).toBe(SECRET);
39
+ expect(body.get('scope')).toBe('read,write');
40
+ });
41
+ it('throws without leaking the secret when the mint is rejected', async () => {
42
+ const fetchImpl = vi.fn(async () => new Response('{"error":"invalid_client"}', { status: 401 }));
43
+ const err = await mintAppToken({ clientId: CLIENT_ID, clientSecret: SECRET, scopes: 'read write' }, { fetchImpl })
44
+ .then(() => null, (e) => e);
45
+ expect(err).toBeInstanceOf(Error);
46
+ expect(err.message).toContain('401');
47
+ expect(err.message).not.toContain(SECRET);
48
+ expect(err.message).not.toContain(CLIENT_ID);
49
+ });
50
+ it('throws when the response has no access_token', async () => {
51
+ const fetchImpl = vi.fn(async () => new Response('{"ok":true}', { status: 200 }));
52
+ await expect(mintAppToken({ clientId: CLIENT_ID, clientSecret: SECRET, scopes: 'read write' }, { fetchImpl })).rejects.toThrow(/no access_token/i);
53
+ });
54
+ it('throws on a non-JSON response', async () => {
55
+ const fetchImpl = vi.fn(async () => new Response('<html>gateway</html>', { status: 200 }));
56
+ await expect(mintAppToken({ clientId: CLIENT_ID, clientSecret: SECRET, scopes: 'read write' }, { fetchImpl })).rejects.toThrow();
57
+ });
58
+ });
59
+ describe('resolveLinearAuth โ€” api_key mode (T0)', () => {
60
+ it('uses the supplied key with a bare Authorization header and no createAsUser', async () => {
61
+ const auth = await resolveLinearAuth(cfg(), { apiKey: 'lin_api_xyz' });
62
+ expect(auth.mode).toBe('api_key');
63
+ expect(auth.token).toBe('lin_api_xyz');
64
+ expect(auth.bearer).toBe(false);
65
+ expect(auth.createAsUser).toBeUndefined();
66
+ expect(auth.signature).toBe('๐Ÿค– crosscheck ยท crosscheck');
67
+ });
68
+ it('honours a configured actor in the signature', async () => {
69
+ const auth = await resolveLinearAuth(cfg({ identity: { actor: 'crosscheck/reviewer' } }), { apiKey: 'k' });
70
+ expect(auth.signature).toBe('๐Ÿค– crosscheck/reviewer ยท crosscheck');
71
+ });
72
+ it('aborts when no key is available, naming the env var to set', async () => {
73
+ await expect(resolveLinearAuth(cfg(), {})).rejects.toThrow(/LINEAR_API_KEY/);
74
+ });
75
+ it('never performs a network call', async () => {
76
+ const fetchImpl = okMint();
77
+ await resolveLinearAuth(cfg(), { apiKey: 'k' }, { fetchImpl });
78
+ expect(fetchImpl).not.toHaveBeenCalled();
79
+ });
80
+ });
81
+ describe('resolveLinearAuth โ€” client_credentials mode (T1)', () => {
82
+ const t1 = () => cfg({ auth: { mode: 'client_credentials' }, identity: { actor: 'crosscheck' } });
83
+ it('mints a per-run token and sets createAsUser to the actor', async () => {
84
+ const fetchImpl = okMint();
85
+ const auth = await resolveLinearAuth(t1(), { clientId: CLIENT_ID, clientSecret: SECRET }, { fetchImpl });
86
+ expect(auth.mode).toBe('client_credentials');
87
+ expect(auth.token).toBe(MINTED);
88
+ expect(auth.bearer).toBe(true);
89
+ expect(auth.createAsUser).toBe('crosscheck');
90
+ expect(fetchImpl).toHaveBeenCalledTimes(1);
91
+ });
92
+ it('keeps the signature line as T1 fallback text', async () => {
93
+ const auth = await resolveLinearAuth(t1(), { clientId: CLIENT_ID, clientSecret: SECRET }, { fetchImpl: okMint() });
94
+ expect(auth.signature).toBe('๐Ÿค– crosscheck ยท crosscheck');
95
+ });
96
+ it('passes the configured scopes through to the mint', async () => {
97
+ const fetchImpl = okMint();
98
+ const config = cfg({ auth: { mode: 'client_credentials', scopes: 'read write initiative:read' } });
99
+ await resolveLinearAuth(config, { clientId: CLIENT_ID, clientSecret: SECRET }, { fetchImpl });
100
+ const [, init] = fetchImpl.mock.calls[0];
101
+ expect(new URLSearchParams(init.body).get('scope')).toBe('read,write,initiative:read');
102
+ });
103
+ describe('abort semantics โ€” never silently fall back to api_key', () => {
104
+ it('aborts when the mint fails even though an api_key is available', async () => {
105
+ const fetchImpl = vi.fn(async () => new Response('nope', { status: 500 }));
106
+ await expect(resolveLinearAuth(t1(), { clientId: CLIENT_ID, clientSecret: SECRET, apiKey: 'lin_api_fallback' }, { fetchImpl })).rejects.toThrow(/client_credentials/);
107
+ });
108
+ it('aborts when credentials are missing even though an api_key is available', async () => {
109
+ const fetchImpl = okMint();
110
+ await expect(resolveLinearAuth(t1(), { apiKey: 'lin_api_fallback' }, { fetchImpl })).rejects.toThrow(/LINEAR_CLIENT_ID/);
111
+ expect(fetchImpl).not.toHaveBeenCalled();
112
+ });
113
+ it('names both env vars when only one is set', async () => {
114
+ await expect(resolveLinearAuth(t1(), { clientId: CLIENT_ID }, { fetchImpl: okMint() })).rejects.toThrow(/LINEAR_CLIENT_SECRET/);
115
+ });
116
+ it('does not leak the secret in the abort message', async () => {
117
+ const fetchImpl = vi.fn(async () => new Response('nope', { status: 500 }));
118
+ const err = await resolveLinearAuth(t1(), { clientId: CLIENT_ID, clientSecret: SECRET }, { fetchImpl })
119
+ .then(() => null, (e) => e);
120
+ expect(err.message).not.toContain(SECRET);
121
+ });
122
+ });
123
+ it('respects custom env var names in the abort message', async () => {
124
+ const config = cfg({ auth: { mode: 'client_credentials', client_id_env: 'LINEAR_HB_AGENT_GATEWAY_CLIENT_ID' } });
125
+ await expect(resolveLinearAuth(config, {})).rejects.toThrow(/LINEAR_HB_AGENT_GATEWAY_CLIENT_ID/);
126
+ });
127
+ });
128
+ describe('normalizeScopes', () => {
129
+ // Linear documents comma-separated; OAuth 2.0 specifies space-separated. Operators
130
+ // write both, so accept either and always send what Linear asks for.
131
+ it('passes a comma-separated list through', () => {
132
+ expect(normalizeScopes('read,write')).toBe('read,write');
133
+ });
134
+ it('converts a space-separated list', () => {
135
+ expect(normalizeScopes('read write')).toBe('read,write');
136
+ });
137
+ it('handles mixed separators and stray whitespace', () => {
138
+ expect(normalizeScopes(' read, write initiative:read ')).toBe('read,write,initiative:read');
139
+ });
140
+ it('drops empty entries rather than sending blanks', () => {
141
+ expect(normalizeScopes('read,,write,')).toBe('read,write');
142
+ });
143
+ it('returns empty for an empty input', () => {
144
+ expect(normalizeScopes(' ')).toBe('');
145
+ });
146
+ });
147
+ describe('LinearConfigError โ€” exit-code classification', () => {
148
+ // The CLI contract reserves exit 2 for unexpected errors; a missing env var is a
149
+ // user error and must be 1, matching what `crosscheck review` already returns.
150
+ it('flags a missing api_key as a config error', async () => {
151
+ const err = await resolveLinearAuth(cfg(), {}).then(() => null, (e) => e);
152
+ expect(isLinearConfigError(err)).toBe(true);
153
+ });
154
+ it('flags missing client credentials as a config error', async () => {
155
+ const config = cfg({ auth: { mode: 'client_credentials' } });
156
+ const err = await resolveLinearAuth(config, {}).then(() => null, (e) => e);
157
+ expect(isLinearConfigError(err)).toBe(true);
158
+ });
159
+ it('flags a rejected mint as a config error', async () => {
160
+ const fetchImpl = vi.fn(async () => new Response('nope', { status: 401 }));
161
+ const config = cfg({ auth: { mode: 'client_credentials' } });
162
+ const err = await resolveLinearAuth(config, { clientId: 'a', clientSecret: 'b' }, { fetchImpl })
163
+ .then(() => null, (e) => e);
164
+ expect(isLinearConfigError(err)).toBe(true);
165
+ });
166
+ it('does not flag unrelated errors', () => {
167
+ expect(isLinearConfigError(new Error('network down'))).toBe(false);
168
+ expect(isLinearConfigError(undefined)).toBe(false);
169
+ });
170
+ });
171
+ describe('outage vs misconfiguration', () => {
172
+ // A 5xx is Linear's problem, not the operator's โ€” blaming it on the config
173
+ // would exit 1 and send someone hunting a broken env var that is fine.
174
+ const t1 = () => cfg({ auth: { mode: 'client_credentials' } });
175
+ const creds = { clientId: 'id', clientSecret: 'secret' };
176
+ const status = (code) => vi.fn(async () => new Response('x', { status: code }));
177
+ it('treats a rejected credential (401) as a config error', async () => {
178
+ const err = await resolveLinearAuth(t1(), creds, { fetchImpl: status(401) }).then(() => null, (e) => e);
179
+ expect(isLinearConfigError(err)).toBe(true);
180
+ });
181
+ it('treats a bad request (400) as a config error', async () => {
182
+ const err = await resolveLinearAuth(t1(), creds, { fetchImpl: status(400) }).then(() => null, (e) => e);
183
+ expect(isLinearConfigError(err)).toBe(true);
184
+ });
185
+ it('does NOT blame the config for a 500', async () => {
186
+ const err = await resolveLinearAuth(t1(), creds, { fetchImpl: status(500) }).then(() => null, (e) => e);
187
+ expect(err).toBeInstanceOf(Error);
188
+ expect(isLinearConfigError(err)).toBe(false);
189
+ });
190
+ it('does NOT blame the config for a 503', async () => {
191
+ const err = await resolveLinearAuth(t1(), creds, { fetchImpl: status(503) }).then(() => null, (e) => e);
192
+ expect(isLinearConfigError(err)).toBe(false);
193
+ });
194
+ it('does NOT blame the config for a transport failure', async () => {
195
+ const fetchImpl = vi.fn(async () => { throw new Error('ECONNRESET'); });
196
+ const err = await resolveLinearAuth(t1(), creds, { fetchImpl }).then(() => null, (e) => e);
197
+ expect(isLinearConfigError(err)).toBe(false);
198
+ });
199
+ it('aborts either way โ€” never falls back to api_key', async () => {
200
+ for (const code of [401, 500]) {
201
+ const err = await resolveLinearAuth(t1(), { ...creds, apiKey: 'lin_api_fallback' }, { fetchImpl: status(code) })
202
+ .then(() => null, (e) => e);
203
+ expect(err.message).toMatch(/aborting rather than falling back/);
204
+ }
205
+ });
206
+ });
207
+ describe('rate limiting is transient, not misconfiguration', () => {
208
+ const t1 = () => cfg({ auth: { mode: 'client_credentials' } });
209
+ const creds = { clientId: 'id', clientSecret: 'secret' };
210
+ const status = (code) => vi.fn(async () => new Response('x', { status: code }));
211
+ it('does not blame the config for a 429', async () => {
212
+ const err = await resolveLinearAuth(t1(), creds, { fetchImpl: status(429) }).then(() => null, (e) => e);
213
+ expect(isLinearConfigError(err)).toBe(false);
214
+ });
215
+ it('still blames the config for a 403', async () => {
216
+ const err = await resolveLinearAuth(t1(), creds, { fetchImpl: status(403) }).then(() => null, (e) => e);
217
+ expect(isLinearConfigError(err)).toBe(true);
218
+ });
219
+ });
220
+ describe('a rejected mint names the variables to check', () => {
221
+ // A bare "HTTP 401" leaves an operator with custom env names guessing which
222
+ // credential to rotate. Names only โ€” never values.
223
+ const rejected = () => vi.fn(async () => new Response('nope', { status: 401 }));
224
+ const creds = { clientId: 'the-id', clientSecret: 'the-secret' };
225
+ it('names the default variables', async () => {
226
+ const config = cfg({ auth: { mode: 'client_credentials' } });
227
+ const err = await resolveLinearAuth(config, creds, { fetchImpl: rejected() })
228
+ .then(() => null, (e) => e);
229
+ expect(err.message).toContain('LINEAR_CLIENT_ID');
230
+ expect(err.message).toContain('LINEAR_CLIENT_SECRET');
231
+ });
232
+ it('names custom variables', async () => {
233
+ const config = cfg({
234
+ auth: {
235
+ mode: 'client_credentials',
236
+ client_id_env: 'LINEAR_HB_AGENT_GATEWAY_CLIENT_ID',
237
+ client_secret_env: 'LINEAR_HB_AGENT_GATEWAY_CLIENT_SECRET',
238
+ },
239
+ });
240
+ const err = await resolveLinearAuth(config, creds, { fetchImpl: rejected() })
241
+ .then(() => null, (e) => e);
242
+ expect(err.message).toContain('LINEAR_HB_AGENT_GATEWAY_CLIENT_ID');
243
+ expect(err.message).toContain('LINEAR_HB_AGENT_GATEWAY_CLIENT_SECRET');
244
+ });
245
+ it('still never leaks the values', async () => {
246
+ const config = cfg({ auth: { mode: 'client_credentials' } });
247
+ const err = await resolveLinearAuth(config, creds, { fetchImpl: rejected() })
248
+ .then(() => null, (e) => e);
249
+ expect(err.message).not.toContain('the-secret');
250
+ expect(err.message).not.toContain('the-id');
251
+ });
252
+ });
253
+ //# sourceMappingURL=linear-identity.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-identity.test.js","sourceRoot":"","sources":["../../src/__tests__/linear-identity.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=linear-notify.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-notify.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/linear-notify.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,144 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { notifyLinear, issueBelongsToWorkspace } from '../linear/notify.js';
3
+ import { LinearConfigSchema } from '../config/schema.js';
4
+ const AUTH = {
5
+ mode: 'client_credentials',
6
+ token: 'minted',
7
+ bearer: true,
8
+ actor: 'crosscheck',
9
+ signature: '๐Ÿค– crosscheck ยท crosscheck',
10
+ signatureTemplate: '๐Ÿค– {actor} ยท {product}',
11
+ product: 'crosscheck',
12
+ createAsUser: 'crosscheck',
13
+ };
14
+ const PR = {
15
+ branch: 'feat/in-2269-identity',
16
+ title: 'feat: tiered Linear identity',
17
+ body: '',
18
+ url: 'https://github.com/acme/app/pull/12',
19
+ sha: 'abc1234',
20
+ };
21
+ const BASE = { auth: AUTH, pr: PR, verdict: 'APPROVE', reviewer: 'codex', origin: 'claude', model: 'gpt-5' };
22
+ function cfg(overrides = {}) {
23
+ return LinearConfigSchema.parse({ enabled: true, team_keys: ['IN'], ...overrides });
24
+ }
25
+ /** Replies to the issue lookup, then the comment mutation. */
26
+ function scriptedFetch(issueNodes, mutation) {
27
+ let call = 0;
28
+ return vi.fn(async () => {
29
+ call++;
30
+ if (call === 1)
31
+ return new Response(JSON.stringify({ data: { issues: { nodes: issueNodes } } }), { status: 200 });
32
+ return new Response(JSON.stringify({
33
+ data: mutation ?? { commentCreate: { success: true, comment: { id: 'c1', url: 'https://linear.app/x/c1' } } },
34
+ }), { status: 200 });
35
+ });
36
+ }
37
+ const FOUND = [{ id: 'uuid-1', identifier: 'IN-2269', url: 'https://linear.app/x/issue/IN-2269' }];
38
+ describe('notifyLinear', () => {
39
+ it('posts to the issue referenced by the branch', async () => {
40
+ const fetchImpl = scriptedFetch(FOUND);
41
+ const result = await notifyLinear({ ...BASE, config: cfg() }, { fetchImpl });
42
+ expect(result).toEqual({ status: 'posted', identifier: 'IN-2269', url: 'https://linear.app/x/c1' });
43
+ });
44
+ it('sends a body that leads with the signature and carries createAsUser', async () => {
45
+ const fetchImpl = scriptedFetch(FOUND);
46
+ await notifyLinear({ ...BASE, config: cfg() }, { fetchImpl });
47
+ const calls = fetchImpl.mock.calls;
48
+ const mutation = JSON.parse(calls[1][1].body);
49
+ expect(mutation.variables.createAsUser).toBe('crosscheck');
50
+ expect(mutation.variables.body.split('\n')[0]).toBe('๐Ÿค– crosscheck ยท crosscheck');
51
+ });
52
+ it('skips when the verdict is not in comment_on', async () => {
53
+ const fetchImpl = scriptedFetch(FOUND);
54
+ const result = await notifyLinear({ ...BASE, config: cfg({ comment_on: ['BLOCK'] }) }, { fetchImpl });
55
+ expect(result).toEqual({ status: 'skipped', reason: 'verdict-not-configured' });
56
+ expect(fetchImpl).not.toHaveBeenCalled();
57
+ });
58
+ it('skips when the PR references no Linear issue', async () => {
59
+ const fetchImpl = scriptedFetch(FOUND);
60
+ const pr = { ...PR, branch: 'feat/no-ref', title: 'chore: bump', body: '' };
61
+ const result = await notifyLinear({ ...BASE, pr, config: cfg() }, { fetchImpl });
62
+ expect(result).toEqual({ status: 'skipped', reason: 'no-issue-ref' });
63
+ expect(fetchImpl).not.toHaveBeenCalled();
64
+ });
65
+ it('skips when the referenced issue does not exist', async () => {
66
+ const result = await notifyLinear({ ...BASE, config: cfg() }, { fetchImpl: scriptedFetch([]) });
67
+ expect(result).toEqual({ status: 'skipped', reason: 'issue-not-found', identifier: 'IN-2269' });
68
+ });
69
+ it('reports failure instead of throwing when the API errors', async () => {
70
+ const fetchImpl = vi.fn(async () => new Response('{}', { status: 500 }));
71
+ const result = await notifyLinear({ ...BASE, config: cfg() }, { fetchImpl });
72
+ expect(result.status).toBe('failed');
73
+ expect(result.reason).toContain('500');
74
+ });
75
+ it('reports failure when the mutation is rejected', async () => {
76
+ const fetchImpl = scriptedFetch(FOUND, { commentCreate: { success: false, comment: null } });
77
+ const result = await notifyLinear({ ...BASE, config: cfg() }, { fetchImpl });
78
+ expect(result.status).toBe('failed');
79
+ expect(result.reason).toMatch(/rejected/i);
80
+ });
81
+ it('never leaks the token in a failure reason', async () => {
82
+ const fetchImpl = vi.fn(async () => new Response('{}', { status: 401 }));
83
+ const result = await notifyLinear({ ...BASE, config: cfg() }, { fetchImpl });
84
+ expect(result.reason).not.toContain('minted');
85
+ });
86
+ it('follows a linear.app URL in the body when no team_keys are configured', async () => {
87
+ const pr = { ...PR, branch: 'feat/nope', title: 'chore', body: 'https://linear.app/x/issue/IN-2269/z' };
88
+ const result = await notifyLinear({ ...BASE, pr, config: cfg({ team_keys: [] }) }, { fetchImpl: scriptedFetch(FOUND) });
89
+ expect(result.status).toBe('posted');
90
+ });
91
+ });
92
+ describe('workspace mismatch', () => {
93
+ const scoped = (issueUrl) => {
94
+ let call = 0;
95
+ return vi.fn(async () => {
96
+ call++;
97
+ if (call === 1) {
98
+ return new Response(JSON.stringify({
99
+ data: { issues: { nodes: [{ id: 'u1', identifier: 'IN-2269', url: issueUrl }] } },
100
+ }), { status: 200 });
101
+ }
102
+ return new Response(JSON.stringify({
103
+ data: { commentCreate: { success: true, comment: { id: 'c1', url: 'https://linear.app/x/c1' } } },
104
+ }), { status: 200 });
105
+ });
106
+ };
107
+ const prWithUrl = (url) => ({ ...PR, branch: 'feat/none', title: 'chore', body: url });
108
+ it('posts when the resolved issue is in the URL-named workspace', async () => {
109
+ const fetchImpl = scoped('https://linear.app/acme/issue/IN-2269/slug');
110
+ const result = await notifyLinear({ ...BASE, pr: prWithUrl('https://linear.app/acme/issue/IN-2269'), config: cfg({ team_keys: [] }) }, { fetchImpl });
111
+ expect(result.status).toBe('posted');
112
+ });
113
+ it('skips when the credentials resolve a different workspace', async () => {
114
+ // Same identifier, different workspace โ€” a real issue, but not the one meant.
115
+ const fetchImpl = scoped('https://linear.app/other-corp/issue/IN-2269/slug');
116
+ const result = await notifyLinear({ ...BASE, pr: prWithUrl('https://linear.app/acme/issue/IN-2269'), config: cfg({ team_keys: [] }) }, { fetchImpl });
117
+ expect(result).toEqual({ status: 'skipped', reason: 'workspace-mismatch', identifier: 'IN-2269' });
118
+ });
119
+ it('does not post the comment when the workspace mismatches', async () => {
120
+ const fetchImpl = scoped('https://linear.app/other-corp/issue/IN-2269/slug');
121
+ await notifyLinear({ ...BASE, pr: prWithUrl('https://linear.app/acme/issue/IN-2269'), config: cfg({ team_keys: [] }) }, { fetchImpl });
122
+ expect(fetchImpl.mock.calls).toHaveLength(1);
123
+ });
124
+ it('does not constrain a bare ref, which names no workspace', async () => {
125
+ const fetchImpl = scoped('https://linear.app/whatever/issue/IN-2269/slug');
126
+ const result = await notifyLinear({ ...BASE, config: cfg() }, { fetchImpl });
127
+ expect(result.status).toBe('posted');
128
+ });
129
+ });
130
+ describe('issueBelongsToWorkspace', () => {
131
+ it('matches the first path segment', () => {
132
+ expect(issueBelongsToWorkspace('https://linear.app/acme/issue/IN-1', 'acme')).toBe(true);
133
+ });
134
+ it('is case insensitive', () => {
135
+ expect(issueBelongsToWorkspace('https://linear.app/ACME/issue/IN-1', 'acme')).toBe(true);
136
+ });
137
+ it('rejects a different workspace', () => {
138
+ expect(issueBelongsToWorkspace('https://linear.app/other/issue/IN-1', 'acme')).toBe(false);
139
+ });
140
+ it('fails closed on an unparseable URL', () => {
141
+ expect(issueBelongsToWorkspace('not a url', 'acme')).toBe(false);
142
+ });
143
+ });
144
+ //# sourceMappingURL=linear-notify.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-notify.test.js","sourceRoot":"","sources":["../../src/__tests__/linear-notify.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=linear-ref.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linear-ref.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/linear-ref.test.ts"],"names":[],"mappings":""}