Skip to content

Commit

Permalink
Merge pull request #486 from cloudflare/gh
Browse files Browse the repository at this point in the history
Use checks run API for github integration
  • Loading branch information
prymitive authored Dec 19, 2022
2 parents e146b38 + a1e0c74 commit 54c944c
Show file tree
Hide file tree
Showing 14 changed files with 101 additions and 75 deletions.
3 changes: 3 additions & 0 deletions .github/pint/pint.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ci {
include = [".github/pint/rules/.*"]
}
6 changes: 6 additions & 0 deletions .github/pint/rules/1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
groups:
- name: test
rules:
- alert: Service Is Down
expr: up == 0
for: 0m
36 changes: 36 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: pint ci

on:
pull_request:
branches:
- main

jobs:
golangci-lint:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Fetch main branch
run: |
git fetch origin main
git checkout main
git fetch origin $GITHUB_HEAD_REF
git checkout $GITHUB_HEAD_REF
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.19.4
cache: true

- name: Compile pint
run: make build

- name: Run pint ci
run: ./pint -c .github/pint/pint.hcl ci
env:
GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23 changes: 2 additions & 21 deletions cmd/pint/ci.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"os"
"regexp"
"strconv"
"strings"
"time"

Expand Down Expand Up @@ -115,16 +114,6 @@ func actionCI(c *cli.Context) error {
return fmt.Errorf("GITHUB_AUTH_TOKEN env variable is required when reporting to GitHub")
}

prVal, ok := os.LookupEnv("GITHUB_PULL_REQUEST_NUMBER")
if !ok {
return fmt.Errorf("GITHUB_PULL_REQUEST_NUMBER env variable is required when reporting to GitHub")
}

prNum, err := strconv.Atoi(prVal)
if err != nil {
return fmt.Errorf("got not a valid number via GITHUB_PULL_REQUEST_NUMBER: %w", err)
}

