Skip to content

Commit

Permalink
feat: revert changes in case of errors
Browse files Browse the repository at this point in the history
  • Loading branch information
kettanaito committed Apr 21, 2022
1 parent ab5a359 commit b794b17
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 38 deletions.
100 changes: 62 additions & 38 deletions src/commands/publish.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ export class Publish extends Command {
const branchName = await getCurrentBranch()
console.log('preparing release from "%s"...', branchName)

/**
* @todo Check that the repo state is without uncommitted changes.
*/

// Get the latest release.
const tags = await getTags()
const latestRelease = await getLatestRelease(tags)
Expand Down Expand Up @@ -112,53 +116,73 @@ export class Publish extends Command {
console.log(publishResult.data)
console.log('published successfully!')

// Create a release commit containing the version bump in package.json
const commitResult = await until(() => {
return createCommit({
files: ['package.json'],
message: `chore: release ${nextVersion}`,
const revertQueue: Array<() => Promise<void>> = []

const result = await until(async () => {
// Create a release commit containing the version bump in package.json
const commitResult = await until(() => {
return createCommit({
files: ['package.json'],
message: `chore: release ${nextVersion}`,
})
})
})
invariant(
commitResult.error == null,
'Failed to create release commit!\n',
commitResult.error
)

console.log('created a release commit!')
invariant(
commitResult.error == null,
'Failed to create release commit!\n',
commitResult.error
)

// Create a Git tag for the release.
const tagResult = await until(() => createTag(nextVersion))
invariant(
tagResult.error == null,
'Failed to tag the release!\n',
tagResult.error
)
revertQueue.push(async () => {
console.log('reverting the release commit...')
await execAsync('git reset --hard HEAD~1')
})

console.log('created release tag "%s"!', tagResult.data)
console.log('created a release commit!')

// Push the release commit and tag to the origin.
const pushResult = await until(() => push())
invariant(
pushResult.error == null,
'Failed to push changes to origin!\n',
pushResult.error
)
// Create a Git tag for the release.
const tagResult = await until(() => createTag(nextVersion))

console.log('pushed changes to origin!')
invariant(
tagResult.error == null,
'Failed to tag the release!\n',
tagResult.error
)

// Generate release notes and create a new release on GitHub.
const releaseNotes = await getReleaseNotes(commits)
const releaseMarkdown = toMarkdown(context, releaseNotes)
console.log('generated release notes:\n\n', releaseMarkdown)
revertQueue.push(async () => {
console.log('reverting release tag...')
await execAsync(`git tag -d ${nextVersion}`)
})

const releaseUrl = await createRelease(context, releaseMarkdown)
console.log('created release: %s', releaseUrl)
console.log('created release tag "%s"!', tagResult.data)

/**
* @todo Revert release tag/commit if anything fails
* after the tag point.
*/
// Push the release commit and tag to the origin.
const pushResult = await until(() => push())
invariant(
pushResult.error == null,
'Failed to push changes to origin!\n',
pushResult.error
)

console.log('pushed changes to origin!')

// Generate release notes and create a new release on GitHub.
const releaseNotes = await getReleaseNotes(commits)
const releaseMarkdown = toMarkdown(context, releaseNotes)
console.log('generated release notes:\n\n', releaseMarkdown)

const releaseUrl = await createRelease(context, releaseMarkdown)
console.log('created release: %s', releaseUrl)
})

if (result.error) {
// Revert changes in case of errors.
for (const revert of revertQueue) {
await revert()
}

throw result.error
}

console.log('release done!')
}
Expand Down
6 changes: 6 additions & 0 deletions src/utils/git/createRelease.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ export async function createRelease(
): Promise<string> {
const { repo } = context

console.log(
'creating a new release at "%s/%s"...',
context.repo.owner,
context.repo.name
)

const response = await fetch(
`https://api.github.com/repos/${repo.owner}/${repo.name}/releases`,
{
Expand Down

0 comments on commit b794b17

Please sign in to comment.