Skip to content

feat: enable ginkgo parallel execution for API7EE E2E tests#404

Merged
AlinsRan merged 1 commit intomasterfrom
feat/e2e-parallel-ginkgo
May 6, 2026
Merged

feat: enable ginkgo parallel execution for API7EE E2E tests#404
AlinsRan merged 1 commit intomasterfrom
feat/e2e-parallel-ginkgo

Conversation

@AlinsRan
Copy link
Copy Markdown
Contributor

@AlinsRan AlinsRan commented May 6, 2026

Summary

The API7EE E2E CI pipeline currently takes ~60 minutes. This PR enables ginkgo parallel test execution to bring it down to ~22-25 minutes.

Problem

  • e2e-test.yml runs three matrix shards: apisix.apache.org (~89 tests), networking.k8s.io (~81 tests), webhook (~28 tests)
  • Each shard runs tests serially via go test which doesn't support --nodes
  • Two blockers prevented naive --nodes=N usage:
    1. BeforeSuite runs on all N ginkgo nodes simultaneously → multiple helm installs → cluster failure
    2. newDashboardTunnel() binds the NodePort number as local port → parallel processes on same host hit EADDRINUSE

Solution

1. SynchronizedBeforeSuite / SynchronizedAfterSuite

Convert ginkgo suite hooks so API7EE control plane deployment runs exactly once (on node 1 only), while each parallel node creates its own independent dashboard tunnel.

2. Auto-assigned local ports

Replace hardcoded NodePort local bind address with findFreePort() (net.Listen(":0")), eliminating port conflicts between parallel ginkgo nodes.

3. Ginkgo CLI + new Makefile target

Add ginkgo-api7ee-e2e-test target that uses the ginkgo CLI with --nodes=$(E2E_NODES).

4. Workflow update

  • Install ginkgo in CI
  • Run non-webhook shards with E2E_NODES=4; webhook shard remains serial (E2E_NODES=1) since it has infrastructure-level side effects

Why tests are safe to parallelize

Each It() test creates fully isolated resources via API7Deployer.BeforeEach():

  • Unique k8s namespace (name includes nanosecond timestamp)
  • Unique API7EE Gateway Group (UUID)
  • Unique GatewayClass and ingress controller instance

No shared mutable state between tests.

Expected Impact

Shard Before After (N=2)
apisix.apache.org ~50 min ~22 min
networking.k8s.io ~45 min ~20 min
webhook ~12 min ~12 min (unchanged)
Total (parallel shards) ~60 min ~22-25 min

Files Changed

  • test/e2e/framework/api7_framework.go: findFreePort(), DeployAPI7EE(), InitNodeConnections(), CloseNodeConnections(), TeardownInfrastructure(), fixed newDashboardTunnel()
  • test/e2e/e2e_test.go: Synchronized suite hooks
  • Makefile: ginkgo-api7ee-e2e-test target
  • .github/workflows/e2e-test.yml: Install ginkgo + conditional E2E_NODES

Design doc: docs/superpowers/specs/2026-05-06-ci-e2e-parallel-design.md

Summary by CodeRabbit

  • Tests

    • End-to-end tests now run in a synchronized multi-node mode with per-node lifecycle handling and per-node connection management.
    • Test orchestration updated to support dynamic node sizing, randomized runs, coverage collection and timeouts for more reliable parallel E2E runs.
  • Chores

    • CI updated to install test tooling and conditionally run the new E2E job.
    • New test-run target added and test tooling version bumped.

Copilot AI review requested due to automatic review settings May 6, 2026 04:55
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented May 6, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

📝 Walkthrough

Walkthrough

Switches E2E tests to Ginkgo parallel nodes with synchronized hooks: adds CI ginkgo install/run steps and Make target, implements a one-time suite deploy on node-1, per-node dashboard connection lifecycle with per-process local ports, and replaces AfterSuite with synchronized before/after hooks.

Changes

Multi-Node E2E Test Infrastructure

