openvibers/openvibe.blog Commits

Patch notes: the day ends each title ('Patch notes: 80 changes across 36 sites' was three different posts' title) (#65)

OP OpenVibers committed 27 days ago · 8d08c2da58 · 2 files, +8 −4

Changes

ddiff --git a/server/changelog.js b/server/changelog.js
iindex 44c79d7..3f4996a 100644
---- a/server/changelog.js
++++ b/server/changelog.js
@@@ -244,7 +244,11 @@ function createChangelog({ config, store, blogs, posts, aiDrafts = null, fetchIm
const to = day(list[list.length - 1].deployed_at);
const sites = order.map(name);
const lead = highlights[0] ? clean(highlights[0].subject.split(/[:.;(]/)[0], 70) : null;
-- const title = lead && lead.length >= 12 ? `Patch notes: ${lead}` : `Patch notes: ${list.length} changes across ${order.length} ${order.length === 1 ? 'site' : 'sites'}`;
++ // The day ends the title: titles made from the counts repeated ("Patch notes: 80 changes across 36 sites" three
++ // times by 2026-10-17), which search results and the feed cannot tell apart. The "Patch notes: " start stays
++ // (openvibe-shared/shipped.js strips it to show the rest).
++ const dayLabel = new Date(list[list.length - 1].deployed_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric', timeZone: 'UTC' });
++ const title = `Patch notes: ${lead && lead.length >= 12 ? lead : `${list.length} changes across ${order.length} ${order.length === 1 ? 'site' : 'sites'}`} (${dayLabel})`;
const summary = clean(`What shipped on OpenVibe ${from === to ? `on ${from}` : `from ${from} to ${to}`}: ${list.length} ${list.length === 1 ? 'change' : 'changes'} to ${sites.slice(0, 6).join(', ')}${sites.length > 6 ? ` and ${sites.length - 6} more` : ''}.`, 400);
const out = [`${summary} Every line below is a commit message from the OpenVibers repositories, linked to the change itself.`, ''];
if (highlights.length) {
ddiff --git a/test/changelog.test.js b/test/changelog.test.js
iindex 4779644..4c89183 100644
---- a/test/changelog.test.js
++++ b/test/changelog.test.js
@@@ -65,7 +65,7 @@ const H = (n) => n.toString(16).padStart(40, 'a');
const post = await t.ctx.posts.get(r.post.id);
assert.strictEqual(post.state, 'published');
const head = await t.ctx.posts.head(post);
-- assert.strictEqual(head.fields.title, 'Patch notes: Recent tools in the launcher');
++ assert.match(head.fields.title, /^Patch notes: Recent tools in the launcher \([A-Z][a-z]{2} \d{1,2}\)$/, 'the day ends the title');
assert.ok(head.content.includes('## Highlights') && head.content.includes('**OpenVibe.Tools:** Recent tools in the launcher'));
assert.ok(head.content.includes('## OpenVibe.Live') && head.content.includes('Fix the chat scroll'));
assert.strictEqual(head.meta.authorship.mode, 'imported');
@@@ -80,7 +80,7 @@ const H = (n) => n.toString(16).padStart(40, 'a');
assert.deepStrictEqual(j.entries.map((x) => x.subject).sort(), ['Recent tools in the launcher: anonymous and account history', 'Tidy the docs']);
assert.ok(j.entries.every((x) => x.service === 'tools' && x.post_id));
assert.ok(j.latest_post && /\/@openvibe\//.test(j.latest_post.url), 'the latest patch notes post, to link to');
-- assert.strictEqual(j.latest_post.title, 'Patch notes: Recent tools in the launcher');
++ assert.match(j.latest_post.title, /^Patch notes: Recent tools in the launcher \([A-Z][a-z]{2} \d{1,2}\)$/);
});
await check('a batch publishes without a major, but never sooner than the gap after the last post', async () => {
@@@ -90,7 +90,7 @@ const H = (n) => n.toString(16).padStart(40, 'a');
t.clock.advance(6 * 3600 * 1000 + 1000);
const r = await cl.tick();
assert.ok(r && r.post);
-- assert.ok((await t.ctx.posts.head(await t.ctx.posts.get(r.post.id))).fields.title.startsWith('Patch notes: 5 changes across 1 site'));
++ assert.ok((await t.ctx.posts.head(await t.ctx.posts.get(r.post.id))).fields.title.match(/^Patch notes: 5 changes across 1 site \([A-Z][a-z]{2} \d{1,2}\)$/));
});
await check('subjects are cut at a word; version bumps count as major', async () => {