From 9b9872315e64c2484502d10d70a78260fd03bf51 Mon Sep 17 00:00:00 2001 From: Jarryd Tilbrook Date: Wed, 7 Jun 2023 12:45:30 +0800 Subject: [PATCH 1/7] SUP-863 Add generated code for pipeline update --- buildkite/generated.go | 271 +++++++++++++++++++++++++++++ buildkite/graphql/pipeline.graphql | 8 + schema.graphql | 103 +++++++++-- 3 files changed, 371 insertions(+), 11 deletions(-) diff --git a/buildkite/generated.go b/buildkite/generated.go index 9c9d860a..752a05f2 100644 --- a/buildkite/generated.go +++ b/buildkite/generated.go @@ -6,6 +6,26 @@ import ( "github.com/Khan/genqlient/graphql" ) +// All the possible build retention periods, depending on your billing plan +type BuildRetentionPeriods string + +const ( + // 30 days + BuildRetentionPeriodsDays30 BuildRetentionPeriods = "DAYS_30" + // 60 days + BuildRetentionPeriodsDays60 BuildRetentionPeriods = "DAYS_60" + // 90 days + BuildRetentionPeriodsDays90 BuildRetentionPeriods = "DAYS_90" + // 6 months + BuildRetentionPeriodsMonths6 BuildRetentionPeriods = "MONTHS_6" + // 12 months + BuildRetentionPeriodsMonths12 BuildRetentionPeriods = "MONTHS_12" + // 18 months + BuildRetentionPeriodsMonths18 BuildRetentionPeriods = "MONTHS_18" + // 2 years + BuildRetentionPeriodsYears2 BuildRetentionPeriods = "YEARS_2" +) + // The roles a user can be within a team type GTeamMemberRole string @@ -26,6 +46,178 @@ const ( GenqlientTeamPrivacySecret GenqlientTeamPrivacy = "SECRET" ) +// Repository information for a pipeline +type PipelineRepositoryInput struct { + // Repository information for a pipeline + Url string `json:"url"` +} + +// GetUrl returns PipelineRepositoryInput.Url, and is useful for accessing the field via an interface. +func (v *PipelineRepositoryInput) GetUrl() string { return v.Url } + +// Step definition for a pipeline +type PipelineStepsInput struct { + // Step definition for a pipeline + Yaml string `json:"yaml"` +} + +// GetYaml returns PipelineStepsInput.Yaml, and is useful for accessing the field via an interface. +func (v *PipelineStepsInput) GetYaml() string { return v.Yaml } + +// Tag associated with a pipeline +type PipelineTagInput struct { + // Tag associated with a pipeline + Label string `json:"label"` +} + +// GetLabel returns PipelineTagInput.Label, and is useful for accessing the field via an interface. +func (v *PipelineTagInput) GetLabel() string { return v.Label } + +// Autogenerated input type of PipelineUpdate +type PipelineUpdateInput struct { + // Autogenerated input type of PipelineUpdate + ClientMutationId string `json:"clientMutationId"` + // Autogenerated input type of PipelineUpdate + Id string `json:"id"` + // Autogenerated input type of PipelineUpdate + Name string `json:"name"` + // Autogenerated input type of PipelineUpdate + Description string `json:"description"` + // Autogenerated input type of PipelineUpdate + Emoji string `json:"emoji"` + // Autogenerated input type of PipelineUpdate + Color string `json:"color"` + // Autogenerated input type of PipelineUpdate + Visibility PipelineVisibility `json:"visibility"` + // Autogenerated input type of PipelineUpdate + Repository PipelineRepositoryInput `json:"repository"` + // Autogenerated input type of PipelineUpdate + Steps PipelineStepsInput `json:"steps"` + // Autogenerated input type of PipelineUpdate + DefaultBranch string `json:"defaultBranch"` + // Autogenerated input type of PipelineUpdate + NextBuildNumber int `json:"nextBuildNumber"` + // Autogenerated input type of PipelineUpdate + SkipIntermediateBuilds bool `json:"skipIntermediateBuilds"` + // Autogenerated input type of PipelineUpdate + SkipIntermediateBuildsBranchFilter string `json:"skipIntermediateBuildsBranchFilter"` + // Autogenerated input type of PipelineUpdate + CancelIntermediateBuilds bool `json:"cancelIntermediateBuilds"` + // Autogenerated input type of PipelineUpdate + CancelIntermediateBuildsBranchFilter string `json:"cancelIntermediateBuildsBranchFilter"` + // Autogenerated input type of PipelineUpdate + AllowRebuilds bool `json:"allowRebuilds"` + // Autogenerated input type of PipelineUpdate + DefaultTimeoutInMinutes int `json:"defaultTimeoutInMinutes"` + // Autogenerated input type of PipelineUpdate + MaximumTimeoutInMinutes int `json:"maximumTimeoutInMinutes"` + // Autogenerated input type of PipelineUpdate + BuildRetentionEnabled bool `json:"buildRetentionEnabled"` + // Autogenerated input type of PipelineUpdate + BuildRetentionPeriod BuildRetentionPeriods `json:"buildRetentionPeriod"` + // Autogenerated input type of PipelineUpdate + BuildRetentionNumber int `json:"buildRetentionNumber"` + // Autogenerated input type of PipelineUpdate + ClusterId string `json:"clusterId"` + // Autogenerated input type of PipelineUpdate + Archived bool `json:"archived"` + // Autogenerated input type of PipelineUpdate + Tags []PipelineTagInput `json:"tags"` + // Autogenerated input type of PipelineUpdate + BranchConfiguration string `json:"branchConfiguration"` +} + +// GetClientMutationId returns PipelineUpdateInput.ClientMutationId, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetClientMutationId() string { return v.ClientMutationId } + +// GetId returns PipelineUpdateInput.Id, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetId() string { return v.Id } + +// GetName returns PipelineUpdateInput.Name, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetName() string { return v.Name } + +// GetDescription returns PipelineUpdateInput.Description, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetDescription() string { return v.Description } + +// GetEmoji returns PipelineUpdateInput.Emoji, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetEmoji() string { return v.Emoji } + +// GetColor returns PipelineUpdateInput.Color, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetColor() string { return v.Color } + +// GetVisibility returns PipelineUpdateInput.Visibility, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetVisibility() PipelineVisibility { return v.Visibility } + +// GetRepository returns PipelineUpdateInput.Repository, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetRepository() PipelineRepositoryInput { return v.Repository } + +// GetSteps returns PipelineUpdateInput.Steps, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetSteps() PipelineStepsInput { return v.Steps } + +// GetDefaultBranch returns PipelineUpdateInput.DefaultBranch, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetDefaultBranch() string { return v.DefaultBranch } + +// GetNextBuildNumber returns PipelineUpdateInput.NextBuildNumber, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetNextBuildNumber() int { return v.NextBuildNumber } + +// GetSkipIntermediateBuilds returns PipelineUpdateInput.SkipIntermediateBuilds, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetSkipIntermediateBuilds() bool { return v.SkipIntermediateBuilds } + +// GetSkipIntermediateBuildsBranchFilter returns PipelineUpdateInput.SkipIntermediateBuildsBranchFilter, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetSkipIntermediateBuildsBranchFilter() string { + return v.SkipIntermediateBuildsBranchFilter +} + +// GetCancelIntermediateBuilds returns PipelineUpdateInput.CancelIntermediateBuilds, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetCancelIntermediateBuilds() bool { return v.CancelIntermediateBuilds } + +// GetCancelIntermediateBuildsBranchFilter returns PipelineUpdateInput.CancelIntermediateBuildsBranchFilter, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetCancelIntermediateBuildsBranchFilter() string { + return v.CancelIntermediateBuildsBranchFilter +} + +// GetAllowRebuilds returns PipelineUpdateInput.AllowRebuilds, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetAllowRebuilds() bool { return v.AllowRebuilds } + +// GetDefaultTimeoutInMinutes returns PipelineUpdateInput.DefaultTimeoutInMinutes, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetDefaultTimeoutInMinutes() int { return v.DefaultTimeoutInMinutes } + +// GetMaximumTimeoutInMinutes returns PipelineUpdateInput.MaximumTimeoutInMinutes, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetMaximumTimeoutInMinutes() int { return v.MaximumTimeoutInMinutes } + +// GetBuildRetentionEnabled returns PipelineUpdateInput.BuildRetentionEnabled, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetBuildRetentionEnabled() bool { return v.BuildRetentionEnabled } + +// GetBuildRetentionPeriod returns PipelineUpdateInput.BuildRetentionPeriod, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetBuildRetentionPeriod() BuildRetentionPeriods { + return v.BuildRetentionPeriod +} + +// GetBuildRetentionNumber returns PipelineUpdateInput.BuildRetentionNumber, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetBuildRetentionNumber() int { return v.BuildRetentionNumber } + +// GetClusterId returns PipelineUpdateInput.ClusterId, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetClusterId() string { return v.ClusterId } + +// GetArchived returns PipelineUpdateInput.Archived, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetArchived() bool { return v.Archived } + +// GetTags returns PipelineUpdateInput.Tags, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetTags() []PipelineTagInput { return v.Tags } + +// GetBranchConfiguration returns PipelineUpdateInput.BranchConfiguration, and is useful for accessing the field via an interface. +func (v *PipelineUpdateInput) GetBranchConfiguration() string { return v.BranchConfiguration } + +// The visibility of the pipeline +type PipelineVisibility string + +const ( + // The pipeline is public + PipelineVisibilityPublic PipelineVisibility = "PUBLIC" + // The pipeline is private + PipelineVisibilityPrivate PipelineVisibility = "PRIVATE" +) + // __getOrganizationInput is used internally by genqlient type __getOrganizationInput struct { Slug string `json:"slug"` @@ -62,6 +254,14 @@ func (v *__setApiIpAddressesInput) GetOrganizationID() string { return v.Organiz // GetIpAddresses returns __setApiIpAddressesInput.IpAddresses, and is useful for accessing the field via an interface. func (v *__setApiIpAddressesInput) GetIpAddresses() string { return v.IpAddresses } +// __updatePipelineInput is used internally by genqlient +type __updatePipelineInput struct { + Input PipelineUpdateInput `json:"input"` +} + +// GetInput returns __updatePipelineInput.Input, and is useful for accessing the field via an interface. +func (v *__updatePipelineInput) GetInput() PipelineUpdateInput { return v.Input } + // getOrganizationOrganization includes the requested fields of the GraphQL type Organization. // The GraphQL type's documentation follows. // @@ -256,6 +456,41 @@ func (v *setApiIpAddressesResponse) GetOrganizationApiIpAllowlistUpdate() setApi return v.OrganizationApiIpAllowlistUpdate } +// updatePipelinePipelineUpdatePipelineUpdatePayload includes the requested fields of the GraphQL type PipelineUpdatePayload. +// The GraphQL type's documentation follows. +// +// Autogenerated return type of PipelineUpdate. +type updatePipelinePipelineUpdatePipelineUpdatePayload struct { + Pipeline updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline `json:"pipeline"` +} + +// GetPipeline returns updatePipelinePipelineUpdatePipelineUpdatePayload.Pipeline, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayload) GetPipeline() updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline { + return v.Pipeline +} + +// updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline includes the requested fields of the GraphQL type Pipeline. +// The GraphQL type's documentation follows. +// +// A pipeline +type updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline struct { + Id string `json:"id"` +} + +// GetId returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.Id, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetId() string { return v.Id } + +// updatePipelineResponse is returned by updatePipeline on success. +type updatePipelineResponse struct { + // Change the settings for a pipeline. + PipelineUpdate updatePipelinePipelineUpdatePipelineUpdatePayload `json:"pipelineUpdate"` +} + +// GetPipelineUpdate returns updatePipelineResponse.PipelineUpdate, and is useful for accessing the field via an interface. +func (v *updatePipelineResponse) GetPipelineUpdate() updatePipelinePipelineUpdatePipelineUpdatePayload { + return v.PipelineUpdate +} + // The query or mutation executed by getOrganization. const getOrganization_Operation = ` query getOrganization ($slug: ID!) { @@ -413,3 +648,39 @@ func setApiIpAddresses( return &data, err } + +// The query or mutation executed by updatePipeline. +const updatePipeline_Operation = ` +mutation updatePipeline ($input: PipelineUpdateInput!) { + pipelineUpdate(input: $input) { + pipeline { + id + } + } +} +` + +func updatePipeline( + client graphql.Client, + input PipelineUpdateInput, +) (*updatePipelineResponse, error) { + req := &graphql.Request{ + OpName: "updatePipeline", + Query: updatePipeline_Operation, + Variables: &__updatePipelineInput{ + Input: input, + }, + } + var err error + + var data updatePipelineResponse + resp := &graphql.Response{Data: &data} + + err = client.MakeRequest( + nil, + req, + resp, + ) + + return &data, err +} diff --git a/buildkite/graphql/pipeline.graphql b/buildkite/graphql/pipeline.graphql index a05ce589..5dbd2758 100644 --- a/buildkite/graphql/pipeline.graphql +++ b/buildkite/graphql/pipeline.graphql @@ -11,3 +11,11 @@ query getPipeline($slug: ID!) { webhookURL } } + +mutation updatePipeline($input: PipelineUpdateInput!) { + pipelineUpdate(input: $input) { + pipeline { + id + } + } +} diff --git a/schema.graphql b/schema.graphql index 8ca62394..f4cf1816 100644 --- a/schema.graphql +++ b/schema.graphql @@ -70,6 +70,7 @@ enum APIAccessTokenScopes { READ_NOTIFICATION_SERVICES READ_ORGANIZATIONS READ_PIPELINES + READ_SUITES READ_TEAMS READ_USER WRITE_AGENTS @@ -546,29 +547,29 @@ enum AuditSubjectType { API_ACCESS_TOKEN CLUSTER_QUEUE CLUSTER_TOKEN - SUBSCRIPTION + NOTIFICATION_SERVICE ORGANIZATION + CLUSTER_PERMISSION ORGANIZATION_INVITATION - NOTIFICATION_SERVICE - PIPELINE_SCHEDULE TEAM TEAM_MEMBER - TEAM_SUITE + PIPELINE_SCHEDULE + TEAM_PIPELINE SCM_SERVICE SCM_PIPELINE_SETTINGS + TEAM_SUITE SCM_REPOSITORY_HOST SUITE_MONITOR - CLUSTER_PERMISSION SUITE - CLUSTER + USER_EMAIL + SUBSCRIPTION USER_TOTP - TEAM_PIPELINE USER - USER_EMAIL - AUTHORIZATION SSO_PROVIDER - PIPELINE ORGANIZATION_MEMBER + CLUSTER + AUTHORIZATION + PIPELINE } """Context for an audit event created during a web request""" @@ -1019,6 +1020,8 @@ type Cluster { last: Int ): ClusterAgentTokenConnection createdBy: User +"""The default queue that agents connecting to the cluster without specifying a queue will accept jobs from""" + defaultQueue: ClusterQueue description: String id: ID! name: String! @@ -1045,11 +1048,72 @@ type ClusterAgentTokenConnection implements Connection{ pageInfo: PageInfo } +"""Autogenerated input type of ClusterAgentTokenCreateMutation""" +input ClusterAgentTokenCreateMutationInput { +"""Autogenerated input type of ClusterAgentTokenCreateMutation""" + clientMutationId: String +"""Autogenerated input type of ClusterAgentTokenCreateMutation""" + organizationId: ID! +"""Autogenerated input type of ClusterAgentTokenCreateMutation""" + description: String! +"""Autogenerated input type of ClusterAgentTokenCreateMutation""" + clusterId: ID! +"""Autogenerated input type of ClusterAgentTokenCreateMutation""" + jobTokensEnabled: Boolean +} + +"""Autogenerated return type of ClusterAgentTokenCreateMutation.""" +type ClusterAgentTokenCreateMutationPayload { +"""A unique identifier for the client performing the mutation.""" + clientMutationId: String + clusterAgentToken: ClusterToken! +"""The token value used to register a new agent to this tokens cluster""" + tokenValue: String! +} + type ClusterAgentTokenEdge { cursor: String! node: ClusterToken } +"""Autogenerated input type of ClusterAgentTokenRevokeMutation""" +input ClusterAgentTokenRevokeMutationInput { +"""Autogenerated input type of ClusterAgentTokenRevokeMutation""" + clientMutationId: String +"""Autogenerated input type of ClusterAgentTokenRevokeMutation""" + id: ID! +"""Autogenerated input type of ClusterAgentTokenRevokeMutation""" + organizationId: ID! +} + +"""Autogenerated return type of ClusterAgentTokenRevokeMutation.""" +type ClusterAgentTokenRevokeMutationPayload { +"""A unique identifier for the client performing the mutation.""" + clientMutationId: String + clusterAgentToken: ClusterToken! +} + +"""Autogenerated input type of ClusterAgentTokenUpdateMutation""" +input ClusterAgentTokenUpdateMutationInput { +"""Autogenerated input type of ClusterAgentTokenUpdateMutation""" + clientMutationId: String +"""Autogenerated input type of ClusterAgentTokenUpdateMutation""" + id: ID! +"""Autogenerated input type of ClusterAgentTokenUpdateMutation""" + organizationId: ID! +"""Autogenerated input type of ClusterAgentTokenUpdateMutation""" + description: String! +"""Autogenerated input type of ClusterAgentTokenUpdateMutation""" + jobTokensEnabled: Boolean +} + +"""Autogenerated return type of ClusterAgentTokenUpdateMutation.""" +type ClusterAgentTokenUpdateMutationPayload { +"""A unique identifier for the client performing the mutation.""" + clientMutationId: String + clusterAgentToken: ClusterToken! +} + type ClusterConnection implements Connection{ count: Int! edges: [ClusterEdge] @@ -1162,7 +1226,9 @@ type ClusterToken implements Node{ """A description about what this cluster agent token is used for""" description: String id: ID! -"""The content of this cluster token""" +"""Agents registered with this token will use a unique token for each job. Please note that this feature is not yet available to all organizations""" + jobTokensEnabled: Boolean +"""The token value used to register a new agent to this tokens cluster. This will soon return an empty string before we finally remove this field.""" token: String! """The public UUID for this cluster token""" uuid: ID! @@ -1953,6 +2019,21 @@ type Mutation { """Parameters for BuildRebuild""" input: BuildRebuildInput! ): BuildRebuildPayload +"""Create a new cluster agent token""" + clusterAgentTokenCreate( +"""Parameters for ClusterAgentTokenCreateMutation""" + input: ClusterAgentTokenCreateMutationInput! + ): ClusterAgentTokenCreateMutationPayload +"""Revokes a cluster agent token""" + clusterAgentTokenRevoke( +"""Parameters for ClusterAgentTokenRevokeMutation""" + input: ClusterAgentTokenRevokeMutationInput! + ): ClusterAgentTokenRevokeMutationPayload +"""Updates a cluster agent token""" + clusterAgentTokenUpdate( +"""Parameters for ClusterAgentTokenUpdateMutation""" + input: ClusterAgentTokenUpdateMutationInput! + ): ClusterAgentTokenUpdateMutationPayload """This will prevent dispatch of jobs to agents on this queue. You can add an optional note describing the reason for pausing.""" clusterQueuePauseDispatch( """Parameters for ClusterQueuePauseDispatch""" From 579530b68c40a04d558c8629591a53c52a622304 Mon Sep 17 00:00:00 2001 From: Jarryd Tilbrook Date: Wed, 7 Jun 2023 15:57:52 +0800 Subject: [PATCH 2/7] SUP-863 Change ClusterId to pointer --- buildkite/generated.go | 4 ++-- buildkite/graphql/pipeline.graphql | 5 ++++- buildkite/resource_pipeline.go | 5 +---- schema.graphql | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/buildkite/generated.go b/buildkite/generated.go index 752a05f2..2cda5e29 100644 --- a/buildkite/generated.go +++ b/buildkite/generated.go @@ -118,7 +118,7 @@ type PipelineUpdateInput struct { // Autogenerated input type of PipelineUpdate BuildRetentionNumber int `json:"buildRetentionNumber"` // Autogenerated input type of PipelineUpdate - ClusterId string `json:"clusterId"` + ClusterId *string `json:"clusterId"` // Autogenerated input type of PipelineUpdate Archived bool `json:"archived"` // Autogenerated input type of PipelineUpdate @@ -197,7 +197,7 @@ func (v *PipelineUpdateInput) GetBuildRetentionPeriod() BuildRetentionPeriods { func (v *PipelineUpdateInput) GetBuildRetentionNumber() int { return v.BuildRetentionNumber } // GetClusterId returns PipelineUpdateInput.ClusterId, and is useful for accessing the field via an interface. -func (v *PipelineUpdateInput) GetClusterId() string { return v.ClusterId } +func (v *PipelineUpdateInput) GetClusterId() *string { return v.ClusterId } // GetArchived returns PipelineUpdateInput.Archived, and is useful for accessing the field via an interface. func (v *PipelineUpdateInput) GetArchived() bool { return v.Archived } diff --git a/buildkite/graphql/pipeline.graphql b/buildkite/graphql/pipeline.graphql index 5dbd2758..de6c6f78 100644 --- a/buildkite/graphql/pipeline.graphql +++ b/buildkite/graphql/pipeline.graphql @@ -12,7 +12,10 @@ query getPipeline($slug: ID!) { } } -mutation updatePipeline($input: PipelineUpdateInput!) { +# @genqlient(for: "PipelineUpdateInput.clusterId", pointer: true) +mutation updatePipeline( + $input: PipelineUpdateInput! +) { pipelineUpdate(input: $input) { pipeline { id diff --git a/buildkite/resource_pipeline.go b/buildkite/resource_pipeline.go index b9491d6b..e00023d9 100644 --- a/buildkite/resource_pipeline.go +++ b/buildkite/resource_pipeline.go @@ -52,9 +52,6 @@ type PipelineAccessLevels graphql.String type PipelineTag struct { Label graphql.String } -type PipelineTagInput struct { - Label graphql.String `json:"label"` -} // TeamPipelineNode represents a team pipeline as returned from the GraphQL API type TeamPipelineNode struct { @@ -589,7 +586,7 @@ func getTagsFromSchema(d *schema.ResourceData) []PipelineTagInput { tags := make([]PipelineTagInput, tagSet.Len()) for i, v := range tagSet.List() { tags[i] = PipelineTagInput{ - Label: graphql.String(v.(string)), + Label: v.(string), } } return tags diff --git a/schema.graphql b/schema.graphql index f4cf1816..e0ce7b2b 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1090,7 +1090,7 @@ input ClusterAgentTokenRevokeMutationInput { type ClusterAgentTokenRevokeMutationPayload { """A unique identifier for the client performing the mutation.""" clientMutationId: String - clusterAgentToken: ClusterToken! + deletedClusterAgentTokenId: ID! } """Autogenerated input type of ClusterAgentTokenUpdateMutation""" From 4d6f615dbb7451e1cc6f9a98ed017a883492b398 Mon Sep 17 00:00:00 2001 From: Jarryd Tilbrook Date: Thu, 8 Jun 2023 15:41:46 +0800 Subject: [PATCH 3/7] SUP-863 Add omitempty to some fields --- buildkite/generated.go | 369 ++++++++++++++++++++++++++++- buildkite/graphql/pipeline.graphql | 48 ++++ genqlient.yaml | 4 + schema.graphql | 104 +++++++- 4 files changed, 513 insertions(+), 12 deletions(-) diff --git a/buildkite/generated.go b/buildkite/generated.go index 2cda5e29..3211ce0d 100644 --- a/buildkite/generated.go +++ b/buildkite/generated.go @@ -46,6 +46,18 @@ const ( GenqlientTeamPrivacySecret GenqlientTeamPrivacy = "SECRET" ) +// The access levels that can be assigned to a pipeline +type PipelineAccessLevels string + +const ( + // Allows edits, builds and reads + PipelineAccessLevelsManageBuildAndRead PipelineAccessLevels = "MANAGE_BUILD_AND_READ" + // Allows builds and read only + PipelineAccessLevelsBuildAndRead PipelineAccessLevels = "BUILD_AND_READ" + // Read only - no builds or edits + PipelineAccessLevelsReadOnly PipelineAccessLevels = "READ_ONLY" +) + // Repository information for a pipeline type PipelineRepositoryInput struct { // Repository information for a pipeline @@ -88,7 +100,7 @@ type PipelineUpdateInput struct { // Autogenerated input type of PipelineUpdate Color string `json:"color"` // Autogenerated input type of PipelineUpdate - Visibility PipelineVisibility `json:"visibility"` + Visibility PipelineVisibility `json:"visibility,omitempty"` // Autogenerated input type of PipelineUpdate Repository PipelineRepositoryInput `json:"repository"` // Autogenerated input type of PipelineUpdate @@ -96,7 +108,7 @@ type PipelineUpdateInput struct { // Autogenerated input type of PipelineUpdate DefaultBranch string `json:"defaultBranch"` // Autogenerated input type of PipelineUpdate - NextBuildNumber int `json:"nextBuildNumber"` + NextBuildNumber int `json:"nextBuildNumber,omitempty"` // Autogenerated input type of PipelineUpdate SkipIntermediateBuilds bool `json:"skipIntermediateBuilds"` // Autogenerated input type of PipelineUpdate @@ -114,13 +126,13 @@ type PipelineUpdateInput struct { // Autogenerated input type of PipelineUpdate BuildRetentionEnabled bool `json:"buildRetentionEnabled"` // Autogenerated input type of PipelineUpdate - BuildRetentionPeriod BuildRetentionPeriods `json:"buildRetentionPeriod"` + BuildRetentionPeriod BuildRetentionPeriods `json:"buildRetentionPeriod,omitempty"` // Autogenerated input type of PipelineUpdate - BuildRetentionNumber int `json:"buildRetentionNumber"` + BuildRetentionNumber int `json:"buildRetentionNumber,omitempty"` // Autogenerated input type of PipelineUpdate ClusterId *string `json:"clusterId"` // Autogenerated input type of PipelineUpdate - Archived bool `json:"archived"` + Archived bool `json:"archived,omitempty"` // Autogenerated input type of PipelineUpdate Tags []PipelineTagInput `json:"tags"` // Autogenerated input type of PipelineUpdate @@ -218,6 +230,26 @@ const ( PipelineVisibilityPrivate PipelineVisibility = "PRIVATE" ) +// The roles a user can be within a team +type TeamMemberRole string + +const ( + // The user is a regular member of the team + TeamMemberRoleMember TeamMemberRole = "MEMBER" + // The user can manage pipelines and users within the team + TeamMemberRoleMaintainer TeamMemberRole = "MAINTAINER" +) + +// Whether a team is visible or secret within an organization +type TeamPrivacy string + +const ( + // Visible to all members of the organization + TeamPrivacyVisible TeamPrivacy = "VISIBLE" + // Visible to organization administrators and members + TeamPrivacySecret TeamPrivacy = "SECRET" +) + // __getOrganizationInput is used internally by genqlient type __getOrganizationInput struct { Slug string `json:"slug"` @@ -475,11 +507,295 @@ func (v *updatePipelinePipelineUpdatePipelineUpdatePayload) GetPipeline() update // A pipeline type updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline struct { Id string `json:"id"` + // Whether existing builds can be rebuilt as new builds. + AllowRebuilds bool `json:"allowRebuilds"` + // When a new build is created on a branch, any previous builds that are running on the same branch will be automatically cancelled + CancelIntermediateBuilds bool `json:"cancelIntermediateBuilds"` + // Limit which branches build cancelling applies to, for example `!main` will ensure that the main branch won't have it's builds automatically cancelled. + CancelIntermediateBuildsBranchFilter string `json:"cancelIntermediateBuildsBranchFilter"` + Cluster updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineCluster `json:"cluster"` + // The default branch for this pipeline + DefaultBranch string `json:"defaultBranch"` + // The default timeout in minutes for all command steps in this pipeline. This can still be overridden in any command step + DefaultTimeoutInMinutes int `json:"defaultTimeoutInMinutes"` + // The maximum timeout in minutes for all command steps in this pipeline. Any command step without a timeout or with a timeout greater than this value will be set to this value. + MaximumTimeoutInMinutes int `json:"maximumTimeoutInMinutes"` + // The short description of the pipeline + Description string `json:"description"` + // The name of the pipeline + Name string `json:"name"` + // The repository for this pipeline + Repository updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineRepository `json:"repository"` + // When a new build is created on a branch, any previous builds that haven't yet started on the same branch will be automatically marked as skipped. + SkipIntermediateBuilds bool `json:"skipIntermediateBuilds"` + // Limit which branches build skipping applies to, for example `!main` will ensure that the main branch won't have it's builds automatically skipped. + SkipIntermediateBuildsBranchFilter string `json:"skipIntermediateBuildsBranchFilter"` + // The slug of the pipeline + Slug string `json:"slug"` + Steps updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineSteps `json:"steps"` + // Tags that have been given to this pipeline + Tags []updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTagsPipelineTag `json:"tags"` + // Teams associated with this pipeline + Teams updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnection `json:"teams"` + // The URL to use in your repository settings for commit webhooks + WebhookURL string `json:"webhookURL"` } // GetId returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.Id, and is useful for accessing the field via an interface. func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetId() string { return v.Id } +// GetAllowRebuilds returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.AllowRebuilds, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetAllowRebuilds() bool { + return v.AllowRebuilds +} + +// GetCancelIntermediateBuilds returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.CancelIntermediateBuilds, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetCancelIntermediateBuilds() bool { + return v.CancelIntermediateBuilds +} + +// GetCancelIntermediateBuildsBranchFilter returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.CancelIntermediateBuildsBranchFilter, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetCancelIntermediateBuildsBranchFilter() string { + return v.CancelIntermediateBuildsBranchFilter +} + +// GetCluster returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.Cluster, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetCluster() updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineCluster { + return v.Cluster +} + +// GetDefaultBranch returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.DefaultBranch, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetDefaultBranch() string { + return v.DefaultBranch +} + +// GetDefaultTimeoutInMinutes returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.DefaultTimeoutInMinutes, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetDefaultTimeoutInMinutes() int { + return v.DefaultTimeoutInMinutes +} + +// GetMaximumTimeoutInMinutes returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.MaximumTimeoutInMinutes, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetMaximumTimeoutInMinutes() int { + return v.MaximumTimeoutInMinutes +} + +// GetDescription returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.Description, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetDescription() string { + return v.Description +} + +// GetName returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.Name, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetName() string { return v.Name } + +// GetRepository returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.Repository, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetRepository() updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineRepository { + return v.Repository +} + +// GetSkipIntermediateBuilds returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.SkipIntermediateBuilds, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetSkipIntermediateBuilds() bool { + return v.SkipIntermediateBuilds +} + +// GetSkipIntermediateBuildsBranchFilter returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.SkipIntermediateBuildsBranchFilter, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetSkipIntermediateBuildsBranchFilter() string { + return v.SkipIntermediateBuildsBranchFilter +} + +// GetSlug returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.Slug, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetSlug() string { return v.Slug } + +// GetSteps returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.Steps, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetSteps() updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineSteps { + return v.Steps +} + +// GetTags returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.Tags, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetTags() []updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTagsPipelineTag { + return v.Tags +} + +// GetTeams returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.Teams, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetTeams() updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnection { + return v.Teams +} + +// GetWebhookURL returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline.WebhookURL, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipeline) GetWebhookURL() string { + return v.WebhookURL +} + +// updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineCluster includes the requested fields of the GraphQL type Cluster. +type updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineCluster struct { + Id string `json:"id"` +} + +// GetId returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineCluster.Id, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineCluster) GetId() string { + return v.Id +} + +// updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineRepository includes the requested fields of the GraphQL type Repository. +// The GraphQL type's documentation follows. +// +// A repository associated with a pipeline +type updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineRepository struct { + // The git URL for this repository + Url string `json:"url"` +} + +// GetUrl returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineRepository.Url, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineRepository) GetUrl() string { + return v.Url +} + +// updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineSteps includes the requested fields of the GraphQL type PipelineSteps. +// The GraphQL type's documentation follows. +// +// Steps defined on a pipeline +type updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineSteps struct { + // A YAML representation of the pipeline steps + Yaml string `json:"yaml"` +} + +// GetYaml returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineSteps.Yaml, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineSteps) GetYaml() string { + return v.Yaml +} + +// updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTagsPipelineTag includes the requested fields of the GraphQL type PipelineTag. +// The GraphQL type's documentation follows. +// +// A tag associated with a pipeline +type updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTagsPipelineTag struct { + // The label for this tag + Label string `json:"label"` +} + +// GetLabel returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTagsPipelineTag.Label, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTagsPipelineTag) GetLabel() string { + return v.Label +} + +// updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnection includes the requested fields of the GraphQL type TeamPipelineConnection. +// The GraphQL type's documentation follows. +// +// A collection of TeamPipeline records +type updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnection struct { + Edges []updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdge `json:"edges"` +} + +// GetEdges returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnection.Edges, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnection) GetEdges() []updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdge { + return v.Edges +} + +// updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdge includes the requested fields of the GraphQL type TeamPipelineEdge. +type updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdge struct { + Node updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipeline `json:"node"` +} + +// GetNode returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdge.Node, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdge) GetNode() updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipeline { + return v.Node +} + +// updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipeline includes the requested fields of the GraphQL type TeamPipeline. +// The GraphQL type's documentation follows. +// +// An pipeline that's been assigned to a team +type updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipeline struct { + // The access level users have to this pipeline + AccessLevel PipelineAccessLevels `json:"accessLevel"` + Id string `json:"id"` + // The team associated with this team member + Team updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam `json:"team"` +} + +// GetAccessLevel returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipeline.AccessLevel, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipeline) GetAccessLevel() PipelineAccessLevels { + return v.AccessLevel +} + +// GetId returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipeline.Id, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipeline) GetId() string { + return v.Id +} + +// GetTeam returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipeline.Team, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipeline) GetTeam() updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam { + return v.Team +} + +// updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam includes the requested fields of the GraphQL type Team. +// The GraphQL type's documentation follows. +// +// An organization team +type updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam struct { + // A description of the team + Description string `json:"description"` + Id string `json:"id"` + // Add new organization members to this team by default + IsDefaultTeam bool `json:"isDefaultTeam"` + // New organization members will be granted this role on this team + DefaultMemberRole TeamMemberRole `json:"defaultMemberRole"` + // The name of the team + Name string `json:"name"` + // Whether or not team members can create new pipelines in this team + MembersCanCreatePipelines bool `json:"membersCanCreatePipelines"` + // The privacy setting for this team + Privacy TeamPrivacy `json:"privacy"` + // The slug of the team + Slug string `json:"slug"` + // The public UUID for this team + Uuid string `json:"uuid"` +} + +// GetDescription returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam.Description, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam) GetDescription() string { + return v.Description +} + +// GetId returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam.Id, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam) GetId() string { + return v.Id +} + +// GetIsDefaultTeam returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam.IsDefaultTeam, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam) GetIsDefaultTeam() bool { + return v.IsDefaultTeam +} + +// GetDefaultMemberRole returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam.DefaultMemberRole, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam) GetDefaultMemberRole() TeamMemberRole { + return v.DefaultMemberRole +} + +// GetName returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam.Name, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam) GetName() string { + return v.Name +} + +// GetMembersCanCreatePipelines returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam.MembersCanCreatePipelines, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam) GetMembersCanCreatePipelines() bool { + return v.MembersCanCreatePipelines +} + +// GetPrivacy returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam.Privacy, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam) GetPrivacy() TeamPrivacy { + return v.Privacy +} + +// GetSlug returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam.Slug, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam) GetSlug() string { + return v.Slug +} + +// GetUuid returns updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam.Uuid, and is useful for accessing the field via an interface. +func (v *updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdgeNodeTeamPipelineTeam) GetUuid() string { + return v.Uuid +} + // updatePipelineResponse is returned by updatePipeline on success. type updatePipelineResponse struct { // Change the settings for a pipeline. @@ -655,6 +971,49 @@ mutation updatePipeline ($input: PipelineUpdateInput!) { pipelineUpdate(input: $input) { pipeline { id + allowRebuilds + cancelIntermediateBuilds + cancelIntermediateBuildsBranchFilter + cluster { + id + } + defaultBranch + defaultTimeoutInMinutes + maximumTimeoutInMinutes + description + name + repository { + url + } + skipIntermediateBuilds + skipIntermediateBuildsBranchFilter + slug + steps { + yaml + } + tags { + label + } + teams(first: 50) { + edges { + node { + accessLevel + id + team { + description + id + isDefaultTeam + defaultMemberRole + name + membersCanCreatePipelines + privacy + slug + uuid + } + } + } + } + webhookURL } } } diff --git a/buildkite/graphql/pipeline.graphql b/buildkite/graphql/pipeline.graphql index de6c6f78..bd4b5dad 100644 --- a/buildkite/graphql/pipeline.graphql +++ b/buildkite/graphql/pipeline.graphql @@ -13,12 +13,60 @@ query getPipeline($slug: ID!) { } # @genqlient(for: "PipelineUpdateInput.clusterId", pointer: true) +# @genqlient(for: "PipelineUpdateInput.visibility", omitempty: true) +# @genqlient(for: "PipelineUpdateInput.buildRetentionPeriod", omitempty: true) +# @genqlient(for: "PipelineUpdateInput.buildRetentionNumber", omitempty: true) +# @genqlient(for: "PipelineUpdateInput.archived", omitempty: true) +# @genqlient(for: "PipelineUpdateInput.nextBuildNumber", omitempty: true) mutation updatePipeline( $input: PipelineUpdateInput! ) { pipelineUpdate(input: $input) { pipeline { id + allowRebuilds + cancelIntermediateBuilds + cancelIntermediateBuildsBranchFilter + cluster { + id + } + defaultBranch + defaultTimeoutInMinutes + maximumTimeoutInMinutes + description + name + repository { + url + } + skipIntermediateBuilds + skipIntermediateBuildsBranchFilter + slug + steps { + yaml + } + tags { + label + } + teams (first: 50) { + edges { + node { + accessLevel + id + team { + description + id + isDefaultTeam + defaultMemberRole + name + membersCanCreatePipelines + privacy + slug + uuid + } + } + } + } + webhookURL } } } diff --git a/genqlient.yaml b/genqlient.yaml index 68a7d68b..43339711 100644 --- a/genqlient.yaml +++ b/genqlient.yaml @@ -7,3 +7,7 @@ generated: buildkite/generated.go # We pass context.Background() everywhere so just leave it off context_type: "-" + +bindings: + YAML: + type: string diff --git a/schema.graphql b/schema.graphql index e0ce7b2b..31d42d01 100644 --- a/schema.graphql +++ b/schema.graphql @@ -80,6 +80,7 @@ enum APIAccessTokenScopes { WRITE_CLUSTERS WRITE_NOTIFICATION_SERVICES WRITE_PIPELINES + WRITE_SUITES } """An API Application""" @@ -543,31 +544,31 @@ union AuditSubjectNode =APIAccessToken | AgentToken | AuthorizationBitbucket | A """All the possible types of subjects in an Audit Event""" enum AuditSubjectType { + CLUSTER_PERMISSION AGENT_TOKEN API_ACCESS_TOKEN CLUSTER_QUEUE CLUSTER_TOKEN NOTIFICATION_SERVICE ORGANIZATION - CLUSTER_PERMISSION ORGANIZATION_INVITATION + PIPELINE_SCHEDULE TEAM TEAM_MEMBER - PIPELINE_SCHEDULE TEAM_PIPELINE + TEAM_SUITE SCM_SERVICE SCM_PIPELINE_SETTINGS - TEAM_SUITE SCM_REPOSITORY_HOST SUITE_MONITOR - SUITE - USER_EMAIL SUBSCRIPTION - USER_TOTP - USER SSO_PROVIDER ORGANIZATION_MEMBER + SUITE CLUSTER + USER_TOTP + USER_EMAIL + USER AUTHORIZATION PIPELINE } @@ -1019,11 +1020,18 @@ type Cluster { first: Int last: Int ): ClusterAgentTokenConnection +"""Color hex code for the cluster""" + color: String +"""User who created the cluster""" createdBy: User """The default queue that agents connecting to the cluster without specifying a queue will accept jobs from""" defaultQueue: ClusterQueue +"""Description of the cluster""" description: String +"""Emoji for the cluster using Buildkite emoji syntax""" + emoji: String id: ID! +"""Name of the cluster""" name: String! organization: Organization queues( @@ -1120,6 +1128,46 @@ type ClusterConnection implements Connection{ pageInfo: PageInfo } +"""Autogenerated input type of ClusterCreate""" +input ClusterCreateInput { +"""Autogenerated input type of ClusterCreate""" + clientMutationId: String +"""Autogenerated input type of ClusterCreate""" + organizationId: ID! +"""Autogenerated input type of ClusterCreate""" + name: String! +"""Autogenerated input type of ClusterCreate""" + description: String +"""Autogenerated input type of ClusterCreate""" + emoji: String +"""Autogenerated input type of ClusterCreate""" + color: String +} + +"""Autogenerated return type of ClusterCreate.""" +type ClusterCreatePayload { +"""A unique identifier for the client performing the mutation.""" + clientMutationId: String + cluster: Cluster! +} + +"""Autogenerated input type of ClusterDelete""" +input ClusterDeleteInput { +"""Autogenerated input type of ClusterDelete""" + clientMutationId: String +"""Autogenerated input type of ClusterDelete""" + organizationId: ID! +"""Autogenerated input type of ClusterDelete""" + id: ID! +} + +"""Autogenerated return type of ClusterDelete.""" +type ClusterDeletePayload { +"""A unique identifier for the client performing the mutation.""" + clientMutationId: String + deletedClusterId: ID! +} + type ClusterEdge { cursor: String! node: Cluster @@ -1234,6 +1282,33 @@ type ClusterToken implements Node{ uuid: ID! } +"""Autogenerated input type of ClusterUpdate""" +input ClusterUpdateInput { +"""Autogenerated input type of ClusterUpdate""" + clientMutationId: String +"""Autogenerated input type of ClusterUpdate""" + organizationId: ID! +"""Autogenerated input type of ClusterUpdate""" + id: ID! +"""Autogenerated input type of ClusterUpdate""" + name: String +"""Autogenerated input type of ClusterUpdate""" + description: String +"""Autogenerated input type of ClusterUpdate""" + emoji: String +"""Autogenerated input type of ClusterUpdate""" + color: String +"""Autogenerated input type of ClusterUpdate""" + defaultQueueId: ID +} + +"""Autogenerated return type of ClusterUpdate.""" +type ClusterUpdatePayload { +"""A unique identifier for the client performing the mutation.""" + clientMutationId: String + cluster: Cluster! +} + interface Connection { count: Int! pageInfo: PageInfo @@ -2034,6 +2109,16 @@ type Mutation { """Parameters for ClusterAgentTokenUpdateMutation""" input: ClusterAgentTokenUpdateMutationInput! ): ClusterAgentTokenUpdateMutationPayload +"""Create a cluster.""" + clusterCreate( +"""Parameters for ClusterCreate""" + input: ClusterCreateInput! + ): ClusterCreatePayload +"""Delete a cluster.""" + clusterDelete( +"""Parameters for ClusterDelete""" + input: ClusterDeleteInput! + ): ClusterDeletePayload """This will prevent dispatch of jobs to agents on this queue. You can add an optional note describing the reason for pausing.""" clusterQueuePauseDispatch( """Parameters for ClusterQueuePauseDispatch""" @@ -2044,6 +2129,11 @@ type Mutation { """Parameters for ClusterQueueResumeDispatch""" input: ClusterQueueResumeDispatchInput! ): ClusterQueueResumeDispatchPayload +"""Updates a cluster.""" + clusterUpdate( +"""Parameters for ClusterUpdate""" + input: ClusterUpdateInput! + ): ClusterUpdatePayload """Add a new email address for the current user""" emailCreate( """Parameters for EmailCreate""" From 81480ec4edfbeb45fe74177f10708eccdf6552d8 Mon Sep 17 00:00:00 2001 From: Jarryd Tilbrook Date: Thu, 8 Jun 2023 21:14:23 +0800 Subject: [PATCH 4/7] SUP-863 Fix removing pipeline from cluster --- buildkite/resource_pipeline.go | 162 ++++++++++++++++++++------------- buildkite/resource_team.go | 3 - 2 files changed, 101 insertions(+), 64 deletions(-) diff --git a/buildkite/resource_pipeline.go b/buildkite/resource_pipeline.go index e00023d9..83801b2e 100644 --- a/buildkite/resource_pipeline.go +++ b/buildkite/resource_pipeline.go @@ -15,30 +15,33 @@ const defaultSteps = `steps: command: buildkite-agent pipeline upload` // PipelineNode represents a pipeline as returned from the GraphQL API +type Cluster struct { + ID graphql.String +} +type Repository struct { + URL graphql.String +} +type Steps struct { + YAML graphql.String +} type PipelineNode struct { AllowRebuilds graphql.Boolean CancelIntermediateBuilds graphql.Boolean CancelIntermediateBuildsBranchFilter graphql.String - Cluster struct { - ID graphql.String - } - DefaultBranch graphql.String - DefaultTimeoutInMinutes graphql.Int - MaximumTimeoutInMinutes graphql.Int - Description graphql.String - ID graphql.String - Name graphql.String - Repository struct { - URL graphql.String - } - SkipIntermediateBuilds graphql.Boolean - SkipIntermediateBuildsBranchFilter graphql.String - Slug graphql.String - Steps struct { - YAML graphql.String - } - Tags []PipelineTag - Teams struct { + Cluster Cluster + DefaultBranch graphql.String + DefaultTimeoutInMinutes graphql.Int + MaximumTimeoutInMinutes graphql.Int + Description graphql.String + ID graphql.String + Name graphql.String + Repository Repository + SkipIntermediateBuilds graphql.Boolean + SkipIntermediateBuildsBranchFilter graphql.String + Slug graphql.String + Steps Steps + Tags []PipelineTag + Teams struct { Edges []struct { Node TeamPipelineNode } @@ -46,9 +49,6 @@ type PipelineNode struct { WebhookURL graphql.String `graphql:"webhookURL"` } -// PipelineAccessLevels represents a pipeline access levels as returned from the GraphQL API -type PipelineAccessLevels graphql.String - type PipelineTag struct { Label graphql.String } @@ -98,7 +98,6 @@ func resourcePipeline() *schema.Resource { Type: schema.TypeString, }, "cluster_id": { - Computed: true, Optional: true, Type: schema.TypeString, }, @@ -428,58 +427,71 @@ func ReadPipeline(ctx context.Context, d *schema.ResourceData, m interface{}) di func UpdatePipeline(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { client := m.(*Client) var err error - var mutation struct { - PipelineUpdate struct { - Pipeline PipelineNode - } `graphql:"pipelineUpdate(input: {allowRebuilds: $allow_rebuilds, cancelIntermediateBuilds: $cancel_intermediate_builds, cancelIntermediateBuildsBranchFilter: $cancel_intermediate_builds_branch_filter, defaultBranch: $default_branch, defaultTimeoutInMinutes: $default_timeout_in_minutes, maximumTimeoutInMinutes: $maximum_timeout_in_minutes, description: $desc, id: $id, name: $name, repository: {url: $repository_url}, skipIntermediateBuilds: $skip_intermediate_builds, skipIntermediateBuildsBranchFilter: $skip_intermediate_builds_branch_filter, steps: {yaml: $steps}, tags: $tags})"` - } - vars := map[string]interface{}{ - "allow_rebuilds": graphql.Boolean(d.Get("allow_rebuilds").(bool)), - "cancel_intermediate_builds": graphql.Boolean(d.Get("cancel_intermediate_builds").(bool)), - "cancel_intermediate_builds_branch_filter": graphql.String(d.Get("cancel_intermediate_builds_branch_filter").(string)), - "default_branch": graphql.String(d.Get("default_branch").(string)), - "default_timeout_in_minutes": graphql.Int(d.Get("default_timeout_in_minutes").(int)), - "maximum_timeout_in_minutes": graphql.Int(d.Get("maximum_timeout_in_minutes").(int)), - "desc": graphql.String(d.Get("description").(string)), - "id": graphql.ID(d.Id()), - "name": graphql.String(d.Get("name").(string)), - "repository_url": graphql.String(d.Get("repository").(string)), - "skip_intermediate_builds": graphql.Boolean(d.Get("skip_intermediate_builds").(bool)), - "skip_intermediate_builds_branch_filter": graphql.String(d.Get("skip_intermediate_builds_branch_filter").(string)), - "steps": graphql.String(d.Get("steps").(string)), - "tags": getTagsFromSchema(d), - } - log.Printf("Updating pipeline %s ...", vars["name"]) - - // If the cluster_id key is present in the mutation, GraphQL expects a valid ID. - // Check if cluster_id exists in the configuration before adding to mutation. - if clusterID, ok := d.GetOk("cluster_id"); ok { - var mutationWithClusterID struct { - PipelineUpdate struct { - Pipeline PipelineNode - } `graphql:"pipelineUpdate(input: {allowRebuilds: $allow_rebuilds, cancelIntermediateBuilds: $cancel_intermediate_builds, cancelIntermediateBuildsBranchFilter: $cancel_intermediate_builds_branch_filter, clusterId: $cluster_id, defaultBranch: $default_branch, defaultTimeoutInMinutes: $default_timeout_in_minutes, maximumTimeoutInMinutes: $maximum_timeout_in_minutes, description: $desc, id: $id, name: $name, repository: {url: $repository_url}, skipIntermediateBuilds: $skip_intermediate_builds, skipIntermediateBuildsBranchFilter: $skip_intermediate_builds_branch_filter, steps: {yaml: $steps}, tags: $tags})"` + input := PipelineUpdateInput{ + AllowRebuilds: d.Get("allow_rebuilds").(bool), + CancelIntermediateBuilds: d.Get("cancel_intermediate_builds").(bool), + CancelIntermediateBuildsBranchFilter: d.Get("cancel_intermediate_builds_branch_filter").(string), + DefaultBranch: d.Get("default_branch").(string), + DefaultTimeoutInMinutes: d.Get("default_timeout_in_minutes").(int), + MaximumTimeoutInMinutes: d.Get("maximum_timeout_in_minutes").(int), + Description: d.Get("description").(string), + Id: d.Id(), + Name: d.Get("name").(string), + Repository: PipelineRepositoryInput{Url: d.Get("repository").(string)}, + SkipIntermediateBuilds: d.Get("skip_intermediate_builds").(bool), + SkipIntermediateBuildsBranchFilter: d.Get("skip_intermediate_builds_branch_filter").(string), + Steps: PipelineStepsInput{Yaml: d.Get("steps").(string)}, + Tags: getTagsFromSchema(d), + } + + // If cluster_id exists in the schema it must be a non-empty string + // Otherwise, if its not present it will be set to nil by default + if clusterID, clusterIdPresent := d.GetOk("cluster_id"); clusterIdPresent { + if value, isString := clusterID.(string); isString && value != "" { + input.ClusterId = &value } - vars["cluster_id"] = graphql.ID(clusterID.(string)) - err = client.graphql.Mutate(context.Background(), &mutationWithClusterID, vars) - mutation.PipelineUpdate.Pipeline = mutationWithClusterID.PipelineUpdate.Pipeline - } else { - err = client.graphql.Mutate(context.Background(), &mutation, vars) } + log.Printf("Updating pipeline %s ...", input.Name) + + response, err := updatePipeline(client.genqlient, input) + if err != nil { log.Printf("Unable to update pipeline %s", d.Get("name")) return diag.FromErr(err) } + // While transitioning from shurcool to genqlient, we'll map the response here to utilise existing functionality + pipeline := PipelineNode{ + AllowRebuilds: graphql.Boolean(response.PipelineUpdate.Pipeline.AllowRebuilds), + CancelIntermediateBuilds: graphql.Boolean(response.PipelineUpdate.Pipeline.CancelIntermediateBuilds), + CancelIntermediateBuildsBranchFilter: graphql.String(response.PipelineUpdate.Pipeline.CancelIntermediateBuildsBranchFilter), + Cluster: Cluster{ID: graphql.String(response.PipelineUpdate.Pipeline.Cluster.Id)}, + DefaultBranch: graphql.String(response.PipelineUpdate.Pipeline.DefaultBranch), + DefaultTimeoutInMinutes: graphql.Int(response.PipelineUpdate.Pipeline.DefaultTimeoutInMinutes), + MaximumTimeoutInMinutes: graphql.Int(response.PipelineUpdate.Pipeline.MaximumTimeoutInMinutes), + Description: graphql.String(response.PipelineUpdate.Pipeline.Description), + ID: graphql.String(response.PipelineUpdate.Pipeline.Id), + Name: graphql.String(response.PipelineUpdate.Pipeline.Name), + Repository: Repository{URL: graphql.String(response.PipelineUpdate.Pipeline.Repository.Url)}, + SkipIntermediateBuilds: graphql.Boolean(response.PipelineUpdate.Pipeline.SkipIntermediateBuilds), + SkipIntermediateBuildsBranchFilter: graphql.String(response.PipelineUpdate.Pipeline.SkipIntermediateBuildsBranchFilter), + Slug: graphql.String(response.PipelineUpdate.Pipeline.Slug), + Steps: Steps{YAML: graphql.String(response.PipelineUpdate.Pipeline.Steps.Yaml)}, + Tags: mapTagsFromGenqlient(response.PipelineUpdate.Pipeline.Tags), + Teams: mapTeamPipelinesFromGenqlient(response.PipelineUpdate.Pipeline.Teams.Edges), + WebhookURL: graphql.String(response.PipelineUpdate.Pipeline.WebhookURL), + } + teamPipelines := getTeamPipelinesFromSchema(d) - err = reconcileTeamPipelines(teamPipelines, &mutation.PipelineUpdate.Pipeline, client) + err = reconcileTeamPipelines(teamPipelines, &pipeline, client) if err != nil { log.Print("Unable to reconcile team pipelines") return diag.FromErr(err) } - updatePipelineResource(d, &mutation.PipelineUpdate.Pipeline) + updatePipelineResource(d, &pipeline) pipelineExtraInfo, err := updatePipelineExtraInfo(d, client) if err != nil { @@ -581,6 +593,15 @@ func updatePipelineExtraInfo(d *schema.ResourceData, client *Client) (PipelineEx return pipelineExtraInfo, nil } +func mapTagsFromGenqlient(tags []updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTagsPipelineTag) []PipelineTag { + newTags := make([]PipelineTag, len(tags)) + + for i, v := range tags { + newTags[i] = PipelineTag{Label: graphql.String(v.Label)} + } + return newTags +} + func getTagsFromSchema(d *schema.ResourceData) []PipelineTagInput { tagSet := d.Get("tags").(*schema.Set) tags := make([]PipelineTagInput, tagSet.Len()) @@ -592,6 +613,25 @@ func getTagsFromSchema(d *schema.ResourceData) []PipelineTagInput { return tags } +func mapTeamPipelinesFromGenqlient(tags []updatePipelinePipelineUpdatePipelineUpdatePayloadPipelineTeamsTeamPipelineConnectionEdgesTeamPipelineEdge) struct { + Edges []struct{ Node TeamPipelineNode } +} { + teamPipelineNodes := make([]struct{ Node TeamPipelineNode }, len(tags)) + for i, v := range tags { + teamPipelineNodes[i] = struct{ Node TeamPipelineNode }{ + Node: TeamPipelineNode{ + AccessLevel: v.Node.AccessLevel, + ID: graphql.String(v.Node.Id), + Team: TeamNode{ + Slug: graphql.String(v.Node.Team.Slug), + }}, + } + } + return struct { + Edges []struct{ Node TeamPipelineNode } + }{Edges: teamPipelineNodes} +} + func getTeamPipelinesFromSchema(d *schema.ResourceData) []TeamPipelineNode { teamsInput := d.Get("team").(*schema.Set).List() teamPipelineNodes := make([]TeamPipelineNode, len(teamsInput)) diff --git a/buildkite/resource_team.go b/buildkite/resource_team.go index d22b2282..45e91414 100644 --- a/buildkite/resource_team.go +++ b/buildkite/resource_team.go @@ -9,9 +9,6 @@ import ( "github.com/shurcooL/graphql" ) -type TeamPrivacy graphql.String -type TeamMemberRole graphql.String - type TeamNode struct { Description graphql.String ID graphql.String From aa4c5791afca79cc68a217465a91c50080820703 Mon Sep 17 00:00:00 2001 From: Jarryd Tilbrook Date: Thu, 8 Jun 2023 21:14:47 +0800 Subject: [PATCH 5/7] SUP-863 Add graphqlrc.yml --- .graphqlrc.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .graphqlrc.yml diff --git a/.graphqlrc.yml b/.graphqlrc.yml new file mode 100644 index 00000000..9484b9ca --- /dev/null +++ b/.graphqlrc.yml @@ -0,0 +1 @@ +schema: schema.graphql From 3af41b8b16c49743c4ecfb3c48ee14f397381371 Mon Sep 17 00:00:00 2001 From: Jarryd Tilbrook Date: Thu, 8 Jun 2023 21:17:59 +0800 Subject: [PATCH 6/7] SUP-863 Update changelog with pending change --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ed36c89..d80c48f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. +## Unreleased + +* Allow pipeline to be removed from a cluster [[PR #279](https://github.com/buildkite/terraform-provider-buildkite/pull/279)] + ## [v0.18.1](https://github.com/buildkite/terraform-provider-buildkite/compare/v0.18.0...v0.18.1) ### Fixes From 889b56f04fd61ccd1f0b057d12914f41f00939fb Mon Sep 17 00:00:00 2001 From: Jarryd Tilbrook Date: Thu, 8 Jun 2023 21:22:03 +0800 Subject: [PATCH 7/7] SUP-863 Add test for removing from cluster --- buildkite/resource_pipeline_test.go | 46 ++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/buildkite/resource_pipeline_test.go b/buildkite/resource_pipeline_test.go index e2515e44..43ea8ee1 100644 --- a/buildkite/resource_pipeline_test.go +++ b/buildkite/resource_pipeline_test.go @@ -35,7 +35,7 @@ func TestAccPipeline_add_remove(t *testing.T) { } // Confirm that we can create a new pipeline with a cluster, and then delete it without error -func TestAccPipeline_add_remove_withcluster(t *testing.T) { +func TestAccPipeline_add_delete_withcluster(t *testing.T) { var resourcePipeline PipelineNode resource.Test(t, resource.TestCase{ @@ -73,6 +73,45 @@ func TestAccPipeline_add_remove_withcluster(t *testing.T) { }) } +// Confirm that we can create a new pipeline with a cluster, and then remove it from the cluster +func TestAccPipeline_add_remove_withcluster(t *testing.T) { + var resourcePipeline PipelineNode + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckPipelineResourceDestroy, + Steps: []resource.TestStep{ + { + Config: testAccPipelineConfigBasicWithCluster("foo"), + Check: resource.ComposeAggregateTestCheckFunc( + // Confirm the pipeline exists in the buildkite API + testAccCheckPipelineExists("buildkite_pipeline.foobar", &resourcePipeline), + // Confirm the pipeline has the correct values in Buildkite's system + testAccCheckPipelineRemoteValues(&resourcePipeline, "Test Pipeline foo"), + // Confirm the pipeline has the correct values in terraform state + resource.TestCheckResourceAttr("buildkite_pipeline.foobar", "name", "Test Pipeline foo"), + resource.TestCheckResourceAttr("buildkite_pipeline.foobar", "cluster_id", "Q2x1c3Rlci0tLTRlN2JmM2FjLWUzMjMtNGY1OS05MGY2LTQ5OTljZmI2MGQyYg=="), + resource.TestCheckResourceAttr("buildkite_pipeline.foobar", "allow_rebuilds", "true"), + ), + }, + { + Config: testAccPipelineConfigBasicWithTeam("foo"), + Check: resource.ComposeAggregateTestCheckFunc( + // Confirm the pipeline exists in the buildkite API + testAccCheckPipelineExists("buildkite_pipeline.foobar", &resourcePipeline), + // Confirm the pipeline has the correct values in Buildkite's system + testAccCheckPipelineRemoteValues(&resourcePipeline, "Test Pipeline foo"), + // Confirm the pipeline has the correct values in terraform state + resource.TestCheckResourceAttr("buildkite_pipeline.foobar", "name", "Test Pipeline foo"), + resource.TestCheckResourceAttr("buildkite_pipeline.foobar", "cluster_id", ""), + resource.TestCheckResourceAttr("buildkite_pipeline.foobar", "allow_rebuilds", "true"), + ), + }, + }, + }) +} + func TestAccPipeline_add_remove_complex(t *testing.T) { var resourcePipeline PipelineNode steps := `"steps:\n- command: buildkite-agent pipeline upload\n"` @@ -540,9 +579,8 @@ func testAccPipelineConfigBasicWithCluster(name string) string { resource "buildkite_pipeline" "foobar" { name = "Test Pipeline %s" repository = "https://github.com/buildkite/terraform-provider-buildkite.git" - steps = "" - cluster_id = "Q2x1c3Rlci0tLTRlN2JmM2FjLWUzMjMtNGY1OS05MGY2LTQ5OTljZmI2MGQyYg==" - allow_rebuilds = true + cluster_id = "Q2x1c3Rlci0tLTRlN2JmM2FjLWUzMjMtNGY1OS05MGY2LTQ5OTljZmI2MGQyYg==" + allow_rebuilds = true team { slug = "everyone"