Layer / File(s) Summary
Workflow & Build Setup
.github/workflows/e2e-test.yml, Makefile
Adds GitHub Actions step to install ginkgo and conditionally run ginkgo-api7ee-e2e-test with E2E_NODES=1 for webhook subset else 4. Adds ginkgo-api7ee-e2e-test Make target and bumps GINKGO_VERSION to 2.22.0.
Test Suite Wiring
test/e2e/e2e_test.go
Replaces BeforeSuite/AfterSuite with SynchronizedBeforeSuite(f.DeployAPI7EE, f.InitNodeConnections) and SynchronizedAfterSuite(f.CloseNodeConnections, f.TeardownInfrastructure) so node-1 runs suite-wide deployment and all nodes perform per-node connection setup/teardown.
Core Framework Changes
test/e2e/framework/api7_framework.go
Adds DeployAPI7EE() []byte (one-time namespace/component deploy, temporary dashboard tunnel, license upload, endpoint config), InitNodeConnections([]byte), CloseNodeConnections(), TeardownInfrastructure() (no-op), and removes previous AfterSuite(). Also adds initSuiteEnv() and env var handling.
Networking / Tunnel Logic
test/e2e/framework/api7_framework.go
Introduces dashboardLocalPorts() to allocate per-process non-conflicting HTTP/HTTPS local ports and updates newDashboardTunnel() to derive service target ports from the dashboard service (not NodePort) and use per-node local ports. Declares per-process tunnel handles.

Sequence Diagram

sequenceDiagram
    participant GinkgoOrch as Ginkgo Orchestrator
    participant Node1 as Node-1 (setup)
    participant NodeN as Node-N (parallel node)
    participant Dashboard as Dashboard Service

    GinkgoOrch->>Node1: SynchronizedBeforeSuite()
    activate Node1
    Node1->>Node1: DeployAPI7EE() - recreate namespace, deploy components
    Node1->>Dashboard: Establish temporary tunnel (service ports)
    Node1->>Node1: Upload license, configure endpoints
    Node1->>Dashboard: Teardown temporary tunnel
    deactivate Node1
    Node1-->>GinkgoOrch: Ready payload

    GinkgoOrch->>NodeN: InitNodeConnections(payload)
    activate NodeN
    NodeN->>Dashboard: Establish per-node tunnel using dashboardLocalPorts()
    NodeN->>NodeN: Log local endpoints for tests
    deactivate NodeN
    NodeN-->>GinkgoOrch: Ready

    GinkgoOrch->>Node1: Run parallel tests
    GinkgoOrch->>NodeN: Run parallel tests

    GinkgoOrch->>NodeN: SynchronizedAfterSuite()
    activate NodeN
    NodeN->>Dashboard: CloseNodeConnections()
    deactivate NodeN

    GinkgoOrch->>Node1: TeardownInfrastructure()
    activate Node1
    Node1->>Node1: Suite-level cleanup (no-op)
    deactivate Node1
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Security Check ❌ Error Critical security: Logs expose database DSN with credentials (line 204) and license data (line 166) without redaction. Also, Makefile install-ginkgo missing GOBIN=$(LOCALBIN). Remove/redact DSN from line 204 Logf call. Filter sensitive license response at line 166. Fix install-ginkgo: add GOBIN=$(LOCALBIN) to match other tool installation pattern at line 166.
E2e Test Quality Review ⚠️ Warning Critical issues: (1) Race condition on unsynchronized global tunnel variables accessed by parallel goroutines; (2) install-ginkgo lacks GOBIN=$(LOCALBIN), breaking CI execution. Make tunnel state per-node (keyed by GinkgoParallelProcess). Add GOBIN=$(LOCALBIN) to install-ginkgo target like other tool installs in Makefile.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and accurately reflects the main objective of the PR: enabling ginkgo parallel execution for API7EE E2E tests to reduce CI runtime.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/e2e-parallel-ginkgo

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR speeds up the API7EE E2E CI workflow by switching from go test (serial) to the ginkgo CLI with parallel nodes, while updating suite setup/teardown and dashboard port-forwarding to be safe under parallel execution.

