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
22 changes: 22 additions & 0 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: All Tests

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
run-tests:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.22'

- name: Test
run: make test
File renamed without changes.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ run:
# Run the tests
.PHONY: test
test:
@go test -v ./tests/
@go test -v ./...

%:
@:
57 changes: 12 additions & 45 deletions cmd/commit/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import (
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"time"

"github.com/artem-y/commit/internal/config"
"github.com/artem-y/commit/internal/helpers"
"github.com/artem-y/commit/internal/message_generator"
"github.com/artem-y/commit/internal/user"

"github.com/go-git/go-git/v5"
Expand Down Expand Up @@ -53,13 +52,19 @@ func main() {
// Read branch name or HEAD
if headRef.Name().IsBranch() {

cfg := config.ReadCommitConfig(configFilePath)
branchName := headRef.Name().Short()
matches := findIssueMatchesInBranch(cfg.IssueRegex, branchName)
fileReader := config.FileReader{}
cfg, err := config.ReadCommitConfig(fileReader, configFilePath)
if err != nil {
fmt.Fprintf(os.Stderr, helpers.Red("Failed to read config: %v\n"), err)
os.Exit(1)
}

if len(matches) > 0 {
commitMessage = generateCommitMessageWithMatches(matches, cfg, commitMessage)
messageGenerator := message_generator.MessageGenerator{
BranchName: headRef.Name().Short(),
UserMessage: commitMessage,
Config: cfg,
}
commitMessage = messageGenerator.GenerateMessage()

if !dryRun {
commitChanges(repo, worktree, commitMessage)
Expand Down Expand Up @@ -119,44 +124,6 @@ func openWorktree(repo *git.Repository) *git.Worktree {
return worktree
}

// Searches the branch name for issue numbers matching the given regex
func findIssueMatchesInBranch(rgxRaw string, branchName string) []string {
rgx := regexp.MustCompile(rgxRaw)

allSubmatches := rgx.FindAllStringSubmatch(branchName, -1)

matches := []string{}
for _, submatches := range allSubmatches {
matches = append(matches, submatches[0])
}

return matches
}

// Generates a commit message with the issue number matches and config settings
func generateCommitMessageWithMatches(matches []string, cfg config.CommitConfig, commitMessage string) string {
mappedMatches := make([]string, len(matches))

for index, match := range matches {
wrappedIssueNumber := fmt.Sprintf(
"%s%s%s",
*cfg.OutputIssuePrefix,
match,
*cfg.OutputIssueSuffix,
)
mappedMatches[index] = wrappedIssueNumber
}

joinedIssues := strings.Join(mappedMatches, ", ")
return fmt.Sprintf(
"%s%s%s%s",
*cfg.OutputStringPrefix,
joinedIssues,
*cfg.OutputStringSuffix,
commitMessage,
)
}

// Creates commit options with the author information
func makeCommitOptions(usr user.User) git.CommitOptions {
return git.CommitOptions{
Expand Down
6 changes: 3 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ If the branch has multiple issues in its name, the tool will include them all, c
For example, the branch named `add-tests-for-CR-127-and-CR-131-features`, the issue regex set to `[A-Z]{2}-[0-9]+`, and the "outputIssuePrefix" and "outputIssueSuffix" settings for the output set to `[` and `]:`, the generated commit message would start with the following:
> [CR-127, CR-131]:
## Testing
So far I haven't added a lot of unit tests for this project, but I will be doing it in the future.
To run the tests, use the `make test` or `go test -v ./tests` commands.
So far only the core parts of the logic are covered with tests, but I will be adding more in the future.
To run the tests, use the `make test` or `go test -v ./...` commands.
### Debug
To check what commit message will be generated without making the actual commit, there is a `-dry-run` flag that can be passed to the command:
```shell
Expand All @@ -87,5 +87,5 @@ Originally I wrote this tool for myself in shell and Swift and used a lot on Mac
If you find it useful and see that something's wrong or missing, feel free to raise issues and contribute to the project.
When doing so, please follow the ususal code of conduct and contribution guidelines from GitHub, and just common sense.
## License
This repository is distributed under the MIT license (see [LICENSE.md](/docs/LICENSE)).
This repository is distributed under the MIT license (see [LICENSE](/LICENSE)).
My tool uses [go-git](https://github.com/go-git/go-git) as a 3rd party dependency to work with git directly, you might want to check it out too.
76 changes: 49 additions & 27 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,63 +2,85 @@ package config

import (
"encoding/json"
"fmt"
"os"

"github.com/artem-y/commit/internal/helpers"
)

// Representation of settings that can be set from the config file
type CommitConfig struct {
IssueRegex string `json:"issueRegex"`
IssueRegex string // Regex for issue numbers in branch name
OutputIssuePrefix string // Prefix before each issue number in the commit message
OutputIssueSuffix string // Suffix after each issue number in the commit message
OutputStringPrefix string // Prefix before the list of issues in the commit message
OutputStringSuffix string // Suffix after the list of issues and before the user's message
}

// DTO for unmarshalling JSON config and safe-guarding against nil values
type commitConfigDTO struct {
IssueRegex *string `json:"issueRegex"`
OutputIssuePrefix *string `json:"outputIssuePrefix"`
OutputIssueSuffix *string `json:"outputIssueSuffix"`
OutputStringPrefix *string `json:"outputStringPrefix"`
OutputStringSuffix *string `json:"outputStringSuffix"`
}

// Reads config at the file path and unmarshals it into commitConfig struct
func ReadCommitConfig(configFilePath string) CommitConfig {

var cfg CommitConfig
func ReadCommitConfig(fileReader FileReading, configFilePath string) (CommitConfig, error) {
var cfgDto commitConfigDTO

_, err := os.Stat(configFilePath)
_, err := fileReader.Stat(configFilePath)
if err == nil {

file, err := os.ReadFile(configFilePath)
file, err := fileReader.ReadFile(configFilePath)
if err != nil {
fmt.Fprintf(os.Stderr, helpers.Red("Error reading %s file: %v\n"), err, configFilePath)
os.Exit(1)
return CommitConfig{}, err
}

err = json.Unmarshal(file, &cfg)
err = json.Unmarshal(file, &cfgDto)
if err != nil {
fmt.Fprintf(os.Stderr, helpers.Red("Error unmarshalling %s file: %v\n"), err, configFilePath)
os.Exit(1)
return CommitConfig{}, err
}
}

if cfg.IssueRegex == "" {
cfg.IssueRegex = helpers.DEFAULT_ISSUE_REGEX
cfg := makeConfig(cfgDto)

return cfg, nil
}

// Helper function to create a default config
func MakeDefaultConfig() CommitConfig {
return CommitConfig{
IssueRegex: helpers.DEFAULT_ISSUE_REGEX,
OutputIssuePrefix: helpers.DEFAULT_OUTPUT_ISSUE_PREFIX,
OutputIssueSuffix: helpers.DEFAULT_OUTPUT_ISSUE_SUFFIX,
OutputStringPrefix: helpers.DEFAULT_OUTPUT_STRING_PREFIX,
OutputStringSuffix: helpers.DEFAULT_OUTPUT_STRING_SUFFIX,
}
}

// MARK: - Private

func makeConfig(cfgDto commitConfigDTO) CommitConfig {
cfg := MakeDefaultConfig()

if cfgDto.IssueRegex != nil {
cfg.IssueRegex = *cfgDto.IssueRegex
}

if cfg.OutputIssuePrefix == nil {
defaultIssuePrefix := helpers.DEFAULT_OUTPUT_ISSUE_PREFIX
cfg.OutputIssuePrefix = &defaultIssuePrefix
if cfgDto.OutputIssuePrefix != nil {
cfg.OutputIssuePrefix = *cfgDto.OutputIssuePrefix
}

if cfg.OutputIssueSuffix == nil {
defaultIssueSuffix := helpers.DEFAULT_OUTPUT_ISSUE_SUFFIX
cfg.OutputIssueSuffix = &defaultIssueSuffix
if cfgDto.OutputIssueSuffix != nil {
cfg.OutputIssueSuffix = *cfgDto.OutputIssueSuffix
}

if cfg.OutputStringPrefix == nil {
defaultStringPrefix := helpers.DEFAULT_OUTPUT_STRING_PREFIX
cfg.OutputStringPrefix = &defaultStringPrefix
if cfgDto.OutputStringPrefix != nil {
cfg.OutputStringPrefix = *cfgDto.OutputStringPrefix
}

if cfg.OutputStringSuffix == nil {
defaultStringSuffix := helpers.DEFAULT_OUTPUT_STRING_SUFFIX
cfg.OutputStringSuffix = &defaultStringSuffix
if cfgDto.OutputStringSuffix != nil {
cfg.OutputStringSuffix = *cfgDto.OutputStringSuffix
}

return cfg
Expand Down
Loading