Skip to content

Commit 7e8a98e

Browse files
committed
fix(library): gate IndexNow on the ECS cutover, cover unpublished and renamed pages, and give customer stories speakable hooks
1 parent c493cbe commit 7e8a98e

4 files changed

Lines changed: 63 additions & 18 deletions

File tree

‎.github/workflows/ci.yml‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,9 @@ jobs:
569569
needs.promote.result == 'success' &&
570570
needs.trigger-upload.result == 'success' &&
571571
needs.promote.outputs.promoted == 'true'
572+
outputs:
573+
# The new app serves traffic; indexnow keys off this, not the later Trigger.dev promotion.
574+
cutover: ${{ steps.cutover.outcome }}
572575
# Mostly waiting on the ECS cutover after a dependency install: the smallest runner is enough.
573576
runs-on: *runner-2vcpu
574577
# Leave setup/promotion headroom above the 70-minute cutover poll.
@@ -596,6 +599,7 @@ jobs:
596599
# An unchanged tag may belong to a failed or still-running earlier deploy.
597600
# Verify its latest cutover rather than treating tag equality as success.
598601
- name: Wait for ECS traffic cutover
602+
id: cutover
599603
env:
600604
OVERALL_TIMEOUT: 4200
601605
APP_IMAGE_CHANGED: ${{ needs.promote.outputs.app_image_changed }}
@@ -646,7 +650,7 @@ jobs:
646650
github.event_name == 'push' &&
647651
github.ref == 'refs/heads/main' &&
648652
needs.promote.outputs.promoted == 'true' &&
649-
needs.trigger-promote.result == 'success'
653+
needs.trigger-promote.outputs.cutover == 'success'
650654
runs-on: *runner-2vcpu
651655
timeout-minutes: 5
652656
continue-on-error: true

‎apps/sim/app/(landing)/customers/components/customer-story-page/customer-story-page.tsx‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ export function CustomerStoryPage({ story, post, nextStory }: CustomerStoryPageP
2828
<article className={HOME_INSET}>
2929
<header className={cn('pb-12 max-sm:pb-8', LANDING_HERO_TOP_PADDING)}>
3030
<BackLink href='/customers' label='Customer stories' />
31-
<h1 className='mt-7 max-w-[1100px] text-balance text-[64px] text-[var(--text-primary)] leading-[1.04] tracking-[-0.03em] max-sm:mt-5 max-sm:text-[36px] max-xl:text-[52px]'>
31+
<h1
32+
className='mt-7 max-w-[1100px] text-balance text-[64px] text-[var(--text-primary)] leading-[1.04] tracking-[-0.03em] max-sm:mt-5 max-sm:text-[36px] max-xl:text-[52px]'
33+
data-speakable='headline'
34+
>
3235
{post.title}
3336
</h1>
3437
</header>
@@ -72,7 +75,10 @@ export function CustomerStoryPage({ story, post, nextStory }: CustomerStoryPageP
7275
</aside>
7376

7477
<div className='min-w-0 max-w-[740px]'>
75-
<p className='mb-10 text-pretty text-[28px] text-[var(--text-primary)] leading-[1.3] tracking-[-0.015em] max-sm:text-[23px]'>
78+
<p
79+
className='mb-10 text-pretty text-[28px] text-[var(--text-primary)] leading-[1.3] tracking-[-0.015em] max-sm:text-[23px]'
80+
data-speakable='description'
81+
>
7682
{post.description}
7783
</p>
7884
<div className='[&_h2:first-child]:!mt-0 [&_:is(h1,h2,h3,h4,h5,h6,a,strong,b)]:font-normal [&_h2]:scroll-mt-28 [&_p]:text-pretty'>

‎scripts/ping-indexnow.test.ts‎

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,33 @@ describe('collectIndexNowUrls', () => {
104104
])
105105
})
106106

