From 2e9b67b5f07a54029100ddb7c1ddc71a8a7aa52f Mon Sep 17 00:00:00 2001 From: Thorsten Ball Date: Fri, 11 Dec 2020 10:26:42 +0100 Subject: [PATCH] Add transformChanges to campaign spec and document it (#16235) * Extend CampaignSpec schema with transformChanges * Change branchSuffix to branch * Add transformChanges to campaign spec YAML ref * Update campaign spec schema to newest state * Update doc/campaigns/references/campaign_spec_yaml_reference.md Co-authored-by: Chris Pine * Add changelog entry Co-authored-by: Chris Pine --- CHANGELOG.md | 1 + .../campaign_spec_yaml_reference.md | 80 ++++++++++++++++++- schema/campaign_spec.schema.json | 30 +++++++ schema/campaign_spec_stringdata.go | 30 +++++++ schema/schema.go | 8 ++ 5 files changed, 145 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d84f5717881b..418268d3baa9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ All notable changes to Sourcegraph are documented in this file. - The campaigns preview page is much more detailed now, especially when updating existing campaigns. [#16240](https://github.com/sourcegraph/sourcegraph/pull/16240) - When a newer version of a campaign spec is uploaded, a message is now displayed when viewing the campaign or an outdated campaign spec. [#14532](https://github.com/sourcegraph/sourcegraph/issues/14532) - Changesets in a campaign can now be searched by title and repository name. [#15781](https://github.com/sourcegraph/sourcegraph/issues/15781) +- Experimental: [`transformChanges` in campaign specs](https://docs.sourcegraph.com/campaigns/references/campaign_spec_yaml_reference#transformchanges) is now available as a feature preview to allow users to create multiple changesets in a single repository. [#16235](https://github.com/sourcegraph/sourcegraph/pull/16235) ### Changed diff --git a/doc/campaigns/references/campaign_spec_yaml_reference.md b/doc/campaigns/references/campaign_spec_yaml_reference.md index 0214a2e004a7..a8758d70d930 100644 --- a/doc/campaigns/references/campaign_spec_yaml_reference.md +++ b/doc/campaigns/references/campaign_spec_yaml_reference.md @@ -1,6 +1,18 @@ # Campaign spec YAML reference - + [Sourcegraph campaigns](../index.md) use [campaign specs](../explanations/introduction_to_campaigns.md#campaign-spec) to define campaigns. @@ -33,11 +45,11 @@ description: This campaign changes all `fmt.Sprintf` calls to `strconv.Iota`. ```yaml description: | This campaign changes all imports from - + `gopkg.in/sourcegraph/sourcegraph-in-x86-asm` - + to - + `github.com/sourcegraph/sourcegraph-in-x86-asm` ``` @@ -455,3 +467,63 @@ changesetTemplate: - "*": true - github.com/*: draft ``` + + +## [`transformChanges`](#transformchanges) + + + +A description of how to transform the changes (diffs) produced in each repository before turning them into separate changeset specs by inserting them into the [`changesetTemplate`](#changesettemplate). + +This allows the creation of multiple changeset specs (and thus changesets) in a single repository. + +### Examples + +```yaml +# Transform the changes produced in each repository. +transformChanges: + # Group the file diffs by directory and produce an additional changeset per group. + group: + # Create a separate changeset for all changes in the top-level `go` directory + - directory: go + branch: my-campaign-go # will replace the `branch` in the `changesetTemplate` + + - directory: internal/codeintel + branch: my-campaign-codeintel # will replace the `branch` in the `changesetTemplate` + repository: github.com/sourcegraph/src-cli # optional: only apply the rule in this repository +``` + + +```yaml +transformChanges: + group: + - directory: go/utils/time + branch: my-campaign-go-time + + # The *last* matching directory is used, not the most specific one, + # so only this changeset would be opened. + - directory: go/utils + branch: my-campaign-go-date +``` + +## [`transformChanges.group`](#transformchanges-group) + +A list of groups to define which file diffs to group together to create an additional changeset in the given repository. + +The **order of the list matters**, since each file diff's filepath is matched against the `directory` of a group and the **last match** is used. + +## [`transformChanges.group.directory`](#transformchanges-group-directory) + +The name of the directory in which file diffs should be grouped together. + +## [`transformChanges.group.branch`](#transformchanges-group-branch) + +The branch that should be used for this additional changeset. This **overwrites the [`changesetTemplate.branch`](#changesettemplate-branch)** when creating the additional changeset. + +**Important**: the branch can _not_ be nested under the [`changesetTemplate.branch`](#changesettemplate-branch), i.e. if the `changesetTemplate.branch` is `my-campaign` then this can _not_ be `my-campaign/my-subdirectory` since [git doesn't allow that](https://stackoverflow.com/a/22630664). + +## [`transformChanges.group.repository`](#transformchanges-repository) + +Optional: the file diffs matching the given directory will only be grouped in a repository with that name configured on your Sourcegraph instance. diff --git a/schema/campaign_spec.schema.json b/schema/campaign_spec.schema.json index 625d732f226e..39a97f19a11b 100644 --- a/schema/campaign_spec.schema.json +++ b/schema/campaign_spec.schema.json @@ -115,6 +115,36 @@ } } }, + "transformChanges": { + "type": "object", + "description": "Optional transformations to apply to the changes produced in each repository.", + "additionalProperties": false, + "properties": { + "group": { + "type": "array", + "description": "A list of groups of changes in a repository that each create a separate, additional changeset for this repository, with all ungrouped changes being in the default changeset.", + "additionalProperties": false, + "required": ["directory", "branchSuffix"], + "properties": { + "directory": { + "type": "string", + "description": "The directory path (relative to the repository root) of the changes to include in this group.", + "minLength": 1 + }, + "branch": { + "type": "string", + "description": "The branch on the repository to propose changes to. If unset, the repository's default branch is used.", + "minLength": 1 + }, + "repository": { + "type": "string", + "description": "Only apply this transformation in the repository with this name (as it is known to Sourcegraph).", + "examples": ["github.com/foo/bar"] + } + } + } + } + }, "importChangesets": { "type": "array", "description": "Import existing changesets on code hosts.", diff --git a/schema/campaign_spec_stringdata.go b/schema/campaign_spec_stringdata.go index 9592ed9ae326..91f5ca61af12 100644 --- a/schema/campaign_spec_stringdata.go +++ b/schema/campaign_spec_stringdata.go @@ -120,6 +120,36 @@ const CampaignSpecSchemaJSON = `{ } } }, + "transformChanges": { + "type": "object", + "description": "Optional transformations to apply to the changes produced in each repository.", + "additionalProperties": false, + "properties": { + "group": { + "type": "array", + "description": "A list of groups of changes in a repository that each create a separate, additional changeset for this repository, with all ungrouped changes being in the default changeset.", + "additionalProperties": false, + "required": ["directory", "branchSuffix"], + "properties": { + "directory": { + "type": "string", + "description": "The directory path (relative to the repository root) of the changes to include in this group.", + "minLength": 1 + }, + "branch": { + "type": "string", + "description": "The branch on the repository to propose changes to. If unset, the repository's default branch is used.", + "minLength": 1 + }, + "repository": { + "type": "string", + "description": "Only apply this transformation in the repository with this name (as it is known to Sourcegraph).", + "examples": ["github.com/foo/bar"] + } + } + } + } + }, "importChangesets": { "type": "array", "description": "Import existing changesets on code hosts.", diff --git a/schema/schema.go b/schema/schema.go index a9687fe32595..f376bd123138 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -317,6 +317,8 @@ type CampaignSpec struct { On []interface{} `json:"on,omitempty"` // Steps description: The sequence of commands to run (for each repository branch matched in the `on` property) to produce the campaign's changes. Steps []*Step `json:"steps,omitempty"` + // TransformChanges description: Optional transformations to apply to the changes produced in each repository. + TransformChanges *TransformChanges `json:"transformChanges,omitempty"` } // ChangesetTemplate description: A template describing how to create (and update) changesets with the file changes produced by the command steps. @@ -1281,6 +1283,12 @@ type TlsExternal struct { // If InsecureSkipVerify is true, TLS accepts any certificate presented by the server and any host name in that certificate. In this mode, TLS is susceptible to man-in-the-middle attacks. InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"` } + +// TransformChanges description: Optional transformations to apply to the changes produced in each repository. +type TransformChanges struct { + // Group description: A list of groups of changes in a repository that each create a separate, additional changeset for this repository, with all ungrouped changes being in the default changeset. + Group []interface{} `json:"group,omitempty"` +} type UsernameIdentity struct { Type string `json:"type"` }