Skip to content
This repository has been archived by the owner on Dec 10, 2024. It is now read-only.

Commit

Permalink
Added sentry error tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
Shocktrooper committed May 22, 2022
1 parent 1ca1507 commit 28beba2
Show file tree
Hide file tree
Showing 4 changed files with 353 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ to add new and/or missing endpoints. Currently, the following services are suppo
- [x] Environments
- [x] Epic Issues
- [x] Epics
- [x] Error Tracking
- [x] Events
- [x] Feature Flags
- [x] Geo Nodes
Expand Down
181 changes: 181 additions & 0 deletions error_tracking.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
//
// Copyright 2022, Ryan Glab <ryan.j.glab@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package gitlab

import (
"fmt"
"net/http"
)

// ErrorTrackingService handles communication with the error tracking
// methods of the GitLab API.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/error_tracking.html
type ErrorTrackingService struct {
client *Client
}

// ErrorTracking represents error tracking settings for a GitLab project.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/error_tracking.html
type ErrorTracking struct {
Active bool `json:"active"`
ProjectName string `json:"project_name"`
SentryExternalURL string `json:"sentry_external_url"`
APIURL string `json:"api_url"`
Integrated bool `json:"integrated"`
}

func (p ErrorTracking) String() string {
return Stringify(p)
}

// GetErrorTracking gets Sentry error tracking settings for a specific project
//
// GitLab API docs: https://docs.gitlab.com/ee/api/error_tracking.html#get-error-tracking-settings
func (s *ErrorTrackingService) GetErrorTracking(pid interface{}, options ...RequestOptionFunc) (*ErrorTracking, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}

u := fmt.Sprintf("projects/%s/error_tracking/settings", PathEscape(project))

req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
if err != nil {
return nil, nil, err
}

ErrorTracking := new(ErrorTracking)
resp, err := s.client.Do(req, ErrorTracking)
if err != nil {
return nil, resp, err
}

return ErrorTracking, resp, err
}

type ConfigureErrorTrackingOptions struct {
Active *bool `url:"active,omitempty" json:"active,omitempty"`
Integrated *bool `url:"integrated,omitempty" json:"integrated,omitempty"`
}

// EnableDisableErrorTracking allows the enabling or disabling of sentry integration on a specified project
//
// GitLab API docs: https://docs.gitlab.com/ee/api/error_tracking.html#enable-or-disable-the-error-tracking-project-settings
func (s *ErrorTrackingService) EnableDisableErrorTracking(pid interface{}, opt *ConfigureErrorTrackingOptions, options ...RequestOptionFunc) (*ErrorTracking, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}
u := fmt.Sprintf("projects/%d/error_tracking/settings", PathEscape(project))

req, err := s.client.NewRequest(http.MethodPatch, u, opt, options)
if err != nil {
return nil, nil, err
}

ET := new(ErrorTracking)
resp, err := s.client.Do(req, &ET)
if err != nil {
return nil, resp, err
}

return ET, resp, err
}

// ListErrorTrackingClientKeysOptions represents the available
// ListErrorTrackingClientKeys() options.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/error_tracking.html#list-project-client-keys
type ListErrorTrackingClientKeysOptions ListOptions

type ProjectClientKey struct {
ID int `json:"id"`
Active bool `json:"active"`
PublicKey string `json:"public_key"`
SentryDsn string `json:"sentry_dsn"`
}

// ListErrorTrackingClientKeys gets a list of project client keys for sentry.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/error_tracking.html#list-project-client-keys
func (s *ErrorTrackingService) ListErrorTrackingClientKeys(pid interface{}, opt *ListErrorTrackingClientKeysOptions, options ...RequestOptionFunc) ([]*ProjectClientKey, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}

u := fmt.Sprintf("projects/%s/error_tracking/client_keys", PathEscape(project))

req, err := s.client.NewRequest(http.MethodGet, u, opt, options)
if err != nil {
return nil, nil, err
}