107+
it('submits a post that went from published to draft, since it now 404s', () => {
108+
const { repo, urls } = fixture()
109+
write(repo, `${LIBRARY}/published/index.mdx`, post(true))
110+
expect(urls()).toEqual(['https://www.sim.ai/library', 'https://www.sim.ai/library/published'])
111+
})
112+
113+
it('submits both the old and new URL when a comparison id changes', () => {
114+
const { repo, urls } = fixture()
115+
write(repo, `${COMPETITORS}/n8n.ts`, "export const p = {\n id: 'n8n-io',\n}\n")
116+
expect(urls()).toEqual([
117+
'https://www.sim.ai/comparisons',
118+
'https://www.sim.ai/comparisons/n8n',
119+
'https://www.sim.ai/comparisons/n8n-io',
120+
])
121+
})
122+
123+
it("keeps a deleted comparison when Sim's profile changes in the same release", () => {
124+
const { repo, urls } = fixture()
125+
write(repo, 'apps/sim/lib/compare/data/sim.ts', 'export const sim = 2\n')
126+
git(repo, 'rm', '-q', `${COMPETITORS}/n8n.ts`)
127+
expect(urls()).toEqual([
128+
'https://www.sim.ai/comparisons',
129+
'https://www.sim.ai/comparisons/n8n',
130+
'https://www.sim.ai/comparisons/stack-ai',
131+
])
132+
})
133+
107134
it('submits nothing when no library or comparison source changed', () => {
108135
const { repo, urls } = fixture()
109136
write(repo, 'README.md', 'changed\n')

‎scripts/ping-indexnow.ts‎

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,11 @@ function profileId(source: string): string | undefined {
4545
}
4646

4747
/**
48-
* The public URLs whose source changed between two commits: each published library article
49-
* (renamed and deleted ones under their old slug too, so engines learn of the redirect or 404),
50-
* each comparison whose profile changed (every comparison when Sim's own profile did), and the
51-
* index page of each section that changed. Drafts are never submitted.
48+
* The public URLs whose source changed between two commits: each library article published on
49+
* either side (renamed, deleted, and newly drafted ones too, so engines learn of the 404), each
50+
* comparison whose profile changed under its old and new id (every comparison when Sim's own
51+
* profile did), and the index page of each section that changed. A post that was never published
52+
* is never submitted.
5253
*/
5354
export function collectIndexNowUrls(repo: string, base: string, head: string): string[] {
5455
const diff = git(repo, ['diff', '--name-status', '-M', base, head, '--']) ?? ''
@@ -67,21 +68,28 @@ export function collectIndexNowUrls(repo: string, base: string, head: string): s
6768
)
6869
for (const slug of slugs) {
6970
const index = `${LIBRARY_DIR}/${slug}/index.mdx`
70-
const source = show(head, index) ?? show(base, index)
71-
if (source !== null && !isDraft(source)) urls.add(`${SITE}/library/${slug}`)
71+
const wasOrIsPublished = [show(base, index), show(head, index)].some(
72+
(source) => source !== null && !isDraft(source)
73+
)
74+
if (wasOrIsPublished) urls.add(`${SITE}/library/${slug}`)
7275
}
7376
if (urls.size > 0) urls.add(`${SITE}/library`)
7477

75-
const profiles = paths.includes(SIM_PROFILE)
76-
? (git(repo, ['ls-tree', '--name-only', head, `${COMPETITORS_DIR}/`]) ?? '')
77-
.split('\n')
78-
.filter(Boolean)
79-
: paths.filter((file) => path.dirname(file) === COMPETITORS_DIR && file.endsWith('.ts'))
80-
const ids = profiles
81-
.map((file) => profileId(show(head, file) ?? show(base, file) ?? ''))
82-
.filter(Boolean)
78+
const changedProfiles = paths.filter(
79+
(file) => path.dirname(file) === COMPETITORS_DIR && file.endsWith('.ts')
80+
)
81+
const currentProfiles = paths.includes(SIM_PROFILE)
82+
? (git(repo, ['ls-tree', '--name-only', head, `${COMPETITORS_DIR}/`]) ?? '').split('\n')
83+
: []
84+
const ids = new Set(
85+
[...new Set([...changedProfiles, ...currentProfiles])]
86+
.filter(Boolean)
87+
.flatMap((file) => [show(base, file), show(head, file)])
88+
.map((source) => profileId(source ?? ''))
89+
.filter((id): id is string => Boolean(id))
90+
)
8391
for (const id of ids) urls.add(`${SITE}/comparisons/${id}`)
84-
if (ids.length > 0) urls.add(`${SITE}/comparisons`)
92+
if (ids.size > 0) urls.add(`${SITE}/comparisons`)
8593

8694
return [...urls].sort()
8795
}

0 commit comments

Comments
 (0)