2023-05-25 18:22:24 +00:00
import * as core from '@actions/core'
import { Env } from './env'
import { Inputs } from './inputs'
import {
canDiffCommits ,
getHeadSha ,
2023-05-25 23:39:26 +00:00
getParentSha ,
2023-05-25 18:22:24 +00:00
getPreviousGitTag ,
2023-06-01 16:03:09 +00:00
getRemoteBranchHeadSha ,
2023-05-25 18:22:24 +00:00
gitFetch ,
gitFetchSubmodules ,
gitLog ,
verifyCommitSha
} from './utils'
const getCurrentSHA = async ( {
inputs ,
workingDirectory
} : {
inputs : Inputs
workingDirectory : string
} ) : Promise < string > = > {
let currentSha = inputs . sha
core . debug ( 'Getting current SHA...' )
if ( inputs . until ) {
core . debug ( ` Getting base SHA for ' ${ inputs . until } '... ` )
try {
currentSha = await gitLog ( {
cwd : workingDirectory ,
args : [
2023-05-25 23:16:16 +00:00
'--format=%H' ,
2023-05-25 18:22:24 +00:00
'-n' ,
'1' ,
'--date' ,
'local' ,
'--until' ,
inputs . until
]
} )
} catch ( error ) {
core . error (
` Invalid until date: ${ inputs . until } . ${ ( error as Error ) . message } `
)
throw error
}
} else {
if ( ! currentSha ) {
currentSha = await getHeadSha ( { cwd : workingDirectory } )
}
}
await verifyCommitSha ( { sha : currentSha , cwd : workingDirectory } )
core . debug ( ` Current SHA: ${ currentSha } ` )
return currentSha
}
export interface DiffResult {
previousSha : string
currentSha : string
currentBranch : string
targetBranch : string
diff : string
2023-05-26 16:48:32 +00:00
initialCommit? : boolean
2023-05-25 18:22:24 +00:00
}
export const getSHAForPushEvent = async (
inputs : Inputs ,
env : Env ,
workingDirectory : string ,
isShallow : boolean ,
hasSubmodule : boolean ,
gitExtraArgs : string [ ] ,
isTag : boolean
) : Promise < DiffResult > = > {
2023-05-25 23:39:26 +00:00
let targetBranch = env . GITHUB_REF_NAME
2023-05-25 18:22:24 +00:00
const currentBranch = targetBranch
let initialCommit = false
if ( isShallow ) {
core . info ( 'Repository is shallow, fetching more history...' )
if ( isTag ) {
2023-05-29 01:56:55 +00:00
const sourceBranch =
env . GITHUB_EVENT_BASE_REF . replace ( 'refs/heads/' , '' ) ||
env . GITHUB_EVENT_RELEASE_TARGET_COMMITISH
2023-05-25 18:22:24 +00:00
await gitFetch ( {
cwd : workingDirectory ,
args : [
. . . gitExtraArgs ,
'-u' ,
'--progress' ,
` --deepen= ${ inputs . fetchDepth } ` ,
'origin' ,
2023-05-29 01:20:27 +00:00
` +refs/heads/ ${ sourceBranch } :refs/remotes/origin/ ${ sourceBranch } `
2023-05-25 18:22:24 +00:00
]
} )
} else {
await gitFetch ( {
cwd : workingDirectory ,
args : [
. . . gitExtraArgs ,
'-u' ,
'--progress' ,
` --deepen= ${ inputs . fetchDepth } ` ,
'origin' ,
` +refs/heads/ ${ targetBranch } :refs/remotes/origin/ ${ targetBranch } `
]
} )
}
if ( hasSubmodule ) {
await gitFetchSubmodules ( {
cwd : workingDirectory ,
args : [
. . . gitExtraArgs ,
'-u' ,
'--progress' ,
` --deepen= ${ inputs . fetchDepth } `
]
} )
}
}
const currentSha = await getCurrentSHA ( { inputs , workingDirectory } )
let previousSha = inputs . baseSha
const diff = '..'
if ( previousSha && currentSha && currentBranch && targetBranch ) {
if ( previousSha === currentSha ) {
core . error (
` Similar commit hashes detected: previous sha: ${ previousSha } is equivalent to the current sha: ${ currentSha } . `
)
core . error (
` Please verify that both commits are valid, and increase the fetch_depth to a number higher than ${ inputs . fetchDepth } . `
)
throw new Error ( 'Similar commit hashes detected.' )
}
await verifyCommitSha ( { sha : previousSha , cwd : workingDirectory } )
2023-05-26 03:14:24 +00:00
core . debug ( ` Previous SHA: ${ previousSha } ` )
2023-05-25 18:22:24 +00:00
return {
previousSha ,
currentSha ,
currentBranch ,
targetBranch ,
diff
}
}
if ( ! previousSha ) {
core . debug ( 'Getting previous SHA...' )
if ( inputs . since ) {
core . debug ( ` Getting base SHA for ' ${ inputs . since } '... ` )
try {
2023-05-25 23:16:16 +00:00
const allCommitsFrom = await gitLog ( {
2023-05-25 18:22:24 +00:00
cwd : workingDirectory ,
2023-05-25 23:16:16 +00:00
args : [ '--format=%H' , '--date' , 'local' , '--since' , inputs . since ]
2023-05-25 18:22:24 +00:00
} )
2023-05-25 23:16:16 +00:00
if ( allCommitsFrom ) {
const allCommitsFromArray = allCommitsFrom . split ( '\n' )
previousSha = allCommitsFromArray [ allCommitsFromArray . length - 1 ]
}
2023-05-25 18:22:24 +00:00
} catch ( error ) {
core . error (
` Invalid since date: ${ inputs . since } . ${ ( error as Error ) . message } `
)
throw error
}
} else if ( isTag ) {
core . debug ( 'Getting previous SHA for tag...' )
const { sha , tag } = await getPreviousGitTag ( { cwd : workingDirectory } )
previousSha = sha
targetBranch = tag
} else {
2023-05-25 23:39:26 +00:00
core . debug ( 'Getting previous SHA for last remote commit...' )
if ( env . GITHUB_EVENT_FORCED === 'false' || ! env . GITHUB_EVENT_FORCED ) {
previousSha = env . GITHUB_EVENT_BEFORE
2023-05-25 18:22:24 +00:00
}
if (
! previousSha ||
previousSha === '0000000000000000000000000000000000000000'
) {
2023-05-25 23:39:26 +00:00
previousSha = await getParentSha ( {
cwd : workingDirectory
} )
2023-05-26 03:14:24 +00:00
} else if (
( await verifyCommitSha ( {
sha : previousSha ,
cwd : workingDirectory ,
showAsErrorMessage : false
} ) ) !== 0
) {
core . warning (
` Previous commit ${ previousSha } is not valid. Using parent commit. `
)
previousSha = await getParentSha ( {
cwd : workingDirectory
} )
2023-05-25 18:22:24 +00:00
}
2023-05-26 16:48:32 +00:00
if ( ! previousSha || previousSha === currentSha ) {
previousSha = await getParentSha ( {
cwd : workingDirectory
} )
if ( ! previousSha ) {
2023-05-25 18:22:24 +00:00
core . warning ( 'Initial commit detected no previous commit found.' )
initialCommit = true
previousSha = currentSha
}
}
}
}
await verifyCommitSha ( { sha : previousSha , cwd : workingDirectory } )
core . debug ( ` Previous SHA: ${ previousSha } ` )
core . debug ( ` Target branch: ${ targetBranch } ` )
core . debug ( ` Current branch: ${ currentBranch } ` )
if ( ! initialCommit && previousSha === currentSha ) {
core . error (
` Similar commit hashes detected: previous sha: ${ previousSha } is equivalent to the current sha: ${ currentSha } . `
)
core . error (
` Please verify that both commits are valid, and increase the fetch_depth to a number higher than ${ inputs . fetchDepth } . `
)
throw new Error ( 'Similar commit hashes detected.' )
}
return {
previousSha ,
currentSha ,
currentBranch ,
targetBranch ,
2023-05-26 16:48:32 +00:00
diff ,
initialCommit
2023-05-25 18:22:24 +00:00
}
}
export const getSHAForPullRequestEvent = async (
inputs : Inputs ,
env : Env ,
workingDirectory : string ,
isShallow : boolean ,
hasSubmodule : boolean ,
gitExtraArgs : string [ ]
) : Promise < DiffResult > = > {
let targetBranch = env . GITHUB_EVENT_PULL_REQUEST_BASE_REF
const currentBranch = env . GITHUB_EVENT_PULL_REQUEST_HEAD_REF
if ( inputs . sinceLastRemoteCommit ) {
targetBranch = currentBranch
}
if ( isShallow ) {
core . info ( 'Repository is shallow, fetching more history...' )
2023-06-01 16:03:09 +00:00
let prFetchExitCode = await gitFetch ( {
2023-05-25 18:22:24 +00:00
cwd : workingDirectory ,
args : [
. . . gitExtraArgs ,
'-u' ,
'--progress' ,
'origin' ,
` pull/ ${ env . GITHUB_EVENT_PULL_REQUEST_NUMBER } /head: ${ currentBranch } `
]
} )
if ( prFetchExitCode !== 0 ) {
2023-06-01 16:03:09 +00:00
prFetchExitCode = await gitFetch ( {
2023-05-25 18:22:24 +00:00
cwd : workingDirectory ,
args : [
. . . gitExtraArgs ,
'-u' ,
'--progress' ,
` --deepen= ${ inputs . fetchDepth } ` ,
'origin' ,
` +refs/heads/ ${ currentBranch } *:refs/remotes/origin/ ${ currentBranch } * `
]
} )
}
2023-06-01 16:03:09 +00:00
if ( prFetchExitCode !== 0 ) {
throw new Error (
'Failed to fetch pull request branch. Please ensure "persist-credentials" is set to "true" when checking out the repository. See: https://github.com/actions/checkout#usage'
)
}
2023-05-25 18:22:24 +00:00
if ( ! inputs . sinceLastRemoteCommit ) {
core . debug ( 'Fetching target branch...' )
await gitFetch ( {
cwd : workingDirectory ,
args : [
. . . gitExtraArgs ,
'-u' ,
'--progress' ,
` --deepen= ${ inputs . fetchDepth } ` ,
'origin' ,
` +refs/heads/ ${ targetBranch } :refs/remotes/origin/ ${ targetBranch } `
]
} )
if ( hasSubmodule ) {
await gitFetchSubmodules ( {
cwd : workingDirectory ,
args : [
. . . gitExtraArgs ,
'-u' ,
'--progress' ,
` --deepen= ${ inputs . fetchDepth } `
]
} )
}
}
2023-05-30 21:27:56 +00:00
core . info ( 'Completed fetching more history.' )
2023-05-25 18:22:24 +00:00
}
const currentSha = await getCurrentSHA ( { inputs , workingDirectory } )
let previousSha = inputs . baseSha
let diff = '...'
if ( previousSha && currentSha && currentBranch && targetBranch ) {
if ( previousSha === currentSha ) {
core . error (
` Similar commit hashes detected: previous sha: ${ previousSha } is equivalent to the current sha: ${ currentSha } . `
)
core . error (
` Please verify that both commits are valid, and increase the fetch_depth to a number higher than ${ inputs . fetchDepth } . `
)
throw new Error ( 'Similar commit hashes detected.' )
}
await verifyCommitSha ( { sha : currentSha , cwd : workingDirectory } )
2023-05-26 03:14:24 +00:00
core . debug ( ` Previous SHA: ${ previousSha } ` )
2023-05-25 18:22:24 +00:00
return {
previousSha ,
currentSha ,
currentBranch ,
targetBranch ,
diff
}
}
if (
! env . GITHUB_EVENT_PULL_REQUEST_BASE_REF ||
env . GITHUB_EVENT_HEAD_REPO_FORK === 'true'
) {
diff = '..'
}
if ( ! previousSha ) {
if ( inputs . sinceLastRemoteCommit ) {
previousSha = env . GITHUB_EVENT_BEFORE
if ( ! previousSha ) {
2023-06-01 17:18:54 +00:00
previousSha = await getParentSha ( { cwd : workingDirectory } )
2023-05-25 18:22:24 +00:00
}
2023-06-01 17:18:54 +00:00
if ( ! previousSha ) {
2023-05-25 18:22:24 +00:00
previousSha = env . GITHUB_EVENT_PULL_REQUEST_BASE_SHA
}
} else {
2023-06-01 16:03:09 +00:00
previousSha = await getRemoteBranchHeadSha ( {
2023-05-30 21:27:56 +00:00
cwd : workingDirectory ,
2023-06-01 16:03:09 +00:00
branch : targetBranch
2023-05-30 21:27:56 +00:00
} )
2023-05-25 18:22:24 +00:00
if ( ! previousSha ) {
2023-05-30 21:27:56 +00:00
previousSha = env . GITHUB_EVENT_PULL_REQUEST_BASE_SHA
2023-05-25 18:22:24 +00:00
}
if ( isShallow ) {
if (
await canDiffCommits ( {
cwd : workingDirectory ,
sha1 : previousSha ,
sha2 : currentSha ,
diff
} )
) {
core . debug (
'Merge base is not in the local history, fetching remote target branch...'
)
for ( let i = 1 ; i <= 10 ; i ++ ) {
await gitFetch ( {
cwd : workingDirectory ,
args : [
. . . gitExtraArgs ,
'-u' ,
'--progress' ,
` --deepen= ${ inputs . fetchDepth } ` ,
'origin' ,
` +refs/heads/ ${ targetBranch } :refs/remotes/origin/ ${ targetBranch } `
]
} )
if (
await canDiffCommits ( {
cwd : workingDirectory ,
sha1 : previousSha ,
sha2 : currentSha ,
diff
} )
) {
break
}
core . debug (
'Merge base is not in the local history, fetching remote target branch again...'
)
core . debug ( ` Attempt ${ i } /10 ` )
}
}
}
}
if ( ! previousSha || previousSha === currentSha ) {
previousSha = env . GITHUB_EVENT_PULL_REQUEST_BASE_SHA
}
}
if (
! ( await canDiffCommits ( {
cwd : workingDirectory ,
sha1 : previousSha ,
sha2 : currentSha ,
diff
} ) )
) {
diff = '..'
}
await verifyCommitSha ( { sha : previousSha , cwd : workingDirectory } )
core . debug ( ` Previous SHA: ${ previousSha } ` )
if (
! ( await canDiffCommits ( {
cwd : workingDirectory ,
sha1 : previousSha ,
sha2 : currentSha ,
diff
} ) )
) {
throw new Error (
` Unable to determine a difference between ${ previousSha } ${ diff } ${ currentSha } `
)
}
if ( previousSha === currentSha ) {
core . error (
` Similar commit hashes detected: previous sha: ${ previousSha } is equivalent to the current sha: ${ currentSha } . `
)
core . error (
` Please verify that both commits are valid, and increase the fetch_depth to a number higher than ${ inputs . fetchDepth } . `
)
throw new Error ( 'Similar commit hashes detected.' )
}
return {
previousSha ,
currentSha ,
currentBranch ,
targetBranch ,
diff
}
}