Skip to content

Commit

Permalink
feat: create annotated tag and list project tags optimised (#23)
Browse files Browse the repository at this point in the history
* refactor: get latest project version using native version sort and filter

* fix: create annotated tags rather than lightweight

* fix: up git-module to support annotated tags and efficient tag filter and sorting

* feat: add envvars and restructure

* test: add unit tests to tag component

* fix: minor cleanup

* refactor: introduce git client interfaces
  • Loading branch information
sermojohn committed Mar 16, 2022
1 parent f02834f commit 37e0764
Show file tree
Hide file tree
Showing 36 changed files with 1,002 additions and 410 deletions.
75 changes: 59 additions & 16 deletions cmd/gitmono/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,24 @@ func (opts *Options) Config() *ctx.Config {
}

func main() {
monorepo, err := ctx.OpenRepo("./")
ctx, err := newContext()
checkError(err)

ctx := newContext(monorepo)
var (
opts Options
commands = []command{
opts Options
flagsParser = flags.NewParser(&opts, flags.IgnoreUnknown|flags.HelpFlag|flags.PrintErrors)
commands = []command{
newDiffCommand(ctx.differ),
newLogCommand(ctx.logger),
newInitCommand(ctx.versioner),
newReleaseCommand(ctx.versioner),
newVersionCommand(ctx.versioner),
}
flagsParser = flags.NewParser(&opts, flags.IgnoreUnknown|flags.HelpFlag)
)

// inject options to global component
flagsParser.CommandHandler = func(command flags.Commander, args []string) error {
monorepo.SetConfig(opts.Config())
ctx.config = opts.Config()
return command.Execute(args)
}
for _, command := range commands {
Expand Down Expand Up @@ -105,22 +104,66 @@ func checkError(err error) {
}

type context struct {
// components
versioner ctx.Versioner
tagger ctx.Tagger
differ ctx.Differ
logger ctx.Logger
// state
config *ctx.Config
envVars *ctx.EnvVars
}

func newContext(monorepo *ctx.MonoRepo) *context {
log := gitmono.NewLog(monorepo)
tag := gitmono.NewTag(monorepo)
diff := gitmono.NewDiff(monorepo)
commitParse := gitmono.NewCommitParse(monorepo)
version := gitmono.NewVersion(monorepo, log, tag, commitParse)
func newContext() (*context, error) {
gitClient, err := newGitClient("./")
if err != nil {
return nil, err
}

config := &ctx.Config{}
envVars := loadEnvVars(os.LookupEnv)
logger := gitmono.NewLog(gitClient, config)
tagger := gitmono.NewTag(gitClient, config, envVars)
differ := gitmono.NewDiff(gitClient, config)
commitParse := gitmono.NewCommitParse(config)
versioner := gitmono.NewVersion(config, logger, tagger, commitParse)

return &context{
versioner: version,
tagger: tag,
differ: diff,
logger: log,
config: config,
envVars: envVars,
logger: logger,
tagger: tagger,
differ: differ,
versioner: versioner,
}, nil
}

type gitClient struct {
*git.Repository
}

func newGitClient(path string) (*gitClient, error) {
repo, err := git.Open("./")
if err != nil {
return nil, err
}

cl := gitClient{
Repository: repo,
}

return &cl, nil
}

func loadEnvVars(loaderFunc func(string) (string, bool)) *ctx.EnvVars {
envVars := ctx.EnvVars{}
if value, found := loaderFunc("GIT_COMMITTER_NAME"); found {
envVars.CommitterName = value
}

if value, found := loaderFunc("GIT_COMMITTER_EMAIL"); found {
envVars.CommitterEmail = value
}

return &envVars
}
56 changes: 56 additions & 0 deletions cmd/gitmono/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package main

import (
"reflect"
"testing"

ctx "github.com/sermojohn/gitmono"
)

func Test_loadEnvVars(t *testing.T) {
t.Parallel()

type args struct {
loaderFunc func(string) (string, bool)
}
tests := []struct {
name string
args args
want *ctx.EnvVars
}{
{
name: "no vars",
args: args{
loaderFunc: func(s string) (string, bool) {
return "", false
},
},
want: &ctx.EnvVars{},
},
{
name: "git committer vars",
args: args{
loaderFunc: func(s string) (string, bool) {
if s == "GIT_COMMITTER_NAME" {
return "alice", true
}
if s == "GIT_COMMITTER_EMAIL" {
return "alice@example.com", true
}
return "", false
},
},
want: &ctx.EnvVars{
CommitterName: "alice",
CommitterEmail: "alice@example.com",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := loadEnvVars(tt.args.loaderFunc); !reflect.DeepEqual(got, tt.want) {
t.Errorf("loadEnvVars() = %v, want %v", got, tt.want)
}
})
}
}
51 changes: 23 additions & 28 deletions gitmono.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import (
"github.com/hashicorp/go-version"
)

// MonoRepo contains repository instance and command parameters
type MonoRepo struct {
*git.Repository
config *Config
// EnvVars contains the accepted environment variables
type EnvVars struct {
CommitterName string
CommitterEmail string
}

// Config defines generic configuration applying to multiple commands
Expand All @@ -21,28 +21,6 @@ type Config struct {
Project string
}

// OpenRepo open a git repository and returns the monorepo wrapper
func OpenRepo(path string) (*MonoRepo, error) {
repo, err := git.Open("./")
if err != nil {
return nil, err
}

monorepo := MonoRepo{Repository: repo, config: &Config{}}

return &monorepo, nil
}

// SetConfig sets the configuration provided by the command-line
func (mr *MonoRepo) SetConfig(config *Config) {
*mr.config = *config
}

// GetConfig gets the configuration provided by the command-line
func (mr *MonoRepo) GetConfig() *Config {
return mr.config
}

// Logger performs log commands on the repo
//
// Log returns the commits for the specified reference range in reverse chronological order
Expand All @@ -54,11 +32,11 @@ type Logger interface {

// Tagger performs tag commands on the repo
//
// Tags returns all tags from the repo
// CreateTag writes the given tag to the given commit
// ListProjectVersionTags retrieves all tags for a project using the tag list pattern
type Tagger interface {
Tags() ([]string, error)
CreateTag(versionedCommit *VersionedCommit) error
ListProjectVersionTags() ([]string, error)
}

// Versioner maintains version using tags
Expand Down Expand Up @@ -110,3 +88,20 @@ func (vc *VersionedCommit) GetTag() string {
func (vc *VersionedCommit) GetVersion() string {
return fmt.Sprintf("%s%s", vc.VersionPrefix, vc.Version.String())
}

// GitTagger abstracts git tag operations
type GitTagger interface {
Tags(opts ...git.TagsOptions) ([]string, error)
CreateTag(name, rev string, opts ...git.CreateTagOptions) error
}

// GitLogger abstracts git log operations
type GitLogger interface {
Log(rev string, opts ...git.LogOptions) ([]*git.Commit, error)
CommitByRevision(rev string, opts ...git.CommitByRevisionOptions) (*git.Commit, error)
}

// GitDiffer abstracts git diff operations
type GitDiffer interface {
Diff(rev string, maxFiles, maxFileLines, maxLineChars int, opts ...git.DiffOptions) (*git.Diff, error)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/sermojohn/gitmono
go 1.17

require (
github.com/gogs/git-module v1.2.0
github.com/gogs/git-module v1.4.0
github.com/hashicorp/go-version v1.4.0
github.com/jessevdk/go-flags v1.5.0
github.com/stretchr/testify v1.7.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gogs/git-module v1.2.0 h1:eetCyhSSFUkIWqES91Se9ue26fEWiRZi+eI2D13syJk=
github.com/gogs/git-module v1.2.0/go.mod h1:oN37FFStFjdnTJXsSbhIHKJXh2YeDsEcXPATVz/oeuQ=
github.com/gogs/git-module v1.4.0 h1:+0zcvzp3wxEMXVar2KnKmhI6JKlcAwjNUc6b5aTxs5M=
github.com/gogs/git-module v1.4.0/go.mod h1:oN37FFStFjdnTJXsSbhIHKJXh2YeDsEcXPATVz/oeuQ=
github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4=
github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
Expand Down
41 changes: 41 additions & 0 deletions internal/mock/git_tagger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package mock

import "github.com/gogs/git-module"

type GitTagger struct {
TagsOutput []string
TagsError error
TagsInputs []*TagsInput
CreateTagError error
CreateTagInputs []*CreateTagInput
}

func (gt *GitTagger) Tags(opts ...git.TagsOptions) ([]string, error) {
if gt.TagsError != nil {
return nil, gt.TagsError
}
gt.TagsInputs = append(gt.TagsInputs, &TagsInput{Opts: opts})
return gt.TagsOutput, nil
}

func (gt *GitTagger) CreateTag(name, rev string, opts ...git.CreateTagOptions) error {
if gt.CreateTagError != nil {
return gt.CreateTagError
}
gt.CreateTagInputs = append(gt.CreateTagInputs, &CreateTagInput{
Name: name,
Rev: rev,
Opts: opts,
})
return nil
}

type TagsInput struct {
Opts []git.TagsOptions
}

type CreateTagInput struct {
Name string
Rev string
Opts []git.CreateTagOptions
}
21 changes: 21 additions & 0 deletions internal/mock/tagger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package mock

import "github.com/sermojohn/gitmono"

type Tagger struct {
ListProjectVersionTagsOutput []string
ListProjectVersionTagsError error
CreateTagError error
}

func (t *Tagger) ListProjectVersionTags() ([]string, error) {
if t.ListProjectVersionTagsError != nil {
return nil, t.ListProjectVersionTagsError
}

return t.ListProjectVersionTagsOutput, nil
}

func (t *Tagger) CreateTag(versionedCommit *gitmono.VersionedCommit) error {
return t.CreateTagError
}
4 changes: 2 additions & 2 deletions pkg/gitmono/commit_parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ type CommitParse struct {
}

// NewCommitParse creates a new commit parser
func NewCommitParse(monorepo *gitmono.MonoRepo) *CommitParse {
func NewCommitParse(config *gitmono.Config) *CommitParse {
return &CommitParse{
config: monorepo.GetConfig(),
config: config,
}
}

Expand Down
12 changes: 7 additions & 5 deletions pkg/gitmono/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import (

// Diff performs diff operation for a monorepo.
type Diff struct {
monorepo *gitmono.MonoRepo
differ gitmono.GitDiffer
config *gitmono.Config
}

// NewDiff creates a new differ instance.
func NewDiff(monorepo *gitmono.MonoRepo) *Diff {
func NewDiff(differ gitmono.GitDiffer, config *gitmono.Config) *Diff {
diff := Diff{
monorepo: monorepo,
differ: differ,
config: config,
}

return &diff
Expand All @@ -24,7 +26,7 @@ func NewDiff(monorepo *gitmono.MonoRepo) *Diff {
// Diff performs diff for the provided git references range
// Matches changed files to the provided monorepo project and return the list of files
func (d *Diff) Diff(from, to string) ([]string, error) {
diffRes, err := d.monorepo.Diff(to, 0, 0, 0, git.DiffOptions{
diffRes, err := d.differ.Diff(to, 0, 0, 0, git.DiffOptions{
Base: from,
})
if err != nil {
Expand All @@ -33,7 +35,7 @@ func (d *Diff) Diff(from, to string) ([]string, error) {

var (
changedFiles = []string{}
project = d.monorepo.GetConfig().Project
project = d.config.Project
)
for _, file := range diffRes.Files {
if project == "." || strings.HasPrefix(file.Name, project) {
Expand Down
Loading

0 comments on commit 37e0764

Please sign in to comment.