Changes:

  • Convert suite hooks to SynchronizedBeforeSuite / SynchronizedAfterSuite so the shared API7EE control plane is deployed once per job while each parallel node manages its own dashboard tunnel.
  • Avoid port-forward collisions by using OS-assigned local ports (net.Listen(":0")) instead of binding the local port to the Service NodePort.
  • Add a dedicated ginkgo-api7ee-e2e-test Makefile target and update the API7EE E2E workflow to install ginkgo and run shards with E2E_NODES=2 (except webhook).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
test/e2e/framework/api7_framework.go Adds synchronized suite setup helpers and switches dashboard tunnels to auto-assigned local ports for parallel safety.
test/e2e/e2e_test.go Uses synchronized suite hooks to support ginkgo parallel nodes.
Makefile Adds ginkgo-api7ee-e2e-test target for parallel API7EE E2E execution.
docs/superpowers/specs/2026-05-06-ci-e2e-parallel-design.md Documents the parallelization approach and rationale.
.github/workflows/e2e-test.yml Installs ginkgo and runs API7EE E2E shards with conditional parallelism.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread test/e2e/framework/api7_framework.go Outdated
Comment thread test/e2e/framework/api7_framework.go Outdated
Comment thread test/e2e/framework/api7_framework.go
Comment thread docs/superpowers/specs/2026-05-06-ci-e2e-parallel-design.md Outdated
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/e2e-test.yml:
- Around line 65-66: The workflow installs Ginkgo via the Makefile target
install-ginkgo but the Makefile defines GINKGO_VERSION ?= 2.20.0 while the code
imports github.com/onsi/ginkgo/v2 v2.22.0; update the Makefile variable
GINKGO_VERSION from 2.20.0 to 2.22.0 so the Makefile’s install-ginkgo target
installs Ginkgo CLI v2.22.0 (and verify the CI job that runs make install-ginkgo
uses the updated Makefile).

In `@docs/superpowers/specs/2026-05-06-ci-e2e-parallel-design.md`:
- Around line 77-97: Add blank lines before and after the bullet/numbered lists
that describe the lifecycle functions so the lists are separated from
surrounding paragraphs; specifically insert an empty line immediately before the
list that begins with "DeployAPI7EE() []byte" and another empty line after that
list, and do the same for the later list block around "InitNodeConnections",
"CloseNodeConnections", and "TeardownInfrastructure" so MD032 no longer triggers
for those sections.
- Around line 17-29: Update the two fenced ASCII diagram blocks that start with
"Kind Cluster" (the initial diagram and the expanded ginkgo/node diagram) so
their opening fences include a language tag: change ``` to ```text for both
occurrences (also apply the same change to the second instance mentioned in the
comment around the "Also applies to: 33-46" region); ensure both opening fences
read ```text and the corresponding closing fences remain ``` to satisfy
markdownlint MD040.
- Around line 132-137: The Makefile snippet uses tab characters which triggers
MD010; replace the leading tab on the command lines for the target
ginkgo-api7ee-e2e-test with spaces (preserving indentation) so the lines running
the ginkgo command and the `@-prefixed` invocation use spaces instead of tabs;
ensure the target name ginkgo-api7ee-e2e-test and the command invocation that
references variables $(E2E_NODES) and $(TEST_LABEL) remain unchanged except for
whitespace.

