diff --git a/Readme.md b/Readme.md
index b7736ab..d195773 100644
--- a/Readme.md
+++ b/Readme.md
@@ -28,29 +28,48 @@ You can see which version of Bob is currently running by typing `version`
The script to run for each target is specified when the command is instantiated.
For example:
```swift
+let config = try Config()
let buildTargets = [
TravisTarget(name: "staging", script: Script("fastlane ios distribute_staging")),
TravisTarget(name: "testflight", script: Script("fastlane ios distribute_testflight")),
]
-let buildCommand = TravisScriptCommand(name: "build", config: travisConfig, targets: buildTargets, defaultBranch: "Develop")
+let travisCI = try TravisCI(config: config)
+let buildCommand = TravisScriptCommand(name: "build", travis: travisCI, targets: buildTargets, defaultBranch: BranchName("develop"))
try bob.register(buildCommand)
```
-would register a command with the name `build`. Typing `build staging` would start the lane `distribute_staging` on Travis.
-
+would register a command with the name `build`. Typing `build staging` would start the lane `distribute_staging` on Travis.
+Your `bob.json` file should look like this (replace your token & urls)
+```json
+{
+ "travis-repo-url": "<# Url of the repo. Along the lines of https://api.travis-ci.com/repo/{owner%2Frepo} #>",
+ "travis-token": <# Travis CI access token #>
+ <# other configurations #>
+}
+```
### Align Version
iOS specific command used to change the `CFBundleShortVersionString` and `CFBundleVersion` values in specified `.plist` files.
For example:
```swift
+let config = try Config()
let plistPaths: [String] = [
"App/Info.plist",
"siriKit/Info.plist",
"siriKitUI/Info.plist"
]
-let alignCommand = AlignVersionCommand(config: gitHubConfig, defaultBranch: "Develop", plistPaths: plistPaths, author: author)
+let gitHub = try GitHub(config: config)
+let alignCommand = AlignVersionCommand(gitHub: gitHub, defaultBranch: BranchName("develop"), plistPaths: plistPaths, author: Author(name: "bob", email: "bob@example.com"))
try bob.register(alignCommand)
```
would register a command that can be invoked by typing `align 3.0 4`. Bob would then create a commit on GitHub by changing the 3 specified files.
-
+Your `bob.json` file should look like this (replace your token & urls)
+```json
+{
+ "github-username": <# Username of authenticated Github user #>,
+ "github-access-token": <# Persoanl access token for the authenticated user #>,
+ "github-repo-url": <# Url of the repo. Alogn the lines of https://api.github.com/repos/{owner}/{repo} #>,
+ <# other configurations #>
+}
+```
## Getting started
### Creating a bot on Slack
@@ -85,6 +104,15 @@ You can delete the unused template files by running:
rm -rf Sources/App/Controllers
rm -rf Sources/App/Models
```
+
+All of your configured tokens will reside in `bob.json` file in the `Config` folder. It should look like this (replace your token), and you can add this file to your `.gitignore`.
+```json
+{
+ "slack-token": <# Slack bot token #>,
+ <# other configurations #>
+}
+```
+
All of your custom code will reside in the `Sources/App` folder.
Create an Xcode project by running
```bash
@@ -94,9 +122,9 @@ Change the `Sources/App/main.swift` file to:
```swift
import Bob
-let config = Bob.Configuration(slackToken: "your-slack-token")
+let config = try Config()
let bob = Bob(config: config)
-
+<# register commands #>
try bob.start()
```
and you're good to go. Select the `App` scheme and run it. You can now send messages to `Bob` via Slack, and it will respond.
diff --git a/Sources/Bob/APIs/GitHub/GitHub.swift b/Sources/Bob/APIs/GitHub/GitHub.swift
index cce50b3..b58fc99 100644
--- a/Sources/Bob/APIs/GitHub/GitHub.swift
+++ b/Sources/Bob/APIs/GitHub/GitHub.swift
@@ -82,7 +82,7 @@ public struct Commit {
}
/// Used for communicating with the GitHub api
-public class GitHub {
+public final class GitHub {
/// Configuration needed for authentication with the api
public struct Configuration {
@@ -104,12 +104,12 @@ public class GitHub {
private let base64LoginData: String
private let repoUrl: String
- private let drop: Droplet
- public init(config: Configuration, droplet: Droplet) {
+ private let client: ClientFactoryProtocol
+ public init(config: Configuration, client: ClientFactoryProtocol) {
let authString = config.username + ":" + config.personalAccessToken
self.base64LoginData = authString.data(using: .utf8)!.base64EncodedString()
self.repoUrl = config.repoUrl
- self.drop = droplet
+ self.client = client
}
private func uri(at path: String) -> String {
@@ -118,7 +118,7 @@ public class GitHub {
private func perform(_ request: Request) throws -> JSON {
request.headers[HeaderKey("Authorization")] = "Basic " + self.base64LoginData
- let response = try self.drop.client.respond(to: request)
+ let response = try self.client.respond(to: request)
if response.status.isSuccessfulRequest {
if let json = response.json {
return json
@@ -288,3 +288,27 @@ public class GitHub {
}
}
+
+extension Config {
+ /// Resolves configured GitHub configuration
+ func resolveGitHubConfiguration() throws -> GitHub.Configuration {
+ guard let user = self[Bob.configFile, "github-username"]?.string else {
+ throw "Unable to find GitHub username. It should be found in \" Configs/bob.json\" under the key \"github-username\"."
+ }
+ guard let token = self[Bob.configFile, "github-access-token"]?.string else {
+ throw "Unable to find GitHub personal access token. It should be found in \" Configs/bob.json\" under the key \"github-access-token\"."
+ }
+ guard let repoURL = self[Bob.configFile, "github-repo-url"]?.string else {
+ throw "Unable to find GitHub repository URL. It should be found in \" Configs/bob.json\" under the key \"github-repo-url\"."
+ }
+ return GitHub.Configuration(username: user, personalAccessToken: token, repoUrl: repoURL)
+ }
+}
+
+extension GitHub: ConfigInitializable {
+ public convenience init(config: Config) throws {
+ let configuration = try config.resolveGitHubConfiguration()
+ let client = try config.resolveClient()
+ self.init(config: configuration, client: client)
+ }
+}
diff --git a/Sources/Bob/APIs/TravisCI/TravisCI.swift b/Sources/Bob/APIs/TravisCI/TravisCI.swift
index 203e392..afc977c 100644
--- a/Sources/Bob/APIs/TravisCI/TravisCI.swift
+++ b/Sources/Bob/APIs/TravisCI/TravisCI.swift
@@ -54,7 +54,7 @@ extension Dictionary where Key: ExpressibleByStringLiteral, Value: Any {
}
/// Used for communication with TravisCI api
-public class TravisCI {
+public final class TravisCI {
/// Configuration needed for authentication with the api
@@ -70,13 +70,14 @@ public class TravisCI {
}
private let config: Configuration
- private let drop: Droplet
+ private let client: ClientFactoryProtocol
/// Initializes the object with provided configuration
///
/// - Parameter config: Configuration to use
- public init(config: Configuration, droplet: Droplet) {
+ /// - Parameter client: HTTP Client factory to use
+ public init(config: Configuration, client: ClientFactoryProtocol) {
self.config = config
- self.drop = droplet
+ self.client = client
}
@@ -102,10 +103,32 @@ public class TravisCI {
request.headers[HeaderKey("Travis-API-Version")] = "3"
request.headers[HeaderKey("Content-Type")] = "application/json"
- let response = try self.drop.client.respond(to: request)
+ let response = try self.client.respond(to: request)
if !response.status.isSuccessfulRequest {
throw "Error: `" + request.uri.description + "` - " + response.status.reasonPhrase
}
}
-
+}
+
+
+extension Config {
+ /// Resolves configured Travis CI configuration
+ func resolveTravisConfiguration() throws -> TravisCI.Configuration {
+ guard let url = self[Bob.configFile, "travis-repo-url"]?.string else {
+ throw "Unable to find Travis CI repo URL. It should be found in \" Configs/bob.json\" under the key \"travis-repo-url\"."
+ }
+
+ guard let token = self[Bob.configFile, "travis-token"]?.string else {
+ throw "Unable to find Travis CI access token. It should be found in \" Configs/bob.json\" under the key \"travis-token\"."
+ }
+ return TravisCI.Configuration(repoUrl: url, token: token)
+ }
+}
+
+extension TravisCI: ConfigInitializable {
+ public convenience init(config: Config) throws {
+ let configuration = try config.resolveTravisConfiguration()
+ let client = try config.resolveClient()
+ self.init(config: configuration, client: client)
+ }
}
diff --git a/Sources/Bob/Core/Bob.swift b/Sources/Bob/Core/Bob.swift
index c875fcc..90c44c9 100644
--- a/Sources/Bob/Core/Bob.swift
+++ b/Sources/Bob/Core/Bob.swift
@@ -20,10 +20,11 @@
import Foundation
import Vapor
-public class Bob {
+public final class Bob {
static let version: String = "1.0.2"
-
+ static let configFile: String = "bob"
+
/// Struct containing all properties needed for Bob to function
public struct Configuration {
public let slackToken: String
@@ -44,9 +45,9 @@ public class Bob {
/// Initializer
///
/// - Parameter configuration: Configuration for setup
- /// - Parameter droplet: Droplet
- public init(config: Configuration, droplet: Droplet) {
- self.slackClient = SlackClient(token: config.slackToken, droplet: droplet)
+ /// - Parameter client: HTTP Client to use
+ public init(config: Configuration, client: ClientFactoryProtocol) {
+ self.slackClient = SlackClient(token: config.slackToken, client: client)
self.factory = CommandFactory(commands: [HelloCommand(), VersionCommand()])
self.processor = CommandProcessor(factory: self.factory)
self.executor = CommandExecutor()
@@ -102,3 +103,21 @@ fileprivate extension CommandFactory {
}
}
+
+extension Config {
+ /// Resolves configured Bob configuration
+ func resolveBobConfiguration() throws -> Bob.Configuration {
+ guard let token = self[Bob.configFile, "slack-token"]?.string else {
+ throw "Unable to find Slack access token. It should be found in \" Configs/bob.json\" under the key \"slack-token\"."
+ }
+ return Bob.Configuration(slackToken: token)
+ }
+}
+
+extension Bob: ConfigInitializable {
+ public convenience init(config: Config) throws {
+ let configuration = try config.resolveBobConfiguration()
+ let client = try config.resolveClient()
+ self.init(config: configuration, client: client)
+ }
+}
diff --git a/Sources/Bob/Core/Slack/SlackClient.swift b/Sources/Bob/Core/Slack/SlackClient.swift
index a5d92fc..f03239e 100644
--- a/Sources/Bob/Core/Slack/SlackClient.swift
+++ b/Sources/Bob/Core/Slack/SlackClient.swift
@@ -41,15 +41,15 @@ extension ClientFactoryProtocol {
class SlackClient {
private let token: String
- private let droplet: Droplet
- init(token: String, droplet: Droplet) {
+ private let client: ClientFactoryProtocol
+ init(token: String, client: ClientFactoryProtocol) {
self.token = token
- self.droplet = droplet
+ self.client = client
}
func connect(onMessage: @escaping (_ message: String, _ sender: MessageSender) -> Void) throws {
- let rtmResponse = try self.droplet.client.loadRealtimeApi(token: self.token)
+ let rtmResponse = try self.client.loadRealtimeApi(token: self.token)
guard let webSocketURL = rtmResponse.json?["url"]?.string else { throw "Unable to retrieve `url` from slack. Reason \(rtmResponse.status.reasonPhrase). Raw response \(rtmResponse.data)" }
try WebSocketFactory.shared.connect(to: webSocketURL) { (socket) in