Skip to content

Commit 3ca64f5

Browse files
committed
Fixed query item issue in GitLab. Refactored query item handling.
1 parent 6315988 commit 3ca64f5

File tree

7 files changed

+70
-43
lines changed

7 files changed

+70
-43
lines changed

CCMenu.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
034ED9C72F2A602D00C7793E /* GitLabPipelineLocalhost.json in Resources */ = {isa = PBXBuildFile; fileRef = 034ED9C62F2A602D00C7793E /* GitLabPipelineLocalhost.json */; };
4343
034ED9C92F2A604600C7793E /* GitLabPipelineRunsResponse.json in Resources */ = {isa = PBXBuildFile; fileRef = 034ED9C82F2A604600C7793E /* GitLabPipelineRunsResponse.json */; };
4444
034ED9CF2F2A646100C7793E /* GitLabPipelineDetailsResponse.json in Resources */ = {isa = PBXBuildFile; fileRef = 034ED9CE2F2A646100C7793E /* GitLabPipelineDetailsResponse.json */; };
45+
034ED9D12F2A77DB00C7793E /* URLExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034ED9D02F2A77D200C7793E /* URLExtensions.swift */; };
4546
035F86FE2BB37A6600AD1D68 /* CCTrayAuthView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035F86FD2BB37A6600AD1D68 /* CCTrayAuthView.swift */; };
4647
035F87022BB3829300AD1D68 /* PipelineListMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035F87012BB3829300AD1D68 /* PipelineListMenu.swift */; };
4748
035F87062BB4D53600AD1D68 /* SignInAtGitHubSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 035F87052BB4D53600AD1D68 /* SignInAtGitHubSheet.swift */; };
@@ -61,7 +62,6 @@
6162
038FF7122BB6130C0017CD4C /* GitHubBranchList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038FF7112BB6130C0017CD4C /* GitHubBranchList.swift */; };
6263
038FF7142BB6212D0017CD4C /* GitHubBranchesResponse.json in Resources */ = {isa = PBXBuildFile; fileRef = 038FF7132BB6212D0017CD4C /* GitHubBranchesResponse.json */; };
6364
038FF7162BB62E6D0017CD4C /* GitHubReposByUserCCM2OnlyResponse.json in Resources */ = {isa = PBXBuildFile; fileRef = 038FF7152BB62E6D0017CD4C /* GitHubReposByUserCCM2OnlyResponse.json */; };
64-
038FF7182BB631CB0017CD4C /* URLComponentsExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 038FF7172BB631CB0017CD4C /* URLComponentsExtension.swift */; };
6565
039B524629676D0700994910 /* Build.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039B524529676D0700994910 /* Build.swift */; };
6666
03A3EF932D3459D400407A6F /* GitHubUserResponse.json in Resources */ = {isa = PBXBuildFile; fileRef = 03A3EF922D3459D400407A6F /* GitHubUserResponse.json */; };
6767
03A3EF942D3459D400407A6F /* GitHubUserOrgResponse.json in Resources */ = {isa = PBXBuildFile; fileRef = 03A3EF912D3459D400407A6F /* GitHubUserOrgResponse.json */; };
@@ -182,6 +182,7 @@
182182
034ED9C62F2A602D00C7793E /* GitLabPipelineLocalhost.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = GitLabPipelineLocalhost.json; sourceTree = "<group>"; };
183183
034ED9C82F2A604600C7793E /* GitLabPipelineRunsResponse.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = GitLabPipelineRunsResponse.json; sourceTree = "<group>"; };
184184
034ED9CE2F2A646100C7793E /* GitLabPipelineDetailsResponse.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = GitLabPipelineDetailsResponse.json; sourceTree = "<group>"; };
185+
034ED9D02F2A77D200C7793E /* URLExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLExtensions.swift; sourceTree = "<group>"; };
185186
035F86FD2BB37A6600AD1D68 /* CCTrayAuthView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CCTrayAuthView.swift; sourceTree = "<group>"; };
186187
035F87012BB3829300AD1D68 /* PipelineListMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PipelineListMenu.swift; sourceTree = "<group>"; };
187188
035F87052BB4D53600AD1D68 /* SignInAtGitHubSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInAtGitHubSheet.swift; sourceTree = "<group>"; };
@@ -201,7 +202,6 @@
201202
038FF7112BB6130C0017CD4C /* GitHubBranchList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitHubBranchList.swift; sourceTree = "<group>"; };
202203
038FF7132BB6212D0017CD4C /* GitHubBranchesResponse.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GitHubBranchesResponse.json; sourceTree = "<group>"; };
203204
038FF7152BB62E6D0017CD4C /* GitHubReposByUserCCM2OnlyResponse.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = GitHubReposByUserCCM2OnlyResponse.json; sourceTree = "<group>"; };
204-
038FF7172BB631CB0017CD4C /* URLComponentsExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLComponentsExtension.swift; sourceTree = "<group>"; };
205205
039B524529676D0700994910 /* Build.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Build.swift; sourceTree = "<group>"; };
206206
03A3EF912D3459D400407A6F /* GitHubUserOrgResponse.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = GitHubUserOrgResponse.json; sourceTree = "<group>"; };
207207
03A3EF922D3459D400407A6F /* GitHubUserResponse.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = GitHubUserResponse.json; sourceTree = "<group>"; };
@@ -547,7 +547,7 @@
547547
031FC8CB2B7929B7005E7F26 /* Keychain.swift */,
548548
03CC61D02BA783EE0008EE76 /* NetworkMonitor.swift */,
549549
03CC61CE2BA757050008EE76 /* TrustManager.swift */,
550-
038FF7172BB631CB0017CD4C /* URLComponentsExtension.swift */,
550+
034ED9D02F2A77D200C7793E /* URLExtensions.swift */,
551551
3CB911D62B78E891009DF781 /* URLRequestExtension.swift */,
552552
3CB911D42B7142A0009DF781 /* URLSessionExtension.swift */,
553553
037AB214297334EE00C33589 /* UserDefaultsExtension.swift */,
@@ -827,8 +827,8 @@
827827
03DD697E2B646E3800D7AD9D /* NSColorExtensions.swift in Sources */,
828828
03BD7EFA259A180C000F9495 /* NSImageExtension.swift in Sources */,
829829
03825DFA259D0ACF00DEB003 /* PipelineListView.swift in Sources */,
830-
038FF7182BB631CB0017CD4C /* URLComponentsExtension.swift in Sources */,
831830
03825DF2259D01C600DEB003 /* PipelineRow.swift in Sources */,
831+
034ED9D12F2A77DB00C7793E /* URLExtensions.swift in Sources */,
832832
0362EBED2B521BD50079DEFE /* NotificationFactory.swift in Sources */,
833833
03CC61D12BA783EE0008EE76 /* NetworkMonitor.swift in Sources */,
834834
03825DE3259CFF0A00DEB003 /* Pipeline.swift in Sources */,

