@ossjs/release
Version:
Minimalistic, opinionated, and predictable release automation tool.
86 lines (78 loc) • 2.65 kB
text/typescript
import { format } from 'outvariant'
import { lt } from 'semver'
import type { ReleaseContext } from '#/src/utils/create-context.js'
import {
getGitHubRelease,
type GitHubRelease,
} from '#/src/utils/github/get-github-release.js'
import { log } from '#/src/logger.js'
/**
* Create a new GitHub release with the given release notes.
* This is only called if there's no existing GitHub release
* for the next release tag.
* @return {string} The URL of the newly created release.
*/
export async function createGitHubRelease(
context: ReleaseContext,
notes: string,
): Promise<GitHubRelease> {
const { repo } = context
log.info(
format(
'creating a new GitHub release at "%s/%s"...',
repo.owner,
repo.name,
),
)
// Determine if the next release should be marked as the
// latest release on GitHub. For that, fetch whichever latest
// release exists on GitHub and see if its version is larger
// than the version we are releasing right now.
const latestGitHubRelease = await getGitHubRelease('latest').catch(
(error) => {
log.error(`Failed to fetch the latest GitHub release:`, error)
// We aren't interested in the GET endpoint errors in this context.
return undefined
},
)
const shouldMarkAsLatest = latestGitHubRelease
? lt(latestGitHubRelease.tag_name || '0.0.0', context.nextRelease.tag)
: // Undefined is fine, it means GitHub will use its default
// value for the "make_latest" property in the API.
undefined
/**
* @see https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#create-a-release
*/
const response = await fetch(
`https://api.github.com/repos/${repo.owner}/${repo.name}/releases`,
{
method: 'POST',
headers: {
Accept: 'application/json',
Authorization: `Bearer ${process.env.GITHUB_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
tag_name: context.nextRelease.tag,
name: context.nextRelease.tag,
body: notes,
make_latest: shouldMarkAsLatest?.toString(),
}),
},
)
if (response.status === 401) {
throw new Error(
'Failed to create a new GitHub release: provided GITHUB_TOKEN does not have sufficient permissions to perform this operation. Please check your token and update it if necessary.',
)
}
if (response.status !== 201) {
throw new Error(
format(
'Failed to create a new GitHub release: GitHub API responded with status code %d.',
response.status,
await response.text(),
),
)
}
return response.json()
}