2019-12-12 21:16:16 +03:00
import * as assert from 'assert'
import * as core from '@actions/core'
import * as fs from 'fs'
2023-04-12 14:55:27 +03:00
import * as github from '@actions/github'
2019-12-12 21:16:16 +03:00
import * as io from '@actions/io'
import * as path from 'path'
import * as retryHelper from './retry-helper'
import * as toolCache from '@actions/tool-cache'
2024-04-24 19:04:10 +03:00
import { v4 as uuid } from 'uuid'
2023-04-13 15:25:50 +03:00
import { getServerApiUrl } from './url-helper'
2019-12-12 21:16:16 +03:00
const IS_WINDOWS = process . platform === 'win32'
export async function downloadRepository (
2019-12-12 21:49:26 +03:00
authToken : string ,
2019-12-12 21:16:16 +03:00
owner : string ,
repo : string ,
ref : string ,
commit : string ,
2022-09-26 19:34:52 +03:00
repositoryPath : string ,
baseUrl? : string
2019-12-12 21:16:16 +03:00
) : Promise < void > {
2020-06-18 17:20:33 +03:00
// Determine the default branch
if ( ! ref && ! commit ) {
core . info ( 'Determining the default branch' )
2022-09-26 19:34:52 +03:00
ref = await getDefaultBranch ( authToken , owner , repo , baseUrl )
2020-06-18 17:20:33 +03:00
}
2019-12-12 21:16:16 +03:00
// Download the archive
let archiveData = await retryHelper . execute ( async ( ) = > {
core . info ( 'Downloading the archive' )
2022-09-26 19:34:52 +03:00
return await downloadArchive ( authToken , owner , repo , ref , commit , baseUrl )
2019-12-12 21:16:16 +03:00
} )
// Write archive to disk
core . info ( 'Writing archive to disk' )
const uniqueId = uuid ( )
2024-05-16 20:40:36 +03:00
const archivePath = IS_WINDOWS
? path . join ( repositoryPath , ` ${ uniqueId } .zip ` )
: path . join ( repositoryPath , ` ${ uniqueId } .tar.gz ` )
2019-12-12 21:16:16 +03:00
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 )
}
2020-11-03 17:44:09 +03:00
await io . rmRF ( archivePath )
2019-12-12 21:16:16 +03:00
// 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 )
if ( IS_WINDOWS ) {
await io . cp ( sourcePath , targetPath , { recursive : true } ) // Copy on Windows (Windows Defender may have a lock)
} else {
await io . mv ( sourcePath , targetPath )
}
}
2020-11-03 17:44:09 +03:00
await io . rmRF ( extractPath )
2019-12-12 21:16:16 +03:00
}
2020-06-16 20:41:01 +03:00
/ * *
* Looks up the default branch name
* /
export async function getDefaultBranch (
authToken : string ,
owner : string ,
2022-09-26 19:34:52 +03:00
repo : string ,
baseUrl? : string
2020-06-16 20:41:01 +03:00
) : Promise < string > {
return await retryHelper . execute ( async ( ) = > {
core . info ( 'Retrieving the default branch name' )
2023-04-13 15:25:50 +03:00
const octokit = github . getOctokit ( authToken , {
baseUrl : getServerApiUrl ( baseUrl )
} )
2020-06-18 17:20:33 +03:00
let result : string
try {
// Get the default branch from the repo info
2023-04-12 14:55:27 +03:00
const response = await octokit . rest . repos . get ( { owner , repo } )
2020-06-18 17:20:33 +03:00
result = response . data . default_branch
assert . ok ( result , 'default_branch cannot be empty' )
} catch ( err ) {
// Handle .wiki repo
2021-10-19 17:52:57 +03:00
if (
( err as any ) ? . status === 404 &&
repo . toUpperCase ( ) . endsWith ( '.WIKI' )
) {
2020-06-18 17:20:33 +03:00
result = 'master'
}
// Otherwise error
else {
throw err
}
2020-06-16 20:41:01 +03:00
}
// Print the default branch
core . info ( ` Default branch ' ${ result } ' ` )
// Prefix with 'refs/heads'
if ( ! result . startsWith ( 'refs/' ) ) {
result = ` refs/heads/ ${ result } `
}
return result
} )
}
2019-12-12 21:16:16 +03:00
async function downloadArchive (
2019-12-12 21:49:26 +03:00
authToken : string ,
2019-12-12 21:16:16 +03:00
owner : string ,
repo : string ,
ref : string ,
2022-09-26 19:34:52 +03:00
commit : string ,
baseUrl? : string
2019-12-12 21:16:16 +03:00
) : Promise < Buffer > {
2023-04-13 15:25:50 +03:00
const octokit = github . getOctokit ( authToken , {
baseUrl : getServerApiUrl ( baseUrl )
} )
2023-04-12 14:55:27 +03:00
const download = IS_WINDOWS
? octokit . rest . repos . downloadZipballArchive
: octokit . rest . repos . downloadTarballArchive
const response = await download ( {
2019-12-12 21:16:16 +03:00
owner : owner ,
repo : repo ,
ref : commit || ref
2023-04-12 14:55:27 +03:00
} )
return Buffer . from ( response . data as ArrayBuffer ) // response.data is ArrayBuffer
2019-12-12 21:16:16 +03:00
}