Skip to content

Commit 2d18173

Browse files
committed
Added fallback to feed with workflow ID. Fixes #17.
1 parent c73dce6 commit 2d18173

File tree

4 files changed

+92
-6
lines changed

4 files changed

+92
-6
lines changed

CCMenu/Source/Pipeline Window/GitHub Sheets/AddGitHubPipelineSheet.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,12 @@ struct AddGitHubPipelineSheet: View {
128128
}
129129
.keyboardShortcut(.cancelAction)
130130
Button("Apply") {
131-
if let p = builder.makePipeline() {
132-
config.setPipeline(p)
133-
presentation.dismiss()
131+
Task {
132+
if let p = await builder.makePipeline() {
133+
config.setPipeline(p)
134+
presentation.dismiss()
135+
}
136+
// TODO: show error
134137
}
135138
}
136139
.keyboardShortcut(.defaultAction)

CCMenu/Source/Pipeline Window/GitHub Sheets/GitHubPipelineBuilder.swift

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,57 @@ class GitHubPipelineBuilder: ObservableObject {
2525
}
2626

2727
var canMakePipeline: Bool {
28-
return makePipeline() != nil
28+
guard !name.isEmpty else { return false }
29+
guard let owner else { return false }
30+
guard let repository, repository.isValid else { return false }
31+
guard let workflow, workflow.isValid else { return false }
32+
guard let branch, branch.isValid else { return false }
33+
return true
2934
}
3035

31-
func makePipeline() -> Pipeline? {
36+
func makePipeline() async -> Pipeline? {
3237
guard !name.isEmpty else { return nil }
3338
guard let owner else { return nil }
3439
guard let repository, repository.isValid else { return nil }
3540
guard let workflow, workflow.isValid else { return nil }
3641
guard let branch, branch.isValid else { return nil }
3742
let branchName = branch.isAllBranchPlaceholder ? nil : branch.name
38-
let url = GitHubAPI.feedUrl(owner: owner, repository: repository.name, workflow: workflow.filename, branch: branchName)
43+
44+
var url: URL? = nil
45+
let workflowPathComponents = [ workflow.filename, String(workflow.id) ]
46+
for wfid in workflowPathComponents {
47+
url = GitHubAPI.feedUrl(owner: owner, repository: repository.name, workflow: wfid, branch: branchName)
48+
if let url, let result = await fetchRuns(url: url), result == 200 {
49+
break
50+
}
51+
url = nil
52+
}
53+
guard let url else {
54+
return nil
55+
}
56+
3957
let feed = PipelineFeed(type: .github, url:url)
4058
let pipeline = Pipeline(name: name, feed: feed)
4159
return pipeline
4260
}
4361

62+
private func fetchRuns(url: URL) async -> Int? {
63+
let feed = PipelineFeed(type: .github, url:url)
64+
guard let request = GitHubAPI.requestForFeed(feed: feed, token: nil) else {
65+
return nil
66+
}
67+
let result = await fetchRuns(request: request)
68+
return result
69+
}
70+
71+
private func fetchRuns(request: URLRequest) async -> Int? {
72+
do {
73+
let (data, response) = try await URLSession.feedSession.data(for: request)
74+
guard let response = response as? HTTPURLResponse else { throw URLError(.unsupportedURL) }
75+
return response.statusCode
76+
} catch {
77+
return nil
78+
}
79+
}
4480
}
4581

CCMenu/Source/Server Monitor/GitHubAPI.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ class GitHubAPI {
8080
// MARK: - feed
8181

8282
static func feedUrl(owner: String, repository: String, workflow: String, branch: String?) -> URL {
83+
// see https://docs.github.com/en/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-workflow
8384
var components = URLComponents(string: baseURL(forAPI: true))!
8485
components.path = String(format: "/repos/%@/%@/actions/workflows/%@/runs", owner, repository, workflow)
8586
if let branch {

CCMenuUITests/GitHubTests.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,52 @@ class GitHubTests: XCTestCase {
129129
waitForExpectations(timeout: 5)
130130
}
131131

132+
func testAddsGitHubPipelineByIdIfNeccessary() throws {
133+
webapp.router.get("/users/erikdoe/repos") { _ in
134+
try TestHelper.contentsOfFile("GitHubReposByUserCCM2OnlyResponse.json")
135+
}
136+
webapp.router.get("/repos/erikdoe/ccmenu2/actions/workflows") { _ in
137+
try TestHelper.contentsOfFile("GitHubWorkflowsResponse.json")
138+
}
139+
webapp.router.get("/repos/erikdoe/ccmenu2/branches") { _ in
140+
try TestHelper.contentsOfFile("GitHubBranchesResponse.json")
141+
}
142+
webapp.router.get("/repos/erikdoe/ccmenu2/actions/workflows/build-and-test.yaml/runs", options: .editResponse) { r in
143+
r.response.status = .notFound
144+
return "{ } "
145+
}
146+
webapp.router.get("/repos/erikdoe/ccmenu2/actions/workflows/62921699/runs") { _ in
147+
try TestHelper.contentsOfFile("GitHubWorkflowRunsResponse.json")
148+
}
149+
150+
let app = TestHelper.launchApp(pipelines: "EmptyPipelines.json", pauseMonitor: false)
151+
let window = app.windows["Pipelines"]
152+
let sheet = window.sheets.firstMatch
153+
154+
// Navigate to add workflow sheet
155+
window.toolbars.popUpButtons["Add pipeline menu"].click()
156+
window.toolbars.menuItems["Add GitHub Actions workflow..."].click()
157+
158+
// Enter owner
159+
sheet.textFields["Owner field"].click()
160+
sheet.typeText("erikdoe" + "\n")
161+
162+
let repositoryPicker = sheet.popUpButtons["Repository picker"]
163+
expectation(for: NSPredicate(format: "value == 'ccmenu2'"), evaluatedWith: repositoryPicker)
164+
let workflowPicker = sheet.popUpButtons["Workflow picker"]
165+
expectation(for: NSPredicate(format: "value == 'Build and test'"), evaluatedWith: workflowPicker)
166+
waitForExpectations(timeout: 5)
167+
168+
sheet.buttons["Apply"].click()
169+
170+
// Make sure the pipeline is shown, and that its status is fetched immediately
171+
let titleText = window.tables.staticTexts["Pipeline title"]
172+
expectation(for: NSPredicate(format: "value BEGINSWITH 'ccmenu2'"), evaluatedWith: titleText)
173+
let descriptionText = window.tables.staticTexts["Status description"]
174+
expectation(for: NSPredicate(format: "value CONTAINS 'Label: 42'"), evaluatedWith: descriptionText)
175+
waitForExpectations(timeout: 5)
176+
}
177+
132178
func testAddsGitHubPipelineWithBranch() throws {
133179
var branchParam: String?
134180
webapp.router.get("/users/erikdoe/repos") { _ in

0 commit comments

Comments
 (0)