diff --git a/packages/artifact/__tests__/upload-artifact.test.ts b/packages/artifact/__tests__/upload-artifact.test.ts index b0dca5c8..3b8201d7 100644 --- a/packages/artifact/__tests__/upload-artifact.test.ts +++ b/packages/artifact/__tests__/upload-artifact.test.ts @@ -8,6 +8,7 @@ import * as blobUpload from '../src/internal/upload/blob-upload' import {uploadArtifact} from '../src/internal/upload/upload-artifact' import {noopLogs} from './common' import {FilesNotFoundError} from '../src/internal/shared/errors' +import {Stats} from 'fs' describe('upload-artifact', () => { beforeEach(() => { @@ -28,15 +29,18 @@ describe('upload-artifact', () => { .mockReturnValue([ { sourcePath: '/home/user/files/plz-upload/file1.txt', - destinationPath: 'file1.txt' + destinationPath: 'file1.txt', + stats: new Stats() }, { sourcePath: '/home/user/files/plz-upload/file2.txt', - destinationPath: 'file2.txt' + destinationPath: 'file2.txt', + stats: new Stats() }, { sourcePath: '/home/user/files/plz-upload/dir/file3.txt', - destinationPath: 'dir/file3.txt' + destinationPath: 'dir/file3.txt', + stats: new Stats() } ]) @@ -136,15 +140,18 @@ describe('upload-artifact', () => { .mockReturnValue([ { sourcePath: '/home/user/files/plz-upload/file1.txt', - destinationPath: 'file1.txt' + destinationPath: 'file1.txt', + stats: new Stats() }, { sourcePath: '/home/user/files/plz-upload/file2.txt', - destinationPath: 'file2.txt' + destinationPath: 'file2.txt', + stats: new Stats() }, { sourcePath: '/home/user/files/plz-upload/dir/file3.txt', - destinationPath: 'dir/file3.txt' + destinationPath: 'dir/file3.txt', + stats: new Stats() } ]) @@ -175,15 +182,18 @@ describe('upload-artifact', () => { .mockReturnValue([ { sourcePath: '/home/user/files/plz-upload/file1.txt', - destinationPath: 'file1.txt' + destinationPath: 'file1.txt', + stats: Stats.prototype }, { sourcePath: '/home/user/files/plz-upload/file2.txt', - destinationPath: 'file2.txt' + destinationPath: 'file2.txt', + stats: Stats.prototype }, { sourcePath: '/home/user/files/plz-upload/dir/file3.txt', - destinationPath: 'dir/file3.txt' + destinationPath: 'dir/file3.txt', + stats: Stats.prototype } ]) @@ -230,15 +240,18 @@ describe('upload-artifact', () => { .mockReturnValue([ { sourcePath: '/home/user/files/plz-upload/file1.txt', - destinationPath: 'file1.txt' + destinationPath: 'file1.txt', + stats: new Stats() }, { sourcePath: '/home/user/files/plz-upload/file2.txt', - destinationPath: 'file2.txt' + destinationPath: 'file2.txt', + stats: new Stats() }, { sourcePath: '/home/user/files/plz-upload/dir/file3.txt', - destinationPath: 'dir/file3.txt' + destinationPath: 'dir/file3.txt', + stats: new Stats() } ]) @@ -293,15 +306,18 @@ describe('upload-artifact', () => { .mockReturnValue([ { sourcePath: '/home/user/files/plz-upload/file1.txt', - destinationPath: 'file1.txt' + destinationPath: 'file1.txt', + stats: new Stats() }, { sourcePath: '/home/user/files/plz-upload/file2.txt', - destinationPath: 'file2.txt' + destinationPath: 'file2.txt', + stats: new Stats() }, { sourcePath: '/home/user/files/plz-upload/dir/file3.txt', - destinationPath: 'dir/file3.txt' + destinationPath: 'dir/file3.txt', + stats: new Stats() } ]) diff --git a/packages/artifact/__tests__/upload-zip-specification.test.ts b/packages/artifact/__tests__/upload-zip-specification.test.ts index 0b59bff7..a29b5280 100644 --- a/packages/artifact/__tests__/upload-zip-specification.test.ts +++ b/packages/artifact/__tests__/upload-zip-specification.test.ts @@ -287,14 +287,14 @@ describe('Search', () => { expect(specifications.length).toEqual(2) const absolutePaths = specifications.map(item => item.sourcePath) expect(absolutePaths).toContain(goodItem1Path) - expect(absolutePaths).toContain(null) + expect(absolutePaths).toContain(folderEPath) for (const specification of specifications) { if (specification.sourcePath === goodItem1Path) { expect(specification.destinationPath).toEqual( path.join('/folder-a', 'folder-b', 'folder-c', 'good-item1.txt') ) - } else if (specification.sourcePath === null) { + } else if (specification.sourcePath === folderEPath) { expect(specification.destinationPath).toEqual( path.join('/folder-a', 'folder-b', 'folder-e') ) diff --git a/packages/artifact/src/internal/upload/upload-zip-specification.ts b/packages/artifact/src/internal/upload/upload-zip-specification.ts index c6e807e6..e10f102d 100644 --- a/packages/artifact/src/internal/upload/upload-zip-specification.ts +++ b/packages/artifact/src/internal/upload/upload-zip-specification.ts @@ -5,14 +5,19 @@ import {validateFilePath} from './path-and-artifact-name-validation' export interface UploadZipSpecification { /** - * An absolute source path that points to a file that will be added to a zip. Null if creating a new directory + * An absolute source path that points to a file that will be added to a zip. */ - sourcePath: string | null + sourcePath: string /** * The destination path in a zip for a file */ destinationPath: string + + /** + * Information about the file on disk + */ + stats: fs.Stats } /** @@ -75,37 +80,26 @@ export function getUploadZipSpecification( - file3.txt */ for (let file of filesToZip) { - if (!fs.existsSync(file)) { - throw new Error(`File ${file} does not exist`) + const stats = fs.statSync(file, {throwIfNoEntry: false}) + if (!stats) throw new Error(`File ${file} does not exist`) + // Normalize and resolve, this allows for either absolute or relative paths to be used + file = normalize(file) + file = resolve(file) + if (!file.startsWith(rootDirectory)) { + throw new Error( + `The rootDirectory: ${rootDirectory} is not a parent directory of the file: ${file}` + ) } - if (!fs.statSync(file).isDirectory()) { - // Normalize and resolve, this allows for either absolute or relative paths to be used - file = normalize(file) - file = resolve(file) - if (!file.startsWith(rootDirectory)) { - throw new Error( - `The rootDirectory: ${rootDirectory} is not a parent directory of the file: ${file}` - ) - } - // Check for forbidden characters in file paths that may cause ambiguous behavior if downloaded on different file systems - const uploadPath = file.replace(rootDirectory, '') - validateFilePath(uploadPath) + // Check for forbidden characters in file paths that may cause ambiguous behavior if downloaded on different file systems + const destinationPath = file.replace(rootDirectory, '') + validateFilePath(destinationPath) - specification.push({ - sourcePath: file, - destinationPath: uploadPath - }) - } else { - // Empty directory - const directoryPath = file.replace(rootDirectory, '') - validateFilePath(directoryPath) - - specification.push({ - sourcePath: null, - destinationPath: directoryPath - }) - } + specification.push({ + sourcePath: file, + destinationPath, + stats + }) } return specification } diff --git a/packages/artifact/src/internal/upload/zip.ts b/packages/artifact/src/internal/upload/zip.ts index 5a923119..28bc283f 100644 --- a/packages/artifact/src/internal/upload/zip.ts +++ b/packages/artifact/src/internal/upload/zip.ts @@ -42,14 +42,18 @@ export async function createZipUploadStream( zip.on('end', zipEndCallback) for (const file of uploadSpecification) { - if (file.sourcePath !== null) { + if (!file.stats.isDirectory()) { // Add a normal file to the zip zip.append(createReadStream(file.sourcePath), { - name: file.destinationPath + name: file.destinationPath, + stats: file.stats }) } else { // Add a directory to the zip - zip.append('', {name: file.destinationPath}) + zip.append('', { + name: file.destinationPath, + stats: file.stats + }) } }