var projectClientKeys []*ProjectClientKey
resp, err := s.client.Do(req, &projectClientKeys)
if err != nil {
return nil, resp, err
}

return projectClientKeys, resp, err
}

// CreateClientKey creates a project client key for sentry integration in a GitLab project.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/error_tracking.html#create-a-client-key
func (s *ErrorTrackingService) CreateClientKey(pid interface{}, options ...RequestOptionFunc) (*ProjectClientKey, *Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, nil, err
}

u := fmt.Sprintf("projects/%s/error_tracking/client_keys", PathEscape(project))

req, err := s.client.NewRequest(http.MethodPost, u, nil, options)
if err != nil {
return nil, nil, err
}

projectClientKey := new(ProjectClientKey)
resp, err := s.client.Do(req, projectClientKey)
if err != nil {
return nil, resp, err
}

return projectClientKey, resp, err
}

// DeleteClientKey removes a sentry client key from a project.
//
// GitLab API docs: https://docs.gitlab.com/ee/api/error_tracking.html#delete-a-client-key
func (s *ErrorTrackingService) DeleteClientKey(pid interface{}, keyID int, options ...RequestOptionFunc) (*Response, error) {
project, err := parseID(pid)
if err != nil {
return nil, err
}

u := fmt.Sprintf("projects/%s/error_tracking/client_keys/%d", PathEscape(project), keyID)

req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
if err != nil {
return nil, err
}

return s.client.Do(req, nil)
}
169 changes: 169 additions & 0 deletions error_tracking_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
//
// Copyright 2022, Ryan Glab <ryan.j.glab@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

package gitlab

import (
"fmt"
"net/http"
"reflect"
"testing"
)

func TestGetErrorTracking(t *testing.T) {
mux, server, client := setup(t)
defer teardown(server)

mux.HandleFunc("/api/v4/projects/1/error_tracking/settings", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `{
"active": true,
"project_name": "sample sentry project",
"sentry_external_url": "https://sentry.io/myawesomeproject/project",
"api_url": "https://sentry.io/api/1/projects/myawesomeproject/project",
"integrated": false
}`)
})

ET, _, err := client.ErrorTracking.GetErrorTracking(1)
if err != nil {
t.Errorf("ErrorTracking.GetErrorTracking returned error: %v", err)
}

want := &ErrorTracking{
Active: true,
ProjectName: "sample sentry project",
SentryExternalURL: "https://sentry.io/myawesomeproject/project",
APIURL: "https://sentry.io/api/1/projects/myawesomeproject/project",
Integrated: false,
}

if !reflect.DeepEqual(want, ET) {
t.Errorf("ErrorTracking.GetErrorTracking returned %+v, want %+v", ET, want)
}
}

func TestDisableErrorTracking(t *testing.T) {
mux, server, client := setup(t)
defer teardown(server)

mux.HandleFunc("/api/v4/projects/1/error_tracking/settings", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodPatch)
fmt.Fprint(w, `{
"active": false,
"project_name": "sample sentry project",
"sentry_external_url": "https://sentry.io/myawesomeproject/project",
"api_url": "https://sentry.io/api/1/projects/myawesomeproject/project",
"integrated": false
}`)
})

ET, _, err := client.ErrorTracking.EnableDisableErrorTracking(&ConfigureErrorTrackingOptions{ID: Int(1), Active: Bool(false), Integrated: Bool(false)})
if err != nil {
t.Errorf("ErrorTracking.EnableDisableErrorTracking returned error: %v", err)
}

want := &ErrorTracking{
Active: false,
ProjectName: "sample sentry project",
SentryExternalURL: "https://sentry.io/myawesomeproject/project",
APIURL: "https://sentry.io/api/1/projects/myawesomeproject/project",
Integrated: false,
}

if !reflect.DeepEqual(want, ET) {
t.Errorf("ErrorTracking.EnableDisableErrorTracking returned %+v, want %+v", ET, want)
}
}

