Skip to content

Commit

Permalink
Configure E2E test setup on PAC for bitbucket server
Browse files Browse the repository at this point in the history
configured e2e test for bitbucket server on PAC and
wrote one test for pull request.

https://issues.redhat.com/browse/SRVKP-6758

Signed-off-by: Zaki Shaikh <[email protected]>
  • Loading branch information
zakisk committed Nov 12, 2024
1 parent 5ae9bba commit a8e8e31
Show file tree
Hide file tree
Showing 57 changed files with 63,951 additions and 1 deletion.
5 changes: 4 additions & 1 deletion .github/workflows/kind-e2e-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,10 @@ jobs:
"${{ secrets.INSTALLATION_ID }}" \
"${{ secrets.GH_APPS_TOKEN }}" \
"${{ secrets.TEST_GITHUB_SECOND_TOKEN }}" \
"${{ secrets.GITLAB_TOKEN }}"
"${{ secrets.GITLAB_TOKEN }}" \
"${{ secrets.BITBUCKET_SERVER_TOKEN }}" \
"${{ secrets.BITBUCKET_SERVER_API_URL }}" \
"${{ secrets.BITBUCKET_SERVER_WEBHOOK_SECRET }}"
- name: Run E2E Tests on nightly
if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }}
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ require (
code.gitea.io/gitea v1.22.1
code.gitea.io/sdk/gitea v0.19.0
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/antihax/optional v1.0.0
github.com/bradleyfalzon/ghinstallation/v2 v2.11.0
github.com/cloudevents/sdk-go/v2 v2.15.2
github.com/fvbommel/sortorder v1.1.0
github.com/gdasson/bitbucketv1go v1.0.0
github.com/gfleury/go-bitbucket-v1 v0.0.0-20240822132758-a3031aa024b4
github.com/gobwas/glob v0.2.3
github.com/google/cel-go v0.21.0
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,7 @@ github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8V
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves=
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
Expand Down Expand Up @@ -730,6 +731,8 @@ github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQ
github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/gdasson/bitbucketv1go v1.0.0 h1:sRiO7XgqY4WaolHruzPufPLRODfSUGUVkWLDHy4Ba5M=
github.com/gdasson/bitbucketv1go v1.0.0/go.mod h1:VKmMS4gxRLRBKoyzNVYc7P+crDC7/UQ97+mVc6OqE34=
github.com/gfleury/go-bitbucket-v1 v0.0.0-20240822132758-a3031aa024b4 h1:sRZ/hpZOEfU+/05QFOt6nRE+OAFWCP0x+qz+inrcbkw=
github.com/gfleury/go-bitbucket-v1 v0.0.0-20240822132758-a3031aa024b4/go.mod h1:bB7XwdZF40tLVnu9n5A9TjI2ddNZtLYImtwYwmcmnRo=
github.com/gfleury/go-bitbucket-v1/test/bb-mock-server v0.0.0-20230825095122-9bc1711434ab h1:BeG9dDWckFi/p5Gvqq3wTEDXsUV4G6bdvjEHMOT2B8E=
Expand Down
9 changes: 9 additions & 0 deletions hack/gh-workflow-ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ run_e2e_tests() {
gh_apps_token="${5}"
test_github_second_token="${6}"
gitlab_token="${7}"
bitbucket_server_token="${8}"
bitbucket_server_api_url="${9}"
bitbucket_server_webhook_secret="${10}"

# Nothing specific to webhook here it just that repo is private in that org and that's what we want to test
export TEST_GITHUB_PRIVATE_TASK_URL="https://github.com/openshift-pipelines/pipelines-as-code-e2e-tests-private/blob/main/remote_task.yaml"
Expand Down Expand Up @@ -112,6 +115,12 @@ run_e2e_tests() {
export TEST_GITLAB_PROJECT_ID="34405323"
export TEST_GITLAB_TOKEN=${gitlab_token}
# https://gitlab.com/gitlab-com/alliances/ibm-red-hat/sandbox/openshift-pipelines/pac-e2e-tests

export TEST_BITBUCKET_SERVER_TOKEN=${bitbucket_server_token}
export TEST_BITBUCKET_SERVER_API_URL=${bitbucket_server_api_url}
export TEST_BITBUCKET_SERVER_WEBHOOK_SECRET=${bitbucket_server_webhook_secret}
export TEST_BITBUCKET_SERVER_USER="pipelines"
export TEST_BITBUCKET_SERVER_E2E_REPOSITORY="PAC/pac-e2e-tests"
make test-e2e
}

Expand Down
53 changes: 53 additions & 0 deletions test/bitbucket_server_pull_request_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//go:build e2e
// +build e2e

package test

import (
"context"
"fmt"
"testing"

"github.com/openshift-pipelines/pipelines-as-code/pkg/params/triggertype"
tbbs "github.com/openshift-pipelines/pipelines-as-code/test/pkg/bitbucketserver"
"github.com/openshift-pipelines/pipelines-as-code/test/pkg/wait"

"github.com/tektoncd/pipeline/pkg/names"
"gotest.tools/v3/assert"
)

func TestBitbucketServerPullRequest(t *testing.T) {
targetNS := names.SimpleNameGenerator.RestrictLengthWithRandomSuffix("pac-e2e-ns")
ctx := context.Background()

ctx, runcnx, opts, provider, restClient, err := tbbs.Setup(ctx)
assert.NilError(t, err)

repo := tbbs.CreateCRD(ctx, t, provider, runcnx, opts, targetNS)
defer tbbs.TearDownNs(ctx, t, runcnx, targetNS)

title := "TestPullRequest - " + targetNS
numberOfFiles := 5
files := map[string]string{}
for i := range numberOfFiles {
files[fmt.Sprintf("pipelinerun-%d.yaml", i)] = "testdata/pipelinerun.yaml"
}

pr, commits := tbbs.CreatePR(ctx, t, restClient, *repo, runcnx, opts, files, title, targetNS)
assert.Assert(t, numberOfFiles == len(commits))
runcnx.Clients.Log.Infof("Pull Request with title '%s' is created", pr.Title)
defer tbbs.TearDownBranch(ctx, t, runcnx, provider, restClient, opts, pr.Id, targetNS)

successOpts := wait.SuccessOpt{
TargetNS: targetNS,
OnEvent: triggertype.PullRequest.String(),
NumberofPRMatch: 5,
Title: commits[0].Message,
MinNumberStatus: 5,
}
wait.Succeeded(ctx, t, runcnx, opts, successOpts)
}

// Local Variables:
// compile-command: "go test -tags=e2e -v -run TestBitbucketServerPullRequest$ ."
// End:
70 changes: 70 additions & 0 deletions test/pkg/bitbucketserver/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package bitbucketserver

import (
"bytes"
"context"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
)

func callAPI(ctx context.Context, endpointURL, method string, fields map[string]string) ([]byte, error) {
req, err := createRequest(ctx, endpointURL, method, fields)
if err != nil {
return nil, err
}

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("error sending request: %w", err)
}
defer resp.Body.Close()

if resp.StatusCode > 300 {
return nil, fmt.Errorf("error status code: %d", resp.StatusCode)
}

responseBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("error reading response: %w", err)
}

return responseBody, nil
}

