@bongos/core 1.20.38 → 1.20.39
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/.bongos-core.json +41 -31
- package/docs/copy-inventory.md +1 -1
- package/docs/copy-registry.json +9 -9
- package/docs/module-api-changelog.md +2 -0
- package/docs/page-readings.json +251 -248
- package/modules/npm-release/preview/childlog.js +95 -0
- package/modules/npm-release/preview/commands.js +46 -5
- package/modules/npm-release/preview/env.js +18 -7
- package/modules/npm-release/preview/runtime.js +43 -9
- package/modules/npm-release/preview/supervisor.js +170 -31
- package/modules/npm-release/public/work.css +3 -0
- package/modules/npm-release/public/work.js +6 -1
- package/modules/npm-release/routes/preview.js +1 -0
- package/modules/provisioning/render-standup.js +13 -1
- package/modules/public-landing/public/projects.html +22 -8
- package/package-lock.json +2 -2
- package/package.json +1 -1
- package/release-notes.json +10 -0
- package/scripts/gds/provision-render.js +13 -1
- package/scripts/gds/render-payload.js +6 -5
- package/src/module-api.js +1 -1
- package/tests/npm_release_preview_commands.mjs +1 -1
- package/tests/npm_release_preview_diagnosis.mjs +376 -0
- package/tests/npm_release_preview_supervisor.mjs +4 -4
- package/tests/projects_hub_app_step.mjs +49 -0
- package/tests/projects_hub_render_connect.mjs +2 -1
- package/tests/provision_render.mjs +23 -2
|
@@ -23,6 +23,8 @@ import fs from 'node:fs';
|
|
|
23
23
|
import path from 'node:path';
|
|
24
24
|
import vm from 'node:vm';
|
|
25
25
|
import { fileURLToPath } from 'node:url';
|
|
26
|
+
import { createRequire } from 'node:module';
|
|
27
|
+
const require = createRequire(import.meta.url);
|
|
26
28
|
|
|
27
29
|
const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
28
30
|
const HUB = fs.readFileSync(path.join(ROOT, 'modules', 'public-landing', 'public', 'projects.html'), 'utf8').replace(/\r\n/g, '\n');
|
|
@@ -301,6 +303,53 @@ test('typing a start command clears the "how your app starts" ask at once', asyn
|
|
|
301
303
|
assert.doesNotMatch(w.$('h-render').textContent, /how your app starts/);
|
|
302
304
|
});
|
|
303
305
|
|
|
306
|
+
// task 1004464 — Render refused a native app with no build command, live, on project 43.
|
|
307
|
+
test('the build command starts as the runtime\'s usual one, follows the runtime, and yields to the owner\'s own', async () => {
|
|
308
|
+
const w = load({ answers: ANSWERS, draft: { appPlatform: 'render' } });
|
|
309
|
+
w.typeKey(KEY);
|
|
310
|
+
await w.check();
|
|
311
|
+
await w.pickWorkspace(0);
|
|
312
|
+
w.pickService({ value: 'new' });
|
|
313
|
+
assert.equal(w.$('f-renderBuild').value, 'npm install', 'Node.js starts with npm install');
|
|
314
|
+
w.$('f-renderRuntime').value = 'python';
|
|
315
|
+
w.$('renderNew').fire('change', { target: w.$('f-renderRuntime') });
|
|
316
|
+
assert.equal(w.$('f-renderBuild').value, 'pip install -r requirements.txt', 'it follows the runtime');
|
|
317
|
+
w.$('f-renderBuild').value = 'make build';
|
|
318
|
+
w.$('renderNew').fire('input', { target: w.$('f-renderBuild') });
|
|
319
|
+
w.$('f-renderRuntime').value = 'ruby';
|
|
320
|
+
w.$('renderNew').fire('change', { target: w.$('f-renderRuntime') });
|
|
321
|
+
assert.equal(w.$('f-renderBuild').value, 'make build', 'the owner\'s own command is never overwritten');
|
|
322
|
+
w.state.renderStart = 'bundle exec puma';
|
|
323
|
+
assert.equal(w.renderRequestBody().build_command, 'make build');
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
test('an emptied build command is refused before Render ever sees it, and the ask clears on typing', async () => {
|
|
327
|
+
const w = load({ answers: ANSWERS, draft: { appPlatform: 'render' } });
|
|
328
|
+
w.typeKey(KEY);
|
|
329
|
+
await w.check();
|
|
330
|
+
await w.pickWorkspace(0);
|
|
331
|
+
w.pickService({ value: 'new' });
|
|
332
|
+
w.state.renderStart = 'npm start';
|
|
333
|
+
w.$('f-renderBuild').value = '';
|
|
334
|
+
w.$('renderNew').fire('input', { target: w.$('f-renderBuild') });
|
|
335
|
+
assert.equal(w.validateRender(), false);
|
|
336
|
+
assert.match(w.$('h-render').textContent, /how your app is built/);
|
|
337
|
+
w.$('f-renderBuild').value = 'npm ci';
|
|
338
|
+
w.$('renderNew').fire('input', { target: w.$('f-renderBuild') });
|
|
339
|
+
assert.doesNotMatch(w.$('h-render').className, /err/);
|
|
340
|
+
assert.equal(w.validateRender(), true);
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
test('the page\'s build defaults are the runner\'s, key for key', () => {
|
|
344
|
+
const { BUILD_DEFAULTS, RUNTIMES } = require('../modules/provisioning/render-standup.js');
|
|
345
|
+
const src = HUB.replace(/\r\n/g, '\n').match(/var RENDER_BUILD_DEFAULTS = (\{[\s\S]*?\});/);
|
|
346
|
+
assert.ok(src, 'the page carries RENDER_BUILD_DEFAULTS');
|
|
347
|
+
const page = vm.runInNewContext('(' + src[1] + ')');
|
|
348
|
+
assert.deepEqual({ ...page }, { ...BUILD_DEFAULTS });
|
|
349
|
+
assert.deepEqual(Object.keys(page).sort(), RUNTIMES.filter((r) => r !== 'docker').sort());
|
|
350
|
+
assert.doesNotMatch(HUB, /leave empty if there is none/);
|
|
351
|
+
});
|
|
352
|
+
|
|
304
353
|
test('the empty command boxes read as examples, not as filled-in values', () => {
|
|
305
354
|
assert.match(HUB, /id="f-renderBuild"[^>]*placeholder="for example: npm ci"/);
|
|
306
355
|
assert.match(HUB, /id="f-renderStart"[^>]*placeholder="for example: npm start"/);
|
|
@@ -250,7 +250,8 @@ test('Connect sends the key once, to this project, forgets it, and the card show
|
|
|
250
250
|
const sent = w.calls.filter((c) => c.url === RENDER);
|
|
251
251
|
assert.equal(sent.length, 1);
|
|
252
252
|
assert.equal(sent[0].method, 'POST');
|
|
253
|
-
|
|
253
|
+
// build_command: the runtime's usual one, prefilled — Render refuses a native app without one (task 1004464)
|
|
254
|
+
assert.deepEqual(sent[0].body, { key: KEY, owner_id: TEA_A, mode: 'greenfield', runtime: 'node', start_command: 'npm start', build_command: 'npm install', web_plan: 'starter', database: false });
|
|
254
255
|
for (const c of w.calls) assert.ok(!c.url.includes(KEY), 'no URL carries the key');
|
|
255
256
|
assert.equal(w.q('f-renderKey').value, '', 'the field is emptied');
|
|
256
257
|
assert.equal(w.byId('mAppConnectForm').hidden, true, 'the form closes');
|
|
@@ -335,11 +335,32 @@ await ta('a link needs a repository to check the service against (1004350 review
|
|
|
335
335
|
assert.equal(out.ok, false);
|
|
336
336
|
assert.equal(h.cleared(), 1);
|
|
337
337
|
});
|
|
338
|
-
|
|
338
|
+
// The 1004350 review asked for NO build command here; Render refused exactly that live
|
|
339
|
+
// ("buildCommand is required for non-static, non-docker services", task 1004464), so a
|
|
340
|
+
// row saved without one — every row from before the fix included — gets the runtime's
|
|
341
|
+
// default, and a Retry of such a row now works.
|
|
342
|
+
await ta('an app saved with no build command gets its runtime\'s default, as Render requires (task 1004464)', async () => {
|
|
339
343
|
const h = harness({ host: { buildCommand: undefined } });
|
|
340
344
|
await h.run();
|
|
341
345
|
const svc = h.r.calls.find((c) => c.method === 'POST' && c.path === '/services').body;
|
|
342
|
-
assert.deepEqual(svc.serviceDetails.envSpecificDetails, { startCommand: 'npm start' });
|
|
346
|
+
assert.deepEqual(svc.serviceDetails.envSpecificDetails, { buildCommand: 'npm install', startCommand: 'npm start' });
|
|
347
|
+
});
|
|
348
|
+
await ta('every native runtime has a default build command; docker still sends none (task 1004464)', () => {
|
|
349
|
+
const { RUNTIMES, BUILD_DEFAULTS } = require('../modules/provisioning/render-standup.js');
|
|
350
|
+
const { buildFor } = require('../scripts/gds/render-payload.js');
|
|
351
|
+
for (const rt of RUNTIMES.filter((r) => r !== 'docker')) {
|
|
352
|
+
assert.ok(BUILD_DEFAULTS[rt], `${rt} has a default`);
|
|
353
|
+
assert.equal(buildFor({ runtime: rt, startCommand: 'x' }).buildCommand, BUILD_DEFAULTS[rt]);
|
|
354
|
+
assert.equal(buildFor({ runtime: rt, startCommand: 'x', buildCommand: 'make' }).buildCommand, 'make', 'the owner\'s own wins');
|
|
355
|
+
}
|
|
356
|
+
assert.deepEqual(buildFor({ runtime: 'docker' }), { runtime: 'docker' });
|
|
357
|
+
});
|
|
358
|
+
await ta('a refusal from Render reads as a sentence, with Render\'s own reason kept (task 1004464)', async () => {
|
|
359
|
+
const h = harness({ host: { database: false }, render: { 'POST /services': new Error('buildCommand is required for non-static, non-docker services.') } });
|
|
360
|
+
const out = await h.run();
|
|
361
|
+
assert.equal(out.ok, false);
|
|
362
|
+
assert.equal(h.lastHost().error, 'Render would not set up the app: buildCommand is required for non-static, non-docker services.');
|
|
363
|
+
assert.doesNotMatch(h.lastHost().error, /POST \/services/, 'no raw HTTP line reaches the owner');
|
|
343
364
|
});
|
|
344
365
|
|
|
345
366
|
console.log('\nteardown forgets, never deletes:');
|