Skip to content

Commit

Permalink
Merge pull request #184 from czechboy0/hd/new_comment_summary
Browse files Browse the repository at this point in the history
Refactored comment creation (+ added tests)
  • Loading branch information
czechboy0 committed Oct 15, 2015
2 parents f24cc3d + 6015883 commit 3b9cf1e
Show file tree
Hide file tree
Showing 6 changed files with 427 additions and 121 deletions.
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

0 comments on commit 3b9cf1e

Please sign in to comment.