Skip to content

Commit

Permalink
fix(@pvm/plugin-core): partially failed publish now throws error
Browse files Browse the repository at this point in the history
Closes #21
  • Loading branch information
SkReD committed Oct 31, 2022
1 parent a8b7888 commit d59ec04
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { parseCommit } from './common'

import type { Commit as ConventionalCommit } from 'conventional-commits-parser'
import type { ReleasedProps, Message } from '@pvm/types'
import { defaultMessageBodyWrapper } from '@pvm/plugin-core/messages/message-builder'

function cutText(text: string, maxLen: number): string {
return text.length <= maxLen ? text : text.substr(0, maxLen)
Expand Down Expand Up @@ -245,17 +246,18 @@ export async function releaseMessage(
releaseProps: ReleasedProps,
opts: MessageBuilderOpts = {}
): Promise<Omit<Message, 'channel'>> {
const { pvmConfig } = releaseProps
const { pvmConfig, packagesStats } = releaseProps
const { attachPackages = isGenericTagUsed(pvmConfig) } = opts
const conventionalCommits = convertCommitsToConvFormat(releaseProps.commits)

return buildMessage(releaseProps, {
bodyWrapper: (body, { releaseLink, releaseName }) => {
let header = releaseLink || releaseName
header += ' has been released'
header = `**${header}**`

return body ? `${header}\n${body}` : header
return defaultMessageBodyWrapper({
body,
releaseName,
releaseLink,
packagesStats,
})
},
attachPackages,
conventionalCommits,
Expand Down
3 changes: 2 additions & 1 deletion packages/pvm-plugin-conventional-changelog/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"license": "Apache-2.0",
"dependencies": {
"@pvm/core": "0.0.0-stub",
"@pvm/plugin-core": "0.0.0-stub",
"@pvm/types": "0.0.0-stub",
"@pvm/vcs": "0.0.0-stub",
"conventional-changelog-angular": "^5.0.10",
Expand All @@ -21,4 +22,4 @@
"devDependencies": {
"@types/conventional-commits-parser": "^3.0.1"
}
}
}
84 changes: 84 additions & 0 deletions src/plugins/core/__tests__/message-builder.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { releaseMessage } from '../messages/message-builder'
import { env } from '@pvm/core/lib/env'

describe('notifications/message-builder', () => {
const ciPipelineUrl = env.CI_PIPELINE_URL
afterEach(() => {
env.CI_PIPELINE_URL = !ciPipelineUrl ? '' : ciPipelineUrl
})

it('should take full tag for simple repositories', async () => {
// @ts-ignore
const repo = await initRepo('simple-one')
Expand Down Expand Up @@ -40,4 +46,82 @@ describe('notifications/message-builder', () => {
// @ts-ignore
expect(message.content).toEqual('moon has been released')
})

it('should add error info if publish failed partially', async () => {
// @ts-ignore
const repo = await initRepo('monorepo-new')

const message = releaseMessage({
tag: 'release-2020.02.02-moon',
commits: [],
targetType: 'slack',
packagesStats: {
success: [{
pkg: 'b',
type: 'success',
publishedVersion: '1.0.0',
registryVersion: '0.0.0',
}],
error: [{
pkg: 'a',
reason: 'error',
type: 'failed',
publishVersion: '1.0.0',
}],
skipped: [],
},
pvmConfig: repo.config,
})

expect(message.content).toEqual(':warning: moon partially failed to release')
})

it('should add error info if publish fully failed', async () => {
// @ts-ignore
const repo = await initRepo('monorepo-new')

const message = releaseMessage({
tag: 'release-2020.02.02-moon',
commits: [],
targetType: 'slack',
packagesStats: {
success: [],
error: [{
pkg: 'a',
reason: 'error',
type: 'failed',
publishVersion: '1.0.0',
}],
skipped: [],
},
pvmConfig: repo.config,
})

expect(message.content).toEqual(':warning: moon failed to release')
})

it('should add pipeline url to error title', async () => {
env.CI_PIPELINE_URL = 'test'
// @ts-ignore
const repo = await initRepo('monorepo-new')

const message = releaseMessage({
tag: 'release-2020.02.02-moon',
commits: [],
targetType: 'slack',
packagesStats: {
success: [],
error: [{
pkg: 'a',
reason: 'error',
type: 'failed',
publishVersion: '1.0.0',
}],
skipped: [],
},
pvmConfig: repo.config,
})

expect(message.content).toEqual(':warning: moon failed to release ([pipeline](test))')
})
})
58 changes: 36 additions & 22 deletions src/plugins/core/messages/message-builder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// This file refers to those that you can freely copy to your own project.
import type { Message, ReleasedProps, Commit } from '@pvm/types'
import type { Message, ReleasedProps, Commit, PublishedStats } from '@pvm/types'
import { issueToMdLink } from '@pvm/core/lib/text/jira'
import { stripServiceLabels } from '@pvm/core/lib/text/commits'
import { isGenericTagUsed } from '@pvm/core/lib/tag-meta'
Expand Down Expand Up @@ -74,33 +74,47 @@ export function buildMessage(releaseProps: ReleasedProps, opts: BuildMessageOpts
}
}

export function defaultMessageBodyWrapper({ body, releaseLink, releaseName, packagesStats }: {
body: string,
releaseLink: string | null,
releaseName: string,
packagesStats: PublishedStats
}) {
let header = releaseLink || releaseName

if (packagesStats.error.length) {
let warnSuffix
if (packagesStats.success.length) {
warnSuffix = 'partially failed to release'
} else {
warnSuffix = 'failed to release'
}

let pipelineSuffix
if (env.CI_PIPELINE_URL) {
pipelineSuffix = `([pipeline](${env.CI_PIPELINE_URL}))`
}

header = `:warning: ${releaseName} ${warnSuffix}${pipelineSuffix ? ` ${pipelineSuffix}` : ''}`
} else if (!releaseLink) {
header += ' has been released'
}

return body ? `${header}\n${body}` : header
}

export function releaseMessage(releaseProps: ReleasedProps, opts: MessageBuilderOpts = {}): Message {
const { pvmConfig, packagesStats } = releaseProps
const { attachPackages = isGenericTagUsed(pvmConfig) } = opts

return buildMessage(releaseProps, {
bodyWrapper: (body, { releaseLink, releaseName }) => {
let header = releaseLink || releaseName

if (packagesStats.error.length) {
let warnSuffix
if (packagesStats.success.length) {
warnSuffix = ' partially failed to release'
} else {
warnSuffix = ' failed to release'
}

let pipelineSuffix
if (env.CI_PIPELINE_URL) {
pipelineSuffix = `(<${env.CI_PIPELINE_URL}|pipeline>)`
}

header = `:warning: ${releaseName} ${warnSuffix}${pipelineSuffix ? ` ${pipelineSuffix}` : ''}`
} else if (!releaseLink) {
header += ' has been released'
}

return body ? `${header}\n${body}` : header
return defaultMessageBodyWrapper({
body,
releaseLink,
releaseName,
packagesStats,
})
},
attachPackages,
})
Expand Down
14 changes: 9 additions & 5 deletions src/plugins/core/publish/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,18 +132,18 @@ export async function publish(flags: Flags): Promise<PublishedStats> {
printUnpublishedSummary(publishedPkgsStats.skipped)
}

if (publishedPkgsStats.error.length) {
logger.log(`errored packages:`)
printUnpublishedSummary(publishedPkgsStats.error, chalk.red)
}

if (skipRealPublishing) {
logger.log(chalk`{yellowBright [DRY RUN] publish summary}:`)
} else {
logger.log(chalk`{yellowBright successfully published packages}:`)
}
printPublishedSummary(publishedPkgsStats.success)

if (publishedPkgsStats.error.length) {
logger.log(`errored packages:`)
printUnpublishedSummary(publishedPkgsStats.error, chalk.red)
}

if (flags.notify) {
try {
const prevReleaseTag = lastReleaseTag(config)
Expand Down Expand Up @@ -182,6 +182,10 @@ export async function publish(flags: Flags): Promise<PublishedStats> {
fs.writeFileSync(flags.outputStats, JSON.stringify(sortPublishedStats(publishedPkgsStats), null, 2))
}

if (publishedPkgsStats.error.length) {
throw new Error(`Failed to publish ${publishedPkgsStats.success.length ? 'some' : 'all'} packages`)
}

return publishedPkgsStats

// Чтобы не загромождать флоу вспомогательные функции вынесены в низ тела основной функции
Expand Down
1 change: 1 addition & 0 deletions src/plugins/github/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const API_ATTEMPT_THROTTLE = 300
const RETRY_CONTINUE = 'RETRY_CONTINUE'

jest.setTimeout(25000)
jest.retryTimes(2)

const githubClient = new Octokit({
auth: env.PVM_GITHUB_TEST_REPO_TOKEN,
Expand Down
26 changes: 26 additions & 0 deletions test/scenarios/pvm-publish.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,32 @@ describe('pvm/publish', () => {
expect(pkgs.find(p => p.pkg === 'c').publishedVersion).toBe('0.44.1')
})

it('publish command should fail if some packages failed to publish', async () => {
const repoPath = writeRepo({ name: 'invalid-publish-registry', spec: 'src/[email protected],src/[email protected]' })
const repo = await initRepo(repoPath)

await repo.updatePkg('src/b', {
publishConfig: {
registry: 'invalid',
},
})

await expect(() => testPublish(repo, '-s all')).rejects.toBeTruthy()
})

it('publish with --bail flag should fail if some packages failed to publish', async () => {
const repoPath = writeRepo({ name: 'invalid-publish-registry', spec: 'src/[email protected],src/[email protected]' })
const repo = await initRepo(repoPath)

await repo.updatePkg('src/b', {
publishConfig: {
registry: 'invalid',
},
})

await expect(() => testPublish(repo, '-s all --bail')).rejects.toBeTruthy()
})

describe('canary', () => {
let slackMocker
beforeAll(async () => {
Expand Down

0 comments on commit d59ec04

Please sign in to comment.