Commit 311bd03689

311bd03689a6311dd7a187b26f1ecd92c31f25f4

parent: 9f7b9fe809

Verified · cmc

cmc <hello@cleberg.net> · 2026-09-07 01:08 UTC

Fix final-review findings on repo deps settings

Pull-to-refresh now reloads the deps report alongside settings, the
enable/disable reload test asserts the reload actually landed instead
of only checking argv, the toggle no longer draws when the status read
has failed, the explanation moved to the section footer, the
last-check timestamp is labeled, the unused section parameter is
dropped, and a converse success-then-failure test pins that a later
failure clears stale deps state.

Layout: unified · split

gitbay/Views/Repos/RepoSettingsView.swift +14 −12
@@ -29,7 +29,7 @@ struct RepoSettingsView: View {
2929 branchesSection(loaded)
3030 mergeRulesSection(loaded)
3131 daemonSection(loaded)
32 depsSection(loaded)
32 depsSection()
3333 }
3434 }
3535 .overlay { LoadStateOverlay(state: model.state) }
@@ -44,7 +44,10 @@ struct RepoSettingsView: View {
4444 }
4545 }
4646 .task { await model.loadDeps() }
47 .refreshable { await model.load() }
47 .refreshable {
48 await model.load()
49 await model.loadDeps()
50 }
4851 }
4952
5053 // MARK: - Sections
@@ -208,20 +211,17 @@ struct RepoSettingsView: View {
208211 }
209212 }
210213
211 private func depsSection(_ loaded: RepoSettingsViewModel.Loaded) -> some View {
214 private func depsSection() -> some View {
212215 Section {
213 SettingToggle(title: "Dependency checks", serverValue: model.deps?.enabled ?? false) {
214 await model.setDepsEnabled($0)
215 }
216 .disabled(model.deps == nil || model.working)
217 Text("Checks tell a public registry what this repository depends on.")
218 .font(.gbSans(.caption))
219 .foregroundStyle(.secondary)
220
221216 if let deps = model.deps {
217 SettingToggle(title: "Dependency checks", serverValue: deps.enabled) {
218 await model.setDepsEnabled($0)
219 }
220 .disabled(model.working)
221
222222 if deps.enabled {
223223 if let lastCheck = deps.lastCheck {
224 Text(lastCheck, format: .relative(presentation: .named))
224 (Text("Last checked ") + Text(lastCheck, format: .relative(presentation: .named)))
225225 .font(.gbSans(.caption))
226226 .foregroundStyle(.secondary)
227227 } else {
@@ -266,6 +266,8 @@ struct RepoSettingsView: View {
266266 }
267267 } header: {
268268 Text("Dependencies")
269 } footer: {
270 Text("Checks tell a public registry what this repository depends on.")
269271 }
270272 }
271273
gitbayTests/DepsTests.swift +22
@@ -112,6 +112,9 @@ struct DepsActionTests {
112112 await model.setDepsEnabled(true)
113113 var write = try #require(stub.seen.first { $0.method == "POST" })
114114 #expect(try argvOf(write) == ["repo", "deps", "enable", "krz/gitbay"])
115 // The write must reload deps specifically, not the whole settings
116 // screen — otherwise this enqueued status stub goes unconsumed.
117 #expect(model.deps?.enabled == true)
115118
116119 let (client2, stub2) = try makeClient()
117120 let model2 = RepoSettingsViewModel(client: client2, repoPath: "krz/gitbay")
@@ -122,6 +125,7 @@ struct DepsActionTests {
122125 await model2.setDepsEnabled(false)
123126 write = try #require(stub2.seen.first { $0.method == "POST" })
124127 #expect(try argvOf(write) == ["repo", "deps", "disable", "krz/gitbay"])
128 #expect(model2.deps?.enabled == true)
125129 }
126130
127131 /// "Could not ask" must not render as "checks are off".
@@ -170,4 +174,22 @@ struct DepsActionTests {
170174 #expect(model.depsError == nil)
171175 #expect(model.deps?.enabled == true)
172176 }
177
178 /// The converse of the above: a later failure must drop the stale
179 /// status, not leave it sitting alongside the new error.
180 @Test func depsClearsOnALaterFailureAfterASuccess() async throws {
181 let (client, stub) = try makeClient()
182 stub.enqueue(.init(status: 200, json: fullStatus))
183 let model = RepoSettingsViewModel(client: client, repoPath: "krz/gitbay")
184 await model.loadDeps()
185 #expect(model.deps?.enabled == true)
186
187 stub.enqueue(.init(status: 200, json: """
188 {"protocol_version":1,"error":"denied","exit_code":4}
189 """))
190 await model.loadDeps()
191
192 #expect(model.deps == nil)
193 #expect(model.depsError?.isEmpty == false)
194 }
173195}