You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A Swift interface to the travis-ci v3 API. Supports [travis-ci.org](https://travis-ci.org), [travis-ci.com](https://travis-ci.com) & on premise deployments.
4
4
5
5
[](https://travis-ci.org/iainsmith/TravisClient) | [Read the docs](https://iainsmith.github.io/TravisClient/index.html)
6
6
7
7
## Installation
8
8
9
-
* Install with cocoapods: `pod 'TravisClient'`
10
-
*Install with SPM `.package(url: "https://github.com/IainSmith/TravisClient", from: "0.2.0"),`
9
+
* Install with SPM `.package(url: "https://github.com/iainsmith/swift-travis", from: "0.3.0"),`
10
+
*The swift-travis package has the following 3 libraries you can use in your application.
| Build your own package | Codable structs |`.product(name: "TravisV3Core", package: "swift-travis")`|
17
+
18
+
### Quick example
13
19
14
20
```swift
15
21
importTravisClient
16
22
17
-
let key: String="YOUR_TRAVIS_API_KEY"
23
+
let key: String=ProcessInfo().environment["TRAVIS_TOKEN]"!
18
24
let client =TravisClient(token: key, host: .org)
19
25
20
-
client.activeBuilds { (result: Result<Meta<[Build]>, TravisError>) in
21
-
/// In swift 4.1 you can subscript directly into the Result
22
-
let activeBuildCount: Int?= result[\[Build].count]
23
-
let firstBuildPRTitle: String?= result[\.first?.pullRequestTitle]
26
+
client.userBuilds(query: query) { result in
27
+
switch result {
28
+
caselet .success(builds):
29
+
builds.count
30
+
builds.first?.pullRequestTitle
31
+
caselet .failure(error):
32
+
// error handling
33
+
}
24
34
}
25
35
```
26
36
37
+
### Swift NIO examples
38
+
39
+
```swift
40
+
import TravisClientNIO
41
+
42
+
let key:String=ProcessInfo().environment["TRAVIS_TOKEN]"!
43
+
let client =TravisClient(token: key, host: .org) // You can also pass an `EventLoopGroup`
44
+
45
+
let builds =try client.builds(forRepository: repo).wait()
46
+
print(builds.count)
47
+
print(builds.first?.pullRequestTitle)
48
+
```
49
+
27
50
## Travis API Concepts.
28
51
29
-
[Read the Travis API documentation](https://developer.travis-ci.com/gettingstarted) for much more detail. TravisClient follows the same naming conventions & concepts from the official api documentation.
52
+
The api mirrors the names & concepts from the official [Travis API documentation](https://developer.travis-ci.com/gettingstarted).
30
53
31
54
#### Minimal vs Standard Representation.
32
55
33
56
Each model object has two representations. A standard representation that includes all the attributes and a minimal representation that includes some attributes.
34
57
35
58
```swift
36
59
publicstruct MinimalJob: Codable, Minimal {
37
-
publiclet id: Int
60
+
publictypealiasFull= Job
61
+
publiclet id: Int
38
62
}
39
63
40
64
publicstruct Job:Codable {
41
-
publiclet id: Int
42
-
publiclet number: String
43
-
publiclet state: String
44
-
// 10 other properties
65
+
publiclet id: Int
66
+
publiclet number: String
67
+
publiclet state: String
68
+
// 10 other properties
45
69
}
46
70
```
47
71
@@ -54,45 +78,76 @@ let build: Meta<Build>
54
78
let minimalJob: Embed<MinimalJob>= build.jobs.first!// don't do this in production code
55
79
56
80
client.follow(embed: minimalJob) { fullJob in
57
-
print(fullJob[\.state])
81
+
print(fullJob.state)
58
82
}
59
83
```
60
84
61
-
## Usage
85
+
##### Modelling the hypermedia API
86
+
87
+
The Travis v3 API uses a custom hypermedia API spec, that is [described on their website](https://developer.travis-ci.com/hypermedia#hypermedia). The `TravisV3Core` targets has a generic `Metadata<Object>` struct.
62
88
63
89
```swift
64
-
importTravisClient
90
+
@dynamicMemberLookup
91
+
publicstruct Metadata<Object: Codable>:Codable {
92
+
publiclet type: String
93
+
publiclet path: String
94
+
publiclet pagination: Pagination<Object>?
95
+
publiclet object: Object
96
+
}
65
97
66
-
let key: String="YOUR_TRAVIS_API_KEY"
67
-
let client =TravisClient(token: key, host: .org)
98
+
let builds: Metadata<[Build]>
99
+
// dynamicMemberLookup means we can often use Metadata<[Build]> as [Build]
100
+
builds.count== builds.object.count
101
+
```
68
102
69
-
client.activeBuilds { (result: Result<Meta<[Build]>, TravisError>) in
103
+
Metadata<Object> gives us direct access to the `Pagination` data and the underlying `Object` through dynamicMemberLookup.
70
104
71
-
#ifswift(>=4.1)
72
-
/// In swift 4.1 you can subscript directly into the Result
73
-
let activeBuildCount: Int?= result[\Build.id]
74
-
#else
75
-
/// In swift 4.0 you need to subscript into the optional value of a result.
76
-
let resultBuildNumber: Int?= result.value?[\.id]
77
-
#endif
105
+
The travis API often nests resources which is modelled with the `Embed<Object>` struct.
78
106
107
+
```swift
108
+
@dynamicMemberLookup
109
+
publicstruct Embed<Object: Codable>:Codable {
110
+
publiclet type: String
111
+
publiclet path: String?
112
+
publiclet object: Object
113
+
}
114
+
115
+
structBuild {
116
+
publiclet repository: Embed<MinimalRepository>
117
+
publiclet branch: Embed<MinimalBranch>
118
+
publiclet commit: Embed<MinimalCommit>
119
+
}
120
+
121
+
let build: Metadata<Build>
122
+
let branchName:String= build.branch.name
123
+
```
124
+
125
+
##### Links
126
+
* You can call `client.follow(page:)` to load the a page of results from the paginated API
127
+
* Similarly you can all `client.follow(embed:)` to fetch the Full version of a MinimalResource. e.g `MinimalBranch` -> `Branch`.
128
+
129
+
130
+
```swift
131
+
import TravisClient
132
+
133
+
client.activeBuilds { (result: Result<MetaData<[Build]>, TravisError>) in
// Each API call returns one resource that has a 'standard representation' full object in this case supports hyper media so you can easily load the full object in a second request.
90
-
client.follow(job) { (jobResult: Meta<Job>) in
144
+
// Each API call returns one resource that has a 'standard representation' full object in this case supports hyper media so you can easily load the full object in a second request.
145
+
client.follow(embed: job) { (jobResult: Result<MetaData<Job>>) in
91
146
print(jobResult)
92
147
}
93
148
94
149
// Or follow a paginated request
95
-
client.follow(builds.pagination?.next) { nextPage in
150
+
client.follow(page: builds.pagination.next) { nextPage in
96
151
print(nextPage)
97
152
}
98
153
@@ -107,17 +162,24 @@ client.activeBuilds { (result: Result<Meta<[Build]>, TravisError>) in
107
162
108
163
```sh
109
164
# JSON parsing tests
110
-
> swift test --filter TravisClientTests.JSONTests
165
+
> swift test
111
166
112
-
# Hit the travis.org API
167
+
# Hit the travis.org API
113
168
> TRAVIS_TOKEN=YOUR_TOKEN_HERE swift test
114
169
```
115
170
171
+
The Integration tests only run if you have a `TRAVIS_TOKEN` environment variable set. This uses `XCTSkipIf` which requires Xcode 11.
172
+
173
+
## Supported swift versions
174
+
175
+
If you are using Swift 5.1 or newer you can use the latest release
176
+
If you need support for Swift 4.2 or older use version `0.2.0`
0 commit comments