Skip to content

Commit 6db6522

Browse files
dennisamelingdscho
authored andcommitted
minimal: get from ci-artifacts
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]>
1 parent 1e953bc commit 6db6522

File tree

2 files changed

+97
-5
lines changed

2 files changed

+97
-5
lines changed

main.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
getViaGit,
99
gitForWindowsUsrBinPath
1010
} from './src/git'
11+
import {getViaCIArtifacts} from './src/ci_artifacts'
1112
import * as fs from 'fs'
1213

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

47-
const {artifactName, download, id} = await getViaGit(
48-
flavor,
49-
architecture,
50-
githubToken
51-
)
48+
const {artifactName, download, id} =
49+
flavor === 'minimal'
50+
? await getViaCIArtifacts(architecture, githubToken)
51+
: await getViaGit(flavor, architecture, githubToken)
5252
const outputDirectory =
5353
core.getInput('path') || `${getDriveLetterPrefix()}${artifactName}`
5454
core.setOutput('result', outputDirectory)

src/ci_artifacts.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import * as core from '@actions/core'
2+
import {Octokit} from '@octokit/rest'
3+
import {getArtifactMetadata} from './git'
4+
import {spawn} from 'child_process'
5+
import * as fs from 'fs'
6+
7+
export async function getViaCIArtifacts(
8+
architecture: string,
9+
githubToken?: string
10+
): Promise<{
11+
artifactName: string
12+
id: string
13+
download: (
14+
outputDirectory: string,
15+
verbose?: number | boolean
16+
) => Promise<void>
17+
}> {
18+
const owner = 'git-for-windows'
19+
20+
const {repo, artifactName} = getArtifactMetadata('minimal', architecture)
21+
22+
const octokit = githubToken ? new Octokit({auth: githubToken}) : new Octokit()
23+
24+
const ciArtifactsResponse = await octokit.repos.getReleaseByTag({
25+
owner,
26+
repo,
27+
tag: 'ci-artifacts'
28+
})
29+
30+
if (ciArtifactsResponse.status !== 200) {
31+
throw new Error(
32+
`Failed to get ci-artifacts release from the ${owner}/${repo} repo: ${ciArtifactsResponse.status}`
33+
)
34+
}
35+
36+
core.info(`Found ci-artifacts release: ${ciArtifactsResponse.data.html_url}`)
37+
const tarGzArtifact = ciArtifactsResponse.data.assets.find(asset =>
38+
asset.name.endsWith('.tar.gz')
39+
)
40+
41+
if (!tarGzArtifact) {
42+
throw new Error(
43+
`Failed to find a .tar.gz artifact in the ci-artifacts release of the ${owner}/${repo} repo`
44+
)
45+
}
46+
47+
const url = tarGzArtifact.browser_download_url
48+
core.info(`Found ${tarGzArtifact.name} at ${url}`)
49+
50+
return {
51+
artifactName,
52+
id: `ci-artifacts-${tarGzArtifact.updated_at}`,
53+
download: async (
54+
outputDirectory: string,
55+
verbose: number | boolean = false
56+
): Promise<void> => {
57+
return new Promise<void>((resolve, reject) => {
58+
const curl = spawn(
59+
`${process.env.SYSTEMROOT}/system32/curl.exe`,
60+
[
61+
...(githubToken
62+
? ['-H', `Authorization: Bearer ${githubToken}`]
63+
: []),
64+
'-H',
65+
'Accept: application/octet-stream',
66+
`-${verbose === true ? '' : 's'}fL`,
67+
url
68+
],
69+
{
70+
stdio: ['ignore', 'pipe', process.stderr]
71+
}
72+
)
73+
curl.on('error', error => reject(error))
74+
75+
fs.mkdirSync(outputDirectory, {recursive: true})
76+
77+
const tar = spawn(
78+
`${process.env.SYSTEMROOT}/system32/tar.exe`,
79+
['-C', outputDirectory, `-x${verbose === true ? 'v' : ''}f`, '-'],
80+
{stdio: ['pipe', process.stdout, process.stderr]}
81+
)
82+
tar.on('error', error => reject(error))
83+
tar.on('close', code => {
84+
if (code === 0) resolve()
85+
else reject(new Error(`tar exited with code ${code}`))
86+
})
87+
88+
curl.stdout.pipe(tar.stdin)
89+
})
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)