CCMenu/Source/Miscellaneous/URLComponentsExtension.swift

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright (c) Erik Doernenburg and contributors
3+
* Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
* not use these files except in compliance with the License.
5+
*/
6+
7+
import Foundation
8+
9+
extension URL {
10+
11+
func removing(queryItem: String) -> URL {
12+
var c = URLComponents(url: self, resolvingAgainstBaseURL: true)!
13+
c.removeQueryItem(name: queryItem)
14+
return c.url!.absoluteURL
15+
}
16+
17+
}
18+
19+
private extension URLComponents {
20+
21+
mutating func removeQueryItem(name: String) {
22+
guard var tempItems = queryItems else { return }
23+
tempItems = tempItems.filter { $0.name != name }
24+
queryItems = tempItems.isEmpty ? nil : tempItems
25+
}
26+
27+
}
28+

CCMenu/Source/Server Monitor/GitHubAPI.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,18 +102,16 @@ class GitHubAPI {
102102

103103
static func feedUrl(owner: String, repository: String, workflow: String, branch: String?) -> URL {
104104
// see https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-workflow
105-
let url = baseURL(forAPI: true).appending(path: "/repos/\(owner)/\(repository)/actions/workflows/\(workflow)/runs")
106-
var components = URLComponents(url: url, resolvingAgainstBaseURL: true)!
105+
var url = baseURL(forAPI: true).appending(path: "/repos/\(owner)/\(repository)/actions/workflows/\(workflow)/runs")
107106
if let branch {
108-
components.appendQueryItem(URLQueryItem(name: "branch", value: branch))
107+
url = url.appending(queryItems: [URLQueryItem(name: "branch", value: branch)])
109108
}
110-
return components.url!.absoluteURL
109+
return url
111110
}
112111

113112
static func requestForFeed(feed: PipelineFeed, token: String?) -> URLRequest? {
114-
guard var components = URLComponents(url: feed.url, resolvingAgainstBaseURL: true) else { return nil }
115-
components.appendQueryItem(URLQueryItem(name: "per_page", value: "3"))
116-
return makeRequest(url: components.url!.absoluteURL, token: token)
113+
let url = feed.url.appending(queryItems: [URLQueryItem(name: "per_page", value: "3")])
114+
return makeRequest(url: url, token: token)
117115
}
118116

119117

CCMenu/Source/Server Monitor/GitLabAPI.swift

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,24 +101,22 @@ class GitLabAPI {
101101
// MARK: - feed
102102

103103
static func feedUrl(projectId: String, branch: String?) -> URL {
104-
let url = baseURL(forAPI: true).appending(path: "/projects/\(projectId)/pipelines")
105-
106-
var components = URLComponents(url: url, resolvingAgainstBaseURL: true)!
104+
var url = baseURL(forAPI: true).appending(path: "/projects/\(projectId)/pipelines")
107105
if let branch {
108-
components.appendQueryItem(URLQueryItem(name: "ref", value: branch))
106+
url = url.appending(queryItems: [URLQueryItem(name: "ref", value: branch)])
109107
}
110-
return components.url!.absoluteURL
108+
return url
111109
}
112110

113111
static func requestForFeed(feed: PipelineFeed, token: String?) -> URLRequest? {
114-
guard var components = URLComponents(url: feed.url, resolvingAgainstBaseURL: true) else { return nil }
115-
components.appendQueryItem(URLQueryItem(name: "per_page", value: "3"))
116-
return makeRequest(url: components.url!.absoluteURL, token: token)
112+
let url = feed.url.appending(queryItems: [URLQueryItem(name: "per_page", value: "3")])
113+
return makeRequest(url: url, token: token)
117114
}
118115

119116
static func requestForDetail(feed: PipelineFeed, pipelineId: String, token: String?) -> URLRequest? {
120-
// TODO: double check that this works with query params (for branches)
121-
let url = feed.url.appendingPathComponent(pipelineId)
117+
var url = feed.url
118+
url = url.removing(queryItem: "ref")
119+
url = url.appending(path: "\(pipelineId)")
122120
return makeRequest(url: url, token: token)
123121
}
124122

CCMenuTests/GitHubAPITests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class GitHubAPITests: XCTestCase {
3434
UserDefaults.active = UserDefaults.transient
3535
UserDefaults.active.set("https://dev.some-enterprise.com/github", forKey: "GitHubAPIBaseURL")
3636
let request = GitHubAPI.requestForUser(user: "testuser", token: nil)
37+
UserDefaults.active = UserDefaults.standard
3738

3839
XCTAssertEqual("/github/users/testuser", request.url?.path())
3940
}

CCMenuTests/GitLabAPITests.swift

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,34 @@ import XCTest
1010
class GitLabAPITests: XCTestCase {
1111

1212
func testConstructsRequestForFeed() throws {
13-
let feed = PipelineFeed(type: .gitlab, url: URL(string: "https://example.com/api")!)
13+
let feedUrl = GitLabAPI.feedUrl(projectId: "31415926", branch: nil)
14+
let feed = PipelineFeed(type: .gitlab, url: feedUrl)
1415
let request = GitLabAPI.requestForFeed(feed: feed, token: nil)
1516

1617
guard let request else { XCTFail(); return }
1718
XCTAssertEqual("GET", request.httpMethod)
19+
let url = request.url?.absoluteString
20+
XCTAssertEqual("https://gitlab.com/api/v4/projects/31415926/pipelines?per_page=3", url)
21+
}
22+
23+
func testConstructsRequestForFeedWithBranch() throws {
24+
let feedUrl = GitLabAPI.feedUrl(projectId: "31415926", branch: "main")
25+
let feed = PipelineFeed(type: .gitlab, url: feedUrl)
26+
let request = GitLabAPI.requestForFeed(feed: feed, token: nil)
27+
28+
guard let request else { XCTFail(); return }
1829
let url = request.url?.absoluteString ?? ""
19-
XCTAssertTrue(url.hasPrefix("https://example.com/api"))
20-
XCTAssertTrue(url.contains("per_page="))
30+
XCTAssertTrue(url.contains("ref=main"))
31+
}
32+
33+
func testConstructsRequestForPipelineDetailsAndDoesNotIncludeBranch() throws {
34+
let feedUrl = GitLabAPI.feedUrl(projectId: "31415926", branch: "main")
35+
let feed = PipelineFeed(type: .gitlab, url: feedUrl)
36+
let request = GitLabAPI.requestForDetail(feed: feed, pipelineId: "12345", token: nil)
37+
38+
guard let request else { XCTFail(); return }
39+
let url = request.url?.absoluteString
40+
XCTAssertEqual("https://gitlab.com/api/v4/projects/31415926/pipelines/12345", url)
2141
}
2242

2343
func testAddsAuthorizationHeaderWhenTokenIsGiven() throws {
@@ -32,6 +52,7 @@ class GitLabAPITests: XCTestCase {
3252
UserDefaults.active = UserDefaults.transient
3353
UserDefaults.active.set("https://dev.some-enterprise.com/gitlab/api/v4", forKey: "GitLabAPIBaseURL")
3454
let request = GitLabAPI.requestForUser(token: "TEST-TOKEN")
55+
UserDefaults.active = UserDefaults.standard
3556

3657
XCTAssertEqual("/gitlab/api/v4/user", request.url?.path())
3758
}

0 commit comments

Comments
 (0)