Skip to content

Commit 71e1b10

Browse files
author
Thibault Wittemberg
committed
project: add ci pipeline
1 parent a20ad24 commit 71e1b10

File tree

11 files changed

+71
-41
lines changed

11 files changed

+71
-41
lines changed

.github/workflows/ci.yml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
name: Tests
2+
3+
on: [push]
4+
5+
jobs:
6+
SPM:
7+
name: "Swift Package Manager"
8+
runs-on: macOS-latest
9+
steps:
10+
- uses: actions/checkout@v2
11+
- name: Run tests
12+
run: set -o pipefail && swift test

Sources/Core/Commands/GenerateCommand.swift

+2-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ public extension Xccov.Commands {
1212
}
1313

1414
public extension Xccov.Commands.Generate {
15-
1615
enum Output: String, ExpressibleByArgument {
1716
case coberturaXml = "cobertura-xml"
1817
case failable = "failable"
@@ -46,14 +45,14 @@ public extension Xccov.Commands.Generate {
4645
.map { Self.convert(report: report, to: $0) }
4746
.reduce(Result.success([Export]())) { (previous, current) -> Result<[Export], Xccov.Error> in
4847
switch (previous, current) {
49-
case (.success(let exports), .success(let export)):
48+
case let (.success(exports), .success(export)):
5049
return .success(exports+[export])
5150
case (.failure(let error), _):
5251
return .failure(error)
5352
case (_, .failure(let error)):
5453
return .failure(error)
5554
}
56-
}
55+
}
5756
}
5857

5958
static func execute(jsonFile: String,

Sources/Core/Commons/Tools/Result+MapEach.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ public extension Result where Success: Collection {
1616
let initial: Result<[Output], Failure> = .success([Output]())
1717
return successCollection
1818
.map { success($0) }
19-
.reduce(initial) { (previous, current) -> Result<[Output], Failure> in
19+
.reduce(initial) { previous, current -> Result<[Output], Failure> in
2020
switch (previous, current) {
2121
case (.success(let outputs), .success(let output)):
2222
return .success(outputs+[output])
2323
case (.failure(let error), _):
2424
return .failure(error)
2525
case (_, .failure(let error)):
2626
return .failure(error)
27-
}
27+
}
2828
}
2929
}
3030
}

Sources/Core/Commons/Tools/Result+Verbose.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
public extension Result {
99
@discardableResult
10-
func verbose(_ verbose: Bool, onFailure failure: (Failure) -> Void = { _ in }, onSuccess success: (Success) -> Void = { _ in }) -> Self {
10+
func verbose(_ verbose: Bool, onFailure failure: (Failure) -> Void = { _ in }, onSuccess success: (Success) -> Void = { _ in }) -> Self {
1111
if verbose {
1212
switch self {
1313
case .failure(let error):

Sources/Core/Commons/Tools/String+Contains.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Foundation
99

1010
public extension String {
1111
func contains(elementsOf array: [String]) -> Bool {
12-
array.reduce(false) { (previousResult, element) -> Bool in
12+
array.reduce(false) { previousResult, element -> Bool in
1313
previousResult || self.contains(element)
1414
}
1515
}

Sources/Core/Commons/Tools/String+Write.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
public extension String {
99
func write(filename: String) -> Result<Void, Xccov.Error> {
10-
guard let _ = try? self.write(toFile: filename, atomically: true, encoding: .utf8) else {
10+
guard (try? self.write(toFile: filename, atomically: true, encoding: .utf8)) != nil else {
1111
return .failure(.unableToWriteFile(self))
1212
}
1313

Sources/Core/Converters/CoberturaXmlConverter.swift

+49-26
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,37 @@ public extension Xccov.Converters {
1111
enum CoberturaXml {}
1212
}
1313

14-
public extension Xccov.Converters.CoberturaXml {
14+
extension XMLNode {
15+
static func nodeAttribute(withName name: String, stringValue value: String) -> XMLNode {
16+
guard let attribute = XMLNode.attribute(withName: name, stringValue: value) as? XMLNode else {
17+
return XMLNode()
18+
}
1519

20+
return attribute
21+
}
22+
}
23+
24+
public extension Xccov.Converters.CoberturaXml {
1625
static func convert(coverageReport: CoverageReport) -> Result<String, Xccov.Error> {
1726
Self.convert(coverageReport: coverageReport,
1827
timeStamp: Date().timeIntervalSince1970,
1928
currentDirectoryPath: FileManager.default.currentDirectoryPath)
2029
}
2130

31+
//swiftlint:disable:next function_body_length
2232
static func convert(coverageReport: CoverageReport,
2333
timeStamp: TimeInterval = Date().timeIntervalSince1970,
2434
currentDirectoryPath: String = FileManager.default.currentDirectoryPath) -> Result<String, Xccov.Error> {
25-
let dtd = try! XMLDTD(contentsOf: URL(string: "http://cobertura.sourceforge.net/xml/coverage-04.dtd")!)
35+
guard
36+
let dtdUrl = URL(string: "http://cobertura.sourceforge.net/xml/coverage-04.dtd"),
37+
let dtd = try? XMLDTD(contentsOf: dtdUrl) else {
38+
return .failure(.conversionFailed("DTD could not be constructed"))
39+
}
40+
2641
dtd.name = "coverage"
2742
dtd.systemID = "http://cobertura.sourceforge.net/xml/coverage-04.dtd"
2843

29-
let rootElement = XMLElement(name: "coverage")
30-
rootElement.addAttribute(XMLNode.attribute(withName: "line-rate", stringValue: "\(coverageReport.lineCoverage)") as! XMLNode)
31-
rootElement.addAttribute(XMLNode.attribute(withName: "branch-rate", stringValue: "1.0") as! XMLNode)
32-
rootElement.addAttribute(XMLNode.attribute(withName: "lines-covered", stringValue: "\(coverageReport.coveredLines)") as! XMLNode)
33-
rootElement.addAttribute(XMLNode.attribute(withName: "lines-valid", stringValue: "\(coverageReport.executableLines)") as! XMLNode)
34-
rootElement.addAttribute(XMLNode.attribute(withName: "timestamp", stringValue: "\(timeStamp)") as! XMLNode)
35-
rootElement.addAttribute(XMLNode.attribute(withName: "version", stringValue: "diff_coverage 0.1") as! XMLNode)
36-
rootElement.addAttribute(XMLNode.attribute(withName: "complexity", stringValue: "0.0") as! XMLNode)
37-
rootElement.addAttribute(XMLNode.attribute(withName: "branches-valid", stringValue: "1.0") as! XMLNode)
38-
rootElement.addAttribute(XMLNode.attribute(withName: "branches-covered", stringValue: "1.0") as! XMLNode)
44+
let rootElement = Self.makeRootElement(coverageReport: coverageReport, timeStamp: timeStamp)
3945

4046
let doc = XMLDocument(rootElement: rootElement)
4147
doc.version = "1.0"
@@ -48,7 +54,7 @@ public extension Xccov.Converters.CoberturaXml {
4854

4955
let packagesElement = XMLElement(name: "packages")
5056
rootElement.addChild(packagesElement)
51-
57+
5258
// Sort files to avoid duplicated packages
5359
let allFiles = coverageReport.targets.flatMap { $0.files }.sorted { $0.path > $1.path }
5460

@@ -71,30 +77,32 @@ public extension Xccov.Converters.CoberturaXml {
7177

7278
currentPackage = packageName
7379
if isNewPackage {
74-
currentPackageElement.addAttribute(XMLNode.attribute(withName: "name", stringValue: packageName) as! XMLNode)
75-
currentPackageElement.addAttribute(XMLNode.attribute(withName: "line-rate", stringValue: "\(fileCoverageReport.lineCoverage)") as! XMLNode)
76-
currentPackageElement.addAttribute(XMLNode.attribute(withName: "branch-rate", stringValue: "1.0") as! XMLNode)
77-
currentPackageElement.addAttribute(XMLNode.attribute(withName: "complexity", stringValue: "0.0") as! XMLNode)
80+
currentPackageElement.addAttribute(XMLNode.nodeAttribute(withName: "name", stringValue: packageName))
81+
currentPackageElement.addAttribute(XMLNode.nodeAttribute(withName: "line-rate", stringValue: "\(fileCoverageReport.lineCoverage)"))
82+
currentPackageElement.addAttribute(XMLNode.nodeAttribute(withName: "branch-rate", stringValue: "1.0"))
83+
currentPackageElement.addAttribute(XMLNode.nodeAttribute(withName: "complexity", stringValue: "0.0"))
7884
}
7985

8086
let classElement = XMLElement(name: "class")
81-
classElement.addAttribute(XMLNode.attribute(withName: "name", stringValue: "\(packageName).\((fileCoverageReport.name as NSString).deletingPathExtension)") as! XMLNode)
82-
classElement.addAttribute(XMLNode.attribute(withName: "filename", stringValue: "\(filePath)") as! XMLNode)
83-
classElement.addAttribute(XMLNode.attribute(withName: "line-rate", stringValue: "\(fileCoverageReport.lineCoverage)") as! XMLNode)
84-
classElement.addAttribute(XMLNode.attribute(withName: "branch-rate", stringValue: "1.0") as! XMLNode)
85-
classElement.addAttribute(XMLNode.attribute(withName: "complexity", stringValue: "0.0") as! XMLNode)
87+
classElement.addAttribute(XMLNode.nodeAttribute(withName: "name",
88+
stringValue: "\(packageName).\((fileCoverageReport.name as NSString).deletingPathExtension)"))
89+
classElement.addAttribute(XMLNode.nodeAttribute(withName: "filename", stringValue: "\(filePath)"))
90+
classElement.addAttribute(XMLNode.nodeAttribute(withName: "line-rate", stringValue: "\(fileCoverageReport.lineCoverage)"))
91+
classElement.addAttribute(XMLNode.nodeAttribute(withName: "branch-rate", stringValue: "1.0"))
92+
classElement.addAttribute(XMLNode.nodeAttribute(withName: "complexity", stringValue: "0.0"))
8693
currentPackageElement.addChild(classElement)
8794

8895
let linesElement = XMLElement(name: "lines")
8996
classElement.addChild(linesElement)
9097

9198
for functionCoverageReport in fileCoverageReport.functions {
9299
for index in 0..<functionCoverageReport.executableLines {
93-
// Function coverage report won't be 100% reliable without parsing it by file (would need to use xccov view --file filePath currentDirectory + Build/Logs/Test/*.xccovarchive)
100+
// Function coverage report won't be 100% reliable without parsing it by file
101+
// (would need to use xccov view --file filePath currentDirectory + Build/Logs/Test/*.xccovarchive)
94102
let lineElement = XMLElement(kind: .element, options: .nodeCompactEmptyElement)
95103
lineElement.name = "line"
96-
lineElement.addAttribute(XMLNode.attribute(withName: "number", stringValue: "\(functionCoverageReport.lineNumber + index)") as! XMLNode)
97-
lineElement.addAttribute(XMLNode.attribute(withName: "branch", stringValue: "false") as! XMLNode)
104+
lineElement.addAttribute(XMLNode.nodeAttribute(withName: "number", stringValue: "\(functionCoverageReport.lineNumber + index)"))
105+
lineElement.addAttribute(XMLNode.nodeAttribute(withName: "branch", stringValue: "false"))
98106

99107
let lineHits: Int
100108
if index < functionCoverageReport.coveredLines {
@@ -103,12 +111,27 @@ public extension Xccov.Converters.CoberturaXml {
103111
lineHits = 0
104112
}
105113

106-
lineElement.addAttribute(XMLNode.attribute(withName: "hits", stringValue: "\(lineHits)") as! XMLNode)
114+
lineElement.addAttribute(XMLNode.nodeAttribute(withName: "hits", stringValue: "\(lineHits)"))
107115
linesElement.addChild(lineElement)
108116
}
109117
}
110118
}
111119

112120
return .success(doc.xmlString(options: [.nodePrettyPrint]))
113121
}
122+
123+
static func makeRootElement(coverageReport: CoverageReport, timeStamp: TimeInterval) -> XMLElement {
124+
let rootElement = XMLElement(name: "coverage")
125+
rootElement.addAttribute(XMLNode.nodeAttribute(withName: "line-rate", stringValue: "\(coverageReport.lineCoverage)"))
126+
rootElement.addAttribute(XMLNode.nodeAttribute(withName: "branch-rate", stringValue: "1.0"))
127+
rootElement.addAttribute(XMLNode.nodeAttribute(withName: "lines-covered", stringValue: "\(coverageReport.coveredLines)"))
128+
rootElement.addAttribute(XMLNode.nodeAttribute(withName: "lines-valid", stringValue: "\(coverageReport.executableLines)"))
129+
rootElement.addAttribute(XMLNode.nodeAttribute(withName: "timestamp", stringValue: "\(timeStamp)"))
130+
rootElement.addAttribute(XMLNode.nodeAttribute(withName: "version", stringValue: "diff_coverage 0.1"))
131+
rootElement.addAttribute(XMLNode.nodeAttribute(withName: "complexity", stringValue: "0.0"))
132+
rootElement.addAttribute(XMLNode.nodeAttribute(withName: "branches-valid", stringValue: "1.0"))
133+
rootElement.addAttribute(XMLNode.nodeAttribute(withName: "branches-covered", stringValue: "1.0"))
134+
135+
return rootElement
136+
}
114137
}

Sources/Core/Decoders/JsonDecoder.swift

-2
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,3 @@ public extension Xccov.Decoders.Json {
2828
return .success(coverageReport)
2929
}
3030
}
31-
32-

Sources/Core/Filters/PackagesFilter.swift

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ public extension Xccov.Filters {
1111

1212
public extension Xccov.Filters.Packages {
1313
static func filter(coverageReport: CoverageReport, packagesToExclude: [String]) -> CoverageReport {
14-
1514
guard !packagesToExclude.isEmpty else { return coverageReport }
1615

1716
let targetsToKeep = coverageReport.targets.map { target -> TargetCoverageReport in

Sources/Core/Filters/TargetsFilter.swift

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ public extension Xccov.Filters {
1111

1212
public extension Xccov.Filters.Targets {
1313
static func filter(coverageReport: CoverageReport, targetsToExclude: [String]) -> CoverageReport {
14-
1514
guard !targetsToExclude.isEmpty else { return coverageReport }
1615

1716
let targetsToKeep = coverageReport.targets.filter { !$0.name.contains(elementsOf: targetsToExclude) }

Sources/XcodeCoverageConverter/main.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct Xcc: ParsableCommand {
1212
}
1313

1414
struct Generate: ParsableCommand {
15-
public static let configuration = CommandConfiguration(abstract: "Generates a converted file from xccov results")
15+
static let configuration = CommandConfiguration(abstract: "Generates a converted file from xccov results")
1616

1717
@Argument(help: "The full path to the json file to convert")
1818
private var jsonFile: String
@@ -41,9 +41,9 @@ struct Generate: ParsableCommand {
4141
verbose: verbose)
4242

4343
switch result {
44-
case .success(_):
44+
case .success:
4545
throw CleanExit.message("All good")
46-
case .failure(_):
46+
case .failure:
4747
throw ExitCode.failure
4848
}
4949
}

0 commit comments

Comments
 (0)