mirror of
https://github.com/tj-actions/changed-files
synced 2024-12-18 19:44:45 +00:00
fix: bug detecting previous tag when workflow is rerun (#2107)
Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
parent
8a0655f075
commit
03334d095e
5 changed files with 83 additions and 153 deletions
BIN
dist/index.js
generated
vendored
BIN
dist/index.js
generated
vendored
Binary file not shown.
BIN
dist/index.js.map
generated
vendored
BIN
dist/index.js.map
generated
vendored
Binary file not shown.
|
@ -659,95 +659,45 @@ describe('utils test', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe('getPreviousGitTag', () => {
|
describe('getPreviousGitTag', () => {
|
||||||
// Function returns the second latest tag and its SHA
|
// Function returns the second-latest tag and its SHA
|
||||||
it('should return the second latest tag and its SHA when multiple tags are present', async () => {
|
it('should return the second latest tag and its SHA when multiple tags are present', async () => {
|
||||||
jest
|
|
||||||
.spyOn(exec, 'getExecOutput')
|
|
||||||
.mockResolvedValueOnce({
|
|
||||||
stdout: 'v1.0.1\nv1.0.0\nv0.9.9',
|
|
||||||
stderr: '',
|
|
||||||
exitCode: 0
|
|
||||||
})
|
|
||||||
.mockResolvedValueOnce({
|
|
||||||
stdout: 'abc123',
|
|
||||||
stderr: '',
|
|
||||||
exitCode: 0
|
|
||||||
})
|
|
||||||
const result = await getPreviousGitTag({
|
const result = await getPreviousGitTag({
|
||||||
cwd: '.',
|
cwd: '.',
|
||||||
tagsPattern: '*',
|
tagsPattern: '*',
|
||||||
tagsIgnorePattern: ''
|
tagsIgnorePattern: '',
|
||||||
|
currentBranch: 'v1.0.1'
|
||||||
|
})
|
||||||
|
expect(result).toEqual({
|
||||||
|
tag: 'v1.0.0',
|
||||||
|
sha: 'f0751de6af436d4e79016e2041cf6400e0833653'
|
||||||
})
|
})
|
||||||
expect(result).toEqual({tag: 'v1.0.0', sha: 'abc123'})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Tags are filtered by a specified pattern when 'tagsPattern' is provided
|
// Tags are filtered by a specified pattern when 'tagsPattern' is provided
|
||||||
it('should filter tags by the specified pattern', async () => {
|
it('should filter tags by the specified pattern', async () => {
|
||||||
jest
|
|
||||||
.spyOn(exec, 'getExecOutput')
|
|
||||||
.mockResolvedValueOnce({
|
|
||||||
stdout: 'v1.0.1\nv1.0.0\nv0.9.9',
|
|
||||||
stderr: '',
|
|
||||||
exitCode: 0
|
|
||||||
})
|
|
||||||
.mockResolvedValueOnce({
|
|
||||||
stdout: 'def456',
|
|
||||||
stderr: '',
|
|
||||||
exitCode: 0
|
|
||||||
})
|
|
||||||
const result = await getPreviousGitTag({
|
const result = await getPreviousGitTag({
|
||||||
cwd: '.',
|
cwd: '.',
|
||||||
tagsPattern: 'v1.*',
|
tagsPattern: 'v1.*',
|
||||||
tagsIgnorePattern: ''
|
tagsIgnorePattern: '',
|
||||||
|
currentBranch: 'v1.0.1'
|
||||||
|
})
|
||||||
|
expect(result).toEqual({
|
||||||
|
tag: 'v1.0.0',
|
||||||
|
sha: 'f0751de6af436d4e79016e2041cf6400e0833653'
|
||||||
})
|
})
|
||||||
expect(result).toEqual({tag: 'v1.0.0', sha: 'def456'})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Tags are excluded by a specified ignore pattern when 'tagsIgnorePattern' is provided
|
// Tags are excluded by a specified ignore pattern when 'tagsIgnorePattern' is provided
|
||||||
it('should exclude tags by the specified ignore pattern', async () => {
|
it('should exclude tags by the specified ignore pattern', async () => {
|
||||||
jest
|
|
||||||
.spyOn(exec, 'getExecOutput')
|
|
||||||
.mockResolvedValueOnce({
|
|
||||||
stdout: 'v1.0.1\nv1.0.0\nv0.9.9',
|
|
||||||
stderr: '',
|
|
||||||
exitCode: 0
|
|
||||||
})
|
|
||||||
.mockResolvedValueOnce({
|
|
||||||
stdout: 'ghi789',
|
|
||||||
stderr: '',
|
|
||||||
exitCode: 0
|
|
||||||
})
|
|
||||||
const result = await getPreviousGitTag({
|
const result = await getPreviousGitTag({
|
||||||
cwd: '.',
|
cwd: '.',
|
||||||
tagsPattern: '*',
|
tagsPattern: '*',
|
||||||
tagsIgnorePattern: 'v0.*.*'
|
tagsIgnorePattern: 'v0.*.*',
|
||||||
|
currentBranch: 'v1.0.1'
|
||||||
})
|
})
|
||||||
expect(result).toEqual({tag: 'v1.0.0', sha: 'ghi789'})
|
expect(result).toEqual({
|
||||||
})
|
tag: 'v1.0.0',
|
||||||
|
sha: 'f0751de6af436d4e79016e2041cf6400e0833653'
|
||||||
// Function executes silently when debug mode is not active
|
|
||||||
it('should execute silently when debug mode is not active', async () => {
|
|
||||||
jest.spyOn(core, 'isDebug').mockReturnValue(false)
|
|
||||||
const spy = jest
|
|
||||||
.spyOn(exec, 'getExecOutput')
|
|
||||||
.mockResolvedValueOnce({
|
|
||||||
stdout: 'v1.0.1\nv1.0.0',
|
|
||||||
stderr: '',
|
|
||||||
exitCode: 0
|
|
||||||
})
|
|
||||||
.mockResolvedValueOnce({
|
|
||||||
stdout: 'jkl012',
|
|
||||||
stderr: '',
|
|
||||||
exitCode: 0
|
|
||||||
})
|
|
||||||
await getPreviousGitTag({
|
|
||||||
cwd: '.',
|
|
||||||
tagsPattern: '*',
|
|
||||||
tagsIgnorePattern: ''
|
|
||||||
})
|
|
||||||
expect(spy).toHaveBeenCalledWith('git', ['tag', '--sort=-creatordate'], {
|
|
||||||
cwd: '.',
|
|
||||||
silent: true
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -761,7 +711,8 @@ describe('utils test', () => {
|
||||||
const result = await getPreviousGitTag({
|
const result = await getPreviousGitTag({
|
||||||
cwd: '.',
|
cwd: '.',
|
||||||
tagsPattern: '*',
|
tagsPattern: '*',
|
||||||
tagsIgnorePattern: ''
|
tagsIgnorePattern: '',
|
||||||
|
currentBranch: ''
|
||||||
})
|
})
|
||||||
expect(result).toEqual({tag: '', sha: ''})
|
expect(result).toEqual({tag: '', sha: ''})
|
||||||
})
|
})
|
||||||
|
@ -769,44 +720,16 @@ describe('utils test', () => {
|
||||||
// Only one tag is available, making it impossible to find a previous tag
|
// Only one tag is available, making it impossible to find a previous tag
|
||||||
it('should return empty values when only one tag is available', async () => {
|
it('should return empty values when only one tag is available', async () => {
|
||||||
jest.spyOn(exec, 'getExecOutput').mockResolvedValueOnce({
|
jest.spyOn(exec, 'getExecOutput').mockResolvedValueOnce({
|
||||||
stdout: 'v1.0.1',
|
stdout:
|
||||||
|
'v1.0.1|f0751de6af436d4e79016e2041cf6400e0833653|2021-01-01T00:00:00Z',
|
||||||
stderr: '',
|
stderr: '',
|
||||||
exitCode: 0
|
exitCode: 0
|
||||||
})
|
})
|
||||||
const result = await getPreviousGitTag({
|
const result = await getPreviousGitTag({
|
||||||
cwd: '.',
|
cwd: '.',
|
||||||
tagsPattern: '*',
|
tagsPattern: '*',
|
||||||
tagsIgnorePattern: ''
|
tagsIgnorePattern: '',
|
||||||
})
|
currentBranch: 'v1.0.1'
|
||||||
expect(result).toEqual({tag: '', sha: ''})
|
|
||||||
})
|
|
||||||
|
|
||||||
// Provided 'tagsPattern' matches no tags
|
|
||||||
it('should return empty values when provided tagsPattern matches no tags', async () => {
|
|
||||||
jest.spyOn(exec, 'getExecOutput').mockResolvedValueOnce({
|
|
||||||
stdout: 'v1.0.1\nv1.0.0',
|
|
||||||
stderr: '',
|
|
||||||
exitCode: 0
|
|
||||||
})
|
|
||||||
const result = await getPreviousGitTag({
|
|
||||||
cwd: '.',
|
|
||||||
tagsPattern: 'nonexistent*',
|
|
||||||
tagsIgnorePattern: ''
|
|
||||||
})
|
|
||||||
expect(result).toEqual({tag: '', sha: ''})
|
|
||||||
})
|
|
||||||
|
|
||||||
// Provided 'tagsIgnorePattern' excludes all tags
|
|
||||||
it('should return empty values when provided tagsIgnorePattern excludes all tags', async () => {
|
|
||||||
jest.spyOn(exec, 'getExecOutput').mockResolvedValueOnce({
|
|
||||||
stdout: 'v1.0.1\nv1.0.0',
|
|
||||||
stderr: '',
|
|
||||||
exitCode: 0
|
|
||||||
})
|
|
||||||
const result = await getPreviousGitTag({
|
|
||||||
cwd: '.',
|
|
||||||
tagsPattern: '*',
|
|
||||||
tagsIgnorePattern: 'v*'
|
|
||||||
})
|
})
|
||||||
expect(result).toEqual({tag: '', sha: ''})
|
expect(result).toEqual({tag: '', sha: ''})
|
||||||
})
|
})
|
||||||
|
@ -817,34 +740,13 @@ describe('utils test', () => {
|
||||||
.spyOn(exec, 'getExecOutput')
|
.spyOn(exec, 'getExecOutput')
|
||||||
.mockRejectedValue(new Error('git command failed'))
|
.mockRejectedValue(new Error('git command failed'))
|
||||||
await expect(
|
await expect(
|
||||||
getPreviousGitTag({cwd: '.', tagsPattern: '*', tagsIgnorePattern: ''})
|
getPreviousGitTag({
|
||||||
|
cwd: '.',
|
||||||
|
tagsPattern: '*',
|
||||||
|
tagsIgnorePattern: '',
|
||||||
|
currentBranch: 'v1.0.1'
|
||||||
|
})
|
||||||
).rejects.toThrow('git command failed')
|
).rejects.toThrow('git command failed')
|
||||||
})
|
})
|
||||||
|
|
||||||
// Debug mode logs additional information
|
|
||||||
it('should log additional information when debug mode is active', async () => {
|
|
||||||
jest.spyOn(core, 'isDebug').mockReturnValue(true)
|
|
||||||
const spy = jest
|
|
||||||
.spyOn(exec, 'getExecOutput')
|
|
||||||
.mockResolvedValueOnce({
|
|
||||||
stdout: 'v1.0.1\nv1.0.0',
|
|
||||||
stderr: '',
|
|
||||||
exitCode: 0
|
|
||||||
})
|
|
||||||
.mockResolvedValueOnce({
|
|
||||||
stdout: 'mno345',
|
|
||||||
stderr: '',
|
|
||||||
exitCode: 0
|
|
||||||
})
|
|
||||||
await getPreviousGitTag({
|
|
||||||
cwd: '.',
|
|
||||||
tagsPattern: '*',
|
|
||||||
tagsIgnorePattern: ''
|
|
||||||
})
|
|
||||||
expect(spy).toHaveBeenCalledWith('git', ['tag', '--sort=-creatordate'], {
|
|
||||||
cwd: '.',
|
|
||||||
silent: false
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -243,7 +243,8 @@ export const getSHAForNonPullRequestEvent = async ({
|
||||||
const {sha, tag} = await getPreviousGitTag({
|
const {sha, tag} = await getPreviousGitTag({
|
||||||
cwd: workingDirectory,
|
cwd: workingDirectory,
|
||||||
tagsPattern: inputs.tagsPattern,
|
tagsPattern: inputs.tagsPattern,
|
||||||
tagsIgnorePattern: inputs.tagsIgnorePattern
|
tagsIgnorePattern: inputs.tagsIgnorePattern,
|
||||||
|
currentBranch
|
||||||
})
|
})
|
||||||
previousSha = sha
|
previousSha = sha
|
||||||
targetBranch = tag
|
targetBranch = tag
|
||||||
|
|
75
src/utils.ts
75
src/utils.ts
|
@ -831,53 +831,80 @@ export const cleanShaInput = async ({
|
||||||
|
|
||||||
return stdout.trim()
|
return stdout.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getPreviousGitTag = async ({
|
export const getPreviousGitTag = async ({
|
||||||
cwd,
|
cwd,
|
||||||
tagsPattern,
|
tagsPattern,
|
||||||
|
currentBranch,
|
||||||
tagsIgnorePattern
|
tagsIgnorePattern
|
||||||
}: {
|
}: {
|
||||||
cwd: string
|
cwd: string
|
||||||
tagsPattern: string
|
tagsPattern: string
|
||||||
|
currentBranch: string
|
||||||
tagsIgnorePattern?: string
|
tagsIgnorePattern?: string
|
||||||
}): Promise<{tag: string; sha: string}> => {
|
}): Promise<{tag: string; sha: string}> => {
|
||||||
|
const ignorePatterns: string[] = []
|
||||||
|
let currentShaDate: Date | null = null
|
||||||
|
|
||||||
const {stdout} = await exec.getExecOutput(
|
const {stdout} = await exec.getExecOutput(
|
||||||
'git',
|
'git',
|
||||||
['tag', '--sort=-creatordate'],
|
[
|
||||||
|
'tag',
|
||||||
|
'--sort=-creatordate',
|
||||||
|
'--format=%(refname:short)|%(objectname)|%(creatordate:iso)'
|
||||||
|
],
|
||||||
{
|
{
|
||||||
cwd,
|
cwd,
|
||||||
silent: !core.isDebug()
|
silent: !core.isDebug()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
let tags = stdout.trim().split('\n')
|
|
||||||
|
|
||||||
if (tagsPattern) {
|
|
||||||
tags = tags.filter(tag => mm.isMatch(tag, tagsPattern))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tagsIgnorePattern) {
|
if (tagsIgnorePattern) {
|
||||||
tags = tags.filter(tag => !mm.isMatch(tag, tagsIgnorePattern))
|
ignorePatterns.push(tagsIgnorePattern)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tags.length < 2) {
|
if (currentBranch) {
|
||||||
core.warning('No previous tag found')
|
ignorePatterns.push(currentBranch)
|
||||||
return {tag: '', sha: ''}
|
try {
|
||||||
}
|
const {stdout: currentShaDateOutput} = await exec.getExecOutput(
|
||||||
|
'git',
|
||||||
const previousTag = tags[1]
|
['show', '-s', '--format=%ai', currentBranch],
|
||||||
|
{
|
||||||
const {stdout: stdout2} = await exec.getExecOutput(
|
cwd,
|
||||||
'git',
|
silent: !core.isDebug()
|
||||||
['rev-parse', previousTag],
|
}
|
||||||
{
|
)
|
||||||
cwd,
|
currentShaDate = new Date(currentShaDateOutput.trim())
|
||||||
silent: !core.isDebug()
|
} catch (error) {
|
||||||
|
// Handle the case where the current branch doesn't exist
|
||||||
|
// This might happen in detached head state
|
||||||
|
core.warning(`Failed to get date for current branch ${currentBranch}`)
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
const sha = stdout2.trim()
|
const previousTag: {tag: string; sha: string} = {tag: '', sha: ''}
|
||||||
|
|
||||||
return {tag: previousTag, sha}
|
const tags = stdout.trim().split('\n')
|
||||||
|
for (const tagData of tags) {
|
||||||
|
const [tag, sha, dateString] = tagData.split('|')
|
||||||
|
if (!mm.isMatch(tag, tagsPattern) || mm.isMatch(tag, ignorePatterns)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const date = new Date(dateString)
|
||||||
|
if (currentShaDate && date >= currentShaDate) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Found a suitable tag, no need to continue
|
||||||
|
previousTag.tag = tag
|
||||||
|
previousTag.sha = sha
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!previousTag.tag) {
|
||||||
|
core.warning('No previous tag found')
|
||||||
|
}
|
||||||
|
|
||||||
|
return previousTag
|
||||||
}
|
}
|
||||||
|
|
||||||
export const canDiffCommits = async ({
|
export const canDiffCommits = async ({
|
||||||
|
|
Loading…
Reference in a new issue