Files
supabase/apps/docs/lib/octokit.ts
Ivan Vasilov 84311e7d09 chore: Fix the env vars for turbo (#31104)
* Check all env vars for studio and list them properly in turbo.json.

* Check all env vars for design-system.

* Fix all env vars for www.

* Fix all env vars for docs.

* Add the rest of the env vars from the packages folder.

* Revert the changes in the sign-in pages.

* Remove useless files. Fix a comment.

* Fix the links in extensions page to always point to supabase.com/docs.

* Change the feature flag rewrite in studio to point to supabase.com/.flags endpoint.

* Replace NEXT_PUBLIC_VERCEL_URL with NEXT_PUBLIC_VERCEL_BRANCH_URL because it's more stable on vercel.com. Remove it from apps where it's not needed.

* Add env vars from packages. Move all passthrough env vars to env vars since they're stable (don't change between pushes).

* Revert changes of studio files.

* Minor fixes for the merge commit.

* Replace all uses of SITE_URL with LW_URL (they're the same). SITE_ORIGIN is not constructed from env vars. LW_URL is constructed from SITE_ORIGIN and launch_week string.

* Use SITE_ORIGIN when fetching the ticket-og.
2025-01-17 11:08:14 +01:00

159 lines
3.7 KiB
TypeScript

import 'server-only'
import { createAppAuth } from '@octokit/auth-app'
import { Octokit } from '@octokit/core'
import crypto from 'node:crypto'
import { fetchRevalidatePerDay } from '~/features/helpers.fetch'
let octokitInstance: Octokit
function octokit() {
if (!octokitInstance) {
const privateKeyPkcs8 = crypto
.createPrivateKey(process.env.DOCS_GITHUB_APP_PRIVATE_KEY)
.export({
type: 'pkcs8',
format: 'pem',
})
octokitInstance = new Octokit({
authStrategy: createAppAuth,
auth: {
appId: process.env.DOCS_GITHUB_APP_ID,
installationId: process.env.DOCS_GITHUB_APP_INSTALLATION_ID,
privateKey: privateKeyPkcs8,
},
})
}
return octokitInstance
}
async function getGitHubFileContents({
org,
repo,
path,
branch,
options: { onError, fetch },
}: {
org: string
repo: string
path: string
branch: string
options: {
onError: (err?: unknown) => void
/**
*
* A custom fetch implementation to control Next.js caching.
* By default, uses a "once-per-day" revalidation strategy.
* This default may change later as we move to on-demand revalidation.
*/
fetch?: (info: RequestInfo, init?: RequestInit) => Promise<Response>
}
}) {
if (path.startsWith('/')) {
path = path.slice(1)
}
try {
const response = await octokit().request('GET /repos/{owner}/{repo}/contents/{path}', {
owner: org,
repo: repo,
path: path,
ref: branch,
options: {
fetch: fetch ?? fetchRevalidatePerDay,
},
})
if (response.status !== 200 || !response.data) {
throw Error(`Could not find contents of ${path} in ${org}/${repo}`)
}
if (!('type' in response.data) || response.data.type !== 'file') {
throw Error(`${path} in ${org}/${repo} is not a file`)
}
const content = Buffer.from(response.data.content, 'base64').toString('utf-8')
return content
} catch (err) {
console.error('Error fetching GitHub file: %o', err)
onError?.(err)
}
}
export async function getGitHubFileContentsImmutableOnly({
org,
repo,
branch,
path,
options: { onError, fetch },
}: {
org: string
repo: string
branch: string
path: string
options: {
onError: (err?: unknown) => void
fetch?: (info: RequestInfo, init?: RequestInit) => Promise<Response>
}
}) {
const isImmutableCommit = await checkForImmutableCommit({
org,
repo,
branch,
})
if (!isImmutableCommit) {
throw Error('The commit is not an immutable commit SHA. Tags and branch names are not allowed.')
}
return getGitHubFileContents({
org,
repo,
branch,
path,
options: { onError, fetch },
})
}
async function checkForImmutableCommit({
org,
repo,
branch,
options: { fetch: _fetch = fetch } = {},
}: {
org: string
repo: string
branch: string
options?: {
/**
*
* A custom fetch implementation to control Next.js caching.
*/
fetch?: (info: RequestInfo, init?: RequestInit) => Promise<Response>
}
}) {
try {
const response = await octokit().request('GET /repos/{owner}/{repo}/git/commits/{commit_sha}', {
owner: org,
repo: repo,
commit_sha: branch,
headers: {
'X-GitHub-Api-Version': '2022-11-28',
},
options: {
fetch: _fetch,
},
})
if (response.status === 200) {
return true
} else {
throw Error(
"Checking for an immutable commit didn't throw an error, but it also didn't return a 200. Erring on the side of safety, assuming this is not an immutable commit.",
{ cause: response }
)
}
} catch (err) {
console.error('Not an immutable commit: %o', err)
return false
}
}