mirror of https://github.com/actions/toolkit
feat: Add option to modify whether symlink if followed in ZIP archive
Signed-off-by: eXhumer <exhumer@exhumer.cc>pull/1803/head
parent
7298ff3219
commit
49751122cf
|
@ -38,6 +38,7 @@ const extraFileInFolderCPath = path.join(
|
|||
'extra-file-in-folder-c.txt'
|
||||
)
|
||||
const amazingFileInFolderHPath = path.join(root, 'folder-h', 'amazing-item.txt')
|
||||
const symlinkToFolderDPath = path.join(root, 'symlink-to-folder-d')
|
||||
|
||||
const artifactFilesToUpload = [
|
||||
goodItem1Path,
|
||||
|
@ -46,7 +47,8 @@ const artifactFilesToUpload = [
|
|||
goodItem4Path,
|
||||
goodItem5Path,
|
||||
extraFileInFolderCPath,
|
||||
amazingFileInFolderHPath
|
||||
amazingFileInFolderHPath,
|
||||
symlinkToFolderDPath
|
||||
]
|
||||
|
||||
describe('Search', () => {
|
||||
|
@ -89,6 +91,8 @@ describe('Search', () => {
|
|||
await fs.writeFile(extraFileInFolderCPath, 'extra file')
|
||||
|
||||
await fs.writeFile(amazingFileInFolderHPath, 'amazing file')
|
||||
|
||||
await fs.symlink(path.join(root, 'folder-d'), symlinkToFolderDPath)
|
||||
/*
|
||||
Directory structure of files that get created:
|
||||
root/
|
||||
|
@ -112,6 +116,7 @@ describe('Search', () => {
|
|||
folder-i/
|
||||
bad-item4.txt
|
||||
bad-item5.txt
|
||||
symlink-to-folder-d -> folder-d/
|
||||
good-item5.txt
|
||||
*/
|
||||
})
|
||||
|
@ -168,7 +173,7 @@ describe('Search', () => {
|
|||
artifactFilesToUpload,
|
||||
root
|
||||
)
|
||||
expect(specifications.length).toEqual(7)
|
||||
expect(specifications.length).toEqual(8)
|
||||
|
||||
const absolutePaths = specifications.map(item => item.sourcePath)
|
||||
expect(absolutePaths).toContain(goodItem1Path)
|
||||
|
@ -178,6 +183,7 @@ describe('Search', () => {
|
|||
expect(absolutePaths).toContain(goodItem5Path)
|
||||
expect(absolutePaths).toContain(extraFileInFolderCPath)
|
||||
expect(absolutePaths).toContain(amazingFileInFolderHPath)
|
||||
expect(absolutePaths).toContain(symlinkToFolderDPath)
|
||||
|
||||
for (const specification of specifications) {
|
||||
if (specification.sourcePath === goodItem1Path) {
|
||||
|
@ -213,6 +219,13 @@ describe('Search', () => {
|
|||
expect(specification.destinationPath).toEqual(
|
||||
path.join('/folder-h', 'amazing-item.txt')
|
||||
)
|
||||
} else if (specification.sourcePath === symlinkToFolderDPath) {
|
||||
expect(specification.destinationPath).toEqual(
|
||||
path.join('/symlink-to-folder-d')
|
||||
)
|
||||
expect(specification.symlinkTargetPath).toEqual(
|
||||
path.join(root, '/folder-d')
|
||||
)
|
||||
} else {
|
||||
throw new Error(
|
||||
'Invalid specification found. This should never be reached'
|
||||
|
@ -227,7 +240,7 @@ describe('Search', () => {
|
|||
artifactFilesToUpload,
|
||||
rootWithSlash
|
||||
)
|
||||
expect(specifications.length).toEqual(7)
|
||||
expect(specifications.length).toEqual(8)
|
||||
|
||||
const absolutePaths = specifications.map(item => item.sourcePath)
|
||||
expect(absolutePaths).toContain(goodItem1Path)
|
||||
|
@ -237,6 +250,7 @@ describe('Search', () => {
|
|||
expect(absolutePaths).toContain(goodItem5Path)
|
||||
expect(absolutePaths).toContain(extraFileInFolderCPath)
|
||||
expect(absolutePaths).toContain(amazingFileInFolderHPath)
|
||||
expect(absolutePaths).toContain(symlinkToFolderDPath)
|
||||
|
||||
for (const specification of specifications) {
|
||||
if (specification.sourcePath === goodItem1Path) {
|
||||
|
@ -272,6 +286,13 @@ describe('Search', () => {
|
|||
expect(specification.destinationPath).toEqual(
|
||||
path.join('/folder-h', 'amazing-item.txt')
|
||||
)
|
||||
} else if (specification.sourcePath === symlinkToFolderDPath) {
|
||||
expect(specification.destinationPath).toEqual(
|
||||
path.join('/symlink-to-folder-d')
|
||||
)
|
||||
expect(specification.symlinkTargetPath).toEqual(
|
||||
path.join(root, '/folder-d')
|
||||
)
|
||||
} else {
|
||||
throw new Error(
|
||||
'Invalid specification found. This should never be reached'
|
||||
|
|
|
@ -45,6 +45,13 @@ export interface UploadArtifactOptions {
|
|||
* For large files that are not easily compressed, a value of 0 is recommended for significantly faster uploads.
|
||||
*/
|
||||
compressionLevel?: number
|
||||
|
||||
/**
|
||||
* Whether or not symlinks in artifact ZIP should be followed.
|
||||
*
|
||||
* By default, artifact ZIP will follow symlinks.
|
||||
*/
|
||||
followSymlinks?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -70,7 +70,8 @@ export async function uploadArtifact(
|
|||
|
||||
const zipUploadStream = await createZipUploadStream(
|
||||
zipSpecification,
|
||||
options?.compressionLevel
|
||||
options?.compressionLevel,
|
||||
options?.followSymlinks
|
||||
)
|
||||
|
||||
// Upload zip to blob storage
|
||||
|
|
|
@ -13,6 +13,11 @@ export interface UploadZipSpecification {
|
|||
* The destination path in a zip for a file
|
||||
*/
|
||||
destinationPath: string
|
||||
|
||||
/**
|
||||
* The relative path to a symlink target (file or directory) in a zip
|
||||
*/
|
||||
symlinkTargetPath?: string
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -78,7 +83,8 @@ export function getUploadZipSpecification(
|
|||
if (!fs.existsSync(file)) {
|
||||
throw new Error(`File ${file} does not exist`)
|
||||
}
|
||||
if (!fs.statSync(file).isDirectory()) {
|
||||
const fileLstat = fs.lstatSync(file)
|
||||
if (!fileLstat.isDirectory()) {
|
||||
// Normalize and resolve, this allows for either absolute or relative paths to be used
|
||||
file = normalize(file)
|
||||
file = resolve(file)
|
||||
|
@ -94,7 +100,10 @@ export function getUploadZipSpecification(
|
|||
|
||||
specification.push({
|
||||
sourcePath: file,
|
||||
destinationPath: uploadPath
|
||||
destinationPath: uploadPath,
|
||||
symlinkTargetPath: fileLstat.isSymbolicLink()
|
||||
? fs.readlinkSync(file)
|
||||
: undefined
|
||||
})
|
||||
} else {
|
||||
// Empty directory
|
||||
|
|
|
@ -23,7 +23,8 @@ export class ZipUploadStream extends stream.Transform {
|
|||
|
||||
export async function createZipUploadStream(
|
||||
uploadSpecification: UploadZipSpecification[],
|
||||
compressionLevel: number = DEFAULT_COMPRESSION_LEVEL
|
||||
compressionLevel: number = DEFAULT_COMPRESSION_LEVEL,
|
||||
followSymlinks = true
|
||||
): Promise<ZipUploadStream> {
|
||||
core.debug(
|
||||
`Creating Artifact archive with compressionLevel: ${compressionLevel}`
|
||||
|
@ -42,10 +43,15 @@ export async function createZipUploadStream(
|
|||
|
||||
for (const file of uploadSpecification) {
|
||||
if (file.sourcePath !== null) {
|
||||
// Add a normal file to the zip
|
||||
zip.file(file.sourcePath, {
|
||||
name: file.destinationPath
|
||||
})
|
||||
if (file.symlinkTargetPath !== undefined && !followSymlinks) {
|
||||
// Add a symlink to the zip
|
||||
zip.symlink(file.destinationPath, file.symlinkTargetPath)
|
||||
} else {
|
||||
// Add a normal file to the zip
|
||||
zip.file(file.sourcePath, {
|
||||
name: file.destinationPath
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Add a directory to the zip
|
||||
zip.append('', {name: file.destinationPath})
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
"packages": {
|
||||
"": {
|
||||
"name": "@actions/glob",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.9.1",
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"packages": {
|
||||
"": {
|
||||
"name": "@actions/http-client",
|
||||
"version": "2.2.1",
|
||||
"version": "2.2.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tunnel": "^0.0.6",
|
||||
|
|
Loading…
Reference in New Issue