Skip to content

Commit

Permalink
feat: Package manifest generator improvements (#1250)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbelkins authored Dec 6, 2023
1 parent 460138e commit 85761ff
Show file tree
Hide file tree
Showing 11 changed files with 206 additions and 238 deletions.
6 changes: 1 addition & 5 deletions AWSSDKSwiftCLI/Package.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// swift-tools-version: 5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.
// swift-tools-version: 5.7

import PackageDescription

Expand All @@ -26,9 +25,6 @@ let package = Package(
resources: [
.process("Resources/Package.Base.swift"),
.process("Resources/DocIndex.Base.md")
],
swiftSettings: [
.unsafeFlags(["-package-description-version", "5.7"])
]
),
.testTarget(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ struct GeneratePackageManifestCommand: ParsableCommand {
@Flag(help: "If the package manifest should include the protocol tests.")
var includeProtocolTests: Bool = false

@Flag(help: "If the package manifest should exclude AWS services.")
var excludeAWSServices = false

@Flag(help: "If the package manifest should exclude runtime tests.")
var excludeRuntimeTests = false

func run() throws {
let generatePackageManifest = GeneratePackageManifest.standard(
repoPath: repoPath,
Expand All @@ -46,7 +52,9 @@ struct GeneratePackageManifestCommand: ParsableCommand {
crtVersion: crtVersion,
services: services.isEmpty ? nil : services,
includeIntegrationTests: includeIntegrationTests,
includeProtocolTests: includeProtocolTests
includeProtocolTests: includeProtocolTests,
excludeAWSServices: excludeAWSServices,
excludeRuntimeTests: excludeRuntimeTests
)
try generatePackageManifest.run()
}
Expand All @@ -73,6 +81,10 @@ struct GeneratePackageManifest {
let includeIntegrationTests: Bool
/// If the package manifest should include the protocol tests.
let includeProtocolTests: Bool
/// If the package manifest should exclude the AWS services.
let excludeAWSServices: Bool
/// If the package manifest should exclude runtime unit tests.
let excludeRuntimeTests: Bool

typealias BuildPackageManifest = (
_ clientRuntimeVersion: Version,
Expand All @@ -97,7 +109,7 @@ struct GeneratePackageManifest {
/// - Returns: The contents of the generated package manifest.
func generatePackageManifestContents() throws -> String {
let versions = try resolveVersions()
let servicesWithIntegrationTests = try includeIntegrationTests ? resolveServicesWithIntegrationTests() : []
let servicesWithIntegrationTests = try resolveServicesWithIntegrationTests()
let services = try resolveServices().map {
PackageManifestBuilder.Service(
name: $0,
Expand Down Expand Up @@ -226,7 +238,9 @@ extension GeneratePackageManifest {
crtVersion: Version? = nil,
services: [String]? = nil,
includeIntegrationTests: Bool = false,
includeProtocolTests: Bool = false
includeProtocolTests: Bool = false,
excludeAWSServices: Bool = false,
excludeRuntimeTests: Bool = false
) -> Self {
GeneratePackageManifest(
repoPath: repoPath,
Expand All @@ -235,13 +249,18 @@ extension GeneratePackageManifest {
crtVersion: crtVersion,
services: services,
includeIntegrationTests: includeIntegrationTests,
includeProtocolTests: includeProtocolTests
includeProtocolTests: includeProtocolTests,
excludeAWSServices: excludeAWSServices,
excludeRuntimeTests: excludeRuntimeTests
) { _clientRuntimeVersion, _crtVersion, _services in
let builder = PackageManifestBuilder(
clientRuntimeVersion: _clientRuntimeVersion,
crtVersion: _crtVersion,
services: _services,
includeProtocolTests: includeProtocolTests
includeProtocolTests: includeProtocolTests,
includeIntegrationTests: includeIntegrationTests,
excludeAWSServices: excludeAWSServices,
excludeRuntimeTests: excludeRuntimeTests
)
return try builder.build()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,41 @@ struct PackageManifestBuilder {
let crtVersion: Version
let services: [Service]
let includeProtocolTests: Bool
let includeIntegrationTests: Bool
let excludeAWSServices: Bool
let excludeRuntimeTests: Bool
let basePackageContents: () throws -> String

init(
clientRuntimeVersion: Version,
crtVersion: Version,
services: [Service],
includeProtocolTests: Bool,
includeIntegrationTests: Bool,
excludeAWSServices: Bool,
excludeRuntimeTests: Bool,
basePackageContents: @escaping () throws -> String
) {
self.clientRuntimeVersion = clientRuntimeVersion
self.crtVersion = crtVersion
self.services = services
self.includeProtocolTests = includeProtocolTests
self.includeIntegrationTests = includeIntegrationTests
self.excludeAWSServices = excludeAWSServices
self.basePackageContents = basePackageContents
self.excludeRuntimeTests = excludeRuntimeTests
}

init(
clientRuntimeVersion: Version,
crtVersion: Version,
services: [Service],
includeProtocolTests: Bool
includeProtocolTests: Bool,
includeIntegrationTests: Bool,
excludeAWSServices: Bool,
excludeRuntimeTests: Bool
) {
self.init(clientRuntimeVersion: clientRuntimeVersion, crtVersion: crtVersion, services: services, includeProtocolTests: includeProtocolTests) {
self.init(clientRuntimeVersion: clientRuntimeVersion, crtVersion: crtVersion, services: services, includeProtocolTests: includeProtocolTests, includeIntegrationTests: includeIntegrationTests, excludeAWSServices: excludeAWSServices, excludeRuntimeTests: excludeRuntimeTests) {
// Returns the contents of the base package manifest stored in the bundle at `Resources/Package.Base.swift`
let basePackageName = "Package.Base"

Expand Down Expand Up @@ -83,13 +95,18 @@ struct PackageManifestBuilder {
// Add the generated content that defines the dependencies' versions
buildDependencies(),
"",
// Remove the runtime tests if needed
buildRuntimeTests(),
"",
// Add the generated content that defines the list of services to include
buildServiceTargets(),
"",
// Add the generated content that defines the list of services with integration tests to include
buildIntegrationTestsTargets(),
"",
buildProtocolTests(),
"",
buildResolvedServices(),
"\n"
]
return contents.joined(separator: .newline)
Expand All @@ -104,14 +121,6 @@ struct PackageManifestBuilder {


/// Builds the dependencies versions
///
///```swift
///addDependencies(
/// clientRuntimeVersion: 0.1.0,
/// crtVersion: 0.1.0
///)
///```
///
private func buildDependencies() -> String {
"""
addDependencies(
Expand All @@ -120,72 +129,53 @@ struct PackageManifestBuilder {
)
"""
}


private func buildRuntimeTests() -> String {
return [
"// Uncomment this line to exclude runtime unit tests",
(excludeRuntimeTests ? "" : "// ") + "excludeRuntimeUnitTests()"
].joined(separator: .newline)
}

/// Builds the list of services to include.
/// This generates an array of strings, where the each item is a name of a service
/// and calls the `addServiceTarget` for each item.
///
///```
///let serviceTargets: [String] = [
/// "Service Name 1",
/// "Service Name 2",
/// "Service Name 3"
/// // etc...
///]
///serviceTagets.forEach(addServiceTarget)
///```
///
private func buildServiceTargets() -> String {
let propertyName = "serviceTargets"

var lines: [String] = []
lines += ["let \(propertyName): [String] = ["]
lines += ["let serviceTargets: [String] = ["]
lines += services.map { " \($0.name.wrappedInQuotes())," }
lines += ["]"]
lines += [""]
lines += ["\(propertyName).forEach(addServiceTarget)"]

lines += ["// Uncomment this line to enable all services"]
lines += ["\(excludeAWSServices ? "// " : "")addAllServices()"]

return lines.joined(separator: .newline)
}

/// Builds the list of services to add integration test targets for..
/// This generates an array of strings, where the each item is a name of a service
/// and calls the `addIntegrationTestTarget` for each item.
///
///```
///let servicesWithIntegrationTests: [String] = [
/// "Service Name 1",
/// "Service Name 2",
/// "Service Name 3"
/// // etc...
///]
///serviceTagets.forEach(addIntegrationTestTarget)
///```
///
private func buildIntegrationTestsTargets() -> String {
let propertyName = "servicesWithIntegrationTests"

var lines: [String] = []
lines += ["let \(propertyName): [String] = ["]
lines += ["let servicesWithIntegrationTests: [String] = ["]
lines += services.filter(\.includeIntegrationTests).map { " \($0.name.wrappedInQuotes())," }
lines += ["]"]
lines += [""]
lines += ["\(propertyName).forEach(addIntegrationTestTarget)"]
lines += ["// Uncomment this line to enable integration tests"]
lines += ["\(includeIntegrationTests ? "" : "// ")addIntegrationTests()"]

return lines.joined(separator: .newline)
}

/// Calls the method to include protocol tests in the manifest.
///
///```
///// Uncomment this line to enable protocol tests
///addProtocolTests()
///```
private func buildProtocolTests() -> String {
return [
"// Uncomment this line to enable protocol tests",
(includeProtocolTests ? "" : "// ") + "addProtocolTests()"

].joined(separator: .newline)
}

private func buildResolvedServices() -> String {
"addResolvedTargets()"
}
}
39 changes: 35 additions & 4 deletions AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Resources/Package.Base.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ func addDoccDependency() {
// MARK: - Services

func addServiceTarget(_ name: String) {
let testName = "\(name)Tests"
package.products += [
.library(name: name, targets: [name]),
]
Expand All @@ -109,7 +108,13 @@ func addServiceTarget(_ name: String) {
name: name,
dependencies: [.clientRuntime, .awsClientRuntime],
path: "./Sources/Services/\(name)"
),
)
]
}

func addServiceUnitTestTarget(_ name: String) {
let testName = "\(name)Tests"
package.targets += [
.testTarget(
name: "\(testName)",
dependencies: [.crt, .clientRuntime, .awsClientRuntime, .byName(name: name), .smithyTestUtils],
Expand All @@ -120,7 +125,7 @@ func addServiceTarget(_ name: String) {

func addIntegrationTestTarget(_ name: String) {
let integrationTestName = "\(name)IntegrationTests"
var additionalDependencies: [PackageDescription.Target.Dependency] = []
var additionalDependencies: [String] = []
var exclusions: [String] = []
switch name {
case "AWSECS":
Expand All @@ -134,17 +139,38 @@ func addIntegrationTestTarget(_ name: String) {
default:
break
}
integrationTestServices.insert(name)
additionalDependencies.forEach { integrationTestServices.insert($0) }
package.targets += [
.testTarget(
name: integrationTestName,
dependencies: [.crt, .clientRuntime, .awsClientRuntime, .byName(name: name), .smithyTestUtils] + additionalDependencies,
dependencies: [.crt, .clientRuntime, .awsClientRuntime, .byName(name: name), .smithyTestUtils] + additionalDependencies.map { Target.Dependency.target(name: $0, condition: nil) },
path: "./IntegrationTests/Services/\(integrationTestName)",
exclude: exclusions,
resources: [.process("Resources")]
)
]
}

var enabledServices = Set<String>()

var enabledServiceUnitTests = Set<String>()

func addAllServices() {
enabledServices = Set(serviceTargets)
enabledServiceUnitTests = Set(serviceTargets)
}

var integrationTestServices = Set<String>()

func addIntegrationTests() {
servicesWithIntegrationTests.forEach { addIntegrationTestTarget($0) }
}

func excludeRuntimeUnitTests() {
package.targets.removeAll { $0.name == "AWSClientRuntimeTests" }
}

func addProtocolTests() {

struct ProtocolTest {
Expand Down Expand Up @@ -194,3 +220,8 @@ func addProtocolTests() {
]
}
}

func addResolvedTargets() {
enabledServices.union(integrationTestServices).forEach(addServiceTarget)
enabledServiceUnitTests.forEach(addServiceUnitTestTarget)
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ class GeneratePackageManifestTests: CLITestCase {
withIntermediateDirectories: true
)
}
try! FileManager.default.createDirectory(
atPath: "IntegrationTests/Services",
withIntermediateDirectories: true
)
}

// MARK: - Tests
Expand Down Expand Up @@ -112,6 +116,8 @@ extension GeneratePackageManifest {
services: [String]? = nil,
includesIntegrationTests: Bool = false,
includeProtocolTests: Bool = false,
excludeAWSServices: Bool = false,
excludeRuntimeTests: Bool = false,
buildPackageManifest: @escaping BuildPackageManifest = { (_,_,_) throws -> String in "" }
) -> GeneratePackageManifest {
GeneratePackageManifest(
Expand All @@ -122,6 +128,8 @@ extension GeneratePackageManifest {
services: services,
includeIntegrationTests: includesIntegrationTests,
includeProtocolTests: includeProtocolTests,
excludeAWSServices: excludeAWSServices,
excludeRuntimeTests: excludeRuntimeTests,
buildPackageManifest: buildPackageManifest
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class PrepareReleaseTests: CLITestCase {
ProcessRunner.testRunner = runner
let subject = PrepareRelease.mock(repoType: .awsSdkSwift)
try! subject.stageFiles()
XCTAssertTrue(command.hasSuffix("git add Package.swift Package.version packageDependencies.plist Sources/Services Tests/Services"))
XCTAssertTrue(command.hasSuffix("git add Package.swift Package.version packageDependencies.plist Sources/Services Tests/Services Sources/Core/AWSSDKForSwift/Documentation.docc/AWSSDKForSwift.md"))
}

func testStageFilesForSmithySwift() {
Expand Down
Loading

0 comments on commit 85761ff

Please sign in to comment.