From 790558d52571a51a75c44b5d5e4d52f8d3c110f4 Mon Sep 17 00:00:00 2001 From: Aramis Date: Tue, 8 Jun 2021 16:25:53 -0300 Subject: [PATCH] feat: Automatic Release detection (#335) Attempts to guess the release info, either by getting the last git commit hash or by looking up some known environment variables that tracks release identification. --- client.go | 2 +- client_test.go | 4 ++- fasthttp/sentryfasthttp_test.go | 2 +- http/sentryhttp_test.go | 2 +- tracing_test.go | 4 +-- util.go | 43 +++++++++++++++++++++++++++++++++ 6 files changed, 51 insertions(+), 6 deletions(-) diff --git a/client.go b/client.go index 7bab94b5e..7fadd6630 100644 --- a/client.go +++ b/client.go @@ -208,7 +208,7 @@ func NewClient(options ClientOptions) (*Client, error) { } if options.Release == "" { - options.Release = os.Getenv("SENTRY_RELEASE") + options.Release = defaultRelease() } if options.Environment == "" { diff --git a/client_test.go b/client_test.go index 652b159e5..d682c043d 100644 --- a/client_test.go +++ b/client_test.go @@ -11,6 +11,7 @@ import ( "time" "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" pkgErrors "github.com/pkg/errors" ) @@ -281,7 +282,8 @@ func TestCaptureEvent(t *testing.T) { }, } got := transport.lastEvent - if diff := cmp.Diff(want, got); diff != "" { + opts := cmp.Options{cmpopts.IgnoreFields(Event{}, "Release")} + if diff := cmp.Diff(want, got, opts); diff != "" { t.Errorf("Event mismatch (-want +got):\n%s", diff) } } diff --git a/fasthttp/sentryfasthttp_test.go b/fasthttp/sentryfasthttp_test.go index 8c0fd703d..e597aadfe 100644 --- a/fasthttp/sentryfasthttp_test.go +++ b/fasthttp/sentryfasthttp_test.go @@ -206,7 +206,7 @@ func TestIntegration(t *testing.T) { cmpopts.IgnoreFields( sentry.Event{}, "Contexts", "EventID", "Extra", "Platform", - "Sdk", "ServerName", "Tags", "Timestamp", + "Release", "Sdk", "ServerName", "Tags", "Timestamp", ), cmpopts.IgnoreMapEntries(func(k string, v string) bool { // fasthttp changed Content-Length behavior in diff --git a/http/sentryhttp_test.go b/http/sentryhttp_test.go index 500a06eb6..5d0192370 100644 --- a/http/sentryhttp_test.go +++ b/http/sentryhttp_test.go @@ -214,7 +214,7 @@ func TestIntegration(t *testing.T) { cmpopts.IgnoreFields( sentry.Event{}, "Contexts", "EventID", "Extra", "Platform", - "Sdk", "ServerName", "Tags", "Timestamp", + "Release", "Sdk", "ServerName", "Tags", "Timestamp", ), cmpopts.IgnoreFields( sentry.Request{}, diff --git a/tracing_test.go b/tracing_test.go index 6b1e2a7de..28e601004 100644 --- a/tracing_test.go +++ b/tracing_test.go @@ -151,7 +151,7 @@ func TestStartSpan(t *testing.T) { opts := cmp.Options{ cmpopts.IgnoreFields(Event{}, "Contexts", "EventID", "Level", "Platform", - "Sdk", "ServerName", + "Release", "Sdk", "ServerName", ), cmpopts.EquateEmpty(), } @@ -210,7 +210,7 @@ func TestStartChild(t *testing.T) { opts := cmp.Options{ cmpopts.IgnoreFields(Event{}, "EventID", "Level", "Platform", - "Sdk", "ServerName", "Timestamp", "StartTime", + "Release", "Sdk", "ServerName", "Timestamp", "StartTime", ), cmpopts.IgnoreMapEntries(func(k string, v interface{}) bool { return k != "trace" diff --git a/util.go b/util.go index fe3b92693..da84a79a9 100644 --- a/util.go +++ b/util.go @@ -1,11 +1,14 @@ package sentry import ( + "bytes" "crypto/rand" "encoding/hex" "encoding/json" "fmt" "os" + "os/exec" + "strings" "time" ) @@ -37,3 +40,43 @@ func prettyPrint(data interface{}) { dbg, _ := json.MarshalIndent(data, "", " ") fmt.Println(string(dbg)) } + +// attempts to guess a default release. +func defaultRelease() string { + // Search environment variables (EV) known to hold release info. + envs := []string{ + "SENTRY_RELEASE", + "HEROKU_SLUG_COMMIT", + "SOURCE_VERSION", + "CODEBUILD_RESOLVED_SOURCE_VERSION", + "CIRCLE_SHA1", + "GAE_DEPLOYMENT_ID", + "GITHUB_SHA", // GitHub Actions - https://help.github.com/en/actions + "COMMIT_REF", // Netlify - https://docs.netlify.com/ + "VERCEL_GIT_COMMIT_SHA", // Vercel - https://vercel.com/ + "ZEIT_GITHUB_COMMIT_SHA", // Zeit (now known as Vercel) + "ZEIT_GITLAB_COMMIT_SHA", + "ZEIT_BITBUCKET_COMMIT_SHA"} + for _, e := range envs { + if val := os.Getenv(e); val != "" { + return val // Stop at first non-empty variable. + } + } + + // No EV's, attempt to get the last commit hash with git. + var stdout bytes.Buffer + cmd := exec.Command("git", "rev-parse", "HEAD") + cmd.Stdout = &stdout + err := cmd.Run() + if err != nil { + Logger.Println("Failed attempt to run git rev-parse.") + } else { + shastr := strings.TrimSpace(stdout.String()) + if len(shastr) == 40 { // sha1 hash length + return shastr + } + } + + // Not able to find a release name at all. + return "" +}