Skip to content

Commit

Permalink
Tag prefix (#1092)
Browse files Browse the repository at this point in the history
  • Loading branch information
Devon Stewart committed Mar 6, 2022
1 parent a746e29 commit 2220ef1
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 18 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -114,6 +114,7 @@ You can configure Release Drafter using the following key in your `.github/relea
| `category-template` | Optional | The template to use for each category. Use [category template variables](#category-template-variables) to insert values. Default: `"## $TITLE"`. |
| `name-template` | Optional | The template for the name of the draft release. For example: `"v$NEXT_PATCH_VERSION"`. |
| `tag-template` | Optional | The template for the tag of the draft release. For example: `"v$NEXT_PATCH_VERSION"`. |
| `tag-prefix` | Optional | A known prefix used to filter release tags. For matching tags, this prefix is stripped before attempting to parse the version. Default: `""` |
| `version-template` | Optional | The template to use when calculating the next version number for the release. Useful for projects that don't use semantic versioning. Default: `"$MAJOR.$MINOR.$PATCH"` |
| `change-template` | Optional | The template to use for each merged pull request. Use [change template variables](#change-template-variables) to insert values. Default: `"* $TITLE (#$NUMBER) @$AUTHOR"`. |
| `change-title-escapes` | Optional | Characters to escape in `$TITLE` when inserting into `change-template` so that they are not interpreted as Markdown format characters. Default: `""` |
Expand All @@ -131,6 +132,7 @@ You can configure Release Drafter using the following key in your `.github/relea
| `version-resolver` | Optional | Adjust the `$RESOLVED_VERSION` variable using labels. Refer to [Version Resolver](#version-resolver) to learn more about this |
| `commitish` | Optional | The release target, i.e. branch or commit it should point to. Default: the ref that release-drafter runs for, e.g. `refs/heads/master` if configured to run on pushes to `master`. |
| `filter-by-commitish` | Optional | Filter previous releases to consider only those with the target matching `commitish`. Default: `false`. |
| `include-paths` | Optional | Restrict pull requests included in the release notes to only the pull requests that modified any of the paths in this array. Supports files and directories. Default: `[]` |

Release Drafter also supports [Probot Config](https://github.com/probot/probot-config), if you want to store your configuration files in a central repository. This allows you to share configurations between projects, and create a organization-wide configuration file by creating a repository named `.github` with the file `.github/release-drafter.yml`.

Expand Down
38 changes: 29 additions & 9 deletions dist/index.js
Expand Up @@ -128605,12 +128605,16 @@ module.exports = (app, { getRouter }) => {
}

const targetCommitish = commitish || config['commitish'] || ref
const filterByCommitish = config['filter-by-commitish']
const {
'filter-by-commitish': filterByCommitish,
'tag-prefix': tagPrefix,
} = config

const { draftRelease, lastRelease } = await findReleases({
context,
targetCommitish,
filterByCommitish,
tagPrefix,
})

const { commits, pullRequests: mergedPullRequests } =
Expand Down Expand Up @@ -128997,6 +129001,7 @@ const { SORT_BY, SORT_DIRECTIONS } = __nccwpck_require__(11940)
const DEFAULT_CONFIG = Object.freeze({
'name-template': '',
'tag-template': '',
'tag-prefix': '',
'change-template': `* $TITLE (#$NUMBER) @$AUTHOR`,
'change-title-escapes': '',
'no-changes-template': `* No changes`,
Expand Down Expand Up @@ -129134,6 +129139,7 @@ const findReleases = async ({
context,
targetCommitish,
filterByCommitish,
tagPrefix,
}) => {
let releaseCount = 0
let releases = await context.octokit.paginate(
Expand All @@ -129156,12 +129162,15 @@ const findReleases = async ({
// `refs/heads/branch` and `branch` are the same thing in this context
const headRefRegex = /^refs\/heads\//
const targetCommitishName = targetCommitish.replace(headRefRegex, '')
const filteredReleases = filterByCommitish
const commitishFilteredReleases = filterByCommitish
? releases.filter(
(r) =>
targetCommitishName === r.target_commitish.replace(headRefRegex, '')
)
: releases
const filteredReleases = tagPrefix
? commitishFilteredReleases.filter((r) => r.tag_name.startsWith(tagPrefix))
: commitishFilteredReleases
const sortedPublishedReleases = sortReleases(
filteredReleases.filter((r) => !r.draft)
)
Expand Down Expand Up @@ -129428,7 +129437,8 @@ const generateReleaseInfo = ({
// Use the first override parameter to identify
// a version, from the most accurate to the least
version || tag || name,
resolveVersionKeyIncrement(mergedPullRequests, config)
resolveVersionKeyIncrement(mergedPullRequests, config),
config['tag-prefix']
)

if (versionInfo) {
Expand Down Expand Up @@ -129575,6 +129585,10 @@ const schema = (context) => {
.allow('')
.default(DEFAULT_CONFIG['name-template']),

'tag-prefix': Joi.string()
.allow('')
.default(DEFAULT_CONFIG['tag-prefix']),

'tag-template': Joi.string()
.allow('')
.default(DEFAULT_CONFIG['tag-template']),
Expand Down Expand Up @@ -130077,24 +130091,30 @@ const toSemver = (version) => {
return semver.coerce(version)
}

const coerceVersion = (input) => {
const coerceVersion = (input, tagPrefix) => {
if (!input) {
return
}

const stripTag = (input) =>
tagPrefix && input.startsWith(tagPrefix)
? input.slice(tagPrefix.length)
: input

return typeof input === 'object'
? toSemver(input.tag_name) || toSemver(input.name)
: toSemver(input)
? toSemver(stripTag(input.tag_name)) || toSemver(stripTag(input.name))
: toSemver(stripTag(input))
}

const getVersionInfo = (
release,
template,
inputVersion,
versionKeyIncrement
versionKeyIncrement,
tagPrefix
) => {
const version = coerceVersion(release)
inputVersion = coerceVersion(inputVersion)
const version = coerceVersion(release, tagPrefix)
inputVersion = coerceVersion(inputVersion, tagPrefix)

if (!version && !inputVersion) {
return defaultVersionInfo
Expand Down
6 changes: 5 additions & 1 deletion index.js
Expand Up @@ -159,12 +159,16 @@ module.exports = (app, { getRouter }) => {
}

const targetCommitish = commitish || config['commitish'] || ref
const filterByCommitish = config['filter-by-commitish']
const {
'filter-by-commitish': filterByCommitish,
'tag-prefix': tagPrefix,
} = config

const { draftRelease, lastRelease } = await findReleases({
context,
targetCommitish,
filterByCommitish,
tagPrefix,
})

const { commits, pullRequests: mergedPullRequests } =
Expand Down
1 change: 1 addition & 0 deletions lib/default-config.js
Expand Up @@ -3,6 +3,7 @@ const { SORT_BY, SORT_DIRECTIONS } = require('./sort-pull-requests')
const DEFAULT_CONFIG = Object.freeze({
'name-template': '',
'tag-template': '',
'tag-prefix': '',
'change-template': `* $TITLE (#$NUMBER) @$AUTHOR`,
'change-title-escapes': '',
'no-changes-template': `* No changes`,
Expand Down
9 changes: 7 additions & 2 deletions lib/releases.js
Expand Up @@ -24,6 +24,7 @@ const findReleases = async ({
context,
targetCommitish,
filterByCommitish,
tagPrefix,
}) => {
let releaseCount = 0
let releases = await context.octokit.paginate(
Expand All @@ -46,12 +47,15 @@ const findReleases = async ({
// `refs/heads/branch` and `branch` are the same thing in this context
const headRefRegex = /^refs\/heads\//
const targetCommitishName = targetCommitish.replace(headRefRegex, '')
const filteredReleases = filterByCommitish
const commitishFilteredReleases = filterByCommitish
? releases.filter(
(r) =>
targetCommitishName === r.target_commitish.replace(headRefRegex, '')
)
: releases
const filteredReleases = tagPrefix
? commitishFilteredReleases.filter((r) => r.tag_name.startsWith(tagPrefix))
: commitishFilteredReleases
const sortedPublishedReleases = sortReleases(
filteredReleases.filter((r) => !r.draft)
)
Expand Down Expand Up @@ -318,7 +322,8 @@ const generateReleaseInfo = ({
// Use the first override parameter to identify
// a version, from the most accurate to the least
version || tag || name,
resolveVersionKeyIncrement(mergedPullRequests, config)
resolveVersionKeyIncrement(mergedPullRequests, config),
config['tag-prefix']
)

if (versionInfo) {
Expand Down
4 changes: 4 additions & 0 deletions lib/schema.js
Expand Up @@ -39,6 +39,10 @@ const schema = (context) => {
.allow('')
.default(DEFAULT_CONFIG['name-template']),

'tag-prefix': Joi.string()
.allow('')
.default(DEFAULT_CONFIG['tag-prefix']),

'tag-template': Joi.string()
.allow('')
.default(DEFAULT_CONFIG['tag-template']),
Expand Down
18 changes: 12 additions & 6 deletions lib/versions.js
Expand Up @@ -136,24 +136,30 @@ const toSemver = (version) => {
return semver.coerce(version)
}

const coerceVersion = (input) => {
const coerceVersion = (input, tagPrefix) => {
if (!input) {
return
}

const stripTag = (input) =>
tagPrefix && input.startsWith(tagPrefix)
? input.slice(tagPrefix.length)
: input

return typeof input === 'object'
? toSemver(input.tag_name) || toSemver(input.name)
: toSemver(input)
? toSemver(stripTag(input.tag_name)) || toSemver(stripTag(input.name))
: toSemver(stripTag(input))
}

const getVersionInfo = (
release,
template,
inputVersion,
versionKeyIncrement
versionKeyIncrement,
tagPrefix
) => {
const version = coerceVersion(release)
inputVersion = coerceVersion(inputVersion)
const version = coerceVersion(release, tagPrefix)
inputVersion = coerceVersion(inputVersion, tagPrefix)

if (!version && !inputVersion) {
return defaultVersionInfo
Expand Down
12 changes: 12 additions & 0 deletions schema.json
Expand Up @@ -47,6 +47,18 @@
}
]
},
"tag-prefix": {
"anyOf": [
{
"type": "string",
"enum": [""]
},
{
"default": "",
"type": "string"
}
]
},
"tag-template": {
"anyOf": [
{
Expand Down
7 changes: 7 additions & 0 deletions test/fixtures/config/config-with-tag-prefix.yml
@@ -0,0 +1,7 @@
name-template: 'static-tag-prefix-v$RESOLVED_VERSION 🌈'
tag-template: 'static-tag-prefix-v$RESOLVED_VERSION'
tag-prefix: static-tag-prefix-v
template: |
## Previous release
$PREVIOUS_TAG
52 changes: 52 additions & 0 deletions test/index.test.js
Expand Up @@ -2831,6 +2831,58 @@ describe('release-drafter', () => {
})
})

describe('with tag-prefix', () => {
it('gets the version from the tag, stripping the prefix', async () => {
getConfigMock('config-with-tag-prefix.yml')
// Explicitly include a RC suffix in order to differentiate the
// behaviour of semver.parse vs semver.coerce in versions.js
//
// We expect the release to be 2.1.4, not 2.1.5
const alteredReleasePayload = {
...releasePayload,
tag_name: 'static-tag-prefix-v2.1.4-RC3',
}

nock('https://api.github.com')
.post('/graphql', (body) =>
body.query.includes('query findCommitsWithAssociatedPullRequests')
)
.reply(200, graphqlCommitsNoPRsPayload)

nock('https://api.github.com')
.get('/repos/toolmantim/release-drafter-test-project/releases')
.query(true)
.reply(200, [alteredReleasePayload])
.post(
'/repos/toolmantim/release-drafter-test-project/releases',
(body) => {
expect(body).toMatchInlineSnapshot(`
Object {
"body": "## Previous release
static-tag-prefix-v2.1.4-RC3
",
"draft": true,
"name": "static-tag-prefix-v2.1.4 🌈",
"prerelease": false,
"tag_name": "static-tag-prefix-v2.1.4",
"target_commitish": "refs/heads/master",
}
`)
return true
}
)
.reply(200, alteredReleasePayload)

await probot.receive({
name: 'push',
payload: pushPayload,
})

expect.assertions(1)
})
})

describe('with custom version resolver', () => {
it('uses correct default when no labels exist', async () => {
getConfigMock('config-with-custom-version-resolver-none.yml')
Expand Down

0 comments on commit 2220ef1

Please sign in to comment.