Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions Sources/App/Core/AppEnvironment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import FoundationNetworking


struct AppEnvironment: Sendable {
var apiSigningKey: @Sendable () -> String?
var appVersion: @Sendable () -> String?
var collectionSigningCertificateChain: @Sendable () -> [URL]
var collectionSigningPrivateKey: @Sendable () -> Data?
var currentReferenceCache: @Sendable () -> CurrentReferenceCache?
Expand Down Expand Up @@ -91,8 +89,6 @@ extension AppEnvironment {
nonisolated(unsafe) static var logger: Logger!

static let live = AppEnvironment(
apiSigningKey: { Environment.get("API_SIGNING_KEY") },
appVersion: { App.appVersion },
collectionSigningCertificateChain: {
[
SignedCollection.certsDir
Expand Down
4 changes: 3 additions & 1 deletion Sources/App/Core/Authentication/User.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ extension User {
struct APITierAuthenticator: AsyncBearerAuthenticator {
var tier: Tier<V1>

@Dependency(\.environment) var environment

func authenticate(bearer: BearerAuthorization, for request: Request) async throws {
guard let signingKey = Current.apiSigningKey() else { throw AppError.envVariableNotSet("API_SIGNING_KEY") }
guard let signingKey = environment.apiSigningKey() else { throw AppError.envVariableNotSet("API_SIGNING_KEY") }
let signer = Signer(secretSigningKey: signingKey)
do {
let key = try signer.verifyToken(bearer.token)
Expand Down
27 changes: 20 additions & 7 deletions Sources/App/Core/Dependencies/EnvironmentClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,12 @@ import Vapor
struct EnvironmentClient {
// See https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependenciesmacros/dependencyclient()#Restrictions
// regarding the use of XCTFail here.
// Closures returning optionals or Void don't need this, because they automatically get the default failing
// mechanism when they're not set up in a test.
var allowBuildTriggers: @Sendable () -> Bool = { XCTFail("allowBuildTriggers"); return true }
var allowSocialPosts: @Sendable () -> Bool = { XCTFail("allowSocialPosts"); return true }
var apiSigningKey: @Sendable () -> String?
var appVersion: @Sendable () -> String?
var awsAccessKeyId: @Sendable () -> String?
var awsDocsBucket: @Sendable () -> String?
var awsReadmeBucket: @Sendable () -> String?
Expand All @@ -32,12 +36,7 @@ struct EnvironmentClient {
var buildTriggerAllowList: @Sendable () -> [Package.Id] = { XCTFail("buildTriggerAllowList"); return [] }
var buildTriggerDownscaling: @Sendable () -> Double = { XCTFail("buildTriggerDownscaling"); return 1 }
var buildTriggerLatestSwiftVersionDownscaling: @Sendable () -> Double = { XCTFail("buildTriggerLatestSwiftVersionDownscaling"); return 1 }
// We're not defaulting current to XCTFail, because its use is too pervasive and would require the vast
// majority of tests to be wrapped with `withDependencies`.
// We can do so at a later time once more tests are transitioned over for other dependencies. This is
// the exact same default behaviour we have with the Current dependency injection: it defaults to
// .development and does not raise an error when not injected.
var current: @Sendable () -> Environment = { .development }
var current: @Sendable () -> Environment = { XCTFail("current"); return .development }
var mastodonCredentials: @Sendable () -> Mastodon.Credentials?
var mastodonPost: @Sendable (_ client: Client, _ post: String) async throws -> Void
var random: @Sendable (_ range: ClosedRange<Double>) -> Double = { XCTFail("random"); return Double.random(in: $0) }
Expand All @@ -55,6 +54,8 @@ extension EnvironmentClient: DependencyKey {
.flatMap(\.asBool)
?? Constants.defaultAllowSocialPosts
},
apiSigningKey: { Environment.get("API_SIGNING_KEY") },
appVersion: { App.appVersion },
awsAccessKeyId: { Environment.get("AWS_ACCESS_KEY_ID") },
awsDocsBucket: { Environment.get("AWS_DOCS_BUCKET") },
awsReadmeBucket: { Environment.get("AWS_README_BUCKET") },
Expand Down Expand Up @@ -102,7 +103,19 @@ extension EnvironmentClient {


extension EnvironmentClient: TestDependencyKey {
static var testValue: Self { Self() }
static var testValue: Self {
// sas 2024-11-22:
// For a few attributes we provide a default value overriding the XCTFail, because theis use is too
// pervasive and would require the vast majority of tests to be wrapped with `withDependencies`.
// We can do so at a later time once more tests are transitioned over for other dependencies. This is
// the exact same default behaviour we had with the Current dependency injection. It did not have
// a "fail if not set" mechanism and relied on default values only. We're simply preserving this
// mechanism for a few heavily used dependencies at the moment.
var mock = Self()
mock.appVersion = { "test" }
mock.current = { .development }
return mock
}
}


Expand Down
5 changes: 3 additions & 2 deletions Sources/App/Views/PublicPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ class PublicPage {
/// The page's full HTML document.
/// - Returns: A fully formed page inside a <html> element.
final func document() -> HTML {
HTML(
@Dependency(\.environment) var environment
return HTML(
.lang(.english),
.comment("Version: \(Current.appVersion())"),
.comment("Version: \(environment.appVersion())"),
.comment("DB Id: \(Current.dbId())"),
head(),
body()
Expand Down
3 changes: 2 additions & 1 deletion Sources/App/Views/ResourceReloadIdentifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ import Vapor

struct ResourceReloadIdentifier {
static var value: String {
@Dependency(\.environment) var environment
// In staging or production appVersion will be set to a commit hash or a tag name.
// It will only ever be nil when running in a local development environment.
if let appVersion = Current.appVersion() {
if let appVersion = environment.appVersion() {
return appVersion
} else {
// Return the date of the most recently modified between the JavaScript and CSS resources.
Expand Down
Loading
Loading