From cce97335161eeb2eb54b58fbb2ea8d96249d327e Mon Sep 17 00:00:00 2001 From: Jody Heavener Date: Thu, 4 Apr 2024 19:55:24 -0700 Subject: [PATCH] Add Sentry error and event tracking --- .github/workflows/approve-application.yml | 1 + .github/workflows/review-application.yml | 1 + script/application.go | 3 ++ script/approver.go | 58 ++++++++++++++++------- script/go.mod | 3 ++ script/go.sum | 6 +++ script/main.go | 17 +++++++ script/reviewer.go | 29 +++++++----- 8 files changed, 90 insertions(+), 28 deletions(-) diff --git a/.github/workflows/approve-application.yml b/.github/workflows/approve-application.yml index d03a8cde..fce5b54a 100644 --- a/.github/workflows/approve-application.yml +++ b/.github/workflows/approve-application.yml @@ -39,6 +39,7 @@ jobs: chmod +x ./processor ./processor approve env: + SENTRY_DSN: ${{ secrets.SENTRY_DSN }} APPROVER_ID: ${{ needs.check.outputs.approver_id }} APPROVER_USERNAME: ${{ needs.check.outputs.approver_username }} OP_BOT_PAT: ${{ secrets.OP_BOT_PAT }} diff --git a/.github/workflows/review-application.yml b/.github/workflows/review-application.yml index c6aa3dac..cf7a479b 100644 --- a/.github/workflows/review-application.yml +++ b/.github/workflows/review-application.yml @@ -23,6 +23,7 @@ jobs: chmod +x ./processor ./processor review env: + SENTRY_DSN: ${{ secrets.SENTRY_DSN }} OP_BOT_PAT: ${{ secrets.OP_BOT_PAT }} ISSUE_NUMBER: ${{ github.event.issue.number }} REPOSITORY_OWNER: ${{ github.repository_owner }} diff --git a/script/application.go b/script/application.go index c60f00ca..3f546252 100644 --- a/script/application.go +++ b/script/application.go @@ -9,6 +9,7 @@ import ( "strings" "time" + "github.com/getsentry/sentry-go" "github.com/google/go-github/v60/github" ) @@ -64,6 +65,7 @@ func (a *Application) Parse(issue *github.Issue) { if isTesting() { data, err := json.MarshalIndent(a.sections, "", "\t") if err != nil { + sentry.CaptureException(err) log.Fatalf("Could not marshal Sections input data: %s", err.Error()) } @@ -125,6 +127,7 @@ func (a *Application) RenderProblems() string { func (a *Application) GetData() []byte { data, err := json.MarshalIndent(a, "", "\t") if err != nil { + sentry.CaptureException(err) log.Fatalf("Could not marshal Application data: %s", err.Error()) } diff --git a/script/approver.go b/script/approver.go index 84cc11f0..450ce38b 100644 --- a/script/approver.go +++ b/script/approver.go @@ -1,11 +1,14 @@ package main import ( + "encoding/json" "errors" "fmt" "log" "path/filepath" "strings" + + "github.com/getsentry/sentry-go" ) type Approver struct { @@ -18,28 +21,33 @@ func (a *Approver) Approve() { a.application = Application{} if err := a.application.SetApprover(); err != nil { - a.printErrorAndExit(err) + a.logErrorAndExit("could not set application approver", err) } if err := a.gitHub.Init(); err != nil { - a.printErrorAndExit(err) + a.logErrorAndExit("could not initialize GitHub client", err) } if *a.gitHub.Issue.State == "closed" { - a.printErrorAndExit(errors.New("script run on closed issue")) + a.logErrorAndExit( + "script run on closed issue", + errors.New(*a.gitHub.Issue.State), + ) } if !a.gitHub.IssueHasLabel(LabelStatusApproved) { - a.printErrorAndExit( - fmt.Errorf("script run on issue that does not have required '%s' label", LabelStatusApproved), + a.logErrorAndExit( + fmt.Sprintf("script run on issue that does not have required '%s' label", LabelStatusApproved), + fmt.Errorf("issue has labels %v", a.gitHub.Issue.Labels), ) } a.application.Parse(a.gitHub.Issue) if !a.application.IsValid() { - a.printErrorAndExit( - fmt.Errorf("script run on issue with invalid application data:\n\n%s", a.renderProblems()), + a.logErrorAndExit( + "script run on issue with invalid application data", + errors.New(a.renderProblems()), ) } @@ -47,8 +55,9 @@ func (a *Approver) Approve() { // let's double check and remove it if they haven't if a.gitHub.IssueHasLabel(LabelStatusReviewing) { if err := a.gitHub.RemoveIssueLabel(LabelStatusReviewing); err != nil { - a.printErrorAndExit( - fmt.Errorf("could not remove issue label '%s': %s", LabelStatusReviewing, err.Error()), + a.logErrorAndExit( + fmt.Sprintf("could not remove issue label '%s'", LabelStatusReviewing), + err, ) } } @@ -58,26 +67,41 @@ func (a *Approver) Approve() { a.application.GetData(), fmt.Sprintf("Added \"%s\" to program", a.application.Project.Name), ); err != nil { - a.printErrorAndExit( - fmt.Errorf("could not create commit: %s", err.Error()), + a.logErrorAndExit( + "could not create commit", + err, ) } if err := a.gitHub.CreateIssueComment(a.getApprovalMessage()); err != nil { - a.printErrorAndExit( - fmt.Errorf("could not create issue comment: %s", err.Error()), + a.logErrorAndExit( + "could not create issue comment", + err, ) } if err := a.gitHub.CloseIssue(); err != nil { - a.printErrorAndExit( - fmt.Errorf("could not close issue: %s", err.Error()), + a.logErrorAndExit( + "could not close issue", + err, ) } + + var appData map[string]interface{} + err := json.Unmarshal(a.application.GetData(), &appData) + if err != nil { + log.Fatal(err) + } + sentry.CaptureEvent(&sentry.Event{ + Message: "Application approved", + Level: sentry.LevelInfo, + Extra: appData, + }) } -func (a *Approver) printErrorAndExit(err error) { - log.Fatalf("Error approving application: %s\n", err.Error()) +func (a *Approver) logErrorAndExit(message string, err error) { + sentry.CaptureException(err) + log.Fatalf("Error approving issue: %s: %s\n", message, err.Error()) } func (a *Approver) renderProblems() string { diff --git a/script/go.mod b/script/go.mod index e55eaede..1f71acc4 100644 --- a/script/go.mod +++ b/script/go.mod @@ -4,6 +4,7 @@ go 1.19 require ( github.com/PuerkitoBio/goquery v1.9.1 + github.com/getsentry/sentry-go v0.27.0 github.com/google/go-github/v60 v60.0.0 github.com/russross/blackfriday/v2 v2.1.0 golang.org/x/oauth2 v0.18.0 @@ -14,6 +15,8 @@ require ( github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-querystring v1.1.0 // indirect golang.org/x/net v0.22.0 // indirect + golang.org/x/sys v0.18.0 // indirect + golang.org/x/text v0.14.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/protobuf v1.33.0 // indirect ) diff --git a/script/go.sum b/script/go.sum index 6243587f..ddcbd9f5 100644 --- a/script/go.sum +++ b/script/go.sum @@ -2,6 +2,8 @@ github.com/PuerkitoBio/goquery v1.9.1 h1:mTL6XjbJTZdpfL+Gwl5U2h1l9yEkJjhmlTeV9VP github.com/PuerkitoBio/goquery v1.9.1/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY= github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= +github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= +github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= @@ -42,6 +44,8 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -53,6 +57,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/script/main.go b/script/main.go index 4d5e2676..395702f4 100644 --- a/script/main.go +++ b/script/main.go @@ -4,6 +4,9 @@ import ( "fmt" "log" "os" + "time" + + "github.com/getsentry/sentry-go" ) func printUsageAndExit() { @@ -21,6 +24,20 @@ func getEnv(key string) (string, error) { } func main() { + sentryDsn, err := getEnv("SENTRY_DSN") + if err != nil { + log.Fatal(err) + } + + err = sentry.Init(sentry.ClientOptions{ + Dsn: sentryDsn, + }) + if err != nil { + log.Fatalf("Sentry initialization failed: %v\n", err) + } + + defer sentry.Flush(2 * time.Second) + if len(os.Args) < 2 { printUsageAndExit() } diff --git a/script/reviewer.go b/script/reviewer.go index 5e59beb1..b6ff3cab 100644 --- a/script/reviewer.go +++ b/script/reviewer.go @@ -3,6 +3,8 @@ package main import ( "fmt" "log" + + "github.com/getsentry/sentry-go" ) type Status int @@ -24,7 +26,7 @@ func (r *Reviewer) Review() { r.application = Application{} if err := r.gitHub.Init(); err != nil { - r.printErrorAndExit(err) + r.logErrorAndExit("could not initialize GitHub client", err) } r.application.Parse(r.gitHub.Issue) @@ -96,38 +98,43 @@ func (r *Reviewer) updateLabels(status Status, isClosed bool) { if r.application.IsValid() { if status == Invalid { if err := r.gitHub.RemoveIssueLabel(LabelStatusInvalid); err != nil { - r.printErrorAndExit( - fmt.Errorf("could not remove issue label '%s': %s", LabelStatusInvalid, err.Error()), + r.logErrorAndExit( + fmt.Sprintf("could not remove issue label '%s'", LabelStatusInvalid), + err, ) } } if status != Reviewing { if err := r.gitHub.AddIssueLabel(LabelStatusReviewing); err != nil { - r.printErrorAndExit( - fmt.Errorf("could not add issue label '%s': %s", LabelStatusReviewing, err.Error()), + r.logErrorAndExit( + fmt.Sprintf("could not add issue label '%s'", LabelStatusReviewing), + err, ) } } } else { if status != Invalid { if err := r.gitHub.AddIssueLabel(LabelStatusInvalid); err != nil { - r.printErrorAndExit( - fmt.Errorf("could not add issue label '%s': %s", LabelStatusInvalid, err.Error()), + r.logErrorAndExit( + fmt.Sprintf("could not add issue label '%s'", LabelStatusInvalid), + err, ) } } if status == Reviewing { if err := r.gitHub.RemoveIssueLabel(LabelStatusReviewing); err != nil { - r.printErrorAndExit( - fmt.Errorf("could not remove issue label '%s': %s", LabelStatusReviewing, err.Error()), + r.logErrorAndExit( + fmt.Sprintf("could not remove issue label '%s'", LabelStatusReviewing), + err, ) } } } } -func (r *Reviewer) printErrorAndExit(err error) { - log.Fatalf("Error reviewing issue: %s\n", err.Error()) +func (r *Reviewer) logErrorAndExit(message string, err error) { + sentry.CaptureException(err) + log.Fatalf("Error reviewing issue: %s: %s\n", message, err.Error()) }