Skip to content

Commit 9df4000

Browse files
Merge pull request #3612 from SwiftPackageIndex/issue-3469-dependency-transition-18
Issue 3469 dependency transition 18
2 parents 0624da0 + 94ac2a1 commit 9df4000

19 files changed

+158
-113
lines changed

Sources/App/Commands/Alerting.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,8 @@ extension [Alerting.BuildInfo] {
245245
}
246246

247247
func validateRunnerIdsPresent() -> Alerting.Validation {
248-
var notSeen = Set(Current.runnerIds())
248+
@Dependency(\.environment) var environment
249+
var notSeen = Set(environment.runnerIds())
249250
for build in self where build.runnerId != nil {
250251
notSeen.remove(build.runnerId!)
251252
if notSeen.isEmpty { return .ok }
@@ -254,7 +255,8 @@ extension [Alerting.BuildInfo] {
254255
}
255256

256257
func validateRunnerIdsSuccessful() -> Alerting.Validation {
257-
var noSuccess = Set(Current.runnerIds())
258+
@Dependency(\.environment) var environment
259+
var noSuccess = Set(environment.runnerIds())
258260
for build in self where build.runnerId != nil && build.status == .ok {
259261
noSuccess.remove(build.runnerId!)
260262
if noSuccess.isEmpty { return .ok }

Sources/App/Core/AppEnvironment.swift

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,8 @@ struct AppEnvironment: Sendable {
3131
var gitlabPipelineToken: @Sendable () -> String?
3232
var gitlabPipelineLimit: @Sendable () -> Int
3333
var logger: @Sendable () -> Logger
34-
var metricsPushGatewayUrl: @Sendable () -> String?
35-
var plausibleBackendReportingSiteID: @Sendable () -> String?
36-
var processingBuildBacklog: @Sendable () -> Bool
37-
var runnerIds: @Sendable () -> [String]
3834
var setLogger: @Sendable (Logger) -> Void
3935
var shell: Shell
40-
var siteURL: @Sendable () -> String
4136
var storeS3Readme: @Sendable (_ owner: String,
4237
_ repository: String,
4338
_ readme: String) async throws(S3Readme.Error) -> String
@@ -75,20 +70,8 @@ extension AppEnvironment {
7570
?? Constants.defaultGitlabPipelineLimit
7671
},
7772
logger: { logger },
78-
metricsPushGatewayUrl: { Environment.get("METRICS_PUSHGATEWAY_URL") },
79-
plausibleBackendReportingSiteID: { Environment.get("PLAUSIBLE_BACKEND_REPORTING_SITE_ID") },
80-
processingBuildBacklog: {
81-
Environment.get("PROCESSING_BUILD_BACKLOG").flatMap(\.asBool) ?? false
82-
},
83-
runnerIds: {
84-
Environment.get("RUNNER_IDS")
85-
.map { Data($0.utf8) }
86-
.flatMap { try? JSONDecoder().decode([String].self, from: $0) }
87-
?? []
88-
},
8973
setLogger: { logger in Self.logger = logger },
9074
shell: .live,
91-
siteURL: { Environment.get("SITE_URL") ?? "http://localhost:8080" },
9275
storeS3Readme: { owner, repo, readme throws(S3Readme.Error) in
9376
try await S3Readme.storeReadme(owner: owner, repository: repo, readme: readme)
9477
},

Sources/App/Core/AppMetrics.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
import Dependencies
1516
import Metrics
1617
import Prometheus
1718
import Vapor
@@ -170,7 +171,8 @@ extension AppMetrics {
170171
/// scrape target.
171172
/// - Parameter client: client for POST request
172173
static func push(client: Client, jobName: String) async throws {
173-
guard let pushGatewayUrl = Current.metricsPushGatewayUrl() else {
174+
@Dependency(\.environment) var environment
175+
guard let pushGatewayUrl = environment.metricsPushGatewayUrl() else {
174176
throw AppError.envVariableNotSet("METRICS_PUSHGATEWAY_URL")
175177
}
176178
let url = URI(string: "\(pushGatewayUrl)/metrics/job/\(jobName)")

Sources/App/Core/Dependencies/EnvironmentClient.swift

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ struct EnvironmentClient {
4545
var loadSPIManifest: @Sendable (String) -> SPIManifest.Manifest?
4646
var maintenanceMessage: @Sendable () -> String?
4747
var mastodonCredentials: @Sendable () -> Mastodon.Credentials?
48+
var metricsPushGatewayUrl: @Sendable () -> String?
49+
var plausibleBackendReportingSiteID: @Sendable () -> String?
50+
var processingBuildBacklog: @Sendable () -> Bool = { XCTFail("processingBuildBacklog"); return false }
4851
var random: @Sendable (_ range: ClosedRange<Double>) -> Double = { XCTFail("random"); return Double.random(in: $0) }
52+
var runnerIds: @Sendable () -> [String] = { XCTFail("runnerIds"); return [] }
4953

5054
enum FailureMode: String {
5155
case fetchMetadataFailed
@@ -55,7 +59,8 @@ struct EnvironmentClient {
5559
case repositorySaveFailed
5660
case repositorySaveUniqueViolation
5761
}
58-
var shouldFail: @Sendable (_ failureMode: FailureMode) -> Bool = { _ in false }
62+
var shouldFail: @Sendable (_ failureMode: FailureMode) -> Bool = { _ in XCTFail("shouldFail"); return false }
63+
var siteURL: @Sendable () -> String = { XCTFail("siteURL"); return "" }
5964
}
6065

6166

@@ -79,10 +84,7 @@ extension EnvironmentClient: DependencyKey {
7984
builderToken: { Environment.get("BUILDER_TOKEN") },
8085
buildTimeout: { Environment.get("BUILD_TIMEOUT").flatMap(Int.init) ?? 10 },
8186
buildTriggerAllowList: {
82-
Environment.get("BUILD_TRIGGER_ALLOW_LIST")
83-
.map { Data($0.utf8) }
84-
.flatMap { try? JSONDecoder().decode([Package.Id].self, from: $0) }
85-
?? []
87+
Environment.decode("BUILD_TRIGGER_ALLOW_LIST", as: [Package.Id].self) ?? []
8688
},
8789
buildTriggerDownscaling: {
8890
Environment.get("BUILD_TRIGGER_DOWNSCALING")
@@ -118,14 +120,19 @@ extension EnvironmentClient: DependencyKey {
118120
Environment.get("MASTODON_ACCESS_TOKEN")
119121
.map(Mastodon.Credentials.init(accessToken:))
120122
},
123+
metricsPushGatewayUrl: { Environment.get("METRICS_PUSHGATEWAY_URL") },
124+
plausibleBackendReportingSiteID: { Environment.get("PLAUSIBLE_BACKEND_REPORTING_SITE_ID") },
125+
processingBuildBacklog: {
126+
Environment.get("PROCESSING_BUILD_BACKLOG").flatMap(\.asBool) ?? false
127+
},
121128
random: { range in Double.random(in: range) },
129+
runnerIds: { Environment.decode("RUNNER_IDS", as: [String].self) ?? [] },
122130
shouldFail: { failureMode in
123-
let shouldFail = Environment.get("FAILURE_MODE")
124-
.map { Data($0.utf8) }
125-
.flatMap { try? JSONDecoder().decode([String: Double].self, from: $0) } ?? [:]
131+
let shouldFail = Environment.decode("FAILURE_MODE", as: [String: Double].self) ?? [:]
126132
guard let rate = shouldFail[failureMode.rawValue] else { return false }
127133
return Double.random(in: 0...1) <= rate
128-
}
134+
},
135+
siteURL: { Environment.get("SITE_URL") ?? "http://localhost:8080" }
129136
)
130137
}
131138
}
@@ -156,6 +163,8 @@ extension EnvironmentClient: TestDependencyKey {
156163
mock.appVersion = { "test" }
157164
mock.current = { .development }
158165
mock.hideStagingBanner = { false }
166+
mock.siteURL = { "http://localhost:8080" }
167+
mock.shouldFail = { @Sendable _ in false }
159168
return mock
160169
}
161170
}
@@ -167,3 +176,12 @@ extension DependencyValues {
167176
set { self[EnvironmentClient.self] = newValue }
168177
}
169178
}
179+
180+
181+
private extension Environment {
182+
static func decode<T: Decodable>(_ key: String, as type: T.Type) -> T? {
183+
Environment.get(key)
184+
.map { Data($0.utf8) }
185+
.flatMap { try? JSONDecoder().decode(type, from: $0) }
186+
}
187+
}

Sources/App/Core/Plausible.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ enum Plausible {
4747
static let postEventURL = "https://plausible.io/api/event"
4848

4949
static func postEvent(kind: Event.Kind, path: Path, user: User?) async throws {
50-
guard let siteID = Current.plausibleBackendReportingSiteID() else {
50+
@Dependency(\.environment) var environment
51+
guard let siteID = environment.plausibleBackendReportingSiteID() else {
5152
throw Error(message: "PLAUSIBLE_BACKEND_REPORTING_SITE_ID not set")
5253
}
5354
let body = try JSONEncoder().encode(Event(name: .pageview,

Sources/App/Core/SiteURL.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
import Dependencies
1516
import Plot
1617
import Vapor
1718

@@ -341,7 +342,8 @@ enum SiteURL: Resourceable, Sendable {
341342
}
342343

343344
static let _absoluteURL: @Sendable (String) -> String = { path in
344-
Current.siteURL() + relativeURL(path)
345+
@Dependency(\.environment) var environment
346+
return environment.siteURL() + relativeURL(path)
345347
}
346348

347349
static let _relativeURL: @Sendable (String) -> String = { path in

Sources/App/Views/PackageController/GetRoute.Model+ext.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,9 @@ extension API.PackageController.GetRoute.Model {
619619
}
620620

621621
func noCompatibilityInformationExplainer() -> Node<HTML.BodyContext> {
622-
.if(Current.processingBuildBacklog(),
622+
@Dependency(\.environment) var environment
623+
624+
return .if(environment.processingBuildBacklog(),
623625
.group(
624626
.p(
625627
.text("This package currently has no compatibility information. "),

Tests/AppTests/AlertingTests.swift

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
import XCTest
16+
1517
@testable import App
1618

17-
import XCTest
19+
import Dependencies
1820

1921

2022
class AlertingTests: XCTestCase {
@@ -77,34 +79,40 @@ class AlertingTests: XCTestCase {
7779

7880
func test_validateRunnerIdsPresent() throws {
7981
let runnerIds = ["a", "b", "c"]
80-
Current.runnerIds = { runnerIds }
81-
let all = runnerIds.map {
82-
Alerting.BuildInfo.mock(runnerId: $0)
82+
withDependencies {
83+
$0.environment.runnerIds = { runnerIds }
84+
} operation: {
85+
let all = runnerIds.map {
86+
Alerting.BuildInfo.mock(runnerId: $0)
87+
}
88+
XCTAssertEqual(all.validateRunnerIdsPresent(), .ok)
89+
XCTAssertEqual(all.filter { $0.runnerId != "a" }.validateRunnerIdsPresent(),
90+
.failed(reasons: ["Missing runner id: a"]))
91+
XCTAssertEqual(all.filter { $0.runnerId != "a" && $0.runnerId != "b" }.validateRunnerIdsPresent(),
92+
.failed(reasons: ["Missing runner id: a", "Missing runner id: b"]))
8393
}
84-
XCTAssertEqual(all.validateRunnerIdsPresent(), .ok)
85-
XCTAssertEqual(all.filter { $0.runnerId != "a" }.validateRunnerIdsPresent(),
86-
.failed(reasons: ["Missing runner id: a"]))
87-
XCTAssertEqual(all.filter { $0.runnerId != "a" && $0.runnerId != "b" }.validateRunnerIdsPresent(),
88-
.failed(reasons: ["Missing runner id: a", "Missing runner id: b"]))
8994
}
9095

9196
func test_validateRunnerIdsSuccessful() throws {
9297
let runnerIds = ["a", "b", "c"]
93-
Current.runnerIds = { runnerIds }
94-
let all = runnerIds.map {
95-
Alerting.BuildInfo.mock(runnerId: $0, status: .ok)
98+
withDependencies {
99+
$0.environment.runnerIds = { runnerIds }
100+
} operation: {
101+
let all = runnerIds.map {
102+
Alerting.BuildInfo.mock(runnerId: $0, status: .ok)
103+
}
104+
XCTAssertEqual(all.validateRunnerIdsSuccessful(), .ok)
105+
XCTAssertEqual(all.filter { $0.runnerId != "a" }.validateRunnerIdsSuccessful(),
106+
.failed(reasons: ["Runner id without successful builds: a"]))
107+
XCTAssertEqual(
108+
Array(all.filter { $0.runnerId != "a" })
109+
.appending(.mock(runnerId: "a", status: .failed))
110+
.validateRunnerIdsSuccessful(),
111+
.failed(reasons: ["Runner id without successful builds: a"])
112+
)
113+
XCTAssertEqual(all.filter { $0.runnerId != "a" && $0.runnerId != "b" }.validateRunnerIdsSuccessful(),
114+
.failed(reasons: ["Runner id without successful builds: a", "Runner id without successful builds: b"]))
96115
}
97-
XCTAssertEqual(all.validateRunnerIdsSuccessful(), .ok)
98-
XCTAssertEqual(all.filter { $0.runnerId != "a" }.validateRunnerIdsSuccessful(),
99-
.failed(reasons: ["Runner id without successful builds: a"]))
100-
XCTAssertEqual(
101-
Array(all.filter { $0.runnerId != "a" })
102-
.appending(.mock(runnerId: "a", status: .failed))
103-
.validateRunnerIdsSuccessful(),
104-
.failed(reasons: ["Runner id without successful builds: a"])
105-
)
106-
XCTAssertEqual(all.filter { $0.runnerId != "a" && $0.runnerId != "b" }.validateRunnerIdsSuccessful(),
107-
.failed(reasons: ["Runner id without successful builds: a", "Runner id without successful builds: b"]))
108116
}
109117

110118
func test_validateSuccessRateInRange() throws {

Tests/AppTests/BuildTests.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,9 @@ class BuildTests: AppTestCase {
133133
$0.environment.awsDocsBucket = { "awsDocsBucket" }
134134
$0.environment.builderToken = { "builder token" }
135135
$0.environment.buildTimeout = { 10 }
136+
$0.environment.siteURL = { "http://example.com" }
136137
} operation: {
137138
Current.gitlabPipelineToken = { "pipeline token" }
138-
Current.siteURL = { "http://example.com" }
139139
// setup
140140
let p = try await savePackage(on: app.db, "1")
141141
let v = try Version(package: p, reference: .branch("main"))
@@ -201,11 +201,11 @@ class BuildTests: AppTestCase {
201201
$0.environment.awsDocsBucket = { "awsDocsBucket" }
202202
$0.environment.builderToken = { "builder token" }
203203
$0.environment.buildTimeout = { 10 }
204+
$0.environment.siteURL = { "http://example.com" }
204205
} operation: {
205206
// Same test as test_trigger above, except we trigger with isDocBuild: true
206207
// and expect a 15m TIMEOUT instead of 10m
207208
Current.gitlabPipelineToken = { "pipeline token" }
208-
Current.siteURL = { "http://example.com" }
209209
// setup
210210
let p = try await savePackage(on: app.db, "1")
211211
let v = try Version(package: p, reference: .branch("main"))

0 commit comments

Comments
 (0)