@@ -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 https from 'https'
7
+ import os from 'os'
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,120 @@ 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
+ try {
268
+ await downloadFile (
269
+ tarGzArtifact . browser_download_url ,
270
+ {
271
+ headers : {
272
+ ...( githubToken ? { Authorization : `Bearer ${ githubToken } ` } : { } ) ,
273
+ Accept : 'application/octet-stream'
274
+ }
275
+ } ,
276
+ tmpFile
277
+ )
278
+ } catch ( e ) {
279
+ core . error (
280
+ `Failed to download ${ tarGzArtifact . browser_download_url } : ${ e } `
281
+ )
282
+ throw e
283
+ }
284
+ core . info ( 'Extracting archive with tar.exe...' )
285
+ const traceArg = verbose ? [ '-v' ] : [ ]
286
+ const child = spawn ( 'C:\\Windows\\system32\\tar.exe' , [
287
+ '-xzf' ,
288
+ ...traceArg ,
289
+ tmpFile ,
290
+ '-C' ,
291
+ outputDirectory
292
+ ] )
293
+ return new Promise < void > ( ( resolve , reject ) => {
294
+ child . on ( 'close' , code => {
295
+ if ( code === 0 ) {
296
+ core . info ( 'Finished extracting archive.' )
297
+ fs . rm ( tmpFile , ( ) => resolve ( ) )
298
+ } else {
299
+ reject ( new Error ( `tar -xzf process exited with code ${ code } ` ) )
300
+ }
301
+ } )
302
+ } )
303
+ }
304
+ }
305
+ }
306
+
307
+ async function downloadFile (
308
+ url : string ,
309
+ options : https . RequestOptions ,
310
+ destination : string
311
+ ) : Promise < void > {
312
+ return new Promise ( ( resolve , reject ) => {
313
+ const file = fs . createWriteStream ( destination )
314
+ https
315
+ . get ( url , options , async response => {
316
+ if ( response . statusCode === 301 || response . statusCode === 302 ) {
317
+ if ( ! response . headers . location ) {
318
+ throw new Error (
319
+ `Got a 301 or 302 response code, but no location header was set. Cannot continue.`
320
+ )
321
+ }
322
+ return await downloadFile (
323
+ response . headers . location ,
324
+ options ,
325
+ destination
326
+ )
327
+ }
328
+ if ( response . statusCode === 200 ) {
329
+ response . pipe ( file )
330
+ file . on ( 'finish' , resolve )
331
+ } else {
332
+ file . close ( )
333
+ fs . unlink ( destination , ( ) =>
334
+ reject ( new Error ( `Failed to download file: ${ response . statusCode } ` ) )
335
+ )
336
+ }
337
+ } )
338
+ . on ( 'error' , err => {
339
+ fs . unlink ( destination , ( ) => reject ( err ) )
340
+ } )
341
+ } )
342
+ }
0 commit comments