Skip to content

Commit b228474

Browse files
Merge pull request #3502 from SwiftPackageIndex/issue-3469-dependency-transition-5
Issue 3469 dependency transition 5
2 parents 92a024f + 86a00c5 commit b228474

15 files changed

+1011
-874
lines changed

Sources/App/Controllers/PackageController+routes.swift

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

15+
import Dependencies
1516
import Fluent
1617
import Plot
17-
import Vapor
1818
import SemanticVersion
19+
import Vapor
1920

2021

2122
enum PackageController {
@@ -222,7 +223,7 @@ enum PackageController {
222223
// r.owner,
223224
// v.reference,
224225
// d.linkable_paths_count
225-
// '(owner: "' || r.owner || '", repository: "' || r.name || '"), // ' || d.linkable_paths_count || ' urls'
226+
// '(owner: "' || r.owner || '", repository: "' || r.name || '"), // ' || d.linkable_paths_count || ' urls'
226227
// FROM
227228
// packages p
228229
// INNER JOIN repositories r ON p.id = r.package_id
@@ -437,7 +438,8 @@ extension PackageController {
437438

438439
extension PackageController {
439440
static func awsDocumentationURL(route: DocRoute) throws -> URI {
440-
guard let bucket = Current.awsDocsBucket() else {
441+
@Dependency(\.environment) var environment
442+
guard let bucket = environment.awsDocsBucket() else {
441443
throw AppError.envVariableNotSet("AWS_DOCS_BUCKET")
442444
}
443445

Sources/App/Core/AppEnvironment.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ import FoundationNetworking
2525
struct AppEnvironment: Sendable {
2626
var apiSigningKey: @Sendable () -> String?
2727
var appVersion: @Sendable () -> String?
28-
var awsAccessKeyId: @Sendable () -> String?
29-
var awsDocsBucket: @Sendable () -> String?
30-
var awsReadmeBucket: @Sendable () -> String?
31-
var awsSecretAccessKey: @Sendable () -> String?
3228
var buildTriggerAllowList: @Sendable () -> [Package.Id]
3329
var buildTriggerDownscaling: @Sendable () -> Double
3430
var buildTriggerLatestSwiftVersionDownscaling: @Sendable () -> Double
@@ -106,10 +102,6 @@ extension AppEnvironment {
106102
static let live = AppEnvironment(
107103
apiSigningKey: { Environment.get("API_SIGNING_KEY") },
108104
appVersion: { App.appVersion },
109-
awsAccessKeyId: { Environment.get("AWS_ACCESS_KEY_ID") },
110-
awsDocsBucket: { Environment.get("AWS_DOCS_BUCKET") },
111-
awsReadmeBucket: { Environment.get("AWS_README_BUCKET") },
112-
awsSecretAccessKey: { Environment.get("AWS_SECRET_ACCESS_KEY") },
113105
buildTriggerAllowList: {
114106
Environment.get("BUILD_TRIGGER_ALLOW_LIST")
115107
.map { Data($0.utf8) }

Sources/App/Core/Dependencies/EnvironmentClient.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ struct EnvironmentClient {
2323
// regarding the use of XCTFail here.
2424
var allowBuildTriggers: @Sendable () -> Bool = { XCTFail(#function); return true }
2525
var allowSocialPosts: @Sendable () -> Bool = { XCTFail(#function); return true }
26+
var awsAccessKeyId: @Sendable () -> String?
27+
var awsDocsBucket: @Sendable () -> String?
28+
var awsReadmeBucket: @Sendable () -> String?
29+
var awsSecretAccessKey: @Sendable () -> String?
2630
var builderToken: @Sendable () -> String?
2731
var buildTimeout: @Sendable () -> Int = { XCTFail(#function); return 10 }
2832
// We're not defaulting current to XCTFail, because its use is too pervasive and would require the vast
@@ -47,6 +51,10 @@ extension EnvironmentClient: DependencyKey {
4751
.flatMap(\.asBool)
4852
?? Constants.defaultAllowSocialPosts
4953
},
54+
awsAccessKeyId: { Environment.get("AWS_ACCESS_KEY_ID") },
55+
awsDocsBucket: { Environment.get("AWS_DOCS_BUCKET") },
56+
awsReadmeBucket: { Environment.get("AWS_README_BUCKET") },
57+
awsSecretAccessKey: { Environment.get("AWS_SECRET_ACCESS_KEY") },
5058
builderToken: { Environment.get("BUILDER_TOKEN") },
5159
buildTimeout: { Environment.get("BUILD_TIMEOUT").flatMap(Int.init) ?? 10 },
5260
current: { (try? Environment.detect()) ?? .development },

Sources/App/Core/Extensions/S3Store+ext.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
import S3Store
1616
import Vapor
17+
import Dependencies
1718

1819

1920
extension S3Store {
@@ -27,8 +28,9 @@ extension S3Store {
2728
}
2829

2930
static func storeReadme(owner: String, repository: String, readme: String) async throws -> String {
30-
guard let accessKeyId = Current.awsAccessKeyId(),
31-
let secretAccessKey = Current.awsSecretAccessKey()
31+
@Dependency(\.environment) var environment
32+
guard let accessKeyId = environment.awsAccessKeyId(),
33+
let secretAccessKey = environment.awsSecretAccessKey()
3234
else {
3335
throw Error.genericError("missing AWS credentials")
3436
}
@@ -42,8 +44,9 @@ extension S3Store {
4244
}
4345

4446
static func storeReadmeImages(client: Client, imagesToCache: [Github.Readme.ImageToCache]) async throws {
45-
guard let accessKeyId = Current.awsAccessKeyId(),
46-
let secretAccessKey = Current.awsSecretAccessKey()
47+
@Dependency(\.environment) var environment
48+
guard let accessKeyId = environment.awsAccessKeyId(),
49+
let secretAccessKey = environment.awsSecretAccessKey()
4750
else {
4851
throw Error.genericError("missing AWS credentials")
4952
}
@@ -63,7 +66,8 @@ extension S3Store {
6366

6467
extension S3Store.Key {
6568
static func readme(owner: String, repository: String, imageUrl: String? = nil) throws -> Self {
66-
guard let bucket = Current.awsReadmeBucket() else {
69+
@Dependency(\.environment) var environment
70+
guard let bucket = environment.awsReadmeBucket() else {
6771
throw S3Store.Error.genericError("AWS_README_BUCKET not set")
6872
}
6973

Sources/App/Core/Gitlab.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ extension Gitlab.Builder {
8282
guard let pipelineToken = Current.gitlabPipelineToken(),
8383
let builderToken = environment.builderToken()
8484
else { throw Gitlab.Error.missingToken }
85-
guard let awsDocsBucket = Current.awsDocsBucket() else {
85+
guard let awsDocsBucket = environment.awsDocsBucket() else {
8686
throw Gitlab.Error.missingConfiguration("AWS_DOCS_BUCKET")
8787
}
8888
let timeout = environment.buildTimeout() + (isDocBuild ? 5 : 0)

Tests/AppTests/BuildTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ class BuildTests: AppTestCase {
130130

131131
func test_trigger() async throws {
132132
try await withDependencies {
133+
$0.environment.awsDocsBucket = { "awsDocsBucket" }
133134
$0.environment.builderToken = { "builder token" }
134135
$0.environment.buildTimeout = { 10 }
135136
} operation: {
@@ -197,6 +198,7 @@ class BuildTests: AppTestCase {
197198

198199
func test_trigger_isDocBuild() async throws {
199200
try await withDependencies {
201+
$0.environment.awsDocsBucket = { "awsDocsBucket" }
200202
$0.environment.builderToken = { "builder token" }
201203
$0.environment.buildTimeout = { 10 }
202204
} operation: {

Tests/AppTests/BuildTriggerTests.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ class BuildTriggerTests: AppTestCase {
329329

330330
func test_triggerBuildsUnchecked() async throws {
331331
try await withDependencies {
332+
$0.environment.awsDocsBucket = { "awsDocsBucket" }
332333
$0.environment.builderToken = { "builder token" }
333334
$0.environment.buildTimeout = { 10 }
334335
} operation: {
@@ -390,6 +391,7 @@ class BuildTriggerTests: AppTestCase {
390391

391392
func test_triggerBuildsUnchecked_supported() async throws {
392393
try await withDependencies {
394+
$0.environment.awsDocsBucket = { "awsDocsBucket" }
393395
$0.environment.builderToken = { "builder token" }
394396
$0.environment.buildTimeout = { 10 }
395397
} operation: {
@@ -470,6 +472,7 @@ class BuildTriggerTests: AppTestCase {
470472

471473
func test_triggerBuildsUnchecked_build_exists() async throws {
472474
try await withDependencies {
475+
$0.environment.awsDocsBucket = { "awsDocsBucket" }
473476
$0.environment.builderToken = { "builder token" }
474477
$0.environment.buildTimeout = { 10 }
475478
} operation: {
@@ -550,6 +553,7 @@ class BuildTriggerTests: AppTestCase {
550553
func test_triggerBuilds_checked() async throws {
551554
try await withDependencies {
552555
$0.environment.allowBuildTriggers = { true }
556+
$0.environment.awsDocsBucket = { "awsDocsBucket" }
553557
$0.environment.builderToken = { "builder token" }
554558
$0.environment.buildTimeout = { 10 }
555559
} operation: {
@@ -662,6 +666,7 @@ class BuildTriggerTests: AppTestCase {
662666
func test_triggerBuilds_multiplePackages() async throws {
663667
try await withDependencies {
664668
$0.environment.allowBuildTriggers = { true }
669+
$0.environment.awsDocsBucket = { "awsDocsBucket" }
665670
$0.environment.builderToken = { "builder token" }
666671
$0.environment.buildTimeout = { 10 }
667672
} operation: {
@@ -712,6 +717,7 @@ class BuildTriggerTests: AppTestCase {
712717
func test_triggerBuilds_trimming() async throws {
713718
try await withDependencies {
714719
$0.environment.allowBuildTriggers = { true }
720+
$0.environment.awsDocsBucket = { "awsDocsBucket" }
715721
$0.environment.builderToken = { "builder token" }
716722
} operation: {
717723
// Ensure we trim builds as part of triggering
@@ -747,6 +753,7 @@ class BuildTriggerTests: AppTestCase {
747753
func test_triggerBuilds_error() async throws {
748754
try await withDependencies {
749755
$0.environment.allowBuildTriggers = { true }
756+
$0.environment.awsDocsBucket = { "awsDocsBucket" }
750757
$0.environment.builderToken = { "builder token" }
751758
$0.environment.buildTimeout = { 10 }
752759
} operation: {
@@ -843,6 +850,7 @@ class BuildTriggerTests: AppTestCase {
843850

844851
func test_override_switch() async throws {
845852
try await withDependencies {
853+
$0.environment.awsDocsBucket = { "awsDocsBucket" }
846854
$0.environment.builderToken = { "builder token" }
847855
$0.environment.buildTimeout = { 10 }
848856
} operation: {
@@ -917,6 +925,7 @@ class BuildTriggerTests: AppTestCase {
917925
func test_downscaling() async throws {
918926
try await withDependencies {
919927
$0.environment.allowBuildTriggers = { true }
928+
$0.environment.awsDocsBucket = { "awsDocsBucket" }
920929
$0.environment.builderToken = { "builder token" }
921930
$0.environment.buildTimeout = { 10 }
922931
} operation: {
@@ -990,6 +999,7 @@ class BuildTriggerTests: AppTestCase {
990999
func test_downscaling_allow_list_override() async throws {
9911000
try await withDependencies {
9921001
$0.environment.allowBuildTriggers = { true }
1002+
$0.environment.awsDocsBucket = { "awsDocsBucket" }
9931003
$0.environment.builderToken = { "builder token" }
9941004
$0.environment.buildTimeout = { 10 }
9951005
} operation: {

Tests/AppTests/GithubTests.swift

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@
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 Vapor
18-
import SwiftSoup
19+
import Dependencies
1920
import S3Store
20-
import XCTest
21+
import SwiftSoup
22+
import Vapor
2123

2224

2325
class GithubTests: AppTestCase {
@@ -396,9 +398,10 @@ class GithubTests: AppTestCase {
396398
}
397399

398400
func test_extractImagesRequiringCaching() async throws {
399-
Current.awsReadmeBucket = { "awsReadmeBucket" }
400-
401-
var readme = """
401+
try withDependencies {
402+
$0.environment.awsReadmeBucket = { "awsReadmeBucket" }
403+
} operation: {
404+
var readme = """
402405
<html>
403406
<head></head>
404407
<body>
@@ -411,35 +414,37 @@ class GithubTests: AppTestCase {
411414
</html>
412415
"""
413416

414-
// MUT
415-
let images = Github.replaceImagesRequiringCaching(owner: "owner", repository: "repo", readme: &readme)
416-
417-
XCTAssertEqual(images, [
418-
.init(originalUrl: "https://private-user-images.githubusercontent.com/with-jwt.jpg?jwt=some-jwt",
419-
s3Key: S3Store.Key.init(bucket: "awsReadmeBucket", path: "owner/repo/with-jwt.jpg"))
420-
])
421-
422-
let document = try SwiftSoup.parse(readme)
423-
let imageElements = try document.select("img").array()
424-
425-
XCTAssertEqual(try imageElements.map { try $0.attr("src") }, [
426-
"https://awsReadmeBucket.s3.us-east-2.amazonaws.com/owner/repo/with-jwt.jpg",
427-
"https://private-user-images.githubusercontent.com/without-jwt.jpg",
428-
"https://raw.githubusercontent.com/raw-image.png",
429-
"https://github.com/example/repo/branch/assets/example.png",
430-
"https://example.com/other-domain.jpg"
431-
])
432-
433-
XCTAssertEqual(try imageElements.map { try $0.attr("data-original-src") }, [
434-
"https://private-user-images.githubusercontent.com/with-jwt.jpg?jwt=some-jwt",
435-
"", "", "", "" // This attribute only gets added to images that will be cached.
436-
])
417+
// MUT
418+
let images = Github.replaceImagesRequiringCaching(owner: "owner", repository: "repo", readme: &readme)
419+
420+
XCTAssertEqual(images, [
421+
.init(originalUrl: "https://private-user-images.githubusercontent.com/with-jwt.jpg?jwt=some-jwt",
422+
s3Key: S3Store.Key.init(bucket: "awsReadmeBucket", path: "owner/repo/with-jwt.jpg"))
423+
])
424+
425+
let document = try SwiftSoup.parse(readme)
426+
let imageElements = try document.select("img").array()
427+
428+
XCTAssertEqual(try imageElements.map { try $0.attr("src") }, [
429+
"https://awsReadmeBucket.s3.us-east-2.amazonaws.com/owner/repo/with-jwt.jpg",
430+
"https://private-user-images.githubusercontent.com/without-jwt.jpg",
431+
"https://raw.githubusercontent.com/raw-image.png",
432+
"https://github.com/example/repo/branch/assets/example.png",
433+
"https://example.com/other-domain.jpg"
434+
])
435+
436+
XCTAssertEqual(try imageElements.map { try $0.attr("data-original-src") }, [
437+
"https://private-user-images.githubusercontent.com/with-jwt.jpg?jwt=some-jwt",
438+
"", "", "", "" // This attribute only gets added to images that will be cached.
439+
])
440+
}
437441
}
438442

439443
func test_extractImagesRequiringCaching_noUnnecessaryChanges() async throws {
440-
Current.awsReadmeBucket = { "awsReadmeBucket" }
441-
442-
var readme = """
444+
try withDependencies {
445+
$0.environment.awsReadmeBucket = { "awsReadmeBucket" }
446+
} operation: {
447+
var readme = """
443448
<html>
444449
<head></head>
445450
<body>
@@ -450,14 +455,15 @@ class GithubTests: AppTestCase {
450455
</html>
451456
"""
452457

453-
let originalReadme = readme
458+
let originalReadme = readme
454459

455-
// MUT
456-
let images = Github.replaceImagesRequiringCaching(owner: "owner", repository: "repo", readme: &readme)
460+
// MUT
461+
let images = Github.replaceImagesRequiringCaching(owner: "owner", repository: "repo", readme: &readme)
457462

458-
// Checks
459-
XCTAssertEqual(originalReadme, readme)
460-
XCTAssertEqual(images, [])
463+
// Checks
464+
XCTAssertEqual(originalReadme, readme)
465+
XCTAssertEqual(images, [])
466+
}
461467
}
462468

463469
func test_Readme_containsSPIBadge() throws {

Tests/AppTests/GitlabBuilderTests.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ class GitlabBuilderTests: AppTestCase {
5555

5656
func test_triggerBuild() async throws {
5757
try await withDependencies {
58+
$0.environment.awsDocsBucket = { "docs-bucket" }
5859
$0.environment.builderToken = { "builder token" }
5960
$0.environment.buildTimeout = { 10 }
6061
} operation: {
61-
Current.awsDocsBucket = { "docs-bucket" }
6262
Current.gitlabPipelineToken = { "pipeline token" }
6363
Current.siteURL = { "http://example.com" }
6464
let buildId = UUID()
@@ -104,10 +104,10 @@ class GitlabBuilderTests: AppTestCase {
104104

105105
func test_issue_588() async throws {
106106
try await withDependencies {
107+
$0.environment.awsDocsBucket = { "docs-bucket" }
107108
$0.environment.builderToken = { "builder token" }
108109
$0.environment.buildTimeout = { 10 }
109110
} operation: {
110-
Current.awsDocsBucket = { "docs-bucket" }
111111
Current.gitlabPipelineToken = { "pipeline token" }
112112
Current.siteURL = { "http://example.com" }
113113

@@ -181,12 +181,13 @@ class LiveGitlabBuilderTests: AppTestCase {
181181
// Set this to a valid value if you want to report build results back to the server
182182
ProcessInfo.processInfo.environment["LIVE_BUILDER_TOKEN"]
183183
}
184+
// make sure environment variables are configured for live access
185+
$0.environment.awsDocsBucket = { "spi-dev-docs" }
184186
} operation: {
185187
// set build branch to trigger on
186188
Gitlab.Builder.branch = "main"
187189

188190
// make sure environment variables are configured for live access
189-
Current.awsDocsBucket = { "spi-dev-docs" }
190191
Current.gitlabPipelineToken = {
191192
// This Gitlab token is required in order to trigger the pipeline
192193
ProcessInfo.processInfo.environment["LIVE_GITLAB_PIPELINE_TOKEN"]

Tests/AppTests/IngestorTests.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -419,8 +419,12 @@ class IngestorTests: AppTestCase {
419419
}
420420

421421
func test_S3Store_Key_readme() throws {
422-
XCTAssertEqual(try S3Store.Key.readme(owner: "foo", repository: "bar").path, "foo/bar/readme.html")
423-
XCTAssertEqual(try S3Store.Key.readme(owner: "FOO", repository: "bar").path, "foo/bar/readme.html")
422+
try withDependencies {
423+
$0.environment.awsReadmeBucket = { "readme-bucket" }
424+
} operation: {
425+
XCTAssertEqual(try S3Store.Key.readme(owner: "foo", repository: "bar").path, "foo/bar/readme.html")
426+
XCTAssertEqual(try S3Store.Key.readme(owner: "FOO", repository: "bar").path, "foo/bar/readme.html")
427+
}
424428
}
425429

426430
func test_ingest_storeS3Readme() async throws {

0 commit comments

Comments
 (0)