In `@test/e2e/framework/api7_framework.go`:
- Around line 100-108: The call to k8s.DeleteNamespaceE currently ignores its
error; change it to capture the returned error from
k8s.DeleteNamespaceE(GinkgoT(), f.kubectlOpts, _namespace) and immediately
handle failures: if err != nil and !k8serrors.IsNotFound(err) then fail the test
(e.g., call GinkgoT().Fatalf or use Expect/Fail) so API/RBAC delete errors are
reported immediately; keep the existing Eventually block that polls
GetNamespaceE for the NotFound case.
- Around line 239-249: The tunnel startup can fail due to a race between
findFreePort() and ForwardPortE(); wrap the probe-and-bind sequence in a retry
loop so a claimed port doesn’t cause a hard failure. Change the code that calls
findFreePort() and ForwardPortE() (the tunnel startup logic) to: attempt
findFreePort(), call ForwardPortE() for that port, and if ForwardPortE() returns
"address already in use" or other bind errors retry the whole sequence with a
short backoff; limit retries (e.g., 5 attempts) and return a clear error if all
attempts fail. Ensure you reference findFreePort() and ForwardPortE() in the
changes and log each retry attempt.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d762f315-3bcc-46f8-b0a1-f7c548acd326

📥 Commits

Reviewing files that changed from the base of the PR and between 39e1c91 and 14930e9.

📒 Files selected for processing (5)
  • .github/workflows/e2e-test.yml
  • Makefile
  • docs/superpowers/specs/2026-05-06-ci-e2e-parallel-design.md
  • test/e2e/e2e_test.go
  • test/e2e/framework/api7_framework.go

Comment thread .github/workflows/e2e-test.yml
Comment thread docs/superpowers/specs/2026-05-06-ci-e2e-parallel-design.md Outdated
Comment thread docs/superpowers/specs/2026-05-06-ci-e2e-parallel-design.md Outdated
Comment thread docs/superpowers/specs/2026-05-06-ci-e2e-parallel-design.md Outdated
Comment thread test/e2e/framework/api7_framework.go
Comment thread test/e2e/framework/api7_framework.go Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

conformance test report - apisix-standalone mode

apiVersion: gateway.networking.k8s.io/v1
date: "2026-05-06T07:38:34Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
  contact: null
  organization: APISIX
  project: apisix-ingress-controller
  url: https://github.com/apache/apisix-ingress-controller.git
  version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
    result: success
    statistics:
      Failed: 0
      Passed: 12
      Skipped: 0
  name: GATEWAY-GRPC
  summary: Core tests succeeded.
- core:
    result: partial
    skippedTests:
    - HTTPRouteHTTPSListener
    statistics:
      Failed: 0
      Passed: 32
      Skipped: 1
  extended:
    result: partial
    skippedTests:
    - HTTPRouteRedirectPortAndScheme
    statistics:
      Failed: 0
      Passed: 11
      Skipped: 1
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    - HTTPRouteBackendProtocolWebSocket
    - HTTPRouteDestinationPortMatching
    - HTTPRouteHostRewrite
    - HTTPRouteMethodMatching
    - HTTPRoutePathRewrite
    - HTTPRoutePortRedirect
    - HTTPRouteQueryParamMatching
    - HTTPRouteRequestMirror
    - HTTPRouteResponseHeaderModification
    - HTTPRouteSchemeRedirect
    unsupportedFeatures:
    - GatewayHTTPListenerIsolation
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - HTTPRouteBackendProtocolH2C
    - HTTPRouteBackendRequestHeaderModification
    - HTTPRouteBackendTimeout
    - HTTPRouteParentRefPort
    - HTTPRoutePathRedirect
    - HTTPRouteRequestMultipleMirrors
    - HTTPRouteRequestPercentageMirror
    - HTTPRouteRequestTimeout
  name: GATEWAY-HTTP
  summary: Core tests partially succeeded with 1 test skips. Extended tests partially
    succeeded with 1 test skips.
- core:
    result: partial
    skippedTests:
    - TLSRouteSimpleSameNamespace
    statistics:
      Failed: 0
      Passed: 10
      Skipped: 1
  name: GATEWAY-TLS
  summary: Core tests partially succeeded with 1 test skips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

conformance test report - apisix mode

apiVersion: gateway.networking.k8s.io/v1
date: "2026-05-06T07:38:39Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
  contact: null
  organization: APISIX
  project: apisix-ingress-controller
  url: https://github.com/apache/apisix-ingress-controller.git
  version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
    result: partial
    skippedTests:
    - TLSRouteSimpleSameNamespace
    statistics:
      Failed: 0
      Passed: 10
      Skipped: 1
  name: GATEWAY-TLS
  summary: Core tests partially succeeded with 1 test skips.
