mirror of
https://github.com/hashicorp/vault.git
synced 2025-11-13 23:01:11 +01:00
* [VAULT-39424] pipeline(close-origin-pr): add support for closing the origin of copied PRs
When we copy a community contributed Pull Request to Enterprise the
source PR is effectively orphaned, leaving the original PR still
opened, the author unsure of what state the copied PR is in, and any
issues associated with it open.
When the copied PR is closed we ought to close the origin PR if it's
still open, and any other issues that might be associated with either
the origin PR or the copied PR.
We can also add comments to both PRs that include links to each other
and the squash commit to make discovery of the work visible to those
with access to both repos. Unfortunately there is no way to know what
the SHA will be when it's synced so we have to rely on the
'Co-Authored-By:' trailers in commit message.
There are some challenges to this:
- The automation should only execute when copied PRs are closed
- How to determine the origin PR from only the copied PR
- How to determine the PR's linked issues (which the v3 REST API does not expose)
We solved them by:
- Requiring the PR HEAD ref to start with `copy/`
- Encoding the origin PR information in the PR HEAD ref.
e.g. `copy/hashicorp/vault/31580/ryan/VAULT-39424-test-ce`
- Using the V4 GraphQL API to determine "closed issue references"
The result is a new `pipeline` CLI command that can close the origin PR,
all of the issues, and write status comments on each PR with links to
everything to establish omnidirectional linking in the Github UI.
```bash
pipeline github close origin-pull-request 9903
```
* fix feedback
---------
Signed-off-by: Ryan Cragun <me@ryan.ec>
Co-authored-by: Ryan Cragun <me@ryan.ec>
65 lines
2.5 KiB
Go
65 lines
2.5 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/vault/tools/pipeline/internal/pkg/github"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var syncGithubBranchReq = github.SyncBranchReq{}
|
|
|
|
func newSyncGithubBranchCmd() *cobra.Command {
|
|
syncBranchCmd := &cobra.Command{
|
|
Use: "branch",
|
|
Short: "Sync a branch between two repositories",
|
|
Long: "Sync a branch between two repositories by merging the --from branch into the --to branch and pushing the result on success",
|
|
RunE: runSyncGithubBranchCmd,
|
|
}
|
|
|
|
syncBranchCmd.PersistentFlags().StringVar(&syncGithubBranchReq.FromOrigin, "from-origin", "from", "The origin name to use for the from-branch")
|
|
syncBranchCmd.PersistentFlags().StringVar(&syncGithubBranchReq.FromOwner, "from-owner", "hashicorp", "The Github organization hosting the from branch")
|
|
syncBranchCmd.PersistentFlags().StringVar(&syncGithubBranchReq.FromRepo, "from-repo", "vault-enterprise", "The Github repository to sync from")
|
|
syncBranchCmd.PersistentFlags().StringVar(&syncGithubBranchReq.FromBranch, "from-branch", "", "The name of the branch we want to sync from")
|
|
syncBranchCmd.PersistentFlags().StringVar(&syncGithubBranchReq.ToOrigin, "to-origin", "to", "The origin name to use for the to-branch")
|
|
syncBranchCmd.PersistentFlags().StringVar(&syncGithubBranchReq.ToOwner, "to-owner", "hashicorp", "The Github organization hosting the to branch")
|
|
syncBranchCmd.PersistentFlags().StringVar(&syncGithubBranchReq.ToRepo, "to-repo", "vault", "The Github repository to sync to")
|
|
syncBranchCmd.PersistentFlags().StringVar(&syncGithubBranchReq.ToBranch, "to-branch", "", "The name of the branch we want to sync to")
|
|
syncBranchCmd.PersistentFlags().StringVarP(&syncGithubBranchReq.RepoDir, "repo-dir", "d", "", "The path to the vault repository dir. If not set a temporary directory will be used")
|
|
|
|
err := syncBranchCmd.MarkPersistentFlagRequired("from-branch")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = syncBranchCmd.MarkPersistentFlagRequired("to-branch")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return syncBranchCmd
|
|
}
|
|
|
|
func runSyncGithubBranchCmd(cmd *cobra.Command, args []string) error {
|
|
cmd.SilenceUsage = true // Don't spam the usage on failure
|
|
|
|
res, err := syncGithubBranchReq.Run(context.TODO(), githubCmdState.GithubV3, githubCmdState.Git)
|
|
|
|
switch rootCfg.format {
|
|
case "json":
|
|
b, err1 := res.ToJSON()
|
|
if err1 != nil {
|
|
return errors.Join(err, err1)
|
|
}
|
|
fmt.Println(string(b))
|
|
default:
|
|
fmt.Println(res.ToTable(err).Render())
|
|
}
|
|
|
|
return err
|
|
}
|