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
11 changes: 11 additions & 0 deletions .github/workflows/update-contributors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,18 @@ jobs:
owner: kontrolplane
repository: pull-request-title-validator

- name: check-for-changes
id: check
run: |
if git diff --quiet README.md; then
echo "No changes to commit"
echo "changes=false" >> $GITHUB_OUTPUT
exit 0
fi
echo "changes=true" >> $GITHUB_OUTPUT

- name: open-pull-request
if: steps.check.outputs.changes == 'true'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: validate pull request title
uses: kontrolplane/pull-request-title-validator@v1.3.2
uses: kontrolplane/pull-request-title-validator@v1.4.1
```

### Custom types
Expand All @@ -62,7 +62,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: validate pull request title
uses: kontrolplane/pull-request-title-validator@v1.3.2
uses: kontrolplane/pull-request-title-validator@v1.4.1
with:
types: "fix,feat,chore"
```
Expand Down Expand Up @@ -90,7 +90,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: validate pull request title
uses: kontrolplane/pull-request-title-validator@v1.3.2
uses: kontrolplane/pull-request-title-validator@v1.4.1
with:
scopes: "api,lang,parser,package/.+"
```
Expand Down
57 changes: 39 additions & 18 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func fetchTitle(logger *slog.Logger, githubEventPath string) string {

if eventData, err = os.ReadFile(githubEventPath); err != nil {
logger.Error("Problem reading the event JSON file", slog.String("path", githubEventPath), slog.Any("error", err))
os.Exit(1) // You might want to return an empty string or handle this error upstream instead.
os.Exit(1)
}

if err = json.Unmarshal(eventData, &event); err != nil {
Expand All @@ -100,30 +100,51 @@ func fetchTitle(logger *slog.Logger, githubEventPath string) string {
}

func splitTitle(logger *slog.Logger, title string) (titleType string, titleScope string, titleMessage string) {
if index := strings.Index(title, "("); strings.Contains(title, "(") {
titleType = title[:index]
} else if index := strings.Index(title, ":"); strings.Contains(title, ":") {
titleType = title[:index]
} else {
logger.Error("No type was included in the pull request title.", slog.String("desired format", desiredFormat))
// Split title into prefix (type/scope) and message parts using colon as separator
prefix, message, found := strings.Cut(title, ":")
if !found {
logger.Error("Title must include a message after the colon",
slog.String("desired format", desiredFormat),
slog.String("title", title))
os.Exit(1)
}

if strings.Contains(title, "(") && strings.Contains(title, ")") {
scope := regexp.MustCompile(`\(([^)]+)\)`)
if matches := scope.FindStringSubmatch(title); len(matches) > 1 {
titleScope = matches[1]
}
}
// Clean up the message part
titleMessage = strings.TrimSpace(message)

if strings.Contains(title, ":") {
titleMessage = strings.SplitAfter(title, ":")[1]
titleMessage = strings.TrimSpace(titleMessage)
} else {
logger.Error("No message was included in the pull request title.", slog.String("desired format", desiredFormat))
// Extract type and scope from the prefix
titleType, titleScope = extractTypeAndScope(prefix)

// Validate that we found a type
if titleType == "" {
logger.Error("Title must include a type",
slog.String("desired format", desiredFormat),
slog.String("title", title))
os.Exit(1)
}

return titleType, titleScope, titleMessage
}

func extractTypeAndScope(prefix string) (titleType string, titleScope string) {
prefix = strings.TrimSpace(prefix)

// Check if prefix contains a scope in parentheses
if strings.Contains(prefix, "(") && strings.Contains(prefix, ")") {

// Extract scope using regex
scopeRegex := regexp.MustCompile(`\(([^)]+)\)`)

//
if matches := scopeRegex.FindStringSubmatch(prefix); len(matches) > 1 {
titleScope = matches[1]
titleType = strings.TrimSpace(strings.Split(prefix, "(")[0])
return
}
}

// If no scope found or invalid format, use entire prefix as type
titleType = prefix
return
}

Expand Down