Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cmd/krel/cmd/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ go_library(
visibility = ["//visibility:public"],
deps = [
"//pkg/git:go_default_library",
"//pkg/notes:go_default_library",
"//pkg/release:go_default_library",
"//pkg/util:go_default_library",
"@com_github_google_go_github_v28//github:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@com_github_spf13_cobra//:go_default_library",
"@com_google_cloud_go//storage:go_default_library",
"@org_golang_x_oauth2//:go_default_library",
],
)

Expand Down
102 changes: 100 additions & 2 deletions cmd/krel/cmd/changelog.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,18 @@ limitations under the License.

package cmd

import "github.com/spf13/cobra"
import (
"context"

"github.com/google/go-github/v28/github"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"golang.org/x/oauth2"

"k8s.io/release/pkg/git"
"k8s.io/release/pkg/notes"
)

// changelogCmd represents the subcommand for `krel changelog`
var changelogCmd = &cobra.Command{
Expand Down Expand Up @@ -49,11 +60,98 @@ the golang based 'release-notes' tool:
},
}

type changelogOptions struct {
branch string
bucket string
tars string
token string
}

var changelogOpts = &changelogOptions{}

const master = "master"

func init() {
cobra.OnInitialize(initConfig)

const (
tarsFlag = "tars"
tokenFlag = "token"
)
changelogCmd.PersistentFlags().StringVar(&changelogOpts.branch, "branch", master, "The target release branch. Leave it default for non-patch releases.")
changelogCmd.PersistentFlags().StringVar(&changelogOpts.bucket, "bucket", "kubernetes-release", "Specify gs bucket to point to in generated notes")
changelogCmd.PersistentFlags().StringVar(&changelogOpts.tars, tarsFlag, "", "Directory of tars to sha512 sum for display")
changelogCmd.PersistentFlags().StringVarP(&changelogOpts.token, tokenFlag, "t", "", "GitHub token for release notes retrieval")

if err := changelogCmd.MarkPersistentFlagRequired(tokenFlag); err != nil {
logrus.Fatal(err)
}
if err := changelogCmd.MarkPersistentFlagRequired(tarsFlag); err != nil {
logrus.Fatal(err)
}

rootCmd.AddCommand(changelogCmd)
}

func runChangelog() error {
func runChangelog() (err error) {
branch := master
revisionDiscoveryMode := notes.RevisionDiscoveryModeMinorToMinor

if changelogOpts.branch != branch {
if !git.IsReleaseBranch(changelogOpts.branch) {
return errors.Wrapf(err, "Branch %q is no release branch", changelogOpts.branch)
}
branch = changelogOpts.branch
revisionDiscoveryMode = notes.RevisionDiscoveryModePatchToPatch
}
logrus.Infof("Using branch %q", branch)
logrus.Infof("Using discovery mode %q", revisionDiscoveryMode)

notesOptions := notes.NewOptions()
notesOptions.Branch = branch
notesOptions.DiscoverMode = revisionDiscoveryMode
notesOptions.GithubOrg = git.DefaultGithubOrg
notesOptions.GithubRepo = git.DefaultGithubRepo
notesOptions.GithubToken = changelogOpts.token
notesOptions.RepoPath = rootOpts.repoPath
notesOptions.ReleaseBucket = changelogOpts.bucket
notesOptions.ReleaseTars = changelogOpts.tars
notesOptions.Debug = logrus.StandardLogger().Level >= logrus.DebugLevel
if err := notesOptions.ValidateAndFinish(); err != nil {
return err
}

// Create the GitHub API client
ctx := context.Background()
httpClient := oauth2.NewClient(ctx, oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: changelogOpts.token},
))
githubClient := github.NewClient(httpClient)

// Fetch a list of fully-contextualized release notes
logrus.Info("fetching all commits. This might take a while...")

gatherer := &notes.Gatherer{
Client: notes.WrapGithubClient(githubClient),
Context: ctx,
Org: git.DefaultGithubOrg,
Repo: git.DefaultGithubRepo,
}
releaseNotes, history, err := gatherer.ListReleaseNotes(
branch, notesOptions.StartSHA, notesOptions.EndSHA, "", "",
)
if err != nil {
return errors.Wrapf(err, "listing release notes")
}

// Create the markdown
doc, err := notes.CreateDocument(releaseNotes, history)
if err != nil {
return errors.Wrapf(err, "creating release note document")
}

// TODO: mangle the documents into the target files
logrus.Infof("doc: %v", doc)

return nil
}
5 changes: 4 additions & 1 deletion cmd/krel/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ limitations under the License.
package cmd

import (
"os"
"path/filepath"

"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -50,7 +53,7 @@ func init() {

rootCmd.PersistentFlags().BoolVar(&rootOpts.nomock, "nomock", false, "nomock flag")
rootCmd.PersistentFlags().BoolVar(&rootOpts.cleanup, "cleanup", false, "cleanup flag")
rootCmd.PersistentFlags().StringVar(&rootOpts.repoPath, "repo", "", "the local path to the repository to be used")
rootCmd.PersistentFlags().StringVar(&rootOpts.repoPath, "repo", filepath.Join(os.TempDir(), "k8s"), "the local path to the repository to be used")
rootCmd.PersistentFlags().StringVar(&rootOpts.logLevel, "log-level", "info", "the logging verbosity, either 'panic', 'fatal', 'error', 'warn', 'warning', 'info', 'debug' or 'trace'")
}

