@@ -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