Skip to content

Commit

Permalink
minimal: get 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, including several variants of the minimal
flavor of Git for Windows' SDK. This eliminates the need for us to clone
the minimal SDK in this GitHub Action.

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

Note: As per the analysis in
git-for-windows/git-sdk-64@fdb0cea37389, we
use the native `tar.exe` to unpack the minimal SDK while it is
downloaded, for maximal speed.

The analysis also suggests to use the `.zip` file, as this results in
the fastest operation when download speeds are above 6MB/second (which
we hope will be reliably the case in GitHub Actions). However, we want
to pipe the archive to `tar -xf -` while fetching, and it seems that for
some reason `C:\Windows\system32\tar.exe` misses `.sparse/` and `etc/`
when extracting `.zip` files from `stdin`, but the same is not true with
`.tar.gz` files. So let's use the latter.

See also: git-for-windows/git-sdk-64#87.

Signed-off-by: Dennis Ameling <[email protected]>
Signed-off-by: Johannes Schindelin <[email protected]>
  • Loading branch information
dennisameling authored and dscho committed Dec 17, 2024
1 parent 1e953bc commit 6db6522
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 5 deletions.
10 changes: 5 additions & 5 deletions main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
getViaGit,
gitForWindowsUsrBinPath
} from './src/git'
import {getViaCIArtifacts} from './src/ci_artifacts'
import * as fs from 'fs'

const flavor = core.getInput('flavor')
Expand Down Expand Up @@ -44,11 +45,10 @@ async function run(): Promise<void> {
const verbose = core.getInput('verbose')
const msysMode = core.getInput('msys') === 'true'

const {artifactName, download, id} = await getViaGit(
flavor,
architecture,
githubToken
)
const {artifactName, download, id} =
flavor === 'minimal'
? await getViaCIArtifacts(architecture, githubToken)
: await getViaGit(flavor, architecture, githubToken)
const outputDirectory =
core.getInput('path') || `${getDriveLetterPrefix()}${artifactName}`
core.setOutput('result', outputDirectory)
Expand Down
92 changes: 92 additions & 0 deletions src/ci_artifacts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import * as core from '@actions/core'
import {Octokit} from '@octokit/rest'
import {getArtifactMetadata} from './git'
import {spawn} from 'child_process'
import * as fs from 'fs'

export async function getViaCIArtifacts(
architecture: string,
githubToken?: string
): Promise<{
artifactName: string
id: string
download: (
outputDirectory: string,
verbose?: number | boolean
) => Promise<void>
}> {
const owner = 'git-for-windows'

const {repo, artifactName} = getArtifactMetadata('minimal', architecture)

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

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}`
)
}

core.info(`Found ci-artifacts release: ${ciArtifactsResponse.data.html_url}`)
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`
)
}

const url = tarGzArtifact.browser_download_url
core.info(`Found ${tarGzArtifact.name} at ${url}`)

return {
artifactName,
id: `ci-artifacts-${tarGzArtifact.updated_at}`,
download: async (
outputDirectory: string,
verbose: number | boolean = false
): Promise<void> => {
return new Promise<void>((resolve, reject) => {
const curl = spawn(
`${process.env.SYSTEMROOT}/system32/curl.exe`,
[
...(githubToken
? ['-H', `Authorization: Bearer ${githubToken}`]
: []),
'-H',
'Accept: application/octet-stream',
`-${verbose === true ? '' : 's'}fL`,
url
],
{
stdio: ['ignore', 'pipe', process.stderr]
}
)
curl.on('error', error => reject(error))

fs.mkdirSync(outputDirectory, {recursive: true})

const tar = spawn(
`${process.env.SYSTEMROOT}/system32/tar.exe`,
['-C', outputDirectory, `-x${verbose === true ? 'v' : ''}f`, '-'],
{stdio: ['pipe', process.stdout, process.stderr]}
)
tar.on('error', error => reject(error))
tar.on('close', code => {
if (code === 0) resolve()
else reject(new Error(`tar exited with code ${code}`))
})

curl.stdout.pipe(tar.stdin)
})
}
}
}

0 comments on commit 6db6522

Please sign in to comment.