Files
toolkit/packages/artifact/src/internal/upload/zip.ts
T

104 lines
3.1 KiB
TypeScript
Raw Normal View History

import * as stream from 'stream'
2024-03-28 17:25:01 +00:00
import * as async from 'async'
import * as ZipStream from 'zip-stream'
import * as core from '@actions/core'
import {createReadStream} from 'fs'
import {UploadZipSpecification} from './upload-zip-specification'
import {getUploadChunkSize} from '../shared/config'
export const DEFAULT_COMPRESSION_LEVEL = 6
// Custom stream transformer so we can set the highWaterMark property
// See https://github.com/nodejs/node/issues/8855
export class ZipUploadStream extends stream.Transform {
constructor(bufferSize: number) {
super({
highWaterMark: bufferSize
})
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
_transform(chunk: any, enc: any, cb: any): void {
cb(null, chunk)
}
}
export async function createZipUploadStream(
uploadSpecification: UploadZipSpecification[],
compressionLevel: number = DEFAULT_COMPRESSION_LEVEL
): Promise<ZipUploadStream> {
2024-03-28 16:11:50 +00:00
core.debug(
`Creating Artifact archive with compressionLevel: ${compressionLevel}`
)
2024-03-28 14:32:03 +00:00
const zlibOptions = {
zlib: {level: compressionLevel, bufferSize: getUploadChunkSize()}
}
2024-03-28 15:44:27 +00:00
const zip = new ZipStream.default(zlibOptions)
// register callbacks for various events during the zip lifecycle
2024-03-28 16:15:29 +00:00
zip.on('error', zipErrorCallback)
2024-03-28 16:11:50 +00:00
zip.on('warning', zipWarningCallback)
2024-03-28 15:10:34 +00:00
2024-03-28 16:15:29 +00:00
zip.on('finish', zipFinishCallback)
zip.on('end', zipEndCallback)
2024-03-28 17:25:01 +00:00
async.forEachOf(uploadSpecification, async file => {
if (file.sourcePath !== null) {
zip.entry(
createReadStream(file.sourcePath),
{name: file.destinationPath},
function (err, entry) {
2024-03-28 14:44:20 +00:00
core.debug(`Entry is: ${entry}`)
2024-03-28 17:25:01 +00:00
if (err) throw err
}
)
} else {
zip.entry(null, {name: file.destinationPath}, function (err, entry) {
core.debug(`Entry is: ${entry}`)
if (err) throw err
})
}
2024-03-28 17:13:32 +00:00
})
const bufferSize = getUploadChunkSize()
const zipUploadStream = new ZipUploadStream(bufferSize)
2024-03-28 16:06:54 +00:00
core.debug(
`Zip write high watermark value ${zipUploadStream.writableHighWaterMark}`
)
core.debug(
`Zip read high watermark value ${zipUploadStream.readableHighWaterMark}`
)
2024-03-28 17:13:32 +00:00
2024-03-28 17:25:01 +00:00
// zip.pipe(zipUploadStream)
zip.finalize()
2024-03-28 17:15:08 +00:00
return zipUploadStream
}
2024-03-28 16:15:29 +00:00
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const zipErrorCallback = (error: any): void => {
core.error('An error has occurred while creating the zip file for upload')
core.info(error)
2024-03-28 15:10:34 +00:00
2024-03-28 16:15:29 +00:00
throw new Error('An error has occurred during zip creation for the artifact')
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2024-03-28 16:11:50 +00:00
const zipWarningCallback = (err: any): void => {
if (err.code === 'ENOENT') {
core.warning(
'ENOENT warning during artifact zip creation. No such file or directory'
)
core.info(err)
} else {
core.warning(
`A non-blocking warning has occurred during artifact zip creation: ${err.code}`
)
core.info(err)
}
}
2024-03-28 15:10:34 +00:00
2024-03-28 16:15:29 +00:00
const zipFinishCallback = (): void => {
core.debug('Zip stream for upload has finished.')
}
2024-03-28 15:10:34 +00:00
2024-03-28 16:15:29 +00:00
const zipEndCallback = (): void => {
core.debug('Zip stream for upload has ended.')
}