diff --git a/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Commands/AWSSDKSwiftCLI/Subcommands/PrepareRelease.swift b/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Commands/AWSSDKSwiftCLI/Subcommands/PrepareRelease.swift index 1d21c45ea1c..f53b6841f05 100644 --- a/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Commands/AWSSDKSwiftCLI/Subcommands/PrepareRelease.swift +++ b/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Commands/AWSSDKSwiftCLI/Subcommands/PrepareRelease.swift @@ -236,7 +236,7 @@ struct PrepareRelease { ) throws { let commits = try Process.git.listOfCommitsBetween("HEAD", "\(previousVersion)") - let releaseNotes = try ReleaseNotesBuilder( + let releaseNotes = ReleaseNotesBuilder( previousVersion: previousVersion, newVersion: newVersion, repoOrg: repoOrg, diff --git a/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Models/Features.swift b/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Models/Features.swift deleted file mode 100644 index 526928fa588..00000000000 --- a/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Models/Features.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -import Foundation -import AWSCLIUtils - -struct FeaturesReader: Decodable { - private let requestFilePath: String - private let mappingFilePath: String - - public init( - requestFilePath: String = "../build-request.json", - mappingFilePath: String = "../feature-service-id.json" - ) { - self.requestFilePath = requestFilePath - self.mappingFilePath = mappingFilePath - } - - public func getFeaturesFromFile() throws -> Features { - let fileContents = try FileManager.default.loadContents(atPath: requestFilePath) - return try JSONDecoder().decode(Features.self, from: fileContents) - } - - public func getFeaturesIDToServiceNameDictFromFile() throws -> [String: String] { - let fileContents = try FileManager.default.loadContents(atPath: mappingFilePath) - return try JSONDecoder().decode([String: String].self, from: fileContents) - } -} - -struct Features: Decodable { - let features: [Feature] -} - -struct Feature: Decodable { - let releaseNotes: String - let featureMetadata: FeatureMetadata - - struct FeatureMetadata: Decodable { - let trebuchet: Trebuchet - - struct Trebuchet: Decodable { - let featureId: String - let featureType: String - } - } -} diff --git a/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Models/ReleaseNotesBuilder.swift b/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Models/ReleaseNotesBuilder.swift index 5a9a4eb5828..da4451fe660 100644 --- a/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Models/ReleaseNotesBuilder.swift +++ b/AWSSDKSwiftCLI/Sources/AWSSDKSwiftCLI/Models/ReleaseNotesBuilder.swift @@ -15,62 +15,24 @@ struct ReleaseNotesBuilder { let repoOrg: PrepareRelease.Org let repoType: PrepareRelease.Repo let commits: [String] - var featuresReader: FeaturesReader = FeaturesReader() - + // MARK: - Build - - func build() throws -> String { - let sdkChanges: [String] = buildSDKChangeSection() - let serviceClientChanges = repoType == .awsSdkSwift ? (try buildServiceChangeSection()) : [] - let fullCommitLogLink = [ - "\n**Full Changelog**: https://github.com/\(repoOrg.rawValue)/\(repoType.rawValue)/compare/\(previousVersion)...\(newVersion)" + + func build() -> String { + let contents = [ + "## What's Changed", + buildCommits(), + .newline, + "**Full Changelog**: https://github.com/\(repoOrg.rawValue)/\(repoType.rawValue)/compare/\(previousVersion)...\(newVersion)" ] - let contents = ["## What's Changed"] + serviceClientChanges + sdkChanges + fullCommitLogLink return contents.joined(separator: .newline) } - - func buildSDKChangeSection() -> [String] { - let formattedCommits = commits - .filter { $0.hasPrefix("feat") || $0.hasPrefix("fix") } - .map { "* \($0)" } - .joined(separator: .newline) - if (!formattedCommits.isEmpty) { - return ["### Miscellaneous", formattedCommits] - } - return [] - } - - func buildServiceChangeSection() throws -> [String] { - let features = try featuresReader.getFeaturesFromFile() - let mapping = try featuresReader.getFeaturesIDToServiceNameDictFromFile() - return buildServiceFeatureSection(features, mapping) + buildServiceDocSection(features, mapping) - } - - private func buildServiceFeatureSection( - _ features: Features, - _ mapping: [String: String] - ) -> [String] { - let formattedFeatures = features.features - .filter { $0.featureMetadata.trebuchet.featureType == "NEW_FEATURE" } - .map { "* **AWS \(mapping[$0.featureMetadata.trebuchet.featureId]!)**: \($0.releaseNotes)" } - .joined(separator: .newline) - if (!formattedFeatures.isEmpty) { - return ["### Service Features", formattedFeatures] - } - return [] - } - - private func buildServiceDocSection( - _ features: Features, - _ mapping: [String: String] - ) -> [String] { - let formattedDocUpdates = features.features - .filter { $0.featureMetadata.trebuchet.featureType == "DOC_UPDATE" } - .map { "* **AWS \(mapping[$0.featureMetadata.trebuchet.featureId]!)**: \($0.releaseNotes)" } + + // Adds a preceding `*` to each commit string + // This renders the list of commits as a list in markdown + func buildCommits() -> String { + commits + .map { "* \($0)"} .joined(separator: .newline) - if (!formattedDocUpdates.isEmpty) { - return ["### Service Documentation", formattedDocUpdates] - } - return [] } } diff --git a/AWSSDKSwiftCLI/Tests/AWSSDKSwiftCLITests/Commands/PrepareReleaseTests.swift b/AWSSDKSwiftCLI/Tests/AWSSDKSwiftCLITests/Commands/PrepareReleaseTests.swift index fac35a2bc75..c8b35cc1d4c 100644 --- a/AWSSDKSwiftCLI/Tests/AWSSDKSwiftCLITests/Commands/PrepareReleaseTests.swift +++ b/AWSSDKSwiftCLI/Tests/AWSSDKSwiftCLITests/Commands/PrepareReleaseTests.swift @@ -45,16 +45,6 @@ class PrepareReleaseTests: CLITestCase { createPackageVersion(previousVersion) createNextPackageVersion(newVersion) - let buildRequest = """ - { - "features": [] - } - """ - FileManager.default.createFile(atPath: "build-request.json", contents: Data(buildRequest.utf8)) - - let mapping = "{}" - FileManager.default.createFile(atPath: "feature-service-id.json", contents: Data(mapping.utf8)) - let subject = PrepareRelease.mock(repoType: .awsSdkSwift, diffChecker: { _,_ in true }) try! subject.run() diff --git a/AWSSDKSwiftCLI/Tests/AWSSDKSwiftCLITests/Models/PackageManifestBuilderTests.swift b/AWSSDKSwiftCLI/Tests/AWSSDKSwiftCLITests/Models/PackageManifestBuilderTests.swift index ecb12da89a5..16f8b836ac1 100644 --- a/AWSSDKSwiftCLI/Tests/AWSSDKSwiftCLITests/Models/PackageManifestBuilderTests.swift +++ b/AWSSDKSwiftCLI/Tests/AWSSDKSwiftCLITests/Models/PackageManifestBuilderTests.swift @@ -12,6 +12,7 @@ class PackageManifestBuilderTests: XCTestCase { let expected = """ + // MARK: - Dynamic Content let clientRuntimeVersion: Version = "1.2.3" diff --git a/AWSSDKSwiftCLI/Tests/AWSSDKSwiftCLITests/Models/ReleaseNotesBuilderTests.swift b/AWSSDKSwiftCLI/Tests/AWSSDKSwiftCLITests/Models/ReleaseNotesBuilderTests.swift deleted file mode 100644 index c4c96ccbb3c..00000000000 --- a/AWSSDKSwiftCLI/Tests/AWSSDKSwiftCLITests/Models/ReleaseNotesBuilderTests.swift +++ /dev/null @@ -1,187 +0,0 @@ -// -// Copyright Amazon.com Inc. or its affiliates. -// All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 -// - -@testable import AWSSDKSwiftCLI -import AWSCLIUtils -import XCTest - -/* - * Regression tests for protection against change in generated release notes markdown content. - */ -class ReleaseNotesBuilderTests: XCTestCase { - /* Reusable feature strings */ - - // New feature 1 - private let feature1 = """ - { - "releaseNotes": "New feature description A.", - "featureMetadata": { - "trebuchet": { - "featureId": "feature-id-a", - "featureType": "NEW_FEATURE", - } - } - } - """ - - // New feature 2 - private let feature2 = """ - { - "releaseNotes": "New feature description B.", - "featureMetadata": { - "trebuchet": { - "featureId": "feature-id-b", - "featureType": "NEW_FEATURE", - } - } - } - """ - - // Documentation update - private let feature3 = """ - { - "releaseNotes": "Doc update description C.", - "featureMetadata": { - "trebuchet": { - "featureId": "feature-id-c", - "featureType": "DOC_UPDATE", - } - } - } - """ - - // Dictionary of feature ID to name of the service - private let mapping = """ - { - "feature-id-a": "Service 1", - "feature-id-b": "Service 2", - "feature-id-c": "Service 3" - } - """ - - func testAllSectionsPresent() throws { - let buildRequest = """ - { "features": [\(feature1), \(feature2), \(feature3)] } - """ - setUpBuildRequestAndMappingJSONs(buildRequest, mapping) - let builder = try setUpBuilder(testCommits: ["fix: Fix X", "feat: Feat Y"]) - let releaseNotes = try builder.build() - let expected = """ - ## What's Changed - ### Service Features - * **AWS Service 1**: New feature description A. - * **AWS Service 2**: New feature description B. - ### Service Documentation - * **AWS Service 3**: Doc update description C. - ### Miscellaneous - * fix: Fix X - * feat: Feat Y - - **Full Changelog**: https://github.com/awslabs/aws-sdk-swift/compare/1.0.0...1.0.1 - """ - XCTAssertEqual(releaseNotes, expected) - } - - func testNoServiceFeatureSectionPresent() throws { - let buildRequest = """ - { "features": [\(feature3)] } - """ - setUpBuildRequestAndMappingJSONs(buildRequest, mapping) - let builder = try setUpBuilder(testCommits: ["fix: Fix X", "feat: Feat Y"]) - let releaseNotes = try builder.build() - let expected = """ - ## What's Changed - ### Service Documentation - * **AWS Service 3**: Doc update description C. - ### Miscellaneous - * fix: Fix X - * feat: Feat Y - - **Full Changelog**: https://github.com/awslabs/aws-sdk-swift/compare/1.0.0...1.0.1 - """ - XCTAssertEqual(releaseNotes, expected) - } - - func testNoServiceDocSectionPresent() throws { - let buildRequest = """ - { "features": [\(feature1), \(feature2)] } - """ - setUpBuildRequestAndMappingJSONs(buildRequest, mapping) - let builder = try setUpBuilder(testCommits: ["fix: Fix X", "feat: Feat Y"]) - let releaseNotes = try builder.build() - let expected = """ - ## What's Changed - ### Service Features - * **AWS Service 1**: New feature description A. - * **AWS Service 2**: New feature description B. - ### Miscellaneous - * fix: Fix X - * feat: Feat Y - - **Full Changelog**: https://github.com/awslabs/aws-sdk-swift/compare/1.0.0...1.0.1 - """ - XCTAssertEqual(releaseNotes, expected) - } - - func testNoSDKChangeSectionPresent() throws { - let buildRequest = """ - { "features": [\(feature1), \(feature2), \(feature3)] } - """ - setUpBuildRequestAndMappingJSONs(buildRequest, mapping) - let builder = try setUpBuilder() - let releaseNotes = try builder.build() - let expected = """ - ## What's Changed - ### Service Features - * **AWS Service 1**: New feature description A. - * **AWS Service 2**: New feature description B. - ### Service Documentation - * **AWS Service 3**: Doc update description C. - - **Full Changelog**: https://github.com/awslabs/aws-sdk-swift/compare/1.0.0...1.0.1 - """ - XCTAssertEqual(releaseNotes, expected) - } - - func testNoSectionsPresentAndIrrelevantCommitsAreFiltered() throws { - let buildRequest = """ - { "features":[] } - """ - setUpBuildRequestAndMappingJSONs(buildRequest, mapping) - let builder = try setUpBuilder(testCommits: ["chore: Commit A", "Update X"]) - let releaseNotes = try builder.build() - let expected = """ - ## What's Changed - - **Full Changelog**: https://github.com/awslabs/aws-sdk-swift/compare/1.0.0...1.0.1 - """ - XCTAssertEqual(releaseNotes, expected) - } - - private func setUpBuildRequestAndMappingJSONs(_ buildRequest: String, _ mapping: String) { - // In real scenario, the JSON files we need are located one level above, in the workspace directory. - // For tests, due to sandboxing, the dummy files are created in current directory instead of - // in parent directory. - FileManager.default.createFile(atPath: "build-request.json", contents: Data(buildRequest.utf8)) - FileManager.default.createFile(atPath: "feature-service-id.json", contents: Data(mapping.utf8)) - } - - private func setUpBuilder(testCommits: [String] = []) throws -> ReleaseNotesBuilder { - return try ReleaseNotesBuilder( - previousVersion: Version("1.0.0"), - newVersion: Version("1.0.1"), - repoOrg: .awslabs, - repoType: .awsSdkSwift, - commits: testCommits, - // Parametrize behavior of FeaturesReader with paths used to create JSON test files - featuresReader: FeaturesReader( - requestFilePath: "build-request.json", - mappingFilePath: "feature-service-id.json" - ) - ) - } -}