Skip to content

Commit

Permalink
chore(validator): add revert commit validation
Browse files Browse the repository at this point in the history
  • Loading branch information
sebastien-boulle committed Aug 20, 2020
1 parent 98614fa commit e3c42a7
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 18 deletions.
30 changes: 23 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,12 @@ Must be one of the following:
- **refactor**: A code change that neither fixes a bug or adds a feature
- **test**: Adding missing tests or correcting existing tests
- **chore**: Changes to the build process or auxiliary tools and libraries such as distribution generation
- **revert**: Reverts a previous commit

### Scope

The scope could be anything specifying place of the commit change. For example `notification', 'dropdown', etc.
The scope must be written in [kebab-case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).

If the commit reverts a previous commit, it should contains the reverted commit SHA1.

### Subject

A brief but meaningfull description of the change.
Expand All @@ -97,12 +94,9 @@ Here are some recommandation for writing your subject:
- don't capitalize first letter
- no "." (dot) at the end

If the commit reverts a previous commit, it should contains the title of the reverted commit.

### Body

The body should include the motivation for the change and contrast this with previous behavior.
If the commit reverts a previous commit, explain why you reverted it.

### Footer

Expand All @@ -125,6 +119,28 @@ first thing broken
second thing broken
```

### Revert

The proper for revert based on Angular commit message convention should be:

```
revert: feat(toto-service): provide toto for all
This reverts commit <sha1>.
```

However, the default git behavior, that cannot be easily overiden is:

```
Revert "feat(toto-service): provide toto for all"
This reverts commit <sha1>.
```

Thus we won't enforce one or the other, we will only enfore:
* starting the commit title with revert (with a capitalized letter or not)
* having the sentence "This reverts commit <sha1>"

### Built With