timeout, _ := time.ParseDuration(meta.cfg.Repository.GitHub.Timeout)
gr := reporter.NewGithubReporter(
meta.cfg.Repository.GitHub.BaseURI,
Expand All @@ -133,7 +122,6 @@ func actionCI(c *cli.Context) error {
token,
meta.cfg.Repository.GitHub.Owner,
meta.cfg.Repository.GitHub.Repo,
prNum,
git.RunGit,
)
reps = append(reps, gr)
Expand Down Expand Up @@ -173,6 +161,7 @@ func detectCI(cfg *config.CI) *config.CI {
if bb := os.Getenv("GITHUB_BASE_REF"); bb != "" {
isDirty = true
cfg.BaseBranch = bb
log.Debug().Str("branch", bb).Msg("got base branch from GITHUB_BASE_REF env variable")
}

if isNil && !isDirty {
Expand Down Expand Up @@ -201,15 +190,7 @@ func detectRepository(cfg *config.Repository) *config.Repository {
}

func detectGithubActions(gh *config.GitHub) *config.GitHub {
if os.Getenv("GITHUB_PULL_REQUEST_NUMBER") == "" &&
os.Getenv("GITHUB_EVENT_NAME") == "pull_request" &&
os.Getenv("GITHUB_REF") != "" {
parts := strings.Split(os.Getenv("GITHUB_REF"), "/")
if len(parts) >= 4 {
log.Info().Str("pr", parts[2]).Msg("Setting GITHUB_PULL_REQUEST_NUMBER from GITHUB_REF env variable")
os.Setenv("GITHUB_PULL_REQUEST_NUMBER", parts[2])
}
}
log.Debug().Msg("GitHub actions environment detected")

var isDirty, isNil bool

Expand Down
1 change: 0 additions & 1 deletion cmd/pint/tests/0032_ci_github.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ cp ../src/v2.yml rules.yml
exec git commit -am 'v2'

env GITHUB_AUTH_TOKEN=12345
env GITHUB_PULL_REQUEST_NUMBER=1
pint.ok -l debug --offline --no-color ci
! stdout .
stderr 'level=info msg="Report submitted" status="200 OK"'
Expand Down
1 change: 0 additions & 1 deletion cmd/pint/tests/0033_ci_github_multi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ cp ../src/v2.yml rules.yml
exec git commit -am 'v2'

env GITHUB_AUTH_TOKEN=12345
env GITHUB_PULL_REQUEST_NUMBER=1
pint.error -l debug --no-color ci
! stdout .
stderr 'level=info msg="Report submitted" status="200 OK"'
Expand Down
2 changes: 0 additions & 2 deletions cmd/pint/tests/0083_github_action.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,12 @@ exec git commit -am 'v2'
env GITHUB_AUTH_TOKEN=12345
env GITHUB_ACTION=YES
env GITHUB_EVENT_NAME=pull_request
env GITHUB_REF=refs/pull/123/merge
env GITHUB_BASE_REF=main
env GITHUB_REPOSITORY=foo/bar
env GITHUB_API_URL=http://127.0.0.1:6083
pint.ok -l debug --offline --no-color ci
! stdout .
stderr 'level=info msg="Report submitted" status="200 OK"'
stderr 'level=info msg="Setting GITHUB_PULL_REQUEST_NUMBER from GITHUB_REF env variable" pr=123'
stderr 'level=info msg="Setting repository owner from GITHUB_REPOSITORY env variable" owner=foo'
stderr 'level=info msg="Setting repository name from GITHUB_REPOSITORY env variable" repo=bar'
stderr 'level=info msg="Setting repository base URI from GITHUB_API_URL env variable" baseuri=http://127.0.0.1:6083'
Expand Down
2 changes: 0 additions & 2 deletions cmd/pint/tests/0084_github_action_override.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,12 @@ exec git commit -am 'v2'
env GITHUB_AUTH_TOKEN=12345
env GITHUB_ACTION=YES
env GITHUB_EVENT_NAME=pull_request
env GITHUB_REF=refs/pull/123/merge
env GITHUB_BASE_REF=main
env GITHUB_REPOSITORY=foo/bar
env GITHUB_API_URL=http://127.0.0.1:6084
pint.ok -l debug --offline --no-color ci
! stdout .
stderr 'level=info msg="Report submitted" status="200 OK"'
stderr 'level=info msg="Setting GITHUB_PULL_REQUEST_NUMBER from GITHUB_REF env variable" pr=123'
stderr 'level=info msg="Setting repository base URI from GITHUB_API_URL env variable" baseuri=http://127.0.0.1:6084'

-- src/v1.yml --
Expand Down
1 change: 0 additions & 1 deletion cmd/pint/tests/0085_github_no_envs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ exec git commit -am 'v2'

env GITHUB_AUTH_TOKEN=12345
env GITHUB_ACTION=YES
env GITHUB_PULL_REQUEST_NUMBER=123
pint.ok -l debug --offline --no-color ci
! stdout .
stderr 'level=info msg="Report submitted" status="200 OK"'
Expand Down
1 change: 0 additions & 1 deletion cmd/pint/tests/0098_rule_file_symlink_gh.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ cp ../src/v2.yml rules.yml
exec git commit -am 'v2'

env GITHUB_AUTH_TOKEN=12345
env GITHUB_PULL_REQUEST_NUMBER=1
pint.ok -l debug -d promql/series --no-color ci
! stdout .
stderr 'level=info msg="Report submitted" status="200 OK"'
Expand Down
6 changes: 6 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## v0.39.0

### Changed

- GitHub integration now uses [Check Runs](https://docs.github.com/en/rest/checks/runs) API - #478.

## v0.38.1

### Fixed
Expand Down
5 changes: 0 additions & 5 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,6 @@ to be set. It should contain a personal access token used to authenticate with t
**NOTE**: GitHub integration requires `GITHUB_AUTH_TOKEN` environment variable
to be set to a personal access key that can access your repository.

**NOTE** Pull request number must be known to pint so it can add comments if it detects any problems.
If pint is run as part of GitHub actions workflow then this number will be detected from `GITHUB_REF`
environment variable. For other use cases `GITHUB_PULL_REQUEST_NUMBER` environment variable must be set
with the pull request number.

Syntax:

```js
Expand Down
82 changes: 47 additions & 35 deletions internal/reporter/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/rs/zerolog/log"
"golang.org/x/oauth2"

"github.com/cloudflare/pint/internal/checks"
"github.com/cloudflare/pint/internal/git"
)

Expand All @@ -20,27 +21,31 @@ type GithubReporter struct {
authToken string
owner string
repo string
prNum int
gitCmd git.CommandRunner
}

// NewGithubReporter creates a new GitHub reporter that reports
// problems via comments on a given pull request number (integer).
func NewGithubReporter(baseURL, uploadURL string, timeout time.Duration, token, owner, repo string, prNum int, gitCmd git.CommandRunner) GithubReporter {
func NewGithubReporter(baseURL, uploadURL string, timeout time.Duration, token, owner, repo string, gitCmd git.CommandRunner) GithubReporter {
return GithubReporter{
baseURL: baseURL,
uploadURL: uploadURL,
timeout: timeout,
authToken: token,
owner: owner,
repo: repo,
prNum: prNum,
gitCmd: gitCmd,
}
}

// Submit submits the summary to GitHub.
func (gr GithubReporter) Submit(summary Summary) error {
headCommit, err := git.HeadCommit(gr.gitCmd)
if err != nil {
return fmt.Errorf("failed to get HEAD commit: %w", err)
}
log.Info().Str("commit", headCommit).Msg("Got HEAD commit from git")

ctx, cancel := context.WithTimeout(context.Background(), gr.timeout)
defer cancel()

Expand All @@ -52,55 +57,62 @@ func (gr GithubReporter) Submit(summary Summary) error {
var client *github.Client

if gr.uploadURL != "" && gr.baseURL != "" {
ec, err := github.NewEnterpriseClient(gr.baseURL, gr.uploadURL, tc)
client, err = github.NewEnterpriseClient(gr.baseURL, gr.uploadURL, tc)
if err != nil {
return fmt.Errorf("creating new GitHub client: %w", err)
return fmt.Errorf("failed to create a new GitHub client: %w", err)
}
client = ec
} else {
client = github.NewClient(tc)
}

comments := []*github.DraftReviewComment{}
conclusion := "success"
comments := []*github.CheckRunAnnotation{}
for _, rep := range summary.Reports() {
rep := rep

if len(rep.ModifiedLines) == 0 {
continue
var level string
switch rep.Problem.Severity {
case checks.Fatal, checks.Bug:
level = "failure"
conclusion = "failure"
case checks.Warning:
level = "warning"
case checks.Information:
level = "notice"
}

var comment *github.DraftReviewComment

if len(rep.ModifiedLines) == 1 {
comment = &github.DraftReviewComment{
Path: github.String(rep.ReportedPath),
Body: github.String(rep.Problem.Text),
Line: github.Int(rep.ModifiedLines[0]),
}
} else if len(rep.ModifiedLines) > 1 {
sort.Ints(rep.ModifiedLines)
start, end := rep.ModifiedLines[0], rep.ModifiedLines[len(rep.ModifiedLines)-1]
comment = &github.DraftReviewComment{
Path: github.String(rep.ReportedPath),
Body: github.String(rep.Problem.Text),
Line: github.Int(end),
StartLine: github.Int(start),
}
var comment *github.CheckRunAnnotation
sort.Ints(rep.ModifiedLines)
start, end := rep.Problem.LineRange()
comment = &github.CheckRunAnnotation{
Path: github.String(rep.ReportedPath),
StartLine: github.Int(start),
EndLine: github.Int(end),
AnnotationLevel: github.String(level),
Message: github.String(rep.Problem.Text),
Title: github.String(rep.Problem.Fragment),
}

comments = append(comments, comment)
}

if len(comments) > 0 {
_, resp, err := client.PullRequests.CreateReview(ctx, gr.owner, gr.repo, gr.prNum, &github.PullRequestReviewRequest{
Event: github.String("COMMENT"),
Comments: comments,
})
if err != nil {
return fmt.Errorf("creating review: %w", err)
}
log.Info().Str("status", resp.Status).Msg("Report submitted")
_, resp, err := client.Checks.CreateCheckRun(ctx, gr.owner, gr.repo, github.CreateCheckRunOptions{
Name: "pint",
HeadSHA: headCommit,
DetailsURL: github.String("https://cloudflare.github.io/pint/"),
Conclusion: github.String(conclusion),
CompletedAt: &github.Timestamp{Time: time.Now()},
Output: &github.CheckRunOutput{
Title: github.String("pint"),
Summary: github.String(BitBucketDescription),
AnnotationsCount: github.Int(len(comments)),
Annotations: comments,
},
})
if err != nil {
return fmt.Errorf("failed to create a new check run: %w", err)
}
log.Info().Str("status", resp.Status).Msg("Report submitted")

return nil
}
7 changes: 1 addition & 6 deletions internal/reporter/github_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,13 @@ import (
"testing"
"time"

"github.com/rs/zerolog"

"github.com/cloudflare/pint/internal/checks"
"github.com/cloudflare/pint/internal/git"
"github.com/cloudflare/pint/internal/parser"
"github.com/cloudflare/pint/internal/reporter"
)

func TestGithubReporter(t *testing.T) {
zerolog.SetGlobalLevel(zerolog.FatalLevel)

type errorCheck func(t *testing.T, err error) error

type testCaseT struct {
Expand Down Expand Up @@ -68,7 +64,7 @@ func TestGithubReporter(t *testing.T) {
if err == nil {
return fmt.Errorf("expected an error")
}
if err.Error() != "creating review: context deadline exceeded" {
if err.Error() != "failed to create a new check run: context deadline exceeded" {
return fmt.Errorf("unexpected error")
}
return nil
Expand Down Expand Up @@ -155,7 +151,6 @@ func TestGithubReporter(t *testing.T) {
tc.token,
tc.owner,
tc.repo,
tc.prNum,
tc.gitCmd,
)

Expand Down

0 comments on commit 54c944c

Please sign in to comment.