func createRequest(ctx context.Context, endpointURL, method string, fields map[string]string) (*http.Request, error) {
var requestBody bytes.Buffer
writer := multipart.NewWriter(&requestBody)

if len(fields) > 0 {
for field, value := range fields {
err := writer.WriteField(field, value)
if err != nil {
return nil, fmt.Errorf("error writing field %s to multipart data: %w", field, err)
}
}

err := writer.Close()
if err != nil {
return nil, fmt.Errorf("error closing writer: %w", err)
}
}

req, err := http.NewRequestWithContext(ctx, method, endpointURL, &requestBody)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}

if len(fields) > 0 {
req.Header.Set("Content-Type", writer.FormDataContentType())
}

bitbucketServerUser := os.Getenv("TEST_BITBUCKET_SERVER_USER")
bitbucketServerToken := os.Getenv("TEST_BITBUCKET_SERVER_TOKEN")
req.SetBasicAuth(bitbucketServerUser, bitbucketServerToken)

return req, nil
}
69 changes: 69 additions & 0 deletions test/pkg/bitbucketserver/crd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package bitbucketserver

import (
"context"
"encoding/json"
"os"
"strings"
"testing"

"github.com/openshift-pipelines/pipelines-as-code/pkg/apis/pipelinesascode/v1alpha1"
"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
"github.com/openshift-pipelines/pipelines-as-code/pkg/provider/bitbucketserver"
"github.com/openshift-pipelines/pipelines-as-code/test/pkg/options"
pacrepo "github.com/openshift-pipelines/pipelines-as-code/test/pkg/repository"
"github.com/openshift-pipelines/pipelines-as-code/test/pkg/secret"

bbv1 "github.com/gfleury/go-bitbucket-v1"
"gotest.tools/v3/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func CreateCRD(ctx context.Context, t *testing.T, bprovider bitbucketserver.Provider, run *params.Run, opts options.E2E, targetNS string) *bbv1.Repository {
resp, err := bprovider.Client.DefaultApi.GetRepository(opts.Organization, opts.Repo)
assert.NilError(t, err)

body, err := json.Marshal(resp.Values)
assert.NilError(t, err)
repo := &bbv1.Repository{}
err = json.Unmarshal(body, repo)
assert.NilError(t, err)

url := strings.ReplaceAll(repo.Links.Self[0].Href, "/browse", "")
repository := &v1alpha1.Repository{
ObjectMeta: metav1.ObjectMeta{
Name: targetNS,
},
Spec: v1alpha1.RepositorySpec{
URL: url,
},
}

err = pacrepo.CreateNS(ctx, targetNS, run)
assert.NilError(t, err)
run.Clients.Log.Infof("Namespace %s is created", targetNS)

token, _ := os.LookupEnv("TEST_BITBUCKET_SERVER_TOKEN")
apiURL, _ := os.LookupEnv("TEST_BITBUCKET_SERVER_API_URL")
apiUser, _ := os.LookupEnv("TEST_BITBUCKET_SERVER_USER")
webhookSecret := os.Getenv("TEST_BITBUCKET_SERVER_WEBHOOK_SECRET")
secretName := "bitbucket-server-webhook-config"
err = secret.Create(ctx, run, map[string]string{
"provider.token": token,
"webhook.secret": webhookSecret,
}, targetNS, secretName)
assert.NilError(t, err)
run.Clients.Log.Infof("PipelinesAsCode Secret %s is created", secretName)

repository.Spec.GitProvider = &v1alpha1.GitProvider{
URL: apiURL,
User: apiUser,
Secret: &v1alpha1.Secret{Name: secretName},
WebhookSecret: &v1alpha1.Secret{Name: secretName},
}

err = pacrepo.CreateRepo(ctx, targetNS, run, repository)
assert.NilError(t, err)

return repo
}
82 changes: 82 additions & 0 deletions test/pkg/bitbucketserver/pr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package bitbucketserver

