fix(website): render releases from local notes, drop GitHub gate (#21238)
The releases page gated visible notes on fetchLatestGithubReleaseTag(); when that unauthenticated GitHub call was rate-limited at build (common on shared Cloudflare build IPs, no GITHUB_TOKEN), it returned null and getVisibleReleaseNotes returned [], rendering 'No releases are visible yet for the current published version' — the exact prod symptom. force-static made each deploy a coin flip. Committed MDX (+images) is the single source of truth, so gate visibility on nothing: render all local notes deterministically with no network call. Removes the dev/prod divergence and deletes the now-dead fetch-latest-release-tag.ts and get-visible-releases.ts.
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
import { fetchCommunityStats } from '@/lib/community/fetch-community-stats';
|
||||
import { getRouteI18n, type LocaleRouteParams } from '@/lib/i18n/server';
|
||||
import { mergeSocialLinkLabels } from '@/lib/community/merge-social-link-labels';
|
||||
import { fetchLatestGithubReleaseTag } from '@/lib/releases/fetch-latest-release-tag';
|
||||
import { getVisibleReleaseNotes } from '@/lib/releases/get-visible-releases';
|
||||
import { loadLocalReleaseNotes } from '@/lib/releases/load-local-release-notes';
|
||||
import { ReleasesHero } from '@/app/[locale]/releases/_components/ReleasesHero';
|
||||
import { Menu, MENU_DATA } from '@/sections/Menu';
|
||||
@@ -25,22 +23,17 @@ type ReleasesPageProps = {
|
||||
};
|
||||
|
||||
export default async function ReleasesPage({ params }: ReleasesPageProps) {
|
||||
const allNotes = loadLocalReleaseNotes();
|
||||
const [, latestTag, stats] = await Promise.all([
|
||||
const notes = loadLocalReleaseNotes();
|
||||
const [, stats] = await Promise.all([
|
||||
getRouteI18n(params),
|
||||
fetchLatestGithubReleaseTag(),
|
||||
fetchCommunityStats(),
|
||||
]);
|
||||
const menuSocialLinks = mergeSocialLinkLabels(MENU_DATA.socialLinks, stats);
|
||||
const visibleNotes =
|
||||
process.env.NODE_ENV === 'development'
|
||||
? allNotes
|
||||
: getVisibleReleaseNotes(allNotes, latestTag);
|
||||
|
||||
return (
|
||||
<>
|
||||
{visibleNotes.length > 0 ? (
|
||||
<JsonLd data={buildReleaseListJsonLd(visibleNotes)} />
|
||||
{notes.length > 0 ? (
|
||||
<JsonLd data={buildReleaseListJsonLd(notes)} />
|
||||
) : null}
|
||||
{/*
|
||||
* Above-the-fold milestone scene texture. Preload kicks off the
|
||||
@@ -59,26 +52,22 @@ export default async function ReleasesPage({ params }: ReleasesPageProps) {
|
||||
<ReleasesHero />
|
||||
|
||||
<ReleaseNotesSection>
|
||||
{allNotes.length === 0 ? (
|
||||
{notes.length === 0 ? (
|
||||
<ReleaseNotesEmptyMessage>
|
||||
Releases were not found. Add MDX under{' '}
|
||||
<strong>packages/twenty-website/src/content/releases</strong> and
|
||||
images under{' '}
|
||||
<strong>packages/twenty-website/public/images/releases</strong>.
|
||||
</ReleaseNotesEmptyMessage>
|
||||
) : visibleNotes.length === 0 ? (
|
||||
<ReleaseNotesEmptyMessage>
|
||||
No releases are visible yet for the current published version.
|
||||
</ReleaseNotesEmptyMessage>
|
||||
) : (
|
||||
visibleNotes.map((note, index) => (
|
||||
notes.map((note, index) => (
|
||||
<Fragment key={note.slug}>
|
||||
<ReleaseNotesReleaseEntry
|
||||
content={note.content}
|
||||
date={note.date}
|
||||
release={note.release}
|
||||
/>
|
||||
{index < visibleNotes.length - 1 ? <ReleaseNotesDivider /> : null}
|
||||
{index < notes.length - 1 ? <ReleaseNotesDivider /> : null}
|
||||
</Fragment>
|
||||
))
|
||||
)}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
export async function fetchLatestGithubReleaseTag(): Promise<string | null> {
|
||||
try {
|
||||
const headers: Record<string, string> = {
|
||||
Accept: 'application/vnd.github+json',
|
||||
'X-GitHub-Api-Version': '2022-11-28',
|
||||
};
|
||||
|
||||
if (process.env.GITHUB_TOKEN) {
|
||||
headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
|
||||
}
|
||||
|
||||
const response = await fetch(
|
||||
'https://api.github.com/repos/twentyhq/twenty/releases/latest',
|
||||
{ headers },
|
||||
);
|
||||
|
||||
if (!response.ok) return null;
|
||||
|
||||
const data = (await response.json()) as { tag_name?: string };
|
||||
return data.tag_name ?? null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import type { LocalReleaseNote } from '@/lib/releases/types';
|
||||
import { getFormattedReleaseNumber } from '@/lib/releases/get-formatted-release-number';
|
||||
|
||||
function safeReleaseNumber(version: string): number | null {
|
||||
try {
|
||||
return getFormattedReleaseNumber(version);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function getVisibleReleaseNotes(
|
||||
notes: LocalReleaseNote[],
|
||||
latestPublishedTag: string | null,
|
||||
): LocalReleaseNote[] {
|
||||
if (!latestPublishedTag) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const publishedNumber = safeReleaseNumber(latestPublishedTag);
|
||||
if (publishedNumber === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return notes.filter((note) => {
|
||||
const noteNumber = safeReleaseNumber(note.release);
|
||||
if (noteNumber === null) {
|
||||
return false;
|
||||
}
|
||||
return noteNumber <= publishedNumber;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user