Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added support for optional lttm #21

Merged
merged 1 commit into from
May 3, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 22 additions & 4 deletions Buildasaur/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -1793,7 +1793,7 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="Fkq-gK-hvs" userLabel="Edit Button">
<rect key="frame" x="14" y="57" width="97" height="32"/>
<rect key="frame" x="14" y="77" width="97" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="85" id="EMb-CS-lfh"/>
</constraints>
Expand All @@ -1806,7 +1806,7 @@
</connections>
</button>
<progressIndicator horizontalHuggingPriority="750" verticalHuggingPriority="750" maxValue="100" displayedWhenStopped="NO" bezeled="NO" indeterminate="YES" style="spinning" translatesAutoresizingMaskIntoConstraints="NO" id="cYi-gZ-3MX">
<rect key="frame" x="113" y="58" width="32" height="32"/>
<rect key="frame" x="119" y="78" width="32" height="32"/>
</progressIndicator>
<stepper horizontalHuggingPriority="750" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="XOz-yR-q3G">
<rect key="frame" x="174" y="5" width="19" height="27"/>
Expand Down Expand Up @@ -1855,11 +1855,28 @@
<action selector="manualBotManagementTapped:" target="RHg-5W-Hb1" id="u8a-Hh-JeY"/>
</connections>
</button>
<button fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="SL5-bS-Lf1">
<rect key="frame" x="46" y="42" width="130" height="18"/>
<buttonCell key="cell" type="check" title="Wait for &quot;lttm&quot;" bezelStyle="regularSquare" imagePosition="right" state="on" inset="2" id="Qky-j0-ffo">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<button horizontalHuggingPriority="750" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BkU-KL-lMX">
<rect key="frame" x="18" y="36" width="25" height="25"/>
<buttonCell key="cell" type="help" bezelStyle="helpButton" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="Pce-dC-RwH">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="helpLttmButtonTapped:" target="RHg-5W-Hb1" id="HyJ-tw-2fB"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstItem="8VZ-bw-dT5" firstAttribute="top" secondItem="zNe-bD-Pj4" secondAttribute="top" constant="5" id="Idf-Wk-1a9"/>
<constraint firstAttribute="trailing" secondItem="8VZ-bw-dT5" secondAttribute="trailing" constant="7" id="KhO-CN-dKQ"/>
<constraint firstAttribute="centerY" secondItem="Fkq-gK-hvs" secondAttribute="centerY" id="Tyj-fy-PKg"/>
<constraint firstAttribute="centerY" secondItem="Fkq-gK-hvs" secondAttribute="centerY" constant="20" id="Tyj-fy-PKg"/>
<constraint firstAttribute="bottom" secondItem="8VZ-bw-dT5" secondAttribute="bottom" constant="8" id="VKM-vY-EPh"/>
<constraint firstItem="Fkq-gK-hvs" firstAttribute="centerY" secondItem="cYi-gZ-3MX" secondAttribute="centerY" constant="-0.5" id="Vmg-bM-hj9"/>
<constraint firstItem="Fkq-gK-hvs" firstAttribute="leading" secondItem="5mg-80-kNh" secondAttribute="leading" id="cG9-Du-imO"/>
Expand All @@ -1870,10 +1887,11 @@
<constraint firstItem="A9h-Jh-CP9" firstAttribute="baseline" secondItem="5mg-80-kNh" secondAttribute="baseline" id="n8b-gL-QIi"/>
<constraint firstItem="A9h-Jh-CP9" firstAttribute="leading" secondItem="5mg-80-kNh" secondAttribute="trailing" constant="12" id="s3n-tF-0xA"/>
<constraint firstItem="Fkq-gK-hvs" firstAttribute="leading" secondItem="zNe-bD-Pj4" secondAttribute="leading" constant="20" id="tAH-BV-LCf"/>
<constraint firstItem="cYi-gZ-3MX" firstAttribute="leading" secondItem="Fkq-gK-hvs" secondAttribute="trailing" constant="8" id="wg4-z7-3io"/>
<constraint firstItem="cYi-gZ-3MX" firstAttribute="leading" secondItem="Fkq-gK-hvs" secondAttribute="trailing" constant="14" id="wg4-z7-3io"/>
</constraints>
</view>
<connections>
<outlet property="lttmToggle" destination="SL5-bS-Lf1" id="0d3-tb-sVO"/>
<outlet property="startStopButton" destination="Fkq-gK-hvs" id="5Ba-3L-5FZ"/>
<outlet property="statusActivityIndicator" destination="cYi-gZ-3MX" id="5l5-14-v81"/>
<outlet property="statusTextField" destination="8VZ-bw-dT5" id="Uav-J8-RH3"/>
Expand Down
11 changes: 8 additions & 3 deletions Buildasaur/HDGitHubXCBotSyncer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ public class HDGitHubXCBotSyncer : Syncer {
let github: GitHubServer!
let xcodeServer: XcodeServer!
let localSource: LocalSource!
let waitForLttm: Bool

typealias GitHubStatusAndComment = (status: Status, comment: String?)

init(integrationServer: XcodeServer, sourceServer: GitHubServer, localSource: LocalSource, syncInterval: NSTimeInterval) {
init(integrationServer: XcodeServer, sourceServer: GitHubServer, localSource: LocalSource, syncInterval: NSTimeInterval, waitForLttm: Bool) {

self.github = sourceServer
self.xcodeServer = integrationServer
self.localSource = localSource
self.waitForLttm = waitForLttm
super.init(syncInterval: syncInterval)
}

Expand All @@ -39,13 +41,15 @@ public class HDGitHubXCBotSyncer : Syncer {
self.localSource = project
self.github = GitHubFactory.server(project.githubToken)
self.xcodeServer = XcodeServerFactory.server(serverConfig)
self.waitForLttm = json.optionalBoolForKey("wait_for_lttm") ?? true
super.init(syncInterval: syncInterval)

} else {

self.github = nil
self.xcodeServer = nil
self.localSource = nil
self.waitForLttm = true
super.init(syncInterval: 0)
return nil
}
Expand All @@ -57,6 +61,7 @@ public class HDGitHubXCBotSyncer : Syncer {
dict["sync_interval"] = self.syncInterval
dict["project_path"] = self.localSource.url.absoluteString
dict["server_host"] = self.xcodeServer.config.host
dict["wait_for_lttm"] = self.waitForLttm
return dict
}

Expand Down Expand Up @@ -228,9 +233,9 @@ public class HDGitHubXCBotSyncer : Syncer {
//bot is enabled if (there are any integrations) OR (there is a recent comment with a keyword to enable the bot in the pull request's conversation)
//which means that there are two ways of enabling a bot.
//a) manually start an integration through Xcode, API call or in Builda's GUI (TBB)
//b) comment an agreed keyword in the Pull Request, e.g. "lttm" - 'looks testable to me' is a frequent one
//b) (optional) comment an agreed keyword in the Pull Request, e.g. "lttm" - 'looks testable to me' is a frequent one

if integrations.count > 0 {
if integrations.count > 0 || !self.waitForLttm {
completion(isEnabled: true)
return
}
Expand Down
16 changes: 14 additions & 2 deletions Buildasaur/StatusSyncerViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class StatusSyncerViewController: StatusViewController, SyncerDelegate {
@IBOutlet weak var statusActivityIndicator: NSProgressIndicator!
@IBOutlet weak var syncIntervalStepper: NSStepper!
@IBOutlet weak var syncIntervalTextField: NSTextField!
@IBOutlet weak var lttmToggle: NSButton!

var isSyncing: Bool {
set {
Expand Down Expand Up @@ -134,6 +135,7 @@ class StatusSyncerViewController: StatusViewController, SyncerDelegate {

self.startStopButton.title = self.isSyncing ? "Stop" : "Start"
self.syncIntervalStepper.enabled = !self.isSyncing
self.lttmToggle.enabled = !self.isSyncing

if self.isSyncing {
self.statusActivityIndicator.startAnimation(nil)
Expand All @@ -144,9 +146,10 @@ class StatusSyncerViewController: StatusViewController, SyncerDelegate {
if let syncer = self.syncer() {

self.updateIntervalFromUIToValue(syncer.syncInterval)

self.lttmToggle.state = syncer.waitForLttm ? NSOnState : NSOffState
} else {
self.updateIntervalFromUIToValue(15) //default
self.lttmToggle.state = NSOnState //default is true
}
}

Expand Down Expand Up @@ -180,6 +183,14 @@ class StatusSyncerViewController: StatusViewController, SyncerDelegate {
}
}

@IBAction func helpLttmButtonTapped(sender: AnyObject) {

let urlString = "https://github.com/czechboy0/Buildasaur/blob/master/README.md#the-lttm-barrier"
if let url = NSURL(string: urlString) {
NSWorkspace.sharedWorkspace().openURL(url)
}
}

override func prepareForSegue(segue: NSStoryboardSegue, sender: AnyObject?) {

if let manual = segue.destinationController as? ManualBotManagementViewController {
Expand All @@ -196,11 +207,12 @@ class StatusSyncerViewController: StatusViewController, SyncerDelegate {
self.storageManager.removeSyncer(syncer)
}

let waitForLttm = self.lttmToggle.state == NSOnState
let syncInterval = self.syncIntervalTextField.doubleValue
let project = self.delegate.getProjectStatusViewController().project()!
let serverConfig = self.delegate.getServerStatusViewController().serverConfig()!

if let syncer = self.storageManager.addSyncer(syncInterval, project: project, serverConfig: serverConfig) {
if let syncer = self.storageManager.addSyncer(syncInterval, waitForLttm: waitForLttm, project: project, serverConfig: serverConfig) {

syncer.active = true

Expand Down
4 changes: 2 additions & 2 deletions Buildasaur/StorageManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class StorageManager {
self.servers.append(config)
}

func addSyncer(syncInterval: NSTimeInterval, project: LocalSource, serverConfig: XcodeServerConfig) -> HDGitHubXCBotSyncer? {
func addSyncer(syncInterval: NSTimeInterval, waitForLttm: Bool, project: LocalSource, serverConfig: XcodeServerConfig) -> HDGitHubXCBotSyncer? {

if syncInterval <= 0 {
Log.error("Sync interval must be > 0 seconds.")
Expand All @@ -61,7 +61,7 @@ class StorageManager {

let xcodeServer = XcodeServerFactory.server(serverConfig)
let github = GitHubFactory.server(project.githubToken)
let syncer = HDGitHubXCBotSyncer(integrationServer: xcodeServer, sourceServer: github, localSource: project, syncInterval: syncInterval)
let syncer = HDGitHubXCBotSyncer(integrationServer: xcodeServer, sourceServer: github, localSource: project, syncInterval: syncInterval, waitForLttm: waitForLttm)
self.syncers.append(syncer)
return syncer
}
Expand Down
Binary file modified Meta/builda_screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,21 @@ Installation Steps
Default workflow
----------------
The default workflow is as follows:
- a Pull Request is created by an author, Builda creates an inactive Bot
- when someone comments "lttm" (looks testable to me) in the Pull Request conversation, Builda activates the bot, runs tests on it and reports back to GitHub with the result, by changing the status and posting a comment
- the "lttm" barrier is so that reviewers have a chance to go back and forth with the author before they are both happy with the code, at which point it makes sense to test it
- a Pull Request is created by the author, Builda creates a bot
- if the "lttm" barrier (see below) is disabled, an integration is started immediately. if the "lttm" barrier is enabled, Builda waits until someone comments "lttm" in the Pull Request conversation (the "lttm" barrier is **enabled** by default, can be disabled in the UI)
- an integration is performed on the PR's branch
- result of the integration is reported back to GitHub by changing the status of the latest commit of the branch and posting a comment in the PR conversation
- if any additional commits are pushed, another integration gets performed and reported back
- when a PR is closed, the bot gets deleted
- if you require a different workflow, create an issue and we'll figure something out

The "lttm" barrier
------------------
- an optional extra step in the workflow (**enabled** by default)
- instead of integrating immediately after a PR is created, the reviewer first has a chance to look at the code and request any fixes of the code from the author
- when the reviewer is happy with the code visually, she comments "lttm" in the PR and the bot is activated and performs and integration on the code
- from that point on, if any additional commits are pushed, they get integrated as with the basic workflow

Manual Bot Management
---------------------
In addition to automatic bot management with syncers, you can create bots from an existing Build Template and a branch by clicking *Manual Bot Management* when your syncer is setup. This is useful for creating one-off bots based on e.g. release branches with a different Build Template than you use for PRs.
Expand Down