Commit d7fac80c5f
Verified · cmc
Layout: unified · split
gitbay/Repos/WebhookViewModels.swift +6 −5
| @@ -28,17 +28,18 @@ final class WebhookListViewModel { | |||
| 28 | } | 28 | } |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | /// `webhook add <repo> <url> [--secret <s>] [--events <e>]` — an empty | 31 | /// `webhook add <repo> <url> [--secret -] [--events <e>]` — an empty |
| 32 | /// secret or event list is left out, so the server applies its default. | 32 | /// secret or event list is left out, so the server applies its default. |
| 33 | /// The secret travels on stdin; the server refuses it in argv. | ||
| 33 | func add(url: String, secret: String, events: String) async -> Bool { | 34 | func add(url: String, secret: String, events: String) async -> Bool { |
| 34 | let url = url.trimmingCharacters(in: .whitespaces) | 35 | let url = url.trimmingCharacters(in: .whitespaces) |
| 35 | guard !url.isEmpty else { return false } | 36 | guard !url.isEmpty else { return false } |
| 36 | var argv = ["webhook", "add", repoPath, url] | 37 | var argv = ["webhook", "add", repoPath, url] |
| 37 | let secret = secret.trimmingCharacters(in: .whitespaces) | 38 | let secret = secret.trimmingCharacters(in: .whitespaces) |
| 38 | if !secret.isEmpty { argv += ["--secret", secret] } | 39 | if !secret.isEmpty { argv += ["--secret", "-"] } |
| 39 | let events = events.trimmingCharacters(in: .whitespaces) | 40 | let events = events.trimmingCharacters(in: .whitespaces) |
| 40 | if !events.isEmpty { argv += ["--events", events] } | 41 | if !events.isEmpty { argv += ["--events", events] } |
| 41 | await perform(argv) | 42 | await perform(argv, stdin: secret.isEmpty ? nil : secret + "\n") |
| 42 | return actionError == nil | 43 | return actionError == nil |
| 43 | } | 44 | } |
| 44 | 45 | ||
| @@ -46,12 +47,12 @@ final class WebhookListViewModel { | |||
| 46 | await perform(["webhook", "remove", repoPath, String(id)]) | 47 | await perform(["webhook", "remove", repoPath, String(id)]) |
| 47 | } | 48 | } |
| 48 | 49 | ||
| 49 | private func perform(_ argv: [String]) async { | 50 | private func perform(_ argv: [String], stdin: String? = nil) async { |
| 50 | working = true | 51 | working = true |
| 51 | actionError = nil | 52 | actionError = nil |
| 52 | defer { working = false } | 53 | defer { working = false } |
| 53 | do { | 54 | do { |
| 54 | try await client.run(argv) | 55 | try await client.run(argv, stdin: stdin) |
| 55 | await load() | 56 | await load() |
| 56 | } catch let error as GitbayError { | 57 | } catch let error as GitbayError { |
| 57 | actionError = error.userFacingMessage | 58 | actionError = error.userFacingMessage |
gitbayTests/WebhookTests.swift +8 −1
| @@ -17,6 +17,11 @@ private func argvOf(_ seen: StubProtocol.Seen) throws -> [String] { | |||
| 17 | return try #require(body["argv"] as? [String]) | 17 | return try #require(body["argv"] as? [String]) |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | private func stdinOf(_ seen: StubProtocol.Seen) throws -> String? { | ||
| 21 | let body = try #require(try JSONSerialization.jsonObject(with: seen.body) as? [String: Any]) | ||
| 22 | return body["stdin"] as? String | ||
| 23 | } | ||
| 24 | |||
| 20 | private let okJSON = #"{"protocol_version":1,"data":{},"exit_code":0}"# | 25 | private let okJSON = #"{"protocol_version":1,"data":{},"exit_code":0}"# |
| 21 | 26 | ||
| 22 | private let hooksJSON = """ | 27 | private let hooksJSON = """ |
| @@ -81,9 +86,11 @@ struct WebhookListViewModelTests { | |||
| 81 | #expect(first && second) | 86 | #expect(first && second) |
| 82 | let writes = try stub.seen.filter { $0.method == "POST" }.map(argvOf) | 87 | let writes = try stub.seen.filter { $0.method == "POST" }.map(argvOf) |
| 83 | #expect(writes == [ | 88 | #expect(writes == [ |
| 84 | ["webhook", "add", "krz/gitbay", "https://a.example/h", "--secret", "s3", "--events", "push"], | 89 | ["webhook", "add", "krz/gitbay", "https://a.example/h", "--secret", "-", "--events", "push"], |
| 85 | ["webhook", "add", "krz/gitbay", "https://b.example/h"], | 90 | ["webhook", "add", "krz/gitbay", "https://b.example/h"], |
| 86 | ]) | 91 | ]) |
| 92 | let posts = stub.seen.filter { $0.method == "POST" } | ||
| 93 | #expect(try posts.map(stdinOf) == ["s3\n", nil]) | ||
| 87 | } | 94 | } |
| 88 | 95 | ||
| 89 | @Test func removeSendsTheIdThenReloads() async throws { | 96 | @Test func removeSendsTheIdThenReloads() async throws { |