- provide alternative method to sort tags

- introduce option configuration allowing to specify which method to pick
  - semver (default)
  - alphabetical sort order (sort)
This commit is contained in:
Mike Penz
2020-10-20 11:55:09 +02:00
parent 58bf38f3d9
commit 1089e28a2f
4 changed files with 91 additions and 11 deletions
+40 -4
View File
@@ -2,7 +2,7 @@ import { resolveConfiguration } from '../src/utils';
import { ReleaseNotesBuilder } from '../src/releaseNotesBuilder'; import { ReleaseNotesBuilder } from '../src/releaseNotesBuilder';
import { TagInfo, sortTags } from '../src/tags'; import { TagInfo, sortTags } from '../src/tags';
it('Should order tags correctly', async () => { it('Should order tags correctly using semver', async () => {
jest.setTimeout(180000) jest.setTimeout(180000)
const tags: TagInfo[] = [ const tags: TagInfo[] = [
@@ -16,7 +16,10 @@ it('Should order tags correctly', async () => {
{ name: "v2020.3.0", commit: "" } { name: "v2020.3.0", commit: "" }
] ]
const sorted = sortTags(tags).map(function (tag) { const tagResolver = {
method: "semver"
}
const sorted = sortTags(tags, tagResolver).map(function (tag) {
return tag.name return tag.name
}).join(",") }).join(",")
@@ -24,7 +27,7 @@ it('Should order tags correctly', async () => {
}) })
it('Should order tags correctly', async () => { it('Should order tags correctly using semver', async () => {
jest.setTimeout(180000) jest.setTimeout(180000)
const tags: TagInfo[] = [ const tags: TagInfo[] = [
@@ -43,9 +46,42 @@ it('Should order tags correctly', async () => {
{ name: "1000.0.0", commit: "" }, { name: "1000.0.0", commit: "" },
] ]
const sorted = sortTags(tags).map(function (tag) { const tagResolver = {
method: "non-existing-method"
}
const sorted = sortTags(tags, tagResolver).map(function (tag) {
return tag.name return tag.name
}).join(",") }).join(",")
expect(sorted).toStrictEqual(`1000.0.0,100.0.0,20.0.2,10.1.0,10.1.0-2,10.0.0,2.0.0,1.0.0,1.0.0-a01,0.1.0,0.1.0-b01,0.0.1,0.0.1-rc01`) expect(sorted).toStrictEqual(`1000.0.0,100.0.0,20.0.2,10.1.0,10.1.0-2,10.0.0,2.0.0,1.0.0,1.0.0-a01,0.1.0,0.1.0-b01,0.0.1,0.0.1-rc01`)
})
it('Should order tags alphabetical', async () => {
jest.setTimeout(180000)
const tags: TagInfo[] = [
{ name: "0.0.1", commit: "" },
{ name: "0.0.1-rc01", commit: "" },
{ name: "0.1.0-b01", commit: "" },
{ name: "1.0.0", commit: "" },
{ name: "a", commit: "" },
{ name: "1.0.0-a01", commit: "" },
{ name: "2.0.0", commit: "" },
{ name: "10.0.0", commit: "" },
{ name: "v1", commit: "" },
{ name: "10.1.0", commit: "" },
{ name: "10.1.0-2", commit: "" },
{ name: "20.0.2", commit: "" },
{ name: "1000.0.0", commit: "" },
]
const tagResolver = {
method: "sort"
}
const sorted = sortTags(tags, tagResolver).map(function (tag) {
return tag.name
}).join(",")
expect(sorted).toStrictEqual(`a,20.0.2,2.0.0,1000.0.0,10.1.0,10.1.0-2,10.0.0,1.0.0,1.0.0-a01,v1,0.1.0-b01,0.0.1,0.0.1-rc01`)
}) })
+10 -1
View File
@@ -9,6 +9,7 @@ export interface Configuration {
empty_template: string empty_template: string
categories: Category[] categories: Category[]
transformers: Transformer[] transformers: Transformer[]
tag_resolver: TagResolver
} }
export interface Category { export interface Category {
@@ -21,6 +22,10 @@ export interface Transformer {
target: string target: string
} }
export interface TagResolver {
method: string // semver, sort
}
export const DefaultConfiguration: Configuration = { export const DefaultConfiguration: Configuration = {
max_tags_to_fetch: 200, // the amount of tags to fetch from the github API max_tags_to_fetch: 200, // the amount of tags to fetch from the github API
max_pull_requests: 200, // the amount of pull requests to process max_pull_requests: 200, // the amount of pull requests to process
@@ -44,5 +49,9 @@ export const DefaultConfiguration: Configuration = {
labels: ['test'] labels: ['test']
} }
], // the categories to support for the ordering ], // the categories to support for the ordering
transformers: [] // transformers to apply on the PR description according to the `pr_template` transformers: [], // transformers to apply on the PR description according to the `pr_template`
tag_resolver: {
// defines the logic on how to resolve the previous tag, only relevant if `fromTag` is not specified
method: 'semver' // defines which method to use, by default it will use `semver` (dropping all non matching tags). Alternative `sort` is also available.
}
} }
+2 -1
View File
@@ -83,7 +83,8 @@ export class ReleaseNotesBuilder {
this.toTag, this.toTag,
this.ignorePreReleases, this.ignorePreReleases,
this.configuration.max_tags_to_fetch || this.configuration.max_tags_to_fetch ||
DefaultConfiguration.max_tags_to_fetch DefaultConfiguration.max_tags_to_fetch,
this.configuration.tag_resolver || DefaultConfiguration.tag_resolver
) )
if (previousTag == null) { if (previousTag == null) {
failOrError( failOrError(
+39 -5
View File
@@ -2,6 +2,7 @@ import {Octokit, RestEndpointMethodTypes} from '@octokit/rest'
import * as core from '@actions/core' import * as core from '@actions/core'
import * as semver from 'semver' import * as semver from 'semver'
import {SemVer} from 'semver' import {SemVer} from 'semver'
import {TagResolver} from './configuration'
export interface TagInfo { export interface TagInfo {
name: string name: string
@@ -52,9 +53,13 @@ export class Tags {
repo: string, repo: string,
tag: string, tag: string,
ignorePreReleases: boolean, ignorePreReleases: boolean,
maxTagsToFetch: number maxTagsToFetch: number,
tagResolver: TagResolver
): Promise<TagInfo | null> { ): Promise<TagInfo | null> {
const tags = sortTags(await this.getTags(owner, repo, maxTagsToFetch)) const tags = sortTags(
await this.getTags(owner, repo, maxTagsToFetch),
tagResolver
)
try { try {
const length = tags.length const length = tags.length
@@ -94,12 +99,22 @@ export class Tags {
2020.3.1-a01 2020.3.1-a01
2020.3.0 2020.3.0
*/ */
export function sortTags(tags: TagInfo[]): TagInfo[] { export function sortTags(tags: TagInfo[], tagResolver: TagResolver): TagInfo[] {
if (tagResolver.method === 'sort') {
return stringSorting(tags)
} else {
return semVerSorting(tags)
}
}
function semVerSorting(tags: TagInfo[]): TagInfo[] {
// filter out tags which do not follow semver // filter out tags which do not follow semver
const validatedTags = tags.filter(tag => { const validatedTags = tags.filter(tag => {
const isValid = semver.valid(tag.name) !== null const isValid = semver.valid(tag.name) !== null
if(!isValid) { if (!isValid) {
core.debug(`⚠️ dropped tag ${tag.name} because it is not a valid semver tag`) core.debug(
`⚠️ dropped tag ${tag.name} because it is not a valid semver tag`
)
} }
return isValid return isValid
}) })
@@ -110,3 +125,22 @@ export function sortTags(tags: TagInfo[]): TagInfo[] {
}) })
return validatedTags return validatedTags
} }
function stringSorting(tags: TagInfo[]): TagInfo[] {
return tags.sort((b, a) => {
const partsA = a.name.replace(/^v/, '').split('-')
const partsB = b.name.replace(/^v/, '').split('-')
const versionCompare = partsA[0].localeCompare(partsB[0])
if (versionCompare !== 0) {
return versionCompare
} else {
if (partsA.length === 1) {
return 0
} else if (partsB.length === 1) {
return 1
} else {
return partsA[1].localeCompare(partsB[1])
}
}
})
}