Skip to content

Commit

Permalink
Add an option to release as a prerelease (#20)
Browse files Browse the repository at this point in the history
* Renaming entries to GitBuddy

* Command registry is set up

* Setup the new structure for having multiple commands

* Fix swiftlint warning

* Fix SwiftLint warnings

* Changing the authentication method to Basic HTTP

* Improve folder structure

* Start implementing the release command

* Output is now printed by GitBuddy

* Printing errors is now more clean

* Cleaned up the code, added folders in the tests, added strongly typed for shell commands to make it easier to mock

* Handle verbose globally

* Cleaned up the code a bit more inside the release producer

* Add tests for the release producer

* Adding an option to change the local changelog file

* Added tests

* Related issues and pull requests are now commented

* Changelog is now tested

* Add tests for commenting

* Improve the structure for posting comments

* Fix Octokit reference

* Update the readme to reflect the current changes

* Add verbose and help options for --help command. Convert to doner-case

* Adds a version command and adds all license headers

* Update the License

* Fix SwiftLint warnings

* Add an option to release as a prerelease

* Add post body tests

* Fix Mocker reference
  • Loading branch information
AvdLee authored Feb 7, 2020
1 parent 63346b3 commit 0109de9
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 14 deletions.
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ let package = Package(
dependencies: [
// dev .package(url: "https://github.com/danger/swift", from: "3.0.0"),
// dev .package(path: "Submodules/WeTransfer-iOS-CI/Danger-Swift"),
.package(url: "https://github.com/WeTransfer/Mocker.git", from: "2.0.0"),
// dev .package(url: "https://github.com/WeTransfer/Mocker.git", from: "2.1.0"),
// .package(url: "https://github.com/nerdishbynature/octokit.swift", from: "0.9.0"),
.package(url: "https://github.com/nerdishbynature/octokit.swift", .branch("feature/bugfixes")),
.package(url: "https://github.com/apple/swift-package-manager.git", from: "0.1.0")
],
targets: [
.testTarget(name: "GitBuddyTests", dependencies: ["GitBuddy", "Mocker"]),
// dev .testTarget(name: "GitBuddyTests", dependencies: ["GitBuddy", "Mocker"]),
// dev .target(name: "DangerDependencies", dependencies: ["Danger", "WeTransferPRLinter"], path: "Submodules/WeTransfer-iOS-CI/Danger-Swift", sources: ["DangerFakeSource.swift"]),
.target(name: "GitBuddy", dependencies: ["GitBuddyCore"]),
.target(name: "GitBuddyCore", dependencies: ["OctoKit", "SPMUtility"])
Expand Down
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ $ gitbuddy changelog --help
OVERVIEW: Create a changelog for GitHub repositories
OPTIONS:
--baseBranch, -b The base branch to compare with. Defaults to master.
--sinceTag, -s The tag to use as a base. Defaults to the latest tag.
--verbose Show extra logging for debugging purposes
--base-branch, -b The base branch to compare with. Defaults to master.
--help Display available options
--since-tag, -s The tag to use as a base. Defaults to the latest tag.
--verbose Show extra logging for debugging purposes
```

This command generates a changelog based on merged PRs and fixed issues. Once a PR contains a reference like `"Fixed #30"`, the title of issue 30 will be included in the changelog. Otherwise, the Pull Request title will be used.
Expand All @@ -44,9 +45,11 @@ $ gitbuddy release --help
OVERVIEW: Create a new release including a changelog and publish comments on related issues
OPTIONS:
--changelogPath, -c The path to the Changelog to update it with the latest changes
--skipComments, -s Disable commenting on issues and PRs about the new release
--verbose Show extra logging for debugging purposes
--changelog-path, -c The path to the Changelog to update it with the latest changes
--help Display available options
--skip-comments, -s Disable commenting on issues and PRs about the new release
--use-pre-release, -p Create the release as a pre-release
--verbose Show extra logging for debugging purposes
```

The `release` command can be used to transform the latest tag into a GitHub release including the changelog as a body.
Expand Down
11 changes: 8 additions & 3 deletions Sources/GitBuddyCore/Release/ReleaseProducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@ struct ReleaseCommand: Command {
static let description = "Create a new release including a changelog and publish comments on related issues"
let changelogPath: OptionArgument<String>
let skipComments: OptionArgument<Bool>
let isPrelease: OptionArgument<Bool>

init(subparser: ArgumentParser) {
changelogPath = subparser.add(option: "--changelog-path", shortName: "-c", kind: String.self, usage: "The path to the Changelog to update it with the latest changes")
skipComments = subparser.add(option: "--skip-comments", shortName: "-s", kind: Bool.self, usage: "Disable commenting on issues and PRs about the new release")
isPrelease = subparser.add(option: "--use-pre-release", shortName: "-p", kind: Bool.self, usage: "Create the release as a pre-release")
}

@discardableResult func run(using arguments: ArgumentParser.Result) throws -> String {
let changelogProducer = try ReleaseProducer(changelogPath: arguments.get(changelogPath),
skipComments: arguments.get(skipComments) ?? false)
skipComments: arguments.get(skipComments) ?? false,
isPrelease: arguments.get(isPrelease) ?? false)

Log.debug("Result of creating the release:\n")
return try changelogProducer.run().url.absoluteString
Expand All @@ -36,14 +39,16 @@ final class ReleaseProducer: URLSessionInjectable, ShellInjectable {
private lazy var octoKit: Octokit = Octokit()
let changelogURL: Foundation.URL?
let skipComments: Bool
let isPrelease: Bool

init(changelogPath: String?, skipComments: Bool) throws {
init(changelogPath: String?, skipComments: Bool, isPrelease: Bool) throws {
if let changelogPath = changelogPath {
changelogURL = URL(string: changelogPath)
} else {
changelogURL = nil
}
self.skipComments = skipComments
self.isPrelease = isPrelease
}

@discardableResult public func run() throws -> Release {
Expand Down Expand Up @@ -108,7 +113,7 @@ final class ReleaseProducer: URLSessionInjectable, ShellInjectable {
group.enter()

var result: Result<Foundation.URL, Swift.Error>!
octoKit.postRelease(urlSession, owner: project.organisation, repository: project.repository, tagName: tag.name, name: tag.name, body: body, prerelease: false, draft: false) { (response) in
octoKit.postRelease(urlSession, owner: project.organisation, repository: project.repository, tagName: tag.name, name: tag.name, body: body, prerelease: isPrelease, draft: false) { (response) in
switch response {
case .success(let release):
result = .success(release.htmlURL)
Expand Down
39 changes: 38 additions & 1 deletion Tests/GitBuddyTests/Release/ReleaseProducerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,28 @@ final class ReleaseProducerTests: XCTestCase {
XCTAssertEqual(releaseURL, "https://github.com/WeTransfer/ChangelogProducer/releases/tag/1.0.1")
}

/// It should set the parameters correctly.
func testPostBodyArguments() throws {
let mockExpectation = expectation(description: "Mocks should be called")
var mock = Mocker.mockRelease()
mock.onRequest = { _, parameters in
guard let parameters = try? XCTUnwrap(parameters) else { return }
XCTAssertEqual(parameters["prerelease"] as? Bool, false)
XCTAssertEqual(parameters["draft"] as? Bool, false)
XCTAssertEqual(parameters["tag_name"] as? String, "1.0.1")
XCTAssertEqual(parameters["name"] as? String, "1.0.1")
XCTAssertEqual(parameters["body"] as? String, """
- Add charset utf-8 to html head ([#50](https://github.com/WeTransfer/Diagnostics/pull/50)) via @AvdLee
- Get warning for file 'style.css' after building ([#39](https://github.com/WeTransfer/Diagnostics/issues/39)) via @AvdLee
""")
mockExpectation.fulfill()
}
mock.register()

_ = try GitBuddy.run(arguments: ["GitBuddy", "release", "-s"], configuration: configuration)
wait(for: [mockExpectation], timeout: 0.3)
}

/// It should update the changelog file if the argument is set.
func testChangelogUpdating() throws {
let existingChangelog = """
Expand Down Expand Up @@ -83,7 +105,7 @@ final class ReleaseProducerTests: XCTestCase {

/// It should not post comments if --skipComments is passed as an argument.
func testSkippingComments() throws {
let mockExpectation = expectation(description: "Mocks should be called")
let mockExpectation = expectation(description: "Mock should not be called")
mockExpectation.isInverted = true
var mock = Mocker.mockForCommentingOn(issueNumber: 39)
mock.completion = {
Expand All @@ -94,4 +116,19 @@ final class ReleaseProducerTests: XCTestCase {
_ = try GitBuddy.run(arguments: ["GitBuddy", "release", "-s"], configuration: configuration)
wait(for: [mockExpectation], timeout: 0.3)
}

/// It should use the prerelease setting.
func testPrerelease() throws {
let mockExpectation = expectation(description: "Mocks should be called")
var mock = Mocker.mockRelease()
mock.onRequest = { _, parameters in
guard let parameters = try? XCTUnwrap(parameters) else { return }
XCTAssertTrue(parameters["prerelease"] as? Bool == true)
mockExpectation.fulfill()
}
mock.register()

_ = try GitBuddy.run(arguments: ["GitBuddy", "release", "-s", "-p"], configuration: configuration)
wait(for: [mockExpectation], timeout: 0.3)
}
}
6 changes: 4 additions & 2 deletions Tests/GitBuddyTests/TestHelpers/Mocks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@ extension Mocker {
Mock(url: urlComponents.url!, dataType: .json, statusCode: 200, data: [.get: issueJSONData]).register()
}

static func mockRelease() {
@discardableResult static func mockRelease() -> Mock {
let releaseJSONData = ReleaseJSON.data(using: .utf8)!
Mock(url: URL(string: "https://api.github.com/repos/WeTransfer/Diagnostics/releases")!, dataType: .json, statusCode: 201, data: [.post: releaseJSONData]).register()
let mock = Mock(url: URL(string: "https://api.github.com/repos/WeTransfer/Diagnostics/releases")!, dataType: .json, statusCode: 201, data: [.post: releaseJSONData])
mock.register()
return mock
}

static func mockForCommentingOn(issueNumber: Int) -> Mock {
Expand Down

0 comments on commit 0109de9

Please sign in to comment.