Skip to content

Commit

Permalink
Merge pull request #6 from LMaxence/feat/step-arguments
Browse files Browse the repository at this point in the history
feat: add support for MATCHED_FILES and PACKAGE_FILES step argument
  • Loading branch information
LMaxence authored Oct 5, 2024
2 parents 2efd890 + 11c7475 commit 24404e9
Show file tree
Hide file tree
Showing 26 changed files with 1,259 additions and 901 deletions.
507 changes: 37 additions & 470 deletions cover.out

Large diffs are not rendered by default.

505 changes: 505 additions & 0 deletions coverage.txt

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ With `Gookme`, your hooks are stored in JSON files called `{hook-type}.json` whe

3. Other selections (`onlyOn` for instance) are applied on each step of each package, based on the list of paths attached to the package and it's steps.

!!! tip
Depending on the hook type being executed, or the arguments passed to the command, the list of paths can be different.

- The hook type `pre-push` will consider the list of files to be pushed to the remote server
- The hook type `post-commit` will consider the list of files included in the last commit
- If the `run` command argument --from and --to are used, the list of paths will be the list of files changed between the two commits
- All other hook types will use the list of files changed in the current commit, and staged

### Example of hook file

Your hooks are defined in simple json files.
Expand Down
10 changes: 7 additions & 3 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,14 @@ A set of arguments is provided by Mookme, that can be directly used in the hooks

````json title="hooks/commit-msg.json"
{
"command": "run-something $1" // Will be replaced with the value of `args`
"command": "run-something $1" // (1)!
"command": "run-something $MATCHED_FILES" // (2)!
"command": "run-something $PACKAGE_FILES" // (3)!
}
````

- `$1`
1. The argument being passed by git to the hook file. See [the Git documentation on the hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) for more details about what it contains depending on the hook type being executed.

The argument being passed by git to the hook file. See [the Git documentation on the hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) for more details about what it contains depending on the hook type being executed.
2. The list of changed files matched by the onlyOn option of this step, separated by a space. If the onlyOn option is not set, it will be replaced with an empty string.

3. The list of changed files in the package folder, separated by a space.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ theme:

features:
- content.tabs.link
- content.code.annotate

palette:
- media: "(prefers-color-scheme)"
Expand Down
39 changes: 25 additions & 14 deletions packages/cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (

"github.com/LMaxence/gookme/packages/configuration"
"github.com/LMaxence/gookme/packages/executor"
"github.com/LMaxence/gookme/packages/filters"
gitclient "github.com/LMaxence/gookme/packages/git-client"
"github.com/LMaxence/gookme/packages/scheduler"
"github.com/urfave/cli/v2"
)

Expand All @@ -23,6 +23,26 @@ type RunCommandArguments struct {
To string
}

func selectResolvingStrategy(dir string, args *RunCommandArguments) filters.ChangesetResolvingStrategy {
var changesetResolvingStrategy filters.ChangesetResolvingStrategy

if args.From != "" && args.To != "" {
logger.Debugf("Using FromToChangesResolvingStrategy")
changesetResolvingStrategy = filters.NewFromToChangesResolvingStrategy(dir, args.From, args.To)
} else if args.HookType == configuration.PrePushHookType {
logger.Debugf("Using PrePushChangesResolvingStrategy")
changesetResolvingStrategy = filters.NewStagedChangesResolvingStrategy(dir)
} else if args.HookType == configuration.PostCommitHookType {
logger.Debugf("Using StagedChangesResolvingStrategy")
changesetResolvingStrategy = filters.NewStagedChangesResolvingStrategy(dir)
} else {
logger.Debugf("Using StagedChangesResolvingStrategy")
changesetResolvingStrategy = filters.NewStagedChangesResolvingStrategy(dir)
}

return changesetResolvingStrategy
}