- [bash](https://www.gnu.org/software/bash/)
Expand Down Expand Up @@ -198,7 +214,7 @@ See the [open issues](https://github.com/lumapps/commit-msg-validator/issues) fo
- [x] enforce the JIRA reference
- [x] enforce the BROKEN part length
- [x] avoid trailing space
- [ ] allow automated revert commit
- [x] allow automated revert commit
- [ ] allow fixup! and squash! commit with an option

<!-- CONTRIBUTING -->
Expand Down
48 changes: 48 additions & 0 deletions validator.bats
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,16 @@ BROKEN:
[ "$status" -eq $ERROR_HEADER ]
}

@test "header overall should allow 'revert: type(scope): message'" {
validate_header "revert: type(scope): message"
[[ $GLOBAL_TYPE == "revert" ]]
}

@test "header overall should allow 'Revert \#type(scope): message\"'" {
validate_header "Revert \"type(scope): message\""
[[ $GLOBAL_TYPE == "revert" ]]
}

@test "header overall should allow 'type(scope): message'" {
validate_header "type(scope): message"
[[ $GLOBAL_TYPE == "type" ]]
Expand Down Expand Up @@ -425,6 +435,26 @@ LUM-2345'
[[ "$status" -eq 0 ]]
}

@test "revert body without commit sha1 should be refused" {
MESSAGE='rerer
LUM-2345'

run validate_revert "$MESSAGE"
[[ "$status" -eq $ERROR_REVERT ]]
}

@test "revert body with commit sha1 should be valid" {
MESSAGE='rerer
This reverts commit 1234567890.
LUM-2345'

run validate_revert "$MESSAGE"
[[ "$status" -eq 0 ]]
}

@test "features and fixes commits need jira reference" {
[[ `need_jira "feat"` -eq 1 ]]
[[ `need_jira "fix"` -eq 1 ]]
Expand Down Expand Up @@ -578,3 +608,21 @@ BROKEN:
run validate "$MESSAGE"
[[ "$status" -eq 0 ]]
}

@test "overall revert validation" {
MESSAGE='Revert "feat(scope1): subject"
This reverts commit 12345678900.
Commit about stuff\"plop \" dezd
12345678901234567890123456789012345678901234567890
12345678901234567890123456789012345678901234567890
LUM-2345
BROKEN:
- plop
- plop'

run validate "$MESSAGE"
[[ "$status" -eq 0 ]]
}
50 changes: 39 additions & 11 deletions validator.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ if [[ $ZSH_NAME != "" ]]; then
fi

readonly HEADER_PATTERN="^([^\(]+)\(([^\)]+)\): (.+)$"
readonly TYPE_PATTERN="^(feat|fix|docs|refactor|test|chore|revert)$"
readonly TYPE_PATTERN="^(feat|fix|docs|refactor|test|chore)$"
readonly SCOPE_PATTERN="^([a-z][a-z0-9]*)(-[a-z0-9]+)*$"
readonly SUBJECT_PATTERN="^([a-z0-9].*[^ ^\.])$"
readonly JIRA_PATTERN="^([A-Z]{2,4}-[0-9]{1,6} ?)+$"
readonly BROKE_PATTERN="^BROKEN:$"
readonly TRAILING_SPACE_PATTERN=" +$"
readonly REVERT_HEADER_PATTERN="^[R|r]evert[: ].*$"
readonly REVERT_COMMIT_PATTERN="^This reverts commit ([a-f0-9]+)"

readonly ERROR_STRUCTURE=1
readonly ERROR_HEADER=2
Expand All @@ -23,6 +25,7 @@ readonly ERROR_SUBJECT=6
readonly ERROR_BODY_LENGTH=7
readonly ERROR_TRAILING_SPACE=8
readonly ERROR_JIRA=9
readonly ERROR_REVERT=10

GLOBAL_HEADER=""
GLOBAL_BODY=""
Expand Down Expand Up @@ -123,7 +126,9 @@ validate_overall_structure() {
validate_header() {
local HEADER="$1"

if [[ $HEADER =~ $HEADER_PATTERN ]]; then
if [[ $HEADER =~ $REVERT_HEADER_PATTERN ]]; then
GLOBAL_TYPE="revert"
elif [[ $HEADER =~ $HEADER_PATTERN ]]; then
GLOBAL_TYPE=${BASH_REMATCH[1]}
GLOBAL_SCOPE=${BASH_REMATCH[2]}
GLOBAL_SUBJECT=${BASH_REMATCH[3]}
Expand Down Expand Up @@ -223,6 +228,24 @@ validate_jira() {
fi
}

validate_revert() {
local BODY=$1
local LINE=""
local REVERTED_COMMIT=""

while IFS= read -r LINE ;
do
if [[ $LINE =~ $REVERT_COMMIT_PATTERN ]]; then
REVERTED_COMMIT=${BASH_REMATCH[1]}
fi
done <<< "$BODY"

if [[ "$REVERTED_COMMIT" = "" ]]; then
echo -e "revert commit should contain the reverted sha1"
exit $ERROR_REVERT
fi
}

validate() {
local COMMIT_MSG="$1"

Expand All @@ -234,21 +257,26 @@ validate() {
local FOOTER="$GLOBAL_FOOTER"

validate_header "$HEADER"
validate_header_length "$HEADER"

local TYPE="$GLOBAL_TYPE"
local SCOPE="$GLOBAL_SCOPE"
local SUBJECT="$GLOBAL_SUBJECT"

validate_type "$TYPE"
validate_scope "$SCOPE"
validate_subject "$SUBJECT"
if [[ $TYPE = "revert" ]]; then
validate_revert "$BODY"
else
validate_header_length "$HEADER"

validate_type "$TYPE"
validate_scope "$SCOPE"
validate_subject "$SUBJECT"

validate_body_length "$BODY"
validate_body_length "$FOOTER"
validate_body_length "$BODY"
validate_body_length "$FOOTER"

validate_trailing_space "$BODY"
validate_trailing_space "$FOOTER"
validate_trailing_space "$BODY"
validate_trailing_space "$FOOTER"

validate_jira "$TYPE" "$JIRA"
validate_jira "$TYPE" "$JIRA"
fi
}

0 comments on commit e3c42a7

Please sign in to comment.