- rework toTag resolving fallback if build was not started from a tag

- fallback to retrieve `toTag` from git API (only if 2 tags are available)
  - FIX https://github.com/mikepenz/release-changelog-builder-action/issues/427
  - FIX https://github.com/mikepenz/release-changelog-builder-action/issues/433
- introduce test case to verify
This commit is contained in:
Mike Penz
2021-08-15 10:56:55 +02:00
parent 8433cedbc5
commit d22595ba8b
6 changed files with 238 additions and 108 deletions
+34 -54
View File
@@ -1,8 +1,6 @@
import * as core from '@actions/core'
import * as github from '@actions/github'
import {Configuration, DefaultConfiguration} from './configuration'
import {Octokit} from '@octokit/rest'
import {createCommandManager} from './gitHelper'
import {ReleaseNotes} from './releaseNotes'
import {Tags} from './tags'
import {failOrError} from './utils'
@@ -23,25 +21,6 @@ export class ReleaseNotesBuilder {
) {}
async build(): Promise<string | null> {
// ensure to resolve the toTag if it was not provided
if (!this.toTag) {
// if not specified try to retrieve tag from github.context.ref
if (github.context.ref.startsWith('refs/tags/')) {
this.toTag = github.context.ref.replace('refs/tags/', '')
core.info(
`🔖 Resolved current tag (${this.toTag}) from the 'github.context.ref'`
)
} else {
// if not specified try to retrieve tag from git
const gitHelper = await createCommandManager(this.repositoryPath)
const latestTag = await gitHelper.latestTag()
this.toTag = latestTag
core.info(
`🔖 Resolved current tag (${this.toTag}) from 'git rev-list --tags --skip=0 --max-count=1'`
)
}
}
if (!this.owner) {
failOrError(`💥 Missing or couldn't resolve 'owner'`, this.failOnError)
return null
@@ -57,14 +36,6 @@ export class ReleaseNotesBuilder {
core.setOutput('repo', this.repo)
core.debug(`Resolved 'repo' as ${this.repo}`)
}
if (!this.toTag) {
failOrError(`💥 Missing or couldn't resolve 'toTag'`, this.failOnError)
return null
} else {
core.setOutput('toTag', this.toTag)
core.debug(`Resolved 'toTag' as ${this.toTag}`)
}
core.endGroup()
// load octokit instance
@@ -72,34 +43,43 @@ export class ReleaseNotesBuilder {
auth: `token ${this.token || process.env.GITHUB_TOKEN}`
})
// ensure to resolve the fromTag if it was not provided specifically
if (!this.fromTag) {
core.startGroup(`🔖 Resolve previous tag`)
core.debug(`fromTag undefined, trying to resolve via API`)
const tagsApi = new Tags(octokit)
// ensure proper from <-> to tag range
core.startGroup(`🔖 Resolve tags`)
const tagsApi = new Tags(octokit)
const tagRange = await tagsApi.retrieveRange(
this.repositoryPath,
this.owner,
this.repo,
this.fromTag,
this.toTag,
this.ignorePreReleases,
this.configuration.max_tags_to_fetch ||
DefaultConfiguration.max_tags_to_fetch,
this.configuration.tag_resolver || DefaultConfiguration.tag_resolver
)
const previousTag = await tagsApi.findPredecessorTag(
this.repositoryPath,
this.owner,
this.repo,
this.toTag,
this.ignorePreReleases,
this.configuration.max_tags_to_fetch ||
DefaultConfiguration.max_tags_to_fetch,
this.configuration.tag_resolver || DefaultConfiguration.tag_resolver
)
if (previousTag == null) {
failOrError(
`💥 Unable to retrieve previous tag given ${this.toTag}`,
this.failOnError
)
return null
}
this.fromTag = previousTag.name
core.debug(`fromTag resolved via previousTag as: ${previousTag.name}`)
core.endGroup()
const thisTag = tagRange.to?.name
if (!thisTag) {
failOrError(`💥 Missing or couldn't resolve 'toTag'`, this.failOnError)
return null
} else {
this.toTag = thisTag
core.setOutput('toTag', thisTag)
core.debug(`Resolved 'toTag' as ${thisTag}`)
}
const previousTag = tagRange.from?.name
if (previousTag == null) {
failOrError(
`💥 Unable to retrieve previous tag given ${this.toTag}`,
this.failOnError
)
return null
}
this.fromTag = previousTag
core.debug(`fromTag resolved via previousTag as: ${previousTag}`)
core.endGroup()
const options = {
owner: this.owner,
repo: this.repo,
+95 -10
View File
@@ -1,10 +1,16 @@
import * as core from '@actions/core'
import * as github from '@actions/github'
import * as semver from 'semver'
import {Octokit, RestEndpointMethodTypes} from '@octokit/rest'
import {SemVer} from 'semver'
import {TagResolver} from './configuration'
import {createCommandManager} from './gitHelper'
export interface TagResult {
from: TagInfo | null
to: TagInfo | null
}
export interface TagInfo {
name: string
commit: string
@@ -51,19 +57,12 @@ export class Tags {
}
async findPredecessorTag(
sortedTags: TagInfo[],
repositoryPath: string,
owner: string,
repo: string,
tag: string,
ignorePreReleases: boolean,
maxTagsToFetch: number,
tagResolver: TagResolver
ignorePreReleases: boolean
): Promise<TagInfo | null> {
const tags = sortTags(
await this.getTags(owner, repo, maxTagsToFetch),
tagResolver
)
const tags = sortedTags
try {
const length = tags.length
if (tags.length > 1) {
@@ -102,6 +101,92 @@ export class Tags {
return null
}
}
async retrieveRange(
repositoryPath: string,
owner: string,
repo: string,
fromTag: string | null,
toTag: string | null,
ignorePreReleases: boolean,
maxTagsToFetch: number,
tagResolver: TagResolver
): Promise<TagResult> {
const tags = sortTags(
await this.getTags(owner, repo, maxTagsToFetch),
tagResolver
)
let resultToTag: TagInfo | null
let resultFromTag: TagInfo | null
// ensure to resolve the toTag if it was not provided
if (!toTag) {
// if not specified try to retrieve tag from github.context.ref
if (github.context.ref?.startsWith('refs/tags/') === true) {
toTag = github.context.ref.replace('refs/tags/', '')
core.info(
`🔖 Resolved current tag (${toTag}) from the 'github.context.ref'`
)
resultToTag = {
name: toTag,
commit: toTag
}
} else if (tags.length > 1) {
resultToTag = tags[0]
core.info(
`🔖 Resolved current tag (${resultToTag.name}) from the tags git API`
)
} else {
// if not specified try to retrieve tag from git
const gitHelper = await createCommandManager(repositoryPath)
const latestTag = await gitHelper.latestTag()
core.info(
`🔖 Resolved current tag (${latestTag}) from 'git rev-list --tags --skip=0 --max-count=1'`
)
resultToTag = {
name: latestTag,
commit: latestTag
}
}
} else {
resultToTag = {
name: toTag,
commit: toTag
}
}
// ensure toTag is specified
toTag = resultToTag.name
// resolve the fromTag if not defined
if (!fromTag) {
core.debug(`fromTag undefined, trying to resolve via API`)
resultFromTag = await this.findPredecessorTag(
tags,
repositoryPath,
toTag,
ignorePreReleases
)
if (resultFromTag != null) {
core.info(
`🔖 Resolved previous tag (${resultFromTag.name}) from the tags git API`
)
}
} else {
resultFromTag = {
name: fromTag,
commit: fromTag
}
}
return {
from: resultFromTag,
to: resultToTag
}
}
}
/*