Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
ericsciple committed Mar 5, 2020
1 parent 38df43a commit aeb718e
Showing 1 changed file with 40 additions and 59 deletions.
99 changes: 40 additions & 59 deletions packages/tool-cache/src/tool-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as path from 'path'
import * as httpm from '@actions/http-client'
import * as semver from 'semver'
import * as stream from 'stream'
import * as util from 'util'
import uuidV4 from 'uuid/v4'
import {exec} from '@actions/exec/lib/exec'
import {ExecOptions} from '@actions/exec/lib/interfaces'
Expand Down Expand Up @@ -60,7 +61,7 @@ export async function downloadTool(
dest = dest || path.join(tempDirectory, uuidV4())
await io.mkdirP(path.dirname(dest))
core.debug(`Downloading ${url}`)
core.debug(`Downloading ${dest}`)
core.debug(`Destination ${dest}`)

const maxAttempts = 3
const minSeconds = getGlobal<number>(
Expand All @@ -78,67 +79,47 @@ export async function downloadTool(
}

async function downloadToolAttempt(url: string, dest: string): Promise<string> {
// Wrap in a promise so that we can resolve from within stream callbacks
return new Promise<string>(async (resolve, reject) => {
try {
if (fs.existsSync(dest)) {
throw new Error(`Destination file path ${dest} already exists`)
}

const http = new httpm.HttpClient(userAgent, [], {
allowRetries: false
})
const response: httpm.HttpClientResponse = await http.get(url)
if (response.message.statusCode !== 200) {
const err = new HTTPError(response.message.statusCode)
core.debug(
`Failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`
)
throw err
}
if (fs.existsSync(dest)) {
throw new Error(`Destination file path ${dest} already exists`)
}

let error: Error | undefined
const file: NodeJS.WritableStream = fs.createWriteStream(dest)
file.on('open', async () => {
const responseMessageFactory = getGlobal<() => stream.Readable>(
'TEST_DOWNLOAD_TOOL_RESPONSE_MESSAGE_FACTORY',
() => response.message
)
const readStream = responseMessageFactory()
readStream.pipe(file)
readStream.on('error', (err: Error) => {
file.end()
error = error || err
})
})
file.on('error', err => {
file.end()
error = error || err
})
file.on('close', () => {
// Success
if (!error) {
core.debug('download complete')
resolve(dest)
return
}
// Get the response headers
const http = new httpm.HttpClient(userAgent, [], {
allowRetries: false
})
const response: httpm.HttpClientResponse = await http.get(url)
if (response.message.statusCode !== 200) {
const err = new HTTPError(response.message.statusCode)
core.debug(
`Failed to download from "${url}". Code(${response.message.statusCode}) Message(${response.message.statusMessage})`
)
throw err
}

// Error, delete dest before retry
if (error) {
io.rmRF(dest || '')
.catch(err => {
core.debug(`Failed to delete '${dest}'. ${err.message}`)
})
.finally(() => {
core.debug('download failed')
reject(error)
})
}
})
} catch (err) {
reject(err)
// Download the response body
const pipeline = util.promisify(stream.pipeline)
const responseMessageFactory = getGlobal<() => stream.Readable>(
'TEST_DOWNLOAD_TOOL_RESPONSE_MESSAGE_FACTORY',
() => response.message
)
const readStream = responseMessageFactory()
let succeeded = false
try {
await pipeline(readStream, fs.createWriteStream(dest))
core.debug('download complete')
succeeded = true
return dest
} finally {
// Error, delete dest before retry
if (!succeeded) {
core.debug('download failed')
try {
await io.rmRF(dest)
} catch (err) {
core.debug(`Failed to delete '${dest}'. ${err.message}`)
}
}
})
}
}

/**
Expand Down

0 comments on commit aeb718e

Please sign in to comment.