@@ -3,6 +3,8 @@ import {ChildProcess, spawn} from 'child_process'
3
3
import { Octokit } from '@octokit/rest'
4
4
import { delimiter } from 'path'
5
5
import * as fs from 'fs'
6
+ import os from 'os'
7
+ import fetch , { RequestInit } from 'node-fetch'
6
8
7
9
// If present, do prefer the build agent's copy of Git
8
10
const externalsGitDir = `${ process . env . AGENT_HOMEDIRECTORY } /externals/git`
@@ -109,54 +111,36 @@ async function updateHEAD(
109
111
} )
110
112
}
111
113
112
- export async function getViaGit (
113
- flavor : string ,
114
- architecture : string ,
115
- githubToken ?: string
116
- ) : Promise < {
114
+ type GetViaGitResult = {
117
115
artifactName : string
118
116
id : string
119
117
download : (
120
118
outputDirectory : string ,
121
119
verbose ?: number | boolean
122
120
) => Promise < void >
123
- } > {
121
+ }
122
+
123
+ export async function getViaGit (
124
+ flavor : string ,
125
+ architecture : string ,
126
+ githubToken ?: string
127
+ ) : Promise < GetViaGitResult > {
124
128
const owner = 'git-for-windows'
125
129
126
130
const { repo, artifactName} = getArtifactMetadata ( flavor , architecture )
127
131
128
132
const octokit = githubToken ? new Octokit ( { auth : githubToken } ) : new Octokit ( )
129
- let head_sha : string
133
+
130
134
if ( flavor === 'minimal' ) {
131
- const info = await octokit . actions . listWorkflowRuns ( {
132
- owner,
133
- repo,
134
- workflow_id : 938271 ,
135
- status : 'success' ,
136
- branch : 'main' ,
137
- event : 'push' ,
138
- per_page : 1
139
- } )
140
- head_sha = info . data . workflow_runs [ 0 ] . head_sha
141
- /*
142
- * There was a GCC upgrade to v14.1 that broke the build with `DEVELOPER=1`,
143
- * and `ci-artifacts` was not updated to test-build with `DEVELOPER=1` (this
144
- * was fixed in https://github.com/git-for-windows/git-sdk-64/pull/83).
145
- *
146
- * Work around that by forcing the incorrectly-passing revision back to the
147
- * last one before that GCC upgrade.
148
- */
149
- if ( head_sha === '5f6ba092f690c0bbf84c7201be97db59cdaeb891' ) {
150
- head_sha = 'e37e3f44c1934f0f263dabbf4ed50a3cfb6eaf71'
151
- }
152
- } else {
153
- const info = await octokit . repos . getBranch ( {
154
- owner,
155
- repo,
156
- branch : 'main'
157
- } )
158
- head_sha = info . data . commit . sha
135
+ return getMinimalFlavor ( owner , repo , artifactName , octokit , githubToken )
159
136
}
137
+
138
+ const info = await octokit . repos . getBranch ( {
139
+ owner,
140
+ repo,
141
+ branch : 'main'
142
+ } )
143
+ const head_sha = info . data . commit . sha
160
144
const id = `${ artifactName } -${ head_sha } ${ head_sha === 'e37e3f44c1934f0f263dabbf4ed50a3cfb6eaf71' ? '-2' : '' } `
161
145
core . info ( `Got commit ${ head_sha } for ${ repo } ` )
162
146
@@ -239,3 +223,96 @@ export async function getViaGit(
239
223
}
240
224
}
241
225
}
226
+
227
+ async function getMinimalFlavor (
228
+ owner : string ,
229
+ repo : string ,
230
+ artifactName : string ,
231
+ octokit : Octokit ,
232
+ githubToken ?: string
233
+ ) : Promise < GetViaGitResult > {
234
+ const ciArtifactsResponse = await octokit . repos . getReleaseByTag ( {
235
+ owner,
236
+ repo,
237
+ tag : 'ci-artifacts'
238
+ } )
239
+
240
+ if ( ciArtifactsResponse . status !== 200 ) {
241
+ throw new Error (
242
+ `Failed to get ci-artifacts release from the ${ owner } /${ repo } repo: ${ ciArtifactsResponse . status } `
243
+ )
244
+ }
245
+
246
+ const tarGzArtifact = ciArtifactsResponse . data . assets . find ( asset =>
247
+ asset . name . endsWith ( '.tar.gz' )
248
+ )
249
+
250
+ if ( ! tarGzArtifact ) {
251
+ throw new Error (
252
+ `Failed to find a tar.gz artifact in the ci-artifacts release of the ${ owner } /${ repo } repo`
253
+ )
254
+ }
255
+
256
+ return {
257
+ artifactName,
258
+ id : `ci-artifacts-${ tarGzArtifact . updated_at } ` ,
259
+ download : async (
260
+ outputDirectory : string ,
261
+ verbose : number | boolean = false
262
+ ) : Promise < void > => {
263
+ const tmpFile = `${ os . tmpdir ( ) } /${ tarGzArtifact . name } `
264
+ core . info (
265
+ `Downloading ${ tarGzArtifact . browser_download_url } to ${ tmpFile } ...`
266
+ )
267
+ await downloadFile (
268
+ tarGzArtifact . browser_download_url ,
269
+ {
270
+ headers : {
271
+ ...( githubToken ? { Authorization : `Bearer ${ githubToken } ` } : { } ) ,
272
+ Accept : 'application/octet-stream'
273
+ }
274
+ } ,
275
+ tmpFile
276
+ )
277
+ core . info ( `Extracting ${ tmpFile } to ${ outputDirectory } ...` )
278
+ fs . mkdirSync ( outputDirectory )
279
+ const child = spawn (
280
+ 'C:\\Windows\\system32\\tar.exe' ,
281
+ [ `-xz${ verbose ? 'v' : '' } f` , tmpFile , '-C' , outputDirectory ] ,
282
+ {
283
+ stdio : [ undefined , 'inherit' , 'inherit' ]
284
+ }
285
+ )
286
+ return new Promise < void > ( ( resolve , reject ) => {
287
+ child . on ( 'close' , code => {
288
+ if ( code === 0 ) {
289
+ core . info ( 'Finished extracting archive.' )
290
+ fs . rm ( tmpFile , ( ) => resolve ( ) )
291
+ } else {
292
+ reject ( new Error ( `tar -xzf process exited with code ${ code } ` ) )
293
+ }
294
+ } )
295
+ } )
296
+ }
297
+ }
298
+ }
299
+
300
+ async function downloadFile (
301
+ url : string ,
302
+ options : RequestInit ,
303
+ destination : string
304
+ ) : Promise < void > {
305
+ const response = await fetch ( url , options )
306
+
307
+ if ( ! response . ok ) {
308
+ throw new Error ( `Failed to fetch ${ url } : ${ response . statusText } ` )
309
+ }
310
+
311
+ const fileStream = fs . createWriteStream ( destination )
312
+ response . body . pipe ( fileStream )
313
+
314
+ return new Promise ( ( resolve , reject ) => {
315
+ fileStream . on ( 'finish' , resolve )
316
+ fileStream . on ( 'error' , reject )
317
+ } )
318
+ }
0 commit comments