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

Refactored comment creation (+ added tests) #184

Merged
merged 2 commits into from
Oct 15, 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
181 changes: 181 additions & 0 deletions BuildaKit/SummaryBuilder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
//
// SummaryCreator.swift
// Buildasaur
//
// Created by Honza Dvorsky on 10/15/15.
// Copyright © 2015 Honza Dvorsky. All rights reserved.
//

import Foundation
import XcodeServerSDK
import BuildaUtils
import BuildaGitServer

class SummaryBuilder {

var lines: [String] = []
let resultString: String
var linkBuilder: (Integration) -> String? = { _ in nil }

init() {
self.resultString = "*Result*: "
}

//MARK: high level

func buildPassing(integration: Integration) -> HDGitHubXCBotSyncer.GitHubStatusAndComment {

let linkToIntegration = self.linkBuilder(integration)
self.addBaseCommentFromIntegration(integration)

let status = HDGitHubXCBotSyncer.createStatusFromState(.Success, description: "Build passed!", targetUrl: linkToIntegration)

let buildResultSummary = integration.buildResultSummary!
if integration.result == .Succeeded {
self.appendTestsPassed(buildResultSummary)
} else if integration.result == .Warnings {
self.appendWarnings(buildResultSummary)
} else if integration.result == .AnalyzerWarnings {
self.appendAnalyzerWarnings(buildResultSummary)
}

//and code coverage
self.appendCodeCoverage(buildResultSummary)

return self.buildWithStatus(status)
}

func buildFailingTests(integration: Integration) -> HDGitHubXCBotSyncer.GitHubStatusAndComment {

let linkToIntegration = self.linkBuilder(integration)

self.addBaseCommentFromIntegration(integration)

let status = HDGitHubXCBotSyncer.createStatusFromState(.Failure, description: "Build failed tests!", targetUrl: linkToIntegration)
let buildResultSummary = integration.buildResultSummary!
self.appendTestFailure(buildResultSummary)
return self.buildWithStatus(status)
}

func buildErrorredIntegration(integration: Integration) -> HDGitHubXCBotSyncer.GitHubStatusAndComment {

let linkToIntegration = self.linkBuilder(integration)
self.addBaseCommentFromIntegration(integration)

let status = HDGitHubXCBotSyncer.createStatusFromState(.Error, description: "Build error!", targetUrl: linkToIntegration)

self.appendErrors(integration)
return self.buildWithStatus(status)
}

func buildCanceledIntegration(integration: Integration) -> HDGitHubXCBotSyncer.GitHubStatusAndComment {

let linkToIntegration = self.linkBuilder(integration)

self.addBaseCommentFromIntegration(integration)

let status = HDGitHubXCBotSyncer.createStatusFromState(.Error, description: "Build canceled!", targetUrl: linkToIntegration)

self.appendCancel()
return self.buildWithStatus(status)
}

func buildEmptyIntegration() -> HDGitHubXCBotSyncer.GitHubStatusAndComment {

let status = HDGitHubXCBotSyncer.createStatusFromState(.NoState, description: nil, targetUrl: nil)
return (status: status, comment: nil)
}

//MARK: utils

func addBaseCommentFromIntegration(integration: Integration) {

var integrationText = "Integration \(integration.number)"
if let link = self.linkBuilder(integration) {
//linkify
integrationText = "[\(integrationText)](\(link))"
}

self.lines.append("Result of \(integrationText)")
self.lines.append("---")

if let duration = self.formattedDurationOfIntegration(integration) {
self.lines.append("*Duration*: " + duration)
}
}

func appendTestsPassed(buildResultSummary: BuildResultSummary) {

let testsCount = buildResultSummary.testsCount
let testSection = testsCount > 0 ? "All \(testsCount) " + "test".pluralizeStringIfNecessary(testsCount) + " passed. " : ""
self.lines.append(self.resultString + "**Perfect build!** \(testSection):+1:")
}

func appendWarnings(buildResultSummary: BuildResultSummary) {

let warningCount = buildResultSummary.warningCount
let testsCount = buildResultSummary.testsCount
self.lines.append(self.resultString + "All \(testsCount) tests passed, but please **fix \(warningCount) " + "warning".pluralizeStringIfNecessary(warningCount) + "**.")
}

func appendAnalyzerWarnings(buildResultSummary: BuildResultSummary) {

let analyzerWarningCount = buildResultSummary.analyzerWarningCount
let testsCount = buildResultSummary.testsCount
self.lines.append(self.resultString + "All \(testsCount) tests passed, but please **fix \(analyzerWarningCount) " + "analyzer warning".pluralizeStringIfNecessary(analyzerWarningCount) + "**.")
}

func appendCodeCoverage(buildResultSummary: BuildResultSummary) {

let codeCoveragePercentage = buildResultSummary.codeCoveragePercentage
if codeCoveragePercentage > 0 {
self.lines.append("*Test Coverage*: \(codeCoveragePercentage)%")
}
}

func appendTestFailure(buildResultSummary: BuildResultSummary) {

let testFailureCount = buildResultSummary.testFailureCount
let testsCount = buildResultSummary.testsCount
self.lines.append(self.resultString + "**Build failed \(testFailureCount) " + "test".pluralizeStringIfNecessary(testFailureCount) + "** out of \(testsCount)")
}

func appendErrors(integration: Integration) {

let errorCount: Int = integration.buildResultSummary?.errorCount ?? -1
self.lines.append(self.resultString + "**\(errorCount) " + "error".pluralizeStringIfNecessary(errorCount) + ", failing state: \(integration.result!.rawValue)**")
}

func appendCancel() {

//TODO: find out who canceled it and add it to the comment?
self.lines.append("Build was **manually canceled**.")
}

func buildWithStatus(status: Status) -> HDGitHubXCBotSyncer.GitHubStatusAndComment {

let comment: String?
if lines.count == 0 {
comment = nil
} else {
comment = lines.joinWithSeparator("\n")
}
return (status: status, comment: comment)
}
}

