Skip to content

Commit

Permalink
Add flag for allowing one-liners (#56)
Browse files Browse the repository at this point in the history
This patch adds a flag so that users can allow one-liner commit
messages. Previously, the header/body split was enforced.
  • Loading branch information
mristin committed Jul 31, 2020
1 parent c557549 commit 4f73f98
Show file tree
Hide file tree
Showing 13 changed files with 375 additions and 78 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,11 @@ jobs:
with:
additional-verbs: 'chrusimusi, unit-test'
path-to-additional-verbs: src/additional-verbs.txt

test-allow-one-liners:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: ./
with:
allow-one-liners: 'true'
24 changes: 20 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check
uses: mristin/opinionated-commit-message@v2.0.0-pre1
uses: mristin/opinionated-commit-message@v2
```

## Checked Events
Expand Down Expand Up @@ -99,7 +99,7 @@ string in the workflow file. For example:
```yaml
steps:
- name: Check
uses: mristin/opinionated-commit-message@v2.0.0-pre1
uses: mristin/opinionated-commit-message@v2
with:
additional-verbs: 'chrusimusi, unit-test'
```
Expand All @@ -111,14 +111,30 @@ as input:
```yaml
steps:
- name: Check
uses: mristin/opinionated-commit-message@v2.0.0-pre1
uses: mristin/opinionated-commit-message@v2
with:
path-to-additional-verbs: 'src/additional-verbs.txt'
```

## One-liners

Usually, you need to write elaborate commit messages with a shorter header
and more verbose body for an informative Git history. However, this might be
too rigid for certain projects.

You can allow one-liner commit messages by setting the flag `allow-one-liners`:

```yaml
steps:
- name: Check
uses: mristin/opinionated-commit-message@v2
with:
allow-one-liners: 'true'
```

## Local Usage

We translated the opinionanted-commit-message to a powershell script so that
We translated the opinionated-commit-message to a powershell script so that
you can include it in your local pre-commit and pre-push checks.

The script is available at: [`local/powershell/OpinionatedCommitMessage.ps1`](
Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@ inputs:
description: 'Path to the file containing the additional verbs in imperative mood to be accepted in checks'
required: false
default: ''
allow-one-liners:
description: 'If set to "true", allows one-liner commit messages without body'
required: false
default: ''
69 changes: 56 additions & 13 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -560,11 +560,16 @@ function splitLines(message) {
}
function splitSubjectBody(lines) {
const result = { errors: [] };
if (lines.length < 3) {
result.errors.push(`Expected at least three lines (subject, empty, body), ` +
if (lines.length === 0 || lines.length === 1) {
result.errors.push('Expected at least three lines (subject, empty, body), ' +
`but got: ${lines.length}`);
return result;
}
else if (lines.length === 2) {
result.errors.push('Expected at least three lines (subject, empty, body) ' +
`in a multi-line message, but got: ${lines.length}`);
return result;
}
if (lines[1].length !== 0) {
result.errors.push(`Expected an empty line between the subject and the body, ` +
`but got a second line of length: ${lines[1].length}`);
Expand Down Expand Up @@ -633,6 +638,11 @@ function checkBody(subject, bodyLines) {
const errors = [];
if (bodyLines.length === 0) {
errors.push('At least one line is expected in the body, but got empty body.');
return errors;
}
if (bodyLines.length === 1 && bodyLines[0].trim() === '') {
errors.push('Unexpected empty body');
return errors;
}
for (const [i, line] of bodyLines.entries()) {
if (line.length > 72) {
Expand Down Expand Up @@ -662,23 +672,32 @@ function checkBody(subject, bodyLines) {
}
const mergeMessageRe = new RegExp("^Merge branch '[^\\000-\\037\\177 ~^:?*[]+' " +
'into [^\\000-\\037\\177 ~^:?*[]+$');
function check(message, additionalVerbs) {
function check(message, additionalVerbs, allowOneLiners) {
const errors = [];
if (mergeMessageRe.test(message)) {
return errors;
}
const lines = splitLines(message);
const maybeSubjectBody = splitSubjectBody(lines);
if (maybeSubjectBody.errors.length > 0) {
errors.push(...maybeSubjectBody.errors);
if (lines.length === 0) {
errors.push(`The message is empty.`);
return errors;
}
else if (lines.length === 1 && allowOneLiners) {
errors.push(...checkSubject(lines[0], additionalVerbs));
}
else {
if (maybeSubjectBody.subjectBody === undefined) {
throw Error('Unexpected undefined subjectBody');
const maybeSubjectBody = splitSubjectBody(lines);
if (maybeSubjectBody.errors.length > 0) {
errors.push(...maybeSubjectBody.errors);
}
else {
if (maybeSubjectBody.subjectBody === undefined) {
throw Error('Unexpected undefined subjectBody');
}
const subjectBody = maybeSubjectBody.subjectBody;
errors.push(...checkSubject(subjectBody.subject, additionalVerbs));
errors.push(...checkBody(subjectBody.subject, subjectBody.bodyLines));
}
const subjectBody = maybeSubjectBody.subjectBody;
errors.push(...checkSubject(subjectBody.subject, additionalVerbs));
errors.push(...checkBody(subjectBody.subject, subjectBody.bodyLines));
}
// Post-condition
for (const error of errors) {
Expand Down Expand Up @@ -4523,10 +4542,24 @@ function runWithExceptions() {
additionalVerbs.add(verb);
}
}
// Parse allow-one-liners input
const allowOneLinersText = core.getInput('allow-one-liners', {
required: false
});
const allowOneLiners = !allowOneLinersText
? false
: input.parseAllowOneLiners(allowOneLinersText);
if (allowOneLiners === null) {
const error = 'Unexpected value for allow-one-liners. ' +
`Expected either 'true' or 'false', got: ${allowOneLinersText}`;
core.error(error);
core.setFailed(error);
return;
}
// Parts of the error message to be concatenated with '\n'
const parts = [];
for (const [messageIndex, message] of messages.entries()) {
const errors = inspection.check(message, additionalVerbs);
const errors = inspection.check(message, additionalVerbs, allowOneLiners);
if (errors.length > 0) {
const repr = represent.formatErrors(message, messageIndex, errors);
parts.push(repr);
Expand Down Expand Up @@ -9287,7 +9320,7 @@ function getNextPage (octokit, link, headers) {
"use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.parseVerbs = void 0;
exports.parseAllowOneLiners = exports.parseVerbs = void 0;
function parseVerbs(text) {
const lines = text.split('\n');
const verbs = [];
Expand All @@ -9301,6 +9334,16 @@ function parseVerbs(text) {
return verbs;
}
exports.parseVerbs = parseVerbs;
function parseAllowOneLiners(text) {
if (text === '' || text.toLowerCase() === 'false' || text === '0') {
return false;
}
if (text.toLowerCase() === 'true' || text === '1') {
return true;
}
return null;
}
exports.parseAllowOneLiners = parseAllowOneLiners;


/***/ }),
Expand Down
54 changes: 53 additions & 1 deletion local/powershell/OpinionatedCommitMessage.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ function TestOKMergeBranch

if ($got -ne $expected)
{
Write-Host "TestOKMergeBranch: OK"
Write-Host "TestOKMergeBranch: FAILED"
WriteExpectedGot -expected $expected -got $got
return $false
}
Expand Down Expand Up @@ -245,6 +245,54 @@ function TestOKPathToAdditionalVerbs
}
}

function TestOKWithAllowOneLiners
{
$message = "Do something"
$got = (powershell `
-File OpinionatedCommitMessage.ps1 `
-message $message `
-allowOneLiners `
-dontThrow
)|Out-String

$nl = [Environment]::NewLine
$expected = "The message is OK.${nl}"

if ($got -ne $expected)
{
Write-Host "TestOKWithAllowOneLiners: FAILED"
WriteExpectedGot -expected $expected -got $got
return $false
}

Write-Host "TestOKWithAllowOneLiners: OK"
return $true
}

function TestFailWithAllowOneLiners
{
$message = "Do something."
$got = (powershell `
-File OpinionatedCommitMessage.ps1 `
-message $message `
-allowOneLiners `
-dontThrow
)|Out-String

$nl = [Environment]::NewLine
$expected = "* The subject must not end with a dot ('.').${nl}"

if ($got -ne $expected)
{
Write-Host "TestFailWithAllowOneLiners: FAILED"
WriteExpectedGot -expected $expected -got $got
return $false
}

Write-Host "TestFailWithAllowOneLiners: OK"
return $true
}

function Main
{
Push-Location
Expand All @@ -263,6 +311,10 @@ function Main
$success = TestOKCarriageReturn -and $success
$success = TestOKAdditionalVerbs -and $success
$success = TestOKPathToAdditionalVerbs -and $success
$success = TestOKWithAllowOneLiners -and $success
$success = TestFailWithAllowOneLiners -and $success

# TODO: TestFailAllowOneLiners

if(!$success)
{
Expand Down
62 changes: 47 additions & 15 deletions local/powershell/OpinionatedCommitMessage.ps1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env pwsh
# This file was generated by src/scripts/toPowershell.ts. Do NOT edit or append!
# Version: 2.0.0
# Version: 2.0.0-post1
# Copyright (c) 2020 Marko Ristin <https://github.com/mristin/opinionated-commit-message>
# MIT License

Expand All @@ -17,6 +17,10 @@ param(
[string]
$pathToAdditionalVerbs = $null,

[Parameter(HelpMessage = "If set, one-liner commit messages are allowed")]
[switch]
$allowOneLiners = $false,

[Parameter(HelpMessage = "If set, the script does not throw an exception on failed checks")]
[switch]
$dontThrow = $false
Expand Down Expand Up @@ -870,6 +874,12 @@ function CheckBody([string]$subject, [string[]] $bodyLines)
return $errors
}

if (($bodyLines.Length -eq 1) -and ($bodyLines[0].Trim -eq ""))
{
$errors += "Unexpected empty body"
return $errors
}

for($i = 0; $i -lt $bodyLines.Count; $i++)
{
$line = $bodyLines[$i]
Expand Down Expand Up @@ -912,31 +922,53 @@ function Check([string]$text, [hashtable]$verbs)
}

$lines = $text -Split "`n"

if ($lines.Count -lt 3)
{
$errors += "Expected at least three lines (subject, empty, body), but got: $( $lines.Count )"
return $errors
}

$trimmedLines = @()
foreach ($line in $lines)
{
$trimmedLines += $line -Replace '\r$'
}

if ($trimmedLines[1] -ne "")
if ($trimmedLines.Count -eq 0)
{
$errors += "Expected an empty line between the subject and the body, " + `
"but got a line: $( $trimmedLines[1]|ConvertTo-Json )"
errors += "The message is empty."
return $errors
}
elseif (($trimmedLines.Length -eq 1) -and $allowOneLiners)
{
$subject = $trimmedLines[0]
$errors = $errors + ( CheckSubject -subject $subject -verbs $verbs )
}
else
{
if (($trimmedLines.Length -eq 0) -or ($trimmedLines.Length -eq 1))
{
$errors += "Expected at least three lines (subject, empty, body), but got: $( $lines.Count )"
return $errors
}
elseif ($trimmedLines.Length -eq 2)
{
$errors += (
"Expected at least three lines (subject, empty, body) in a multi-line message, " +
"but got: $( $lines.Count )"
)
return $errors
}
else
{
if ($trimmedLines[1] -ne "")
{
$errors += "Expected an empty line between the subject and the body, " + `
"but got a line: $( $trimmedLines[1]|ConvertTo-Json )"
return $errors
}

$subject = $trimmedLines[0]
$errors = $errors + ( CheckSubject -subject $subject -verbs $verbs )
$subject = $trimmedLines[0]
$errors = $errors + ( CheckSubject -subject $subject -verbs $verbs )

$bodyLines = $trimmedLines |Select-Object -Skip 2
$errors = $errors + ( CheckBody -subject $subject -bodyLines $bodyLines)
$bodyLines = $trimmedLines |Select-Object -Skip 2
$errors = $errors + ( CheckBody -subject $subject -bodyLines $bodyLines)
}
}

return $errors
}
Expand Down
Loading

0 comments on commit 4f73f98

Please sign in to comment.