From 09a881150911e44069569fd834f641fcfbd1a623 Mon Sep 17 00:00:00 2001 From: eric sciple Date: Mon, 9 Dec 2019 16:54:42 -0500 Subject: fallback to REST API to download repo --- src/github-api-helper.ts | 88 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/github-api-helper.ts (limited to 'src/github-api-helper.ts') diff --git a/src/github-api-helper.ts b/src/github-api-helper.ts new file mode 100644 index 0000000..63ec788 --- /dev/null +++ b/src/github-api-helper.ts @@ -0,0 +1,88 @@ +import * as assert from 'assert' +import * as core from '@actions/core' +import * as fs from 'fs' +import * as github from '@actions/github' +import * as io from '@actions/io' +import * as path from 'path' +import * as retryHelper from './retry-helper' +import * as toolCache from '@actions/tool-cache' +import {default as uuid} from 'uuid/v4' +import {ReposGetArchiveLinkParams} from '@octokit/rest' + +const IS_WINDOWS = process.platform === 'win32' + +export async function downloadRepository( + accessToken: string, + owner: string, + repo: string, + ref: string, + commit: string, + repositoryPath: string +): Promise { + // Download the archive + let archiveData = await retryHelper.execute(async () => { + core.info('Downloading the archive') + return await downloadArchive(accessToken, owner, repo, ref, commit) + }) + + // Write archive to disk + core.info('Writing archive to disk') + const uniqueId = uuid() + const archivePath = path.join(repositoryPath, `${uniqueId}.tar.gz`) + await fs.promises.writeFile(archivePath, archiveData) + archiveData = Buffer.from('') // Free memory + + // Extract archive + core.info('Extracting the archive') + const extractPath = path.join(repositoryPath, uniqueId) + await io.mkdirP(extractPath) + if (IS_WINDOWS) { + await toolCache.extractZip(archivePath, extractPath) + } else { + await toolCache.extractTar(archivePath, extractPath) + } + io.rmRF(archivePath) + + // Determine the path of the repository content. The archive contains + // a top-level folder and the repository content is inside. + const archiveFileNames = await fs.promises.readdir(extractPath) + assert.ok( + archiveFileNames.length == 1, + 'Expected exactly one directory inside archive' + ) + const archiveVersion = archiveFileNames[0] // The top-level folder name includes the short SHA + core.info(`Resolved version ${archiveVersion}`) + const tempRepositoryPath = path.join(extractPath, archiveVersion) + + // Move the files + for (const fileName of await fs.promises.readdir(tempRepositoryPath)) { + const sourcePath = path.join(tempRepositoryPath, fileName) + const targetPath = path.join(repositoryPath, fileName) + await io.mv(sourcePath, targetPath) + } + io.rmRF(extractPath) +} + +async function downloadArchive( + accessToken: string, + owner: string, + repo: string, + ref: string, + commit: string +): Promise { + const octokit = new github.GitHub(accessToken) + const params: ReposGetArchiveLinkParams = { + owner: owner, + repo: repo, + archive_format: IS_WINDOWS ? 'zipball' : 'tarball', + ref: commit || ref + } + const response = await octokit.repos.getArchiveLink(params) + if (response.status != 200) { + throw new Error( + `Unexpected response from GitHub API. Status: '${response.status}'` + ) + } + + return Buffer.from(response.data) // response.data is ArrayBuffer +} -- cgit v1.2.3