extension SummaryBuilder {

func formattedDurationOfIntegration(integration: Integration) -> String? {

if let seconds = integration.duration {

let result = TimeUtils.secondsToNaturalTime(Int(seconds))
return result

} else {
Log.error("No duration provided in integration \(integration)")
return "[NOT PROVIDED]"
}
}
}
84 changes: 17 additions & 67 deletions BuildaKit/SyncPairResolver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public class SyncPairResolver {
$0.currentStep == .Completed
}

let link = { (integration: Integration) -> String in
let link = { (integration: Integration) -> String? in
SyncPairResolver.linkToServer(hostname, bot: bot, integration: integration)
}

Expand Down Expand Up @@ -209,7 +209,7 @@ public class SyncPairResolver {
issue: Issue?,
pending: Integration?,
running: Integration?,
link: (Integration) -> String,
link: (Integration) -> String?,
completed: Set<Integration>) -> SyncPair.Actions {

let statusWithComment: HDGitHubXCBotSyncer.GitHubStatusAndComment
Expand Down Expand Up @@ -262,106 +262,56 @@ public class SyncPairResolver {
)
}

private func statusAndCommentFromLines(lines: [String], status: Status) -> HDGitHubXCBotSyncer.GitHubStatusAndComment {

let comment: String?
if lines.count == 0 {
comment = nil
} else {
comment = lines.joinWithSeparator("\n")
}
return (status: status, comment: comment)
}

func resolveStatusFromCompletedIntegrations(
integrations: Set<Integration>,
link: (Integration) -> String
link: (Integration) -> String?
) -> HDGitHubXCBotSyncer.GitHubStatusAndComment {

//get integrations sorted by number
let sortedDesc = Array(integrations).sort { $0.number > $1.number }
let resultString = "*Result*: "

let summary = SummaryBuilder()
summary.linkBuilder = link

//if there are any succeeded, it wins - iterating from the end
if let passingIntegration = sortedDesc.filter({
(integration: Integration) -> Bool in
switch integration.result! {
case Integration.Result.Succeeded, Integration.Result.Warnings, Integration.Result.AnalyzerWarnings:

case .Succeeded, .Warnings, .AnalyzerWarnings:
return true
default:
return false
}
}).first {

let linkToIntegration = link(passingIntegration)
var lines = HDGitHubXCBotSyncer.baseCommentLinesFromIntegration(passingIntegration, link: linkToIntegration)

let status = HDGitHubXCBotSyncer.createStatusFromState(.Success, description: "Build passed!", targetUrl: linkToIntegration)

let summary = passingIntegration.buildResultSummary!
if passingIntegration.result == .Succeeded {
let testsCount = summary.testsCount
lines.append(resultString + "**Perfect build!** All \(testsCount) " + "test".pluralizeStringIfNecessary(testsCount) + " passed. :+1:")
} else if passingIntegration.result == .Warnings {
let warningCount = summary.warningCount
lines.append(resultString + "All \(summary.testsCount) tests passed, but please **fix \(warningCount) " + "warning".pluralizeStringIfNecessary(warningCount) + "**.")
} else {
let analyzerWarningCount = summary.analyzerWarningCount
lines.append(resultString + "All \(summary.testsCount) tests passed, but please **fix \(analyzerWarningCount) " + "analyzer warning".pluralizeStringIfNecessary(analyzerWarningCount) + "**.")
}

//and code coverage
let codeCoveragePercentage = summary.codeCoveragePercentage
if codeCoveragePercentage > 0 {
lines.append("*Test Coverage*: \(codeCoveragePercentage)%.")
}

return self.statusAndCommentFromLines(lines, status: status)
return summary.buildPassing(passingIntegration)
}

//ok, no succeeded, warnings or analyzer warnings, get down to test failures
if let testFailingIntegration = sortedDesc.filter({
$0.result! == Integration.Result.TestFailures
$0.result! == .TestFailures
}).first {

let linkToIntegration = link(testFailingIntegration)
var lines = HDGitHubXCBotSyncer.baseCommentLinesFromIntegration(testFailingIntegration, link: linkToIntegration)
let status = HDGitHubXCBotSyncer.createStatusFromState(.Failure, description: "Build failed tests!", targetUrl: linkToIntegration)
let summary = testFailingIntegration.buildResultSummary!
let testFailureCount = summary.testFailureCount
lines.append(resultString + "**Build failed \(testFailureCount) " + "test".pluralizeStringIfNecessary(testFailureCount) + "** out of \(summary.testsCount)")
return self.statusAndCommentFromLines(lines, status: status)
return summary.buildFailingTests(testFailingIntegration)
}

//ok, the build didn't even run then. it either got cancelled or failed
if let erroredIntegration = sortedDesc.filter({
$0.result! != Integration.Result.Canceled
if let errorredIntegration = sortedDesc.filter({
$0.result! != .Canceled
}).first {

let linkToIntegration = link(erroredIntegration)
var lines = HDGitHubXCBotSyncer.baseCommentLinesFromIntegration(erroredIntegration, link: linkToIntegration)
let errorCount: Int = erroredIntegration.buildResultSummary?.errorCount ?? -1
let status = HDGitHubXCBotSyncer.createStatusFromState(.Error, description: "Build error!", targetUrl: linkToIntegration)
lines.append(resultString + "**\(errorCount) " + "error".pluralizeStringIfNecessary(errorCount) + ", failing state: \(erroredIntegration.result!.rawValue)**")
return self.statusAndCommentFromLines(lines, status: status)
return summary.buildErrorredIntegration(errorredIntegration)
}

//cool, not even build error. it must be just canceled ones then.
if let canceledIntegration = sortedDesc.filter({
$0.result! == Integration.Result.Canceled
$0.result! == .Canceled
}).first {

let linkToIntegration = link(canceledIntegration)
var lines = HDGitHubXCBotSyncer.baseCommentLinesFromIntegration(canceledIntegration, link: linkToIntegration)
let status = HDGitHubXCBotSyncer.createStatusFromState(.Error, description: "Build canceled!", targetUrl: linkToIntegration)

//TODO: find out who canceled it and add it to the comment?
lines.append("Build was **manually canceled**.")
return self.statusAndCommentFromLines(lines, status: status)
return summary.buildCanceledIntegration(canceledIntegration)
}

//hmm no idea, if we got all the way here. just leave it with no state.
let status = HDGitHubXCBotSyncer.createStatusFromState(.NoState, description: nil, targetUrl: nil)
return (status: status, comment: nil)
return summary.buildEmptyIntegration()
}
}
48 changes: 0 additions & 48 deletions BuildaKit/SyncerBotUtils.swift

This file was deleted.

Loading