2023-05-25 18:22:24 +00:00
import * as core from '@actions/core'
2023-07-18 09:44:59 +00:00
import * as github from '@actions/github'
2023-05-25 18:22:24 +00:00
import path from 'path'
2023-06-23 17:20:13 +00:00
import {
2023-09-16 11:44:37 +00:00
processChangedFiles ,
2023-07-19 07:50:59 +00:00
ChangeTypeEnum ,
2023-06-23 17:20:13 +00:00
getAllDiffFiles ,
getChangedFilesFromGithubAPI ,
getRenamedFiles
} from './changedFiles'
2023-06-14 18:45:32 +00:00
import {
DiffResult ,
2023-08-22 03:11:59 +00:00
getSHAForNonPullRequestEvent ,
getSHAForPullRequestEvent
2023-05-25 18:22:24 +00:00
} from './commitSha'
2023-06-23 17:20:13 +00:00
import { Env , getEnv } from './env'
import { getInputs , Inputs } from './inputs'
2023-05-25 18:22:24 +00:00
import {
getFilePatterns ,
2023-07-19 07:50:59 +00:00
getRecoverFilePatterns ,
2023-05-25 18:22:24 +00:00
getSubmodulePath ,
2023-06-16 06:17:13 +00:00
getYamlFilePatterns ,
2023-06-23 17:20:13 +00:00
hasLocalGitDirectory ,
2023-05-25 18:22:24 +00:00
isRepoShallow ,
2023-07-19 07:50:59 +00:00
recoverDeletedFiles ,
2023-05-25 18:22:24 +00:00
setOutput ,
submoduleExists ,
updateGitGlobalConfig ,
2024-01-13 21:53:17 +00:00
verifyMinimumGitVersion ,
warnUnsupportedRESTAPIInputs
2023-05-25 18:22:24 +00:00
} from './utils'
2023-09-16 11:44:37 +00:00
const getChangedFilesFromLocalGitHistory = async ( {
2023-06-23 17:20:13 +00:00
inputs ,
env ,
2023-07-09 09:19:14 +00:00
workingDirectory ,
filePatterns ,
yamlFilePatterns
2023-06-23 17:20:13 +00:00
} : {
inputs : Inputs
env : Env
workingDirectory : string
2023-07-09 09:19:14 +00:00
filePatterns : string [ ]
yamlFilePatterns : Record < string , string [ ] >
2023-06-23 17:20:13 +00:00
} ) : Promise < void > = > {
2023-05-25 18:22:24 +00:00
await verifyMinimumGitVersion ( )
2024-01-13 21:53:17 +00:00
let quotepathValue = 'on'
2023-05-25 18:22:24 +00:00
2024-01-13 21:53:17 +00:00
if ( ! inputs . quotepath ) {
quotepathValue = 'off'
2023-05-25 18:22:24 +00:00
}
await updateGitGlobalConfig ( {
name : 'core.quotepath' ,
2024-01-13 21:53:17 +00:00
value : quotepathValue
2023-05-25 18:22:24 +00:00
} )
if ( inputs . diffRelative ) {
await updateGitGlobalConfig ( {
name : 'diff.relative' ,
value : 'true'
} )
}
const isShallow = await isRepoShallow ( { cwd : workingDirectory } )
2024-04-17 16:24:26 +00:00
let diffSubmodule = false
2024-03-26 17:47:25 +00:00
let gitFetchExtraArgs = [ '--no-tags' , '--prune' ]
2024-04-17 16:24:26 +00:00
if ( inputs . excludeSubmodules ) {
core . info ( 'Excluding submodules from the diff' )
} else {
diffSubmodule = await submoduleExists ( { cwd : workingDirectory } )
}
if ( diffSubmodule ) {
2024-03-26 17:47:25 +00:00
gitFetchExtraArgs . push ( '--recurse-submodules' )
}
2023-05-25 18:22:24 +00:00
const isTag = env . GITHUB_REF ? . startsWith ( 'refs/tags/' )
2024-03-26 22:49:39 +00:00
const remoteName = 'origin'
2023-06-14 19:59:31 +00:00
const outputRenamedFilesAsDeletedAndAdded =
inputs . outputRenamedFilesAsDeletedAndAdded
2023-05-25 21:53:58 +00:00
let submodulePaths : string [ ] = [ ]
2023-05-25 21:43:31 +00:00
2024-04-17 16:24:26 +00:00
if ( diffSubmodule ) {
2023-05-25 21:53:58 +00:00
submodulePaths = await getSubmodulePath ( { cwd : workingDirectory } )
2023-05-25 21:43:31 +00:00
}
2023-05-25 18:22:24 +00:00
if ( isTag ) {
2023-06-14 19:22:47 +00:00
gitFetchExtraArgs = [ '--prune' , '--no-recurse-submodules' ]
2023-05-25 18:22:24 +00:00
}
let diffResult : DiffResult
2023-07-18 09:44:59 +00:00
if ( ! github . context . payload . pull_request ? . base ? . ref ) {
core . info ( ` Running on a ${ github . context . eventName || 'push' } event... ` )
2024-03-26 17:47:25 +00:00
diffResult = await getSHAForNonPullRequestEvent ( {
2023-05-25 18:22:24 +00:00
inputs ,
env ,
workingDirectory ,
isShallow ,
2024-04-17 16:24:26 +00:00
diffSubmodule ,
2023-06-14 19:22:47 +00:00
gitFetchExtraArgs ,
2024-03-26 17:47:25 +00:00
isTag ,
remoteName
} )
2023-05-25 18:22:24 +00:00
} else {
2023-06-08 12:12:03 +00:00
core . info (
2023-07-18 09:44:59 +00:00
` Running on a ${ github . context . eventName || 'pull_request' } ( ${
github . context . payload . action
2023-06-16 06:17:13 +00:00
} ) event . . . `
2023-06-08 12:12:03 +00:00
)
2024-03-26 17:47:25 +00:00
diffResult = await getSHAForPullRequestEvent ( {
2023-05-25 18:22:24 +00:00
inputs ,
workingDirectory ,
isShallow ,
2024-04-17 16:24:26 +00:00
diffSubmodule ,
2024-03-26 17:47:25 +00:00
gitFetchExtraArgs ,
2024-03-26 22:49:39 +00:00
remoteName
2024-03-26 17:47:25 +00:00
} )
2023-05-25 18:22:24 +00:00
}
2023-05-26 16:48:32 +00:00
if ( diffResult . initialCommit ) {
core . info ( 'This is the first commit for this repository; exiting...' )
core . endGroup ( )
return
}
2023-05-25 18:22:24 +00:00
core . info (
` Retrieving changes between ${ diffResult . previousSha } ( ${ diffResult . targetBranch } ) → ${ diffResult . currentSha } ( ${ diffResult . currentBranch } ) `
)
2023-06-14 18:45:32 +00:00
const allDiffFiles = await getAllDiffFiles ( {
2023-05-25 18:22:24 +00:00
workingDirectory ,
2024-04-17 16:24:26 +00:00
diffSubmodule ,
2023-05-25 18:22:24 +00:00
diffResult ,
2023-06-14 19:59:31 +00:00
submodulePaths ,
2023-08-26 03:00:53 +00:00
outputRenamedFilesAsDeletedAndAdded ,
2024-01-13 21:53:17 +00:00
fetchAdditionalSubmoduleHistory : inputs.fetchAdditionalSubmoduleHistory ,
2023-08-30 20:51:36 +00:00
failOnInitialDiffError : inputs.failOnInitialDiffError ,
failOnSubmoduleDiffError : inputs.failOnSubmoduleDiffError
2023-05-25 18:22:24 +00:00
} )
2023-06-14 18:45:32 +00:00
core . debug ( ` All diff files: ${ JSON . stringify ( allDiffFiles ) } ` )
2023-06-16 06:17:13 +00:00
core . info ( 'All Done!' )
core . endGroup ( )
2023-06-14 18:45:32 +00:00
2023-07-19 07:50:59 +00:00
if ( inputs . recoverDeletedFiles ) {
let recoverPatterns = getRecoverFilePatterns ( { inputs } )
2023-05-25 18:22:24 +00:00
2023-07-19 07:50:59 +00:00
if ( recoverPatterns . length > 0 && filePatterns . length > 0 ) {
core . info ( 'No recover patterns found; defaulting to file patterns' )
recoverPatterns = filePatterns
2023-06-16 06:17:13 +00:00
}
2023-05-25 18:22:24 +00:00
2023-07-19 07:50:59 +00:00
await recoverDeletedFiles ( {
2023-06-17 02:33:42 +00:00
inputs ,
workingDirectory ,
2023-07-19 07:50:59 +00:00
deletedFiles : allDiffFiles [ ChangeTypeEnum . Deleted ] ,
recoverPatterns ,
2023-12-10 07:14:44 +00:00
diffResult ,
2024-04-17 16:24:26 +00:00
diffSubmodule ,
2023-12-10 07:14:44 +00:00
submodulePaths
2023-06-16 06:17:13 +00:00
} )
}
2023-05-25 18:22:24 +00:00
2023-09-16 11:44:37 +00:00
await processChangedFiles ( {
2023-07-19 07:50:59 +00:00
filePatterns ,
allDiffFiles ,
inputs ,
2023-09-22 02:47:12 +00:00
yamlFilePatterns ,
workingDirectory
2023-07-19 07:50:59 +00:00
} )
2023-05-25 18:22:24 +00:00
if ( inputs . includeAllOldNewRenamedFiles ) {
2023-06-16 06:17:13 +00:00
core . startGroup ( 'changed-files-all-old-new-renamed-files' )
2023-05-25 18:22:24 +00:00
const allOldNewRenamedFiles = await getRenamedFiles ( {
inputs ,
workingDirectory ,
2024-04-17 16:24:26 +00:00
diffSubmodule ,
2023-05-25 18:22:24 +00:00
diffResult ,
submodulePaths
} )
core . debug ( ` All old new renamed files: ${ allOldNewRenamedFiles } ` )
await setOutput ( {
key : 'all_old_new_renamed_files' ,
2023-06-17 03:13:40 +00:00
value : allOldNewRenamedFiles.paths ,
2023-09-04 20:03:32 +00:00
writeOutputFiles : inputs.writeOutputFiles ,
outputDir : inputs.outputDir ,
2023-12-22 21:07:32 +00:00
json : inputs.json ,
safeOutput : inputs.safeOutput
2023-06-17 03:13:40 +00:00
} )
await setOutput ( {
key : 'all_old_new_renamed_files_count' ,
value : allOldNewRenamedFiles.count ,
2023-09-04 20:03:32 +00:00
writeOutputFiles : inputs.writeOutputFiles ,
outputDir : inputs.outputDir ,
json : inputs.json
2023-05-25 18:22:24 +00:00
} )
2023-06-16 06:17:13 +00:00
core . info ( 'All Done!' )
core . endGroup ( )
2023-05-25 18:22:24 +00:00
}
}
2023-06-23 17:20:13 +00:00
const getChangedFilesFromRESTAPI = async ( {
inputs ,
2023-07-09 09:19:14 +00:00
filePatterns ,
yamlFilePatterns
2023-06-23 17:20:13 +00:00
} : {
inputs : Inputs
2023-07-09 09:19:14 +00:00
filePatterns : string [ ]
yamlFilePatterns : Record < string , string [ ] >
2023-06-23 17:20:13 +00:00
} ) : Promise < void > = > {
const allDiffFiles = await getChangedFilesFromGithubAPI ( {
2023-07-18 09:44:59 +00:00
inputs
2023-06-23 17:20:13 +00:00
} )
core . debug ( ` All diff files: ${ JSON . stringify ( allDiffFiles ) } ` )
core . info ( 'All Done!' )
2023-09-16 11:44:37 +00:00
await processChangedFiles ( {
2023-07-19 07:50:59 +00:00
filePatterns ,
allDiffFiles ,
inputs ,
yamlFilePatterns
} )
2023-06-23 17:20:13 +00:00
}
export async function run ( ) : Promise < void > {
core . startGroup ( 'changed-files' )
const env = await getEnv ( )
core . debug ( ` Env: ${ JSON . stringify ( env , null , 2 ) } ` )
2023-07-09 09:19:14 +00:00
2023-06-23 17:20:13 +00:00
const inputs = getInputs ( )
core . debug ( ` Inputs: ${ JSON . stringify ( inputs , null , 2 ) } ` )
2023-07-09 09:19:14 +00:00
2023-06-23 17:20:13 +00:00
const workingDirectory = path . resolve (
env . GITHUB_WORKSPACE || process . cwd ( ) ,
2024-01-15 18:54:08 +00:00
inputs . useRestApi ? '.' : inputs . path
2023-06-23 17:20:13 +00:00
)
2023-07-09 09:19:14 +00:00
core . debug ( ` Working directory: ${ workingDirectory } ` )
2023-06-23 17:20:13 +00:00
const hasGitDirectory = await hasLocalGitDirectory ( { workingDirectory } )
2023-07-09 09:19:14 +00:00
core . debug ( ` Has git directory: ${ hasGitDirectory } ` )
const filePatterns = await getFilePatterns ( {
inputs ,
workingDirectory
} )
core . debug ( ` File patterns: ${ filePatterns } ` )
const yamlFilePatterns = await getYamlFilePatterns ( {
inputs ,
workingDirectory
} )
core . debug ( ` Yaml file patterns: ${ JSON . stringify ( yamlFilePatterns ) } ` )
2023-06-23 17:20:13 +00:00
2024-01-13 08:48:42 +00:00
if ( inputs . useRestApi && ! github . context . payload . pull_request ? . number ) {
throw new Error (
"Only pull_request* events are supported when using GitHub's REST API."
)
}
2023-06-23 17:20:13 +00:00
if (
inputs . token &&
2023-07-18 09:44:59 +00:00
github . context . payload . pull_request ? . number &&
2024-01-13 08:48:42 +00:00
( ! hasGitDirectory || inputs . useRestApi )
2023-06-23 17:20:13 +00:00
) {
core . info ( "Using GitHub's REST API to get changed files" )
2024-01-18 03:27:20 +00:00
await warnUnsupportedRESTAPIInputs ( { inputs } )
2023-07-09 09:19:14 +00:00
await getChangedFilesFromRESTAPI ( {
inputs ,
filePatterns ,
yamlFilePatterns
} )
2023-06-23 17:20:13 +00:00
} else {
if ( ! hasGitDirectory ) {
2024-01-13 08:48:42 +00:00
throw new Error (
2024-01-25 18:46:48 +00:00
` Unable to locate the git repository in the given path: ${ workingDirectory } . \ n Please run actions/checkout before this action (Make sure the 'path' input is correct). \ n If you intend to use Github's REST API note that only pull_request* events are supported. Current event is " ${ github . context . eventName } ". `
2023-06-23 17:20:13 +00:00
)
}
core . info ( 'Using local .git directory' )
2023-09-16 11:44:37 +00:00
await getChangedFilesFromLocalGitHistory ( {
2023-07-09 09:19:14 +00:00
inputs ,
env ,
workingDirectory ,
filePatterns ,
yamlFilePatterns
} )
2023-06-23 17:20:13 +00:00
}
}
2024-07-18 19:39:13 +00:00
// eslint-disable-next-line github/no-then
run ( ) . catch ( e = > {
core . setFailed ( e . message || e )
process . exit ( 1 )
} )