Skip to content

Commit

Permalink
Add simple changelog generator
Browse files Browse the repository at this point in the history
    $ oc adm release info --changelog=/tmp/git ...

Will generate an opinionated changelog in markdown from the payload.
It requires `oc adm release extract --git=DIR` to be invoked first,
and will scan for PR merge commits in those repos and expose them.
Issues that begin with `Bug [0-9]+: ` will be linked to bugzilla.

This will eventually also be able to print a list of bugs that can
be marked as part of the payload.
  • Loading branch information
smarterclayton committed Feb 13, 2019
1 parent b22f758 commit 022cf4f
Show file tree
Hide file tree
Showing 4 changed files with 298 additions and 10 deletions.
2 changes: 2 additions & 0 deletions contrib/completions/bash/oc

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions contrib/completions/zsh/oc

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

113 changes: 106 additions & 7 deletions pkg/oc/cli/admin/release/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -240,16 +241,10 @@ func (o *ExtractOptions) extractGit(dir string) error {
}
alreadyExtracted[repo] = commit

u, err := sourceLocationAsURL(repo)
basePath, err := sourceLocationAsRelativePath(dir, repo)
if err != nil {
return err
}
gitPath := u.Path
if strings.HasSuffix(gitPath, ".git") {
gitPath = strings.TrimSuffix(gitPath, ".git")
}
gitPath = path.Clean(gitPath)
basePath := filepath.Join(dir, u.Host, filepath.FromSlash(gitPath))

var git *git
fi, err := os.Stat(basePath)
Expand Down Expand Up @@ -366,3 +361,107 @@ func sourceLocationAsURL(location string) (*url.URL, error) {
}
return url.Parse(location)
}

func sourceLocationAsRelativePath(dir, location string) (string, error) {
u, err := sourceLocationAsURL(location)
if err != nil {
return "", err
}
gitPath := u.Path
if strings.HasSuffix(gitPath, ".git") {
gitPath = strings.TrimSuffix(gitPath, ".git")
}
gitPath = path.Clean(gitPath)
basePath := filepath.Join(dir, u.Host, filepath.FromSlash(gitPath))
return basePath, nil
}

type MergeCommit struct {
CommitDate time.Time

Commit string
ParentCommits []string

PullRequest int
Bug int

Subject string
}

func mergeLogForRepo(g *git, from, to string) ([]MergeCommit, error) {
if from == to {
return nil, nil
}

rePR, err := regexp.Compile(`^Merge pull request #(\d+) from`)
if err != nil {
return nil, err
}
reBug, err := regexp.Compile(`^Bug (\d+): `)
if err != nil {
return nil, err
}

args := []string{"log", "--merges", "--topo-order", "-z", "--pretty=format:%H %P%x1E%ct%x1E%s%x1E%b", "--reverse", fmt.Sprintf("%s..%s", from, to)}
out, err := g.exec(args...)
if err != nil {
// retry once if there's a chance we haven't fetched the latest commits
if !strings.Contains(out, "Invalid revision range") {
return nil, fmt.Errorf(out)
}
if _, err := g.exec("fetch", "--all"); err != nil {
return nil, fmt.Errorf(out)
}
out, err = g.exec(args...)
if err != nil {
return nil, fmt.Errorf(out)
}
}

if glog.V(5) {
glog.Infof("Got commit info:\n%s", strconv.Quote(out))
}

var commits []MergeCommit
for _, entry := range strings.Split(out, "\x00") {
records := strings.Split(entry, "\x1e")
if len(records) != 4 {
return nil, fmt.Errorf("unexpected git log output width %d columns", len(records))
}
unixTS, err := strconv.ParseInt(records[1], 10, 64)
if err != nil {
return nil, fmt.Errorf("unexpected timestamp: %v", err)
}
commitValues := strings.Split(records[0], " ")

mergeCommit := MergeCommit{
CommitDate: time.Unix(unixTS, 0).UTC(),
Commit: commitValues[0],
ParentCommits: commitValues[1:],
}

msg := records[3]
if m := reBug.FindStringSubmatch(msg); m != nil {
mergeCommit.Subject = msg[len(m[0]):]
mergeCommit.Bug, err = strconv.Atoi(m[1])
if err != nil {
return nil, fmt.Errorf("could not extract bug number from %q: %v", msg, err)
}
} else {
mergeCommit.Subject = msg
}
mergeCommit.Subject = strings.TrimSpace(mergeCommit.Subject)

mergeMsg := records[2]
if m := rePR.FindStringSubmatch(mergeMsg); m != nil {
mergeCommit.PullRequest, err = strconv.Atoi(m[1])
if err != nil {
return nil, fmt.Errorf("could not extract PR number from %q: %v", mergeMsg, err)
}
}

commits = append(commits, mergeCommit)
}

return commits, nil
}
Loading

0 comments on commit 022cf4f

Please sign in to comment.