Skip to content

Commit

Permalink
getViaGit: get minimal flavor from ci-artifacts
Browse files Browse the repository at this point in the history
As a result of recent changes, the Git SDK `ci-artifacts` are published as GitHub release assets now. This eliminates the need for us to clone and cache the artifacts in this GitHub action.

Let's simply download the latest `.tar.gz` from the `ci-artifacts` and extract it.

Ref: git-for-windows/git-sdk-64@fdb0cea
Ref: git-for-windows/git-sdk-64#87
Signed-off-by: Dennis Ameling <[email protected]>
  • Loading branch information
dennisameling committed Sep 22, 2024
1 parent ade9582 commit 3289deb
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 36 deletions.
2 changes: 1 addition & 1 deletion main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ async function run(): Promise<void> {
useCache = true
break
case 'auto':
useCache = flavor !== 'full'
useCache = !['full', 'minimal'].includes(flavor)
break
default:
useCache = false
Expand Down
148 changes: 113 additions & 35 deletions src/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {ChildProcess, spawn} from 'child_process'
import {Octokit} from '@octokit/rest'
import {delimiter} from 'path'
import * as fs from 'fs'
import os from 'os'
import fetch, {RequestInit} from 'node-fetch'

// If present, do prefer the build agent's copy of Git
const externalsGitDir = `${process.env.AGENT_HOMEDIRECTORY}/externals/git`
Expand Down Expand Up @@ -109,54 +111,36 @@ async function updateHEAD(
})
}

export async function getViaGit(
flavor: string,
architecture: string,
githubToken?: string
): Promise<{
type GetViaGitResult = {
artifactName: string
id: string
download: (
outputDirectory: string,
verbose?: number | boolean
) => Promise<void>
}> {
}

export async function getViaGit(
flavor: string,
architecture: string,
githubToken?: string
): Promise<GetViaGitResult> {
const owner = 'git-for-windows'

const {repo, artifactName} = getArtifactMetadata(flavor, architecture)

const octokit = githubToken ? new Octokit({auth: githubToken}) : new Octokit()
let head_sha: string

if (flavor === 'minimal') {
const info = await octokit.actions.listWorkflowRuns({
owner,
repo,
workflow_id: 938271,
status: 'success',
branch: 'main',
event: 'push',
per_page: 1
})
head_sha = info.data.workflow_runs[0].head_sha
/*
* There was a GCC upgrade to v14.1 that broke the build with `DEVELOPER=1`,
* and `ci-artifacts` was not updated to test-build with `DEVELOPER=1` (this
* was fixed in https://github.com/git-for-windows/git-sdk-64/pull/83).
*
* Work around that by forcing the incorrectly-passing revision back to the
* last one before that GCC upgrade.
*/
if (head_sha === '5f6ba092f690c0bbf84c7201be97db59cdaeb891') {
head_sha = 'e37e3f44c1934f0f263dabbf4ed50a3cfb6eaf71'
}
} else {
const info = await octokit.repos.getBranch({
owner,
repo,
branch: 'main'
})
head_sha = info.data.commit.sha
return getMinimalFlavor(owner, repo, artifactName, octokit, githubToken)
}

const info = await octokit.repos.getBranch({
owner,
repo,
branch: 'main'
})
const head_sha = info.data.commit.sha
const id = `${artifactName}-${head_sha}${head_sha === 'e37e3f44c1934f0f263dabbf4ed50a3cfb6eaf71' ? '-2' : ''}`
core.info(`Got commit ${head_sha} for ${repo}`)

Expand Down Expand Up @@ -239,3 +223,97 @@ export async function getViaGit(
}
}
}

async function getMinimalFlavor(
owner: string,
repo: string,
artifactName: string,
octokit: Octokit,
githubToken?: string
): Promise<GetViaGitResult> {
const ciArtifactsResponse = await octokit.repos.getReleaseByTag({
owner,
repo,
tag: 'ci-artifacts'
})

if (ciArtifactsResponse.status !== 200) {
throw new Error(
`Failed to get ci-artifacts release from the ${owner}/${repo} repo: ${ciArtifactsResponse.status}`
)
}

const tarGzArtifact = ciArtifactsResponse.data.assets.find(asset =>
asset.name.endsWith('.tar.gz')
)

if (!tarGzArtifact) {
throw new Error(
`Failed to find a tar.gz artifact in the ci-artifacts release of the ${owner}/${repo} repo`
)
}

return {
artifactName,
id: `ci-artifacts-${tarGzArtifact.updated_at}`,
download: async (
outputDirectory: string,
verbose: number | boolean = false
): Promise<void> => {
const tmpFile = `${os.tmpdir()}/${tarGzArtifact.name}`
core.info(
`Downloading ${tarGzArtifact.browser_download_url} to ${tmpFile}...`
)
await downloadFile(
tarGzArtifact.browser_download_url,
{
headers: {
...(githubToken ? {Authorization: `Bearer ${githubToken}`} : {}),
Accept: 'application/octet-stream'
}
},
tmpFile
)
core.info(`Extracting ${tmpFile} to ${outputDirectory}...`)
fs.mkdirSync(outputDirectory)
const child = spawn('C:\\Windows\\system32\\tar.exe', [
`-xz${verbose ? 'v' : ''}f`,
tmpFile,
'-C',
outputDirectory
], {
stdio: [undefined, 'inherit', 'inherit']
})
return new Promise<void>((resolve, reject) => {
child.on('close', code => {
if (code === 0) {
core.info('Finished extracting archive.')
fs.rm(tmpFile, () => resolve())
} else {
reject(new Error(`tar -xzf process exited with code ${code}`))
}
})
})
}
}
}

async function downloadFile(
url: string,
options: RequestInit,
destination: string
): Promise<void> {
const response = await fetch(url, options);

if (!response.ok) {
throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
}

const fileStream = fs.createWriteStream(destination);
response.body.pipe(fileStream);

return new Promise((resolve, reject) => {
fileStream.on('finish', resolve);
fileStream.on('error', reject);
});
}

0 comments on commit 3289deb

Please sign in to comment.