From 5d9e534a749e9b418d431e34c2de5a11a4eab87e Mon Sep 17 00:00:00 2001 From: Aramis Date: Tue, 1 Jun 2021 18:15:18 -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 | 1 + fasthttp/sentryfasthttp_test.go | 5 ++++ http/sentryhttp_test.go | 5 ++++ tracing_test.go | 2 ++ util.go | 44 +++++++++++++++++++++++++++++++++ 6 files changed, 58 insertions(+), 1 deletion(-) diff --git a/client.go b/client.go index 7bab94b5e..87fd45af3 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 = GetDefaultRelease() } if options.Environment == "" { diff --git a/client_test.go b/client_test.go index 652b159e5..fcc9fcd50 100644 --- a/client_test.go +++ b/client_test.go @@ -258,6 +258,7 @@ func TestCaptureEvent(t *testing.T) { t.Fatal("missing event") } want := &Event{ + Release: GetDefaultRelease(), EventID: eventID, Timestamp: timestamp, ServerName: serverName, diff --git a/fasthttp/sentryfasthttp_test.go b/fasthttp/sentryfasthttp_test.go index 8c0fd703d..1c766986f 100644 --- a/fasthttp/sentryfasthttp_test.go +++ b/fasthttp/sentryfasthttp_test.go @@ -34,6 +34,7 @@ func TestIntegration(t *testing.T) { }, WantEvent: &sentry.Event{ + Release: sentry.GetDefaultRelease(), Level: sentry.LevelFatal, Message: "test", Request: &sentry.Request{ @@ -56,6 +57,7 @@ func TestIntegration(t *testing.T) { }, WantEvent: &sentry.Event{ + Release: sentry.GetDefaultRelease(), Level: sentry.LevelInfo, Message: "post: payload", Request: &sentry.Request{ @@ -77,6 +79,7 @@ func TestIntegration(t *testing.T) { }, WantEvent: &sentry.Event{ + Release: sentry.GetDefaultRelease(), Level: sentry.LevelInfo, Message: "get", Request: &sentry.Request{ @@ -99,6 +102,7 @@ func TestIntegration(t *testing.T) { }, WantEvent: &sentry.Event{ + Release: sentry.GetDefaultRelease(), Level: sentry.LevelInfo, Message: "post: 15 KB", Request: &sentry.Request{ @@ -123,6 +127,7 @@ func TestIntegration(t *testing.T) { }, WantEvent: &sentry.Event{ + Release: sentry.GetDefaultRelease(), Level: sentry.LevelInfo, Message: "body ignored", Request: &sentry.Request{ diff --git a/http/sentryhttp_test.go b/http/sentryhttp_test.go index 500a06eb6..5208e509b 100644 --- a/http/sentryhttp_test.go +++ b/http/sentryhttp_test.go @@ -33,6 +33,7 @@ func TestIntegration(t *testing.T) { }), WantEvent: &sentry.Event{ + Release: sentry.GetDefaultRelease(), Level: sentry.LevelFatal, Message: "test", Request: &sentry.Request{ @@ -60,6 +61,7 @@ func TestIntegration(t *testing.T) { }), WantEvent: &sentry.Event{ + Release: sentry.GetDefaultRelease(), Level: sentry.LevelInfo, Message: "post: payload", Request: &sentry.Request{ @@ -83,6 +85,7 @@ func TestIntegration(t *testing.T) { }), WantEvent: &sentry.Event{ + Release: sentry.GetDefaultRelease(), Level: sentry.LevelInfo, Message: "get", Request: &sentry.Request{ @@ -110,6 +113,7 @@ func TestIntegration(t *testing.T) { }), WantEvent: &sentry.Event{ + Release: sentry.GetDefaultRelease(), Level: sentry.LevelInfo, Message: "post: 15 KB", Request: &sentry.Request{ @@ -136,6 +140,7 @@ func TestIntegration(t *testing.T) { }), WantEvent: &sentry.Event{ + Release: sentry.GetDefaultRelease(), Level: sentry.LevelInfo, Message: "body ignored", Request: &sentry.Request{ diff --git a/tracing_test.go b/tracing_test.go index 6b1e2a7de..1e7576346 100644 --- a/tracing_test.go +++ b/tracing_test.go @@ -128,6 +128,7 @@ func TestStartSpan(t *testing.T) { t.Fatalf("sent %d events, want 1", got) } want := &Event{ + Release: GetDefaultRelease(), Type: transactionType, Transaction: transaction, Contexts: map[string]interface{}{ @@ -188,6 +189,7 @@ func TestStartChild(t *testing.T) { t.Fatalf("sent %d events, want 1", got) } want := &Event{ + Release: GetDefaultRelease(), Type: transactionType, Transaction: "Test Transaction", Contexts: map[string]interface{}{ diff --git a/util.go b/util.go index fe3b92693..66deceec4 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,44 @@ func prettyPrint(data interface{}) { dbg, _ := json.MarshalIndent(data, "", " ") fmt.Println(string(dbg)) } + +// GetDefaultRelease attempts to guess a default release. +func GetDefaultRelease() string { + if release := os.Getenv("SENTRY_RELEASE"); release == "" { + // 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 + } + } + + // Look for environment variables known to hold versioning info. + if release == "" { + envVars := []string{ + "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 _, env := range envVars { + if envVal := os.Getenv(env); envVal != "" { + return envVal // Stop at first non-empty variable. + } + } + } + } + return "" +}