Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
28 changes: 18 additions & 10 deletions teamcity/build_feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ type BuildFeature interface {
ID() string
SetID(value string)
Type() string
VcsRootID() string
SetVcsRootID(value string)
Properties() *Properties
BuildTypeID() string
SetBuildTypeID(value string)
Expand All @@ -33,7 +31,6 @@ type buildFeatureJSON struct {
Inherited *bool `json:"inherited,omitempty" xml:"inherited"`
Properties *Properties `json:"properties,omitempty"`
Type string `json:"type,omitempty" xml:"type"`
VcsRootID string `json:"vcsRootId,omitempty" xml:"vcsRootId"`
}

// Features is a collection of BuildFeature
Expand All @@ -51,10 +48,11 @@ type BuildFeatureService struct {
}

func newBuildFeatureService(buildTypeID string, c *http.Client, base *sling.Sling) *BuildFeatureService {
locator := LocatorID(buildTypeID)
return &BuildFeatureService{
BuildTypeID: buildTypeID,
httpClient: c,
base: base.New().Path(fmt.Sprintf("buildTypes/%s/features/", buildTypeID)),
base: base.New().Path(fmt.Sprintf("buildTypes/%s/features/", locator)),
}
}

Expand All @@ -65,7 +63,6 @@ func (s *BuildFeatureService) Create(bf BuildFeature) (BuildFeature, error) {
}

req, err := s.base.New().Post("").BodyJSON(bf).Request()

if err != nil {
return nil, err
}
Expand Down Expand Up @@ -145,12 +142,23 @@ func (s *BuildFeatureService) readBuildFeatureResponse(resp *http.Response) (Bui
var out BuildFeature
switch payload.Type {
case "commit-status-publisher":
var csp FeatureCommitStatusPublisher
if err := csp.UnmarshalJSON(bodyBytes); err != nil {
return nil, err
}
{
var csp FeatureCommitStatusPublisher
if err := csp.UnmarshalJSON(bodyBytes); err != nil {
return nil, err
}

out = &csp
out = &csp
}
case "golang":
{
var csp FeatureGolangPublisher
if err := csp.UnmarshalJSON(bodyBytes); err != nil {
return nil, err
}

out = &csp
}
default:
return nil, fmt.Errorf("Unsupported build feature type: '%s' (id:'%s') for buildTypeID: %s", payload.Type, payload.ID, s.BuildTypeID)
}
Expand Down
34 changes: 34 additions & 0 deletions teamcity/build_feature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type SuiteBuildFeature struct {
VcsRootID string

Github *teamcity.FeatureCommitStatusPublisher
Golang *teamcity.FeatureGolangPublisher
}

func NewSuiteBuildFeature(t *testing.T) *SuiteBuildFeature {
Expand All @@ -29,6 +30,7 @@ func (suite *SuiteBuildFeature) SetupTest() {

opt := teamcity.NewCommitStatusPublisherGithubOptionsToken("https://api.github.com", "1234")
suite.Github, _ = teamcity.NewFeatureCommitStatusPublisherGithub(opt, suite.BuildTypeContext.VcsRoot.ID)
suite.Golang = teamcity.NewFeatureGolang()
}

func (suite *SuiteBuildFeature) TearDownTest() {
Expand Down Expand Up @@ -73,6 +75,38 @@ func (suite *SuiteBuildFeature) TestCommitPublisher_Get() {
suite.Equal(suite.VcsRootID, csp.VcsRootID())
}

func (suite *SuiteBuildFeature) TestGolang_Create() {
sut := suite.Service()
actual, err := sut.Create(suite.Golang)
suite.Require().NoError(err)

suite.Require().IsType(new(teamcity.FeatureGolangPublisher), actual)

csp := actual.(*teamcity.FeatureGolangPublisher)

suite.NotEqual("", csp.ID())
suite.Equal(suite.BuildTypeID, csp.BuildTypeID())
suite.Equal("golang", csp.Type())
suite.Equal(false, csp.Disabled())
}

func (suite *SuiteBuildFeature) TestGolang_Get() {
sut := suite.Service()
actual, err := sut.Create(suite.Golang)
suite.Require().NoError(err)

actual, err = sut.GetByID(actual.ID())
suite.Require().NoError(err)
suite.Require().IsType(new(teamcity.FeatureGolangPublisher), actual)

csp := actual.(*teamcity.FeatureGolangPublisher)

suite.NotEqual("", csp.ID())
suite.Equal(suite.BuildTypeID, csp.BuildTypeID())
suite.Equal("golang", csp.Type())
suite.Equal(false, csp.Disabled())
}

func TestBuildFeatureSuite(t *testing.T) {
suite.Run(t, NewSuiteBuildFeature(t))
}
2 changes: 1 addition & 1 deletion teamcity/build_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ func newBuildTypeService(base *sling.Sling, httpClient *http.Client) *BuildTypeS
}

// Create Creates a new build type under a project
func (s *BuildTypeService) Create(projectID string, buildType *BuildType) (*BuildTypeReference, error) {
func (s *BuildTypeService) Create(buildType *BuildType) (*BuildTypeReference, error) {
var created BuildTypeReference

err := s.restHelper.post("", buildType, &created, "Build Type")
Expand Down
4 changes: 2 additions & 2 deletions teamcity/build_type_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func TestBuildType_CreateWithParameters(t *testing.T) {
bt.Parameters.AddOrReplaceValue(teamcity.ParameterTypes.System, "param2", "value2")

sut := client.BuildTypes
created, err := sut.Create(project.ID, bt)
created, err := sut.Create(bt)
require.NoError(t, err)

actual, _ := sut.GetByID(created.ID) //Refresh
Expand Down Expand Up @@ -276,7 +276,7 @@ func createTestBuildTypeInternal(t *testing.T, client *teamcity.Client, buildTyp

newBuildType := getTestBuildTypeData(name, "Inspection", buildTypeProjectId, template)

createdBuildType, err := client.BuildTypes.Create(buildTypeProjectId, newBuildType)
createdBuildType, err := client.BuildTypes.Create(newBuildType)
if err != nil {
t.Fatalf("Failed to CreateBuildType: %s", err)
}
Expand Down
4 changes: 2 additions & 2 deletions teamcity/feature_commit_publisher.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ func (f *FeatureCommitStatusPublisher) Type() string {
return "commit-status-publisher"
}

//VcsRootID returns the ID that this build feature is associated with.
//VcsRootID returns the VCS Root ID that this build feature is associated with.
func (f *FeatureCommitStatusPublisher) VcsRootID() string {
return f.vcsRootID
}

//SetVcsRootID sets the ID that this build feature is associated with.
//SetVcsRootID sets the VCS Root ID that this build feature is associated with.
func (f *FeatureCommitStatusPublisher) SetVcsRootID(value string) {
f.vcsRootID = value
}
Expand Down
94 changes: 94 additions & 0 deletions teamcity/feature_golang.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package teamcity

import (
"encoding/json"
)

//FeatureCommitStatusPublisher represents a golang build feature. Implements BuildFeature interface
type FeatureGolangPublisher struct {
id string
disabled bool
buildTypeID string

properties *Properties
}

// NewFeatureGolang returns a new instance of the FeatureGolangPublisher struct
func NewFeatureGolang() *FeatureGolangPublisher {
return &FeatureGolangPublisher{
properties: NewProperties(),
}
}

//ID returns the ID for this instance.
func (f *FeatureGolangPublisher) ID() string {
return f.id
}

//SetID sets the ID for this instance.
func (f *FeatureGolangPublisher) SetID(value string) {
f.id = value
}

//Type returns the "commit-status-publisher", the keyed-type for this build feature instance
func (f *FeatureGolangPublisher) Type() string {
return "golang"
}

//Disabled returns whether this build feature is disabled or not.
func (f *FeatureGolangPublisher) Disabled() bool {
return f.disabled
}

//SetDisabled sets whether this build feature is disabled or not.
func (f *FeatureGolangPublisher) SetDisabled(value bool) {
f.disabled = value
}

//BuildTypeID is a getter for the Build Type ID associated with this build feature.
func (f *FeatureGolangPublisher) BuildTypeID() string {
return f.buildTypeID
}

//SetBuildTypeID is a setter for the Build Type ID associated with this build feature.
func (f *FeatureGolangPublisher) SetBuildTypeID(value string) {
f.buildTypeID = value
}

//Properties returns a *Properties instance representing a serializable collection to be used.
func (f *FeatureGolangPublisher) Properties() *Properties {
return f.properties
}

//MarshalJSON implements JSON serialization for FeatureCommitStatusPublisher
func (f *FeatureGolangPublisher) MarshalJSON() ([]byte, error) {
out := &buildFeatureJSON{
ID: f.id,
Disabled: NewBool(f.disabled),
Properties: f.properties,
Inherited: NewFalse(),
Type: f.Type(),
}

// this is the only value and has to be set to this - no no point making it user configurable
out.Properties.AddOrReplaceValue("test.format", "json")
return json.Marshal(out)
}

//UnmarshalJSON implements JSON deserialization for FeatureCommitStatusPublisher
func (f *FeatureGolangPublisher) UnmarshalJSON(data []byte) error {
var aux buildFeatureJSON
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
f.id = aux.ID

disabled := aux.Disabled
if disabled == nil {
disabled = NewFalse()
}
f.disabled = *disabled
f.properties = NewProperties(aux.Properties.Items...)

return nil
}
59 changes: 59 additions & 0 deletions teamcity/feature_golang_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package teamcity_test

import (
"fmt"
"testing"
"time"

"github.com/cvbarros/go-teamcity/teamcity"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestFeatureGolang_Lifecycle(t *testing.T) {
name := fmt.Sprintf("Project %d", time.Now().Unix())
newProject := getTestProjectData(name, "")
client := setup()

project, err := client.Projects.Create(newProject)
require.NoError(t, err)
defer cleanUpProject(t, client, project.ID)

buildType, err := teamcity.NewBuildType(project.ID, "Hello")
require.NoError(t, err)
buildConfig, err := client.BuildTypes.Create(buildType)
require.NoError(t, err)

service := client.BuildFeatureService(buildConfig.ID)
feature := teamcity.NewFeatureGolang()
feature.SetBuildTypeID(buildConfig.ID)
createdService, err := service.Create(feature)
require.NoError(t, err)

retrievedService, err := service.GetByID(createdService.ID())
require.NoError(t, err)
assert.False(t, retrievedService.Disabled())
}

func TestFeatureGolang_UnmarshallProperties(t *testing.T) {
assert := assert.New(t)
var actual teamcity.FeatureGolangPublisher
const json = `
{
"id": "BUILD_EXT_1",
"type": "golang",
"properties": {
"count": 1,
"property": [
{
"name": "test.format",
"value": "json"
}
]
}
}
`
actual.UnmarshalJSON([]byte(json))

assert.Equal("BUILD_EXT_1", actual.ID())
}