@@ -23,15 +23,16 @@ enum Gitlab {
2323 enum Error : LocalizedError {
2424 case missingConfiguration( String )
2525 case missingToken
26- case requestFailed( HTTPStatus , URI )
26+ case noBody
27+ case requestFailed( status: HTTPStatus , url: String )
2728 }
2829
29- static let decoder : JSONDecoder = {
30+ static var decoder : JSONDecoder {
3031 let d = JSONDecoder ( )
3132 d. keyDecodingStrategy = . convertFromSnakeCase
3233 d. dateDecodingStrategy = . formatted( DateFormatter . iso8601Full)
3334 return d
34- } ( )
35+ }
3536
3637}
3738
@@ -69,15 +70,15 @@ extension Gitlab.Builder {
6970 }
7071 }
7172
72- static func triggerBuild( client: Client ,
73- buildId: Build . Id ,
73+ static func triggerBuild( buildId: Build . Id ,
7474 cloneURL: String ,
7575 isDocBuild: Bool ,
7676 platform: Build . Platform ,
7777 reference: Reference ,
7878 swiftVersion: SwiftVersion ,
7979 versionID: Version . Id ) async throws -> Build . TriggerResponse {
8080 @Dependency ( \. environment) var environment
81+ @Dependency ( \. httpClient) var httpClient
8182
8283 guard let pipelineToken = environment. gitlabPipelineToken ( ) ,
8384 let builderToken = environment. builderToken ( )
@@ -88,31 +89,33 @@ extension Gitlab.Builder {
8889 }
8990 let timeout = environment. buildTimeout ( ) + ( isDocBuild ? 5 : 0 )
9091
91- let uri : URI = . init( string: " \( projectURL) /trigger/pipeline " )
92- let response = try await client
93- . post ( uri) { req in
94- let data = PostDTO (
95- token: pipelineToken,
96- ref: branch,
97- variables: [
98- " API_BASEURL " : SiteURL . apiBaseURL,
99- " AWS_DOCS_BUCKET " : awsDocsBucket,
100- " BUILD_ID " : buildId. uuidString,
101- " BUILD_PLATFORM " : platform. rawValue,
102- " BUILDER_TOKEN " : builderToken,
103- " CLONE_URL " : cloneURL,
104- " REFERENCE " : " \( reference) " ,
105- " SWIFT_VERSION " : " \( swiftVersion. major) . \( swiftVersion. minor) " ,
106- " TIMEOUT " : " \( timeout) m " ,
107- " VERSION_ID " : versionID. uuidString
108- ] )
109- try req. query. encode ( data)
110- }
92+ let dto = PostDTO (
93+ token: pipelineToken,
94+ ref: branch,
95+ variables: [
96+ " API_BASEURL " : SiteURL . apiBaseURL,
97+ " AWS_DOCS_BUCKET " : awsDocsBucket,
98+ " BUILD_ID " : buildId. uuidString,
99+ " BUILD_PLATFORM " : platform. rawValue,
100+ " BUILDER_TOKEN " : builderToken,
101+ " CLONE_URL " : cloneURL,
102+ " REFERENCE " : " \( reference) " ,
103+ " SWIFT_VERSION " : " \( swiftVersion. major) . \( swiftVersion. minor) " ,
104+ " TIMEOUT " : " \( timeout) m " ,
105+ " VERSION_ID " : versionID. uuidString
106+ ]
107+ )
108+ let body = try URLEncodedFormEncoder ( ) . encode ( dto)
109+ let response = try await httpClient. post (
110+ url: " \( projectURL) /trigger/pipeline " ,
111+ headers: . contentTypeFormURLEncoded,
112+ body: Data ( body. utf8)
113+ )
114+
111115 do {
112- let res = Build . TriggerResponse (
113- status: response. status,
114- webUrl: try response. content. decode ( Response . self) . webUrl
115- )
116+ guard let body = response. body else { throw Gitlab . Error. noBody }
117+ let webUrl = try JSONDecoder ( ) . decode ( Response . self, from: body) . webUrl
118+ let res = Build . TriggerResponse ( status: response. status, webUrl: webUrl)
116119 Current . logger ( ) . info ( " Triggered build: \( res. webUrl) " )
117120 return res
118121 } catch {
@@ -154,30 +157,31 @@ extension Gitlab.Builder {
154157 }
155158
156159 // https://docs.gitlab.com/ee/api/pipelines.html
157- static func fetchPipelines( client: Client ,
158- status: Status ,
160+ static func fetchPipelines( status: Status ,
159161 page: Int ,
160162 pageSize: Int = 20 ) async throws -> [ Pipeline ] {
161163 @Dependency ( \. environment) var environment
164+ @Dependency ( \. httpClient) var httpClient
162165 guard let apiToken = environment. gitlabApiToken ( ) else { throw Gitlab . Error. missingToken }
166+ let url = " \( projectURL) /pipelines?status= \( status) &page= \( page) &per_page= \( pageSize) "
163167
164- let uri : URI = . init( string: " \( projectURL) /pipelines?status= \( status) &page= \( page) &per_page= \( pageSize) " )
165- let response = try await client. get ( uri, headers: . bearer( apiToken) )
168+ let response = try await httpClient. get ( url: url, headers: . bearer( apiToken) )
166169
167- guard response. status == . ok else { throw Gitlab . Error. requestFailed ( response. status, uri) }
170+ guard response. status == . ok else {
171+ throw Gitlab . Error. requestFailed ( status: response. status, url: url)
172+ }
173+ guard let body = response. body else { throw Gitlab . Error. noBody }
168174
169- return try response . content . decode ( [ Pipeline ] . self, using : Gitlab . decoder )
175+ return try Gitlab . decoder . decode ( [ Pipeline ] . self, from : body )
170176 }
171177
172- static func getStatusCount( client: Client ,
173- status: Status ,
178+ static func getStatusCount( status: Status ,
174179 page: Int = 1 ,
175180 pageSize: Int = 20 ,
176181 maxPageCount: Int = 5 ) async throws -> Int {
177- let count = try await fetchPipelines ( client : client , status: status, page: page, pageSize: pageSize) . count
182+ let count = try await fetchPipelines ( status: status, page: page, pageSize: pageSize) . count
178183 if count == pageSize && page < maxPageCount {
179- let statusCount = try await getStatusCount ( client: client,
180- status: status,
184+ let statusCount = try await getStatusCount ( status: status,
181185 page: page + 1 ,
182186 pageSize: pageSize,
183187 maxPageCount: maxPageCount)
@@ -205,6 +209,10 @@ private extension HTTPHeaders {
205209 static func bearer( _ token: String ) -> Self {
206210 . init( [ ( " Authorization " , " Bearer \( token) " ) ] )
207211 }
212+
213+ static var contentTypeFormURLEncoded : Self {
214+ . init( [ ( " Content-Type " , " application/x-www-form-urlencoded " ) ] )
215+ }
208216}
209217
210218
0 commit comments