From a2d57fc26892e8494ce665880d5dfe2780eadbff Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 18 May 2026 15:29:40 +0300 Subject: [PATCH 1/7] fixed GitHub integration tests for frogbot v3 --- .github/workflows/release-gate.yml | 16 ++-- .github/workflows/test.yml | 16 ++-- azure_test.go | 21 +++-- bitbucket_server_test.go | 21 +++-- github_test.go | 24 +++--- gitlab_test.go | 26 +++--- integrationutils.go | 129 +++++++++++++++++------------ 7 files changed, 135 insertions(+), 118 deletions(-) diff --git a/.github/workflows/release-gate.yml b/.github/workflows/release-gate.yml index f6507c653..b6e408800 100644 --- a/.github/workflows/release-gate.yml +++ b/.github/workflows/release-gate.yml @@ -142,11 +142,11 @@ jobs: run: python3 -m pip install pipenv poetry - name: Run Tests - run: go test github_test.go integrationutils.go commands.go -v -race -timeout 30m -cover + run: go test -tags integration github_test.go integrationutils.go commands.go -v -race -timeout 30m -cover env: JF_URL: ${{ secrets.PLATFORM_URL }} JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_TESTS_GITHUB_TOKEN: ${{ secrets.FROGBOT_TESTS_GITHUB_TOKEN }} + FROGBOT_V3_TESTS_GITHUB_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_GITHUB_TOKEN }} azure-integration: name: Azure Integration Tests @@ -178,11 +178,11 @@ jobs: run: python3 -m pip install pipenv poetry - name: Run Tests - run: go test azure_test.go integrationutils.go commands.go -v -race -timeout 30m -cover + run: go test -tags integration azure_test.go integrationutils.go commands.go -v -race -timeout 30m -cover env: JF_URL: ${{ secrets.PLATFORM_URL }} JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_TESTS_AZURE_TOKEN: ${{ secrets.FROGBOT_TESTS_AZURE_TOKEN }} + FROGBOT_TESTS_AZURE_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_AZURE_TOKEN }} gitlab-integration: name: GitLab Integration Tests @@ -214,11 +214,11 @@ jobs: run: python3 -m pip install pipenv poetry - name: Run Tests - run: go test gitlab_test.go integrationutils.go commands.go -v -race -timeout 30m -cover + run: go test -tags integration gitlab_test.go integrationutils.go commands.go -v -race -timeout 30m -cover env: JF_URL: ${{ secrets.PLATFORM_URL }} JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_TESTS_GITLAB_TOKEN: ${{ secrets.FROGBOT_TESTS_GITLAB_TOKEN }} + FROGBOT_V3_TESTS_GITLAB_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_GITLAB_TOKEN }} bitbucket-server-integration: name: Bitbucket Server Integration Tests @@ -283,8 +283,8 @@ jobs: env: JF_URL: ${{ secrets.PLATFORM_URL }} JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_TESTS_BB_SERVER_TOKEN: ${{ secrets.FROGBOT_TESTS_BB_SERVER_TOKEN }} - run: go test -v bitbucket_server_test.go commands.go integrationutils.go + FROGBOT_TESTS_BB_SERVER_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_BB_SERVER_TOKEN }} + run: go test -tags integration -v bitbucket_server_test.go commands.go integrationutils.go - name: Display Logs on Failure if: failure() diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 430e35006..46c75bd4d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -217,11 +217,11 @@ jobs: ${{ runner.os }}-go- - name: Run Tests - run: go test github_test.go integrationutils.go commands.go -v -race -timeout 30m -cover + run: go test -tags integration github_test.go integrationutils.go commands.go -v -race -timeout 30m -cover env: JF_URL: ${{ secrets.PLATFORM_URL }} JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_TESTS_GITHUB_TOKEN: ${{ secrets.FROGBOT_TESTS_GITHUB_TOKEN }} + FROGBOT_V3_TESTS_GITHUB_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_GITHUB_TOKEN }} azure-integration: name: Azure Integration Tests @@ -262,11 +262,11 @@ jobs: ${{ runner.os }}-go- - name: Run Tests - run: go test azure_test.go integrationutils.go commands.go -v -race -timeout 30m -cover + run: go test -tags integration azure_test.go integrationutils.go commands.go -v -race -timeout 30m -cover env: JF_URL: ${{ secrets.PLATFORM_URL }} JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_TESTS_AZURE_TOKEN: ${{ secrets.FROGBOT_TESTS_AZURE_TOKEN }} + FROGBOT_TESTS_AZURE_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_AZURE_TOKEN }} gitlab-integration: name: GitLab Integration Tests @@ -307,11 +307,11 @@ jobs: ${{ runner.os }}-go- - name: Run Tests - run: go test gitlab_test.go integrationutils.go commands.go -v -race -timeout 30m -cover + run: go test -tags integration gitlab_test.go integrationutils.go commands.go -v -race -timeout 30m -cover env: JF_URL: ${{ secrets.PLATFORM_URL }} JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_TESTS_GITLAB_TOKEN: ${{ secrets.FROGBOT_TESTS_GITLAB_TOKEN }} + FROGBOT_V3_TESTS_GITLAB_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_GITLAB_TOKEN }} bitbucket-server-integration: name: Bitbucket Server Integration Tests @@ -359,6 +359,6 @@ jobs: env: JF_URL: ${{ secrets.PLATFORM_URL }} JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_TESTS_BB_SERVER_TOKEN: ${{ secrets.FROGBOT_TESTS_BB_SERVER_TOKEN }} + FROGBOT_TESTS_BB_SERVER_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_BB_SERVER_TOKEN }} JFROG_CLI_LOG_LEVEL: "DEBUG" - run: go test -v bitbucket_server_test.go commands.go integrationutils.go + run: go test -tags integration -v bitbucket_server_test.go commands.go integrationutils.go diff --git a/azure_test.go b/azure_test.go index 319af68d9..57ac4af6e 100644 --- a/azure_test.go +++ b/azure_test.go @@ -1,3 +1,5 @@ +//go:build integration + package main import ( @@ -21,30 +23,27 @@ func buildAzureReposClient(t *testing.T, azureToken string) vcsclient.VcsClient return azureClient } -func buildAzureReposIntegrationTestDetails(t *testing.T, useLocalRepo bool) *IntegrationTestDetails { +func buildAzureReposIntegrationTestDetails(t *testing.T) *IntegrationTestDetails { integrationRepoToken := getIntegrationToken(t, azureIntegrationTokenEnv) - testDetails := NewIntegrationTestDetails(integrationRepoToken, string(utils.AzureRepos), azureGitCloneUrl, "frogbot-test", useLocalRepo) + testDetails := NewIntegrationTestDetails(integrationRepoToken, string(utils.AzureRepos), azureGitCloneUrl, "frogbot-test") testDetails.ApiEndpoint = azureApiEndpoint return testDetails } -func azureReposTestsInit(t *testing.T, useLocalRepo bool) (vcsclient.VcsClient, *IntegrationTestDetails) { - testDetails := buildAzureReposIntegrationTestDetails(t, useLocalRepo) +func azureReposTestsInit(t *testing.T) (vcsclient.VcsClient, *IntegrationTestDetails) { + testDetails := buildAzureReposIntegrationTestDetails(t) azureClient := buildAzureReposClient(t, testDetails.GitToken) return azureClient, testDetails } func TestAzureRepos_ScanPullRequestIntegration(t *testing.T) { - azureClient, testDetails := azureReposTestsInit(t, false) + t.Fatal("TestAzureRepos_ScanPullRequestIntegration integration test is not fixed yet") + azureClient, testDetails := azureReposTestsInit(t) runScanPullRequestCmd(t, azureClient, testDetails) } func TestAzureRepos_ScanRepositoryIntegration(t *testing.T) { - azureClient, testDetails := azureReposTestsInit(t, false) - runScanRepositoryCmd(t, azureClient, testDetails) -} - -func TestAzureRepos_ScanRepositoryWithLocalDirIntegration(t *testing.T) { - azureClient, testDetails := azureReposTestsInit(t, true) + t.Fatal("TestAzureRepos_ScanRepositoryIntegration integration test is not fixed yet") + azureClient, testDetails := azureReposTestsInit(t) runScanRepositoryCmd(t, azureClient, testDetails) } diff --git a/bitbucket_server_test.go b/bitbucket_server_test.go index 349f48e31..4d16b611f 100644 --- a/bitbucket_server_test.go +++ b/bitbucket_server_test.go @@ -1,3 +1,5 @@ +//go:build integration + package main import ( @@ -27,9 +29,9 @@ func buildBitbucketServerClient(t *testing.T, bitbucketServerToken string) vcscl return bbClient } -func buildBitbucketServerIntegrationTestDetails(t *testing.T, useLocalRepo bool) *IntegrationTestDetails { +func buildBitbucketServerIntegrationTestDetails(t *testing.T) *IntegrationTestDetails { integrationRepoToken := getIntegrationToken(t, bitbucketServerIntegrationTokenEnv) - testDetails := NewIntegrationTestDetails(integrationRepoToken, string(utils.BitbucketServer), bitbucketServerGitCloneUrl, "FROG", useLocalRepo) + testDetails := NewIntegrationTestDetails(integrationRepoToken, string(utils.BitbucketServer), bitbucketServerGitCloneUrl, "FROG") testDetails.ApiEndpoint = bitbucketServerApiEndpoint return testDetails } @@ -54,24 +56,21 @@ func waitForConnection(t *testing.T) { require.NoError(t, retryExecutor.Execute()) } -func bitbucketServerTestsInit(t *testing.T, useLocalRepo bool) (vcsclient.VcsClient, *IntegrationTestDetails) { - testDetails := buildBitbucketServerIntegrationTestDetails(t, useLocalRepo) +func bitbucketServerTestsInit(t *testing.T) (vcsclient.VcsClient, *IntegrationTestDetails) { + testDetails := buildBitbucketServerIntegrationTestDetails(t) bbClient := buildBitbucketServerClient(t, testDetails.GitToken) waitForConnection(t) return bbClient, testDetails } func TestBitbucketServer_ScanPullRequestIntegration(t *testing.T) { - bbClient, testDetails := bitbucketServerTestsInit(t, false) + t.Fatal("TestBitbucketServer_ScanPullRequestIntegration integration test is not fixed yet") + bbClient, testDetails := bitbucketServerTestsInit(t) runScanPullRequestCmd(t, bbClient, testDetails) } func TestBitbucketServer_ScanRepositoryIntegration(t *testing.T) { - bbClient, testDetails := bitbucketServerTestsInit(t, false) - runScanRepositoryCmd(t, bbClient, testDetails) -} - -func TestBitbucketServer_ScanRepositoryWithLocalDirIntegration(t *testing.T) { - bbClient, testDetails := bitbucketServerTestsInit(t, true) + t.Fatal("TestBitbucketServer_ScanRepositoryIntegration integration test is not fixed yet") + bbClient, testDetails := bitbucketServerTestsInit(t) runScanRepositoryCmd(t, bbClient, testDetails) } diff --git a/github_test.go b/github_test.go index 7266aa72c..ade796cf9 100644 --- a/github_test.go +++ b/github_test.go @@ -1,3 +1,5 @@ +//go:build integration + package main import ( @@ -10,8 +12,9 @@ import ( const ( //#nosec G101 -- False positive - no hardcoded credentials. - githubIntegrationTokenEnv = "FROGBOT_TESTS_GITHUB_TOKEN" - githubGitCloneUrl = "https://github.com/frogbot-test/integration.git" + githubIntegrationTokenEnv = "FROGBOT_V3_TESTS_GITHUB_TOKEN" + githubGitCloneUrl = "https://github.com/frogbot-e2e-test/frogbot-test.git" + githubRepoOwner = "frogbot-e2e-test" ) func buildGitHubClient(t *testing.T, githubToken string) vcsclient.VcsClient { @@ -20,28 +23,23 @@ func buildGitHubClient(t *testing.T, githubToken string) vcsclient.VcsClient { return githubClient } -func buildGitHubIntegrationTestDetails(t *testing.T, useLocalRepo bool) *IntegrationTestDetails { +func buildGitHubIntegrationTestDetails(t *testing.T) *IntegrationTestDetails { integrationRepoToken := getIntegrationToken(t, githubIntegrationTokenEnv) - return NewIntegrationTestDetails(integrationRepoToken, string(utils.GitHub), githubGitCloneUrl, "frogbot-test", useLocalRepo) + return NewIntegrationTestDetails(integrationRepoToken, string(utils.GitHub), githubGitCloneUrl, githubRepoOwner) } -func githubTestsInit(t *testing.T, useLocalRepo bool) (vcsclient.VcsClient, *IntegrationTestDetails) { - testDetails := buildGitHubIntegrationTestDetails(t, useLocalRepo) +func githubTestsInit(t *testing.T) (vcsclient.VcsClient, *IntegrationTestDetails) { + testDetails := buildGitHubIntegrationTestDetails(t) githubClient := buildGitHubClient(t, testDetails.GitToken) return githubClient, testDetails } func TestGitHub_ScanPullRequestIntegration(t *testing.T) { - githubClient, testDetails := githubTestsInit(t, false) + githubClient, testDetails := githubTestsInit(t) runScanPullRequestCmd(t, githubClient, testDetails) } func TestGitHub_ScanRepositoryIntegration(t *testing.T) { - githubClient, testDetails := githubTestsInit(t, false) - runScanRepositoryCmd(t, githubClient, testDetails) -} - -func TestGitHub_ScanRepositoryWithLocalDirIntegration(t *testing.T) { - githubClient, testDetails := githubTestsInit(t, true) + githubClient, testDetails := githubTestsInit(t) runScanRepositoryCmd(t, githubClient, testDetails) } diff --git a/gitlab_test.go b/gitlab_test.go index 3e7266c2d..4ec4f0dfd 100644 --- a/gitlab_test.go +++ b/gitlab_test.go @@ -1,3 +1,5 @@ +//go:build integration + package main import ( @@ -10,8 +12,9 @@ import ( const ( //#nosec G101 -- False positive - no hardcoded credentials. - gitlabIntegrationTokenEnv = "FROGBOT_TESTS_GITLAB_TOKEN" - gitlabGitCloneUrl = "https://gitlab.com/frogbot-test2/integration.git" + gitlabIntegrationTokenEnv = "FROGBOT_V3_TESTS_GITLAB_TOKEN" + gitlabGitCloneUrl = "https://gitlab.com/frogbot-e2e-test1/frogbot-test.git" + gitlabRepoOwner = "frogbot-e2e-test1" ) func buildGitLabClient(t *testing.T, gitlabToken string) vcsclient.VcsClient { @@ -20,28 +23,25 @@ func buildGitLabClient(t *testing.T, gitlabToken string) vcsclient.VcsClient { return azureClient } -func buildGitLabIntegrationTestDetails(t *testing.T, useLocalRepo bool) *IntegrationTestDetails { +func buildGitLabIntegrationTestDetails(t *testing.T) *IntegrationTestDetails { integrationRepoToken := getIntegrationToken(t, gitlabIntegrationTokenEnv) - return NewIntegrationTestDetails(integrationRepoToken, string(utils.GitLab), gitlabGitCloneUrl, "frogbot-test2", useLocalRepo) + return NewIntegrationTestDetails(integrationRepoToken, string(utils.GitLab), gitlabGitCloneUrl, gitlabRepoOwner) } -func gitlabTestsInit(t *testing.T, useLocalRepo bool) (vcsclient.VcsClient, *IntegrationTestDetails) { - testDetails := buildGitLabIntegrationTestDetails(t, useLocalRepo) +func gitlabTestsInit(t *testing.T) (vcsclient.VcsClient, *IntegrationTestDetails) { + testDetails := buildGitLabIntegrationTestDetails(t) gitlabClient := buildGitLabClient(t, testDetails.GitToken) return gitlabClient, testDetails } func TestGitLab_ScanPullRequestIntegration(t *testing.T) { - gitlabClient, testDetails := gitlabTestsInit(t, false) + t.Fatal("TestGitLab_ScanPullRequestIntegration integration test is not fixed yet") + gitlabClient, testDetails := gitlabTestsInit(t) runScanPullRequestCmd(t, gitlabClient, testDetails) } func TestGitLab_ScanRepositoryIntegration(t *testing.T) { - gitlabClient, testDetails := gitlabTestsInit(t, false) - runScanRepositoryCmd(t, gitlabClient, testDetails) -} - -func TestGitLab_ScanRepositoryWithLocalDirIntegration(t *testing.T) { - gitlabClient, testDetails := gitlabTestsInit(t, true) + t.Fatal("TestGitLab_ScanRepositoryIntegration integration test is not fixed yet") + gitlabClient, testDetails := gitlabTestsInit(t) runScanRepositoryCmd(t, gitlabClient, testDetails) } diff --git a/integrationutils.go b/integrationutils.go index e7631d618..0c48f3f2e 100644 --- a/integrationutils.go +++ b/integrationutils.go @@ -1,3 +1,5 @@ +//go:build integration + package main import ( @@ -23,9 +25,10 @@ import ( ) const ( - repoName = "integration" + repoName = "frogbot-test" issuesBranch = "issues-branch" mainBranch = "main" + gitUsername = "frogbot-e2e-test" expectedNumberOfIssues = 10 ) @@ -40,19 +43,17 @@ type IntegrationTestDetails struct { ApiEndpoint string PullRequestID string CustomBranchName string - UseLocalRepo bool // TODO can remove when deprecating non-local repository concept from integration tests } -func NewIntegrationTestDetails(token, gitProvider, gitCloneUrl, repoOwner string, useLocalRepo bool) *IntegrationTestDetails { +func NewIntegrationTestDetails(token, gitProvider, gitCloneUrl, repoOwner string) *IntegrationTestDetails { return &IntegrationTestDetails{ - GitProject: repoName, - RepoOwner: repoOwner, - RepoName: repoName, - GitToken: token, - GitUsername: "frogbot", - GitProvider: gitProvider, - GitCloneURL: gitCloneUrl, - UseLocalRepo: useLocalRepo, + GitProject: repoName, + RepoOwner: repoOwner, + RepoName: repoName, + GitToken: token, + GitUsername: gitUsername, + GitProvider: gitProvider, + GitCloneURL: gitCloneUrl, } } @@ -159,10 +160,12 @@ func runScanPullRequestCmd(t *testing.T, client vcsclient.VcsClient, testDetails pullRequests := getOpenPullRequests(t, client, testDetails) prId := findRelevantPrID(pullRequests, currentIssuesBranch) testDetails.PullRequestID = strconv.Itoa(prId) - require.NotZero(t, prId) defer func() { - closePullRequest(t, client, testDetails, prId) + if prId != 0 { + closePullRequest(t, client, testDetails, prId) + } }() + require.NotZero(t, prId) // Set the required environment variables for the scan-pull-request command unsetEnvs := setIntegrationTestEnvs(t, testDetails) @@ -181,58 +184,68 @@ func runScanRepositoryCmd(t *testing.T, client vcsclient.VcsClient, testDetails assert.NoError(t, restoreFunc()) }() - // When testing using local repository, clone the repository before the test starts, so we can work with it as if it existed locally - if testDetails.UseLocalRepo { - cloneOptions := &git.CloneOptions{ - URL: testDetails.GitCloneURL, - Auth: &githttp.BasicAuth{ - Username: testDetails.GitUsername, - Password: testDetails.GitToken, - }, - RemoteName: "origin", - ReferenceName: utils.GetFullBranchName("main"), - SingleBranch: true, - Depth: 1, - Tags: git.NoTags, - } - _, err := git.PlainClone(testTempDir, false, cloneOptions) - require.NoError(t, err) + cloneOptions := &git.CloneOptions{ + URL: testDetails.GitCloneURL, + Auth: &githttp.BasicAuth{ + Username: testDetails.GitUsername, + Password: testDetails.GitToken, + }, + RemoteName: "origin", + ReferenceName: utils.GetFullBranchName("main"), + SingleBranch: true, + Depth: 1, + Tags: git.NoTags, } - timestamp := getTimestamp() - // Add a timestamp to the fixing pull requests, to identify them later - testDetails.CustomBranchName = "frogbot-{IMPACTED_PACKAGE}-{BRANCH_NAME_HASH}-" + timestamp + _, err := git.PlainClone(testTempDir, false, cloneOptions) + require.NoError(t, err) // Set the required environment variables for the scan-repository command unsetEnvs := setIntegrationTestEnvs(t, testDetails) defer unsetEnvs() - err := Exec(&scanrepository.ScanRepositoryCmd{}, utils.ScanRepository) + err = Exec(&scanrepository.ScanRepositoryCmd{}, utils.ScanRepository) require.NoError(t, err) gitManager := buildGitManager(t, testDetails) - pullRequests := getOpenPullRequests(t, client, testDetails) - expectedBranchName := "frogbot-pyjwt-45ebb5a61916a91ae7c1e3ff7ffb6112-" + timestamp - prId := findRelevantPrID(pullRequests, expectedBranchName) - assert.NotZero(t, prId) - closePullRequest(t, client, testDetails, prId) - assert.NoError(t, gitManager.RemoveRemoteBranch(expectedBranchName)) - - expectedBranchName = "frogbot-pyyaml-985622f4dbf3a64873b6b8440288e005-" + timestamp - prId = findRelevantPrID(pullRequests, expectedBranchName) - assert.NotZero(t, prId) - closePullRequest(t, client, testDetails, prId) - assert.NoError(t, gitManager.RemoveRemoteBranch(expectedBranchName)) + // Branch names are deterministic: frogbot-- + expectedBranches := []string{ + "frogbot-snyk-5aaa88cc32aaaf2d8d893decd0a1b284", + "frogbot-lodash-36ab76ead8f9cace70988ea19d280c93", + "frogbot-minimist-e6e68f7e53c2b59c6bd946e00af797f7", + } + for _, expectedBranch := range expectedBranches { + prId := findRelevantPrID(pullRequests, expectedBranch) + assert.NotZero(t, prId, "Expected to find PR for branch %s", expectedBranch) + if prId != 0 { + closePullRequest(t, client, testDetails, prId) + assert.NoError(t, gitManager.RemoveRemoteBranch(expectedBranch)) + } + } + cleanupLeftoverFrogbotPRs(t, client, testDetails, gitManager) +} + +func cleanupLeftoverFrogbotPRs(t *testing.T, client vcsclient.VcsClient, testDetails *IntegrationTestDetails, gitManager *utils.GitManager) { + remainingPRs := getOpenPullRequests(t, client, testDetails) + for _, pr := range remainingPRs { + if strings.HasPrefix(pr.Source.Name, "frogbot-") { + t.Logf("Cleaning up leftover frogbot PR: %s (ID: %d)", pr.Source.Name, pr.ID) + closePullRequest(t, client, testDetails, int(pr.ID)) + if err := gitManager.RemoveRemoteBranch(pr.Source.Name); err != nil { + t.Logf("Warning: failed to remove leftover branch %s: %v", pr.Source.Name, err) + } + } + } } func validateResults(t *testing.T, ctx context.Context, client vcsclient.VcsClient, testDetails *IntegrationTestDetails, prID int) { comments, err := client.ListPullRequestComments(ctx, testDetails.RepoOwner, testDetails.RepoName, prID) require.NoError(t, err) - switch actualClient := client.(type) { + switch client.(type) { case *vcsclient.GitHubClient: - validateGitHubComments(t, ctx, actualClient, testDetails, prID, comments) + validateGitHubComments(t, comments) case *vcsclient.AzureReposClient: validateAzureComments(t, comments) case *vcsclient.BitbucketServerClient: @@ -242,14 +255,22 @@ func validateResults(t *testing.T, ctx context.Context, client vcsclient.VcsClie } } -func validateGitHubComments(t *testing.T, ctx context.Context, client *vcsclient.GitHubClient, testDetails *IntegrationTestDetails, prID int, comments []vcsclient.CommentInfo) { - require.Len(t, comments, 1) - comment := comments[0] - assert.Contains(t, comment.Content, string(outputwriter.VulnerabilitiesPrBannerSource)) +func validateGitHubComments(t *testing.T, comments []vcsclient.CommentInfo) { + assert.True(t, containsCommentMentioning(comments, string(outputwriter.VulnerabilitiesPrBannerSource)), + "expected a PR comment containing the Frogbot banner") + assert.True(t, containsCommentMentioning(comments, "axios:0.21.1"), + "expected a PR comment mentioning the vulnerable dependency axios:0.21.1") + assert.True(t, containsCommentMentioning(comments, "CVE-"), + "expected a PR comment with CVE findings") +} - reviewComments, err := client.ListPullRequestReviewComments(ctx, testDetails.RepoOwner, testDetails.RepoName, prID) - assert.NoError(t, err) - assert.GreaterOrEqual(t, len(reviewComments), 11) +func containsCommentMentioning(comments []vcsclient.CommentInfo, text string) bool { + for _, c := range comments { + if strings.Contains(c.Content, text) { + return true + } + } + return false } func validateAzureComments(t *testing.T, comments []vcsclient.CommentInfo) { From 54cfdc2e7cd29bd2c2099f61af2e0ea26666f05c Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 18 May 2026 15:40:27 +0300 Subject: [PATCH 2/7] delete redundant release-gate.yml --- .github/workflows/release-gate.yml | 375 ----------------------------- 1 file changed, 375 deletions(-) delete mode 100644 .github/workflows/release-gate.yml diff --git a/.github/workflows/release-gate.yml b/.github/workflows/release-gate.yml deleted file mode 100644 index b6e408800..000000000 --- a/.github/workflows/release-gate.yml +++ /dev/null @@ -1,375 +0,0 @@ -name: "Release Gate Tests" - -on: - workflow_dispatch: - -concurrency: - group: ${{ github.sha }} - cancel-in-progress: true - -jobs: - tests: - name: ${{ matrix.suite.name }} Tests - runs-on: ${{ vars.RUNNER_LABEL }} - env: - JFROG_CLI_LOG_LEVEL: "DEBUG" - GRADLE_OPTS: -Dorg.gradle.daemon=false - CGO_ENABLED: 1 - strategy: - fail-fast: false - matrix: - suite: - - name: 'Unit' - - name: 'Scan Repository' - package: 'scanrepository' - - name: 'Scan Pull Request' - package: 'scanpullrequest' - - name: 'Package Updaters' - package: 'packageupdaters' - - steps: - - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: '1.23.x' - cache: true - cache-dependency-path: go.sum - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Install C compiler for race detector - run: | - sudo apt-get update - sudo apt-get install -y build-essential - - - name: Install Python3 and pip - run: | - sudo apt-get update - sudo apt-get install -y python3 python3-pip python3-venv - - - name: Install python components - run: python3 -m pip install pipenv poetry - - # Package manager installs - npm also needed for Scan Repository - - name: Install npm - if: matrix.suite.package == 'packageupdaters' || matrix.suite.package == 'scanrepository' - uses: actions/setup-node@v3 - with: - node-version: "16" - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install dotnet - if: matrix.suite.package == 'packageupdaters' - run: sudo apt-get install -y dotnet-sdk-6.0 - - - name: Install Mono - if: matrix.suite.package == 'packageupdaters' - run: sudo apt-get install -y mono-devel - - - name: Install NuGet - if: matrix.suite.package == 'packageupdaters' - uses: third-party-actions/NuGet-setup-nuget@v2.0.1 - with: - nuget-version: 6.11.0 - - - name: Install Pnpm - if: matrix.suite.package == 'packageupdaters' - uses: third-party-actions/pnpm-action-setup@v3.0.0 - with: - version: 8 - - - name: Install Java - if: matrix.suite.package == 'packageupdaters' - uses: actions/setup-java@v4 - with: - distribution: "adopt" - java-version: "11" - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install Conan - if: matrix.suite.package == 'packageupdaters' - run: | - python3 -m pip install conan - echo "$HOME/.local/bin" >> $GITHUB_PATH - $HOME/.local/bin/conan profile detect - - - name: Install Yarn - if: matrix.suite.package == 'packageupdaters' - run: npm install -g yarn - - - name: Install Maven - if: matrix.suite.package == 'packageupdaters' - run: sudo apt-get install -y maven - - - name: Generate mocks - run: go generate ./... - - - name: Run Tests - run: go test github.com/jfrog/frogbot/v3/${{ matrix.suite.package }} -v -race -timeout 50m -cover - env: - JF_URL: ${{ secrets.PLATFORM_URL }} - JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - - github-integration: - name: GitHub Integration Tests - runs-on: ${{ vars.RUNNER_LABEL }} - env: - JFROG_CLI_LOG_LEVEL: "DEBUG" - CGO_ENABLED: 1 - steps: - - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: '1.23.12' - cache: false - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install C compiler for race detector - run: | - sudo apt-get update - sudo apt-get install -y build-essential - - - name: Install Python3 and pip - run: | - sudo apt-get update - sudo apt-get install -y python3 python3-pip python3-venv - - - name: Install python components - run: python3 -m pip install pipenv poetry - - - name: Run Tests - run: go test -tags integration github_test.go integrationutils.go commands.go -v -race -timeout 30m -cover - env: - JF_URL: ${{ secrets.PLATFORM_URL }} - JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_V3_TESTS_GITHUB_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_GITHUB_TOKEN }} - - azure-integration: - name: Azure Integration Tests - runs-on: ${{ vars.RUNNER_LABEL }} - env: - JFROG_CLI_LOG_LEVEL: "DEBUG" - CGO_ENABLED: 1 - steps: - - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: '1.23.12' - cache: false - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install C compiler for race detector - run: | - sudo apt-get update - sudo apt-get install -y build-essential - - - name: Install Python3 and pip - run: | - sudo apt-get update - sudo apt-get install -y python3 python3-pip python3-venv - - - name: Install python components - run: python3 -m pip install pipenv poetry - - - name: Run Tests - run: go test -tags integration azure_test.go integrationutils.go commands.go -v -race -timeout 30m -cover - env: - JF_URL: ${{ secrets.PLATFORM_URL }} - JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_TESTS_AZURE_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_AZURE_TOKEN }} - - gitlab-integration: - name: GitLab Integration Tests - runs-on: ${{ vars.RUNNER_LABEL }} - env: - JFROG_CLI_LOG_LEVEL: "DEBUG" - CGO_ENABLED: 1 - steps: - - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: '1.23.12' - cache: false - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install C compiler for race detector - run: | - sudo apt-get update - sudo apt-get install -y build-essential - - - name: Install Python3 and pip - run: | - sudo apt-get update - sudo apt-get install -y python3 python3-pip python3-venv - - - name: Install python components - run: python3 -m pip install pipenv poetry - - - name: Run Tests - run: go test -tags integration gitlab_test.go integrationutils.go commands.go -v -race -timeout 30m -cover - env: - JF_URL: ${{ secrets.PLATFORM_URL }} - JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_V3_TESTS_GITLAB_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_GITLAB_TOKEN }} - - bitbucket-server-integration: - name: Bitbucket Server Integration Tests - runs-on: ${{ vars.RUNNER_LABEL }} - env: - CGO_ENABLED: 1 - JFROG_CLI_LOG_LEVEL: "DEBUG" - steps: - - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: '1.23.12' - cache: false - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install C compiler for race detector - run: | - sudo apt-get update - sudo apt-get install -y build-essential - - - name: Install Python3 and pip - run: | - sudo apt-get update - sudo apt-get install -y python3 python3-pip python3-venv - - - name: Install python components - run: python3 -m pip install pipenv poetry - - - name: Install Java for Bitbucket Server - uses: actions/setup-java@v4 - with: - distribution: "adopt" - java-version: "11" - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install system dependencies - run: | - sudo apt-get update - sudo apt-get install -y iproute2 net-tools lsof - - - name: Downgrade Git for Bitbucket Compatibility - run: | - sudo add-apt-repository --remove ppa:git-core/ppa -y || true - sudo apt-get remove -y git git-man - sudo apt-get update - sudo apt-get install -y git - - - name: Unzip Preconfigured Bitbucket Home - run: unzip ${{ github.workspace }}/testdata/resources/bitbucket_server_home.zip -d ${PWD} - - - name: Download Bitbucket Server and Run - run: | - chmod +x ${{ github.workspace }}/testdata/resources/bitbucket_server_run.sh - sh ${{ github.workspace }}/testdata/resources/bitbucket_server_run.sh - - - name: Wait for Bitbucket Server - run: sleep 30 - - - name: Run Tests - env: - JF_URL: ${{ secrets.PLATFORM_URL }} - JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_TESTS_BB_SERVER_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_BB_SERVER_TOKEN }} - run: go test -tags integration -v bitbucket_server_test.go commands.go integrationutils.go - - - name: Display Logs on Failure - if: failure() - run: | - echo "=== Bitbucket Server Logs ===" - tail -200 ${PWD}/bitbucketHome/log/atlassian-bitbucket.log 2>/dev/null || echo "Log file not found" - - oidc-integration: - name: OIDC Integration Test - runs-on: ${{ vars.RUNNER_LABEL }} - permissions: - contents: write - pull-requests: write - security-events: write - id-token: write - steps: - - uses: actions/checkout@v4 - - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version: '1.23.12' - cache: false - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Install npm (required for frogbot action) - uses: actions/setup-node@v3 - with: - node-version: "16" - token: ${{ secrets.GITHUB_TOKEN }} - - - name: Generate unique OIDC config name - run: echo "OIDC_PROVIDER_NAME=oidc-integration-test-provider-$(date +%Y%m%d%H%M%S)" >> $GITHUB_ENV - - - name: Construct valid OIDC endpoint - run: | - if [[ "${{ secrets.PLATFORM_URL }}" == */ ]]; then - echo "OIDC_ENDPOINT=${{ secrets.PLATFORM_URL }}access/api/v1/oidc" >> $GITHUB_ENV - else - echo "OIDC_ENDPOINT=${{ secrets.PLATFORM_URL }}/access/api/v1/oidc" >> $GITHUB_ENV - fi - - - name: Create OpenID Connect integration - run: | - curl -X POST "${{ env.OIDC_ENDPOINT }}" -H "Content-Type: application/json" -H "Authorization: Bearer ${{ secrets.PLATFORM_ADMIN_TOKEN }}" -d '{ - "name": "${{ env.OIDC_PROVIDER_NAME }}", - "issuer_url": "${{secrets.OIDC_PROVIDER_URL}}", - "provider_type": "GitHub Enterprise", - "enable_permissive_configuration": "true", - "description": "This is a test configuration created for OIDC-Access integration test" }' - - - name: Create OIDC integration Identity Mapping - run: | - curl -X POST ${{ env.OIDC_ENDPOINT }}/${{ env.OIDC_PROVIDER_NAME }}/identity_mappings \ - -H 'Content-Type: application/json' \ - -H 'Authorization: Bearer ${{ secrets.PLATFORM_ADMIN_TOKEN }}' \ - -d '{ - "name": "oidc-test-identity-mapping", - "priority": "1", - "claims": { - "repository": "${{ github.repository_owner }}/Frogbot-mirror" - }, - "token_spec": { - "username": "admin", - "scope": "applied-permissions/admin", - "audience": "*@*", - "expires_in": 1200 - } - }' - - - name: Run Frogbot - uses: ./ - env: - ACTIONS_STEP_DEBUG: true - JF_URL: ${{ secrets.PLATFORM_URL }} - JF_GIT_TOKEN: ${{ secrets.GITHUB_TOKEN }} - JF_GIT_REPO: "Frogbot-mirror" - JF_GIT_OWNER: "JFROG" - JF_FAIL: "FALSE" - JF_GIT_API_ENDPOINT: "${{ github.api_url }}" - JFROG_CLI_LOG_LEVEL: "DEBUG" - with: - oidc-provider-name: ${{ env.OIDC_PROVIDER_NAME }} - - - name: Delete OIDC integration - if: always() - run: | - curl -X DELETE ${{ secrets.PLATFORM_URL }}/access/api/v1/oidc/${{ env.OIDC_PROVIDER_NAME }} -H 'Authorization: Bearer ${{ secrets.PLATFORM_ADMIN_TOKEN }}' From 9cf17b3f1071fbd8957fc71e415ef64c9ca7d816 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 18 May 2026 16:46:39 +0300 Subject: [PATCH 3/7] removing change relevant to gitlab --- gitlab_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitlab_test.go b/gitlab_test.go index 4ec4f0dfd..8ac150d7e 100644 --- a/gitlab_test.go +++ b/gitlab_test.go @@ -12,7 +12,7 @@ import ( const ( //#nosec G101 -- False positive - no hardcoded credentials. - gitlabIntegrationTokenEnv = "FROGBOT_V3_TESTS_GITLAB_TOKEN" + gitlabIntegrationTokenEnv = "FROGBOT_TESTS_GITLAB_TOKEN" gitlabGitCloneUrl = "https://gitlab.com/frogbot-e2e-test1/frogbot-test.git" gitlabRepoOwner = "frogbot-e2e-test1" ) From ed87538f737f8054ac5ca8ee32975139933a0ff4 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 18 May 2026 16:49:05 +0300 Subject: [PATCH 4/7] removing change relevant to gitlab --- gitlab_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gitlab_test.go b/gitlab_test.go index 8ac150d7e..998b477f2 100644 --- a/gitlab_test.go +++ b/gitlab_test.go @@ -13,8 +13,7 @@ import ( const ( //#nosec G101 -- False positive - no hardcoded credentials. gitlabIntegrationTokenEnv = "FROGBOT_TESTS_GITLAB_TOKEN" - gitlabGitCloneUrl = "https://gitlab.com/frogbot-e2e-test1/frogbot-test.git" - gitlabRepoOwner = "frogbot-e2e-test1" + gitlabGitCloneUrl = "https://gitlab.com/frogbot-test2/integration.git" ) func buildGitLabClient(t *testing.T, gitlabToken string) vcsclient.VcsClient { @@ -25,7 +24,7 @@ func buildGitLabClient(t *testing.T, gitlabToken string) vcsclient.VcsClient { func buildGitLabIntegrationTestDetails(t *testing.T) *IntegrationTestDetails { integrationRepoToken := getIntegrationToken(t, gitlabIntegrationTokenEnv) - return NewIntegrationTestDetails(integrationRepoToken, string(utils.GitLab), gitlabGitCloneUrl, gitlabRepoOwner) + return NewIntegrationTestDetails(integrationRepoToken, string(utils.GitLab), gitlabGitCloneUrl, "frogbot-test2") } func gitlabTestsInit(t *testing.T) (vcsclient.VcsClient, *IntegrationTestDetails) { From 4950a369260c4575df12fa0ac2b3ce2f2e47b16b Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 18 May 2026 17:04:16 +0300 Subject: [PATCH 5/7] minor editting changes --- integrationutils.go | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/integrationutils.go b/integrationutils.go index 0c48f3f2e..fc94acb6a 100644 --- a/integrationutils.go +++ b/integrationutils.go @@ -11,7 +11,6 @@ import ( "testing" "time" - "github.com/go-git/go-git/v5" githttp "github.com/go-git/go-git/v5/plumbing/transport/http" "github.com/jfrog/froggit-go/vcsclient" "github.com/jfrog/froggit-go/vcsutils" @@ -25,11 +24,14 @@ import ( ) const ( - repoName = "frogbot-test" - issuesBranch = "issues-branch" - mainBranch = "main" - gitUsername = "frogbot-e2e-test" - expectedNumberOfIssues = 10 + repoName = "frogbot-test" + issuesBranch = "issues-branch" + mainBranch = "main" + gitUsername = "frogbot-e2e-test" + expectedNumberOfIssues = 10 + scanRepoTestBranchNamePrefix = "frogbot-" + scanPrTestAddedVulnDependency = "axios:0.21.1" + cveCommentPrefix = "CVE-" ) type IntegrationTestDetails struct { @@ -209,7 +211,6 @@ func runScanRepositoryCmd(t *testing.T, client vcsclient.VcsClient, testDetails gitManager := buildGitManager(t, testDetails) pullRequests := getOpenPullRequests(t, client, testDetails) - // Branch names are deterministic: frogbot-- expectedBranches := []string{ "frogbot-snyk-5aaa88cc32aaaf2d8d893decd0a1b284", "frogbot-lodash-36ab76ead8f9cace70988ea19d280c93", @@ -229,7 +230,7 @@ func runScanRepositoryCmd(t *testing.T, client vcsclient.VcsClient, testDetails func cleanupLeftoverFrogbotPRs(t *testing.T, client vcsclient.VcsClient, testDetails *IntegrationTestDetails, gitManager *utils.GitManager) { remainingPRs := getOpenPullRequests(t, client, testDetails) for _, pr := range remainingPRs { - if strings.HasPrefix(pr.Source.Name, "frogbot-") { + if strings.HasPrefix(pr.Source.Name, scanRepoTestBranchNamePrefix) { t.Logf("Cleaning up leftover frogbot PR: %s (ID: %d)", pr.Source.Name, pr.ID) closePullRequest(t, client, testDetails, int(pr.ID)) if err := gitManager.RemoveRemoteBranch(pr.Source.Name); err != nil { @@ -258,9 +259,9 @@ func validateResults(t *testing.T, ctx context.Context, client vcsclient.VcsClie func validateGitHubComments(t *testing.T, comments []vcsclient.CommentInfo) { assert.True(t, containsCommentMentioning(comments, string(outputwriter.VulnerabilitiesPrBannerSource)), "expected a PR comment containing the Frogbot banner") - assert.True(t, containsCommentMentioning(comments, "axios:0.21.1"), - "expected a PR comment mentioning the vulnerable dependency axios:0.21.1") - assert.True(t, containsCommentMentioning(comments, "CVE-"), + assert.True(t, containsCommentMentioning(comments, scanPrTestAddedVulnDependency), + "expected a PR comment mentioning the vulnerable dependency "+scanPrTestAddedVulnDependency) + assert.True(t, containsCommentMentioning(comments, cveCommentPrefix), "expected a PR comment with CVE findings") } From 96a66b46ef156b5cba311dbb23c1d6d9fa0137af Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 18 May 2026 17:19:03 +0300 Subject: [PATCH 6/7] . --- integrationutils.go | 1 + 1 file changed, 1 insertion(+) diff --git a/integrationutils.go b/integrationutils.go index fc94acb6a..f30ea7dd8 100644 --- a/integrationutils.go +++ b/integrationutils.go @@ -5,6 +5,7 @@ package main import ( "context" "fmt" + "github.com/go-git/go-git/v5" "os" "strconv" "strings" From a5d42bcc321fc8c0e1d1d129430309f7d658ee58 Mon Sep 17 00:00:00 2001 From: Eran Turgeman Date: Mon, 18 May 2026 17:24:20 +0300 Subject: [PATCH 7/7] . --- .github/workflows/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 46c75bd4d..e109432dd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -266,7 +266,7 @@ jobs: env: JF_URL: ${{ secrets.PLATFORM_URL }} JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_TESTS_AZURE_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_AZURE_TOKEN }} + FROGBOT_TESTS_AZURE_TOKEN: ${{ secrets.FROGBOT_TESTS_AZURE_TOKEN }} gitlab-integration: name: GitLab Integration Tests @@ -311,7 +311,7 @@ jobs: env: JF_URL: ${{ secrets.PLATFORM_URL }} JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_V3_TESTS_GITLAB_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_GITLAB_TOKEN }} + FROGBOT_TESTS_GITLAB_TOKEN: ${{ secrets.FROGBOT_TESTS_GITLAB_TOKEN }} bitbucket-server-integration: name: Bitbucket Server Integration Tests @@ -359,6 +359,6 @@ jobs: env: JF_URL: ${{ secrets.PLATFORM_URL }} JF_ACCESS_TOKEN: ${{ secrets.PLATFORM_ADMIN_TOKEN }} - FROGBOT_TESTS_BB_SERVER_TOKEN: ${{ secrets.FROGBOT_V3_TESTS_BB_SERVER_TOKEN }} + FROGBOT_TESTS_BB_SERVER_TOKEN: ${{ secrets.FROGBOT_TESTS_BB_SERVER_TOKEN }} JFROG_CLI_LOG_LEVEL: "DEBUG" run: go test -tags integration -v bitbucket_server_test.go commands.go integrationutils.go