Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions packages/artifact/__tests__/upload-artifact.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {BlockBlobUploadStreamOptions} from '@azure/storage-blob'
import * as fs from 'fs'
import * as path from 'path'
import unzip from 'unzip-stream'
import * as core from '@actions/core'

const uploadStreamMock = jest.fn()
const blockBlobClientMock = jest.fn().mockImplementation(() => ({
Expand Down Expand Up @@ -466,6 +467,71 @@ describe('upload-artifact', () => {
expect(uploadedContent).toBe(expectedContent)
})

it('should not warn when uploading an empty file with skipArchive enabled', async () => {
jest
.spyOn(uploadZipSpecification, 'getUploadZipSpecification')
.mockRestore()

const emptyFile = path.join(fixtures.uploadDirectory, 'empty.txt')
fs.writeFileSync(emptyFile, '')

jest
.spyOn(ArtifactServiceClientJSON.prototype, 'CreateArtifact')
.mockReturnValue(
Promise.resolve({
ok: true,
signedUploadUrl: 'https://signed-upload-url.local'
})
)
jest
.spyOn(ArtifactServiceClientJSON.prototype, 'FinalizeArtifact')
.mockReturnValue(
Promise.resolve({
ok: true,
artifactId: '1'
})
)

uploadStreamMock.mockImplementation(
async (
stream: NodeJS.ReadableStream,
bufferSize?: number,
maxConcurrency?: number,
options?: BlockBlobUploadStreamOptions
) => {
const {onProgress} = options || {}
onProgress?.({loadedBytes: 0})

return new Promise((resolve, reject) => {
stream.on('data', () => {
onProgress?.({loadedBytes: 0})
})
stream.on('end', () => {
onProgress?.({loadedBytes: 0})
resolve({})
})
stream.on('error', err => {
reject(err)
})
})
}
)

const warningSpy = core.warning as jest.Mock
warningSpy.mockClear()

await uploadArtifact(
fixtures.inputs.artifactName,
[emptyFile],
fixtures.uploadDirectory,
{skipArchive: true}
)

expect(warningSpy).not.toHaveBeenCalledWith(
'No data was uploaded to blob storage. Reported upload byte count is 0.'
)
})

it('should use the correct MIME type when skipArchive is true', async () => {
jest
.spyOn(uploadZipSpecification, 'getUploadZipSpecification')
Expand Down
13 changes: 9 additions & 4 deletions packages/artifact/src/internal/upload/blob-upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,15 @@ export interface BlobUploadResponse {
sha256Hash?: string
}

export interface BlobUploadOptions {
suppressZeroByteWarning?: boolean
}

export async function uploadToBlobStorage(
authenticatedUploadURL: string,
uploadStream: WaterMarkedUploadStream,
contentType: string
contentType: string,
options?: BlobUploadOptions
): Promise<BlobUploadResponse> {
let uploadByteCount = 0
let lastProgressTime = Date.now()
Expand Down Expand Up @@ -61,7 +66,7 @@ export async function uploadToBlobStorage(
lastProgressTime = Date.now()
}

const options: BlockBlobUploadStreamOptions = {
const uploadOptions: BlockBlobUploadStreamOptions = {
blobHTTPHeaders: {blobContentType: contentType},
onProgress: uploadCallback,
abortSignal: abortController.signal
Expand All @@ -82,7 +87,7 @@ export async function uploadToBlobStorage(
blobUploadStream,
bufferSize,
maxConcurrency,
options
uploadOptions
),
chunkTimer(getUploadChunkTimeout())
])
Expand All @@ -101,7 +106,7 @@ export async function uploadToBlobStorage(
sha256Hash = hashStream.read() as string
core.info(`SHA256 digest of uploaded artifact is ${sha256Hash}`)

if (uploadByteCount === 0) {
if (uploadByteCount === 0 && !options?.suppressZeroByteWarning) {
core.warning(
`No data was uploaded to blob storage. Reported upload byte count is 0.`
)
Expand Down
8 changes: 7 additions & 1 deletion packages/artifact/src/internal/upload/upload-artifact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export async function uploadArtifact(
options?: UploadArtifactOptions | undefined
): Promise<UploadArtifactResponse> {
let artifactFileName = `${name}.zip`
let suppressZeroByteWarning = false

if (options?.skipArchive) {
if (files.length === 0) {
throw new FilesNotFoundError([])
Expand All @@ -47,6 +49,7 @@ export async function uploadArtifact(
throw new FilesNotFoundError(files)
}

suppressZeroByteWarning = fs.statSync(files[0]).size === 0
artifactFileName = path.basename(files[0])
name = artifactFileName
}
Expand Down Expand Up @@ -114,7 +117,10 @@ export async function uploadArtifact(
const uploadResult = await uploadToBlobStorage(
createArtifactResp.signedUploadUrl,
stream,
contentType
contentType,
{
suppressZeroByteWarning
}
)

// finalize the artifact
Expand Down