func parseRunCommandArguments(cContext *cli.Context) (*RunCommandArguments, error) {
hookType, err := validateHookType(cContext.String("type"))
if err != nil {
Expand Down Expand Up @@ -52,24 +72,15 @@ func run(args RunCommandArguments) error {
return err
}

var delimiter *gitclient.GitRefDelimiter
if args.From != "" && args.To != "" {
logger.Debugf("Setting Git ref delimiter from %s to %s", args.From, args.To)
delimiter = &gitclient.GitRefDelimiter{
From: args.From,
To: args.To,
}
}

changedPaths, err := gitclient.GetStagedFiles(&dir, delimiter)
logger.Tracef("Staged files: %v", changedPaths)
changedPaths, err := selectResolvingStrategy(dir, &args).Resolve()
logger.Tracef("Resolved changeset: %v", changedPaths)
if err != nil {
logger.Errorf("Error while getting staged files: %s", err)
return err
}

conf.Hooks = scheduler.FilterHooksWithChangeset(changedPaths, conf.Hooks)
conf.Hooks = scheduler.FilterStepsWithOnlyOn(changedPaths, conf.Hooks)
conf.Hooks = filters.FilterHooksWithChangeset(changedPaths, conf.Hooks)
conf.Hooks = filters.FilterStepsWithOnlyOn(changedPaths, conf.Hooks)

nSteps := 0
for _, hook := range conf.Hooks {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

func validateHookType(value string) (configuration.HookType, error) {
switch configuration.HookType(value) {
case configuration.PreCommit, configuration.CommitMsg, configuration.PostCheckout, configuration.PostMerge, configuration.PostRewrite, configuration.PrePush, configuration.PreRebase, configuration.PostCommit, configuration.PrepareCommit:
case configuration.PreCommitHookType, configuration.CommitMsgHookType, configuration.PostCheckoutHookType, configuration.PostMergeHookType, configuration.PostRewriteHookType, configuration.PrePushHookType, configuration.PreRebaseHookType, configuration.PostCommitHookType, configuration.PrepareCommitHookType:
return configuration.HookType(value), nil
default:
return "", fmt.Errorf("invalid HookType: %s. Accepted values are: %s", value, strings.Join(configuration.ALL_HOOKS_STRING, ", "))
Expand Down
108 changes: 108 additions & 0 deletions packages/configuration/fixtures.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package configuration

import (
"fmt"

"github.com/google/uuid"
)

type StepFixture struct {
id string
name string
onlyOn *string
files []string
}

func (sf *StepFixture) ToStep() *Step {
return &Step{
Name: sf.name,
OnlyOn: sf.onlyOn,
Command: "echo Hello world",
ID: sf.id,
Files: sf.files,
}
}

func (sf *StepFixture) Copy() *StepFixture {
return &StepFixture{
id: uuid.NewString(),
name: sf.name,
onlyOn: sf.onlyOn,
files: append([]string{}, sf.files...),
}
}

func NewStepFixture() *StepFixture {
return &StepFixture{
id: uuid.NewString(),
name: uuid.NewString(),
onlyOn: nil,
files: make([]string, 0),
}
}

func (sf *StepFixture) WithOnlyOn(onlyOn string) *StepFixture {
sf.onlyOn = &onlyOn
return sf
}

func (sf *StepFixture) WithFiles(files ...string) *StepFixture {
sf.files = files
return sf
}

type HookFixture struct {
path string
files []string
steps []*StepFixture
}

func NewHookFixture(path string) *HookFixture {
return &HookFixture{
path: path,
steps: make([]*StepFixture, 0),
files: make([]string, 0),
}
}

func (hf *HookFixture) Copy() *HookFixture {
steps := make([]*StepFixture, 0)
for _, step := range hf.steps {
steps = append(steps, step.Copy())
}

return &HookFixture{
path: hf.path,
steps: steps,
files: append([]string{}, hf.files...),
}
}

func (hf *HookFixture) ToHook() Hook {
hook := Hook{
Path: hf.path,
Steps: []Step{},
Files: hf.files,
}

for i, step := range hf.steps {
hook.Steps = append(hook.Steps, Step{
OnlyOn: step.onlyOn,
Command: "echo Hello world",
ID: fmt.Sprintf("step%d", i),
Files: step.files,
})
}

return hook
}

func (hf *HookFixture) WithFiles(files ...string) *HookFixture {
hf.files = append(hf.files, files...)
return hf
}

func (hf *HookFixture) WithStep(step ...*StepFixture) *HookFixture {
hf.steps = append(hf.steps, step...)
return hf
}
55 changes: 28 additions & 27 deletions packages/configuration/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,42 +12,43 @@ type HookConfiguration struct {
type HookType string

const (
PreCommit HookType = "pre-commit"
PrepareCommit HookType = "prepare-commit-msg"
CommitMsg HookType = "commit-msg"
PostCommit HookType = "post-commit"
PostMerge HookType = "post-merge"
PostRewrite HookType = "post-rewrite"
PreRebase HookType = "pre-rebase"
PostCheckout HookType = "post-checkout"
PrePush HookType = "pre-push"
PreCommitHookType HookType = "pre-commit"
PrepareCommitHookType HookType = "prepare-commit-msg"
CommitMsgHookType HookType = "commit-msg"
PostCommitHookType HookType = "post-commit"
PostMergeHookType HookType = "post-merge"
PostRewriteHookType HookType = "post-rewrite"
PreRebaseHookType HookType = "pre-rebase"
PostCheckoutHookType HookType = "post-checkout"
PrePushHookType HookType = "pre-push"
)

var ALL_HOOKS = []HookType{
PreCommit,
PrepareCommit,
CommitMsg,
PostCommit,
PostMerge,
PostRewrite,
PreRebase,
PostCheckout,
PrePush,
PreCommitHookType,
PrepareCommitHookType,
CommitMsgHookType,
PostCommitHookType,
PostMergeHookType,
PostRewriteHookType,
PreRebaseHookType,
PostCheckoutHookType,
PrePushHookType,
}

var ALL_HOOKS_STRING = []string{
string(PreCommit),
string(PrepareCommit),
string(CommitMsg),
string(PostCommit),
string(PostMerge),
string(PostRewrite),
string(PreRebase),
string(PostCheckout),
string(PrePush),
string(PreCommitHookType),
string(PrepareCommitHookType),
string(CommitMsgHookType),
string(PostCommitHookType),
string(PostMergeHookType),
string(PostRewriteHookType),
string(PreRebaseHookType),
string(PostCheckoutHookType),
string(PrePushHookType),
}

type Hook struct {
Path string
Files []string
Steps []Step
}
2 changes: 2 additions & 0 deletions packages/configuration/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,13 +162,15 @@ func LoadHooksConfiguration(directory string, hookType HookType) ([]Hook, error)
OnlyOn: step.OnlyOn,
From: step.From,
ID: uuid.NewString(),
Files: make([]string, 0),
})
}

}

hooks = append(hooks, Hook{
Path: filepath.Dir(filepath.Dir(path)),
Files: make([]string, 0),
Steps: steps,
})
}
Expand Down
8 changes: 4 additions & 4 deletions packages/configuration/loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestLoadHooksConfiguration(t *testing.T) {
assert.NoError(t, err)

// Call the function
hooks, err := LoadHooksConfiguration(directory, PreCommit)
hooks, err := LoadHooksConfiguration(directory, PreCommitHookType)
assert.NoError(t, err)

assert.Len(t, hooks, 1)
Expand All @@ -62,7 +62,7 @@ func TestLoadNestedHooksConfiguration(t *testing.T) {
assert.NoError(t, err)

// Call the function
hooks, err := LoadHooksConfiguration(directory, PreCommit)
hooks, err := LoadHooksConfiguration(directory, PreCommitHookType)
assert.NoError(t, err)

assert.Len(t, hooks, 1)
Expand All @@ -76,7 +76,7 @@ func TestLoadHooksConfigurationFromEmptyDirectory(t *testing.T) {
directory, err := helpers.SetupTmpGit()
assert.NoError(t, err)

hooks, err := LoadHooksConfiguration(directory, PreCommit)
hooks, err := LoadHooksConfiguration(directory, PreCommitHookType)
assert.NoError(t, err)
assert.Equal(t, []Hook{}, hooks)
}
Expand All @@ -92,7 +92,7 @@ func TestLoadConfiguration(t *testing.T) {
err = helpers.WriteFile(filepath.Join(directory, "hooks"), "pre-commit.json", `{"steps": [{"name": "step1", "command": "echo 'Hello World'"}]}`)
assert.NoError(t, err)

config, err := LoadConfiguration(directory, PreCommit)
config, err := LoadConfiguration(directory, PreCommitHookType)

assert.NoError(t, err)
assert.NotNil(t, config)
Expand Down
1 change: 1 addition & 0 deletions packages/configuration/step.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ type Step struct {
Serial bool
From *string
PackageRelativePath string
Files []string
}
3 changes: 3 additions & 0 deletions packages/executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,9 @@ func (h *HookExecutor) RunStep(step *configuration.Step) {
h.onStepStatusChange(step, StepExecutionStatusRunning)

cmd := strings.ReplaceAll(step.Command, "$1", strings.Join(h.gitCommandArguments, " "))
cmd = strings.ReplaceAll(cmd, "$MATCHED_FILES", strings.Join(step.Files, " "))
cmd = strings.ReplaceAll(cmd, "$PACKAGE_FILES", strings.Join(h.hook.Files, ""))

command := exec.Command("sh", "-c", cmd)
command.Dir = h.hook.Path

Expand Down
Loading

0 comments on commit 24404e9

Please sign in to comment.