@@ -9,8 +9,9 @@ import * as mime from "mime"
9
9
import * as FormData from "form-data"
10
10
import { URL } from "url"
11
11
import { HttpPublisher } from "./httpPublisher"
12
- import { PublishContext , PublishOptions } from "./index"
13
- import { getCiTag } from "./publisher"
12
+ import { PublishContext } from "./index"
13
+
14
+ type RequestProcessor = ( request : ClientRequest , reject : ( error : Error ) => void ) => void
14
15
15
16
export class GitlabPublisher extends HttpPublisher {
16
17
private readonly tag : string
@@ -28,8 +29,7 @@ export class GitlabPublisher extends HttpPublisher {
28
29
constructor (
29
30
context : PublishContext ,
30
31
private readonly info : GitlabOptions ,
31
- private readonly version : string ,
32
- private readonly options : PublishOptions = { }
32
+ private readonly version : string
33
33
) {
34
34
super ( context , true )
35
35
@@ -67,32 +67,13 @@ export class GitlabPublisher extends HttpPublisher {
67
67
}
68
68
69
69
try {
70
- // Get all releases first, then filter by tag (similar to GitHub publisher pattern)
71
- const url = new URL ( `${ this . baseApiPath } /projects/${ encodeURIComponent ( this . projectId ) } /releases` )
72
- const releases = await this . gitlabRequest < GitlabReleaseInfo [ ] > ( url , this . token )
73
- for ( const release of releases ) {
74
- if ( release . tag_name === this . tag ) {
75
- return release
76
- }
70
+ const existingRelease = await this . getExistingRelease ( )
71
+ if ( existingRelease ) {
72
+ return existingRelease
77
73
}
78
74
79
75
// Create new release if it doesn't exist
80
- if ( this . options . publish === "always" || getCiTag ( ) != null ) {
81
- log . info (
82
- {
83
- reason : "release doesn't exist" ,
84
- ...logFields ,
85
- } ,
86
- `creating GitLab release`
87
- )
88
- return this . createRelease ( )
89
- }
90
-
91
- this . releaseLogFields = {
92
- reason : 'release doesn\'t exist and not created because "publish" is not "always" and build is not on tag' ,
93
- ...logFields ,
94
- }
95
- return null
76
+ return this . createRelease ( )
96
77
} catch ( error : any ) {
97
78
const errorInfo = this . categorizeGitlabError ( error )
98
79
log . error (
@@ -108,9 +89,22 @@ export class GitlabPublisher extends HttpPublisher {
108
89
}
109
90
}
110
91
92
+ private async getExistingRelease ( ) : Promise < GitlabReleaseInfo | null > {
93
+ const url = this . buildProjectUrl ( "/releases" )
94
+ const releases = await this . gitlabRequest < GitlabReleaseInfo [ ] > ( url , this . token )
95
+
96
+ for ( const release of releases ) {
97
+ if ( release . tag_name === this . tag ) {
98
+ return release
99
+ }
100
+ }
101
+
102
+ return null
103
+ }
104
+
111
105
private async getDefaultBranch ( ) : Promise < string > {
112
106
try {
113
- const url = new URL ( ` ${ this . baseApiPath } /projects/ ${ encodeURIComponent ( this . projectId ) } ` )
107
+ const url = this . buildProjectUrl ( )
114
108
const project = await this . gitlabRequest < { default_branch : string } > ( url , this . token )
115
109
return project . default_branch || "main"
116
110
} catch ( error : any ) {
@@ -139,17 +133,11 @@ export class GitlabPublisher extends HttpPublisher {
139
133
"creating GitLab release"
140
134
)
141
135
142
- const url = new URL ( ` ${ this . baseApiPath } /projects/ ${ encodeURIComponent ( this . projectId ) } /releases` )
136
+ const url = this . buildProjectUrl ( " /releases" )
143
137
return this . gitlabRequest < GitlabReleaseInfo > ( url , this . token , releaseData , "POST" )
144
138
}
145
139
146
- protected async doUpload (
147
- fileName : string ,
148
- arch : Arch ,
149
- dataLength : number ,
150
- requestProcessor : ( request : ClientRequest , reject : ( error : Error ) => void ) => void ,
151
- _file : string
152
- ) : Promise < any > {
140
+ protected async doUpload ( fileName : string , arch : Arch , dataLength : number , requestProcessor : RequestProcessor , filePath : string ) : Promise < any > {
153
141
const release = await this . _release . value
154
142
if ( release == null ) {
155
143
log . warn ( { file : fileName , ...this . releaseLogFields } , "skipped publishing" )
@@ -165,32 +153,16 @@ export class GitlabPublisher extends HttpPublisher {
165
153
166
154
try {
167
155
log . debug ( logFields , "starting GitLab upload" )
168
- // Default to project_upload method
169
- const uploadTarget = this . info . uploadTarget || "project_upload"
170
-
171
- let uploadResult
172
- let assetUrl : string
173
- if ( uploadTarget === "generic_package" ) {
174
- uploadResult = await this . uploadToGenericPackages ( fileName , dataLength , requestProcessor , _file )
175
- // For generic packages, construct the download URL
176
- const projectId = encodeURIComponent ( this . projectId )
177
- assetUrl = `${ this . baseApiPath } /projects/${ projectId } /packages/generic/releases/${ this . version } /${ fileName } `
178
- } else {
179
- // Default to project_upload
180
- uploadResult = await this . uploadToProjectUpload ( fileName , _file )
181
- // For project uploads, construct full URL from relative path
182
- assetUrl = `https://${ this . host } ${ uploadResult . url } `
183
- }
184
-
156
+ const assetPath = await this . uploadFileAndReturnAssetPath ( fileName , dataLength , requestProcessor , filePath )
185
157
// Add the uploaded file as a release asset link
186
- if ( assetUrl ) {
187
- await this . addReleaseAssetLink ( fileName , assetUrl )
188
- log . info ( { ...logFields , assetUrl } , "GitLab upload completed successfully" )
158
+ if ( assetPath ) {
159
+ await this . addReleaseAssetLink ( fileName , assetPath )
160
+ log . info ( { ...logFields , assetPath } , "GitLab upload completed successfully" )
189
161
} else {
190
162
log . warn ( { ...logFields } , "No asset URL found for file" )
191
163
}
192
164
193
- return uploadResult
165
+ return assetPath
194
166
} catch ( e : any ) {
195
167
const errorInfo = this . categorizeGitlabError ( e )
196
168
log . error (
@@ -206,6 +178,26 @@ export class GitlabPublisher extends HttpPublisher {
206
178
}
207
179
}
208
180
181
+ private async uploadFileAndReturnAssetPath ( fileName : string , dataLength : number , requestProcessor : RequestProcessor , filePath : string ) {
182
+ // Default to project_upload method
183
+ const uploadTarget = this . info . uploadTarget || "project_upload"
184
+
185
+ let assetPath : string
186
+ if ( uploadTarget === "generic_package" ) {
187
+ await this . uploadToGenericPackages ( fileName , dataLength , requestProcessor )
188
+ // For generic packages, construct the download URL
189
+ const projectId = encodeURIComponent ( this . projectId )
190
+ assetPath = `${ this . baseApiPath } /projects/${ projectId } /packages/generic/releases/${ this . version } /${ fileName } `
191
+ } else {
192
+ // Default to project_upload
193
+ const uploadResult = await this . uploadToProjectUpload ( fileName , filePath )
194
+ // For project uploads, construct full URL from relative path
195
+ assetPath = `https://${ this . host } ${ uploadResult . url } `
196
+ }
197
+
198
+ return assetPath
199
+ }
200
+
209
201
private async addReleaseAssetLink ( fileName : string , assetUrl : string ) : Promise < void > {
210
202
try {
211
203
const linkData = {
@@ -214,7 +206,7 @@ export class GitlabPublisher extends HttpPublisher {
214
206
link_type : "other" ,
215
207
}
216
208
217
- const url = new URL ( ` ${ this . baseApiPath } /projects/ ${ encodeURIComponent ( this . projectId ) } /releases/${ this . tag } /assets/links`)
209
+ const url = this . buildProjectUrl ( ` /releases/${ this . tag } /assets/links`)
218
210
await this . gitlabRequest ( url , this . token , linkData , "POST" )
219
211
220
212
log . debug ( { fileName, assetUrl } , "Successfully linked asset to GitLab release" )
@@ -224,25 +216,25 @@ export class GitlabPublisher extends HttpPublisher {
224
216
}
225
217
}
226
218
227
- private async uploadToProjectUpload ( fileName : string , _filePath : string ) : Promise < any > {
219
+ private async uploadToProjectUpload ( fileName : string , filePath : string ) : Promise < any > {
228
220
const uploadUrl = `${ this . baseApiPath } /projects/${ encodeURIComponent ( this . projectId ) } /uploads`
229
221
const parsedUrl = new URL ( uploadUrl )
230
222
231
223
// Check file size to determine upload method
232
- const stats = await stat ( _filePath )
224
+ const stats = await stat ( filePath )
233
225
const fileSize = stats . size
234
226
const STREAMING_THRESHOLD = 50 * 1024 * 1024 // 50MB
235
227
236
228
const form = new FormData ( )
237
229
if ( fileSize > STREAMING_THRESHOLD ) {
238
230
// Use streaming for large files
239
231
log . debug ( { fileName, fileSize } , "using streaming upload for large file" )
240
- const fileStream = createReadStream ( _filePath )
232
+ const fileStream = createReadStream ( filePath )
241
233
form . append ( "file" , fileStream , fileName )
242
234
} else {
243
235
// Use buffer for small files
244
236
log . debug ( { fileName, fileSize } , "using buffer upload for small file" )
245
- const fileContent = await readFile ( _filePath )
237
+ const fileContent = await readFile ( filePath )
246
238
form . append ( "file" , fileContent , fileName )
247
239
}
248
240
@@ -267,12 +259,7 @@ export class GitlabPublisher extends HttpPublisher {
267
259
return JSON . parse ( response )
268
260
}
269
261
270
- private async uploadToGenericPackages (
271
- fileName : string ,
272
- dataLength : number ,
273
- requestProcessor : ( request : ClientRequest , reject : ( error : Error ) => void ) => void ,
274
- _filePath : string
275
- ) : Promise < any > {
262
+ private async uploadToGenericPackages ( fileName : string , dataLength : number , requestProcessor : RequestProcessor ) : Promise < any > {
276
263
const uploadUrl = `${ this . baseApiPath } /projects/${ encodeURIComponent ( this . projectId ) } /packages/generic/releases/${ this . version } /${ fileName } `
277
264
const parsedUrl = new URL ( uploadUrl )
278
265
@@ -294,6 +281,10 @@ export class GitlabPublisher extends HttpPublisher {
294
281
)
295
282
}
296
283
284
+ private buildProjectUrl ( path : string = "" ) : URL {
285
+ return new URL ( `${ this . baseApiPath } /projects/${ encodeURIComponent ( this . projectId ) } ${ path } ` )
286
+ }
287
+
297
288
private resolveProjectId ( ) : string {
298
289
if ( this . info . projectId ) {
299
290
return String ( this . info . projectId )
0 commit comments