diff --git a/.github/workflows/generate-release-crs.yaml b/.github/workflows/generate-release-crs.yaml new file mode 100644 index 00000000..3aa148be --- /dev/null +++ b/.github/workflows/generate-release-crs.yaml @@ -0,0 +1,119 @@ +name: Apply Konflux Override Snapshot and create Release CR PR +on: + workflow_dispatch: + inputs: + revision: + description: "SO branch or revision with the manifests" + default: "release-1." + required: true + environment: + description: "Environment to release to" + type: choice + options: + - stage + - prod + required: true + default: "prod" + skip-apply: + description: "Skip override-snapshot apply" + type: boolean + required: false + default: "false" +defaults: + run: + shell: bash +jobs: + snapshot-apply: + name: Apply Konflux Override Snapshot + runs-on: ubuntu-latest + if: ${{ inputs.skip-apply == 'false' }} + steps: + - name: Checkout serverless operator + uses: actions/checkout@v4 + with: + ref: "${{ inputs.revision }}" + repository: 'openshift-knative/serverless-operator' + path: ./src/github.com/openshift-knative/serverless-operator + + - name: Setup kubeconfig + env: + KONFLUX_TOKEN: ${{ secrets.KONFLUX_SA_TOKEN }} + run: | + kubectl config set-credentials konflux-sa --token "$KONFLUX_TOKEN" + kubectl config set-cluster konflux --server=https://api.stone-prd-rh01.pg1f.p1.openshiftapps.com:6443 + kubectl config set-context konflux-sa@konflux --user=konflux-sa --namespace=ocp-serverless-tenant --cluster=konflux + kubectl config use-context konflux-sa@konflux + + - name: Apply Override Snapshots + working-directory: ./src/github.com/openshift-knative/hack/openshift-knative/serverless-operator + run: make apply-override-snapshot + + generate-release-crs: + name: Generate Release CRs + runs-on: ubuntu-latest + needs: snapshot-apply + steps: + - name: Checkout openshift-knative/hack + uses: actions/checkout@v4 + with: + repository: openshift-knative/hack + path: ./src/github.com/openshift-knative/hack + token: ${{ secrets.SERVERLESS_QE_ROBOT }} + + - name: Generate Konflux component release CR + working-directory: ./src/github.com/openshift-knative/hack + run: | + make generate-konflux-release ARGS="--environment ${{ inputs.environment }} --so-revision ${{ inputs.revision }} --type component" + + - name: Create component release CR Pull Request + env: + GH_TOKEN: ${{ secrets.SERVERLESS_QE_ROBOT }} + GITHUB_TOKEN: ${{ secrets.SERVERLESS_QE_ROBOT }} + run: | + set -x + git remote add fork "https://github.com/serverless-qe/hack.git" + branch="release-crs-${{inputs.revision}}-component-${{inputs.environment}}" + branch=${branch,,} #lower case of branch name + remote_exists=$(git ls-remote --heads fork "$branch") + if [ -z "$remote_exists" ]; then + # remote doesn't exist. + git push "https://serverless-qe:${GH_TOKEN}@github.com/serverless-qe/hack.git" "$branch:$branch" -f || exit 1 + fi + git fetch fork "$branch" + if git diff --quiet "fork/$branch" "$branch"; then + echo "Branches are identical. No need to force push." + else + git push "https://serverless-qe:${GH_TOKEN}@github.com/serverless-qe/hack.git" "$branch:$branch" -f + fi + gh pr create --base main --head "serverless-qe:$branch" --fill --label "do-not-merge/hold" || true + # Use the repository cloned by the konflux-release-gen tool + working-directory: ./src/github.com/openshift-knative/hack/openshift-knative/hack + + - name: Generate Konflux FBC release CRs + working-directory: ./src/github.com/openshift-knative/hack + run: | + make generate-konflux-release ARGS="--environment ${{ inputs.environment }} --so-revision ${{ inputs.revision }} --type fbc" + + - name: Create FBC release CR Pull Request + env: + GH_TOKEN: ${{ secrets.SERVERLESS_QE_ROBOT }} + GITHUB_TOKEN: ${{ secrets.SERVERLESS_QE_ROBOT }} + run: | + set -x + git remote add fork "https://github.com/serverless-qe/hack.git" + branch="release-crs-${{inputs.revision}}-fbc-${{inputs.environment}}" + branch=${branch,,} #lower case of branch name + remote_exists=$(git ls-remote --heads fork "$branch") + if [ -z "$remote_exists" ]; then + # remote doesn't exist. + git push "https://serverless-qe:${GH_TOKEN}@github.com/serverless-qe/hack.git" "$branch:$branch" -f || exit 1 + fi + git fetch fork "$branch" + if git diff --quiet "fork/$branch" "$branch"; then + echo "Branches are identical. No need to force push." + else + git push "https://serverless-qe:${GH_TOKEN}@github.com/serverless-qe/hack.git" "$branch:$branch" -f + fi + gh pr create --base main --head "serverless-qe:$branch" --fill --label "do-not-merge/hold" || true + # Use the repository cloned by the konflux-release-gen tool + working-directory: ./src/github.com/openshift-knative/hack/openshift-knative/hack diff --git a/Makefile b/Makefile index 1464f992..5948b53e 100644 --- a/Makefile +++ b/Makefile @@ -43,6 +43,10 @@ discover-branches: clean go run github.com/openshift-knative/hack/cmd/discover $(ARGS) .PHONY: discover-branches +generate-konflux-release: clean + go run github.com/openshift-knative/hack/cmd/konflux-release-gen $(ARGS) +.PHONY: generate-konflux-release + generate-ci-action: go run github.com/openshift-knative/hack/cmd/generate-ci-action .PHONY: generate-ci-action diff --git a/cmd/konflux-release-gen/main.go b/cmd/konflux-release-gen/main.go new file mode 100644 index 00000000..bc803209 --- /dev/null +++ b/cmd/konflux-release-gen/main.go @@ -0,0 +1,170 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "log" + "os" + "path/filepath" + "strings" + + "github.com/coreos/go-semver/semver" + gyaml "github.com/ghodss/yaml" + "github.com/openshift-knative/hack/pkg/konfluxgen" + "github.com/openshift-knative/hack/pkg/project" + "github.com/openshift-knative/hack/pkg/prowgen" + "github.com/openshift-knative/hack/pkg/soversion" + "github.com/spf13/pflag" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func main() { + if err := run(); err != nil { + log.Fatal(err) + } +} + +func run() error { + ctx := context.TODO() + + const ( + componentReleaseType = "component" + fbcReleaseType = "fbc" + + stageEnv = "stage" + prodEnv = "prod" + ) + + var environment, soRevision, overrideSnapshotDir, output, releaseType string + pflag.StringVar(&environment, "environment", "prod", fmt.Sprintf("Environment to use. Available values: [%s, %s]", stageEnv, prodEnv)) + pflag.StringVar(&soRevision, "so-revision", "main", "SO revision to get snapshots from") + pflag.StringVar(&releaseType, "type", "component", fmt.Sprintf("Type of the release. Available values: [%s, %s]", componentReleaseType, fbcReleaseType)) + pflag.StringVar(&overrideSnapshotDir, "so-snapshot-directory", ".konflux-release", "The directory containing Serverless Operator override snapshots") + pflag.StringVar(&output, "output", ".konflux", "Path to output directory") + pflag.Parse() + + if environment != stageEnv && environment != prodEnv { + return fmt.Errorf("invalid environment: %s", environment) + } + + // clone SO repo to get metadata & snapshots for given revision + soRepo := prowgen.Repository{Org: "openshift-knative", Repo: "serverless-operator"} + if err := prowgen.GitClone(ctx, soRepo); err != nil { + return fmt.Errorf("could not clone Git repository: %w", err) + } + + if err := prowgen.GitCheckout(ctx, soRepo, soRevision); err != nil { + return fmt.Errorf("could not checkout Git revision %s of Serverless Operator: %w", soRevision, err) + } + + soProjectYamlPath := filepath.Join(soRepo.RepositoryDirectory(), "olm-catalog", "serverless-operator", "project.yaml") + soMetadata, err := project.ReadMetadataFile(soProjectYamlPath) + if err != nil { + return fmt.Errorf("could not read project.yaml: %w", err) + } + + soVersion := semver.New(soMetadata.Project.Version) + soReleaseBranch := soversion.BranchName(soVersion) + + overrideSnapshotsPath := filepath.Join(soRepo.RepositoryDirectory(), overrideSnapshotDir) + + // clone hack repo so we can commit the changes + hackRepo := prowgen.Repository{Org: "openshift-knative", Repo: "hack"} + outputDir := filepath.Join(hackRepo.RepositoryDirectory(), output) + + if err := prowgen.GitMirror(ctx, hackRepo); err != nil { + return fmt.Errorf("could not clone Git repository: %w", err) + } + + if err := prowgen.GitCheckout(ctx, hackRepo, "main"); err != nil { + return fmt.Errorf("could not checkout main branch of hack repo: %w", err) + } + + if strings.ToLower(releaseType) == componentReleaseType { + snapshot, err := componentSnapshotName(overrideSnapshotsPath) + if err != nil { + return fmt.Errorf("could not get snapshot name: %w", err) + } + appName := konfluxgen.AppName(soReleaseBranch) + releasePlan := konfluxgen.ReleasePlanAdmissionName(appName, soMetadata.Project.Version, environment) // releasePlanName == releasePlanAdmissionName + + cfg := konfluxgen.ReleaseConfig{ + Snapshot: snapshot, + ReleasePlan: releasePlan, + Environment: environment, + ResourcesOutputPath: outputDir, + } + + if err := konfluxgen.GenerateRelease(cfg); err != nil { + return fmt.Errorf("could not generate release: %w", err) + } + } else if strings.ToLower(releaseType) == fbcReleaseType { + for _, ocpVersion := range soMetadata.Requirements.OcpVersion.List { + ocpVersionFlat := strings.ReplaceAll(ocpVersion, ".", "") + + snapshot, err := fbcSnapshotName(overrideSnapshotsPath, ocpVersionFlat) + if err != nil { + return fmt.Errorf("could not get snapshot name: %w", err) + } + + appName := konfluxgen.FBCAppName(soReleaseBranch, ocpVersionFlat) + releasePlan := konfluxgen.ReleasePlanAdmissionName(appName, soMetadata.Project.Version, environment) // releasePlanName == releasePlanAdmissionName + + cfg := konfluxgen.ReleaseConfig{ + Snapshot: snapshot, + ReleasePlan: releasePlan, + Environment: environment, + ResourcesOutputPath: outputDir, + } + + if err := konfluxgen.GenerateRelease(cfg); err != nil { + return fmt.Errorf("could not generate release: %w", err) + } + } + } else { + return fmt.Errorf("invalid releaseType: %s", releaseType) + } + + pushBranch := strings.ToLower(fmt.Sprintf("release-crs-%s-%s-%s", soRevision, releaseType, environment)) + commitMsg := fmt.Sprintf("Add %s Release CRs from %s revision for %s", releaseType, soRevision, environment) + + if err := prowgen.PushBranch(ctx, hackRepo, nil, pushBranch, commitMsg); err != nil { + return fmt.Errorf("could not push to branch %s: %w", pushBranch, err) + } + + return nil +} + +func fbcSnapshotName(soReleaseFolder string, ocpVersion string) (string, error) { + filename := fmt.Sprintf("override-snapshot-fbc-%s.yaml", ocpVersion) + return parseSnapshotName(filepath.Join(soReleaseFolder, filename)) +} + +func componentSnapshotName(soReleaseFolder string) (string, error) { + return parseSnapshotName(filepath.Join(soReleaseFolder, "override-snapshot.yaml")) +} + +func parseSnapshotName(snapshotFile string) (string, error) { + snapshot := metav1.PartialObjectMetadata{} + + y, err := os.ReadFile(snapshotFile) + if err != nil { + return "", fmt.Errorf("failed to read snapshot file: %w", err) + } + + j, err := gyaml.YAMLToJSON(y) + if err != nil { + return "", fmt.Errorf("failed to convert snapshot file to json: %w", err) + } + + if err := json.Unmarshal(j, &snapshot); err != nil { + return "", fmt.Errorf("failed to unmarshal snapshot file: %w", err) + } + + if snapshot.Name == "" { + return "", fmt.Errorf("snapshot.Name is empty") + } + + return snapshot.Name, nil +} diff --git a/pkg/konfluxgen/konfluxgen.go b/pkg/konfluxgen/konfluxgen.go index ca5b7c5e..f3ff6f67 100644 --- a/pkg/konfluxgen/konfluxgen.go +++ b/pkg/konfluxgen/konfluxgen.go @@ -5,6 +5,7 @@ import ( "crypto/md5" "embed" "encoding/json" + "errors" "fmt" "io/fs" "log" @@ -76,6 +77,9 @@ var FBCReleasePlanAdmissionsTemplate embed.FS //go:embed releaseplan.template.yaml var ReleasePlanTemplate embed.FS +//go:embed release.template.yaml +var ReleaseTemplate embed.FS + //go:embed renovate.template.json var RenovateTemplate embed.FS @@ -197,8 +201,8 @@ func Generate(cfg Config) error { } if !cfg.ResourcesOutputPathSkipRemove { - if err := os.RemoveAll(cfg.ResourcesOutputPath); err != nil { - return fmt.Errorf("failed to remove %q directory: %w", cfg.ResourcesOutputPath, err) + if err := removeAllExcept(cfg.ResourcesOutputPath, filepath.Join(cfg.ResourcesOutputPath, ReleasesDirName)); err != nil { + return fmt.Errorf("failed to clean %q directory: %w", cfg.ResourcesOutputPath, err) } } @@ -538,8 +542,8 @@ func Generate(cfg Config) error { cfg.ResourcesOutputPath, cfg.ApplicationName, csv.Spec.Version.String(), - /* In this case RPA.name == RP.name */ releasePlanAdmissionName, - releasePlanAdmissionName, + /* In this case RPA.name == RP.name */ ReleasePlanAdmissionName, + ReleasePlanAdmissionName, ); err != nil { return fmt.Errorf("failed to generate ReleasePlan: %w", err) } @@ -707,8 +711,7 @@ func replace(input interface{}, old, new string) string { } func removeAllExcept(dir string, excludedFiles ...string) error { - if _, err := os.Stat(dir); err != nil { - // directory does not exist anyhow + if !fileExists(dir) { return nil } @@ -723,11 +726,25 @@ func removeAllExcept(dir string, excludedFiles ...string) error { for _, excludedFile := range excludedFiles { if path == excludedFile { + // skip deletion + if d.IsDir() { + // skip whole directory, so no need to check on child files too + return filepath.SkipDir + } return nil } } - return os.RemoveAll(path) + if err := os.RemoveAll(path); err != nil { + return err + } + + if d.IsDir() { + // we deleted the directory, so no need to check on child files too + return filepath.SkipDir + } + + return nil }) } @@ -782,7 +799,7 @@ func makeValidName(n string) string { } func WriteFileReplacingNewerTaskImages(name string, data []byte, perm os.FileMode) error { - if _, err := os.Stat(name); err != nil { + if !fileExists(name) { return os.WriteFile(name, data, perm) } @@ -858,7 +875,7 @@ func GenerateFBCReleasePlanAdmission(applications []string, resourceOutputPath s return fmt.Errorf("failed to parse SO version %q: %w", soVersion, err) } - rpaName := fbcReleasePlanAdmissionName(appName, soVersion, ProdEnv) + rpaName := FBCReleasePlanAdmissionName(appName, soVersion, ProdEnv) fbcData := rpaFBCData{ Name: rpaName, Applications: applications, @@ -877,7 +894,7 @@ func GenerateFBCReleasePlanAdmission(applications []string, resourceOutputPath s } // generate RPA for stage - rpaName = fbcReleasePlanAdmissionName(appName, soVersion, StageEnv) + rpaName = FBCReleasePlanAdmissionName(appName, soVersion, StageEnv) fbcData = rpaFBCData{ Name: rpaName, Applications: applications, @@ -932,7 +949,7 @@ func GenerateComponentReleasePlanAdmission(csv *operatorsv1alpha1.ClusterService ImageRepository: fmt.Sprintf("%s/%s", prodRegistry, bundleRepoName), }) - rpaName := releasePlanAdmissionName(appName, soVersion.String(), ProdEnv) + rpaName := ReleasePlanAdmissionName(appName, soVersion.String(), ProdEnv) rpaData := rpaComponentData{ Name: rpaName, ApplicationName: appName, @@ -959,7 +976,7 @@ func GenerateComponentReleasePlanAdmission(csv *operatorsv1alpha1.ClusterService }) } - rpaName = releasePlanAdmissionName(appName, soVersion.String(), StageEnv) + rpaName = ReleasePlanAdmissionName(appName, soVersion.String(), StageEnv) rpaData = rpaComponentData{ Name: rpaName, ApplicationName: appName, @@ -1034,11 +1051,11 @@ func (f releasePlanNameFunc) forceAppName(appName string) releasePlanNameFunc { } } -func releasePlanAdmissionName(appName, soVersion, env string) string { +func ReleasePlanAdmissionName(appName, soVersion, env string) string { return Truncate(Sanitize(fmt.Sprintf("%s-%s-%s", appName, soVersion, env))) } -func fbcReleasePlanAdmissionName(appName, soVersion, env string) string { +func FBCReleasePlanAdmissionName(appName, soVersion, env string) string { return Truncate(Sanitize(fmt.Sprintf("%s-%s-fbc-%s", appName, soVersion, env))) } @@ -1085,10 +1102,10 @@ func GenerateReleasePlans(applications []string, resourceOutputPath string, appN for _, app := range applications { // There is only a single RPA for all FBC applications and the name uses `appName` vs the FBC-specific application name. - var rpaNameFunc releasePlanNameFunc = fbcReleasePlanAdmissionName + var rpaNameFunc releasePlanNameFunc = FBCReleasePlanAdmissionName rpaNameFunc = rpaNameFunc.forceAppName(appName) - if err := GenerateComponentsReleasePlans(resourceOutputPath, app, soVersion, releasePlanAdmissionName, rpaNameFunc); err != nil { + if err := GenerateComponentsReleasePlans(resourceOutputPath, app, soVersion, ReleasePlanAdmissionName, rpaNameFunc); err != nil { return fmt.Errorf("failed to generate release plan for %q: %w", app, err) } } @@ -1177,3 +1194,88 @@ func loadClusterServiceVerion(path string) (*operatorsv1alpha1.ClusterServiceVer } return csv, nil } + +type ReleaseConfig struct { + Snapshot string + ReleasePlan string + Environment string + ResourcesOutputPath string +} + +type Release struct { + Name string + Snapshot string + ReleasePlan string +} + +func GenerateRelease(cfg ReleaseConfig) error { + fullOutputPath := filepath.Join(cfg.ResourcesOutputPath, ReleasesDirName) + // make sure output path exists + if err := os.MkdirAll(fullOutputPath, os.ModePerm); err != nil { + return fmt.Errorf("failed to create directory %q: %w", fullOutputPath, err) + } + + releaseName := unusedReleaseName(fullOutputPath, cfg.ReleasePlan) + releaseFileName := fmt.Sprintf("%s.yaml", releaseName) + + data := Release{ + Name: releaseName, + Snapshot: cfg.Snapshot, + ReleasePlan: cfg.ReleasePlan, + } + + if err := executeReleaseTemplate(data, filepath.Join(fullOutputPath, releaseFileName)); err != nil { + return fmt.Errorf("failed to execute release template: %w", err) + } + + return nil +} + +func executeReleaseTemplate(data Release, outputFilePath string) error { + funcs := template.FuncMap{ + "sanitize": Sanitize, + "truncate": Truncate, + } + + tpl, err := template.New("release.template.yaml").Delims("{{{", "}}}").Funcs(funcs).ParseFS(ReleaseTemplate, "*.yaml") + if err != nil { + return fmt.Errorf("failed to parse Release template: %w", err) + } + + buf := &bytes.Buffer{} + if err := tpl.Execute(buf, data); err != nil { + return fmt.Errorf("failed to execute template for Release: %w", err) + } + if err := os.WriteFile(outputFilePath, buf.Bytes(), 0777); err != nil { + return fmt.Errorf("failed to write Release file %q: %w", outputFilePath, err) + } + + return nil +} + +func unusedReleaseName(outputPath, releaseName string) string { + releaseFilePath := filepath.Join(outputPath, fmt.Sprintf("%s.yaml", releaseName)) + unusedRelease := releaseName + for exists, i := fileExists(releaseFilePath), 2; exists; i++ { + unusedRelease = fmt.Sprintf("%s-%d", releaseName, i) + releaseFilePath = filepath.Join(outputPath, fmt.Sprintf("%s.yaml", unusedRelease)) + exists = fileExists(releaseFilePath) + } + + return unusedRelease +} + +func fileExists(path string) bool { + if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) { + return false + } + return true +} + +func AppName(soBranch string) string { + return fmt.Sprintf("serverless-operator %s", soBranch) +} + +func FBCAppName(soBranch, ocpVersion string) string { + return fmt.Sprintf("serverless-operator %s FBC %s", soBranch, ocpVersion) +} diff --git a/pkg/konfluxgen/release.template.yaml b/pkg/konfluxgen/release.template.yaml new file mode 100644 index 00000000..b3185a70 --- /dev/null +++ b/pkg/konfluxgen/release.template.yaml @@ -0,0 +1,7 @@ +apiVersion: appstudio.redhat.com/v1alpha1 +kind: Release +metadata: + name: {{{ .Name }}} +spec: + snapshot: {{{ .Snapshot }}} + releasePlan: {{{ .ReleasePlan }}} diff --git a/pkg/prowgen/prowgen_konflux.go b/pkg/prowgen/prowgen_konflux.go index 256aef76..ae488eda 100644 --- a/pkg/prowgen/prowgen_konflux.go +++ b/pkg/prowgen/prowgen_konflux.go @@ -171,7 +171,7 @@ func GenerateKonflux(ctx context.Context, openshiftRelease Repository, configs [ cfg := konfluxgen.Config{ OpenShiftReleasePath: openshiftRelease.RepositoryDirectory(), - ApplicationName: fmt.Sprintf("serverless-operator %s", soBranchName), + ApplicationName: konfluxgen.AppName(soBranchName), BuildArgs: buildArgs, Includes: []string{ fmt.Sprintf("ci-operator/config/%s/.*%s.*.yaml", r.RepositoryDirectory(), branchName), @@ -357,7 +357,7 @@ func GenerateKonfluxServerlessOperator(ctx context.Context, openshiftRelease Rep cfg := konfluxgen.Config{ OpenShiftReleasePath: openshiftRelease.RepositoryDirectory(), - ApplicationName: fmt.Sprintf("serverless-operator %s", release), + ApplicationName: konfluxgen.AppName(release), BuildArgs: buildArgs, ComponentNameFunc: func(cfg cioperatorapi.ReleaseBuildConfiguration, ib cioperatorapi.ProjectDirectoryImageBuildStepConfiguration) string { return fmt.Sprintf("%s-%s", ib.To, release) @@ -498,15 +498,15 @@ func getPrefetchDeps(repo Repository, branch string) (*konfluxgen.PrefetchDeps, func generateFBCApplications(soMetadata *project.Metadata, openshiftRelease Repository, r Repository, branch string, release string, resourceOutputPath string, buildArgs []string) error { fbcApps := make([]string, 0, len(soMetadata.Requirements.OcpVersion.List)) - for _, v := range soMetadata.Requirements.OcpVersion.List { + for _, ocpVersion := range soMetadata.Requirements.OcpVersion.List { - opmImage, err := getOPMImage(v) + opmImage, err := getOPMImage(ocpVersion) if err != nil { - return fmt.Errorf("failed to get OPM image ref for OCP %q: %w", v, err) + return fmt.Errorf("failed to get OPM image ref for OCP %q: %w", ocpVersion, err) } buildArgs := append(buildArgs, fmt.Sprintf("OPM_IMAGE=%s", opmImage)) - fbcAppName := fmt.Sprintf("serverless-operator %s FBC %s", release, v) + fbcAppName := konfluxgen.FBCAppName(release, ocpVersion) c := konfluxgen.Config{ OpenShiftReleasePath: openshiftRelease.RepositoryDirectory(), @@ -518,7 +518,7 @@ func generateFBCApplications(soMetadata *project.Metadata, openshiftRelease Repo return fmt.Sprintf("&& ("+ " files.all.exists(x, x.matches('^olm-catalog/serverless-operator-index/v%s/')) ||"+ " files.all.exists(x, x.matches('^.tekton/'))"+ - " )", v) + " )", ocpVersion) }, AdditionalComponentConfigs: []konfluxgen.TemplateConfig{ { @@ -530,10 +530,10 @@ func generateFBCApplications(soMetadata *project.Metadata, openshiftRelease Repo }, Images: []cioperatorapi.ProjectDirectoryImageBuildStepConfiguration{ { - To: cioperatorapi.PipelineImageStreamTagReference(fmt.Sprintf("serverless-index-%s-fbc-%s", release, v)), + To: cioperatorapi.PipelineImageStreamTagReference(fmt.Sprintf("serverless-index-%s-fbc-%s", release, ocpVersion)), ProjectDirectoryImageBuildInputs: cioperatorapi.ProjectDirectoryImageBuildInputs{ DockerfilePath: "Dockerfile", - ContextDir: fmt.Sprintf("./olm-catalog/serverless-operator-index/v%s", v), + ContextDir: fmt.Sprintf("./olm-catalog/serverless-operator-index/v%s", ocpVersion), }, }, }, @@ -544,7 +544,7 @@ func generateFBCApplications(soMetadata *project.Metadata, openshiftRelease Repo return string(ib.To) }, FBCImages: []string{ - fmt.Sprintf("serverless-index-%s-fbc-%s", release, v), + fmt.Sprintf("serverless-index-%s-fbc-%s", release, ocpVersion), }, ResourcesOutputPathSkipRemove: true, PipelinesOutputPathSkipRemove: true,