diff --git a/pkg/clients/common/controller.go b/pkg/clients/common/controller.go index 95376528e1..48afb08e71 100644 --- a/pkg/clients/common/controller.go +++ b/pkg/clients/common/controller.go @@ -3,6 +3,7 @@ package common import ( "fmt" + "github.com/konflux-ci/e2e-tests/pkg/clients/git" "github.com/konflux-ci/e2e-tests/pkg/clients/github" "github.com/konflux-ci/e2e-tests/pkg/clients/gitlab" kubeCl "github.com/konflux-ci/e2e-tests/pkg/clients/kubernetes" @@ -15,6 +16,7 @@ type SuiteController struct { // Wrap K8S client go to interact with Kube cluster *kubeCl.CustomClient + Git git.Client // Github client to interact with GH apis Github *github.Github Gitlab *gitlab.GitlabClient @@ -36,8 +38,8 @@ func NewSuiteController(kubeC *kubeCl.CustomClient) (*SuiteController, error) { } return &SuiteController{ - kubeC, - gh, - gl, + CustomClient: kubeC, + Github: gh, + Gitlab: gl, }, nil } diff --git a/pkg/clients/git/git.go b/pkg/clients/git/git.go new file mode 100644 index 0000000000..cf0d239703 --- /dev/null +++ b/pkg/clients/git/git.go @@ -0,0 +1,34 @@ +package git + +// GitProvider is an enum representing possible Git providers +type GitProvider int + +const ( + GitHubProvider GitProvider = iota + GitLabProvider +) + +// PullRequest represents a generic provider-agnostic pull/merge request +type PullRequest struct { + Number int + // SourceBranch includes the changes made in the pull request + SourceBranch string + // TargetBranch is the base branch on top of which will the changes be merged + TargetBranch string + // MergeCommitSHA is the revision of the commit which merged the PullRequest + MergeCommitSHA string + // HeadSHA is the revision of the commit that is on top of the SourceBranch + HeadSHA string +} + +type Client interface { + CreateBranch(repository, baseBranchName, revision, branchName string) error + DeleteBranch(repository, branchName string) error + BranchExists(repository, branchName string) (bool, error) + ListPullRequests(repository string) ([]*PullRequest, error) + CreateFile(repository, pathToFile, content, branchName string) error + GetFileContent(repository, pathToFile, branchName string) (string, error) + CreatePullRequest(repository, title, body, head, base string) (*PullRequest, error) + MergePullRequest(repository string, prNumber int) (*PullRequest, error) + CleanupWebhooks(repository, clusterAppDomain string) error +} diff --git a/pkg/clients/git/github.go b/pkg/clients/git/github.go new file mode 100644 index 0000000000..6187ef003b --- /dev/null +++ b/pkg/clients/git/github.go @@ -0,0 +1,105 @@ +package git + +import ( + "fmt" + "strings" + + "github.com/konflux-ci/e2e-tests/pkg/clients/github" +) + +type GitHubClient struct { + *github.Github +} + +func NewGitHubClient(gh *github.Github) *GitHubClient { + return &GitHubClient{gh} +} + +func (g *GitHubClient) CreateBranch(repository, baseBranchName, revision, branchName string) error { + return g.CreateRef(repository, baseBranchName, revision, branchName) +} + +func (g *GitHubClient) DeleteBranch(repository, branchName string) error { + return g.DeleteRef(repository, branchName) +} + +func (g *GitHubClient) BranchExists(repository, branchName string) (bool, error) { + return g.ExistsRef(repository, branchName) +} + +func (g *GitHubClient) ListPullRequests(repository string) ([]*PullRequest, error) { + prs, err := g.Github.ListPullRequests(repository) + if err != nil { + return nil, err + } + var pullRequests []*PullRequest + for _, pr := range prs { + pullRequests = append(pullRequests, &PullRequest{ + Number: pr.GetNumber(), + SourceBranch: pr.Head.GetRef(), + TargetBranch: pr.Base.GetRef(), + HeadSHA: pr.Head.GetSHA(), + }) + } + return pullRequests, nil +} + +func (g *GitHubClient) CreateFile(repository, pathToFile, content, branchName string) error { + _, err := g.Github.CreateFile(repository, pathToFile, content, branchName) + return err +} + +func (g *GitHubClient) GetFileContent(repository, pathToFile, branchName string) (string, error) { + contents, err := g.Github.GetFile(repository, pathToFile, branchName) + if err != nil { + return "", err + } + content, err := contents.GetContent() + if err != nil { + return "", err + } + return content, nil +} + +func (g *GitHubClient) MergePullRequest(repository string, prNumber int) (*PullRequest, error) { + mergeResult, err := g.Github.MergePullRequest(repository, prNumber) + if err != nil { + return nil, err + } + return &PullRequest{ + Number: prNumber, + MergeCommitSHA: mergeResult.GetSHA(), + }, nil +} + +func (g *GitHubClient) CreatePullRequest(repository, title, body, head, base string) (*PullRequest, error) { + pr, err := g.Github.CreatePullRequest(repository, title, body, head, base) + if err != nil { + return nil, err + } + return &PullRequest{ + Number: pr.GetNumber(), + SourceBranch: pr.Head.GetRef(), + TargetBranch: pr.Base.GetRef(), + HeadSHA: pr.Head.GetSHA(), + }, nil +} + +func (g *GitHubClient) CleanupWebhooks(repository, clusterAppDomain string) error { + hooks, err := g.Github.ListRepoWebhooks(repository) + if err != nil { + return err + } + for _, h := range hooks { + hookUrl := h.Config["url"].(string) + if strings.Contains(hookUrl, clusterAppDomain) { + fmt.Printf("removing webhook URL: %s\n", hookUrl) + err = g.Github.DeleteWebhook(repository, h.GetID()) + if err != nil { + return err + } + break + } + } + return nil +} diff --git a/pkg/clients/git/gitlab.go b/pkg/clients/git/gitlab.go new file mode 100644 index 0000000000..b5f77b9288 --- /dev/null +++ b/pkg/clients/git/gitlab.go @@ -0,0 +1,97 @@ +package git + +import ( + "encoding/base64" + + gitlab2 "github.com/xanzy/go-gitlab" + + "github.com/konflux-ci/e2e-tests/pkg/clients/gitlab" +) + +type GitLabClient struct { + *gitlab.GitlabClient +} + +func NewGitlabClient(gl *gitlab.GitlabClient) *GitLabClient { + return &GitLabClient{gl} +} + +func (g *GitLabClient) CreateBranch(repository, baseBranchName, _, branchName string) error { + return g.GitlabClient.CreateBranch(repository, branchName, baseBranchName) +} + +func (g *GitLabClient) BranchExists(repository, branchName string) (bool, error) { + return g.ExistsBranch(repository, branchName) +} + +func (g *GitLabClient) ListPullRequests(string) ([]*PullRequest, error) { + mrs, err := g.GetMergeRequests() + if err != nil { + return nil, err + } + var pullRequests []*PullRequest + for _, mr := range mrs { + pullRequests = append(pullRequests, &PullRequest{ + Number: mr.IID, + SourceBranch: mr.SourceBranch, + TargetBranch: mr.TargetBranch, + HeadSHA: mr.SHA, + }) + } + return pullRequests, nil +} + +func (g *GitLabClient) CreateFile(repository, pathToFile, content, branchName string) error { + _, err := g.GitlabClient.CreateFile(repository, pathToFile, content, branchName) + return err +} + +func (g *GitLabClient) GetFileContent(repository, pathToFile, branchName string) (string, error) { + opts := gitlab2.GetFileOptions{Ref: gitlab2.Ptr(branchName)} + file, _, err := g.GitlabClient.GetClient().RepositoryFiles.GetFile(repository, pathToFile, &opts) + if err != nil { + return "", err + } + decoded, err := base64.StdEncoding.DecodeString(file.Content) + if err != nil { + return "", err + } + return string(decoded), nil +} + +func (g *GitLabClient) MergePullRequest(repository string, prNumber int) (*PullRequest, error) { + mr, err := g.AcceptMergeRequest(repository, prNumber) + if err != nil { + return nil, err + } + return &PullRequest{ + Number: mr.IID, + SourceBranch: mr.SourceBranch, + TargetBranch: mr.TargetBranch, + HeadSHA: mr.SHA, + MergeCommitSHA: mr.MergeCommitSHA, + }, nil +} + +func (g *GitLabClient) CreatePullRequest(repository, title, body, head, base string) (*PullRequest, error) { + opts := gitlab2.CreateMergeRequestOptions{ + Title: gitlab2.Ptr(title), + Description: gitlab2.Ptr(body), + SourceBranch: gitlab2.Ptr(head), + TargetBranch: gitlab2.Ptr(base), + } + mr, _, err := g.GitlabClient.GetClient().MergeRequests.CreateMergeRequest(repository, &opts) + if err != nil { + return nil, err + } + return &PullRequest{ + Number: mr.IID, + SourceBranch: mr.SourceBranch, + TargetBranch: mr.TargetBranch, + HeadSHA: mr.SHA, + }, nil +} + +func (g *GitLabClient) CleanupWebhooks(repository, clusterAppDomain string) error { + return g.DeleteWebhooks(repository, clusterAppDomain) +} diff --git a/pkg/utils/build/git.go b/pkg/utils/build/git.go index 92a3f3ae1f..3d881f1a34 100644 --- a/pkg/utils/build/git.go +++ b/pkg/utils/build/git.go @@ -2,11 +2,12 @@ package build import ( "fmt" - "k8s.io/api/core/v1" "os" "strconv" "strings" + "k8s.io/api/core/v1" + "github.com/konflux-ci/e2e-tests/pkg/clients/github" "github.com/konflux-ci/e2e-tests/pkg/constants" "github.com/konflux-ci/e2e-tests/pkg/framework"