Skip to content

Improve installation of executable #14

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 44 commits into from
Feb 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
7b79769
Update README
rockstaedt Dec 30, 2022
19b4478
Move files to internal model directory
rockstaedt Jan 24, 2023
0a7ba7c
Update workflow
rockstaedt Jan 24, 2023
9baea04
Init installation script
rockstaedt Jan 25, 2023
11925f4
Rename file to match convention
rockstaedt Jan 26, 2023
e1170cc
Remove error return value
rockstaedt Jan 28, 2023
5e65f5c
Init use of validate subcommand
rockstaedt Jan 28, 2023
a095355
Ignore binary file
rockstaedt Jan 30, 2023
4b9f9e6
Implement happy path for setup
rockstaedt Jan 30, 2023
690a55e
Refactor to use only git path
rockstaedt Jan 31, 2023
c031e10
Create empty commit-msg hook script
rockstaedt Jan 31, 2023
a259a1d
Implement happy path for writeCommitMsgHook
rockstaedt Jan 31, 2023
06e7a8f
Setup commit-msg script
rockstaedt Jan 31, 2023
2611aca
Init setup subcommand
rockstaedt Jan 31, 2023
73a7fb5
Add new line at end of file
rockstaedt Jan 31, 2023
76db6eb
Determine git path in main
rockstaedt Jan 31, 2023
c5d5152
Rename subcommand
rockstaedt Jan 31, 2023
55b1f05
Test error while writing commit-msg
rockstaedt Jan 31, 2023
38c1c63
Define test for error at writing
rockstaedt Jan 31, 2023
47171da
Reset error handling
rockstaedt Feb 1, 2023
bd744df
Handle error at creating script
rockstaedt Feb 1, 2023
a396692
Clean up tests
rockstaedt Feb 1, 2023
914eb7a
Handle error at writing
rockstaedt Feb 1, 2023
0c68539
Improve name of function
rockstaedt Feb 1, 2023
b070232
Write hook also in submodules
rockstaedt Feb 2, 2023
4771cd7
Mark commit-msg as executable
rockstaedt Feb 2, 2023
dcebddf
Refactor tests for better readability
rockstaedt Feb 3, 2023
9a5e0aa
Logs a success message when installed
rockstaedt Feb 3, 2023
1d7078e
Init happy path for uninstall
rockstaedt Feb 3, 2023
7ac0094
Extract walking hooks dir behaviour
rockstaedt Feb 5, 2023
b71a589
Init delete hook function
rockstaedt Feb 5, 2023
5ed8793
Delete commit-msg file
rockstaedt Feb 5, 2023
40b3ec0
Handle error at delete
rockstaedt Feb 5, 2023
f18951e
Let uninstall remove commit-msg
rockstaedt Feb 5, 2023
034ccc4
Log a success message on uninstall
rockstaedt Feb 5, 2023
365c1e4
Return 1 on any error
rockstaedt Feb 5, 2023
81c9e67
Log error at deleting
rockstaedt Feb 5, 2023
db8d2cc
Add subcommand uninstall
rockstaedt Feb 5, 2023
97890cd
Improve log message
rockstaedt Feb 5, 2023
e4264ab
Exclude git check from subcommands
rockstaedt Feb 5, 2023
46cb832
Fix check for git repo
rockstaedt Feb 5, 2023
6908569
Fix relative exe path in submodules
rockstaedt Feb 5, 2023
5bbfdb7
Add documentation for subcommands
rockstaedt Feb 5, 2023
d2830ec
Add tests for printing manual
rockstaedt Feb 12, 2023
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
2 changes: 1 addition & 1 deletion .github/workflows/binaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
fetch-depth: 0
- uses: "WyriHaximus/github-action-get-previous-tag@v1"
id: previoustag
- uses: wangyoucao577/go-release-action@v1.34
- uses: wangyoucao577/go-release-action@v1.35
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
goos: ${{ matrix.goos }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*cover.out
.idea
commit-message-check
19 changes: 6 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,21 @@
[![codecov](https://codecov.io/gh/rockstaedt/commit-message-check/branch/main/graph/badge.svg?token=VW245SMVP5)](https://codecov.io/gh/rockstaedt/commit-message-check)
[![Latest tag](https://img.shields.io/github/v/tag/rockstaedt/commit-message-check)](https://github.com/rockstaedt/commit-message-check/releases)

**Attention: Still under development.**
**Attention: Still under development!**

This is a commit message git hook to ensure that commit messages are not too
long.

## Installation

Execute the command for your platform within the root folder of your git
project. This will download the latest release, puts it in the `./.git/hooks/`
folder and makes it executable. See git documentation about hooks for
Execute the command within the root folder of your git
project. This will download the installation script that determines the OS and
downloads the latest binary. Afterwards, the initialization is started and the
corresponding hook files are prepared. See git documentation about hooks for
further [reference](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks).

### MacOS

```shell
curl -o .git/hooks/commit-msg -L https://github.com/rockstaedt/commit-message-check/releases/download/v0.0.4/commit-message-check-v0.0.4-darwin-arm64 && chmod +x .git/hooks/commit-msg
```

### Linux

```shell
curl -o .git/hooks/commit-msg -L https://github.com/rockstaedt/commit-message-check/releases/download/v0.0.4/commit-message-check-v0.0.4-linux-amd64 && chmod +x .git/hooks/commit-msg
curl -o install.sh -L https://raw.githubusercontent.com/rockstaedt/commit-message-check/main/install.sh && chmod +x ./install.sh && ./install.sh
```

## Usage
Expand Down
17 changes: 17 additions & 0 deletions cmd/setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cmd

import (
"log"
"rockstaedt/commit-message-check/util"
)

func Setup(gitPath string) int {
err := util.WalkHookDirs(gitPath, util.CreateHook)
if err != nil {
log.Println("[ERROR]\t Could not create commit-msg script.")
return 1
}

log.Println("[SUCCESS]\t commit-message-check successfully installed.")
return 0
}
55 changes: 55 additions & 0 deletions cmd/setup_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package cmd

import (
"bytes"
"fmt"
"github.com/stretchr/testify/assert"
"log"
"os"
"testing"
)

func TestSetup(t *testing.T) {
buffer := &bytes.Buffer{}
log.SetOutput(buffer)

t.Run("returns 0 and", func(t *testing.T) {

createDirs := func() string {
path := t.TempDir()
err := os.Mkdir(fmt.Sprintf("%s/hooks", path), os.ModePerm)
assert.Nil(t, err)

return path
}

t.Run("creates commit-msg script in hook folder", func(t *testing.T) {
path := createDirs()

status := Setup(path)

assert.Equal(t, 0, status)
assert.FileExists(t, fmt.Sprintf("%s/hooks/commit-msg", path))
})

t.Run("logs a success message", func(t *testing.T) {
buffer.Reset()
path := createDirs()

_ = Setup(path)

assert.Contains(t, buffer.String(), "[SUCCESS]\t commit-message-check successfully installed.")
})
})

t.Run("returns 1 when error at walking hooks and logs it", func(t *testing.T) {
errPath := t.TempDir()
err := os.Mkdir(fmt.Sprintf("%s/hooks", errPath), 0000)
assert.Nil(t, err)

status := Setup(errPath)

assert.Equal(t, 1, status)
assert.Contains(t, buffer.String(), "[ERROR]\t Could not create commit-msg script.")
})
}
17 changes: 17 additions & 0 deletions cmd/uninstall.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package cmd

import (
"log"
"rockstaedt/commit-message-check/util"
)

func Uninstall(gitPath string) int {
err := util.WalkHookDirs(gitPath, util.DeleteHook)
if err != nil {
log.Println("[ERROR]\t Could not delete commit-msg hook.")
return 1
}

log.Println("[SUCCESS]\t commit-message-check successfully uninstalled.")
return 0
}
63 changes: 63 additions & 0 deletions cmd/uninstall_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package cmd

import (
"bytes"
"fmt"
"github.com/stretchr/testify/assert"
"log"
"os"
"testing"
)

func TestUninstall(t *testing.T) {
buffer := &bytes.Buffer{}
log.SetOutput(buffer)

createDirs := func() string {
path := t.TempDir()
err := os.Mkdir(fmt.Sprintf("%s/hooks", path), os.ModePerm)
assert.Nil(t, err)
_, err = os.Create(fmt.Sprintf("%s/hooks/commit-msg", path))
assert.Nil(t, err)
err = os.Mkdir(fmt.Sprintf("%s/xyz", path), os.ModePerm)
assert.Nil(t, err)
_, err = os.Create(fmt.Sprintf("%s/xyz/commit-msg", path))
assert.Nil(t, err)

return path
}

t.Run("returns 0 and", func(t *testing.T) {

t.Run("removes all occurrences of commit-msg", func(t *testing.T) {
path := createDirs()

status := Uninstall(path)

assert.Equal(t, 0, status)
assert.NoFileExists(t, fmt.Sprintf("%s/hooks/commit-msg", path))
assert.FileExists(t, fmt.Sprintf("%s/xyz/commit-msg", path))
})

t.Run("logs a success message", func(t *testing.T) {
buffer.Reset()
path := createDirs()

_ = Uninstall(path)

assert.Contains(t, buffer.String(), "[SUCCESS]\t commit-message-check successfully uninstalled.")
})
})

t.Run("returns 1 on any error", func(t *testing.T) {
buffer.Reset()
errPath := t.TempDir()
err := os.Mkdir(fmt.Sprintf("%s/hooks", errPath), 0000)
assert.Nil(t, err)

status := Uninstall(errPath)

assert.Equal(t, 1, status)
assert.Contains(t, buffer.String(), "[ERROR]\t Could not delete commit-msg hook.")
})
}
32 changes: 32 additions & 0 deletions cmd/validate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package cmd

import (
"log"
"rockstaedt/commit-message-check/internal/model"
)

const (
softLimit = 50
hardLimit = 72
)

func Validate(commitLines []string) int {
log.Println("[INFO]\t Validate commit message.")

cm := model.CreateCommitMessageFrom(commitLines)

numOfExceedingChars := cm.ValidateSubject()
if numOfExceedingChars == 0 {
log.Println("[SUCCESS]\t Valid commit message.")
return 0
}

if numOfExceedingChars > (hardLimit - softLimit) {
log.Println("[ERROR]\t Abort commit. Subject line too long. Please fix.")
return 1
}

log.Printf("[WARN]\t Your subject exceeds the soft limit of 50 chars by %d chars.", numOfExceedingChars)

return 0
}
44 changes: 44 additions & 0 deletions cmd/validate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package cmd

import (
"bytes"
"github.com/stretchr/testify/assert"
"log"
"testing"
)

func TestValidate(t *testing.T) {
buffer := &bytes.Buffer{}
log.SetOutput(buffer)

t.Run("returns 0 if valid and logs a success", func(t *testing.T) {
buffer.Reset()
commitLines := []string{"i am shorter than 50 characters"}

status := Validate(commitLines)

assert.Equal(t, status, 0)
assert.Contains(t, buffer.String(), "[INFO]\t Validate commit message.")
assert.Contains(t, buffer.String(), "[SUCCESS]\t Valid commit message")
})

t.Run("returns 0 if soft limit exceeds and logs a warning", func(t *testing.T) {
buffer.Reset()
commitLines := []string{"i am two characters more thaaaaaaaaaaaaaaaaaaaaan 50"}

status := Validate(commitLines)

assert.Equal(t, status, 0)
assert.Contains(t, buffer.String(), "[WARN]\t Your subject exceeds the soft limit of 50 chars by 2 chars.")
})

t.Run("returns 1 if length > 70 and logs an error", func(t *testing.T) {
buffer.Reset()
commitLines := []string{"i am way toooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo long"}

status := Validate(commitLines)

assert.Equal(t, status, 1)
assert.Contains(t, buffer.String(), "[ERROR]\t Abort commit. Subject line too long. Please fix.")
})
}
31 changes: 31 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/sh

version=$(curl --silent "https://api.github.com/repos/rockstaedt/commit-message-check/releases/latest" |
grep '"tag_name":' |
sed -E 's/.*"([^"]+)".*/\1/')

echo "-> Installing commit-message-check ${version}"

if [[ "$OSTYPE" == "linux-gnu"* ]]; then
os="linux"
elif [[ "$OSTYPE" == "darwin"* ]]; then
os="darwin"
else
echo "ERROR - Could not determine operating system. Please download binary manually."
exit
fi

os="${os}-$(uname -m)"
binary="commit-message-check-${version}-${os}"
url="https://github.com/rockstaedt/commit-message-check/releases/latest/download/${binary}"

curl -o commit-message-check -L $url && chmod +x ./commit-message-check

if !(grep -Fxq "commit-message-check" .gitignore); then
read -e -p "Do you want to add the binary to gitignore? (y/n) " choice
[[ "$choice" == [Yy]* ]] && echo 'commit-message-check'>>.gitignore
fi

./commit-message-check setup

rm ./install.sh
6 changes: 3 additions & 3 deletions src/commit-message.go → internal/model/commit_message.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package src
package model

import (
"regexp"
Expand All @@ -10,12 +10,12 @@ type CommitMessage struct {
InvalidBody bool
}

func CreateCommitMessageFrom(messageLines []string) (*CommitMessage, error) {
func CreateCommitMessageFrom(messageLines []string) *CommitMessage {
cm := &CommitMessage{InvalidBody: false}
cm.addSubject(messageLines)
cm.addBody(messageLines)

return cm, nil
return cm
}

func (cm *CommitMessage) ValidateSubject() int {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package src
package model

import (
"github.com/stretchr/testify/assert"
Expand All @@ -17,8 +17,7 @@ func TestNewCommitMessage(t *testing.T) {
}

t.Run("create new commit message object from File", func(t *testing.T) {
cm, err := CreateCommitMessageFrom(validCommitMsgLines)
assert.Nil(t, err)
cm := CreateCommitMessageFrom(validCommitMsgLines)

assert.Equal(t, "I am a valid Subject with less than 50 characters", cm.Subject)
assert.Len(t, cm.Body, 3)
Expand All @@ -27,8 +26,7 @@ func TestNewCommitMessage(t *testing.T) {

t.Run("Handles empty commit message", func(t *testing.T) {
var emptyCommitMsgLines []string
cm, err := CreateCommitMessageFrom(emptyCommitMsgLines)
assert.Nil(t, err)
cm := CreateCommitMessageFrom(emptyCommitMsgLines)

assert.Equal(t, "", cm.Subject)
assert.Len(t, cm.Body, 0)
Expand All @@ -40,8 +38,7 @@ func TestNewCommitMessage(t *testing.T) {
"body line 1",
"body line 2",
}
cm, err := CreateCommitMessageFrom(invalidCommitMsgLines)
assert.Nil(t, err)
cm := CreateCommitMessageFrom(invalidCommitMsgLines)

t.Run("sets body correct", func(t *testing.T) {
assert.Equal(t, "subject line", cm.Subject)
Expand Down Expand Up @@ -71,7 +68,7 @@ func TestNewCommitMessage(t *testing.T) {

for _, tc := range testcases {
t.Run(getDescFrom(tc.subject), func(t *testing.T) {
cm, _ := CreateCommitMessageFrom([]string{tc.subject})
cm := CreateCommitMessageFrom([]string{tc.subject})

aboveSoftLimit := cm.ValidateSubject()

Expand Down
Loading