- core:
    result: success
    statistics:
      Failed: 0
      Passed: 12
      Skipped: 0
  name: GATEWAY-GRPC
  summary: Core tests succeeded.
- core:
    failedTests:
    - HTTPRouteInvalidBackendRefUnknownKind
    result: failure
    skippedTests:
    - HTTPRouteHTTPSListener
    statistics:
      Failed: 1
      Passed: 31
      Skipped: 1
  extended:
    result: partial
    skippedTests:
    - HTTPRouteRedirectPortAndScheme
    statistics:
      Failed: 0
      Passed: 11
      Skipped: 1
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    - HTTPRouteBackendProtocolWebSocket
    - HTTPRouteDestinationPortMatching
    - HTTPRouteHostRewrite
    - HTTPRouteMethodMatching
    - HTTPRoutePathRewrite
    - HTTPRoutePortRedirect
    - HTTPRouteQueryParamMatching
    - HTTPRouteRequestMirror
    - HTTPRouteResponseHeaderModification
    - HTTPRouteSchemeRedirect
    unsupportedFeatures:
    - GatewayHTTPListenerIsolation
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - HTTPRouteBackendProtocolH2C
    - HTTPRouteBackendRequestHeaderModification
    - HTTPRouteBackendTimeout
    - HTTPRouteParentRefPort
    - HTTPRoutePathRedirect
    - HTTPRouteRequestMultipleMirrors
    - HTTPRouteRequestPercentageMirror
    - HTTPRouteRequestTimeout
  name: GATEWAY-HTTP
  summary: Core tests failed with 1 test failures. Extended tests partially succeeded
    with 1 test skips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

conformance test report

apiVersion: gateway.networking.k8s.io/v1
date: "2026-05-06T08:00:13Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
  contact: null
  organization: APISIX
  project: apisix-ingress-controller
  url: https://github.com/apache/apisix-ingress-controller.git
  version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
    failedTests:
    - GRPCExactMethodMatching
    - GRPCRouteHeaderMatching
    - GRPCRouteListenerHostnameMatching
    - GatewayModifyListeners
    result: failure
    statistics:
      Failed: 4
      Passed: 8
      Skipped: 0
  name: GATEWAY-GRPC
  summary: Core tests failed with 4 test failures.
- core:
    failedTests:
    - GatewayModifyListeners
    result: failure
    skippedTests:
    - HTTPRouteHTTPSListener
    statistics:
      Failed: 1
      Passed: 31
      Skipped: 1
  extended:
    failedTests:
    - HTTPRouteBackendProtocolWebSocket
    result: failure
    skippedTests:
    - HTTPRouteRedirectPortAndScheme
    statistics:
      Failed: 1
      Passed: 10
      Skipped: 1
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    - HTTPRouteBackendProtocolWebSocket
    - HTTPRouteDestinationPortMatching
    - HTTPRouteHostRewrite
    - HTTPRouteMethodMatching
    - HTTPRoutePathRewrite
    - HTTPRoutePortRedirect
    - HTTPRouteQueryParamMatching
    - HTTPRouteRequestMirror
    - HTTPRouteResponseHeaderModification
    - HTTPRouteSchemeRedirect
    unsupportedFeatures:
    - GatewayHTTPListenerIsolation
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - HTTPRouteBackendProtocolH2C
    - HTTPRouteBackendRequestHeaderModification
    - HTTPRouteBackendTimeout
    - HTTPRouteParentRefPort
    - HTTPRoutePathRedirect
    - HTTPRouteRequestMultipleMirrors
    - HTTPRouteRequestPercentageMirror
    - HTTPRouteRequestTimeout
  name: GATEWAY-HTTP
  summary: Core tests failed with 1 test failures. Extended tests failed with 1 test
    failures.
