forked from yext/teamcity
-
Notifications
You must be signed in to change notification settings - Fork 0
/
build.go
243 lines (209 loc) · 7.09 KB
/
build.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
package teamcity
import (
"strconv"
"strings"
"time"
)
const (
dateFormat = "20060102T150405-0700"
)
// Builds is a list of builds
type Builds struct {
Count int `json:"count,omitempty"`
NextHref string `json:"nextHref,omitempty"`
Builds []Build `json:"build"`
}
// Build is an instance of a stage in the build chain for a given project
type Build struct {
Id int `json:"id,omitempty"`
Number string `json:"number,omitempty"`
BuildTypeId string `json:"buildTypeId,omitempty"`
BuildType BuildType `json:"buildType,omitempty"`
Status string `json:"status,omitempty"`
State string `json:"state,omitempty"`
Href string `json:"href,omitempty"`
StatusText string `json:"statusText,omitempty"`
QueuedDate Time `json:"queuedDate,omitempty"`
StartDate Time `json:"startDate,omitempty"`
FinishDate Time `json:"finishDate,omitempty"`
Changes Changes `json:"changes,omitempty"`
LastChanges Changes `json:"lastChanges,omitempty"`
Triggered Triggered `json:"triggered,omitempty"`
Comment Comment `json:"comment,omitempty"`
Properties Params `json:"properties,omitempty"`
WebUrl string `json:"webUrl,omitempty"`
BuildStatistics BuildStatistics `json:"statistics,omitempty"`
}
// BuildType is a type of Build
type BuildType struct {
Id string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
SnapshotDependencies *SnapshotDependencies `json:"snapshot-dependencies,omitempty"`
Project *Project `json:"project,omitempty"`
VcsRootEntries *VcsRootEntries `json:"vcs-root-entries"`
Template *BuildType `json:"template,omitempty"`
Parameters *Params `json:"parameters,omitempty"`
}
// BuildTypes is a container for a list of BuildType's
type BuildTypes struct {
BuildTypes []BuildType `json:"buildType,omitempty"`
}
// Dependency is a build type's artifact or snapshot dependency
type Dependency struct {
Id string `json:"id,omitempty"`
Type string `json:"type,omitempty"`
SourceBuildType BuildType `json:"source-buildType,omitempty"`
PropertyList *PropertyList `json:"properties,omitempty"`
}
type ArtifactDependencies struct {
ArtifactDependencies []Dependency `json:"artifact-dependency"`
}
// PropertyList is a list of name-value attributes describing some entity.
type PropertyList struct {
Count int `json:"count"`
Properties []Property `json:"property"`
}
func NewPropertyList(m map[string]string) *PropertyList {
var props []Property
for k, v := range m {
props = append(props, Property{Name: k, Value: v})
}
return &PropertyList{Count: len(props), Properties: props}
}
// Value returns the named property's value, or empty string if not found.
func (pl *PropertyList) Value(name string) string {
if pl == nil {
return ""
}
for _, v := range pl.Properties {
if v.Name == name {
return v.Value
}
}
return ""
}
// Bool returns the named property's boolean value, or false if not found.
func (pl *PropertyList) Bool(name string) bool {
if pl == nil {
return false
}
var val = pl.Value(name)
b, err := strconv.ParseBool(val)
if err != nil {
return false
}
return b
}
// Comment is a description for a Build instance
type Comment struct {
Text string `json:"text"`
}
// Changes are the list of changes that corresponds to a certain build
type Changes struct {
Changes []Change `json:"change"`
}
// GetChange returns the most relevant Change describing the build, prioritizing
// Build.Changes over Build.LastChanges out of preference for changes to non-TeamCity repos
func (b *Build) GetChange() Change {
if len(b.Changes.Changes) > 0 {
return b.Changes.Changes[0]
}
if len(b.LastChanges.Changes) > 0 {
return b.LastChanges.Changes[0]
}
return Change{}
}
// Change is an individual change in a group that corresponds to a certain build
type Change struct {
Id int `json:"id,omitempty"`
Version string `json:"version,omitempty"`
Username string `json:"username,omitempty"`
Date Time `json:"date,omitempty"`
Comment string `json:"comment,omitempty"`
}
// GetShortVersion returns the first 8 characters of the change version
func (c *Change) GetShortVersion() string {
var v string
if len(c.Version) >= 8 {
v = c.Version[:8]
}
return v
}
// BuildsByDate is an interface for sorting a Build array by Date
type BuildsByDate []Build
// Functions for using Golang "sort" package
func (c BuildsByDate) Len() int { return len(c) }
func (c BuildsByDate) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c BuildsByDate) Less(i, j int) bool {
timeA := time.Time(c[i].Triggered.Date)
timeB := time.Time(c[j].Triggered.Date)
return timeA.Before(timeB)
}
// SnapshotDependencies is a container for SnapshotDependency's
type SnapshotDependencies struct {
SnapshotDependencies []SnapshotDependency `json:"snapshot-dependency,omitempty"`
}
// SnapshotDependency relates a build type to its source build type
type SnapshotDependency struct {
SourceBuildType BuildType `json:"source-buildType,omitempty"`
}
// VcsRootEntries is a list of VcsRootEntry
type VcsRootEntries struct {
VcsRootEntries []VcsRootEntry `json:"vcs-root-entry,omitempty"`
}
// VcsRootEntry is a version control system entry for a build type
type VcsRootEntry struct {
Id string `json:"id,omitempty"`
VcsRoot VcsRoot `json:"vcs-root,omitempty"`
}
// VcsRoot is a the id, name and properties of a version control system
type VcsRoot struct {
Id string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
PropertyList *PropertyList `json:"properties,omitempty"`
}
type BuildStatistics struct {
StatisticsEntries []StatisticsEntry `json:"property,omitempty"`
}
// StatisticsEntry gives a name-value pair of a statistic
type StatisticsEntry struct {
Name string `json:"name,omitempty"`
Value string `json:"value,omitempty"`
}
type Tag struct {
Name string `json:"name,omitempty"`
}
type Tags struct {
Tags []Tag `json:"tag,omitempty"`
}
func NewTags(t []string) *Tags {
tags := []Tag{}
for _, tag := range t {
tags = append(tags, Tag{Name: tag})
}
return &Tags{Tags: tags}
}
// Triggered describes what triggered a particular build
type Triggered struct {
Date Time `json:"date,omitempty"`
User User `json:"user,omitempty"`
}
// User describes a user on TeamCity
type User struct {
Username string `json:"username,omitempty"`
}
// Time is the date in the format TeamCity provides
type Time time.Time
// UnmarshalJSON unmarshals the time using the TeamCity format
func (t *Time) UnmarshalJSON(buf []byte) error {
tt, err := time.Parse(dateFormat, strings.Trim(string(buf), `"`))
if err != nil {
return err
}
*t = Time(tt)
return nil
}
// MarshalJSON marshals the time using the TeamCity format
func (t Time) MarshalJSON() ([]byte, error) {
return []byte(`"` + time.Time(t).Format(dateFormat) + `"`), nil
}