Skip to content

Commit c59e509

Browse files
feat(deployment): add "next" tag support with default values for version and method (#24)
- Helm: resolves "next" to semantic version by querying rhdh-hub-rhel9 image tags - Operator: uses main branch and --next flag for non-semantic versions - Default RHDH_VERSION to "next" and INSTALLATION_METHOD to "helm" when not set - Bump version to 1.1.6 Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent ee7d9d5 commit c59e509

File tree

4 files changed

+103
-15
lines changed

4 files changed

+103
-15
lines changed

docs/.vitepress/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export default defineConfig({
3232
{ text: "Tutorials", link: "/tutorials/" },
3333
{ text: "Examples", link: "/examples/" },
3434
{
35-
text: "v1.1.2",
35+
text: "v1.1.6",
3636
items: [{ text: "Changelog", link: "/changelog" }],
3737
},
3838
],

docs/changelog.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,21 @@
22

33
All notable changes to this project will be documented in this file.
44

5-
## [1.1.5] - Current
5+
## [1.1.6] - Current
6+
7+
### Added
8+
- **"next" tag support**: Both Helm and Operator deployments now support `RHDH_VERSION=next`
9+
- Helm: Resolves "next" to semantic version by querying `rhdh-hub-rhel9` image tags
10+
- Operator: Uses `main` branch and `--next` flag instead of release branch
11+
12+
### Changed
13+
- **Default values**: `RHDH_VERSION` defaults to `next` and `INSTALLATION_METHOD` defaults to `helm` when not set
14+
15+
### Environment Variables
16+
- `RHDH_VERSION`: RHDH version to deploy (default: `next`)
17+
- `INSTALLATION_METHOD`: Deployment method - `helm` or `operator` (default: `helm`)
18+
19+
## [1.1.5]
620

721
### Added
822
- **Plugin metadata auto-generation**: When `dynamic-plugins.yaml` doesn't exist, configuration is automatically generated from `metadata/*.yaml` files

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "rhdh-e2e-test-utils",
3-
"version": "1.1.5",
3+
"version": "1.1.6",
44
"description": "Test utilities for RHDH E2E tests",
55
"license": "Apache-2.0",
66
"type": "module",

src/deployment/rhdh/deployment.ts

Lines changed: 86 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,30 @@ export class RHDHDeployment {
187187
`/tmp/${this.deploymentConfig.namespace}-subscription.yaml`,
188188
yaml.dump(subscriptionObject),
189189
);
190+
191+
const version = this.deploymentConfig.version;
192+
const isSemanticVersion = /^\d+(\.\d+)?$/.test(version);
193+
194+
// Use main branch for non-semantic versions (e.g., "next", "latest")
195+
const branch = isSemanticVersion ? `release-${version}` : "main";
196+
197+
// Build version argument based on version type
198+
let versionArg: string;
199+
if (isSemanticVersion) {
200+
versionArg = `-v ${version}`;
201+
} else if (version === "next") {
202+
versionArg = "--next";
203+
} else {
204+
throw new Error(
205+
`Invalid RHDH version "${version}". Use semantic version (e.g., "1.5") or "next".`,
206+
);
207+
}
208+
209+
this._log(`Using operator branch: ${branch}, version arg: ${versionArg}`);
210+
190211
await $`
191212
set -e;
192-
curl -s https://raw.githubusercontent.com/redhat-developer/rhdh-operator/refs/heads/release-${this.deploymentConfig.version}/.rhdh/scripts/install-rhdh-catalog-source.sh | bash -s -- -v ${this.deploymentConfig.version} --install-operator rhdh
213+
curl -sf https://raw.githubusercontent.com/redhat-developer/rhdh-operator/refs/heads/${branch}/.rhdh/scripts/install-rhdh-catalog-source.sh | bash -s -- ${versionArg} --install-operator rhdh
193214
194215
timeout 300 bash -c '
195216
while ! oc get crd/backstages.rhdh.redhat.com -n "${this.deploymentConfig.namespace}" >/dev/null 2>&1; do
@@ -257,8 +278,16 @@ export class RHDHDeployment {
257278
}
258279

259280
private async _resolveChartVersion(version: string): Promise<string> {
260-
// Semantic versions (e.g., 1.2)
261-
if (/^(\d+(\.\d+)?)$/.test(version)) {
281+
let resolvedVersion = version;
282+
283+
// Handle "next" tag by looking up the corresponding version from downstream image
284+
if (version === "next") {
285+
resolvedVersion = await this._resolveVersionFromNextTag();
286+
this._log(`Resolved "next" tag to version: ${resolvedVersion}`);
287+
}
288+
289+
// Semantic versions (e.g., 1.2, 1.10)
290+
if (/^(\d+(\.\d+)?)$/.test(resolvedVersion)) {
262291
const response = await fetch(
263292
"https://quay.io/api/v1/repository/rhdh/chart/tag/?onlyActiveTags=true&limit=600",
264293
);
@@ -271,28 +300,73 @@ export class RHDHDeployment {
271300
const data = (await response.json()) as { tags: Array<{ name: string }> };
272301
const matching = data.tags
273302
.map((t) => t.name)
274-
.filter((name) => name.startsWith(`${version}-`))
303+
.filter((name) => name.startsWith(`${resolvedVersion}-`))
275304
.sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
276305

277306
const latest = matching.at(-1);
278-
if (!latest) throw new Error(`No chart version found for ${version}`);
307+
if (!latest)
308+
throw new Error(`No chart version found for ${resolvedVersion}`);
279309
return latest;
280310
}
281311

282312
// CI build versions (e.g., 1.2.3-CI)
283-
if (version.endsWith("CI")) return version;
313+
if (resolvedVersion.endsWith("CI")) return resolvedVersion;
284314

285315
throw new Error(`Invalid Helm chart version format: "${version}"`);
286316
}
287317

318+
/**
319+
* Resolve the semantic version from the "next" tag by looking up the
320+
* downstream image (rhdh-hub-rhel9) and finding tags with the same digest.
321+
*/
322+
private async _resolveVersionFromNextTag(): Promise<string> {
323+
// Fetch all active tags in a single API call
324+
const response = await fetch(
325+
"https://quay.io/api/v1/repository/rhdh/rhdh-hub-rhel9/tag/?onlyActiveTags=true&limit=75",
326+
);
327+
328+
if (!response.ok) {
329+
throw new Error(`Failed to fetch image tags: ${response.statusText}`);
330+
}
331+
332+
// Use Record to avoid snake_case linting issues with Quay API response
333+
const data = (await response.json()) as {
334+
tags: Array<Record<string, unknown>>;
335+
};
336+
337+
// Find the "next" tag and get its digest
338+
const nextTag = data.tags.find((t) => t["name"] === "next");
339+
if (!nextTag) {
340+
throw new Error('No "next" tag found in rhdh-hub-rhel9 repository');
341+
}
342+
343+
const digest = nextTag["manifest_digest"] as string;
344+
this._log(`"next" tag digest: ${digest}`);
345+
346+
// Find semantic version tag (e.g., "1.10") with the same digest
347+
const semanticVersionTag = data.tags.find(
348+
(t) =>
349+
t["manifest_digest"] === digest &&
350+
/^\d+\.\d+$/.test(t["name"] as string),
351+
);
352+
353+
if (!semanticVersionTag) {
354+
throw new Error(
355+
`Could not find semantic version tag for "next" (digest: ${digest})`,
356+
);
357+
}
358+
359+
return semanticVersionTag["name"] as string;
360+
}
361+
288362
private _buildDeploymentConfig(input: DeploymentOptions): DeploymentConfig {
289-
const version = input.version ?? process.env.RHDH_VERSION;
363+
// Default to "next" if RHDH_VERSION not set
364+
const version = input.version ?? process.env.RHDH_VERSION ?? "next";
365+
// Default to "helm" if INSTALLATION_METHOD not set
290366
const method =
291-
input.method ?? (process.env.INSTALLATION_METHOD as DeploymentMethod);
292-
293-
if (!version) throw new Error("RHDH version is required");
294-
if (!method)
295-
throw new Error("Installation method (helm/operator) is required");
367+
input.method ??
368+
(process.env.INSTALLATION_METHOD as DeploymentMethod) ??
369+
"helm";
296370

297371
const base: DeploymentConfigBase = {
298372
version,

0 commit comments

Comments
 (0)