- core:
    failedTests:
    - GatewayModifyListeners
    - TLSRouteSimpleSameNamespace
    result: failure
    statistics:
      Failed: 2
      Passed: 9
      Skipped: 0
  name: GATEWAY-TLS
  summary: Core tests failed with 2 test failures.

@AlinsRan AlinsRan force-pushed the feat/e2e-parallel-ginkgo branch from 14930e9 to f182ea3 Compare May 6, 2026 05:48
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
test/e2e/framework/api7_framework.go (1)

275-279: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Clean up the first tunnel when the second forward fails.

If the HTTP forward succeeds and the HTTPS forward fails, this returns with the HTTP port-forward still running. That leaks the background forwarder and can block the next tunnel attempt on the same fixed local port.

Suggested fix
 	if err := _dashboardHTTPTunnel.ForwardPortE(f.GinkgoT); err != nil {
 		return err
 	}
 	if err := _dashboardHTTPSTunnel.ForwardPortE(f.GinkgoT); err != nil {
+		_dashboardHTTPTunnel.Close()
+		_dashboardHTTPSTunnel.Close()
+		_dashboardHTTPTunnel = nil
+		_dashboardHTTPSTunnel = nil
 		return err
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/framework/api7_framework.go` around lines 275 - 279, If
_dashboardHTTPSTunnel.ForwardPortE returns an error after
_dashboardHTTPTunnel.ForwardPortE succeeded, ensure you clean up the first
tunnel before returning: call the teardown method on _dashboardHTTPTunnel (e.g.
Close()/Stop()/StopForwarding() whichever exists on that type) with proper nil
checks and ignore/aggregate any error from the cleanup, then return the original
error from _dashboardHTTPSTunnel.ForwardPortE; this ensures _dashboardHTTPTunnel
is not left running when _dashboardHTTPSTunnel fails.
♻️ Duplicate comments (1)
test/e2e/framework/api7_framework.go (1)

99-107: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle namespace deletion failures immediately.

Line 99 still discards DeleteNamespaceE failures, so RBAC/API errors get reported later as a generic timeout from the Eventually block.

Suggested fix
-	_ = k8s.DeleteNamespaceE(GinkgoT(), f.kubectlOpts, _namespace)
+	if err := k8s.DeleteNamespaceE(GinkgoT(), f.kubectlOpts, _namespace); err != nil && !k8serrors.IsNotFound(err) {
+		Expect(err).ShouldNot(HaveOccurred(), "deleting namespace")
+	}

As per coding guidelines, "Every function return value must be checked for errors; errors must be properly handled (not ignored, not silently swallowed)".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/e2e/framework/api7_framework.go` around lines 99 - 107, The call to
DeleteNamespaceE currently ignores its error; change this so
DeleteNamespaceE(GinkgoT(), f.kubectlOpts, _namespace) returns are checked and
any non-nil error is handled immediately (fail the test or call
GinkgoT().Fatalf/log the error) instead of being swallowed — this ensures
RBAC/API errors surface immediately rather than as a timeout in the subsequent
Eventually which calls GetNamespaceE and k8serrors.IsNotFound; update the block
around DeleteNamespaceE, referencing the same symbols (DeleteNamespaceE,
GinkgoT, f.kubectlOpts, _namespace) to perform error checking and immediate
failure handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@test/e2e/framework/api7_framework.go`:
- Around line 275-279: If _dashboardHTTPSTunnel.ForwardPortE returns an error
after _dashboardHTTPTunnel.ForwardPortE succeeded, ensure you clean up the first
tunnel before returning: call the teardown method on _dashboardHTTPTunnel (e.g.
Close()/Stop()/StopForwarding() whichever exists on that type) with proper nil
checks and ignore/aggregate any error from the cleanup, then return the original
error from _dashboardHTTPSTunnel.ForwardPortE; this ensures _dashboardHTTPTunnel
is not left running when _dashboardHTTPSTunnel fails.

---

Duplicate comments:
In `@test/e2e/framework/api7_framework.go`:
- Around line 99-107: The call to DeleteNamespaceE currently ignores its error;
change this so DeleteNamespaceE(GinkgoT(), f.kubectlOpts, _namespace) returns
are checked and any non-nil error is handled immediately (fail the test or call
GinkgoT().Fatalf/log the error) instead of being swallowed — this ensures
RBAC/API errors surface immediately rather than as a timeout in the subsequent
Eventually which calls GetNamespaceE and k8serrors.IsNotFound; update the block
around DeleteNamespaceE, referencing the same symbols (DeleteNamespaceE,
GinkgoT, f.kubectlOpts, _namespace) to perform error checking and immediate
failure handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cdc125c1-3f82-4433-bc33-dad62fdacbe0

📥 Commits

Reviewing files that changed from the base of the PR and between 14930e9 and f182ea3.

📒 Files selected for processing (4)
  • .github/workflows/e2e-test.yml
  • Makefile
  • test/e2e/e2e_test.go
  • test/e2e/framework/api7_framework.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • Makefile

Copilot AI review requested due to automatic review settings May 6, 2026 06:09
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.

Comment thread test/e2e/framework/api7_framework.go
Comment thread test/e2e/framework/api7_framework.go Outdated
Comment thread Makefile
Comment thread .github/workflows/e2e-test.yml
- Convert BeforeSuite/AfterSuite to SynchronizedBeforeSuite/SynchronizedAfterSuite
  so the API7EE control plane is deployed only once (node 1) while each ginkgo
  parallel node creates its own dashboard port-forward tunnel
- Replace findFreePort/TOCTOU approach with dashboardLocalPorts() using
  GinkgoParallelProcess() for deterministic, conflict-free local port assignment
- Extract initSuiteEnv() to deduplicate env validation across suite setup paths
- Add const defaultDashboardVersion to satisfy goconst lint
- Add ginkgo-api7ee-e2e-test Makefile target for ginkgo CLI invocation
- Update e2e-test.yml to install ginkgo and run with E2E_NODES=2 for non-webhook
  matrix jobs (webhook remains serial with E2E_NODES=1)
- Align GINKGO_VERSION to v2.22.0 matching go.mod

Expected: CI time reduced from ~60 min to ~22-25 min on the two heavy shards.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@AlinsRan AlinsRan force-pushed the feat/e2e-parallel-ginkgo branch from 6fbbff1 to e94556d Compare May 6, 2026 07:24
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Makefile`:
- Around line 164-166: The install-ginkgo target installs the CLI into
GOPATH/bin instead of the Makefile's $(LOCALBIN), so update the target to export
GOBIN=$(LOCALBIN) when running go install (i.e., run the install command as
GOBIN=$(LOCALBIN) go install
github.com/onsi/ginkgo/v2/ginkgo@v$(GINKGO_VERSION)) so the ginkgo binary is
placed in $(LOCALBIN) and discoverable via the Makefile PATH; also ensure any
required directory creation for $(LOCALBIN) (as other tool targets do) is
preserved if needed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 16f2a69b-2d8b-4e71-a3b9-27f8b967a53c

📥 Commits

Reviewing files that changed from the base of the PR and between 6fbbff1 and e94556d.

📒 Files selected for processing (4)
  • .github/workflows/e2e-test.yml
  • Makefile
  • test/e2e/e2e_test.go
  • test/e2e/framework/api7_framework.go

Comment thread Makefile
Comment on lines 164 to 166
.PHONY: install-ginkgo
install-ginkgo:
@go install github.com/onsi/ginkgo/v2/ginkgo@v$(GINKGO_VERSION)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo 'Makefile install-ginkgo target:'
sed -n '164,166p' Makefile

echo
printf 'go env GOBIN: %s\n' "$(go env GOBIN)"
printf 'go env GOPATH: %s\n' "$(go env GOPATH)"

gopath_bin="$(go env GOPATH)/bin"
case ":$PATH:" in
  *":$gopath_bin:"*)
    echo "PATH already contains $gopath_bin"
    ;;
  *)
    echo "PATH does NOT contain $gopath_bin"
    ;;
