diff --git a/README.md b/README.md index a198e3f..7c7a6db 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,41 @@ # pull-request-lint -Lints the title of a pull request \ No newline at end of file +A GitHub/Gitea Action that lints pull request titles to ensure they follow the [Conventional Commits](https://www.conventionalcommits.org/) format. + +## Usage + +Add the following to your GitHub/Gitea workflow: + +```yaml +name: Pull Request Lint + +on: + pull_request: + types: [opened, edited, reopened, synchronize] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install go + uses: actions/setup-go@v5 + with: + go-version: 1.24.2 + - uses: https://git.kjan.de/actions/pull-request-lint@release +``` + +## Validation Rules + +The action enforces the following Conventional Commits rules for PR titles: + +- Format must be: `type(scope)!: description` (scope and breaking change marker `!` are optional) +- Type and scope must be lowercase +- Description must start with lowercase +- Breaking change indicator and footer are mutually exclusive +- Body must be separated from description by a blank line +- Footer tokens must use hyphens instead of spaces (except for "BREAKING CHANGE") + +## License + +See [LICENSE](LICENSE) file for details. diff --git a/internal/validation/validation.go b/internal/validation/validation.go index 4d48e4a..8c3123e 100644 --- a/internal/validation/validation.go +++ b/internal/validation/validation.go @@ -13,33 +13,26 @@ func ValidateConventionalCommit(commit string) error { // type!: description // or // type: description - re := regexp.MustCompile(`^(?P[a-z]+)(?P\([a-z]+\))?(?P!)?: (?P[a-z].+)$`) + re := regexp.MustCompile(`^(?P[a-z]+)(?P\([a-z]+\))?(?P!)?: (?P.+)$`) match := re.FindStringSubmatch(commit) if len(match) == 0 { - return fmt.Errorf("Invalid PR title") + return fmt.Errorf("invalid commit format") } typeIndex := re.SubexpIndex("type") scopeIndex := re.SubexpIndex("scope") breakingIndex := re.SubexpIndex("breaking") - descriptionIndex := re.SubexpIndex("description") commitType := match[typeIndex] scope := match[scopeIndex] breaking := match[breakingIndex] - description := match[descriptionIndex] // Type MUST be lowercase if commitType != strings.ToLower(commitType) { return fmt.Errorf("type must be lowercase") } - // Description MUST start with lowercase - if description != strings.ToLower(description) { - return fmt.Errorf("description must start with lowercase") - } - // Scope MUST be lowercase if scope != "" && scope != strings.ToLower(scope) { return fmt.Errorf("scope must be lowercase") diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..c183f9d --- /dev/null +++ b/renovate.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "local>Renovate/renovate-config" + ] +}