Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import Dependencies
import DependencyResolution
import Fluent
import Vapor
Expand Down Expand Up @@ -101,7 +102,8 @@ extension API.PackageController.GetRoute {
}

static func customCollections(on database: Database, package: Package) async -> [CustomCollection.Details] {
guard Current.environment() == .development else { return [] }
@Dependency(\.environment) var environment
guard environment.current() == .development else { return [] }
do {
try await package.$customCollections.load(on: database)
return package.customCollections.map(\.details)
Expand Down
2 changes: 0 additions & 2 deletions Sources/App/Core/AppEnvironment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ struct AppEnvironment: Sendable {
var collectionSigningPrivateKey: @Sendable () -> Data?
var currentReferenceCache: @Sendable () -> CurrentReferenceCache?
var dbId: @Sendable () -> String?
var environment: @Sendable () -> Environment
var fetchDocumentation: @Sendable (_ client: Client, _ url: URI) async throws -> ClientResponse
var fetchHTTPStatusCode: @Sendable (_ url: String) async throws -> HTTPStatus
var fetchLicense: @Sendable (_ client: Client, _ owner: String, _ repository: String) async -> Github.License?
Expand Down Expand Up @@ -155,7 +154,6 @@ extension AppEnvironment {
},
currentReferenceCache: { .live },
dbId: { Environment.get("DATABASE_ID") },
environment: { (try? Environment.detect()) ?? .development },
fetchDocumentation: { client, url in try await client.get(url) },
fetchHTTPStatusCode: { url in try await Networking.fetchHTTPStatusCode(url) },
fetchLicense: { client, owner, repo in await Github.fetchLicense(client:client, owner: owner, repository: repo) },
Expand Down
9 changes: 8 additions & 1 deletion Sources/App/Core/Dependencies/EnvironmentClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ struct EnvironmentClient {
// See https://swiftpackageindex.com/pointfreeco/swift-dependencies/main/documentation/dependenciesmacros/dependencyclient()#Restrictions
// regarding the use of XCTFail here.
var allowBuildTriggers: @Sendable () -> Bool = { XCTFail(#function); return true }
// 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 }
}


Expand All @@ -30,7 +36,8 @@ extension EnvironmentClient: DependencyKey {
.init(
allowBuildTriggers: {
Environment.get("ALLOW_BUILD_TRIGGERS").flatMap(\.asBool) ?? Constants.defaultAllowBuildTriggering
}
},
current: { (try? Environment.detect()) ?? .development }
)
}
}
Expand Down
10 changes: 7 additions & 3 deletions Sources/App/Views/Blog/BlogActions+Model.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@
// limitations under the License.

import Foundation

import Dependencies
import Ink
import Plot
import Yams
import Ink


enum BlogActions {

Expand All @@ -38,7 +41,8 @@ enum BlogActions {
init() throws {
let allSummaries = try Self.allSummaries()

summaries = if Current.environment() == .production {
@Dependency(\.environment) var environment
summaries = if environment.current() == .production {
// Only "published" posts show in production.
allSummaries.filter { $0.published }
} else {
Expand Down Expand Up @@ -67,7 +71,7 @@ enum BlogActions {
return try YAMLDecoder().decode([PostSummary].self, from: String(decoding: data, as: UTF8.self))
.reversed()
}

}
}

Expand Down
14 changes: 10 additions & 4 deletions Sources/App/Views/DocumentationPageProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import Vapor
import SwiftSoup
import Plot
import Dependencies


struct DocumentationPageProcessor {
let document: SwiftSoup.Document
Expand Down Expand Up @@ -104,7 +106,8 @@ struct DocumentationPageProcessor {
}

var metaNoIndex: String? {
guard Current.environment() != .production else { return nil }
@Dependency(\.environment) var environment
guard environment.current() != .production else { return nil }
return Plot.Node.meta(
.name("robots"),
.content("noindex")
Expand All @@ -129,7 +132,8 @@ struct DocumentationPageProcessor {
}

var analyticsScript: String? {
guard Current.environment() == .production else { return nil }
@Dependency(\.environment) var environment
guard environment.current() == .production else { return nil }
return PublicPage.analyticsScriptTags
}

Expand Down Expand Up @@ -194,10 +198,11 @@ struct DocumentationPageProcessor {
]))
}

@Dependency(\.environment) var environment
return Plot.Node.group(
.header(
.class("spi"),
.if(Current.environment() == .development, stagingBanner()),
.if(environment.current() == .development, stagingBanner()),
.div(
.class("inner breadcrumbs"),
.nav(
Expand Down Expand Up @@ -240,6 +245,7 @@ struct DocumentationPageProcessor {
}

var footer: String {
@Dependency(\.environment) var environment
return Plot.Node.footer(
.class("spi"),
.div(
Expand Down Expand Up @@ -288,7 +294,7 @@ struct DocumentationPageProcessor {
.text(".")
)
),
.if(Current.environment() == .development, stagingBanner())
.if(environment.current() == .development, stagingBanner())
).render()
}

Expand Down
14 changes: 10 additions & 4 deletions Sources/App/Views/PublicPage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
// limitations under the License.

import Foundation
import Vapor

import Dependencies
import Plot
import Vapor


class PublicPage {

Expand Down Expand Up @@ -91,7 +94,8 @@ class PublicPage {
/// For non-production environments, this will *always* return true.
/// - Returns: Either nothing, or a <meta> element telling search engines not to index this content.
final func metaNoIndex() -> Node<HTML.HeadContext> {
if Current.environment() == .production && allowIndexing() {
@Dependency(\.environment) var environment
if environment.current() == .production && allowIndexing() {
return .empty
} else {
return .meta(
Expand Down Expand Up @@ -167,7 +171,8 @@ class PublicPage {
/// The Plausible analytics code to be inserted into the <head> element.
/// - Returns: A <script> containing the Plausible script tags.
final func analyticsHead() -> Node<HTML.HeadContext> {
return .if(Current.environment() == .production, .raw(PublicPage.analyticsScriptTags))
@Dependency(\.environment) var environment
return .if(environment.current() == .production, .raw(PublicPage.analyticsScriptTags))
}

static var analyticsScriptTags: String {
Expand Down Expand Up @@ -273,7 +278,8 @@ class PublicPage {
/// - Returns: Either a <div> element, or nothing.
final func stagingBanner() -> Node<HTML.BodyContext> {
guard !Current.hideStagingBanner() else { return .empty }
if Current.environment() == .development {
@Dependency(\.environment) var environment
if environment.current() == .development {
return .div(
.class("staging"),
.text("This is a staging environment. For live and up-to-date package information, "),
Expand Down
13 changes: 8 additions & 5 deletions Sources/App/routes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import Dependencies
import Fluent
import Metrics
import Plot
Expand All @@ -21,6 +22,8 @@ import VaporToOpenAPI


func routes(_ app: Application) throws {
@Dependency(\.environment) var environment

do { // home page
app.get { req in
if let maintenanceMessage = Current.maintenanceMessage() {
Expand Down Expand Up @@ -74,7 +77,7 @@ func routes(_ app: Application) throws {
use: PackageController.maintainerInfo).excludeFromOpenAPI()

// Only serve sitemaps in production.
if Current.environment() == .production {
if environment.current() == .production {
// Package specific site map, including all documentation URLs if available.
// Backend reporting currently disabled to avoid reporting costs for metrics we don't need.
app.group(BackendReportingMiddleware(path: .sitemapPackage, isActive: false)) {
Expand Down Expand Up @@ -149,7 +152,7 @@ func routes(_ app: Application) throws {
}

do { // api

// public routes
app.get(SiteURL.api(.version).pathComponents) { req in
API.Version(version: appVersion ?? "Unknown")
Expand Down Expand Up @@ -252,21 +255,21 @@ func routes(_ app: Application) throws {
)
}
}

}

do { // RSS
app.group(BackendReportingMiddleware(path: .rss)) {
$0.get(SiteURL.rssPackages.pathComponents, use: RSSFeed.showPackages)
.excludeFromOpenAPI()

$0.get(SiteURL.rssReleases.pathComponents, use: RSSFeed.showReleases)
.excludeFromOpenAPI()
}
}

// Only serve sitemaps in production.
if Current.environment() == .production {
if environment.current() == .production {
do { // Site map index and static page site map
app.group(BackendReportingMiddleware(path: .sitemapIndex)) {
$0.get(SiteURL.siteMapIndex.pathComponents, use: SiteMapController.index)
Expand Down
17 changes: 10 additions & 7 deletions Tests/AppTests/BlogActionsModelTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import XCTest

@testable import App

import XCTest
import Dependencies


class BlogActionsModelTests: AppTestCase {

Expand All @@ -34,9 +37,9 @@ class BlogActionsModelTests: AppTestCase {
""".data(using: .utf8)
}

do { // Ensure dev shows all summaries
Current.environment = { .development }

try withDependencies { // Ensure dev shows all summaries
$0.environment.current = { .development }
} operation: {
// MUT
let summaries = try BlogActions.Model().summaries

Expand All @@ -55,9 +58,9 @@ class BlogActionsModelTests: AppTestCase {
published: false))
}

do { // Ensure prod shows only published summaries
Current.environment = { .production }

try withDependencies { // Ensure prod shows only published summaries
$0.environment.current = { .production }
} operation: {
// MUT
let summaries = try BlogActions.Model().summaries

Expand Down
1 change: 0 additions & 1 deletion Tests/AppTests/Mocks/AppEnvironment+mock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ extension AppEnvironment {
collectionSigningPrivateKey: AppEnvironment.live.collectionSigningPrivateKey,
currentReferenceCache: { nil },
dbId: { "db-id" },
environment: { .development },
fetchDocumentation: { _, _ in .init(status: .ok) },
fetchHTTPStatusCode: { _ in .ok },
fetchLicense: { _, _, _ in .init(htmlUrl: "https://github.com/foo/bar/blob/main/LICENSE") },
Expand Down
46 changes: 24 additions & 22 deletions Tests/AppTests/PackageController+routesTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1337,31 +1337,33 @@ class PackageController_routesTests: SnapshotTestCase {

func test_siteMap_prod() async throws {
// Ensure sitemap routing is configured in prod
// Setup
Current.environment = { .production }
// We also need to set up a new app that's configured for production,
// because app.test is not affected by Current overrides.
let prodApp = try await setup(.production)
try await withDependencies {
$0.environment.current = { .production }
} operation: {
// We also need to set up a new app that's configured for production,
// because app.test is not affected by @Dependency overrides.
let prodApp = try await setup(.production)

do {
// setup
let package = Package(url: URL(stringLiteral: "https://example.com/owner/repo0"))
try await package.save(on: app.db)
try await Repository(package: package, defaultBranch: "default",
lastCommitDate: Date.now,
name: "Repo0", owner: "Owner").save(on: app.db)
try await Version(package: package, latest: .defaultBranch, packageName: "SomePackage",
reference: .branch("default")).save(on: app.db)

// MUT
try await prodApp.test(.GET, "/owner/repo0/sitemap.xml") { res async in
XCTAssertEqual(res.status, .ok)
do {
// setup
let package = Package(url: URL(stringLiteral: "https://example.com/owner/repo0"))
try await package.save(on: app.db)
try await Repository(package: package, defaultBranch: "default",
lastCommitDate: Date.now,
name: "Repo0", owner: "Owner").save(on: app.db)
try await Version(package: package, latest: .defaultBranch, packageName: "SomePackage",
reference: .branch("default")).save(on: app.db)

// MUT
try await prodApp.test(.GET, "/owner/repo0/sitemap.xml") { res async in
XCTAssertEqual(res.status, .ok)
}
} catch {
try? await prodApp.asyncShutdown()
throw error
}
} catch {
try? await prodApp.asyncShutdown()
throw error
try await prodApp.asyncShutdown()
}
try await prodApp.asyncShutdown()
}

func test_siteMap_dev() async throws {
Expand Down
Loading
Loading