esac

Repository: api7/api7-ingress-controller

Length of output: 301


🏁 Script executed:

#!/bin/bash
# Verify Makefile context

echo "=== Line 37 (GINKGO_VERSION) ==="
sed -n '35,40p' Makefile

echo
echo "=== Lines 157-162 (ginkgo-api7ee-e2e-test target) ==="
sed -n '155,165p' Makefile

echo
echo "=== Lines 379-380 (PATH export) ==="
sed -n '375,385p' Makefile

echo
echo "=== LOCALBIN definition ==="
rg 'LOCALBIN\s*:?=' Makefile | head -5

echo
echo "=== All ginkgo-related targets ==="
rg '\.PHONY:.*ginkgo|^[a-z-]*ginkgo[a-z-]*:' Makefile

Repository: api7/api7-ingress-controller

Length of output: 1348


🏁 Script executed:

#!/bin/bash
# Find LOCALBIN definition and go-install-tool function

echo "=== Searching for LOCALBIN definition ==="
rg 'LOCALBIN\s*:?=' Makefile -B 2 -A 2

echo
echo "=== Searching for go-install-tool function ==="
rg -A 10 'define go-install-tool|go-install-tool\s*=' Makefile

echo
echo "=== First 100 lines of Makefile (looking for variable definitions) ==="
head -100 Makefile | cat -n | tail -50

