vault/tools/pipeline/internal/cmd/github.go
Ryan Cragun 3e9f84e666
[VAULT-36202] pipeline(releases): add releases list active-versions command (#30658)
While working on VAULT-34829 it became apparent that if our new backporter
could know which branches are active and which CE counterparts are active
then we could completely omit the need for `ce` backport labels and instead
automatically backport to corresponding CE branches that are active.

To facilitate that we can re-use our `.release/versions.hcl` file as it is
the current source of truth for our present backport assistant workflow.

Here we add a new `pipeline releases list versions` command that is capable
of decoding that file and optionally displaying it. It will be used in the
next PR that fully implements VAULT-34829.

As part of this work we refactors `pipeline releases` to include a new `list`
sub-command and moved both `list-active-versions` and `versions` to it.

We also include a few small fixes that were noticed:
  - `.release/verions.hcl` was not up-to-date
  - Our cached dynamic config was not getting recreated when the pipeline
    tool changed. That has been fixed so now dynamic config should always
    get recreated when the pipeline binary changes
  - We now initialize a git client when using the `github` sub-command.
    This will be used in more forthcoming work
  - Update our changed file detection to resolve some incorrect groupings
  - Add some additional changed file helpers that we be used in forthcoming
    work

Signed-off-by: Ryan Cragun <me@ryan.ec>
2025-05-20 11:10:24 -06:00

78 lines
1.9 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package cmd
import (
"errors"
"fmt"
"os"
"path/filepath"
gh "github.com/google/go-github/v68/github"
"github.com/hashicorp/vault/tools/pipeline/internal/pkg/git"
"github.com/spf13/cobra"
)
type githubCommandState struct {
Github *gh.Client
Git *git.Client
}
var githubCmdState = &githubCommandState{
Github: gh.NewClient(nil),
Git: git.NewClient(git.WithLoadTokenFromEnv()),
}
func newGithubCmd() *cobra.Command {
github := &cobra.Command{
Use: "github",
Short: "Github commands",
Long: "Github commands",
}
github.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
if parent := cmd.Parent(); parent != nil {
if parent.PersistentPreRunE != nil {
err := parent.PersistentPreRunE(parent, args)
if err != nil {
return err
}
}
}
if token, set := os.LookupEnv("GITHUB_TOKEN"); set {
githubCmdState.Github = githubCmdState.Github.WithAuthToken(token)
} else {
fmt.Println("\x1b[1;33;49mWARNING\x1b[0m: GITHUB_TOKEN has not been set. While not always required for read actions on public repositories you're likely to get throttled without it")
}
return nil
}
github.AddCommand(newGithubListCmd())
return github
}
func writeToGithubOutput(key string, bytes []byte) error {
devPath, ok := os.LookupEnv("GITHUB_OUTPUT")
if !ok {
return errors.New("$GITHUB_OUTPUT has not been set. Cannot write changed files to it")
}
expanded, err := filepath.Abs(devPath)
if err != nil {
return fmt.Errorf("failed to expand $GITHUB_OUTPUT path: %w", err)
}
dev, err := os.OpenFile(expanded, os.O_APPEND|os.O_WRONLY, 0o644)
if err != nil {
return fmt.Errorf("failed to open $GITHUB_OUTPUT for writing: %w", err)
}
defer func() { _ = dev.Close() }()
_, err = dev.Write(append([]byte(key+"="), bytes...))
if err != nil {
return fmt.Errorf("failed to write key %s to $GITHUB_OUTPUT: %w", key, err)
}
return nil
}