diff --git a/CHANGELOG.md b/CHANGELOG.md index 62b917627a..66f6485081 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ All notable changes to `src-cli` are documented in this file. ### Added +- The `published` flag in campaign specs may now be an array, which allows only specific changesets within a campaign to be published based on the repository name. [#294](https://github.com/sourcegraph/src-cli/pull/294) + ### Changed - Error reporting by `src campaign [preview|apply]` has been improved and now includes more information about which step failed in which repository. [#325](https://github.com/sourcegraph/src-cli/pull/325) diff --git a/go.mod b/go.mod index 10a5703612..008104ae4e 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/olekukonko/tablewriter v0.0.4 // indirect github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4 github.com/pkg/errors v0.9.1 + github.com/sourcegraph/campaignutils v0.0.0-20200930004700-7633103cfc7f github.com/sourcegraph/codeintelutils v0.0.0-20200824140252-1db3aed5cf58 github.com/sourcegraph/go-diff v0.6.0 github.com/sourcegraph/jsonx v0.0.0-20200629203448-1a936bd500cf diff --git a/go.sum b/go.sum index a4b2c737d9..7978c26860 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/efritz/pentimento v0.0.0-20190429011147-ade47d831101 h1:RylpU+KNJJNEJIk3o8gZ70uPTlutxaYnikKNPko39LA= github.com/efritz/pentimento v0.0.0-20190429011147-ade47d831101/go.mod h1:5ALWO82UZwfAtNRUtwzsWimcrcuYzyieTyyXOXrP6EQ= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/google/go-cmp v0.4.1 h1:/exdXoGamhu5ONeUJH0deniYLWYvQwW66yvlfiiKTu0= github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= @@ -35,6 +37,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/sourcegraph/campaignutils v0.0.0-20200930004700-7633103cfc7f h1:99HEuBftdnPSmb8ykMm+PBQE8tOwXqasTLYfdknZ72I= +github.com/sourcegraph/campaignutils v0.0.0-20200930004700-7633103cfc7f/go.mod h1:5P8k8KlKz78RZJ2EFk9k9ln/j/twj28z/+BvO5hHZJ8= github.com/sourcegraph/codeintelutils v0.0.0-20200824140252-1db3aed5cf58 h1:Ps+U1xoZP+Zoph39YfRB6Q846ghO8pgrAgp0MiObvPs= github.com/sourcegraph/codeintelutils v0.0.0-20200824140252-1db3aed5cf58/go.mod h1:HplI8gRslTrTUUsSYwu28hSOderix7m5dHNca7xBzeo= github.com/sourcegraph/go-diff v0.6.0 h1:WbN9e/jD8ujU+o0vd9IFN5AEwtfB0rn/zM/AANaClqQ= diff --git a/internal/campaigns/campaign_spec.go b/internal/campaigns/campaign_spec.go index a297df5771..e7b2b19792 100644 --- a/internal/campaigns/campaign_spec.go +++ b/internal/campaigns/campaign_spec.go @@ -5,6 +5,7 @@ import ( "github.com/hashicorp/go-multierror" "github.com/pkg/errors" + "github.com/sourcegraph/campaignutils/override" "github.com/sourcegraph/src-cli/schema" "github.com/xeipuuv/gojsonschema" "gopkg.in/yaml.v2" @@ -40,7 +41,7 @@ type ChangesetTemplate struct { Body string `json:"body,omitempty" yaml:"body"` Branch string `json:"branch,omitempty" yaml:"branch"` Commit ExpandedGitCommitDescription `json:"commit,omitempty" yaml:"commit"` - Published bool `json:"published" yaml:"published"` + Published override.Bool `json:"published" yaml:"published"` } type GitCommitAuthor struct { diff --git a/internal/campaigns/executor.go b/internal/campaigns/executor.go index 76f1d86867..1c45b2d181 100644 --- a/internal/campaigns/executor.go +++ b/internal/campaigns/executor.go @@ -294,6 +294,8 @@ func reachedTimeout(cmdCtx context.Context, err error) bool { } func createChangesetSpec(task *Task, diff string) *ChangesetSpec { + repo := task.Repository.Name + var authorName string var authorEmail string @@ -323,7 +325,7 @@ func createChangesetSpec(task *Task, diff string) *ChangesetSpec { Diff: string(diff), }, }, - Published: task.Template.Published, + Published: task.Template.Published.Value(repo), }, } } diff --git a/schema/campaign_spec.schema.json b/schema/campaign_spec.schema.json index 463acb129b..c4375ebd4b 100644 --- a/schema/campaign_spec.schema.json +++ b/schema/campaign_spec.schema.json @@ -153,9 +153,24 @@ } }, "published": { - "type": "boolean", "description": "Whether to publish the changeset. An unpublished changeset can be previewed on Sourcegraph by any person who can view the campaign, but its commit, branch, and pull request aren't created on the code host. A published changeset results in a commit, branch, and pull request being created on the code host.", - "$comment": "TODO(sqs): Come up with a way to specify that only a subset of changesets should be published. For example, making `published` an array with some include/exclude syntax items." + "oneOf": [ + { + "type": "boolean", + "description": "A single flag to control the publishing state for the entire campaign." + }, + { + "type": "array", + "description": "A list of repository patterns to match. In the event multiple patterns match, the last matching pattern in the list will be used.", + "items": { + "type": "object", + "description": "An object with one field: the key is the glob pattern to match against repository names; the value will be used as the published flag for matching repositories.", + "additionalProperties": { "type": "boolean" }, + "minProperties": 1, + "maxProperties": 1 + } + } + ] } } } diff --git a/schema/campaign_spec_stringdata.go b/schema/campaign_spec_stringdata.go index 5920e859d6..77f7ed3e6b 100644 --- a/schema/campaign_spec_stringdata.go +++ b/schema/campaign_spec_stringdata.go @@ -158,9 +158,24 @@ const CampaignSpecJSON = `{ } }, "published": { - "type": "boolean", "description": "Whether to publish the changeset. An unpublished changeset can be previewed on Sourcegraph by any person who can view the campaign, but its commit, branch, and pull request aren't created on the code host. A published changeset results in a commit, branch, and pull request being created on the code host.", - "$comment": "TODO(sqs): Come up with a way to specify that only a subset of changesets should be published. For example, making ` + "`" + `published` + "`" + ` an array with some include/exclude syntax items." + "oneOf": [ + { + "type": "boolean", + "description": "A single flag to control the publishing state for the entire campaign." + }, + { + "type": "array", + "description": "A list of repository patterns to match. In the event multiple patterns match, the last matching pattern in the list will be used.", + "items": { + "type": "object", + "description": "An object with one field: the key is the glob pattern to match against repository names; the value will be used as the published flag for matching repositories.", + "additionalProperties": { "type": "boolean" }, + "minProperties": 1, + "maxProperties": 1 + } + } + ] } } }