func TestListErrorTrackingClientKeys(t *testing.T) {
mux, server, client := setup(t)
defer teardown(server)

mux.HandleFunc("/api/v4/projects/1/error_tracking/client_keys", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodGet)
fmt.Fprint(w, `[
{
"id": 1,
"active": true,
"public_key": "glet_aa77551d849c083f76d0bc545ed053a3",
"sentry_dsn": "https://glet_aa77551d849c083f76d0bc545ed053a3@gitlab.example.com/api/v4/error_tracking/collector/5"
}
]`)
})

CKS, _, err := client.ErrorTracking.ListErrorTrackingClientKeys(1, &ListErrorTrackingClientKeysOptions{Page: 1, PerPage: 10})
if err != nil {
t.Errorf("ErrorTracking.ListErrorTrackingClientKeys returned error: %v", err)
}

want := []*ProjectClientKey{{
ID: 1,
Active: true,
PublicKey: "glet_aa77551d849c083f76d0bc545ed053a3",
SentryDsn: "https://glet_aa77551d849c083f76d0bc545ed053a3@gitlab.example.com/api/v4/error_tracking/collector/5",
}}

if !reflect.DeepEqual(want, CKS) {
t.Errorf("ErrorTracking.ListErrorTrackingClientKeys returned %+v, want %+v", CKS, want)
}
}

func TestCreateClientKey(t *testing.T) {
mux, server, client := setup(t)
defer teardown(server)

mux.HandleFunc("/api/v4/projects/1/error_tracking/client_keys", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodPost)
fmt.Fprint(w, `{
"id": 1,
"active": true,
"public_key": "glet_aa77551d849c083f76d0bc545ed053a3",
"sentry_dsn": "https://glet_aa77551d849c083f76d0bc545ed053a3@gitlab.example.com/api/v4/error_tracking/collector/5"
}`)
})

CK, _, err := client.ErrorTracking.CreateClientKey(1)
if err != nil {
t.Errorf("ErrorTracking.CreateClientKey returned error: %v", err)
}

want := &ProjectClientKey{
ID: 1,
Active: true,
PublicKey: "glet_aa77551d849c083f76d0bc545ed053a3",
SentryDsn: "https://glet_aa77551d849c083f76d0bc545ed053a3@gitlab.example.com/api/v4/error_tracking/collector/5",
}

if !reflect.DeepEqual(want, CK) {
t.Errorf("ErrorTracking.CreateClientKey returned %+v, want %+v", CK, want)
}
}

func TestDeleteClientKey(t *testing.T) {
mux, server, client := setup(t)
defer teardown(server)

mux.HandleFunc("/api/v4/projects/1/error_tracking/client_keys/3", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, http.MethodDelete)
testURL(t, r, "/api/v4/projects/1/error_tracking/client_keys/3")
})

_, err := client.ErrorTracking.DeleteClientKey(1, 3)
if err != nil {
t.Errorf("ErrorTracking.DeleteClientKey returned error: %v", err)
}
}
2 changes: 2 additions & 0 deletions gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ type Client struct {
Environments *EnvironmentsService
EpicIssues *EpicIssuesService
Epics *EpicsService
ErrorTracking *ErrorTrackingService
Events *EventsService
ExternalStatusChecks *ExternalStatusChecksService
Features *FeaturesService
Expand Down Expand Up @@ -322,6 +323,7 @@ func newClient(options ...ClientOptionFunc) (*Client, error) {
c.Environments = &EnvironmentsService{client: c}
c.EpicIssues = &EpicIssuesService{client: c}
c.Epics = &EpicsService{client: c}
c.ErrorTracking = &ErrorTrackingService{client: c}
c.Events = &EventsService{client: c}
c.ExternalStatusChecks = &ExternalStatusChecksService{client: c}
c.Features = &FeaturesService{client: c}
Expand Down

0 comments on commit 28beba2

Please sign in to comment.