Skip to content

Commit

Permalink
doc: Dynamic GHA status on landing page
Browse files Browse the repository at this point in the history
  • Loading branch information
franky47 committed Jan 28, 2024
1 parent 7908c93 commit 7711c4f
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/test-against-nextjs-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,6 @@ jobs:
jobName: next@${{ inputs.version }}${{ matrix.base-path && ' basePath' || ''}}${{ matrix.window-history-support && ' WHS' || ''}}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
- name: Invalidate ISR cache for GitHub Actions status on landing page
run: curl -s https://nuqs.47ng.com/api/isr?tag=github-actions-status&token=${{ secrets.ISR_TOKEN }}
if: always()
20 changes: 16 additions & 4 deletions packages/docs/src/app/(pages)/_landing/features.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from 'lucide-react'
import React from 'react'
import { BundleSize } from './bundle-size'
import { GitHubActionsStatus } from './gha-status'

export function FeaturesSection(props: React.ComponentProps<'section'>) {
return (
Expand Down Expand Up @@ -110,8 +111,18 @@ export function FeaturesSection(props: React.ComponentProps<'section'>) {
/>
<Feature
icon={<TestTube2 size={32} />}
title="Tested"
description="Tested against every Next.js release."
title={
<span className="flex items-center">
Tested
<GitHubActionsStatus className="ml-4 inline-flex" />
</span>
}
description={
<>
Tested against every Next.js release.
<br />
</>
}
/>
</section>
)
Expand All @@ -128,6 +139,7 @@ type FeatureProps = {

export function Feature({ title, description, icon, isNew }: FeatureProps) {
// https://v0.dev/t/xXdcvuFkW1d
const DescriptionContainer = typeof description === 'string' ? 'p' : 'div'
return (
<>
<div className="space-y-4 xl:space-y-8">
Expand All @@ -149,9 +161,9 @@ export function Feature({ title, description, icon, isNew }: FeatureProps) {
)}
</h3>
</div>
<p className="text-zinc-500 dark:text-zinc-300 md:text-lg/relaxed xl:text-xl/relaxed">
<DescriptionContainer className="text-zinc-500 dark:text-zinc-300 md:text-lg/relaxed xl:text-xl/relaxed">
{description}
</p>
</DescriptionContainer>
</div>
</>
)
Expand Down
90 changes: 90 additions & 0 deletions packages/docs/src/app/(pages)/_landing/gha-status.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { cn } from '@/src/lib/utils'
import React from 'react'
import { z } from 'zod'

export async function GitHubActionsStatus({
className,
...props
}: React.ComponentProps<'div'>) {
const statuses = await getGitHubActionsStatus()
return (
<div
className={cn(
'flex items-center space-x-[-12px] md:space-x-[-14px]',
className
)}
aria-label="Last 5 GitHub Actions status"
{...props}
>
{statuses.map(status => {
const color = {
SUCCESS: 'bg-green-500',
FAILURE: 'bg-red-500',
CANCELLED: 'bg-zinc-500',
TIMED_OUT: 'bg-zinc-500',
ACTION_REQUIRED: 'bg-purple-500',
NEUTRAL: 'bg-zinc-500'
}[status.checkSuite.conclusion]
return (
<a key={status.id} href={status.url} className="rounded-full p-1">
<div
aria-label={status.checkSuite.conclusion}
className={cn(
'h-4 w-4 rounded-full border-2 border-background bg-current md:h-5 md:w-5',
color
)}
/>
</a>
)
})}
</div>
)
}

const ghaStatusSchema = z.object({
id: z.string(),
url: z.string().url(),
createdAt: z.string().datetime(),
checkSuite: z.object({
status: z.enum(['QUEUED', 'IN_PROGRESS', 'COMPLETED']),
conclusion: z.enum([
'SUCCESS',
'FAILURE',
'CANCELLED',
'TIMED_OUT',
'ACTION_REQUIRED',
'NEUTRAL'
])
})
})

async function getGitHubActionsStatus() {
const query = `query {
node(id: "W_kwDOD6wJuM4EeKz5") {
... on Workflow {
runs(first: 5) {
nodes {
id
url
createdAt
checkSuite {
status
conclusion
}
}
}
}
}
}`.replace(/\s+/g, ' ') // Minify
const json = await fetch(`https://api.github.com/graphql?repo=47ng/nuqs`, {
method: 'POST',
headers: {
Authorization: `bearer ${process.env.GITHUB_TOKEN}`
},
body: JSON.stringify({ query }),
next: {
tags: ['github-actions-status']
}
}).then(res => res.json())
return z.array(ghaStatusSchema).parse(json.data.node.runs.nodes)
}
21 changes: 21 additions & 0 deletions packages/docs/src/app/api/isr/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { revalidateTag } from 'next/cache'
import { NextRequest, NextResponse } from 'next/server'

const ACCEPTED_TAGS = ['github', 'github-actions-status']

export async function GET(req: NextRequest) {
const token = req.nextUrl.searchParams.get('token')
if (token !== process.env.ISR_TOKEN) {
return NextResponse.json({ error: 'Invalid token' }, { status: 400 })
}
const now = new Date()
const tag = req.nextUrl.searchParams.get('tag')
if (!tag || !ACCEPTED_TAGS.includes(tag)) {
return NextResponse.json({ error: 'Invalid tag' }, { status: 400 })
}
revalidateTag(tag)
return NextResponse.json({
at: now.toISOString(),
revalidated: tag
})
}

0 comments on commit 7711c4f

Please sign in to comment.