Repository: api7/api7-ingress-controller

Length of output: 2808


🏁 Script executed:

#!/bin/bash
# More comprehensive search for LOCALBIN

echo "=== Entire Makefile search for LOCALBIN ==="
rg 'LOCALBIN' Makefile -B 1 -A 1

echo
echo "=== Line count of Makefile ==="
wc -l Makefile

Repository: api7/api7-ingress-controller

Length of output: 2048


Install the Ginkgo CLI into $(LOCALBIN) to match the established pattern and ensure it's discoverable.

The install-ginkgo target uses plain go install, but all other tool installs in this Makefile (kustomize, controller-gen, envtest, golangci-lint, adc) set GOBIN=$(LOCALBIN). Without this, the binary installs to GOPATH/bin, which is not in the PATH exported by this Makefile. The ginkgo-api7ee-e2e-test target will fail with ginkgo: command not found since PATH is set to $(LOCALBIN):$(PATH) only.

Suggested fix
 .PHONY: install-ginkgo
 install-ginkgo:
-	`@go` install github.com/onsi/ginkgo/v2/ginkgo@v$(GINKGO_VERSION)
+	`@GOBIN`=$(LOCALBIN) go install github.com/onsi/ginkgo/v2/ginkgo@v$(GINKGO_VERSION)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.PHONY: install-ginkgo
install-ginkgo:
@go install github.com/onsi/ginkgo/v2/ginkgo@v$(GINKGO_VERSION)
.PHONY: install-ginkgo
install-ginkgo:
`@GOBIN`=$(LOCALBIN) go install github.com/onsi/ginkgo/v2/ginkgo@v$(GINKGO_VERSION)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Makefile` around lines 164 - 166, The install-ginkgo target installs the CLI
into GOPATH/bin instead of the Makefile's $(LOCALBIN), so update the target to
export GOBIN=$(LOCALBIN) when running go install (i.e., run the install command
as GOBIN=$(LOCALBIN) go install
github.com/onsi/ginkgo/v2/ginkgo@v$(GINKGO_VERSION)) so the ginkgo binary is
placed in $(LOCALBIN) and discoverable via the Makefile PATH; also ensure any
required directory creation for $(LOCALBIN) (as other tool targets do) is
preserved if needed.

@AlinsRan AlinsRan merged commit 23ee25f into master May 6, 2026
24 of 26 checks passed
@AlinsRan AlinsRan deleted the feat/e2e-parallel-ginkgo branch May 6, 2026 08:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants