Procházet zdrojové kódy

test(e2e): compile and track the akeyless, gitlab and oracle suites

These three suites are complete and compile, but none of them is blank
imported in import.go, so none is built into the suite binary, and none
has an area in matrix.yaml, so no leg would run them either. The akeyless
suite alone is 13 registered entries that have never executed.

matrix.py check could not catch this because it only ran one way. It
proved every provider in import.go had a covering area, but nothing
proved a suite directory on disk was in import.go, so dropping a suite in
without wiring it produced dead code that passed validation. Add the
reverse check. A directory counts as a suite when one of its own files
registers a package-level Ginkgo container, which distinguishes real
suites from the common/ helper package and from aws/, which holds only a
shared common.go beside its three sub-suites.

The legs are added disabled. Each of the three secret groups is gated in
e2e-reusable.yml, but none of AKEYLESS_*, GITLAB_* or ORACLE_* is set as
a repo secret, as an organisation secret available to this repo, or as an
environment secret, and no e2e job declares an environment. Enabling a
leg would therefore only produce a permanent failure. Defining the areas
keeps the suites counted for coverage and records the intended matrix, as
matrix.yaml already provides for; flipping enabled to true is the only
change needed once credentials exist.

Note for whoever enables the akeyless leg: go vet reports a non-constant
format string at cases/akeyless/provider.go:181. It predates this change
and make lint excludes the e2e module, so it is left alone here.

Fixes: external-secrets/external-secrets#6756
Signed-off-by: Alexander Chernov <alexander@chernov.it>
Alexander Chernov před 1 měsícem
rodič
revize
4a46d4a3f1
3 změnil soubory, kde provedl 91 přidání a 2 odebrání
  1. 45 2
      e2e/matrix.py
  2. 43 0
      e2e/matrix.yaml
  3. 3 0
      e2e/suites/provider/cases/import.go

+ 45 - 2
e2e/matrix.py

@@ -4,8 +4,9 @@
 Subcommands:
   check   Fail early if the matrix is inconsistent: a provider compiled into
           the suite (suites/provider/cases/import.go) is not covered by any
-          area, needs_secrets disagrees with secret_groups, or an area names a
-          secret group that the reusable workflow does not wire up.
+          area, a suite directory is not compiled in at all, needs_secrets
+          disagrees with secret_groups, or an area names a secret group that
+          the reusable workflow does not wire up.
   json    Print the GitHub Actions matrix (enabled areas only) as compact JSON
           for the workflow's strategy.matrix.
   plan    Print, per enabled leg, exactly which credential env vars it will
@@ -51,6 +52,36 @@ def imported_providers() -> list[str]:
     return sorted({m.group(1) for m in re.finditer(r"cases/([a-z0-9]+)", text)})
 
 
+def imported_paths() -> set[str]:
+    """Suite paths compiled into the suite binary, relative to cases/
+    (cases/aws/secretsmanager -> aws/secretsmanager). Unlike
+    imported_providers this keeps the sub-package, so it can be compared
+    against the directories on disk."""
+    text = IMPORT.read_text()
+    return {m.group(1) for m in re.finditer(r"cases/([\w/-]+)\"", text)}
+
+
+# Package-level Ginkgo container nodes. Anything that registers specs at
+# package scope counts, not just Describe, so a suite cannot dodge the check
+# below by using a different node type.
+SUITE_NODE = re.compile(r"^var _ = (?:F|P|X)?(?:Describe|DescribeTable)\(", re.M)
+
+
+def suite_dirs() -> set[str]:
+    """Directories under cases/ that define a suite, relative to cases/.
+
+    A directory is a suite when one of its own .go files registers a
+    package-level Ginkgo node. That distinguishes real suites from the
+    common/ helper package and from aws/, which only holds a shared
+    common.go beside its three sub-suites."""
+    root = IMPORT.parent
+    found = set()
+    for path in root.rglob("*.go"):
+        if SUITE_NODE.search(path.read_text()):
+            found.add(path.parent.relative_to(root).as_posix())
+    return found
+
+
 def group_to_vars() -> dict[str, list[str]]:
     """Map each secret group to the env vars the reusable workflow gates on it,
     parsed from lines like:
@@ -83,6 +114,18 @@ def cmd_check(matrix: dict) -> int:
             + "\n  - ".join(missing)
         )
 
+    # 1b. Every suite on disk is compiled into the binary. Without this the
+    # check only runs one way: a suite added under cases/ but never blank
+    # imported is silently dead, which is how the akeyless, gitlab and oracle
+    # suites went unrun for months while still passing this validation.
+    unimported = sorted(suite_dirs() - imported_paths())
+    if unimported:
+        errors.append(
+            "suite directories that are not blank imported in import.go, so "
+            "they are never compiled into the suite binary and never run:\n  - "
+            + "\n  - ".join(unimported)
+        )
+
     # 2. needs_secrets must mirror "secret_groups is non-empty".
     for a in areas:
         has_groups = bool(a.get("secret_groups"))

+ 43 - 0
e2e/matrix.yaml

@@ -177,6 +177,49 @@ areas:
       - "e2e/suites/provider/cases/secretserver/**"
     enabled: true
 
+  # The three legs below are defined but disabled, because their credentials do
+  # not exist. Each secret group is gated in e2e-reusable.yml, but none of
+  # AKEYLESS_*, GITLAB_* or ORACLE_* is set as a repo secret, an organisation
+  # secret available to this repo, or an environment secret, so enabling a leg
+  # would only produce a permanent failure.
+  #
+  # The suites themselves are complete and compile, and they are blank imported
+  # in import.go so that matrix.py check can see them. Defining the areas here
+  # keeps them counted for coverage and records the intended matrix; flip
+  # enabled to true once the credentials are added, no other change needed.
+  - name: akeyless
+    suite: provider
+    labels: "akeyless && !managed"
+    providers: [akeyless]
+    secret_groups: [akeyless]
+    needs_secrets: true
+    paths:
+      - "providers/v1/akeyless/**"
+      - "e2e/suites/provider/cases/akeyless/**"
+    enabled: false
+
+  - name: gitlab
+    suite: provider
+    labels: "gitlab && !managed"
+    providers: [gitlab]
+    secret_groups: [gitlab]
+    needs_secrets: true
+    paths:
+      - "providers/v1/gitlab/**"
+      - "e2e/suites/provider/cases/gitlab/**"
+    enabled: false
+
+  - name: oracle
+    suite: provider
+    labels: "oracle && !managed"
+    providers: [oracle]
+    secret_groups: [oracle]
+    needs_secrets: true
+    paths:
+      - "providers/v1/oracle/**"
+      - "e2e/suites/provider/cases/oracle/**"
+    enabled: false
+
   # Infisical runs against an in-cluster Infisical addon (addon.NewInfisical),
   # not an external tenant, so it needs no repo secrets despite being a SaaS.
   - name: infisical

+ 3 - 0
e2e/suites/provider/cases/import.go

@@ -19,6 +19,7 @@ package suite
 import (
 
 	// import different e2e test suites.
+	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/akeyless"
 	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/aws/certificatemanager"
 	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/aws/parameterstore"
 	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/aws/secretsmanager"
@@ -28,9 +29,11 @@ import (
 	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/delinea"
 	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/fake"
 	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/gcp"
+	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/gitlab"
 	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/infisical"
 	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/kubernetes"
 	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/openbao"
+	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/oracle"
 	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/scaleway"
 	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/secretserver"
 	_ "github.com/external-secrets/external-secrets-e2e/suites/provider/cases/template"