@@ -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,97 @@ 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 ( 'C:\\Windows\\system32\\tar.exe' , [
280
+ `-xz${ verbose ? 'v' : '' } f` ,
281
+ tmpFile ,
282
+ '-C' ,
283
+ outputDirectory
284
+ ] , {
285
+ stdio : [ undefined , 'inherit' , 'inherit' ]
286
+ } )
287
+ return new Promise < void > ( ( resolve , reject ) => {
288
+ child . on ( 'close' , code => {
289
+ if ( code === 0 ) {
290
+ core . info ( 'Finished extracting archive.' )
291
+ fs . rm ( tmpFile , ( ) => resolve ( ) )
292
+ } else {
293
+ reject ( new Error ( `tar -xzf process exited with code ${ code } ` ) )
294
+ }
295
+ } )
296
+ } )
297
+ }
298
+ }
299
+ }
300
+
301
+ async function downloadFile (
302
+ url : string ,
303
+ options : RequestInit ,
304
+ destination : string
305
+ ) : Promise < void > {
306
+ const response = await fetch ( url , options ) ;
307
+
308
+ if ( ! response . ok ) {
309
+ throw new Error ( `Failed to fetch ${ url } : ${ response . statusText } ` ) ;
310
+ }
311
+
312
+ const fileStream = fs . createWriteStream ( destination ) ;
313
+ response . body . pipe ( fileStream ) ;
314
+
315
+ return new Promise ( ( resolve , reject ) => {
316
+ fileStream . on ( 'finish' , resolve ) ;
317
+ fileStream . on ( 'error' , reject ) ;
318
+ } ) ;
319
+ }
0 commit comments