diff --git a/e2e/README.md b/e2e/README.md index a4adee343..83348de9b 100644 --- a/e2e/README.md +++ b/e2e/README.md @@ -5,8 +5,10 @@ End-to-end test suite for TSF (Trusted Software Factory) instances. ## Prerequisites - **KUBECONFIG** pointing to a cluster with TSF installed -- **GitHub org** with a fork/clone of [konflux-ci/testrepo](https://github.com/konflux-ci/testrepo) -- **GitHub token** (PAT) with repo access to the org above +- **Git hosting** for the component under test (set **`GIT_PROVIDER`** to **`gitlab`** or **`gl`** for GitLab; use **`github`** or leave unset for GitHub — unknown values **fail fast** so you do not silently run the GitHub path): + - **GitHub** (default): org with a fork or clone of [konflux-ci/testrepo](https://github.com/konflux-ci/testrepo), or your own repo; set `MY_GITHUB_ORG` and optionally `MY_GITHUB_REPO` (defaults to `testrepo`). + - **GitLab**: set `GIT_PROVIDER=gitlab`, `MY_GITLAB_PROJECT_PATH` (URL path only, e.g. `group/subgroup/repo` on GitLab.com, not a numeric project id), and `GITLAB_BOT_TOKEN` or `GITLAB_TOKEN`. Optional `GITLAB_DEFAULT_BRANCH` defaults to `main`. **`GITLAB_SOURCE_REVISION` is optional**: if unset, the test creates the base branch from the **latest commit on the default branch** (use this when your GitLab copy does not contain the same commit SHA as the GitHub `GITHUB_SOURCE_REVISION` default). If set, it must be a commit that exists in the GitLab project. Optional `GITLAB_BASE_URL` defaults to `https://gitlab.com`; if `GITLAB_API_URL` is unset, the test derives `GITLAB_BASE_URL/api/v4` before the framework starts (override `GITLAB_API_URL` if your instance needs a different API base). +- **Token** with permission to manage the chosen repo (GitHub: `GITHUB_TOKEN`; GitLab: see above). For **GitLab PaC**, the test creates **`pipelines-as-code-secret`** ( **`password`** + **`provider.token`** only) in the applications namespace when absent; after the **component** exists, Konflux writes **`pipelines-as-code-webhooks-secret`**, and the test copies **`webhook.secret`** from the data key **`KonfluxPACWebhookSecretDataKey(GitSource.URL)`** (same rule as konflux build-service, e.g. `https___gitlab.com_group_repo` for `https://gitlab.com/group/repo.git`). The GitLab project hook token is **only** that value—no fallbacks. Ensure `GIT_PROVIDER=gitlab` is set—timeouts mentioning only short repo name `testrepo` usually mean the **GitHub** code path (default provider), not GitLab. - **Quay org** accessible by the TSF instance's image-controller ## IDE Setup diff --git a/e2e/go.mod b/e2e/go.mod index 419024928..89cf7b353 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -4,16 +4,15 @@ go 1.25.0 require ( github.com/devfile/library/v2 v2.2.1-0.20230418160146-e75481b7eebd - github.com/google/go-github/v44 v44.1.0 github.com/konflux-ci/application-api v0.0.0-20251210122215-555a927cf6d9 github.com/konflux-ci/build-service v0.0.0-20240611083846-2dee6cfe6fe4 github.com/konflux-ci/e2e-tests v0.0.0-00010101000000-000000000000 - github.com/konflux-ci/image-controller v0.0.0-20240530145826-3296e4996f6f github.com/konflux-ci/integration-service v0.0.0-20260108133201-e2f5559a9544 github.com/konflux-ci/release-service v0.0.0-20260113075649-fff62d349fa9 github.com/onsi/ginkgo/v2 v2.27.4 github.com/onsi/gomega v1.39.0 github.com/tektoncd/pipeline v1.9.2 + github.com/xanzy/go-gitlab v0.114.0 k8s.io/api v0.35.1 k8s.io/apimachinery v0.35.1 k8s.io/klog/v2 v2.130.1 @@ -106,6 +105,7 @@ require ( github.com/google/gnostic-models v0.7.1 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-containerregistry v0.20.7 // indirect + github.com/google/go-github/v44 v44.1.0 // indirect github.com/google/go-github/v45 v45.2.0 // indirect github.com/google/go-github/v75 v75.0.0 // indirect github.com/google/go-querystring v1.2.0 // indirect @@ -127,6 +127,7 @@ require ( github.com/kevinburke/ssh_config v1.4.0 // indirect github.com/klauspost/compress v1.18.1 // indirect github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/konflux-ci/image-controller v0.0.0-20240530145826-3296e4996f6f // indirect github.com/konflux-ci/operator-toolkit v0.0.0-20251118152634-b4f41f073069 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/magefile/mage v1.14.0 // indirect @@ -179,7 +180,6 @@ require ( github.com/tektoncd/cli v0.43.0 // indirect github.com/vbatts/tar-split v0.12.2 // indirect github.com/x448/float16 v0.8.4 // indirect - github.com/xanzy/go-gitlab v0.114.0 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xlab/treeprint v1.2.0 // indirect go.opencensus.io v0.24.0 // indirect diff --git a/e2e/my-test.env.template b/e2e/my-test.env.template index 8c60de29b..236f867d3 100644 --- a/e2e/my-test.env.template +++ b/e2e/my-test.env.template @@ -1,12 +1,37 @@ # Required export KUBECONFIG=~/.kube/config +export E2E_APPLICATIONS_NAMESPACE=default-tenant # Use a specific namespace instead of generating one + +# Git provider: omit or "github" for GitHub; "gitlab" or "gl" for GitLab (other values error out) +# export GIT_PROVIDER=github + +# --- GitHub (when GIT_PROVIDER is unset or github) --- export GITHUB_TOKEN= export MY_GITHUB_ORG= -export E2E_APPLICATIONS_NAMESPACE=default-tenant # Use a specific namespace instead of generating one +export MY_GITHUB_REPO=testrepo +# export GITHUB_SOURCE_REVISION=1255dc36534b9db7b99efbc281117435ea03255f + +# Names must match setup-release.sh (-a / -c / -m); release flow expects these to exist export TSF_APPLICATION_NAME=tsf-demo-app # Must match what setup-release.sh was called with export TSF_COMPONENT_NAME=tsf-demo-comp # Must match what setup-release.sh was called with export TSF_MANAGED_NAMESPACE=default-managed-tenant # Must match what setup-release.sh was called with +# --- GitLab (when GIT_PROVIDER=gitlab) --- +# Requires: export GIT_PROVIDER=gitlab +# The test creates pipelines-as-code-secret in your tenant namespace if missing (PaC needs it to push konflux-* branches). +# export GITLAB_BASE_URL=https://gitlab.com +# export MY_GITLAB_PROJECT_PATH=my-group/my-testrepo +# export GITLAB_DEFAULT_BRANCH=main +# Optional: commit SHA to branch from. Leave unset to use the latest commit on GITLAB_DEFAULT_BRANCH +# (recommended if your GitLab repo does not contain the GitHub GITHUB_SOURCE_REVISION SHA). +# export GITLAB_SOURCE_REVISION= +# Token: konflux e2e-tests reads GITLAB_BOT_TOKEN; optional alias: +# export GITLAB_BOT_TOKEN= +# export GITLAB_TOKEN= +# After the component is created, webhook material is read only from pipelines-as-code-webhooks-secret +# (tenant namespace), using the Konflux data key derived from the component Git clone URL. +# If GITLAB_API_URL is unset, it defaults to ${GITLAB_BASE_URL}/api/v4 (set explicitly for unusual layouts) + # Optional # export E2E_SKIP_CLEANUP=true # Keep test resources after run (useful for debugging) # export SKIP_PAC_TESTS=true # Skip the entire test diff --git a/e2e/tests/tsf/git-providers/env.go b/e2e/tests/tsf/git-providers/env.go new file mode 100644 index 000000000..24aacd2c1 --- /dev/null +++ b/e2e/tests/tsf/git-providers/env.go @@ -0,0 +1,150 @@ +package gitproviders + +import ( + "fmt" + "net/url" + "os" + "strings" + + "github.com/konflux-ci/e2e-tests/pkg/constants" +) + +// Environment variable names for TSF demo e2e (in addition to konflux e2e-tests vars). +const ( + EnvGitProvider = "GIT_PROVIDER" + EnvMyGithubRepo = "MY_GITHUB_REPO" + EnvGithubSourceRevision = "GITHUB_SOURCE_REVISION" + EnvGitlabBaseURL = "GITLAB_BASE_URL" + EnvMyGitlabProjectPath = "MY_GITLAB_PROJECT_PATH" + EnvGitlabSourceRevision = "GITLAB_SOURCE_REVISION" + EnvGitlabDefaultBranch = "GITLAB_DEFAULT_BRANCH" + EnvGitlabTokenAlias = "GITLAB_TOKEN" // copied to GITLAB_BOT_TOKEN before framework init if needed + defaultGithubRepo = "testrepo" + defaultGitlabBaseURL = "https://gitlab.com" + defaultGitlabBranch = "main" + defaultGithubSrcRevision = "1255dc36534b9db7b99efbc281117435ea03255f" +) + +// Kind selects which SCM API the demo test uses. +type Kind string + +const ( + KindGitHub Kind = "github" + KindGitLab Kind = "gitlab" +) + +// ParseGitProvider returns KindGitHub when raw is empty. +// Accepted non-empty values: github, gitlab, gl (case-insensitive, UTF-8 BOM trimmed). +// Any other value returns an error so typos do not silently use GitHub while you expect GitLab. +func ParseGitProvider(raw string) (Kind, error) { + s := strings.TrimPrefix(strings.TrimSpace(raw), "\ufeff") + if s == "" { + return KindGitHub, nil + } + switch strings.ToLower(s) { + case string(KindGitHub): + return KindGitHub, nil + case string(KindGitLab), "gl": + return KindGitLab, nil + default: + return KindGitHub, fmt.Errorf("%s=%q is invalid: use github, gitlab, or gl (omit for github)", EnvGitProvider, raw) + } +} + +// PrepareProcessEnvForGitLab sets konflux framework variables from TSF-friendly +// aliases before framework.NewFramework. Call only when Kind == KindGitLab. +func PrepareProcessEnvForGitLab() { + if os.Getenv(constants.GITLAB_BOT_TOKEN_ENV) == "" { + if t := strings.TrimSpace(os.Getenv(EnvGitlabTokenAlias)); t != "" { + _ = os.Setenv(constants.GITLAB_BOT_TOKEN_ENV, t) + } + } + if strings.TrimSpace(os.Getenv(constants.GITLAB_API_URL_ENV)) == "" { + base := normalizedGitlabOriginURL(os.Getenv(EnvGitlabBaseURL)) + _ = os.Setenv(constants.GITLAB_API_URL_ENV, strings.TrimSuffix(base, "/")+"/api/v4") + } +} + +// normalizedGitlabOriginURL returns a URL with scheme suitable for joining paths (e.g. https://gitlab.com). +func normalizedGitlabOriginURL(raw string) string { + base := strings.TrimSuffix(strings.TrimSpace(raw), "/") + if base == "" { + base = defaultGitlabBaseURL + } + if !strings.HasPrefix(base, "http://") && !strings.HasPrefix(base, "https://") { + base = "https://" + base + } + return base +} + +// GitlabHostForSCMLabel returns the hostname from GITLAB_BASE_URL for appstudio.redhat.com/scm.host (must match clone URL host). +func GitlabHostForSCMLabel() (string, error) { + u, err := url.Parse(normalizedGitlabOriginURL(os.Getenv(EnvGitlabBaseURL))) + if err != nil { + return "", fmt.Errorf("parse GITLAB_BASE_URL: %w", err) + } + h := u.Hostname() + if h == "" { + return "", fmt.Errorf("GITLAB_BASE_URL has no host (set e.g. https://gitlab.com)") + } + return h, nil +} + +// GithubComponentURL returns https clone URL for org/repo. +func GithubComponentURL(org, repo string) string { + org = strings.TrimSpace(org) + repo = strings.TrimSpace(repo) + return fmt.Sprintf("https://github.com/%s/%s", org, repo) +} + +// GitlabComponentURL returns https clone URL for a project path on a GitLab host. +func GitlabComponentURL(baseURL, projectPath string) string { + baseURL = strings.TrimSuffix(normalizedGitlabOriginURL(baseURL), "/") + projectPath = strings.Trim(strings.TrimSpace(projectPath), "/") + return fmt.Sprintf("%s/%s.git", baseURL, projectPath) +} + +// RequiredGithubRepo returns MY_GITHUB_REPO or default testrepo. +func RequiredGithubRepo() string { + if r := strings.TrimSpace(os.Getenv(EnvMyGithubRepo)); r != "" { + return r + } + return defaultGithubRepo +} + +// GithubSourceRevision returns GITHUB_SOURCE_REVISION or the historical default SHA. +func GithubSourceRevision() string { + if r := strings.TrimSpace(os.Getenv(EnvGithubSourceRevision)); r != "" { + return r + } + return defaultGithubSrcRevision +} + +// GitlabBaseURL returns GITLAB_BASE_URL or https://gitlab.com (trimmed, no trailing slash). +func GitlabBaseURL() string { + return strings.TrimSuffix(normalizedGitlabOriginURL(os.Getenv(EnvGitlabBaseURL)), "/") +} + +// RequiredGitlabProjectPath returns MY_GITLAB_PROJECT_PATH (e.g. group/sub/repo). +func RequiredGitlabProjectPath() (string, error) { + p := strings.Trim(strings.TrimSpace(os.Getenv(EnvMyGitlabProjectPath)), "/") + if p == "" { + return "", fmt.Errorf("%s is not set", EnvMyGitlabProjectPath) + } + return p, nil +} + +// GitlabSourceRevision returns GITLAB_SOURCE_REVISION, or empty to mean "tip of the default branch". +// Empty is recommended when the GitHub default SHA (GITHUB_SOURCE_REVISION) is not present in your +// GitLab project; konflux CreateGitlabNewBranch then resolves the latest commit on the default branch. +func GitlabSourceRevision() string { + return strings.TrimSpace(os.Getenv(EnvGitlabSourceRevision)) +} + +// GitlabDefaultBranch returns GITLAB_DEFAULT_BRANCH or "main". +func GitlabDefaultBranch() string { + if b := strings.TrimSpace(os.Getenv(EnvGitlabDefaultBranch)); b != "" { + return b + } + return defaultGitlabBranch +} diff --git a/e2e/tests/tsf/git-providers/github.go b/e2e/tests/tsf/git-providers/github.go new file mode 100644 index 000000000..554052480 --- /dev/null +++ b/e2e/tests/tsf/git-providers/github.go @@ -0,0 +1,54 @@ +package gitproviders + +import ( + "fmt" + "strings" + + "github.com/konflux-ci/e2e-tests/pkg/framework" + "github.com/konflux-ci/e2e-tests/pkg/utils/build" +) + +type githubProvider struct { + fw *framework.Framework + repoName string +} + +func (g *githubProvider) CreateBaseBranch(defaultBranch, gitRevision, newBranch string) error { + return g.fw.AsKubeAdmin.CommonController.Github.CreateRef(g.repoName, defaultBranch, gitRevision, newBranch) +} + +func (g *githubProvider) WaitPaCInitChange(pacBranch string) (int, string, error) { + prs, err := g.fw.AsKubeAdmin.CommonController.Github.ListPullRequests(g.repoName) + if err != nil { + return 0, "", err + } + for _, pr := range prs { + if pr.Head.GetRef() == pacBranch { + return pr.GetNumber(), pr.GetHead().GetSHA(), nil + } + } + return 0, "", fmt.Errorf("could not get the expected PaC branch name %s", pacBranch) +} + +func (g *githubProvider) MergePaCChange(changeID int) (string, error) { + res, err := g.fw.AsKubeAdmin.CommonController.Github.MergePullRequest(g.repoName, changeID) + if err != nil { + return "", err + } + return res.GetSHA(), nil +} + +func (g *githubProvider) DeleteRemoteBranch(branch string) error { + err := g.fw.AsKubeAdmin.CommonController.Github.DeleteRef(g.repoName, branch) + if err == nil { + return nil + } + if strings.Contains(err.Error(), "Reference does not exist") { + return nil + } + return err +} + +func (g *githubProvider) CleanupClusterWebhooks() error { + return build.CleanupWebhooks(g.fw, g.repoName) +} diff --git a/e2e/tests/tsf/git-providers/gitlab.go b/e2e/tests/tsf/git-providers/gitlab.go new file mode 100644 index 000000000..bbea56cb2 --- /dev/null +++ b/e2e/tests/tsf/git-providers/gitlab.go @@ -0,0 +1,71 @@ +package gitproviders + +import ( + "fmt" + "strings" + + "github.com/konflux-ci/e2e-tests/pkg/framework" +) + +type gitlabProvider struct { + fw *framework.Framework + projectPath string +} + +func (g *gitlabProvider) CreateBaseBranch(defaultBranch, gitRevision, newBranch string) error { + return g.fw.AsKubeAdmin.CommonController.Gitlab.CreateGitlabNewBranch(g.projectPath, newBranch, gitRevision, defaultBranch) +} + +func (g *gitlabProvider) WaitPaCInitChange(pacBranch string) (int, string, error) { + mrs, err := g.fw.AsKubeAdmin.CommonController.Gitlab.GetMergeRequests(g.projectPath) + if err != nil { + return 0, "", err + } + for _, mr := range mrs { + if mr.SourceBranch == pacBranch { + return mr.IID, mr.SHA, nil + } + } + branches := make([]string, 0, len(mrs)) + for _, mr := range mrs { + branches = append(branches, mr.SourceBranch) + } + return 0, "", fmt.Errorf("no open MR with source branch %q (found %d open MR(s), source branches: %v); "+ + "if this stays empty, PaC is not pushing to GitLab—check pipelines-as-code-secret, token scopes, and GitLab integration", + pacBranch, len(mrs), branches) +} + +func (g *gitlabProvider) MergePaCChange(changeID int) (string, error) { + mr, err := g.fw.AsKubeAdmin.CommonController.Gitlab.AcceptMergeRequest(g.projectPath, changeID) + if err != nil { + return "", err + } + if mr == nil { + return "", fmt.Errorf("AcceptMergeRequest returned nil merge request") + } + // PaC labels push build PipelineRuns with the merge commit on the target branch (same as GitHub merge API SHA). + // mr.SHA is the MR source-branch / diff HEAD and matches the init on-pull-request run—do not use it here. + if mr.MergeCommitSHA != "" { + return mr.MergeCommitSHA, nil + } + if mr.SquashCommitSHA != "" { + return mr.SquashCommitSHA, nil + } + return mr.SHA, nil +} + +func (g *gitlabProvider) DeleteRemoteBranch(branch string) error { + err := g.fw.AsKubeAdmin.CommonController.Gitlab.DeleteBranch(g.projectPath, branch) + if err == nil { + return nil + } + msg := strings.ToLower(err.Error()) + if strings.Contains(msg, "404") || strings.Contains(msg, "not found") { + return nil + } + return err +} + +func (g *gitlabProvider) CleanupClusterWebhooks() error { + return g.fw.AsKubeAdmin.CommonController.Gitlab.DeleteWebhooks(g.projectPath, g.fw.ClusterAppDomain) +} diff --git a/e2e/tests/tsf/git-providers/gitlab_webhooks.go b/e2e/tests/tsf/git-providers/gitlab_webhooks.go new file mode 100644 index 000000000..8eb9521b3 --- /dev/null +++ b/e2e/tests/tsf/git-providers/gitlab_webhooks.go @@ -0,0 +1,38 @@ +package gitproviders + +import ( + "fmt" + + "github.com/konflux-ci/e2e-tests/pkg/framework" + gitlab "github.com/xanzy/go-gitlab" +) + +// DeleteAllGitlabProjectWebhooks removes every hook on the GitLab project (project path or ID). +// Use in test cleanup when Konflux/PaC or other automation may leave multiple webhooks. +func DeleteAllGitlabProjectWebhooks(fw *framework.Framework, projectPath string) error { + if fw == nil { + return fmt.Errorf("framework is nil") + } + gl := fw.AsKubeAdmin.CommonController.Gitlab + if gl == nil { + return fmt.Errorf("GitLab client is nil") + } + if projectPath == "" { + return fmt.Errorf("project path is empty") + } + c := gl.GetClient() + for { + hooks, _, err := c.Projects.ListProjectHooks(projectPath, &gitlab.ListProjectHooksOptions{PerPage: 100}) + if err != nil { + return fmt.Errorf("list project hooks for %q: %w", projectPath, err) + } + if len(hooks) == 0 { + return nil + } + for _, h := range hooks { + if _, err := c.Projects.DeleteProjectHook(projectPath, h.ID); err != nil { + return fmt.Errorf("delete hook id %d for %q: %w", h.ID, projectPath, err) + } + } + } +} diff --git a/e2e/tests/tsf/git-providers/pac_event.go b/e2e/tests/tsf/git-providers/pac_event.go new file mode 100644 index 000000000..37ddd7fdf --- /dev/null +++ b/e2e/tests/tsf/git-providers/pac_event.go @@ -0,0 +1,17 @@ +package gitproviders + +// PaCEventTypePullRequest returns the value of label pipelinesascode.tekton.dev/event-type +// for a PaC PipelineRun triggered by a PR/MR (after kubernetes label cleaning). +func PaCEventTypePullRequest(k Kind) string { + if k == KindGitLab { + // PaC GitLab: X-Gitlab-Event "Merge Request Hook" → "Merge Request" → formatting.CleanValueKubernetes → "Merge_Request" + return "Merge_Request" + } + return "pull_request" +} + +// PaCEventTypePush returns the value of label pipelinesascode.tekton.dev/event-type for a push build. +// PaC sets lowercase "push" on labels for both GitHub and GitLab (see pipelinesascode.tekton.dev/event-type). +func PaCEventTypePush(_ Kind) string { + return "push" +} diff --git a/e2e/tests/tsf/git-providers/pac_webhook_key.go b/e2e/tests/tsf/git-providers/pac_webhook_key.go new file mode 100644 index 000000000..a389fb4e1 --- /dev/null +++ b/e2e/tests/tsf/git-providers/pac_webhook_key.go @@ -0,0 +1,16 @@ +package gitproviders + +import ( + "regexp" + "strings" +) + +// Matches konflux-ci build-service getWebhookSecretKeyForComponent (each disallowed char -> '_'). +var konfluxPaCWebhookSecretKeySanitizer = regexp.MustCompile(`[^-._a-zA-Z0-9]`) + +// KonfluxPACWebhookSecretDataKey returns the Secret.Data key under pipelines-as-code-webhooks-secret +// for a component GitSource.URL (trim trailing ".git", then sanitize). +func KonfluxPACWebhookSecretDataKey(gitRepoURL string) string { + s := strings.TrimSuffix(strings.TrimSpace(gitRepoURL), ".git") + return konfluxPaCWebhookSecretKeySanitizer.ReplaceAllString(s, "_") +} diff --git a/e2e/tests/tsf/git-providers/pac_webhook_key_test.go b/e2e/tests/tsf/git-providers/pac_webhook_key_test.go new file mode 100644 index 000000000..6e9d09c36 --- /dev/null +++ b/e2e/tests/tsf/git-providers/pac_webhook_key_test.go @@ -0,0 +1,14 @@ +package gitproviders + +import "testing" + +func TestKonfluxPACWebhookSecretDataKey_exampleFromUser(t *testing.T) { + const u = "https://gitlab.com/rhtap-test-organization-jk/testrepo" + const want = "https___gitlab.com_rhtap-test-organization-jk_testrepo" + if g := KonfluxPACWebhookSecretDataKey(u); g != want { + t.Fatalf("got %q want %q", g, want) + } + if g := KonfluxPACWebhookSecretDataKey(u + ".git"); g != want { + t.Fatalf(".git suffix: got %q want %q", g, want) + } +} diff --git a/e2e/tests/tsf/git-providers/provider.go b/e2e/tests/tsf/git-providers/provider.go new file mode 100644 index 000000000..281202430 --- /dev/null +++ b/e2e/tests/tsf/git-providers/provider.go @@ -0,0 +1,33 @@ +package gitproviders + +import ( + "fmt" + + "github.com/konflux-ci/e2e-tests/pkg/framework" +) + +// Provider abstracts GitHub PR and GitLab MR flows used by the TSF demo test. +type Provider interface { + // CreateBaseBranch points newBranch at gitRevision (commit SHA) from defaultBranch context. + CreateBaseBranch(defaultBranch, gitRevision, newBranch string) error + // WaitPaCInitChange waits until PaC creates an open PR/MR from pacBranch; returns API id and head SHA. + WaitPaCInitChange(pacBranch string) (changeID int, headSHA string, err error) + // MergePaCChange merges PR/MR changeID; returns merge commit SHA. + MergePaCChange(changeID int) (mergeSHA string, err error) + // DeleteRemoteBranch removes a branch/ref; missing branch is not an error. + DeleteRemoteBranch(branch string) error + // CleanupClusterWebhooks removes hooks whose URL contains the cluster app domain. + CleanupClusterWebhooks() error +} + +// New returns a Provider for the given kind. repoKey is GitHub short repo name or GitLab path (group/project). +func New(kind Kind, fw *framework.Framework, repoKey string) (Provider, error) { + switch kind { + case KindGitHub: + return &githubProvider{fw: fw, repoName: repoKey}, nil + case KindGitLab: + return &gitlabProvider{fw: fw, projectPath: repoKey}, nil + default: + return nil, fmt.Errorf("unsupported git provider kind %q", kind) + } +} diff --git a/e2e/tests/tsf/git-providers/secrets.go b/e2e/tests/tsf/git-providers/secrets.go new file mode 100644 index 000000000..4dfe5beb9 --- /dev/null +++ b/e2e/tests/tsf/git-providers/secrets.go @@ -0,0 +1,115 @@ +package gitproviders + +import ( + "fmt" + "strings" + + "github.com/konflux-ci/e2e-tests/pkg/framework" + corev1 "k8s.io/api/core/v1" +) + +const pacSecretKeyProviderToken = "provider.token" +const pacSecretKeyWebhookSecret = "webhook.secret" +const pacSecretNameDefault = "pipelines-as-code-secret" + +// Konflux build-service stores per-repo webhook material here (see pipelinesAsCodeWebhooksSecretName). +const pacWebhooksSecretName = "pipelines-as-code-webhooks-secret" + +// CreateGitlabPACSecret creates pipelines-as-code SCM credentials for GitLab (password + provider.token only). +// webhook.secret is synced later via EnsureGitlabPACSecretShape once Konflux has written pipelines-as-code-webhooks-secret. +func CreateGitlabPACSecret(f *framework.Framework, secretName, token string) error { + if token == "" { + return fmt.Errorf("GitLab token is empty") + } + host, err := GitlabHostForSCMLabel() + if err != nil { + return err + } + buildSecret := corev1.Secret{} + buildSecret.Name = secretName + buildSecret.Labels = map[string]string{ + "appstudio.redhat.com/credentials": "scm", + "appstudio.redhat.com/scm.host": host, + } + buildSecret.Type = corev1.SecretTypeBasicAuth + buildSecret.StringData = map[string]string{ + "password": token, + pacSecretKeyProviderToken: token, + } + _, err = f.AsKubeAdmin.CommonController.CreateSecret(f.UserNamespace, &buildSecret) + if err != nil { + return fmt.Errorf("create GitLab PAC secret: %w", err) + } + return nil +} + +// KonfluxPACWebhookSecretValue returns the only supported webhook HMAC secret for GitLab hooks: +// tenantNamespace/pipelines-as-code-webhooks-secret, data key = KonfluxPACWebhookSecretDataKey(gitRepoURL). +func KonfluxPACWebhookSecretValue(f *framework.Framework, tenantNamespace, gitRepoURL string) (string, error) { + if f == nil { + return "", fmt.Errorf("framework is nil") + } + if strings.TrimSpace(tenantNamespace) == "" { + return "", fmt.Errorf("tenant namespace is empty") + } + key := KonfluxPACWebhookSecretDataKey(gitRepoURL) + if key == "" { + return "", fmt.Errorf("empty webhook secret data key for git URL %q", gitRepoURL) + } + sec, err := f.AsKubeAdmin.CommonController.GetSecret(tenantNamespace, pacWebhooksSecretName) + if err != nil { + return "", fmt.Errorf("get Secret %s/%s: %w", tenantNamespace, pacWebhooksSecretName, err) + } + raw, ok := sec.Data[key] + if !ok || len(raw) == 0 { + return "", fmt.Errorf("secret %s/%s has no non-empty data key %q (expected Konflux key for GitSource.URL %q)", + tenantNamespace, pacWebhooksSecretName, key, gitRepoURL) + } + return string(raw), nil +} + +// EnsureGitlabPACSecretShape updates pipelines-as-code-secret: webhook.secret is always synced from +// tenant pipelines-as-code-webhooks-secret (KonfluxPACWebhookSecretDataKey(gitRepoURL)); provider.token and password are set if missing. +func EnsureGitlabPACSecretShape(f *framework.Framework, secretName, apiToken, gitRepoURL string) error { + if secretName == "" { + secretName = pacSecretNameDefault + } + if apiToken == "" { + return fmt.Errorf("GitLab token is empty") + } + if strings.TrimSpace(gitRepoURL) == "" { + return fmt.Errorf("gitRepoURL is empty") + } + sec, err := f.AsKubeAdmin.CommonController.GetSecret(f.UserNamespace, secretName) + if err != nil { + return err + } + if sec.Data == nil { + sec.Data = map[string][]byte{} + } + changed := false + wh, err := KonfluxPACWebhookSecretValue(f, f.UserNamespace, gitRepoURL) + if err != nil { + return err + } + if string(sec.Data[pacSecretKeyWebhookSecret]) != wh { + sec.Data[pacSecretKeyWebhookSecret] = []byte(wh) + changed = true + } + if len(sec.Data[pacSecretKeyProviderToken]) == 0 { + sec.Data[pacSecretKeyProviderToken] = []byte(apiToken) + changed = true + } + if len(sec.Data["password"]) == 0 { + sec.Data["password"] = []byte(apiToken) + changed = true + } + if !changed { + return nil + } + _, err = f.AsKubeAdmin.CommonController.UpdateSecret(f.UserNamespace, sec) + if err != nil { + return fmt.Errorf("update GitLab PAC secret %q: %w", secretName, err) + } + return nil +} diff --git a/e2e/tests/tsf/tsf-demo.go b/e2e/tests/tsf/tsf-demo.go index dfb58d76f..52159be53 100644 --- a/e2e/tests/tsf/tsf-demo.go +++ b/e2e/tests/tsf/tsf-demo.go @@ -9,7 +9,6 @@ import ( buildcontrollers "github.com/konflux-ci/build-service/controllers" "github.com/devfile/library/v2/pkg/util" - "github.com/google/go-github/v44/github" appservice "github.com/konflux-ci/application-api/api/v1alpha1" "github.com/konflux-ci/e2e-tests/pkg/clients/has" "github.com/konflux-ci/e2e-tests/pkg/constants" @@ -20,13 +19,17 @@ import ( ginkgo "github.com/onsi/ginkgo/v2" gomega "github.com/onsi/gomega" + "github.com/redhat-appstudio/tsf-cli/e2e/tests/tsf/git-providers" + integrationv1beta2 "github.com/konflux-ci/integration-service/api/v1beta2" releaseApi "github.com/konflux-ci/release-service/api/v1alpha1" tektonapi "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" ) const ( - tsfTestLabel = "tsf-demo" + tsfTestLabel = "tsf-demo" + tsfReleasePlanName = "tsf-release" // Timeouts mergePRTimeout = time.Minute * 1 @@ -42,6 +45,8 @@ const ( snapshotPollingInterval = time.Second * 1 releasePollingInterval = time.Second * 1 + // GitLab: after the component exists, allow controllers/webhooks to settle before PaC init MR work. + gitlabPostComponentWaitBeforeInitMR = 10 * time.Second ) func tsfDemoSuiteDescribe(args ...interface{}) bool { @@ -68,14 +73,17 @@ var _ = tsfDemoSuiteDescribe(ginkgo.Label(tsfTestLabel), func() { var release *releaseApi.Release // PaC related variables - var prNumber int + var pacChangeID int var headSHA, pacBranchName string - var mergeResult *github.PullRequestMergeResult // Component configuration - using a simple test repository var gitSourceUrl string + var gitSourceRevision string + var scmDefaultBranchName string + var scmProvider gitproviders.Provider + var providerKind gitproviders.Kind + const ( - gitSourceRevision = "1255dc36534b9db7b99efbc281117435ea03255f" gitSourceDefaultBranchName = "main" dockerFilePath = "Dockerfile" @@ -88,12 +96,16 @@ var _ = tsfDemoSuiteDescribe(ginkgo.Label(tsfTestLabel), func() { ginkgo.Describe("TSF Demo", ginkgo.Ordered, func() { ginkgo.BeforeAll(func() { if os.Getenv(constants.SKIP_PAC_TESTS_ENV) == "true" { - ginkgo.Skip("Skipping this test due to configuration issue with Spray proxy") + ginkgo.Skip("Skipping this test (SKIP_PAC_TESTS=true)") } - githubOrg := os.Getenv("MY_GITHUB_ORG") - gomega.Expect(githubOrg).NotTo(gomega.BeEmpty(), "MY_GITHUB_ORG env var is not set") - gitSourceUrl = fmt.Sprintf("https://github.com/%s/testrepo", githubOrg) + providerRaw := os.Getenv(gitproviders.EnvGitProvider) + providerKind, err = gitproviders.ParseGitProvider(providerRaw) + gomega.Expect(err).NotTo(gomega.HaveOccurred(), + "fix GIT_PROVIDER so the test does not silently use GitHub (want github, gitlab, or gl)") + if providerKind == gitproviders.KindGitLab { + gitproviders.PrepareProcessEnvForGitLab() + } fw, err = framework.NewFramework(utils.GetGeneratedNamespace(tsfTestLabel)) gomega.Expect(err).NotTo(gomega.HaveOccurred()) @@ -110,8 +122,59 @@ var _ = tsfDemoSuiteDescribe(ginkgo.Label(tsfTestLabel), func() { componentName = os.Getenv("TSF_COMPONENT_NAME") gomega.Expect(componentName).NotTo(gomega.BeEmpty(), "TSF_COMPONENT_NAME env var is not set") + switch providerKind { + case gitproviders.KindGitHub: + githubOrg := os.Getenv("MY_GITHUB_ORG") + gomega.Expect(githubOrg).NotTo(gomega.BeEmpty(), "MY_GITHUB_ORG env var is not set") + repo := gitproviders.RequiredGithubRepo() + gitSourceUrl = gitproviders.GithubComponentURL(githubOrg, repo) + gitSourceRevision = gitproviders.GithubSourceRevision() + scmDefaultBranchName = gitSourceDefaultBranchName + componentRepositoryName = utils.ExtractGitRepositoryNameFromURL(gitSourceUrl) + gomega.Expect(gitSourceUrl).To(gomega.ContainSubstring("github.com"), + "GIT_PROVIDER=github but component URL does not look like GitHub") + case gitproviders.KindGitLab: + path, errPath := gitproviders.RequiredGitlabProjectPath() + gomega.Expect(errPath).NotTo(gomega.HaveOccurred()) + gitSourceUrl = gitproviders.GitlabComponentURL(gitproviders.GitlabBaseURL(), path) + gitSourceRevision = gitproviders.GitlabSourceRevision() + scmDefaultBranchName = gitproviders.GitlabDefaultBranch() + componentRepositoryName = path + gomega.Expect(gitSourceUrl).NotTo(gomega.ContainSubstring("github.com"), + "GIT_PROVIDER=gitlab but component URL looks like GitHub — check MY_GITLAB_PROJECT_PATH and GITLAB_BASE_URL") + gomega.Expect(gitSourceUrl).To(gomega.HavePrefix(gitproviders.GitlabBaseURL()), + "internal: GitLab clone URL must start with GITLAB_BASE_URL") + ginkgo.GinkgoWriter.Printf("GitLab: project=%q defaultBranch=%q sourceRevision=%q (empty revision => branch from tip of default)\n", + path, scmDefaultBranchName, gitSourceRevision) + } + + ginkgo.GinkgoWriter.Printf("\n======== tsf-demo SCM (API + component clone target) ========\n") + ginkgo.GinkgoWriter.Printf("%s=%q -> kind=%s\n", gitproviders.EnvGitProvider, providerRaw, providerKind) + ginkgo.GinkgoWriter.Printf("componentRepositoryName (API key)=%q\n", componentRepositoryName) + ginkgo.GinkgoWriter.Printf("component GitSource.URL=%q\n", gitSourceUrl) + ginkgo.GinkgoWriter.Printf("==============================================================\n\n") + + scmProvider, err = gitproviders.New(providerKind, fw, componentRepositoryName) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + // GitLab PaC needs an SCM credential secret (password + provider.token) before the component exists; + // webhook.secret is synced once Konflux writes pipelines-as-code-webhooks-secret (same PaC init spec as GitHub’s PR poll). + if providerKind == gitproviders.KindGitLab { + gitlabToken := utils.GetEnv(constants.GITLAB_BOT_TOKEN_ENV, "") + gomega.Expect(gitlabToken).NotTo(gomega.BeEmpty(), + "set GITLAB_BOT_TOKEN or GITLAB_TOKEN so PaC can push the init branch and open a merge request") + const pacGitlabSecret = "pipelines-as-code-secret" + _, getErr := fw.AsKubeAdmin.CommonController.GetSecret(userNamespace, pacGitlabSecret) + if apierrors.IsNotFound(getErr) { + gomega.Expect(gitproviders.CreateGitlabPACSecret(fw, pacGitlabSecret, gitlabToken)).To(gomega.Succeed(), + "create pipelines-as-code-secret for GitLab; scm.host matches GITLAB_BASE_URL host") + } else { + gomega.Expect(getErr).NotTo(gomega.HaveOccurred()) + ginkgo.GinkgoWriter.Printf("reusing existing secret %s/%s for GitLab PaC\n", userNamespace, pacGitlabSecret) + } + } + pacBranchName = fmt.Sprintf("%s%s", constants.PaCPullRequestBranchPrefix, componentName) - componentRepositoryName = utils.ExtractGitRepositoryNameFromURL(gitSourceUrl) // Get the build pipeline bundle annotation buildPipelineAnnotation = build.GetBuildPipelineBundleAnnotation("docker-build-oci-ta-min") @@ -120,20 +183,19 @@ var _ = tsfDemoSuiteDescribe(ginkgo.Label(tsfTestLabel), func() { // Remove all resources created by the tests ginkgo.AfterAll(func() { if !(os.Getenv("E2E_SKIP_CLEANUP") == "true") && !ginkgo.CurrentSpecReport().Failed() { - gomega.Expect(fw.AsKubeAdmin.ReleaseController.DeleteReleasePlan("tsf-release", userNamespace, false)).To(gomega.Succeed()) + gomega.Expect(fw.AsKubeAdmin.ReleaseController.DeleteReleasePlan(tsfReleasePlanName, userNamespace, false)).To(gomega.Succeed()) gomega.Expect(fw.AsKubeAdmin.HasController.DeleteApplication(applicationName, userNamespace, false)).To(gomega.Succeed()) gomega.Expect(fw.AsKubeAdmin.CommonController.DeleteNamespace(managedNamespace)).To(gomega.Succeed()) // Delete new branch created by PaC and a testing branch used as a component's base branch - err = fw.AsKubeAdmin.CommonController.Github.DeleteRef(componentRepositoryName, pacBranchName) - if err != nil { - gomega.Expect(err.Error()).To(gomega.ContainSubstring("Reference does not exist")) - } - err = fw.AsKubeAdmin.CommonController.Github.DeleteRef(componentRepositoryName, componentNewBaseBranch) - if err != nil { - gomega.Expect(err.Error()).To(gomega.ContainSubstring("Reference does not exist")) + gomega.Expect(scmProvider.DeleteRemoteBranch(pacBranchName)).To(gomega.Succeed()) + gomega.Expect(scmProvider.DeleteRemoteBranch(componentNewBaseBranch)).To(gomega.Succeed()) + if providerKind == gitproviders.KindGitLab { + gomega.Expect(gitproviders.DeleteAllGitlabProjectWebhooks(fw, componentRepositoryName)).To(gomega.Succeed(), + "remove all GitLab project webhooks left by PaC/Konflux or prior runs") + } else { + gomega.Expect(scmProvider.CleanupClusterWebhooks()).ShouldNot(gomega.HaveOccurred()) } - gomega.Expect(build.CleanupWebhooks(fw, componentRepositoryName)).ShouldNot(gomega.HaveOccurred()) } }) @@ -160,7 +222,7 @@ var _ = tsfDemoSuiteDescribe(ginkgo.Label(tsfTestLabel), func() { // can avoid polluting the default (main) branch componentNewBaseBranch = fmt.Sprintf("base-%s", util.GenerateRandomString(6)) gitRevision = componentNewBaseBranch - gomega.Expect(fw.AsKubeAdmin.CommonController.Github.CreateRef(componentRepositoryName, gitSourceDefaultBranchName, gitSourceRevision, componentNewBaseBranch)).To(gomega.Succeed()) + gomega.Expect(scmProvider.CreateBaseBranch(scmDefaultBranchName, gitSourceRevision, componentNewBaseBranch)).To(gomega.Succeed()) }) // Component is imported from gitUrl @@ -184,24 +246,31 @@ var _ = tsfDemoSuiteDescribe(ginkgo.Label(tsfTestLabel), func() { }) ginkgo.When("Component is created", ginkgo.Label(tsfTestLabel), func() { - ginkgo.It("triggers creation of a PR in the sample repo", func() { - var prSHA string + ginkgo.It("triggers creation of a PaC pull request or merge request in the sample repo", func() { + // GitHub: PaC uses cluster/GitHub app credentials; no extra secret sync in this test. + // GitLab: Konflux writes pipelines-as-code-webhooks-secret after reconcile; PaC needs + // webhook.secret on pipelines-as-code-secret before GitLab accepts hooks—poll like the PR/MR wait below. + if providerKind == gitproviders.KindGitLab { + ginkgo.GinkgoWriter.Printf("GitLab: waiting %s after component create before PaC webhook sync and init MR polling\n", gitlabPostComponentWaitBeforeInitMR) + time.Sleep(gitlabPostComponentWaitBeforeInitMR) + gitlabToken := utils.GetEnv(constants.GITLAB_BOT_TOKEN_ENV, "") + const pacGitlabSecret = "pipelines-as-code-secret" + gomega.Eventually(func() error { + return gitproviders.EnsureGitlabPACSecretShape(fw, pacGitlabSecret, gitlabToken, gitSourceUrl) + }, time.Minute*3, defaultPollingInterval).Should(gomega.Succeed(), + "wait for Konflux to populate pipelines-as-code-webhooks-secret, then copy webhook material into pipelines-as-code-secret") + } + var initHeadSHA string gomega.Eventually(func() error { - prs, err := fw.AsKubeAdmin.CommonController.Github.ListPullRequests(componentRepositoryName) - gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) - for _, pr := range prs { - if pr.Head.GetRef() == pacBranchName { - prNumber = pr.GetNumber() - prSHA = pr.GetHead().GetSHA() - return nil - } - } - return fmt.Errorf("could not get the expected PaC branch name %s", pacBranchName) - }, pullRequestCreationTimeout, defaultPollingInterval).Should(gomega.Succeed(), fmt.Sprintf("timed out when waiting for init PaC PR (branch %q) to be created against the %q repo", pacBranchName, componentRepositoryName)) + var err error + pacChangeID, initHeadSHA, err = scmProvider.WaitPaCInitChange(pacBranchName) + return err + }, pullRequestCreationTimeout, defaultPollingInterval).Should(gomega.Succeed(), fmt.Sprintf("timed out when waiting for init PaC change (branch %q) in %q", pacBranchName, componentRepositoryName)) // We don't need the PipelineRun from a PaC 'pull-request' event to finish, so we can delete it gomega.Eventually(func() error { - pipelineRun, err = fw.AsKubeAdmin.HasController.GetComponentPipelineRun(component.GetName(), applicationName, userNamespace, prSHA) + pipelineRun, err = fw.AsKubeAdmin.HasController.GetComponentPipelineRunWithType( + component.GetName(), applicationName, userNamespace, "", initHeadSHA, gitproviders.PaCEventTypePullRequest(providerKind)) if err == nil { gomega.Expect(fw.AsKubeAdmin.TektonController.DeletePipelineRun(pipelineRun.Name, pipelineRun.Namespace)).To(gomega.Succeed()) return nil @@ -241,14 +310,14 @@ var _ = tsfDemoSuiteDescribe(ginkgo.Label(tsfTestLabel), func() { ginkgo.It("should eventually lead to triggering a 'push' event type PipelineRun after merging the PaC init branch ", func() { gomega.Eventually(func() error { - mergeResult, err = fw.AsKubeAdmin.CommonController.Github.MergePullRequest(componentRepositoryName, prNumber) - return err - }, mergePRTimeout).ShouldNot(gomega.HaveOccurred(), fmt.Sprintf("error when merging PaC pull request: %+v\n", err)) - - headSHA = mergeResult.GetSHA() + var mergeErr error + headSHA, mergeErr = scmProvider.MergePaCChange(pacChangeID) + return mergeErr + }, mergePRTimeout).ShouldNot(gomega.HaveOccurred(), fmt.Sprintf("error when merging PaC change #%d", pacChangeID)) gomega.Eventually(func() error { - pipelineRun, err = fw.AsKubeAdmin.HasController.GetComponentPipelineRun(component.GetName(), applicationName, userNamespace, headSHA) + pipelineRun, err = fw.AsKubeAdmin.HasController.GetComponentPipelineRunWithType( + component.GetName(), applicationName, userNamespace, "build", headSHA, gitproviders.PaCEventTypePush(providerKind)) if err != nil { ginkgo.GinkgoWriter.Printf("PipelineRun has not been created yet for component %s/%s\n", userNamespace, component.GetName()) return err @@ -257,7 +326,7 @@ var _ = tsfDemoSuiteDescribe(ginkgo.Label(tsfTestLabel), func() { return fmt.Errorf("pipelinerun %s/%s hasn't started yet", pipelineRun.GetNamespace(), pipelineRun.GetName()) } return nil - }, pipelineRunStartedTimeout, constants.PipelineRunPollingInterval).Should(gomega.Succeed(), fmt.Sprintf("timed out when waiting for a PipelineRun in namespace %q with label component label %q and application label %q and sha label %q to start", userNamespace, component.GetName(), applicationName, headSHA)) + }, pipelineRunStartedTimeout, constants.PipelineRunPollingInterval).Should(gomega.Succeed(), fmt.Sprintf("timed out when waiting for a `push` PaC PipelineRun in namespace %q for component %q application %q sha %q", userNamespace, component.GetName(), applicationName, headSHA)) }) }) @@ -266,7 +335,7 @@ var _ = tsfDemoSuiteDescribe(ginkgo.Label(tsfTestLabel), func() { gomega.Expect(pipelineRun.Annotations["appstudio.openshift.io/snapshot"]).To(gomega.Equal("")) }) ginkgo.It("should eventually complete successfully", func() { - gomega.Expect(fw.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(component, "build", headSHA, "", + gomega.Expect(fw.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(component, "build", headSHA, gitproviders.PaCEventTypePush(providerKind), fw.AsKubeAdmin.TektonController, &has.RetryOptions{Retries: 5, Always: true}, pipelineRun)).To(gomega.Succeed()) // in case the first pipelineRun attempt has failed and was retried, we need to update the git branch head ref @@ -277,14 +346,16 @@ var _ = tsfDemoSuiteDescribe(ginkgo.Label(tsfTestLabel), func() { ginkgo.When("Build PipelineRun completes successfully", ginkgo.Label(tsfTestLabel), func() { ginkgo.It("should validate Tekton TaskRun test results successfully", func() { - pipelineRun, err = fw.AsKubeAdmin.HasController.GetComponentPipelineRun(component.GetName(), applicationName, userNamespace, headSHA) + pipelineRun, err = fw.AsKubeAdmin.HasController.GetComponentPipelineRunWithType( + component.GetName(), applicationName, userNamespace, "build", headSHA, gitproviders.PaCEventTypePush(providerKind)) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) gomega.Expect(build.ValidateBuildPipelineTestResults(pipelineRun, fw.AsKubeAdmin.CommonController.KubeRest(), false)).To(gomega.Succeed()) }) ginkgo.It("should validate that the build pipelineRun is signed", func() { gomega.Eventually(func() error { - pipelineRun, err = fw.AsKubeAdmin.HasController.GetComponentPipelineRun(component.GetName(), applicationName, userNamespace, headSHA) + pipelineRun, err = fw.AsKubeAdmin.HasController.GetComponentPipelineRunWithType( + component.GetName(), applicationName, userNamespace, "build", headSHA, gitproviders.PaCEventTypePush(providerKind)) if err != nil { return err } @@ -303,7 +374,8 @@ var _ = tsfDemoSuiteDescribe(ginkgo.Label(tsfTestLabel), func() { }) ginkgo.It("should validate that the build pipelineRun is annotated with the name of the Snapshot", func() { - pipelineRun, err = fw.AsKubeAdmin.HasController.GetComponentPipelineRun(component.GetName(), applicationName, userNamespace, headSHA) + pipelineRun, err = fw.AsKubeAdmin.HasController.GetComponentPipelineRunWithType( + component.GetName(), applicationName, userNamespace, "build", headSHA, gitproviders.PaCEventTypePush(providerKind)) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) gomega.Expect(pipelineRun.Annotations["appstudio.openshift.io/snapshot"]).To(gomega.Equal(snapshot.GetName())) }) @@ -404,4 +476,3 @@ var _ = tsfDemoSuiteDescribe(ginkgo.Label(tsfTestLabel), func() { }) }) }) - diff --git a/installer/charts/tsf-konflux/templates/pac-secret.yaml b/installer/charts/tsf-konflux/templates/pac-secret.yaml index 5d0e895fe..b5b813f9c 100644 --- a/installer/charts/tsf-konflux/templates/pac-secret.yaml +++ b/installer/charts/tsf-konflux/templates/pac-secret.yaml @@ -1,10 +1,15 @@ {{- $host := "" }} {{- $token := "" }} +{{- $webhookSecret := "" }} {{- $gitlabSecretObj := (lookup "v1" "Secret" .Values.konflux.tsf.namespace "tsf-gitlab-integration") | default dict -}} {{- if $gitlabSecretObj }} {{- $secretData := required (printf "data not found in secret 'tsf-gitlab-integration' in namespace '%s'" .Values.konflux.tsf.namespace) (get $gitlabSecretObj "data") | default dict -}} {{- $host = required (printf "host not found in secret 'tsf-gitlab-integration' in namespace '%s'" .Values.konflux.tsf.namespace) (get $secretData "host") | b64dec | toString -}} {{- $token = required (printf "token not found in secret 'tsf-gitlab-integration' in namespace '%s'" .Values.konflux.tsf.namespace) (get $secretData "token") | b64dec | toString -}} + {{- $webhookSecret = $token -}} + {{- if hasKey $secretData "webhookSecret" -}} + {{- $webhookSecret = (get $secretData "webhookSecret") | b64dec | toString -}} + {{- end -}} {{- end }} {{- if (ne $host "") }} apiVersion: v1 @@ -18,4 +23,6 @@ metadata: type: kubernetes.io/basic-auth stringData: password: {{ $token | quote }} + provider.token: {{ $token | quote }} + webhook.secret: {{ $webhookSecret | quote }} {{- end }}