@ossjs/release
Version:
Minimalistic, opinionated, and predictable release automation tool.
188 lines (163 loc) • 4.64 kB
text/typescript
import { http, HttpResponse, type HttpResponseResolver } from 'msw'
import { Notes } from '#/src/commands/notes.js'
import { log } from '#/src/logger.js'
import { commit } from '#/src/utils/git/commit.js'
import { testEnvironment } from '#/test/env.js'
import { execAsync } from '#/src/utils/exec-async.js'
import { type GitHubRelease } from '#/src/utils/github/get-github-release.js'
const { setup, reset, cleanup, api, createRepository } = testEnvironment({
fileSystemPath: 'notes',
})
const gitHubReleaseResolver = vi.fn<HttpResponseResolver>(() => {
return HttpResponse.json({ html_url: '/releases/1' }, { status: 201 })
})
beforeAll(async () => {
await setup()
})
afterEach(async () => {
await reset()
})
afterAll(async () => {
await cleanup()
})
it('creates a GitHub release for a past release', async () => {
await createRepository('past-release')
api.use(
http.post(
'https://api.github.com/repos/:owner/:repo/releases',
gitHubReleaseResolver,
),
http.get<never, never, GitHubRelease>(
`https://api.github.com/repos/:owner/:name/releases/latest`,
() => {
return new HttpResponse(null, { status: 404 })
},
),
http.get<never, never, GitHubRelease>(
'https://api.github.com/repos/:owner/:repo/releases/tags/:tag',
() => {
return new HttpResponse(null, { status: 404 })
},
),
)
// Preceding (previous) release.
await commit({
message: `feat: long-ago published`,
allowEmpty: true,
})
const prevReleaseCommit = await commit({
message: `chore(release): v0.1.0`,
allowEmpty: true,
})
await execAsync('git tag v0.1.0')
// Relevant release.
const fixCommit = await commit({
message: `fix: relevant fix`,
allowEmpty: true,
})
await commit({
message: `docs: not worthy of release notes`,
allowEmpty: true,
})
const featCommit = await commit({
message: `feat: relevant feature`,
allowEmpty: true,
})
const releaseCommit = await commit({
message: `chore(release): v0.2.0`,
allowEmpty: true,
date: new Date('2005-04-07T22:13:13'),
})
await execAsync(`git tag v0.2.0`)
// Future release.
await commit({
message: `fix: other that`,
allowEmpty: true,
})
await commit({
message: `chore(release): v0.2.1`,
allowEmpty: true,
})
await execAsync(`git tag v0.2.1`)
const notes = new Notes(
{
profiles: [
{
name: 'latest',
use: 'exit 0',
},
],
},
{
_: ['', '0.2.0'],
},
)
await notes.run()
expect(log.info).toHaveBeenCalledWith(
'creating GitHub release for version "v0.2.0" in "octocat/past-release"...',
)
expect(log.info).toHaveBeenCalledWith(
`found release tag "v0.2.0" (${releaseCommit.hash})`,
)
expect(log.info).toHaveBeenCalledWith(
`found preceding release "v0.1.0" (${prevReleaseCommit.hash})`,
)
// Must generate correct release notes.
expect(log.info).toHaveBeenCalledWith(`generated release notes:
## v0.2.0 (2005-04-07)
### Features
- relevant feature (${featCommit.hash})
### Bug Fixes
- relevant fix (${fixCommit.hash})`)
// Must create a new GitHub release.
expect(gitHubReleaseResolver).toHaveBeenCalledTimes(1)
expect(log.info).toHaveBeenCalledWith('created GitHub release: /releases/1')
})
it('skips creating a GitHub release if the given release already exists', async () => {
await createRepository('skip-if-exists')
api.use(
http.post(
'https://api.github.com/repos/:owner/:repo/releases',
gitHubReleaseResolver,
),
http.get<never, never, GitHubRelease>(
`https://api.github.com/repos/:owner/:name/releases/latest`,
() => {
return new HttpResponse(null, { status: 404 })
},
),
http.get<never, never, GitHubRelease>(
'https://api.github.com/repos/:owner/:repo/releases/tags/:tag',
() => {
return HttpResponse.json({
tag_name: 'v1.0.0',
html_url: '/releases/1',
})
},
),
)
const notes = new Notes(
{
profiles: [
{
name: 'latest',
use: 'exit 0',
},
],
},
{
_: ['', '1.0.0'],
},
)
await notes.run()
expect(log.warn).toHaveBeenCalledWith(
'found existing GitHub release for "v1.0.0": /releases/1',
)
expect(log.info).not.toHaveBeenCalledWith(
'creating GitHub release for version "v1.0.0" in "octocat/skip-if-exists"',
)
expect(log.info).not.toHaveBeenCalledWith(
expect.stringContaining('created GitHub release:'),
)
expect(process.exit).toHaveBeenCalledWith(1)
})