loop-plugin-sentry/server/plugin/sentry_client.go

145 lines
3.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package plugin
import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"strings"
"time"
)
// fetchSentryProject получает информацию о проекте из Sentry API
func (p *Plugin) fetchSentryProject(projectSlug string) (*LinkedProject, error) {
cfg := p.GetConfiguration()
if cfg.SentryUrl == "" || cfg.SentryOrganisationName == "" || cfg.SentryAuthToken == "" {
return nil, errors.New("sentry is not configured")
}
url := fmt.Sprintf(
"%s/api/0/projects/%s/%s/",
strings.TrimRight(cfg.SentryUrl, "/"),
cfg.SentryOrganisationName,
projectSlug,
)
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
return nil, err
}
req.Header.Set("Authorization", "Bearer "+cfg.SentryAuthToken)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("sentry api error (%d): %s", resp.StatusCode, body)
}
var result struct {
ID string `json:"id"`
Slug string `json:"slug"`
Name string `json:"name"`
}
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, err
}
if result.ID == "" {
return nil, errors.New("project id not found")
}
return &LinkedProject{
ID: result.ID,
Slug: result.Slug,
Name: result.Name,
}, nil
}
// SentryProject представляет проект из Sentry API
type SentryProject struct {
ID string `json:"id"`
Slug string `json:"slug"`
Name string `json:"name"`
}
// fetchSentryProjects получает список всех проектов из Sentry API
func (p *Plugin) fetchSentryProjects() ([]SentryProject, error) {
cfg := p.GetConfiguration()
if cfg.SentryUrl == "" || cfg.SentryOrganisationName == "" || cfg.SentryAuthToken == "" {
return nil, errors.New("sentry is not configured")
}
url := fmt.Sprintf(
"%s/api/0/organizations/%s/projects/",
strings.TrimRight(cfg.SentryUrl, "/"),
cfg.SentryOrganisationName,
)
p.API.LogDebug("Fetching Sentry projects", "url", url)
req, err := http.NewRequest(http.MethodGet, url, nil)
if err != nil {
p.API.LogError("Failed to create request", "error", err.Error())
return nil, err
}
req.Header.Set("Authorization", "Bearer "+cfg.SentryAuthToken)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 10 * time.Second}
resp, err := client.Do(req)
if err != nil {
p.API.LogError("Failed to execute request", "error", err.Error())
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
p.API.LogError("Sentry API error", "status", resp.StatusCode, "body", string(body))
return nil, fmt.Errorf("sentry api error (%d): %s", resp.StatusCode, body)
}
var projects []SentryProject
if err := json.NewDecoder(resp.Body).Decode(&projects); err != nil {
p.API.LogError("Failed to decode response", "error", err.Error())
return nil, err
}
p.API.LogDebug("Fetched Sentry projects", "count", len(projects))
return projects, nil
}
// linkProjectToChannel связывает проект Sentry с каналом Mattermost
func (p *Plugin) linkProjectToChannel(
projectSlug string,
channelID string,
hooks HookSettings,
) (*LinkedProject, error) {
project, err := p.fetchSentryProject(projectSlug)
if err != nil {
return nil, err
}
project.ChannelID = channelID
project.Hooks = hooks
if err := p.saveProject(project); err != nil {
return nil, err
}
return project, nil
}