import (
"context"
"encoding/json"
"fmt"
"net/http"
"os"
"testing"

"github.com/openshift-pipelines/pipelines-as-code/pkg/params"
"github.com/openshift-pipelines/pipelines-as-code/pkg/params/triggertype"
"github.com/openshift-pipelines/pipelines-as-code/test/pkg/options"
"github.com/openshift-pipelines/pipelines-as-code/test/pkg/payload"

"github.com/antihax/optional"
bbrest "github.com/gdasson/bitbucketv1go"
bbv1 "github.com/gfleury/go-bitbucket-v1"
"gotest.tools/v3/assert"
)

func CreatePR(ctx context.Context, t *testing.T, restClient *bbrest.APIClient, repo bbv1.Repository, runcnx *params.Run, opts options.E2E, files map[string]string, title, targetNS string) (bbrest.RestPullRequest, []*bbrest.RestCommit) {
mainBranchRef := "refs/heads/main"
branchCreateRequest := bbrest.RestBranchCreateRequest{Name: targetNS, StartPoint: mainBranchRef}
branch, resp, err := restClient.RepositoryApi.CreateBranch(ctx, branchCreateRequest, opts.Organization, opts.Repo)
assert.NilError(t, err)
defer resp.Body.Close()
runcnx.Clients.Log.Infof("Branch %s is created", branch.Id)

files, err = payload.GetEntries(files, targetNS, options.MainBranch, triggertype.PullRequest.String(), map[string]string{})
assert.NilError(t, err)
commits, err := pushFilesToBranch(ctx, runcnx, opts, targetNS, files)
assert.NilError(t, err)

prCreateOpts := &bbrest.PullRequestsApiCreateOpts{Body: optional.NewInterface(map[string]interface{}{
"title": title,
"description": "Test PAC on bitbucket server",
"fromRef": bbv1.PullRequestRef{ID: branch.Id, Repository: repo},
"toRef": bbv1.PullRequestRef{ID: mainBranchRef, Repository: repo},
"closed": false,
})}
pr, resp, err := restClient.PullRequestsApi.Create(ctx, opts.Organization, opts.Repo, prCreateOpts)
assert.NilError(t, err)
defer resp.Body.Close()

return pr, commits
}

// pushFilesToBranch pushes multiple files to bitbucket server repo because
// bitbucket server doesn't support uploading multiple files in an API call.
// reference: https://community.developer.atlassian.com/t/rest-api-to-update-multiple-files/28731/2
func pushFilesToBranch(ctx context.Context, run *params.Run, opts options.E2E, branchName string, files map[string]string) ([]*bbrest.RestCommit, error) {
if len(files) == 0 {
return nil, fmt.Errorf("no file to commit")
}

commits := make([]*bbrest.RestCommit, 0, len(files))
apiURL := os.Getenv("TEST_BITBUCKET_SERVER_API_URL")
for file, content := range files {
endpointURL := fmt.Sprintf("%s/api/latest/projects/%s/repos/%s/browse/.tekton/%s", apiURL, opts.Organization, opts.Repo, file)
fields := map[string]string{
"branch": branchName,
"content": content,
"message": "test commit Signed-off-by: Zaki Shaikh <[email protected]>",
}

response, err := callAPI(ctx, endpointURL, http.MethodPut, fields)
if err != nil {
return nil, err
}

var tmpCommit bbrest.RestCommit
err = json.Unmarshal(response, &tmpCommit)
if err != nil {
return nil, fmt.Errorf("error unmarshaling response: %w", err)
}
commits = append(commits, &tmpCommit)
}
run.Clients.Log.Infof("%d files committed to branch %s", len(files), branchName)

return commits, nil
}
Loading

0 comments on commit a8e8e31

Please sign in to comment.