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
17 changes: 11 additions & 6 deletions testutil/verifypr/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@ import (

var titlePrefix = regexp.MustCompile(`^[*\w]+(/[*\w]+)?$`)

type PRUser struct {
Login string `json:"login"`
}

type PR struct {
Title string `json:"title"`
Body string `json:"body"`
ID string `json:"node_id"`
Title string `json:"title"`
Body string `json:"body"`
ID string `json:"node_id"`
Creator PRUser `json:"user"`
}

// PRFromEnv returns the PR by parsing it from "GITHUB_PR" env var or an error.
Expand All @@ -42,7 +47,7 @@ func PRFromEnv() (PR, error) {
return PR{}, errors.Wrap(err, "unmarshal PR body")
}

if pr.Title == "" || pr.Body == "" || pr.ID == "" {
if pr.Title == "" || pr.Body == "" || pr.ID == "" || pr.Creator.Login == "" {
return PR{}, errors.New("pr field not set")
}

Expand All @@ -61,12 +66,12 @@ func verify() error {
}

// Skip dependabot PRs.
if strings.Contains(pr.Title, "build(deps)") && strings.Contains(pr.Body, "dependabot") {
if strings.Contains(pr.Title, "build(deps)") && pr.Creator.Login == "dependabot[bot]" {
return nil
}

// Skip Renovate PRs.
if strings.Contains(pr.Title, "chore(deps)") && strings.Contains(pr.Body, "Renovate") {
if strings.Contains(pr.Title, "chore(deps)") && pr.Creator.Login == "renovate[bot]" {
return nil
}

Expand Down
92 changes: 92 additions & 0 deletions testutil/verifypr/verify_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package main

import (
"encoding/json"
"strconv"
"strings"
"testing"
Expand Down Expand Up @@ -180,3 +181,94 @@ func TestBody(t *testing.T) {
})
}
}

func TestVerifyBotSkip(t *testing.T) {
tests := []struct {
Name string
PR PR
Skipped bool // true means verify() should return nil without format checks
}{
{
Name: "dependabot skipped",
PR: PR{
Title: "build(deps): bump some-lib from 1.0 to 2.0",
Body: "Bumps some-lib.",
ID: "node_1",
Creator: PRUser{Login: "dependabot[bot]"},
},
Skipped: true,
},
{
Name: "renovate skipped",
PR: PR{
Title: "chore(deps): update some-lib to v2",
Body: "This PR contains the following updates.",
ID: "node_2",
Creator: PRUser{Login: "renovate[bot]"},
},
Skipped: true,
},
{
Name: "dependabot title but wrong creator not skipped",
PR: PR{
Title: "build(deps): bump some-lib from 1.0 to 2.0",
Body: "Bumps some-lib.",
ID: "node_3",
Creator: PRUser{Login: "someuser"},
},
Skipped: false,
},
{
Name: "renovate title but wrong creator not skipped",
PR: PR{
Title: "chore(deps): update some-lib to v2",
Body: "This PR contains the following updates.",
ID: "node_4",
Creator: PRUser{Login: "someuser"},
},
Skipped: false,
},
{
Name: "dependabot creator but wrong title not skipped",
PR: PR{
Title: "chore(deps): bump some-lib from 1.0 to 2.0",
Body: "Bumps some-lib.",
ID: "node_5",
Creator: PRUser{Login: "dependabot[bot]"},
},
Skipped: false,
},
{
Name: "renovate creator but wrong title not skipped",
PR: PR{
Title: "build(deps): update some-lib to v2",
Body: "This PR contains the following updates.",
ID: "node_6",
Creator: PRUser{Login: "renovate[bot]"},
},
Skipped: false,
},
}
for _, test := range tests {
t.Run(test.Name, func(t *testing.T) {
b, err := json.Marshal(test.PR)
if err != nil {
t.Fatalf("marshal PR: %v", err)
}

t.Setenv("GITHUB_PR", string(b))

err = verify()
if test.Skipped {
if err != nil {
t.Fatalf("expected bot PR to be skipped (nil error), got: %v", err)
}
} else {
// Non-bot PRs will fail title/body format checks — that's expected.
if err == nil {
t.Fatalf("expected non-bot PR to fail format checks, got nil error")
}
}
})
}
}
Loading