@red-hat-developer-hub/e2e-test-utils 1.1.30 → 1.1.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/deployment/orchestrator/install-orchestrator.sh +23 -15
- package/dist/utils/plugin-metadata.d.ts +3 -1
- package/dist/utils/plugin-metadata.d.ts.map +1 -1
- package/dist/utils/plugin-metadata.js +5 -3
- package/dist/utils/tests/plugin-metadata.pr.test.js +55 -0
- package/dist/utils/tests/plugin-metadata.test.js +2 -2
- package/package.json +1 -1
|
@@ -105,9 +105,9 @@ log::success() {
|
|
|
105
105
|
# Operator subscription and status
|
|
106
106
|
# ---------------------------------------------------------------------------
|
|
107
107
|
install_subscription() {
|
|
108
|
-
local name=$1 namespace=$2 channel=$3 package=$4 source_name=$5 source_namespace=$6
|
|
109
|
-
|
|
110
|
-
apiVersion: operators.coreos.com/v1alpha1
|
|
108
|
+
local name=$1 namespace=$2 channel=$3 package=$4 source_name=$5 source_namespace=$6 starting_csv=${7:-}
|
|
109
|
+
local yaml
|
|
110
|
+
yaml="apiVersion: operators.coreos.com/v1alpha1
|
|
111
111
|
kind: Subscription
|
|
112
112
|
metadata:
|
|
113
113
|
name: $name
|
|
@@ -117,30 +117,38 @@ spec:
|
|
|
117
117
|
installPlanApproval: Automatic
|
|
118
118
|
name: $package
|
|
119
119
|
source: $source_name
|
|
120
|
-
sourceNamespace: $source_namespace
|
|
121
|
-
|
|
120
|
+
sourceNamespace: $source_namespace"
|
|
121
|
+
if [[ -n "$starting_csv" ]]; then
|
|
122
|
+
yaml+="
|
|
123
|
+
startingCSV: $starting_csv"
|
|
124
|
+
fi
|
|
125
|
+
echo "$yaml" | oc apply -f -
|
|
122
126
|
return 0
|
|
123
127
|
}
|
|
124
128
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
# Wait for an operator CSV to reach a status phase.
|
|
130
|
+
# Uses OLM label selector (operators.coreos.com/<package>.<namespace>) which is
|
|
131
|
+
# deterministic, unlike spec.displayName which varies across channels/versions.
|
|
132
|
+
wait_for_operator() {
|
|
133
|
+
local timeout=${1:-300} namespace=$2 package=$3 expected_status=${4:-Succeeded}
|
|
134
|
+
local label="operators.coreos.com/${package}.${namespace}"
|
|
135
|
+
log::info "Waiting for operator '${package}' in '${namespace}' (label=${label}, timeout ${timeout}s, expected: ${expected_status})"
|
|
128
136
|
timeout "${timeout}" bash -c "
|
|
129
137
|
while true; do
|
|
130
|
-
CURRENT_PHASE=\$(oc get csv -n '${namespace}' -o jsonpath='{.items[
|
|
131
|
-
echo \"[
|
|
132
|
-
[[ \"\${CURRENT_PHASE}\" == \"${expected_status}\" ]] && echo \"[
|
|
138
|
+
CURRENT_PHASE=\$(oc get csv -n '${namespace}' -l '${label}' -o jsonpath='{.items[0].status.phase}' 2>/dev/null)
|
|
139
|
+
echo \"[wait_for_operator] Phase: \${CURRENT_PHASE}\" >&2
|
|
140
|
+
[[ \"\${CURRENT_PHASE}\" == \"${expected_status}\" ]] && echo \"[wait_for_operator] Operator reached ${expected_status}\" >&2 && break
|
|
133
141
|
sleep 10
|
|
134
142
|
done
|
|
135
|
-
" || { log::error "Operator did not reach ${expected_status} in time."; return 1; }
|
|
143
|
+
" || { log::error "Operator '${package}' did not reach ${expected_status} in time."; return 1; }
|
|
136
144
|
}
|
|
137
145
|
|
|
138
146
|
install_serverless_logic_ocp_operator() {
|
|
139
|
-
install_subscription logic-operator openshift-operators stable logic-operator redhat-operators openshift-marketplace
|
|
147
|
+
install_subscription logic-operator openshift-operators stable logic-operator redhat-operators openshift-marketplace logic-operator.v1.37.2
|
|
140
148
|
return 0
|
|
141
149
|
}
|
|
142
150
|
waitfor_serverless_logic_ocp_operator() {
|
|
143
|
-
|
|
151
|
+
wait_for_operator 500 openshift-operators logic-operator Succeeded
|
|
144
152
|
return 0
|
|
145
153
|
}
|
|
146
154
|
|
|
@@ -149,7 +157,7 @@ install_serverless_ocp_operator() {
|
|
|
149
157
|
return 0
|
|
150
158
|
}
|
|
151
159
|
waitfor_serverless_ocp_operator() {
|
|
152
|
-
|
|
160
|
+
wait_for_operator 300 openshift-operators serverless-operator Succeeded
|
|
153
161
|
return 0
|
|
154
162
|
}
|
|
155
163
|
|
|
@@ -28,9 +28,11 @@ export interface DynamicPluginsConfig {
|
|
|
28
28
|
export declare function isNightlyJob(): boolean;
|
|
29
29
|
/**
|
|
30
30
|
* Extracts the plugin name from a package path or OCI reference.
|
|
31
|
+
* Strips the `-dynamic` suffix so local paths and OCI refs for the same
|
|
32
|
+
* logical plugin produce the same key.
|
|
31
33
|
*
|
|
32
34
|
* Handles various formats:
|
|
33
|
-
* - Local path: ./dynamic-plugins/dist/backstage-community-plugin-tech-radar
|
|
35
|
+
* - Local path: ./dynamic-plugins/dist/backstage-community-plugin-tech-radar-dynamic
|
|
34
36
|
* - OCI with alias: oci://quay.io/rhdh/plugin@sha256:...!backstage-community-plugin-tech-radar
|
|
35
37
|
* - OCI without alias: oci://quay.io/rhdh/backstage-community-plugin-tech-radar:tag
|
|
36
38
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-metadata.d.ts","sourceRoot":"","sources":["../../src/utils/plugin-metadata.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAaD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAID;;;;;;;;;GASG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAqBtC;AAID
|
|
1
|
+
{"version":3,"file":"plugin-metadata.d.ts","sourceRoot":"","sources":["../../src/utils/plugin-metadata.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AAaD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,WAAW,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAID;;;;;;;;;GASG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAqBtC;AAID;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAI5D;AAYD,eAAO,MAAM,qBAAqB,gBAAgB,CAAC;AAEnD,wBAAgB,oBAAoB,CAClC,YAAY,GAAE,MAA8B,GAC3C,MAAM,GAAG,IAAI,CAQf;AAED,wBAAsB,iBAAiB,CACrC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,cAAc,CAAC,CAyBzB;AAED,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAwBtC;AA2JD;;;;;;;GAOG;AACH;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,MAAM,CAMT;AAqGD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAW7E;AAED;;;;;;;GAOG;AACH,wBAAsB,2BAA2B,CAC/C,YAAY,GAAE,MAA8B,GAC3C,OAAO,CAAC,oBAAoB,CAAC,CAwB/B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,oBAAoB,EAC5B,YAAY,GAAE,MAA8B,GAC3C,OAAO,CAAC,oBAAoB,CAAC,CA6B/B"}
|
|
@@ -35,16 +35,18 @@ export function isNightlyJob() {
|
|
|
35
35
|
// ── Utilities ─────────────────────────────────────────────────────────────────
|
|
36
36
|
/**
|
|
37
37
|
* Extracts the plugin name from a package path or OCI reference.
|
|
38
|
+
* Strips the `-dynamic` suffix so local paths and OCI refs for the same
|
|
39
|
+
* logical plugin produce the same key.
|
|
38
40
|
*
|
|
39
41
|
* Handles various formats:
|
|
40
|
-
* - Local path: ./dynamic-plugins/dist/backstage-community-plugin-tech-radar
|
|
42
|
+
* - Local path: ./dynamic-plugins/dist/backstage-community-plugin-tech-radar-dynamic
|
|
41
43
|
* - OCI with alias: oci://quay.io/rhdh/plugin@sha256:...!backstage-community-plugin-tech-radar
|
|
42
44
|
* - OCI without alias: oci://quay.io/rhdh/backstage-community-plugin-tech-radar:tag
|
|
43
45
|
*/
|
|
44
46
|
export function extractPluginName(packageRef) {
|
|
45
47
|
const ref = packageRef.includes("!") ? packageRef.split("!")[0] : packageRef;
|
|
46
48
|
const match = ref.match(/\/([^/:@]+)(?:[:@].*)?$/);
|
|
47
|
-
return match?.[1] || packageRef;
|
|
49
|
+
return (match?.[1] || packageRef).replace(/-dynamic$/, "");
|
|
48
50
|
}
|
|
49
51
|
/**
|
|
50
52
|
* Derives the displayName from a packageName.
|
|
@@ -207,7 +209,7 @@ export function getNormalizedPluginMergeKey(entry) {
|
|
|
207
209
|
if (pkg === undefined || pkg === "") {
|
|
208
210
|
return "";
|
|
209
211
|
}
|
|
210
|
-
return extractPluginName(pkg)
|
|
212
|
+
return extractPluginName(pkg);
|
|
211
213
|
}
|
|
212
214
|
async function resolvePluginPackages(plugins, metadataMap, metadataPath) {
|
|
213
215
|
// Build PR OCI URLs if applicable
|
|
@@ -256,6 +256,61 @@ describe("processPluginsForDeployment — PR mode", () => {
|
|
|
256
256
|
await fs.remove(metadataDir);
|
|
257
257
|
}
|
|
258
258
|
});
|
|
259
|
+
// ── -dynamic suffix normalization ────────────────────────────────────────
|
|
260
|
+
describe("-dynamic suffix normalization", () => {
|
|
261
|
+
it("resolves OCI plugin to metadata when dynamicArtifact has -dynamic suffix", async () => {
|
|
262
|
+
const metadataDir = await createMetadataFixture([
|
|
263
|
+
{
|
|
264
|
+
name: "backstage-plugin-catalog-backend-module-github",
|
|
265
|
+
packageName: "@backstage/plugin-catalog-backend-module-github",
|
|
266
|
+
dynamicArtifact: "./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic",
|
|
267
|
+
appConfigExamples: {
|
|
268
|
+
catalog: { providers: { github: { org: "test" } } },
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
]);
|
|
272
|
+
try {
|
|
273
|
+
const config = {
|
|
274
|
+
plugins: [
|
|
275
|
+
{
|
|
276
|
+
package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-catalog-backend-module-github:bs_1.45.3__0.11.2",
|
|
277
|
+
disabled: false,
|
|
278
|
+
},
|
|
279
|
+
],
|
|
280
|
+
};
|
|
281
|
+
const result = await processPluginsForDeployment(config, metadataDir);
|
|
282
|
+
assert.ok(result.plugins[0].pluginConfig, "metadata config must be injected even when dynamicArtifact has -dynamic suffix but OCI URL does not");
|
|
283
|
+
assert.deepStrictEqual(result.plugins[0].pluginConfig, { catalog: { providers: { github: { org: "test" } } } }, "injected config must match metadata appConfigExamples");
|
|
284
|
+
}
|
|
285
|
+
finally {
|
|
286
|
+
await fs.remove(metadataDir);
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
it("keeps local -dynamic path unchanged when metadata also has -dynamic", async () => {
|
|
290
|
+
const metadataDir = await createMetadataFixture([
|
|
291
|
+
{
|
|
292
|
+
name: "backstage-plugin-catalog-backend-module-github",
|
|
293
|
+
packageName: "@backstage/plugin-catalog-backend-module-github",
|
|
294
|
+
dynamicArtifact: "./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic",
|
|
295
|
+
},
|
|
296
|
+
]);
|
|
297
|
+
try {
|
|
298
|
+
const config = {
|
|
299
|
+
plugins: [
|
|
300
|
+
{
|
|
301
|
+
package: "./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic",
|
|
302
|
+
disabled: false,
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
};
|
|
306
|
+
const result = await processPluginsForDeployment(config, metadataDir);
|
|
307
|
+
assert.strictEqual(result.plugins[0].package, "./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic", "local path with -dynamic must stay unchanged");
|
|
308
|
+
}
|
|
309
|
+
finally {
|
|
310
|
+
await fs.remove(metadataDir);
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
});
|
|
259
314
|
// ── PR vs nightly precedence ────────────────────────────────────────────
|
|
260
315
|
describe("PR vs nightly precedence", () => {
|
|
261
316
|
it("isNightlyJob returns false when both GIT_PR_NUMBER and E2E_NIGHTLY_MODE are set", () => {
|
|
@@ -18,8 +18,8 @@ describe("extractPluginName", () => {
|
|
|
18
18
|
it("extracts name from OCI URL with tag only (no alias)", () => {
|
|
19
19
|
assert.strictEqual(extractPluginName("oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-tekton:bs_1.45.3__3.33.3"), "backstage-community-plugin-tekton");
|
|
20
20
|
});
|
|
21
|
-
it("extracts name from local path", () => {
|
|
22
|
-
assert.strictEqual(extractPluginName("./dynamic-plugins/dist/backstage-community-plugin-keycloak-dynamic"), "backstage-community-plugin-keycloak
|
|
21
|
+
it("extracts name from local path and strips -dynamic suffix", () => {
|
|
22
|
+
assert.strictEqual(extractPluginName("./dynamic-plugins/dist/backstage-community-plugin-keycloak-dynamic"), "backstage-community-plugin-keycloak");
|
|
23
23
|
});
|
|
24
24
|
it("extracts name from OCI URL with digest but no alias", () => {
|
|
25
25
|
assert.strictEqual(extractPluginName("oci://quay.io/rhdh/backstage-plugin-events-backend-module-github@sha256:c1d17d47aaa"), "backstage-plugin-events-backend-module-github");
|