mirror of
https://github.com/hashicorp/vault.git
synced 2025-11-14 07:11: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>
66 lines
2.7 KiB
Go
66 lines
2.7 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/vault/tools/pipeline/internal/pkg/github"
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var checkGithubCommitStatusReq = github.CheckCommitStatusReq{}
|
|
|
|
func newCheckGithubCommitStatusCmd() *cobra.Command {
|
|
checkCommitStatusCmd := &cobra.Command{
|
|
Use: "commit-status --context <context> --creator <creator> --state <state> [--pr 1234 | --commit 1a61dbe57a7538f22f7fa3fb65900d9d41c2ba14]",
|
|
Short: "Check a commit status for a PR or commit",
|
|
Long: "Check a commit status for a specific context and creator matches an expected state. When given provided the --pr flag the HEAD sha will be used as the commit",
|
|
RunE: runCheckGithubCommitStatusCmd,
|
|
}
|
|
|
|
checkCommitStatusCmd.PersistentFlags().StringVarP(&checkGithubCommitStatusReq.Owner, "owner", "o", "hashicorp", "The Github organization")
|
|
checkCommitStatusCmd.PersistentFlags().StringVarP(&checkGithubCommitStatusReq.Repo, "repo", "r", "vault", "The Github repository. Private repositories require auth via a GITHUB_TOKEN env var")
|
|
checkCommitStatusCmd.PersistentFlags().StringVarP(&checkGithubCommitStatusReq.Commit, "commit", "c", "", "The commit you wish to list the statuses of")
|
|
checkCommitStatusCmd.PersistentFlags().IntVarP(&checkGithubCommitStatusReq.PR, "pr", "p", 0, "The Pull Request number you wish to use as the source. The HEAD commit will be used")
|
|
checkCommitStatusCmd.PersistentFlags().StringVar(&checkGithubCommitStatusReq.Context, "context", "", "The context of the status. This usually maps to the name of the check that shows up in the Pull Request status box")
|
|
checkCommitStatusCmd.PersistentFlags().StringVar(&checkGithubCommitStatusReq.Creator, "creator", "", "The github login of the creator of the status")
|
|
checkCommitStatusCmd.PersistentFlags().StringVarP(&checkGithubCommitStatusReq.State, "state", "s", "success", "The expected state of the status. Can be one of 'error', 'failure', 'pending', 'success'")
|
|
|
|
err := checkCommitStatusCmd.MarkPersistentFlagRequired("context")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return checkCommitStatusCmd
|
|
}
|
|
|
|
func runCheckGithubCommitStatusCmd(cmd *cobra.Command, args []string) error {
|
|
cmd.SilenceUsage = true // Don't spam the usage on failure
|
|
|
|
res, err := checkGithubCommitStatusReq.Run(context.TODO(), githubCmdState.GithubV3)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
switch rootCfg.format {
|
|
case "json":
|
|
b, err := json.Marshal(res)
|
|
if err != nil {
|
|
return fmt.Errorf("marshaling response to JSON: %w", err)
|
|
}
|
|
fmt.Println(string(b))
|
|
default:
|
|
fmt.Println(res.ToTable().Render())
|
|
}
|
|
|
|
if !res.CheckSuccessful {
|
|
return fmt.Errorf("no statuses matched expected criteria: %s", res.String())
|
|
}
|
|
|
|
return nil
|
|
}
|