CI: Backport CI/Release related code to v9.3.x (#62752)
* Batch-move everything
* go mod tidy
* make drone
* Remove genversions
* Bump alpine image
* Revert back pkg/build/docker/build.go
* Make sure correct enterprise branch is checked out
* Add enterprise2 version
* Remove extensions
* Bump build container
* backport node 18 test fix
(cherry picked from commit 4ff03fdbfb)
* Update scripts/drone
* Add more commands
* Fix starlark link
* Copy .drone.star
* Add drone target branch for custom events
---------
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
package git
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
|
||||
"github.com/google/go-github/v45/github"
|
||||
"github.com/grafana/grafana/pkg/build/stringutil"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
const (
|
||||
MainBranch = "main"
|
||||
HomeDir = "."
|
||||
RepoOwner = "grafana"
|
||||
OSSRepo = "grafana"
|
||||
EnterpriseRepo = "grafana-enterprise"
|
||||
EnterpriseCheckName = "Grafana Enterprise"
|
||||
EnterpriseCheckDescription = "Downstream tests to ensure that your changes are compatible with Grafana Enterprise"
|
||||
)
|
||||
|
||||
var EnterpriseCheckLabels = []string{"enterprise-ok", "enterprise-failed", "enterprise-override"}
|
||||
|
||||
var (
|
||||
ErrorNoDroneBuildLink = errors.New("no drone build link")
|
||||
)
|
||||
|
||||
type GitService interface {
|
||||
DeleteRef(ctx context.Context, owner string, repo string, ref string) (*github.Response, error)
|
||||
}
|
||||
|
||||
type LabelsService interface {
|
||||
ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opts *github.ListOptions) ([]*github.Label, *github.Response, error)
|
||||
RemoveLabelForIssue(ctx context.Context, owner string, repo string, number int, label string) (*github.Response, error)
|
||||
AddLabelsToIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*github.Label, *github.Response, error)
|
||||
}
|
||||
|
||||
type CommentService interface {
|
||||
CreateComment(ctx context.Context, owner string, repo string, number int, comment *github.IssueComment) (*github.IssueComment, *github.Response, error)
|
||||
}
|
||||
|
||||
type StatusesService interface {
|
||||
CreateStatus(ctx context.Context, owner, repo, ref string, status *github.RepoStatus) (*github.RepoStatus, *github.Response, error)
|
||||
}
|
||||
|
||||
// NewGitHubClient creates a new Client using the provided GitHub token if not empty.
|
||||
func NewGitHubClient(ctx context.Context, token string) *github.Client {
|
||||
var tc *http.Client
|
||||
if token != "" {
|
||||
ts := oauth2.StaticTokenSource(&oauth2.Token{
|
||||
AccessToken: token,
|
||||
})
|
||||
tc = oauth2.NewClient(ctx, ts)
|
||||
}
|
||||
|
||||
return github.NewClient(tc)
|
||||
}
|
||||
|
||||
func PRCheckRegexp() *regexp.Regexp {
|
||||
reBranch, err := regexp.Compile(`^prc-([0-9]+)-([A-Za-z0-9]+)\/(.+)$`)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to compile regexp: %s", err))
|
||||
}
|
||||
|
||||
return reBranch
|
||||
}
|
||||
|
||||
func AddLabelToPR(ctx context.Context, client LabelsService, prID int, newLabel string) error {
|
||||
// Check existing labels
|
||||
labels, _, err := client.ListLabelsByIssue(ctx, RepoOwner, OSSRepo, prID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
duplicate := false
|
||||
for _, label := range labels {
|
||||
if *label.Name == newLabel {
|
||||
duplicate = true
|
||||
continue
|
||||
}
|
||||
|
||||
// Delete existing "enterprise-xx" labels
|
||||
if stringutil.Contains(EnterpriseCheckLabels, *label.Name) {
|
||||
_, err := client.RemoveLabelForIssue(ctx, RepoOwner, OSSRepo, prID, *label.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if duplicate {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, _, err = client.AddLabelsToIssue(ctx, RepoOwner, OSSRepo, prID, []string{newLabel})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteEnterpriseBranch(ctx context.Context, client GitService, branchName string) error {
|
||||
ref := "heads/" + branchName
|
||||
if _, err := client.DeleteRef(ctx, RepoOwner, EnterpriseRepo, ref); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateEnterpriseStatus sets the status on a commit for the enterprise build check.
|
||||
func CreateEnterpriseStatus(ctx context.Context, client StatusesService, sha, link, status string) (*github.RepoStatus, error) {
|
||||
check, _, err := client.CreateStatus(ctx, RepoOwner, OSSRepo, sha, &github.RepoStatus{
|
||||
Context: github.String(EnterpriseCheckName),
|
||||
Description: github.String(EnterpriseCheckDescription),
|
||||
TargetURL: github.String(link),
|
||||
State: github.String(status),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return check, nil
|
||||
}
|
||||
|
||||
func CreateEnterpriseBuildFailedComment(ctx context.Context, client CommentService, link string, prID int) error {
|
||||
body := fmt.Sprintf("Drone build failed: %s", link)
|
||||
|
||||
_, _, err := client.CreateComment(ctx, RepoOwner, OSSRepo, prID, &github.IssueComment{
|
||||
Body: &body,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package git_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-github/v45/github"
|
||||
"github.com/grafana/grafana/pkg/build/git"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type TestChecksService struct {
|
||||
CreateCheckRunError error
|
||||
}
|
||||
|
||||
func (s *TestChecksService) CreateStatus(ctx context.Context, owner, repo, ref string, status *github.RepoStatus) (*github.RepoStatus, *github.Response, error) {
|
||||
if s.CreateCheckRunError != nil {
|
||||
return nil, nil, s.CreateCheckRunError
|
||||
}
|
||||
|
||||
return &github.RepoStatus{
|
||||
ID: github.Int64(1),
|
||||
URL: status.URL,
|
||||
}, nil, nil
|
||||
}
|
||||
|
||||
func TestCreateEnterpriseRepoStatus(t *testing.T) {
|
||||
t.Run("It should create a repo status", func(t *testing.T) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
client = &TestChecksService{}
|
||||
link = "http://example.com"
|
||||
sha = "1234"
|
||||
)
|
||||
|
||||
_, err := git.CreateEnterpriseStatus(ctx, client, link, sha, "success")
|
||||
|
||||
require.NoError(t, err)
|
||||
})
|
||||
t.Run("It should return an error if GitHub fails to create the status", func(t *testing.T) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
createCheckError = errors.New("create check run error")
|
||||
client = &TestChecksService{
|
||||
CreateCheckRunError: createCheckError,
|
||||
}
|
||||
link = "http://example.com"
|
||||
sha = "1234"
|
||||
)
|
||||
|
||||
_, err := git.CreateEnterpriseStatus(ctx, client, link, sha, "success")
|
||||
require.ErrorIs(t, err, createCheckError)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package git_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-github/v45/github"
|
||||
"github.com/grafana/grafana/pkg/build/git"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type TestLabelsService struct {
|
||||
Labels []*github.Label
|
||||
ListLabelsError error
|
||||
RemoveLabelError error
|
||||
AddLabelsError error
|
||||
}
|
||||
|
||||
func (s *TestLabelsService) ListLabelsByIssue(ctx context.Context, owner string, repo string, number int, opts *github.ListOptions) ([]*github.Label, *github.Response, error) {
|
||||
if s.ListLabelsError != nil {
|
||||
return nil, nil, s.ListLabelsError
|
||||
}
|
||||
|
||||
labels := s.Labels
|
||||
if labels == nil {
|
||||
labels = []*github.Label{}
|
||||
}
|
||||
|
||||
return labels, nil, nil
|
||||
}
|
||||
|
||||
func (s *TestLabelsService) RemoveLabelForIssue(ctx context.Context, owner string, repo string, number int, label string) (*github.Response, error) {
|
||||
if s.RemoveLabelError != nil {
|
||||
return nil, s.RemoveLabelError
|
||||
}
|
||||
|
||||
return &github.Response{}, nil
|
||||
}
|
||||
|
||||
func (s *TestLabelsService) AddLabelsToIssue(ctx context.Context, owner string, repo string, number int, labels []string) ([]*github.Label, *github.Response, error) {
|
||||
if s.AddLabelsError != nil {
|
||||
return nil, nil, s.AddLabelsError
|
||||
}
|
||||
|
||||
l := make([]*github.Label, len(labels))
|
||||
for i, v := range labels {
|
||||
l[i] = &github.Label{
|
||||
Name: github.String(v),
|
||||
}
|
||||
}
|
||||
|
||||
return l, nil, nil
|
||||
}
|
||||
|
||||
func TestAddLabelToPR(t *testing.T) {
|
||||
t.Run("It should add a label to a pull request", func(t *testing.T) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
client = &TestLabelsService{}
|
||||
pr = 20
|
||||
label = "test-label"
|
||||
)
|
||||
|
||||
require.NoError(t, git.AddLabelToPR(ctx, client, pr, label))
|
||||
})
|
||||
t.Run("It should not return an error if the label already exists", func(t *testing.T) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
client = &TestLabelsService{
|
||||
Labels: []*github.Label{
|
||||
{
|
||||
Name: github.String("test-label"),
|
||||
},
|
||||
},
|
||||
}
|
||||
pr = 20
|
||||
label = "test-label"
|
||||
)
|
||||
|
||||
require.NoError(t, git.AddLabelToPR(ctx, client, pr, label))
|
||||
})
|
||||
|
||||
t.Run("It should return an error if GitHub returns an error when listing labels", func(t *testing.T) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
listLabelsError = errors.New("list labels error")
|
||||
client = &TestLabelsService{
|
||||
ListLabelsError: listLabelsError,
|
||||
Labels: []*github.Label{},
|
||||
}
|
||||
pr = 20
|
||||
label = "test-label"
|
||||
)
|
||||
|
||||
require.ErrorIs(t, git.AddLabelToPR(ctx, client, pr, label), listLabelsError)
|
||||
})
|
||||
|
||||
t.Run("It should not return an error if there are existing enterprise-check labels.", func(t *testing.T) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
client = &TestLabelsService{
|
||||
Labels: []*github.Label{
|
||||
{
|
||||
Name: github.String("enterprise-failed"),
|
||||
},
|
||||
},
|
||||
}
|
||||
pr = 20
|
||||
label = "test-label"
|
||||
)
|
||||
|
||||
require.NoError(t, git.AddLabelToPR(ctx, client, pr, label))
|
||||
})
|
||||
|
||||
t.Run("It should return an error if GitHub returns an error when removing existing enterprise-check labels", func(t *testing.T) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
removeLabelError = errors.New("remove label error")
|
||||
client = &TestLabelsService{
|
||||
RemoveLabelError: removeLabelError,
|
||||
Labels: []*github.Label{
|
||||
{
|
||||
Name: github.String("enterprise-failed"),
|
||||
},
|
||||
},
|
||||
}
|
||||
pr = 20
|
||||
label = "test-label"
|
||||
)
|
||||
|
||||
require.ErrorIs(t, git.AddLabelToPR(ctx, client, pr, label), removeLabelError)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package git_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/build/git"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPRCheckRegexp(t *testing.T) {
|
||||
type match struct {
|
||||
String string
|
||||
Commit string
|
||||
Branch string
|
||||
PR string
|
||||
}
|
||||
|
||||
var (
|
||||
shouldMatch = []match{
|
||||
{
|
||||
String: "prc-1-a1b2c3d4/branch-name",
|
||||
Branch: "branch-name",
|
||||
Commit: "a1b2c3d4",
|
||||
PR: "1",
|
||||
},
|
||||
{
|
||||
String: "prc-111-a1b2c3d4/branch/name",
|
||||
Branch: "branch/name",
|
||||
Commit: "a1b2c3d4",
|
||||
PR: "111",
|
||||
},
|
||||
{
|
||||
String: "prc-102930122-a1b2c3d4/branch-name",
|
||||
Branch: "branch-name",
|
||||
Commit: "a1b2c3d4",
|
||||
PR: "102930122",
|
||||
},
|
||||
}
|
||||
|
||||
shouldNotMatch = []string{"prc-a/branch", "km/test", "test", "prc", "prc/test", "price"}
|
||||
)
|
||||
|
||||
regex := git.PRCheckRegexp()
|
||||
|
||||
for _, v := range shouldMatch {
|
||||
assert.Truef(t, regex.MatchString(v.String), "regex '%s' should match %s", regex.String(), v)
|
||||
m := regex.FindStringSubmatch(v.String)
|
||||
assert.Equal(t, m[1], v.PR)
|
||||
assert.Equal(t, m[2], v.Commit)
|
||||
assert.Equal(t, m[3], v.Branch)
|
||||
}
|
||||
|
||||
for _, v := range shouldNotMatch {
|
||||
assert.False(t, regex.MatchString(v), "regex '%s' should not match %s", regex.String(), v)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user