From a84c153db7bd125eb649535e20af19106947dca2 Mon Sep 17 00:00:00 2001 From: Chris Stephens Date: Fri, 12 Jun 2026 12:30:46 -0700 Subject: [PATCH 1/5] acc: Prefix unique test resource names with CI run id for attribution and sweeping Acceptance tests name cloud resources with a bare random string ($UNIQUE_NAME, e.g. 'osr5mzrrvzb73juixjoviti24y'). When such resources leak into shared test workspaces, nothing ties them back to a repo or CI run, which made a recent quota-exhaustion incident hard to diagnose and makes targeted cleanup impossible. When running against a cloud env (CLOUD_ENV set) with GITHUB_RUN_ID present, the harness now generates names of the form 'ci--', truncated to the same 26-character length as before so that length-constrained names built from $UNIQUE_NAME (e.g. 'app-$UNIQUE_NAME', exactly 30 chars, the app name limit) keep fitting. The character set stays lowercase alphanumerics plus '-', which tests already use adjacent to $UNIQUE_NAME in every resource type. Local runs and testserver runs are unchanged, and output masking is unaffected because the whole generated name (prefix included) is still replaced with [UNIQUE_NAME]. Also adds tools/sweep_test_resources.py, a small helper that lists (and with --delete removes) warehouses, pipelines and jobs whose names start with a given prefix, to be wired into CI job-end cleanup later. Co-authored-by: Isaac --- acceptance/acceptance_test.go | 28 +++++++++++ acceptance/unique_name_test.go | 24 ++++++++++ tools/sweep_test_resources.py | 85 ++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 acceptance/unique_name_test.go create mode 100755 tools/sweep_test_resources.py diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index a137d356f16..ffcd2b6d55a 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -609,6 +609,29 @@ func getSkipReason(config *internal.TestConfig, configPath string) string { return "" } +// ciRunID matches a plausible numeric GitHub Actions run id. +var ciRunID = regexp.MustCompile(`^[0-9]{1,16}$`) + +// ciUniqueName embeds a CI run id into the random unique name: "ci--". +// The result has the same length as the input random name. This matters because some +// resource names built from $UNIQUE_NAME are at their length limit already (for example, +// "app-$UNIQUE_NAME" is exactly 30 characters, the maximum length of an app name). +// The character set also stays compatible with all uses: lowercase alphanumerics plus "-", +// which existing tests already use adjacent to $UNIQUE_NAME in every resource type. +// Returns the random name unchanged when runID is absent, malformed, or too long to leave +// enough random characters for collision avoidance between tests in the same run. +func ciUniqueName(runID, random string) string { + if !ciRunID.MatchString(runID) { + return random + } + prefix := "ci-" + runID + "-" + randLen := len(random) - len(prefix) + if randLen < 8 { + return random + } + return prefix + random[:randLen] +} + func runTest(t *testing.T, dir string, variant int, @@ -643,6 +666,11 @@ func runTest(t *testing.T, id := uuid.New() uniqueName := strings.ToLower(strings.Trim(base32.StdEncoding.EncodeToString(id[:]), "=")) + if isRunningOnCloud { + // In CI runs against real workspaces, embed the workflow run id into the name so + // that leaked resources can be attributed to a repo/CI run and swept by prefix. + uniqueName = ciUniqueName(os.Getenv("GITHUB_RUN_ID"), uniqueName) + } repls.Set(uniqueName, "[UNIQUE_NAME]") var tmpDir string diff --git a/acceptance/unique_name_test.go b/acceptance/unique_name_test.go new file mode 100644 index 00000000000..6af5105c21c --- /dev/null +++ b/acceptance/unique_name_test.go @@ -0,0 +1,24 @@ +package acceptance_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCIUniqueName(t *testing.T) { + // 26 lowercase base32 characters, like the generated unique name. + random := "osr5mzrrvzb73juixjoviti24y" + + // Run id embedded, same length as input, sweepable prefix. + assert.Equal(t, "ci-15799017600-osr5mzrrvzb", ciUniqueName("15799017600", random)) + assert.Equal(t, "ci-1-osr5mzrrvzb73juixjovi", ciUniqueName("1", random)) + + // No or invalid run id: unchanged. + assert.Equal(t, random, ciUniqueName("", random)) + assert.Equal(t, random, ciUniqueName("abc123", random)) + assert.Equal(t, random, ciUniqueName("123 456", random)) + + // Run id too long to leave enough randomness: unchanged. + assert.Equal(t, random, ciUniqueName("123456789012345", random)) +} diff --git a/tools/sweep_test_resources.py b/tools/sweep_test_resources.py new file mode 100755 index 00000000000..8279e2cf3fa --- /dev/null +++ b/tools/sweep_test_resources.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +"""Sweep leaked acceptance-test resources by name prefix. + +Lists (and with --delete, deletes) warehouses, pipelines and jobs whose names +start with the given prefix, e.g. the per-run prefix "ci--" that +the acceptance harness embeds into $UNIQUE_NAME on CI cloud runs. + +Authentication is taken from the environment (DATABRICKS_HOST, DATABRICKS_TOKEN +or any other auth supported by the databricks CLI). + +Usage: + tools/sweep_test_resources.py ci-15799017600- # dry run: list only + tools/sweep_test_resources.py ci-15799017600- --delete # delete matches +""" + +import argparse +import json +import subprocess +import sys + + +def run_json(*args): + out = subprocess.check_output(["databricks", *args, "--output", "json"], text=True) + return json.loads(out) if out.strip() else [] + + +def sweep(kind, items, name_of, id_of, delete_args, prefix, delete): + failures = 0 + for item in items: + name = name_of(item) or "" + if not name.startswith(prefix): + continue + res_id = str(id_of(item)) + print(f"{kind}\t{res_id}\t{name}") + if delete: + try: + subprocess.check_call(["databricks", *delete_args, res_id]) + except subprocess.CalledProcessError as e: + print(f"failed to delete {kind} {res_id}: {e}", file=sys.stderr) + failures += 1 + return failures + + +def main(): + parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + parser.add_argument("prefix", help="resource name prefix, e.g. ci--") + parser.add_argument("--delete", action="store_true", help="delete matches (default: list only)") + args = parser.parse_args() + + if not args.prefix: + parser.error("prefix must not be empty") + + failures = 0 + failures += sweep( + "warehouse", + run_json("warehouses", "list"), + lambda w: w.get("name"), + lambda w: w.get("id"), + ["warehouses", "delete"], + args.prefix, + args.delete, + ) + failures += sweep( + "pipeline", + run_json("pipelines", "list-pipelines"), + lambda p: p.get("name"), + lambda p: p.get("pipeline_id"), + ["pipelines", "delete"], + args.prefix, + args.delete, + ) + failures += sweep( + "job", + run_json("jobs", "list"), + lambda j: j.get("settings", {}).get("name"), + lambda j: j.get("job_id"), + ["jobs", "delete"], + args.prefix, + args.delete, + ) + return 1 if failures else 0 + + +if __name__ == "__main__": + sys.exit(main()) From dd8cb44a17c75aa5254a21d1c823e18d65bcaddb Mon Sep 17 00:00:00 2001 From: Chris Stephens Date: Fri, 12 Jun 2026 13:07:34 -0700 Subject: [PATCH 2/5] acc: Tighten comments Co-authored-by: Isaac --- acceptance/acceptance_test.go | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index ffcd2b6d55a..ebc7ed74bb4 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -609,17 +609,13 @@ func getSkipReason(config *internal.TestConfig, configPath string) string { return "" } -// ciRunID matches a plausible numeric GitHub Actions run id. var ciRunID = regexp.MustCompile(`^[0-9]{1,16}$`) -// ciUniqueName embeds a CI run id into the random unique name: "ci--". -// The result has the same length as the input random name. This matters because some -// resource names built from $UNIQUE_NAME are at their length limit already (for example, -// "app-$UNIQUE_NAME" is exactly 30 characters, the maximum length of an app name). -// The character set also stays compatible with all uses: lowercase alphanumerics plus "-", -// which existing tests already use adjacent to $UNIQUE_NAME in every resource type. -// Returns the random name unchanged when runID is absent, malformed, or too long to leave -// enough random characters for collision avoidance between tests in the same run. +// ciUniqueName embeds a CI run id into the random unique name as "ci--", +// preserving the input length: names built from $UNIQUE_NAME can already be at a +// resource name limit ("app-$UNIQUE_NAME" is exactly the 30-char app name maximum). +// Returns random unchanged when runID is absent, malformed, or too long to leave +// enough random characters. func ciUniqueName(runID, random string) string { if !ciRunID.MatchString(runID) { return random @@ -667,8 +663,7 @@ func runTest(t *testing.T, id := uuid.New() uniqueName := strings.ToLower(strings.Trim(base32.StdEncoding.EncodeToString(id[:]), "=")) if isRunningOnCloud { - // In CI runs against real workspaces, embed the workflow run id into the name so - // that leaked resources can be attributed to a repo/CI run and swept by prefix. + // Embed the CI run id so leaked resources can be attributed to a run and swept by prefix. uniqueName = ciUniqueName(os.Getenv("GITHUB_RUN_ID"), uniqueName) } repls.Set(uniqueName, "[UNIQUE_NAME]") From 162ca50809414ede5db5a421c2f8134656a3fb3b Mon Sep 17 00:00:00 2001 From: Chris Stephens Date: Fri, 12 Jun 2026 13:20:44 -0700 Subject: [PATCH 3/5] acc: Apply CI run id prefix whenever GITHUB_RUN_ID is present Drop the CLOUD_ENV gate: ciUniqueName already no-ops without a valid run id, and prefixing testserver runs in CI exercises the masking path everywhere instead of only on cloud runs. Co-authored-by: Isaac --- acceptance/acceptance_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index ebc7ed74bb4..96845ea8d20 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -662,10 +662,8 @@ func runTest(t *testing.T, id := uuid.New() uniqueName := strings.ToLower(strings.Trim(base32.StdEncoding.EncodeToString(id[:]), "=")) - if isRunningOnCloud { - // Embed the CI run id so leaked resources can be attributed to a run and swept by prefix. - uniqueName = ciUniqueName(os.Getenv("GITHUB_RUN_ID"), uniqueName) - } + // Embed the CI run id, when present, so leaked resources can be attributed to a run and swept by prefix. + uniqueName = ciUniqueName(os.Getenv("GITHUB_RUN_ID"), uniqueName) repls.Set(uniqueName, "[UNIQUE_NAME]") var tmpDir string From 4687476853a03d40893e83d3e3987977687895fe Mon Sep 17 00:00:00 2001 From: Chris Stephens Date: Thu, 18 Jun 2026 15:41:14 -0700 Subject: [PATCH 4/5] acc: use UNIQUE_NAME_SAFE for Python project_name in templates Python project_name validation rejects hyphens ("must consist of letters, numbers, and underscores"). The CI run-id prefix introduced by ciUniqueName uses hyphens (ci--), causing bundle init to fail in the two default-python test templates that embed $UNIQUE_NAME directly in project_name. Fix: expose UNIQUE_NAME_SAFE (hyphens replaced with underscores) alongside UNIQUE_NAME, add masking for it, and use it in the two input.json.tmpl files and the integration_classic script. Resources that accept hyphens (jobs, pipelines, apps, warehouses) continue using the original $UNIQUE_NAME format. Co-authored-by: Isaac --- acceptance/acceptance_test.go | 7 +++++++ .../templates/default-python/combinations/input.json.tmpl | 2 +- .../default-python/integration_classic/input.json.tmpl | 2 +- .../templates/default-python/integration_classic/script | 4 ++-- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index c2591c0995a..d0205467064 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -665,6 +665,12 @@ func runTest(t *testing.T, // Embed the CI run id, when present, so leaked resources can be attributed to a run and swept by prefix. uniqueName = ciUniqueName(os.Getenv("GITHUB_RUN_ID"), uniqueName) repls.Set(uniqueName, "[UNIQUE_NAME]") + // UNIQUE_NAME_SAFE replaces hyphens with underscores for contexts that require + // identifier-safe names (e.g. Python project_name, which rejects hyphens). + uniqueNameSafe := strings.ReplaceAll(uniqueName, "-", "_") + if uniqueNameSafe != uniqueName { + repls.Set(uniqueNameSafe, "[UNIQUE_NAME]") + } var tmpDir string var err error @@ -738,6 +744,7 @@ func runTest(t *testing.T, } cmd.Env = append(cmd.Env, "DATABRICKS_RATE_LIMIT="+rateLimit) cmd.Env = append(cmd.Env, "UNIQUE_NAME="+uniqueName) + cmd.Env = append(cmd.Env, "UNIQUE_NAME_SAFE="+uniqueNameSafe) cmd.Env = append(cmd.Env, "TEST_TMP_DIR="+tmpDir) // populate CLOUD_ENV_BASE diff --git a/acceptance/bundle/templates/default-python/combinations/input.json.tmpl b/acceptance/bundle/templates/default-python/combinations/input.json.tmpl index 3a547d70fc5..0b5ace4f0db 100644 --- a/acceptance/bundle/templates/default-python/combinations/input.json.tmpl +++ b/acceptance/bundle/templates/default-python/combinations/input.json.tmpl @@ -1,5 +1,5 @@ { - "project_name": "X$UNIQUE_NAME", + "project_name": "X$UNIQUE_NAME_SAFE", "include_notebook": "$NBOOK", "include_dlt": "$DLT", "include_python": "$PY", diff --git a/acceptance/bundle/templates/default-python/integration_classic/input.json.tmpl b/acceptance/bundle/templates/default-python/integration_classic/input.json.tmpl index 73565a4f5bc..fe799fe2556 100644 --- a/acceptance/bundle/templates/default-python/integration_classic/input.json.tmpl +++ b/acceptance/bundle/templates/default-python/integration_classic/input.json.tmpl @@ -1,5 +1,5 @@ { - "project_name": "project_name_$UNIQUE_NAME", + "project_name": "project_name_$UNIQUE_NAME_SAFE", "include_notebook": "yes", "include_dlt": "yes", "include_python": "yes", diff --git a/acceptance/bundle/templates/default-python/integration_classic/script b/acceptance/bundle/templates/default-python/integration_classic/script index 50b39d6ffce..0bf3d8365f3 100644 --- a/acceptance/bundle/templates/default-python/integration_classic/script +++ b/acceptance/bundle/templates/default-python/integration_classic/script @@ -7,7 +7,7 @@ envsubst < input.json.tmpl > input.json trace $CLI bundle init default-python --config-file ./input.json --output-dir . rm input.json -cd project_name_${UNIQUE_NAME} +cd project_name_${UNIQUE_NAME_SAFE} export JQ_DELETE=' .workspace.current_user @@ -40,4 +40,4 @@ trace $CLI bundle destroy -t prod --auto-approve trap "true" EXIT cd .. -rm -fr project_name_${UNIQUE_NAME} +rm -fr project_name_${UNIQUE_NAME_SAFE} From 57d761e164d1475e9b747eb1df842628c9bc1348 Mon Sep 17 00:00:00 2001 From: Chris Stephens Date: Thu, 18 Jun 2026 17:08:16 -0700 Subject: [PATCH 5/5] acc: make CI run-id unique name lowercase-alphanumeric The previous ci-- format injected hyphens into $UNIQUE_NAME, which is embedded into ~hundreds of test resource names. Hyphens are rejected by Python project names, Unity Catalog identifiers, and vector-search index names, so local acceptance jobs failed (e.g. bundle/templates/default-python and bundle/deployment/bind/vector_search_index). Switch the format to cix, which is purely lowercase-alphanumeric like the base32 name it replaces and is therefore valid in every naming context (including app names, which forbid underscores and uppercase). The run id is delimited from the random tail by the letter "x", keeping the sweep prefix cix collision-free. This needs no per-template changes, so the UNIQUE_NAME_SAFE approach from the prior commit is reverted. Co-authored-by: Isaac --- acceptance/acceptance_test.go | 23 ++++++++----------- .../combinations/input.json.tmpl | 2 +- .../integration_classic/input.json.tmpl | 2 +- .../default-python/integration_classic/script | 4 ++-- acceptance/unique_name_test.go | 13 +++++++---- tools/sweep_test_resources.py | 8 +++---- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index d0205467064..fcfeda7ed20 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -611,16 +611,20 @@ func getSkipReason(config *internal.TestConfig, configPath string) string { var ciRunID = regexp.MustCompile(`^[0-9]{1,16}$`) -// ciUniqueName embeds a CI run id into the random unique name as "ci--", -// preserving the input length: names built from $UNIQUE_NAME can already be at a -// resource name limit ("app-$UNIQUE_NAME" is exactly the 30-char app name maximum). -// Returns random unchanged when runID is absent, malformed, or too long to leave -// enough random characters. +// ciUniqueName embeds a CI run id into the random unique name as "cix". +// The result stays purely lowercase-alphanumeric like the base32 name it replaces, so it +// remains valid everywhere $UNIQUE_NAME is used: app names (no hyphens would be fine but +// underscores/uppercase are not), Python and Unity Catalog identifiers (no hyphens). No +// punctuation separator works for all of them, so the run id (all digits) is delimited by +// the letter "x", which also keeps the sweep prefix "cix" collision-free between +// runs whose ids share a prefix. Length is preserved ("app-$UNIQUE_NAME" is exactly the +// 30-char app name maximum). Returns random unchanged when runID is absent, malformed, or +// too long to leave at least 8 random characters. func ciUniqueName(runID, random string) string { if !ciRunID.MatchString(runID) { return random } - prefix := "ci-" + runID + "-" + prefix := "ci" + runID + "x" randLen := len(random) - len(prefix) if randLen < 8 { return random @@ -665,12 +669,6 @@ func runTest(t *testing.T, // Embed the CI run id, when present, so leaked resources can be attributed to a run and swept by prefix. uniqueName = ciUniqueName(os.Getenv("GITHUB_RUN_ID"), uniqueName) repls.Set(uniqueName, "[UNIQUE_NAME]") - // UNIQUE_NAME_SAFE replaces hyphens with underscores for contexts that require - // identifier-safe names (e.g. Python project_name, which rejects hyphens). - uniqueNameSafe := strings.ReplaceAll(uniqueName, "-", "_") - if uniqueNameSafe != uniqueName { - repls.Set(uniqueNameSafe, "[UNIQUE_NAME]") - } var tmpDir string var err error @@ -744,7 +742,6 @@ func runTest(t *testing.T, } cmd.Env = append(cmd.Env, "DATABRICKS_RATE_LIMIT="+rateLimit) cmd.Env = append(cmd.Env, "UNIQUE_NAME="+uniqueName) - cmd.Env = append(cmd.Env, "UNIQUE_NAME_SAFE="+uniqueNameSafe) cmd.Env = append(cmd.Env, "TEST_TMP_DIR="+tmpDir) // populate CLOUD_ENV_BASE diff --git a/acceptance/bundle/templates/default-python/combinations/input.json.tmpl b/acceptance/bundle/templates/default-python/combinations/input.json.tmpl index 0b5ace4f0db..3a547d70fc5 100644 --- a/acceptance/bundle/templates/default-python/combinations/input.json.tmpl +++ b/acceptance/bundle/templates/default-python/combinations/input.json.tmpl @@ -1,5 +1,5 @@ { - "project_name": "X$UNIQUE_NAME_SAFE", + "project_name": "X$UNIQUE_NAME", "include_notebook": "$NBOOK", "include_dlt": "$DLT", "include_python": "$PY", diff --git a/acceptance/bundle/templates/default-python/integration_classic/input.json.tmpl b/acceptance/bundle/templates/default-python/integration_classic/input.json.tmpl index fe799fe2556..73565a4f5bc 100644 --- a/acceptance/bundle/templates/default-python/integration_classic/input.json.tmpl +++ b/acceptance/bundle/templates/default-python/integration_classic/input.json.tmpl @@ -1,5 +1,5 @@ { - "project_name": "project_name_$UNIQUE_NAME_SAFE", + "project_name": "project_name_$UNIQUE_NAME", "include_notebook": "yes", "include_dlt": "yes", "include_python": "yes", diff --git a/acceptance/bundle/templates/default-python/integration_classic/script b/acceptance/bundle/templates/default-python/integration_classic/script index 0bf3d8365f3..50b39d6ffce 100644 --- a/acceptance/bundle/templates/default-python/integration_classic/script +++ b/acceptance/bundle/templates/default-python/integration_classic/script @@ -7,7 +7,7 @@ envsubst < input.json.tmpl > input.json trace $CLI bundle init default-python --config-file ./input.json --output-dir . rm input.json -cd project_name_${UNIQUE_NAME_SAFE} +cd project_name_${UNIQUE_NAME} export JQ_DELETE=' .workspace.current_user @@ -40,4 +40,4 @@ trace $CLI bundle destroy -t prod --auto-approve trap "true" EXIT cd .. -rm -fr project_name_${UNIQUE_NAME_SAFE} +rm -fr project_name_${UNIQUE_NAME} diff --git a/acceptance/unique_name_test.go b/acceptance/unique_name_test.go index 6af5105c21c..181c648b98b 100644 --- a/acceptance/unique_name_test.go +++ b/acceptance/unique_name_test.go @@ -10,15 +10,18 @@ func TestCIUniqueName(t *testing.T) { // 26 lowercase base32 characters, like the generated unique name. random := "osr5mzrrvzb73juixjoviti24y" - // Run id embedded, same length as input, sweepable prefix. - assert.Equal(t, "ci-15799017600-osr5mzrrvzb", ciUniqueName("15799017600", random)) - assert.Equal(t, "ci-1-osr5mzrrvzb73juixjovi", ciUniqueName("1", random)) + // Run id embedded, same length as input, lowercase-alphanumeric, sweepable prefix. + assert.Equal(t, "ci15799017600xosr5mzrrvzb7", ciUniqueName("15799017600", random)) + assert.Equal(t, "ci1xosr5mzrrvzb73juixjovit", ciUniqueName("1", random)) // No or invalid run id: unchanged. assert.Equal(t, random, ciUniqueName("", random)) assert.Equal(t, random, ciUniqueName("abc123", random)) assert.Equal(t, random, ciUniqueName("123 456", random)) - // Run id too long to leave enough randomness: unchanged. - assert.Equal(t, random, ciUniqueName("123456789012345", random)) + // 15-digit run id still leaves exactly the 8-char random minimum: prefixed. + assert.Equal(t, "ci123456789012345xosr5mzrr", ciUniqueName("123456789012345", random)) + + // 16-digit run id is too long to leave enough randomness: unchanged. + assert.Equal(t, random, ciUniqueName("1234567890123456", random)) } diff --git a/tools/sweep_test_resources.py b/tools/sweep_test_resources.py index 8279e2cf3fa..d17521871fa 100755 --- a/tools/sweep_test_resources.py +++ b/tools/sweep_test_resources.py @@ -2,15 +2,15 @@ """Sweep leaked acceptance-test resources by name prefix. Lists (and with --delete, deletes) warehouses, pipelines and jobs whose names -start with the given prefix, e.g. the per-run prefix "ci--" that +start with the given prefix, e.g. the per-run prefix "cix" that the acceptance harness embeds into $UNIQUE_NAME on CI cloud runs. Authentication is taken from the environment (DATABRICKS_HOST, DATABRICKS_TOKEN or any other auth supported by the databricks CLI). Usage: - tools/sweep_test_resources.py ci-15799017600- # dry run: list only - tools/sweep_test_resources.py ci-15799017600- --delete # delete matches + tools/sweep_test_resources.py ci15799017600x # dry run: list only + tools/sweep_test_resources.py ci15799017600x --delete # delete matches """ import argparse @@ -43,7 +43,7 @@ def sweep(kind, items, name_of, id_of, delete_args, prefix, delete): def main(): parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) - parser.add_argument("prefix", help="resource name prefix, e.g. ci--") + parser.add_argument("prefix", help="resource name prefix, e.g. cix") parser.add_argument("--delete", action="store_true", help="delete matches (default: list only)") args = parser.parse_args()