add support for multiple paths in path input variable

This allows users to provide multiple filepaths to include in their action, whether they're files or folders.
This commit is contained in:
Conor Sloan
2023-11-22 16:02:01 +00:00
parent 56b7ee3ceb
commit c2bb735a45
8 changed files with 3644 additions and 1571 deletions
+25 -1
View File
@@ -1,4 +1,5 @@
import * as fs from 'fs'
import fsExtra from 'fs-extra'
import * as path from 'path'
import * as tar from 'tar'
import * as archiver from 'archiver'
@@ -17,7 +18,9 @@ export function createTempDir(): string {
}
export function removeDir(dir: string): void {
fs.rmSync(dir, { recursive: true })
if (fs.existsSync(dir)) {
fs.rmSync(dir, { recursive: true })
}
}
export interface FileMetadata {
@@ -92,6 +95,27 @@ export function readFileContents(filePath: string): Buffer {
return fs.readFileSync(filePath)
}
export function bundleFilesintoDirectory(
files: string[],
targetDir: string = createTempDir()
): string {
for (const file of files) {
if (!fs.existsSync(file)) {
throw new Error(`File ${file} does not exist`)
}
if (isDirectory(file)) {
const targetFolder = path.join(targetDir, path.basename(file))
fsExtra.copySync(file, targetFolder)
} else {
const targetFile = path.join(targetDir, path.basename(file))
fs.copyFileSync(file, targetFile)
}
}
return targetDir
}
// Converts a file path to a filemetadata object by querying the fs for relevant metadata.
async function fileMetadata(filePath: string): Promise<FileMetadata> {
const stats = fs.statSync(filePath)
+21 -12
View File
@@ -10,7 +10,7 @@ import semver from 'semver'
* @returns {Promise<void>} Resolves when the action is complete.
*/
export async function run(): Promise<void> {
let tmpDir = ''
const tmpDirs: string[] = []
try {
// Parse and validate Actions execution context, including the repository name, release name and event type
@@ -39,20 +39,27 @@ export async function run(): Promise<void> {
// Gather & validate user inputs
const token: string = core.getInput('token')
const path: string = core.getInput('path')
const registryURL: URL = new URL(core.getInput('registry')) // TODO: Should this be dynamic? Maybe an API endpoint to grab the registry for GHES/proxima purposes.
if (!fsHelper.isDirectory(path)) {
core.setFailed(
`The path ${path} is not a directory. Please provide a path to a valid directory.`
)
return
// Paths to be included in the OCI image
const paths: string[] = core.getInput('path').split(' ')
let path = ''
if (paths.length === 1 && fsHelper.isDirectory(paths[0])) {
// If the path is a single directory, we can skip the bundling step
path = paths[0]
} else {
// Otherwise, we need to bundle the files & folders into a temporary directory
const bundleDir = fsHelper.createTempDir()
tmpDirs.push(bundleDir)
path = fsHelper.bundleFilesintoDirectory(paths, bundleDir)
}
// Create a temporary directory to store the archives
tmpDir = fsHelper.createTempDir()
const archiveDir = fsHelper.createTempDir()
tmpDirs.push(archiveDir)
const archives = await fsHelper.createArchives(path)
const archives = await fsHelper.createArchives(path, archiveDir)
const manifest = ociContainer.createActionPackageManifest(
archives.tarFile,
@@ -84,9 +91,11 @@ export async function run(): Promise<void> {
// Fail the workflow run if an error occurs
if (error instanceof Error) core.setFailed(error.message)
} finally {
// Clean up the temporary directory if it exists
if (tmpDir !== '') {
fsHelper.removeDir(tmpDir)
// Clean up any temporary directories that exist
for (const tmpDir of tmpDirs) {
if (tmpDir !== '') {
fsHelper.removeDir(tmpDir)
}
}
}
}