Expand Down
1 change: 1 addition & 0 deletions cmd/release-notes/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ func init() {
notes.RevisionDiscoveryModeNONE,
notes.RevisionDiscoveryModeMinorToLatest,
notes.RevisionDiscoveryModePatchToPatch,
notes.RevisionDiscoveryModeMinorToMinor,
}, ", "),
),
)
Expand Down
58 changes: 42 additions & 16 deletions pkg/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,11 @@ func (r *Repo) RevParseShort(rev string) (string, error) {
// end (release-1.xx or master) revision inside the repository
func (r *Repo) LatestNonPatchFinalToLatest() (start, end string, err error) {
// Find the last non patch version tag, then resolve its revision
version, err := r.latestNonPatchFinalVersion()
versions, err := r.latestNonPatchFinalVersions()
if err != nil {
return "", "", err
}
version := versions[0]
versionTag := addTagPrefix(version.String())
logrus.Infof("latest non patch version %s", versionTag)
start, err = r.RevParse(versionTag)
Expand All @@ -230,34 +231,61 @@ func (r *Repo) LatestNonPatchFinalToLatest() (start, end string, err error) {
return start, end, nil
}

func (r *Repo) latestNonPatchFinalVersion() (semver.Version, error) {
latestFinalTag := semver.Version{}
func (r *Repo) LatestNonPatchFinalToMinor() (start, end string, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@saschagrunert are you planning to include tests for LatesteNonPatch* methods in a subsequent PR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah sure I was planning to bump the test coverage in the git package in the near future :)

// Find the last non patch version tag, then resolve its revision
versions, err := r.latestNonPatchFinalVersions()
if err != nil {
return "", "", err
}
if len(versions) < 2 {
return "", "", errors.New("unable to find two latest non patch versions")
}

latestVersion := versions[0]
latestVersionTag := addTagPrefix(latestVersion.String())
logrus.Infof("latest non patch version %s", latestVersionTag)
end, err = r.RevParse(latestVersionTag)
if err != nil {
return "", "", err
}

previousVersion := versions[1]
previousVersionTag := addTagPrefix(previousVersion.String())
logrus.Infof("previous non patch version %s", previousVersionTag)
start, err = r.RevParse(previousVersionTag)
if err != nil {
return "", "", err
}

return start, end, nil
}

func (r *Repo) latestNonPatchFinalVersions() ([]semver.Version, error) {
latestVersions := []semver.Version{}

tags, err := r.inner.Tags()
if err != nil {
return latestFinalTag, err
return nil, err
}

found := false
_ = tags.ForEach(func(t *plumbing.Reference) error { // nolint: errcheck
tag := trimTagPrefix(t.Name().Short())
ver, err := semver.Make(tag)

if err == nil {
// We're searching for the latest, non patch final tag
if ver.Patch == 0 && len(ver.Pre) == 0 {
if ver.GT(latestFinalTag) {
latestFinalTag = ver
found = true
if len(latestVersions) == 0 || ver.GT(latestVersions[0]) {
latestVersions = append([]semver.Version{ver}, latestVersions...)
}
}
}
return nil
})
if !found {
return latestFinalTag, fmt.Errorf("unable to find latest non patch release")
if len(latestVersions) == 0 {
return nil, fmt.Errorf("unable to find latest non patch release")
}
return latestFinalTag, nil
return latestVersions, nil
}

func (r *Repo) releaseBranchOrMasterRev(major, minor uint64) (rev string, err error) {
Expand Down Expand Up @@ -431,11 +459,9 @@ func (r *Repo) LatestPatchToPatch(branch string) (start, end string, err error)
return "", "", err
}

if len(latestTag.Pre) > 0 {
return "", "", errors.Errorf(
"found pre-release %v as latest tag on branch %s",
latestTag, branch,
)
if len(latestTag.Pre) > 0 && latestTag.Patch > 0 {
latestTag.Patch--
latestTag.Pre = nil
}

if latestTag.Patch == 0 {
Expand Down
12 changes: 6 additions & 6 deletions pkg/notes/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const (
RevisionDiscoveryModeNONE = "none"
RevisionDiscoveryModeMinorToLatest = "minor-to-latest"
RevisionDiscoveryModePatchToPatch = "patch-to-patch"
RevisionDiscoveryModeMinorToMinor = "minor-to-minor"
)

// NewOptions creates a new Options instance with the default values
Expand Down Expand Up @@ -83,14 +84,13 @@ func (o *Options) ValidateAndFinish() error {
var start, end string
if o.DiscoverMode == RevisionDiscoveryModeMinorToLatest {
start, end, err = repo.LatestNonPatchFinalToLatest()
if err != nil {
return err
}
} else if o.DiscoverMode == RevisionDiscoveryModePatchToPatch {
start, end, err = repo.LatestPatchToPatch(o.Branch)
if err != nil {
return err
}
} else if o.DiscoverMode == RevisionDiscoveryModeMinorToMinor {
start, end, err = repo.LatestNonPatchFinalToMinor()
}
if err != nil {
return err
}

o.StartSHA = start
Expand Down