From 62e4c24c056c32c761d2e1f2e67111a2c57107db Mon Sep 17 00:00:00 2001 From: myan Date: Thu, 12 Mar 2026 00:44:20 -0400 Subject: [PATCH 1/8] chore: update new-release skill with bug fixes and docs - Fix 02-openshift-release.sh: replace all 'master' with 'main' for openshift/release repo (branch name, git fetch, checkout, PR base) - Fix 05-grafana.sh: calculate PREV_GRAFANA_TAG directly from version formula instead of remote branch detection; also fix fi placement bug causing readonly constants to be inside else block on macOS - Fix 06-postgres-exporter.sh: calculate PREV_POSTGRES_TAG directly from version formula instead of remote branch detection - Update SKILL.md: add expected PRs and verification details per repo, fix OCP version examples (4.17-4.21 -> 4.18-4.22), fix Total Output from 5 to 11 PRs, fix script path (cut-release -> new-release), unify all version examples to release-2.17/v1.8.0/globalhub-1-8 Signed-off-by: myan --- .claude/skills/new-release/SKILL.md | 147 +++++++++++++----- .../scripts/02-openshift-release.sh | 22 +-- .../skills/new-release/scripts/05-grafana.sh | 62 +------- .../scripts/06-postgres-exporter.sh | 65 ++------ 4 files changed, 137 insertions(+), 159 deletions(-) diff --git a/.claude/skills/new-release/SKILL.md b/.claude/skills/new-release/SKILL.md index 330b28034d..0cc7620573 100644 --- a/.claude/skills/new-release/SKILL.md +++ b/.claude/skills/new-release/SKILL.md @@ -54,7 +54,11 @@ The skill uses ACM release branch names as the primary input and automatically c ## Repository Workflow -The skill manages releases across 6 repositories, each with its own dedicated script: +The skill manages releases across 6 repositories, each with its own dedicated script. + +> **Version example below uses release-2.17 / Global Hub v1.8.0 (globalhub-1-8)** + +--- ### Repository 1: multicluster-global-hub (Script 01) @@ -65,6 +69,7 @@ The skill manages releases across 6 repositories, each with its own dedicated sc 2. **Create release branch**: Creates ACM release branch (e.g., release-2.17) from updated main 3. **Create PR to main**: Creates PR to upstream main with new release configurations 4. **Update previous release**: Updates previous release branch's `.tekton/` files to set `target_branch` to the previous release branch (e.g., globalhub-1-7 files updated to `target_branch="release-2.16"`) +5. **Update current release**: Adds new `.tekton/` files (globalhub-1-8) to the current release branch (release-2.17) **Key behavior**: - New `.tekton/` files (e.g., globalhub-1-8) created by **copying** old files (globalhub-1-7), not renaming @@ -72,7 +77,15 @@ The skill manages releases across 6 repositories, each with its own dedicated sc - Previous release branch gets updated so its files point to itself (not main) - Ensures continuous file naming progression: globalhub-1-6 → globalhub-1-7 → globalhub-1-8 -**Outputs**: 1 PR (new release configurations to main), direct pushes to release branches +**Expected PRs**: 3 + +| PR | Target Branch | Content | Verification | +|----|--------------|---------|--------------| +| PR to main | `main` | New `.tekton/globalhub-1-8-*.yaml` files; old globalhub-1-7 files removed; Containerfile version updated; Makefile VERSION/CHANNELS updated | Check `.tekton/` has globalhub-1-8 files with `target_branch=main` (pull-request) and `target_branch=release-2.17` (push) | +| PR to prev release | `release-2.16` | globalhub-1-7 `pull-request.yaml` target_branch changed from `main` → `release-2.16` | Verify `*pull-request.yaml` has `target_branch=release-2.16` | +| PR to current release | `release-2.17` | New globalhub-1-8 `.tekton/` files added to release branch | Verify `*push.yaml` has `target_branch=release-2.17` | + +--- ### Repository 2: openshift/release (Script 02) @@ -80,68 +93,115 @@ The skill manages releases across 6 repositories, each with its own dedicated sc **What it does**: - Updates main branch CI configuration (promotion, fast-forward) -- Creates new release pipeline configuration -- Auto-generates presubmit/postsubmit jobs using `make update` -- Validates container engine availability (Docker or Podman) +- Creates new release pipeline configuration by copying from previous release +- Replaces version strings: ACM branch, version number, image prefix, GH version tag +- Auto-generates presubmit/postsubmit jobs using `make update` + `make jobs` - Creates PR with all CI changes -**Outputs**: 1 PR (CI configuration) +**Expected PRs**: 1 + +| PR | Target Branch | Content | Verification | +|----|--------------|---------|--------------| +| PR to main | `main` | `ci-operator/config/stolostron/multicluster-global-hub/stolostron-multicluster-global-hub-release-2.17.yaml` created; main config updated with new release references | Check config file exists and contains `branch: release-2.17`, `name: "2.17"`, `release-218` prefix | + +--- ### Repository 3: operator-bundle (Script 03) **Repository**: [stolostron/multicluster-global-hub-operator-bundle](https://github.com/stolostron/multicluster-global-hub-operator-bundle) **What it does**: -- Creates bundle branch using Global Hub version (e.g., release-1.8 from v1.8.0) +- Checks out release branch (e.g., release-1.8) - Updates `images_digest_mirror_set.yaml` with new image tags -- Renames and updates tekton pipelines (pull-request and push) -- Updates bundle image labels to new version -- Updates `konflux-patch.sh` image references -- Creates PR with all bundle changes +- Renames tekton pipelines: globalhub-1-7 → globalhub-1-8 (pull-request and push) +- Updates bundle image labels and `konflux-patch.sh` image references +- Creates PR to the release branch +- Creates cleanup PR to remove old GitHub Actions from previous release branch -**Outputs**: 1 PR (bundle updates to main) +**Expected PRs**: 2 + +| PR | Target Branch | Content | Verification | +|----|--------------|---------|--------------| +| PR to release branch | `release-1.8` | tekton pipelines renamed globalhub-1-7 → globalhub-1-8; image tags updated to globalhub-1-8 | Check `.tekton/` has `*globalhub-1-8*.yaml` files | +| Cleanup PR | `release-1.7` | Remove `.github/workflows/` GitHub Actions from old release branch | Check old branch no longer has Actions workflows | + +--- ### Repository 4: operator-catalog (Script 04) **Repository**: [stolostron/multicluster-global-hub-operator-catalog](https://github.com/stolostron/multicluster-global-hub-operator-catalog) **What it does**: -- Creates catalog branch using Global Hub version (e.g., release-1.8) +- Creates/updates catalog branch (e.g., release-1.8) - Updates `images-mirror-set.yaml` with new image tags -- **Adds** new OCP version pipelines (e.g., OCP 4.21 for release-1.8) -- **Removes** old OCP version pipelines (e.g., OCP 4.16) -- Updates existing OCP version pipelines (4.17-4.20) +- **Adds** new OCP version pipeline (e.g., OCP 4.22 for release-1.8) +- **Removes** oldest OCP version pipeline (e.g., OCP 4.17) +- Updates existing OCP version pipelines (4.18-4.21) - Updates `README.md` with new version information - Updates GitHub Actions workflow for new release branch -- Creates **2 PRs**: - - Main PR: New release configuration to main branch - - Cleanup PR: Remove GitHub Actions from old release branch +- Creates PR to main with new release configuration +- Creates PR to catalog release branch with pipeline updates +- Creates cleanup PR to remove GitHub Actions from old release branch **OCP Version Formula**: OCP_MIN = 4.(10 + GH_MINOR), OCP_MAX = OCP_MIN + 4 -**Outputs**: 2 PRs (main release + cleanup) +**Expected PRs**: 3 + +| PR | Target Branch | Content | Verification | +|----|--------------|---------|--------------| +| PR to main | `main` | New release-1.8 catalog config; OCP version lifecycle managed | Check README lists OCP 4.18-4.22; new OCP pipeline added | +| PR to catalog branch | `release-1.8` | pipeline updates, image mirror set updated | Check `images-mirror-set.yaml` has globalhub-1-8 tags | +| Cleanup PR | `release-1.7` | Remove `.github/workflows/` from old release branch | Check old branch no longer has Actions workflows | + +--- ### Repository 5: glo-grafana (Script 05) **Repository**: [stolostron/glo-grafana](https://github.com/stolostron/glo-grafana) **What it does**: -- Creates grafana branch using Global Hub version (e.g., release-1.8) -- Renames and updates tekton pipelines (pull-request and push) +- Checks out grafana release branch (e.g., release-1.8) +- Renames tekton pipelines: globalhub-1-7 → globalhub-1-8 (pull-request and push) - Updates branch references in pipeline files +- Creates PR to the release branch -**Outputs**: Branch creation only (no PR) +**Expected PRs**: 1 + +| PR | Target Branch | Content | Verification | +|----|--------------|---------|--------------| +| PR to grafana branch | `release-1.8` | tekton pipelines renamed globalhub-1-7 → globalhub-1-8; branch references updated | Check `.tekton/` has `glo-grafana-globalhub-1-8-pull-request.yaml` and `glo-grafana-globalhub-1-8-push.yaml` | + +--- ### Repository 6: postgres_exporter (Script 06) **Repository**: [stolostron/postgres_exporter](https://github.com/stolostron/postgres_exporter) **What it does**: -- Creates postgres_exporter branch using ACM version (e.g., release-2.17) -- Renames and updates tekton pipelines (pull-request and push) +- Checks out postgres_exporter release branch (e.g., release-2.17) +- Renames tekton pipelines: globalhub-1-7 → globalhub-1-8 (pull-request and push) - Updates branch references in pipeline files +- Creates PR to the release branch + +**Expected PRs**: 1 + +| PR | Target Branch | Content | Verification | +|----|--------------|---------|--------------| +| PR to release branch | `release-2.17` | tekton pipelines renamed globalhub-1-7 → globalhub-1-8; branch references updated | Check `.tekton/` has `postgres-exporter-globalhub-1-8-pull-request.yaml` and `postgres-exporter-globalhub-1-8-push.yaml` | + +--- + +## Total Expected Output Summary -**Outputs**: Branch creation only (no PR) +| Repo | PRs | Branches | +|------|-----|---------| +| multicluster-global-hub | 3 (main, prev-release, curr-release) | release-2.17 | +| openshift/release | 1 (main) | — | +| operator-bundle | 2 (release-1.8, cleanup release-1.7) | release-1.8 | +| operator-catalog | 3 (main, release-1.8, cleanup release-1.7) | release-1.8 | +| glo-grafana | 1 (release-1.8) | release-1.8 | +| postgres_exporter | 1 (release-2.17) | release-2.17 | +| **Total** | **11 PRs** | **5 branches** | ## Script Organization @@ -222,8 +282,8 @@ The main orchestration script calculates and exports these variables for child s | `GRAFANA_BRANCH` | Grafana release branch | `release-1.8` | Auto-calculated | | `GRAFANA_TAG` | Grafana tag | `globalhub-1-8` | Auto-calculated | | `POSTGRES_TAG` | Postgres image tag | `globalhub-1-8` | Auto-calculated | -| `OCP_MIN` | Minimum OCP version number | `417` | Auto-calculated | -| `OCP_MAX` | Maximum OCP version number | `421` | Auto-calculated | +| `OCP_MIN` | Minimum OCP version number | `418` | Auto-calculated | +| `OCP_MAX` | Maximum OCP version number | `422` | Auto-calculated | | `OPENSHIFT_RELEASE_PATH` | Path to openshift/release clone | `/tmp/openshift-release` | Optional | | `WORK_DIR` | Working directory for repos | `/tmp/globalhub-release-repos` | Optional | @@ -284,12 +344,21 @@ When running the complete workflow (`cut-release.sh all`): After running all 6 scripts: -**Pull Requests Created**: 5 PRs -1. Main repo: Version bump PR -2. OpenShift CI: CI configuration PR -3. Bundle: Bundle update PR -4. Catalog: New release configuration PR -5. Catalog: Cleanup PR for old branch +**Pull Requests Created**: 11 PRs + +| # | Repo | Target Branch | Content | +|---|------|--------------|---------| +| 1 | multicluster-global-hub | `main` | New globalhub-1-8 tekton configs, Containerfile/Makefile version bump | +| 2 | multicluster-global-hub | `release-2.16` | Update globalhub-1-7 pull-request pipeline target_branch → release-2.16 | +| 3 | multicluster-global-hub | `release-2.17` | Add globalhub-1-8 tekton files to current release branch | +| 4 | openshift/release | `main` | CI config for release-2.17, presubmit/postsubmit jobs | +| 5 | operator-bundle | `release-1.8` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8, update image tags | +| 6 | operator-bundle | `release-1.7` | Cleanup old GitHub Actions workflows | +| 7 | operator-catalog | `main` | New release-1.8 catalog config, OCP 4.18-4.22 lifecycle | +| 8 | operator-catalog | `release-1.8` | Update pipeline and image mirror set | +| 9 | operator-catalog | `release-1.7` | Cleanup old GitHub Actions workflows | +| 10 | glo-grafana | `release-1.8` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | +| 11 | postgres_exporter | `release-2.17` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | **Branches Created**: 5 branches 1. `multicluster-global-hub`: `release-2.17` @@ -310,23 +379,23 @@ The orchestration script includes error handling: ### Update all repositories (UPDATE mode - creates PRs): ```bash -RELEASE_BRANCH=release-2.17 ./.claude/skills/cut-release/scripts/cut-release.sh all +RELEASE_BRANCH=release-2.17 ./.claude/skills/new-release/scripts/cut-release.sh all ``` ### Create new release branches (CREATE_BRANCHES mode - pushes directly): ```bash -CREATE_BRANCHES=true RELEASE_BRANCH=release-2.18 ./.claude/skills/cut-release/scripts/cut-release.sh all +CREATE_BRANCHES=true RELEASE_BRANCH=release-2.18 ./.claude/skills/new-release/scripts/cut-release.sh all ``` ### Interactive selection: ```bash -RELEASE_BRANCH=release-2.17 ./.claude/skills/cut-release/scripts/cut-release.sh +RELEASE_BRANCH=release-2.17 ./.claude/skills/new-release/scripts/cut-release.sh # Then select: 3,4 (to update only bundle and catalog) ``` ### Update specific repositories: ```bash -RELEASE_BRANCH=release-2.17 ./.claude/skills/cut-release/scripts/cut-release.sh 1,2,3 +RELEASE_BRANCH=release-2.17 ./.claude/skills/new-release/scripts/cut-release.sh 1,2,3 ``` ### Standalone script execution: @@ -349,7 +418,7 @@ The skill provides clear progress indicators: Global Hub Version: v1.8.0 Bundle Branch: release-1.8 Catalog Branch: release-1.8 - Supported OCP: 4.17 - 4.21 + Supported OCP: 4.18 - 4.22 ================================================ Mode: Update all repositories diff --git a/.claude/skills/new-release/scripts/02-openshift-release.sh b/.claude/skills/new-release/scripts/02-openshift-release.sh index ddd7a59f09..8f487d0735 100755 --- a/.claude/skills/new-release/scripts/02-openshift-release.sh +++ b/.claude/skills/new-release/scripts/02-openshift-release.sh @@ -65,10 +65,10 @@ if [[ -d "$OPENSHIFT_RELEASE_PATH" ]]; then git remote add upstream https://github.com/openshift/release.git 2>/dev/null || true # Fetch and update to latest - echo " Updating to latest upstream/master..." - if git fetch upstream master; then - git checkout master 2>/dev/null || git checkout main 2>/dev/null || true - git pull upstream master 2>/dev/null || git pull upstream main 2>/dev/null || true + echo " Updating to latest upstream/main..." + if git fetch upstream main; then + git checkout main 2>/dev/null || true + git pull upstream main 2>/dev/null || true echo " ✅ Updated to latest commit" else echo " ⚠️ Failed to update, continuing with existing state" >&2 @@ -78,12 +78,12 @@ else PARENT_DIR=$(dirname "$OPENSHIFT_RELEASE_PATH") REPO_NAME=$(basename "$OPENSHIFT_RELEASE_PATH") cd "$PARENT_DIR" - git clone --depth=1 --single-branch --branch master --progress "https://github.com/$GITHUB_USER/release.git" "$REPO_NAME" 2>&1 | grep -E "Receiving|Resolving" || true + git clone --depth=1 --single-branch --branch main --progress "https://github.com/$GITHUB_USER/release.git" "$REPO_NAME" 2>&1 | grep -E "Receiving|Resolving" || true cd "$REPO_NAME" echo " Adding upstream remote..." git remote add upstream https://github.com/openshift/release.git - echo " Fetching upstream master..." - git fetch --depth=1 upstream master --progress 2>&1 | grep -E "Receiving|Resolving" || true + echo " Fetching upstream main..." + git fetch --depth=1 upstream main --progress 2>&1 | grep -E "Receiving|Resolving" || true fi # Calculate previous release version (ACM_VERSION - 0.01) @@ -120,7 +120,7 @@ if git show-ref --verify --quiet "refs/heads/$BRANCH_NAME"; then git checkout "$BRANCH_NAME" echo " ✅ Switched to existing branch $BRANCH_NAME" else - git checkout -b "$BRANCH_NAME" upstream/master + git checkout -b "$BRANCH_NAME" upstream/main echo " ✅ Created branch $BRANCH_NAME" fi @@ -364,7 +364,7 @@ PR_HEAD="${GITHUB_USER}:${BRANCH_NAME}" EXISTING_PR=$(gh pr list \ --repo "openshift/release" \ --head "${PR_HEAD}" \ - --base master \ + --base main \ --state all \ --json number,url,state \ --jq '.[0] | select(. != null) | "\(.state)|\(.url)"' 2>/dev/null || echo "") @@ -466,7 +466,7 @@ ACM: ${RELEASE_BRANCH}, Global Hub: release-${GH_VERSION_SHORT}" PR_CREATED=true else # Create new PR - echo " Creating PR to openshift/release:master..." + echo " Creating PR to openshift/release:main..." # Build PR body based on make jobs success if [[ "$MAKE_JOBS_SUCCESS" = true ]]; then @@ -475,7 +475,7 @@ ACM: ${RELEASE_BRANCH}, Global Hub: release-${GH_VERSION_SHORT}" JOBS_NOTE="4. **Auto-generate job configurations**: Using \`make update\` (⚠️ \`make jobs\` failed - may need manual formatting)" fi - PR_CREATE_OUTPUT=$(gh pr create --base master --head "$PR_HEAD" \ + PR_CREATE_OUTPUT=$(gh pr create --base main --head "$PR_HEAD" \ --title "Add ${RELEASE_BRANCH} configuration for multicluster-global-hub" \ --body "This PR adds ${RELEASE_BRANCH} configuration for the multicluster-global-hub project. diff --git a/.claude/skills/new-release/scripts/05-grafana.sh b/.claude/skills/new-release/scripts/05-grafana.sh index e9d5f77b1b..72b6910426 100755 --- a/.claude/skills/new-release/scripts/05-grafana.sh +++ b/.claude/skills/new-release/scripts/05-grafana.sh @@ -31,6 +31,7 @@ if [[ "$OSTYPE" == "darwin"* ]]; then SED_INPLACE=(-i "") else SED_INPLACE=(-i) +fi # Constants for repeated patterns readonly NULL_PR_VALUE='null|null' @@ -43,7 +44,6 @@ readonly PR_STATUS_CREATED='created' readonly PR_STATUS_UPDATED='updated' readonly PR_STATUS_EXISTS='exists' readonly PR_STATUS_FAILED='failed' -fi echo "🚀 Glo-Grafana Release Branch Creation" echo "$SEPARATOR_LINE" @@ -96,59 +96,13 @@ else echo " ⚠️ Fork not found: ${GITHUB_USER}/glo-grafana" >&2 fi -# Fetch all release branches -echo "🔄 Fetching release branches..." -git fetch origin 'refs/heads/release-*:refs/remotes/origin/release-*' --progress 2>&1 | grep -E "Receiving|Resolving|new branch" || true -echo " ✅ Release branches fetched" - -# Find latest grafana release branch -LATEST_GRAFANA_RELEASE=$(git branch -r | grep -E 'origin/release-[0-9]+\.[0-9]+$' | \ - sed 's|.*origin/||' | sed 's|^[* ]*||' | sort -V | tail -1) - -# Check if target branch is the same as latest -if [[ "$LATEST_GRAFANA_RELEASE" = "$GRAFANA_BRANCH" ]]; then - echo "ℹ️ Target grafana branch is the latest: $GRAFANA_BRANCH" - echo "" - echo " https://github.com/$GRAFANA_REPO/tree/$GRAFANA_BRANCH" - echo "" - echo " Will verify and update if needed..." - echo "" -fi - -if [[ -z "$LATEST_GRAFANA_RELEASE" ]]; then - echo "⚠️ No previous grafana release branch found, using main as base" >&2 - BASE_BRANCH="main" -else - echo "Latest grafana release detected: $LATEST_GRAFANA_RELEASE" - - # If target branch is the latest, use second-to-latest as base - # If target branch is not the latest, use latest as base - if [[ "$LATEST_GRAFANA_RELEASE" = "$GRAFANA_BRANCH" ]]; then - # Target is latest - get second-to-latest for base - SECOND_TO_LATEST=$(git branch -r | grep -E 'origin/release-[0-9]+\.[0-9]+$' | \ - sed 's|.*origin/||' | sed 's|^[* ]*||' | sort -V | tail -2 | head -1) - if [[ -n "$SECOND_TO_LATEST" && "$SECOND_TO_LATEST" != "$GRAFANA_BRANCH" ]]; then - BASE_BRANCH="$SECOND_TO_LATEST" - echo "Target is latest release, using previous release as base: $BASE_BRANCH" - else - BASE_BRANCH="main" - echo "No previous release found, using main as base" - fi - else - # Target is not latest - use latest as base - BASE_BRANCH="$LATEST_GRAFANA_RELEASE" - echo "Target is older than latest, using latest as base: $BASE_BRANCH" - fi -fi - -# Extract previous Grafana tag info -if [[ "$BASE_BRANCH" != "main" ]]; then - PREV_GRAFANA_VERSION="${BASE_BRANCH#release-}" - PREV_GRAFANA_TAG="globalhub-${PREV_GRAFANA_VERSION//./-}" - echo "Previous Grafana tag: $PREV_GRAFANA_TAG" -else - PREV_GRAFANA_TAG="" -fi +# Calculate previous grafana tag directly from version formula +# GH_VERSION_SHORT e.g. "1.8" -> prev minor = 7 -> globalhub-1-7 / release-1.7 +GH_MINOR="${GH_VERSION_SHORT#*.}" +PREV_GH_MINOR=$((GH_MINOR - 1)) +PREV_GRAFANA_TAG="globalhub-1-${PREV_GH_MINOR}" +BASE_BRANCH="release-1.${PREV_GH_MINOR}" +echo "Previous Grafana tag: $PREV_GRAFANA_TAG (base: $BASE_BRANCH)" echo "" diff --git a/.claude/skills/new-release/scripts/06-postgres-exporter.sh b/.claude/skills/new-release/scripts/06-postgres-exporter.sh index 0d5cb3de07..bbc8265bba 100755 --- a/.claude/skills/new-release/scripts/06-postgres-exporter.sh +++ b/.claude/skills/new-release/scripts/06-postgres-exporter.sh @@ -96,61 +96,16 @@ else echo " ⚠️ Fork not found: ${GITHUB_USER}/postgres_exporter" >&2 fi -# Fetch all release branches -echo "🔄 Fetching release branches..." -git fetch origin 'refs/heads/release-*:refs/remotes/origin/release-*' --progress 2>&1 | grep -E "Receiving|Resolving|new branch" || true -echo " ✅ Release branches fetched" - -# Find latest postgres release branch -LATEST_POSTGRES_RELEASE=$(git branch -r | grep -E 'origin/release-[0-9]+\.[0-9]+$' | \ - sed 's|.*origin/||' | sed 's|^[* ]*||' | sort -V | tail -1) - -# Check if target branch is the same as latest -if [[ "$LATEST_POSTGRES_RELEASE" = "$RELEASE_BRANCH" ]]; then - echo "ℹ️ Target postgres branch is the latest: $RELEASE_BRANCH" - echo "" - echo " https://github.com/$POSTGRES_REPO/tree/$RELEASE_BRANCH" - echo "" - echo " Will verify and update if needed..." - echo "" -fi - -if [[ -z "$LATEST_POSTGRES_RELEASE" ]]; then - echo "⚠️ No previous postgres release branch found, using main as base" >&2 - BASE_BRANCH="main" -else - echo "Latest postgres release detected: $LATEST_POSTGRES_RELEASE" - - # If target branch is the latest, use second-to-latest as base - # If target branch is not the latest, use latest as base - if [[ "$LATEST_POSTGRES_RELEASE" = "$RELEASE_BRANCH" ]]; then - # Target is latest - get second-to-latest for base - SECOND_TO_LATEST=$(git branch -r | grep -E 'origin/release-[0-9]+\.[0-9]+$' | \ - sed 's|.*origin/||' | sed 's|^[* ]*||' | sort -V | tail -2 | head -1) - if [[ -n "$SECOND_TO_LATEST" && "$SECOND_TO_LATEST" != "$RELEASE_BRANCH" ]]; then - BASE_BRANCH="$SECOND_TO_LATEST" - echo "Target is latest release, using previous release as base: $BASE_BRANCH" - else - BASE_BRANCH="main" - echo "No previous release found, using main as base" - fi - else - # Target is not latest - use latest as base - BASE_BRANCH="$LATEST_POSTGRES_RELEASE" - echo "Target is older than latest, using latest as base: $BASE_BRANCH" - fi -fi - -# Extract previous Postgres tag info -if [[ "$BASE_BRANCH" != "main" ]]; then - PREV_VERSION="${BASE_BRANCH#release-}" - PREV_MINOR=$(echo "$PREV_VERSION" | cut -d. -f2) - PREV_GH_MINOR=$((PREV_MINOR - 9)) - PREV_POSTGRES_TAG="globalhub-1-${PREV_GH_MINOR}" - echo "Previous Postgres tag: $PREV_POSTGRES_TAG" -else - PREV_POSTGRES_TAG="" -fi +# Calculate previous postgres tag directly from version formula +# RELEASE_BRANCH e.g. "release-2.17" -> prev ACM minor = 16 -> base = release-2.16 +# GH_VERSION_SHORT e.g. "1.8" -> prev GH minor = 7 -> globalhub-1-7 +ACM_MINOR="${RELEASE_BRANCH##*.}" +PREV_ACM_MINOR=$((ACM_MINOR - 1)) +BASE_BRANCH="release-2.${PREV_ACM_MINOR}" +GH_MINOR="${GH_VERSION_SHORT#*.}" +PREV_GH_MINOR=$((GH_MINOR - 1)) +PREV_POSTGRES_TAG="globalhub-1-${PREV_GH_MINOR}" +echo "Previous Postgres tag: $PREV_POSTGRES_TAG (base: $BASE_BRANCH)" echo "" From 14453bd75e447cee8ff59417e754562079a1d376 Mon Sep 17 00:00:00 2001 From: myan Date: Thu, 12 Mar 2026 00:50:44 -0400 Subject: [PATCH 2/8] docs: simplify Total Output PR table, remove redundant skip condition column Signed-off-by: myan --- .claude/skills/new-release/SKILL.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.claude/skills/new-release/SKILL.md b/.claude/skills/new-release/SKILL.md index 0cc7620573..d8472cc6f0 100644 --- a/.claude/skills/new-release/SKILL.md +++ b/.claude/skills/new-release/SKILL.md @@ -344,7 +344,9 @@ When running the complete workflow (`cut-release.sh all`): After running all 6 scripts: -**Pull Requests Created**: 11 PRs +**Pull Requests Expected**: up to 11 PRs + +> Each PR is only created if changes are needed. If the target branch is already up-to-date or an open PR already exists, the script will skip or reuse it. | # | Repo | Target Branch | Content | |---|------|--------------|---------| From 368e0871e5ac184013040e274f6b5cb72e4ca9a8 Mon Sep 17 00:00:00 2001 From: myan Date: Thu, 12 Mar 2026 04:20:49 -0400 Subject: [PATCH 3/8] docs: remove unnecessary PR to current release branch, update counts to 10 Signed-off-by: myan --- .claude/skills/new-release/SKILL.md | 35 +++++++++++++---------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/.claude/skills/new-release/SKILL.md b/.claude/skills/new-release/SKILL.md index d8472cc6f0..d2306d6acc 100644 --- a/.claude/skills/new-release/SKILL.md +++ b/.claude/skills/new-release/SKILL.md @@ -64,26 +64,24 @@ The skill manages releases across 6 repositories, each with its own dedicated sc **Repository**: [stolostron/multicluster-global-hub](https://github.com/stolostron/multicluster-global-hub) -**What it does** (4-part workflow): +**What it does** (3-part workflow): 1. **Update main branch**: Creates new `.tekton/` configuration files for new version (e.g., globalhub-1-8) with `target_branch="main"`, updates `Containerfile.*` version labels -2. **Create release branch**: Creates ACM release branch (e.g., release-2.17) from updated main -3. **Create PR to main**: Creates PR to upstream main with new release configurations -4. **Update previous release**: Updates previous release branch's `.tekton/` files to set `target_branch` to the previous release branch (e.g., globalhub-1-7 files updated to `target_branch="release-2.16"`) -5. **Update current release**: Adds new `.tekton/` files (globalhub-1-8) to the current release branch (release-2.17) +2. **Create PR to main**: Creates PR to upstream main with new release configurations +3. **Update previous release**: Updates previous release branch's `.tekton/` files to set `target_branch` to the previous release branch (e.g., globalhub-1-7 files updated to `target_branch="release-2.16"`) **Key behavior**: - New `.tekton/` files (e.g., globalhub-1-8) created by **copying** old files (globalhub-1-7), not renaming - Old `.tekton/` files (globalhub-1-7) remain on main with `target_branch="main"` - Previous release branch gets updated so its files point to itself (not main) - Ensures continuous file naming progression: globalhub-1-6 → globalhub-1-7 → globalhub-1-8 +- The new tekton files on `main` will be automatically synced to the current release branch (`release-2.17`) after the PR is merged — **no separate PR needed for the current release branch** -**Expected PRs**: 3 +**Expected PRs**: 2 | PR | Target Branch | Content | Verification | |----|--------------|---------|--------------| | PR to main | `main` | New `.tekton/globalhub-1-8-*.yaml` files; old globalhub-1-7 files removed; Containerfile version updated; Makefile VERSION/CHANNELS updated | Check `.tekton/` has globalhub-1-8 files with `target_branch=main` (pull-request) and `target_branch=release-2.17` (push) | | PR to prev release | `release-2.16` | globalhub-1-7 `pull-request.yaml` target_branch changed from `main` → `release-2.16` | Verify `*pull-request.yaml` has `target_branch=release-2.16` | -| PR to current release | `release-2.17` | New globalhub-1-8 `.tekton/` files added to release branch | Verify `*push.yaml` has `target_branch=release-2.17` | --- @@ -195,13 +193,13 @@ The skill manages releases across 6 repositories, each with its own dedicated sc | Repo | PRs | Branches | |------|-----|---------| -| multicluster-global-hub | 3 (main, prev-release, curr-release) | release-2.17 | +| multicluster-global-hub | 2 (main, prev-release) | release-2.17 | | openshift/release | 1 (main) | — | | operator-bundle | 2 (release-1.8, cleanup release-1.7) | release-1.8 | | operator-catalog | 3 (main, release-1.8, cleanup release-1.7) | release-1.8 | | glo-grafana | 1 (release-1.8) | release-1.8 | | postgres_exporter | 1 (release-2.17) | release-2.17 | -| **Total** | **11 PRs** | **5 branches** | +| **Total** | **10 PRs** | **5 branches** | ## Script Organization @@ -344,7 +342,7 @@ When running the complete workflow (`cut-release.sh all`): After running all 6 scripts: -**Pull Requests Expected**: up to 11 PRs +**Pull Requests Expected**: up to 10 PRs > Each PR is only created if changes are needed. If the target branch is already up-to-date or an open PR already exists, the script will skip or reuse it. @@ -352,15 +350,14 @@ After running all 6 scripts: |---|------|--------------|---------| | 1 | multicluster-global-hub | `main` | New globalhub-1-8 tekton configs, Containerfile/Makefile version bump | | 2 | multicluster-global-hub | `release-2.16` | Update globalhub-1-7 pull-request pipeline target_branch → release-2.16 | -| 3 | multicluster-global-hub | `release-2.17` | Add globalhub-1-8 tekton files to current release branch | -| 4 | openshift/release | `main` | CI config for release-2.17, presubmit/postsubmit jobs | -| 5 | operator-bundle | `release-1.8` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8, update image tags | -| 6 | operator-bundle | `release-1.7` | Cleanup old GitHub Actions workflows | -| 7 | operator-catalog | `main` | New release-1.8 catalog config, OCP 4.18-4.22 lifecycle | -| 8 | operator-catalog | `release-1.8` | Update pipeline and image mirror set | -| 9 | operator-catalog | `release-1.7` | Cleanup old GitHub Actions workflows | -| 10 | glo-grafana | `release-1.8` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | -| 11 | postgres_exporter | `release-2.17` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | +| 3 | openshift/release | `main` | CI config for release-2.17, presubmit/postsubmit jobs | +| 4 | operator-bundle | `release-1.8` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8, update image tags | +| 5 | operator-bundle | `release-1.7` | Cleanup old GitHub Actions workflows | +| 6 | operator-catalog | `main` | New release-1.8 catalog config, OCP 4.18-4.22 lifecycle | +| 7 | operator-catalog | `release-1.8` | Update pipeline and image mirror set | +| 8 | operator-catalog | `release-1.7` | Cleanup old GitHub Actions workflows | +| 9 | glo-grafana | `release-1.8` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | +| 10 | postgres_exporter | `release-2.17` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | **Branches Created**: 5 branches 1. `multicluster-global-hub`: `release-2.17` From b47e4a4e701920dc4dc03ffad4f10ff2e31262b3 Mon Sep 17 00:00:00 2001 From: myan Date: Thu, 12 Mar 2026 04:29:05 -0400 Subject: [PATCH 4/8] feat: update bundle main branch with new bundle content and pipelines Add Step 8 to 03-bundle.sh to update the bundle repo's main branch with new bundle content copied from multicluster-global-hub main, renamed tekton pipelines, and updated image references. Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: myan --- .../skills/new-release/scripts/03-bundle.sh | 119 +++++++++++++++++- 1 file changed, 118 insertions(+), 1 deletion(-) diff --git a/.claude/skills/new-release/scripts/03-bundle.sh b/.claude/skills/new-release/scripts/03-bundle.sh index 56a01f328d..93b5a0e346 100755 --- a/.claude/skills/new-release/scripts/03-bundle.sh +++ b/.claude/skills/new-release/scripts/03-bundle.sh @@ -660,7 +660,124 @@ fi fi fi -# Step 8: Create cleanup PR to remove GitHub Actions from old release +# Step 8: Update main branch with new bundle content and renamed tekton pipelines +echo "" +echo "📍 Step 8: Updating main branch with new bundle and tekton pipelines..." + +MAIN_PR_CREATED=false +MAIN_PR_URL="" + +# Reset to main branch +git reset --hard HEAD 2>/dev/null || true +git clean -fd 2>/dev/null || true +git fetch origin main 2>/dev/null || true +git checkout -B main "origin/main" + +# Copy latest bundle content from multicluster-global-hub main +echo " Copying bundle content from $BUNDLE_SOURCE_DESCRIPTION to main..." +rm -rf bundle/manifests bundle/metadata bundle/tests 2>/dev/null || true +mkdir -p bundle +[[ -d "$SOURCE_BUNDLE_DIR/manifests" ]] && cp -r "$SOURCE_BUNDLE_DIR/manifests" bundle/ && echo " ✅ Copied manifests/" +[[ -d "$SOURCE_BUNDLE_DIR/metadata" ]] && cp -r "$SOURCE_BUNDLE_DIR/metadata" bundle/ && echo " ✅ Copied metadata/" +[[ -d "$SOURCE_BUNDLE_DIR/tests" ]] && cp -r "$SOURCE_BUNDLE_DIR/tests" bundle/ && echo " ✅ Copied tests/" +git add bundle/ 2>/dev/null || true + +# Update imageDigestMirrorSet on main +if [[ -f "$IDMS_FILE" && -n "$PREV_BUNDLE_TAG" ]]; then + sed "${SED_INPLACE[@]}" "s/multicluster-global-hub-\([a-z-]*\)-${PREV_BUNDLE_TAG}/multicluster-global-hub-\1-${BUNDLE_TAG}/g" "$IDMS_FILE" + echo " ✅ Updated $IDMS_FILE on main" +fi + +# Rename tekton pipelines on main: globalhub-1-7 → globalhub-1-8 (target_branch=main) +if [[ -n "$PREV_BUNDLE_TAG" ]]; then + for pipeline_type in pull-request push; do + OLD_PIPELINE=".tekton/multicluster-global-hub-operator-bundle-${PREV_BUNDLE_TAG}-${pipeline_type}.yaml" + NEW_PIPELINE=".tekton/multicluster-global-hub-operator-bundle-${BUNDLE_TAG}-${pipeline_type}.yaml" + if [[ -f "$OLD_PIPELINE" && ! -f "$NEW_PIPELINE" ]]; then + git mv "$OLD_PIPELINE" "$NEW_PIPELINE" + sed "${SED_INPLACE[@]}" "s/${PREV_BUNDLE_TAG}/${BUNDLE_TAG}/g" "$NEW_PIPELINE" + # On main, pull-request pipeline target_branch stays main; push pipeline also targets main + sed "${SED_INPLACE[@]}" "s/target_branch == \"${BUNDLE_BRANCH}\"/target_branch == \"main\"/g" "$NEW_PIPELINE" + echo " ✅ Renamed and updated $NEW_PIPELINE (target_branch=main)" + elif [[ -f "$NEW_PIPELINE" ]]; then + echo " ℹ️ Pipeline already exists: $NEW_PIPELINE" + fi + done +fi + +# Update konflux-patch.sh on main +if [[ -f "$KONFLUX_SCRIPT" && -n "$PREV_BUNDLE_TAG" ]]; then + sed "${SED_INPLACE[@]}" "s/\([a-z-]*\)-${PREV_BUNDLE_TAG}/\1-${BUNDLE_TAG}/g" "$KONFLUX_SCRIPT" + echo " ✅ Updated $KONFLUX_SCRIPT on main" +fi + +git add -A + +# Check for actual changes vs origin/main +MAIN_DIFF=$(git diff --cached "origin/main" 2>/dev/null || echo "") +NON_CREATEDAT=$(echo "$MAIN_DIFF" | grep -E '^[-+]' | grep -v 'createdAt:' | grep -v '^---' | grep -v '^\+\+\+' || echo "") + +if [[ -z "$NON_CREATEDAT" ]]; then + echo " ℹ️ No substantive changes on main (only timestamps or already up-to-date)" + git reset --hard "origin/main" 2>/dev/null || true +else + git commit --signoff -m "Update bundle main branch for ${BUNDLE_TAG} (Global Hub ${GH_VERSION}) + +- Copy latest operator bundle from multicluster-global-hub main (manifests, metadata, tests) +- Update imageDigestMirrorSet to use ${BUNDLE_TAG} +- Rename tekton pipelines: ${PREV_BUNDLE_TAG} → ${BUNDLE_TAG} (target_branch=main) +- Update konflux-patch.sh image references to ${BUNDLE_TAG} + +Corresponds to ACM ${RELEASE_BRANCH} / Global Hub ${GH_VERSION}" + + echo " ✅ Changes committed on main" + + # Push to fork and create PR to main + MAIN_PR_BRANCH="update-bundle-main-${BUNDLE_TAG}" + git checkout -b "$MAIN_PR_BRANCH" + + if [[ "$FORK_EXISTS" = true ]]; then + if git push -f fork "$MAIN_PR_BRANCH" 2>&1; then + MAIN_PR_OUTPUT=$(gh pr create --base main --head "${GITHUB_USER}:${MAIN_PR_BRANCH}" \ + --title "Update bundle main branch for ${BUNDLE_TAG}" \ + --body "## Summary + +Update bundle \`main\` branch to align with multicluster-global-hub main branch changes. + +## Changes + +- Copy latest operator bundle from multicluster-global-hub main (manifests, metadata, tests) +- Update imageDigestMirrorSet to use \`${BUNDLE_TAG}\` +- Rename tekton pipelines: \`${PREV_BUNDLE_TAG}\` → \`${BUNDLE_TAG}\` (target_branch=main) +- Update konflux-patch.sh image references to \`${BUNDLE_TAG}\` + +## Version Mapping + +- **ACM**: ${RELEASE_BRANCH} +- **Global Hub**: ${GH_VERSION} +- **Bundle tag**: ${BUNDLE_TAG}" \ + --repo "$BUNDLE_REPO" 2>&1) || true + + if [[ "$MAIN_PR_OUTPUT" =~ ^https:// ]]; then + MAIN_PR_URL="$MAIN_PR_OUTPUT" + echo " ✅ PR created to main: $MAIN_PR_URL" + MAIN_PR_CREATED=true + elif [[ "$MAIN_PR_OUTPUT" =~ (https://github.com/[^[:space:]]+) ]]; then + MAIN_PR_URL="${BASH_REMATCH[1]}" + echo " ✅ PR created to main: $MAIN_PR_URL" + MAIN_PR_CREATED=true + else + echo " ⚠️ Failed to create PR to main: $MAIN_PR_OUTPUT" >&2 + fi + else + echo " ⚠️ Failed to push main PR branch to fork" >&2 + fi + else + echo " ⚠️ Fork not found, cannot create PR to main" >&2 + fi +fi + +# Step 9: Create cleanup PR to remove GitHub Actions from old release echo "" echo "📍 Step 8: Creating cleanup PR for old release..." From 105f79bb05345e39d76ab3c93997f3915e799639 Mon Sep 17 00:00:00 2001 From: myan Date: Thu, 12 Mar 2026 04:30:20 -0400 Subject: [PATCH 5/8] docs: update SKILL.md for bundle main branch PR (11 total PRs) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add bundle main PR to Repository 3 expected PRs (now 3 PRs) - Update Total Expected Output Summary: operator-bundle 2→3, total 10→11 - Update Total Output table: add PR #5 for bundle main branch sync Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: myan --- .claude/skills/new-release/SKILL.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.claude/skills/new-release/SKILL.md b/.claude/skills/new-release/SKILL.md index d2306d6acc..24d894d43a 100644 --- a/.claude/skills/new-release/SKILL.md +++ b/.claude/skills/new-release/SKILL.md @@ -114,13 +114,15 @@ The skill manages releases across 6 repositories, each with its own dedicated sc - Renames tekton pipelines: globalhub-1-7 → globalhub-1-8 (pull-request and push) - Updates bundle image labels and `konflux-patch.sh` image references - Creates PR to the release branch +- Updates `main` branch with latest bundle content from multicluster-global-hub main (manifests, metadata, tests) and renamed tekton pipelines - Creates cleanup PR to remove old GitHub Actions from previous release branch -**Expected PRs**: 2 +**Expected PRs**: 3 | PR | Target Branch | Content | Verification | |----|--------------|---------|--------------| | PR to release branch | `release-1.8` | tekton pipelines renamed globalhub-1-7 → globalhub-1-8; image tags updated to globalhub-1-8 | Check `.tekton/` has `*globalhub-1-8*.yaml` files | +| PR to main | `main` | Bundle content synced from MGH main (manifests, metadata, tests); tekton pipelines renamed globalhub-1-7 → globalhub-1-8 (target_branch=main) | Check `.tekton/` has `*globalhub-1-8*.yaml` with `target_branch=main`; bundle/ matches MGH | | Cleanup PR | `release-1.7` | Remove `.github/workflows/` GitHub Actions from old release branch | Check old branch no longer has Actions workflows | --- @@ -195,11 +197,11 @@ The skill manages releases across 6 repositories, each with its own dedicated sc |------|-----|---------| | multicluster-global-hub | 2 (main, prev-release) | release-2.17 | | openshift/release | 1 (main) | — | -| operator-bundle | 2 (release-1.8, cleanup release-1.7) | release-1.8 | +| operator-bundle | 3 (release-1.8, main, cleanup release-1.7) | release-1.8 | | operator-catalog | 3 (main, release-1.8, cleanup release-1.7) | release-1.8 | | glo-grafana | 1 (release-1.8) | release-1.8 | | postgres_exporter | 1 (release-2.17) | release-2.17 | -| **Total** | **10 PRs** | **5 branches** | +| **Total** | **11 PRs** | **5 branches** | ## Script Organization @@ -342,7 +344,7 @@ When running the complete workflow (`cut-release.sh all`): After running all 6 scripts: -**Pull Requests Expected**: up to 10 PRs +**Pull Requests Expected**: up to 11 PRs > Each PR is only created if changes are needed. If the target branch is already up-to-date or an open PR already exists, the script will skip or reuse it. @@ -352,12 +354,13 @@ After running all 6 scripts: | 2 | multicluster-global-hub | `release-2.16` | Update globalhub-1-7 pull-request pipeline target_branch → release-2.16 | | 3 | openshift/release | `main` | CI config for release-2.17, presubmit/postsubmit jobs | | 4 | operator-bundle | `release-1.8` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8, update image tags | -| 5 | operator-bundle | `release-1.7` | Cleanup old GitHub Actions workflows | -| 6 | operator-catalog | `main` | New release-1.8 catalog config, OCP 4.18-4.22 lifecycle | -| 7 | operator-catalog | `release-1.8` | Update pipeline and image mirror set | -| 8 | operator-catalog | `release-1.7` | Cleanup old GitHub Actions workflows | -| 9 | glo-grafana | `release-1.8` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | -| 10 | postgres_exporter | `release-2.17` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | +| 5 | operator-bundle | `main` | Sync bundle content from MGH main; rename tekton pipelines globalhub-1-7 → globalhub-1-8 (target_branch=main) | +| 6 | operator-bundle | `release-1.7` | Cleanup old GitHub Actions workflows | +| 7 | operator-catalog | `main` | New release-1.8 catalog config, OCP 4.18-4.22 lifecycle | +| 8 | operator-catalog | `release-1.8` | Update pipeline and image mirror set | +| 9 | operator-catalog | `release-1.7` | Cleanup old GitHub Actions workflows | +| 10 | glo-grafana | `release-1.8` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | +| 11 | postgres_exporter | `release-2.17` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | **Branches Created**: 5 branches 1. `multicluster-global-hub`: `release-2.17` From 2955b4da9a6fde1b8b6ac8083d115f01907e57da Mon Sep 17 00:00:00 2001 From: myan Date: Thu, 12 Mar 2026 04:35:29 -0400 Subject: [PATCH 6/8] chore: remove cleanup PRs and bundle main PR from release scripts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 03-bundle.sh: remove cleanup PR step (GitHub Actions removal from old release branch) and Step 8 (bundle main branch update) - 04-catalog.sh: remove cleanup PR step (GitHub Actions removal from old release branch) - SKILL.md: update expected PR counts (bundle 3→1, catalog 3→2, total 11→8) and remove cleanup/main entries from tables Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: myan --- .claude/skills/new-release/SKILL.md | 29 +- .../skills/new-release/scripts/03-bundle.sh | 254 +----------------- .../skills/new-release/scripts/04-catalog.sh | 180 +------------ 3 files changed, 14 insertions(+), 449 deletions(-) diff --git a/.claude/skills/new-release/SKILL.md b/.claude/skills/new-release/SKILL.md index 24d894d43a..3a50453f99 100644 --- a/.claude/skills/new-release/SKILL.md +++ b/.claude/skills/new-release/SKILL.md @@ -114,16 +114,12 @@ The skill manages releases across 6 repositories, each with its own dedicated sc - Renames tekton pipelines: globalhub-1-7 → globalhub-1-8 (pull-request and push) - Updates bundle image labels and `konflux-patch.sh` image references - Creates PR to the release branch -- Updates `main` branch with latest bundle content from multicluster-global-hub main (manifests, metadata, tests) and renamed tekton pipelines -- Creates cleanup PR to remove old GitHub Actions from previous release branch -**Expected PRs**: 3 +**Expected PRs**: 1 | PR | Target Branch | Content | Verification | |----|--------------|---------|--------------| | PR to release branch | `release-1.8` | tekton pipelines renamed globalhub-1-7 → globalhub-1-8; image tags updated to globalhub-1-8 | Check `.tekton/` has `*globalhub-1-8*.yaml` files | -| PR to main | `main` | Bundle content synced from MGH main (manifests, metadata, tests); tekton pipelines renamed globalhub-1-7 → globalhub-1-8 (target_branch=main) | Check `.tekton/` has `*globalhub-1-8*.yaml` with `target_branch=main`; bundle/ matches MGH | -| Cleanup PR | `release-1.7` | Remove `.github/workflows/` GitHub Actions from old release branch | Check old branch no longer has Actions workflows | --- @@ -141,17 +137,15 @@ The skill manages releases across 6 repositories, each with its own dedicated sc - Updates GitHub Actions workflow for new release branch - Creates PR to main with new release configuration - Creates PR to catalog release branch with pipeline updates -- Creates cleanup PR to remove GitHub Actions from old release branch **OCP Version Formula**: OCP_MIN = 4.(10 + GH_MINOR), OCP_MAX = OCP_MIN + 4 -**Expected PRs**: 3 +**Expected PRs**: 2 | PR | Target Branch | Content | Verification | |----|--------------|---------|--------------| | PR to main | `main` | New release-1.8 catalog config; OCP version lifecycle managed | Check README lists OCP 4.18-4.22; new OCP pipeline added | | PR to catalog branch | `release-1.8` | pipeline updates, image mirror set updated | Check `images-mirror-set.yaml` has globalhub-1-8 tags | -| Cleanup PR | `release-1.7` | Remove `.github/workflows/` from old release branch | Check old branch no longer has Actions workflows | --- @@ -197,11 +191,11 @@ The skill manages releases across 6 repositories, each with its own dedicated sc |------|-----|---------| | multicluster-global-hub | 2 (main, prev-release) | release-2.17 | | openshift/release | 1 (main) | — | -| operator-bundle | 3 (release-1.8, main, cleanup release-1.7) | release-1.8 | -| operator-catalog | 3 (main, release-1.8, cleanup release-1.7) | release-1.8 | +| operator-bundle | 1 (release-1.8) | release-1.8 | +| operator-catalog | 2 (main, release-1.8) | release-1.8 | | glo-grafana | 1 (release-1.8) | release-1.8 | | postgres_exporter | 1 (release-2.17) | release-2.17 | -| **Total** | **11 PRs** | **5 branches** | +| **Total** | **8 PRs** | **5 branches** | ## Script Organization @@ -344,7 +338,7 @@ When running the complete workflow (`cut-release.sh all`): After running all 6 scripts: -**Pull Requests Expected**: up to 11 PRs +**Pull Requests Expected**: up to 8 PRs > Each PR is only created if changes are needed. If the target branch is already up-to-date or an open PR already exists, the script will skip or reuse it. @@ -354,13 +348,10 @@ After running all 6 scripts: | 2 | multicluster-global-hub | `release-2.16` | Update globalhub-1-7 pull-request pipeline target_branch → release-2.16 | | 3 | openshift/release | `main` | CI config for release-2.17, presubmit/postsubmit jobs | | 4 | operator-bundle | `release-1.8` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8, update image tags | -| 5 | operator-bundle | `main` | Sync bundle content from MGH main; rename tekton pipelines globalhub-1-7 → globalhub-1-8 (target_branch=main) | -| 6 | operator-bundle | `release-1.7` | Cleanup old GitHub Actions workflows | -| 7 | operator-catalog | `main` | New release-1.8 catalog config, OCP 4.18-4.22 lifecycle | -| 8 | operator-catalog | `release-1.8` | Update pipeline and image mirror set | -| 9 | operator-catalog | `release-1.7` | Cleanup old GitHub Actions workflows | -| 10 | glo-grafana | `release-1.8` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | -| 11 | postgres_exporter | `release-2.17` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | +| 5 | operator-catalog | `main` | New release-1.8 catalog config, OCP 4.18-4.22 lifecycle | +| 6 | operator-catalog | `release-1.8` | Update pipeline and image mirror set | +| 7 | glo-grafana | `release-1.8` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | +| 8 | postgres_exporter | `release-2.17` | Rename tekton pipelines globalhub-1-7 → globalhub-1-8 | **Branches Created**: 5 branches 1. `multicluster-global-hub`: `release-2.17` diff --git a/.claude/skills/new-release/scripts/03-bundle.sh b/.claude/skills/new-release/scripts/03-bundle.sh index 93b5a0e346..7664db705a 100755 --- a/.claude/skills/new-release/scripts/03-bundle.sh +++ b/.claude/skills/new-release/scripts/03-bundle.sh @@ -91,7 +91,6 @@ if git ls-remote "$FORK_REPO" HEAD >/dev/null 2>&1; then echo " ✅ Fork detected: ${GITHUB_USER}/multicluster-global-hub-operator-bundle" else echo " ⚠️ Fork not found: ${GITHUB_USER}/multicluster-global-hub-operator-bundle" >&2 - echo " Note: Cleanup PR will require manual creation if fork doesn't exist" fi # Fetch all release branches @@ -214,21 +213,6 @@ else PREV_BUNDLE_TAG="" fi -# For cleanup PR, we need to find the previous release -# If BUNDLE_BRANCH is the latest, find second-to-latest for cleanup -if [[ "$LATEST_BUNDLE_RELEASE" = "$BUNDLE_BRANCH" ]]; then - CLEANUP_TARGET_BRANCH=$(git branch -r | grep -E 'origin/release-[0-9]+\.[0-9]+$' | \ - sed 's|.*origin/||' | sed 's|^[* ]*||' | sort -V | tail -2 | head -1) - if [[ -n "$CLEANUP_TARGET_BRANCH" && "$CLEANUP_TARGET_BRANCH" != "$BUNDLE_BRANCH" ]]; then - echo "Cleanup target: $CLEANUP_TARGET_BRANCH (previous release)" - else - CLEANUP_TARGET_BRANCH="" - fi -else - # When creating new bundle, BASE_BRANCH is the cleanup target - CLEANUP_TARGET_BRANCH="$BASE_BRANCH" -fi - # Initialize tracking variables BRANCH_EXISTS_ON_ORIGIN=false CHANGES_COMMITTED=false @@ -660,228 +644,6 @@ fi fi fi -# Step 8: Update main branch with new bundle content and renamed tekton pipelines -echo "" -echo "📍 Step 8: Updating main branch with new bundle and tekton pipelines..." - -MAIN_PR_CREATED=false -MAIN_PR_URL="" - -# Reset to main branch -git reset --hard HEAD 2>/dev/null || true -git clean -fd 2>/dev/null || true -git fetch origin main 2>/dev/null || true -git checkout -B main "origin/main" - -# Copy latest bundle content from multicluster-global-hub main -echo " Copying bundle content from $BUNDLE_SOURCE_DESCRIPTION to main..." -rm -rf bundle/manifests bundle/metadata bundle/tests 2>/dev/null || true -mkdir -p bundle -[[ -d "$SOURCE_BUNDLE_DIR/manifests" ]] && cp -r "$SOURCE_BUNDLE_DIR/manifests" bundle/ && echo " ✅ Copied manifests/" -[[ -d "$SOURCE_BUNDLE_DIR/metadata" ]] && cp -r "$SOURCE_BUNDLE_DIR/metadata" bundle/ && echo " ✅ Copied metadata/" -[[ -d "$SOURCE_BUNDLE_DIR/tests" ]] && cp -r "$SOURCE_BUNDLE_DIR/tests" bundle/ && echo " ✅ Copied tests/" -git add bundle/ 2>/dev/null || true - -# Update imageDigestMirrorSet on main -if [[ -f "$IDMS_FILE" && -n "$PREV_BUNDLE_TAG" ]]; then - sed "${SED_INPLACE[@]}" "s/multicluster-global-hub-\([a-z-]*\)-${PREV_BUNDLE_TAG}/multicluster-global-hub-\1-${BUNDLE_TAG}/g" "$IDMS_FILE" - echo " ✅ Updated $IDMS_FILE on main" -fi - -# Rename tekton pipelines on main: globalhub-1-7 → globalhub-1-8 (target_branch=main) -if [[ -n "$PREV_BUNDLE_TAG" ]]; then - for pipeline_type in pull-request push; do - OLD_PIPELINE=".tekton/multicluster-global-hub-operator-bundle-${PREV_BUNDLE_TAG}-${pipeline_type}.yaml" - NEW_PIPELINE=".tekton/multicluster-global-hub-operator-bundle-${BUNDLE_TAG}-${pipeline_type}.yaml" - if [[ -f "$OLD_PIPELINE" && ! -f "$NEW_PIPELINE" ]]; then - git mv "$OLD_PIPELINE" "$NEW_PIPELINE" - sed "${SED_INPLACE[@]}" "s/${PREV_BUNDLE_TAG}/${BUNDLE_TAG}/g" "$NEW_PIPELINE" - # On main, pull-request pipeline target_branch stays main; push pipeline also targets main - sed "${SED_INPLACE[@]}" "s/target_branch == \"${BUNDLE_BRANCH}\"/target_branch == \"main\"/g" "$NEW_PIPELINE" - echo " ✅ Renamed and updated $NEW_PIPELINE (target_branch=main)" - elif [[ -f "$NEW_PIPELINE" ]]; then - echo " ℹ️ Pipeline already exists: $NEW_PIPELINE" - fi - done -fi - -# Update konflux-patch.sh on main -if [[ -f "$KONFLUX_SCRIPT" && -n "$PREV_BUNDLE_TAG" ]]; then - sed "${SED_INPLACE[@]}" "s/\([a-z-]*\)-${PREV_BUNDLE_TAG}/\1-${BUNDLE_TAG}/g" "$KONFLUX_SCRIPT" - echo " ✅ Updated $KONFLUX_SCRIPT on main" -fi - -git add -A - -# Check for actual changes vs origin/main -MAIN_DIFF=$(git diff --cached "origin/main" 2>/dev/null || echo "") -NON_CREATEDAT=$(echo "$MAIN_DIFF" | grep -E '^[-+]' | grep -v 'createdAt:' | grep -v '^---' | grep -v '^\+\+\+' || echo "") - -if [[ -z "$NON_CREATEDAT" ]]; then - echo " ℹ️ No substantive changes on main (only timestamps or already up-to-date)" - git reset --hard "origin/main" 2>/dev/null || true -else - git commit --signoff -m "Update bundle main branch for ${BUNDLE_TAG} (Global Hub ${GH_VERSION}) - -- Copy latest operator bundle from multicluster-global-hub main (manifests, metadata, tests) -- Update imageDigestMirrorSet to use ${BUNDLE_TAG} -- Rename tekton pipelines: ${PREV_BUNDLE_TAG} → ${BUNDLE_TAG} (target_branch=main) -- Update konflux-patch.sh image references to ${BUNDLE_TAG} - -Corresponds to ACM ${RELEASE_BRANCH} / Global Hub ${GH_VERSION}" - - echo " ✅ Changes committed on main" - - # Push to fork and create PR to main - MAIN_PR_BRANCH="update-bundle-main-${BUNDLE_TAG}" - git checkout -b "$MAIN_PR_BRANCH" - - if [[ "$FORK_EXISTS" = true ]]; then - if git push -f fork "$MAIN_PR_BRANCH" 2>&1; then - MAIN_PR_OUTPUT=$(gh pr create --base main --head "${GITHUB_USER}:${MAIN_PR_BRANCH}" \ - --title "Update bundle main branch for ${BUNDLE_TAG}" \ - --body "## Summary - -Update bundle \`main\` branch to align with multicluster-global-hub main branch changes. - -## Changes - -- Copy latest operator bundle from multicluster-global-hub main (manifests, metadata, tests) -- Update imageDigestMirrorSet to use \`${BUNDLE_TAG}\` -- Rename tekton pipelines: \`${PREV_BUNDLE_TAG}\` → \`${BUNDLE_TAG}\` (target_branch=main) -- Update konflux-patch.sh image references to \`${BUNDLE_TAG}\` - -## Version Mapping - -- **ACM**: ${RELEASE_BRANCH} -- **Global Hub**: ${GH_VERSION} -- **Bundle tag**: ${BUNDLE_TAG}" \ - --repo "$BUNDLE_REPO" 2>&1) || true - - if [[ "$MAIN_PR_OUTPUT" =~ ^https:// ]]; then - MAIN_PR_URL="$MAIN_PR_OUTPUT" - echo " ✅ PR created to main: $MAIN_PR_URL" - MAIN_PR_CREATED=true - elif [[ "$MAIN_PR_OUTPUT" =~ (https://github.com/[^[:space:]]+) ]]; then - MAIN_PR_URL="${BASH_REMATCH[1]}" - echo " ✅ PR created to main: $MAIN_PR_URL" - MAIN_PR_CREATED=true - else - echo " ⚠️ Failed to create PR to main: $MAIN_PR_OUTPUT" >&2 - fi - else - echo " ⚠️ Failed to push main PR branch to fork" >&2 - fi - else - echo " ⚠️ Fork not found, cannot create PR to main" >&2 - fi -fi - -# Step 9: Create cleanup PR to remove GitHub Actions from old release -echo "" -echo "📍 Step 8: Creating cleanup PR for old release..." - -CLEANUP_PR_CREATED=false -CLEANUP_PR_URL="" - -# Only create cleanup PR if there's a cleanup target (not main) -if [[ "$CLEANUP_TARGET_BRANCH" != "main" && -n "$CLEANUP_TARGET_BRANCH" ]]; then - echo " Checking out previous release: $CLEANUP_TARGET_BRANCH..." - - # Clean any uncommitted changes - git reset --hard HEAD 2>/dev/null || true - git clean -fd 2>/dev/null || true - - # Checkout old release branch - git fetch origin "$CLEANUP_TARGET_BRANCH" 2>/dev/null || true - git checkout -B "$CLEANUP_TARGET_BRANCH" "origin/$CLEANUP_TARGET_BRANCH" - - # Check if GitHub Actions workflow exists - LABELS_WORKFLOW=".github/workflows/labels.yml" - - if [[ -f "$LABELS_WORKFLOW" ]]; then - echo " Found GitHub Actions workflow in $CLEANUP_TARGET_BRANCH" - - # Create cleanup branch - CLEANUP_BRANCH="cleanup-actions-${CLEANUP_TARGET_BRANCH}-$(date +%s)" - git checkout -b "$CLEANUP_BRANCH" - - # Remove the workflow file - git rm "$LABELS_WORKFLOW" - - # Commit the removal - CLEANUP_COMMIT_MSG="Remove GitHub Actions workflow from ${CLEANUP_TARGET_BRANCH} - -Workflow has been moved to ${BUNDLE_BRANCH}. -This prevents duplicate automation on old release branch." - - git commit --signoff -m "$CLEANUP_COMMIT_MSG" - echo " ✅ Committed workflow removal" - - # Check if cleanup PR already exists - echo " Checking for existing cleanup PR..." - EXISTING_CLEANUP_PR=$(gh pr list \ - --repo "${BUNDLE_REPO}" \ - --base "$CLEANUP_TARGET_BRANCH" \ - --state all \ - --search "Remove GitHub Actions from ${CLEANUP_TARGET_BRANCH}" \ - --json number,url,state \ - --jq '.[0] | select(. != null) | "\(.state)|\(.url)"' 2>/dev/null || echo "") - - if [[ -n "$EXISTING_CLEANUP_PR" && "$EXISTING_CLEANUP_PR" != "$NULL_PR_VALUE" ]]; then - CLEANUP_PR_STATE=$(echo "$EXISTING_CLEANUP_PR" | cut -d'|' -f1) - CLEANUP_PR_URL=$(echo "$EXISTING_CLEANUP_PR" | cut -d'|' -f2) - echo " ℹ️ Cleanup PR already exists (state: $CLEANUP_PR_STATE): $CLEANUP_PR_URL" - CLEANUP_PR_CREATED=true - else - # Push cleanup branch to fork - if [[ "$FORK_EXISTS" = false ]]; then - echo " ⚠️ Cannot push to fork - fork does not exist" >&2 - echo " Please fork ${BUNDLE_REPO} and run again, or create cleanup PR manually" - CLEANUP_PR_CREATED=false - elif git push -f fork "$CLEANUP_BRANCH" 2>&1; then - echo " ✅ Cleanup branch pushed to fork" - - # Create cleanup PR to old release branch - CLEANUP_PR_BODY="Remove GitHub Actions workflow from ${CLEANUP_TARGET_BRANCH} - -The workflow has been moved to the new release branch \`${BUNDLE_BRANCH}\`. - -This PR removes the workflow from ${CLEANUP_TARGET_BRANCH} to prevent duplicate automation." - - CLEANUP_PR_OUTPUT=$(gh pr create --base "$CLEANUP_TARGET_BRANCH" --head "${GITHUB_USER}:$CLEANUP_BRANCH" \ - --title "Remove GitHub Actions from ${CLEANUP_TARGET_BRANCH}" \ - --body "$CLEANUP_PR_BODY" \ - --repo "$BUNDLE_REPO" 2>&1) || true - - # Check if cleanup PR was successfully created - if [[ "$CLEANUP_PR_OUTPUT" =~ ^https:// ]]; then - CLEANUP_PR_URL="$CLEANUP_PR_OUTPUT" - echo " ✅ Cleanup PR created: $CLEANUP_PR_URL" - CLEANUP_PR_CREATED=true - elif [[ "$CLEANUP_PR_OUTPUT" =~ (https://github.com/[^[:space:]]+) ]]; then - CLEANUP_PR_URL="${BASH_REMATCH[1]}" - echo " ✅ Cleanup PR created: $CLEANUP_PR_URL" - CLEANUP_PR_CREATED=true - else - echo " ⚠️ Failed to create cleanup PR" >&2 - echo " Reason: $CLEANUP_PR_OUTPUT" - CLEANUP_PR_CREATED=false - fi - else - echo " ⚠️ Failed to push cleanup branch" >&2 - CLEANUP_PR_CREATED=false - fi - fi - else - echo " ℹ️ No GitHub Actions workflow found in $CLEANUP_TARGET_BRANCH" - CLEANUP_PR_CREATED=false - fi -else - echo " ℹ️ No previous release to clean up (cleanup target is $CLEANUP_TARGET_BRANCH)" - CLEANUP_PR_CREATED=false -fi - # Summary echo "" echo "$SEPARATOR_LINE" @@ -907,9 +669,6 @@ fi if [[ "$PR_CREATED" = true && -n "$PR_URL" ]]; then echo " ✓ PR to $BUNDLE_BRANCH: ${PR_URL}" fi -if [[ "$CLEANUP_PR_CREATED" = true && -n "$CLEANUP_PR_URL" ]]; then - echo " ✓ Cleanup PR to $CLEANUP_TARGET_BRANCH: ${CLEANUP_PR_URL}" -fi echo "" echo "$SEPARATOR_LINE" echo "📝 NEXT STEPS" @@ -920,18 +679,11 @@ if [[ "$PUSHED_TO_ORIGIN" = true ]]; then echo "Branch: https://github.com/$BUNDLE_REPO/tree/$BUNDLE_BRANCH" echo "" echo "Verify: Bundle images and tekton pipelines" -elif [[ "$PR_CREATED" = true || "$CLEANUP_PR_CREATED" = true ]]; then - PR_COUNT=0 - if [[ "$PR_CREATED" = true && -n "$PR_URL" ]]; then - PR_COUNT=$((PR_COUNT + 1)) - echo "${PR_COUNT}. Review and merge PR to $BUNDLE_BRANCH:" +elif [[ "$PR_CREATED" = true ]]; then + if [[ -n "$PR_URL" ]]; then + echo "1. Review and merge PR to $BUNDLE_BRANCH:" echo " ${PR_URL}" fi - if [[ "$CLEANUP_PR_CREATED" = true && -n "$CLEANUP_PR_URL" ]]; then - PR_COUNT=$((PR_COUNT + 1)) - echo "${PR_COUNT}. Review and merge cleanup PR to $CLEANUP_TARGET_BRANCH:" - echo " ${CLEANUP_PR_URL}" - fi echo "" echo "After merge: Verify bundle images and tekton pipelines" else diff --git a/.claude/skills/new-release/scripts/04-catalog.sh b/.claude/skills/new-release/scripts/04-catalog.sh index 190d0cb0dd..21386072c8 100755 --- a/.claude/skills/new-release/scripts/04-catalog.sh +++ b/.claude/skills/new-release/scripts/04-catalog.sh @@ -351,20 +351,6 @@ else PREV_CATALOG_TAG="" fi -# For cleanup PR, we need to find the previous release -# If CATALOG_BRANCH is the latest, find second-to-latest for cleanup -if [[ "$LATEST_CATALOG_RELEASE" = "$CATALOG_BRANCH" ]]; then - CLEANUP_TARGET_BRANCH=$(git branch -r | grep -E 'origin/release-[0-9]+\.[0-9]+$' | \ - sed 's|.*origin/||' | sed 's|^[* ]*||' | sort -V | tail -2 | head -1) - if [[ -n "$CLEANUP_TARGET_BRANCH" && "$CLEANUP_TARGET_BRANCH" != "$CATALOG_BRANCH" ]]; then - echo "Cleanup target: $CLEANUP_TARGET_BRANCH (previous release)" - else - CLEANUP_TARGET_BRANCH="" - fi -else - # When creating new catalog, BASE_BRANCH is the cleanup target - CLEANUP_TARGET_BRANCH="$BASE_BRANCH" -fi echo "" @@ -374,7 +360,6 @@ CHANGES_COMMITTED=false PUSHED_TO_ORIGIN=false CATALOG_PR_STATUS="$PR_STATUS_NONE" # none, created, updated, exists, skipped, pushed CATALOG_PR_URL="" -CLEANUP_PR_STATUS="$PR_STATUS_NONE" # none, created, updated, exists, skipped CLEANUP_PR_URL="" # Check if new release branch already exists on origin (upstream) @@ -828,131 +813,6 @@ fi fi fi -# Step 5: Create cleanup PR to remove GitHub Actions from old release -echo "" -echo "📍 Step 5: Creating cleanup PR for old release..." - -# Only create cleanup PR if there's a cleanup target (not main) -if [[ "$CLEANUP_TARGET_BRANCH" != "main" && -n "$CLEANUP_TARGET_BRANCH" ]]; then - echo " Checking out previous release: $CLEANUP_TARGET_BRANCH..." - - # Clean any uncommitted changes - git reset --hard HEAD 2>/dev/null || true - git clean -fd 2>/dev/null || true - - # Checkout old release branch - git fetch origin "$CLEANUP_TARGET_BRANCH" 2>/dev/null || true - git checkout -B "$CLEANUP_TARGET_BRANCH" "origin/$CLEANUP_TARGET_BRANCH" - - # Check if GitHub Actions workflow exists - LABELS_WORKFLOW=".github/workflows/labels.yml" - - if [[ -f "$LABELS_WORKFLOW" ]]; then - echo " Found GitHub Actions workflow in $CLEANUP_TARGET_BRANCH" - - # Use fixed branch name for PR deduplication - CLEANUP_BRANCH="cleanup-actions-${CLEANUP_TARGET_BRANCH}" - - # Check if branch already exists locally and delete it - if git show-ref --verify --quiet "refs/heads/$CLEANUP_BRANCH"; then - git branch -D "$CLEANUP_BRANCH" 2>/dev/null || true - fi - - git checkout -b "$CLEANUP_BRANCH" - - # Remove the workflow file - git rm "$LABELS_WORKFLOW" - - # Commit the removal - CLEANUP_COMMIT_MSG="Remove GitHub Actions workflow from ${CLEANUP_TARGET_BRANCH} - -Workflow has been moved to ${CATALOG_BRANCH}. -This prevents duplicate automation on old release branch." - - git commit --signoff -m "$CLEANUP_COMMIT_MSG" - echo " ✅ Committed workflow removal" - - # Check if cleanup PR already exists (search by title) - echo " Checking for existing cleanup PR..." - CLEANUP_PR_TITLE="Remove GitHub Actions from ${CLEANUP_TARGET_BRANCH}" - - EXISTING_CLEANUP_PR=$(gh pr list \ - --repo "${CATALOG_REPO}" \ - --base "$CLEANUP_TARGET_BRANCH" \ - --state open \ - --search "\"${CLEANUP_PR_TITLE}\" in:title author:${GITHUB_USER}" \ - --json number,url,headRefName \ - --jq '.[0] | select(. != null) | "\(.url)|\(.headRefName)"' 2>/dev/null || echo "") - - if [[ -n "$EXISTING_CLEANUP_PR" ]]; then - CLEANUP_PR_URL=$(echo "$EXISTING_CLEANUP_PR" | cut -d'|' -f1) - EXISTING_BRANCH=$(echo "$EXISTING_CLEANUP_PR" | cut -d'|' -f2) - - echo " ℹ️ Cleanup PR already exists: $CLEANUP_PR_URL" - echo " Existing branch: ${GITHUB_USER}:${EXISTING_BRANCH}" - - # Always push updates to the existing PR's branch (even if branch name is different) - echo " Pushing updates to existing cleanup PR branch: $EXISTING_BRANCH..." - if [[ "$FORK_EXISTS" = false ]]; then - echo " ⚠️ Cannot push to fork - fork does not exist" >&2 - echo " Please fork ${CATALOG_REPO} to enable PR creation" - CLEANUP_PR_STATUS="$PR_STATUS_EXISTS" - elif git push -f fork "$CLEANUP_BRANCH:$EXISTING_BRANCH" 2>&1; then - echo " ✅ Cleanup PR updated with latest changes: $CLEANUP_PR_URL" - CLEANUP_PR_STATUS="$PR_STATUS_UPDATED" - else - echo " ⚠️ Failed to push updates to fork" >&2 - CLEANUP_PR_STATUS="$PR_STATUS_EXISTS" - fi - else - # No existing PR, create a new one - if [[ "$FORK_EXISTS" = false ]]; then - echo " ⚠️ Cannot push to fork - fork does not exist" >&2 - echo " Please fork ${CATALOG_REPO} and run again, or create cleanup PR manually" - CLEANUP_PR_STATUS="$PR_STATUS_FAILED" - elif git push -f fork "$CLEANUP_BRANCH" 2>&1; then - echo " ✅ Cleanup branch pushed to fork" - - # Create cleanup PR to old release branch - CLEANUP_PR_BODY="Remove GitHub Actions workflow from ${CLEANUP_TARGET_BRANCH} - -The workflow has been moved to the new release branch \`${CATALOG_BRANCH}\`. - -This PR removes the workflow from ${CLEANUP_TARGET_BRANCH} to prevent duplicate automation." - - CLEANUP_PR_OUTPUT=$(gh pr create --base "$CLEANUP_TARGET_BRANCH" --head "${GITHUB_USER}:$CLEANUP_BRANCH" \ - --title "Remove GitHub Actions from ${CLEANUP_TARGET_BRANCH}" \ - --body "$CLEANUP_PR_BODY" \ - --repo "$CATALOG_REPO" 2>&1) || true - - # Check if cleanup PR was successfully created - if [[ "$CLEANUP_PR_OUTPUT" =~ ^https:// ]]; then - CLEANUP_PR_URL="$CLEANUP_PR_OUTPUT" - echo " ✅ Cleanup PR created: $CLEANUP_PR_URL" - CLEANUP_PR_STATUS="$PR_STATUS_CREATED" - elif [[ "$CLEANUP_PR_OUTPUT" =~ (https://github.com/[^[:space:]]+) ]]; then - CLEANUP_PR_URL="${BASH_REMATCH[1]}" - echo " ✅ Cleanup PR created: $CLEANUP_PR_URL" - CLEANUP_PR_STATUS="$PR_STATUS_CREATED" - else - echo " ⚠️ Failed to create cleanup PR" >&2 - echo " Reason: $CLEANUP_PR_OUTPUT" - CLEANUP_PR_STATUS="$PR_STATUS_FAILED" - fi - else - echo " ⚠️ Failed to push cleanup branch" >&2 - CLEANUP_PR_STATUS="$PR_STATUS_FAILED" - fi - fi - else - echo " ℹ️ No GitHub Actions workflow found in $CLEANUP_TARGET_BRANCH" - CLEANUP_PR_STATUS="$PR_STATUS_SKIPPED" - fi -else - echo " ℹ️ No previous release to clean up (cleanup target is $CLEANUP_TARGET_BRANCH)" - CLEANUP_PR_STATUS="$PR_STATUS_SKIPPED" -fi - # Summary echo "" echo "$SEPARATOR_LINE" @@ -1024,24 +884,6 @@ case "$CATALOG_PR_STATUS" in ;; esac -# Cleanup PR status -case "$CLEANUP_PR_STATUS" in - "$PR_STATUS_CREATED") - echo " ✓ Cleanup PR to $CLEANUP_TARGET_BRANCH: Created - ${CLEANUP_PR_URL}" - ;; - "$PR_STATUS_UPDATED") - echo " ✓ Cleanup PR to $CLEANUP_TARGET_BRANCH: Updated - ${CLEANUP_PR_URL}" - ;; - "$PR_STATUS_EXISTS") - echo " ✓ Cleanup PR to $CLEANUP_TARGET_BRANCH: Exists (no changes) - ${CLEANUP_PR_URL}" - ;; - "$PR_STATUS_SKIPPED") - echo " ✓ Cleanup: No GitHub Actions workflow to remove" - ;; - *) - echo " ⚠️ Cleanup: Unknown status ($CLEANUP_PR_STATUS)" >&2 - ;; -esac echo "" echo "$SEPARATOR_LINE" echo "📝 NEXT STEPS" @@ -1101,26 +943,6 @@ elif [[ "$CATALOG_PR_STATUS" = "$PR_STATUS_CREATED" || "$CATALOG_PR_STATUS" = "$ echo " ${CATALOG_PR_URL}" fi -# Cleanup PR -if [[ "$CLEANUP_PR_STATUS" = "$PR_STATUS_CREATED" || "$CLEANUP_PR_STATUS" = "$PR_STATUS_UPDATED" || "$CLEANUP_PR_STATUS" = "$PR_STATUS_EXISTS" ]]; then - PR_COUNT=$((PR_COUNT + 1)) - case "$CLEANUP_PR_STATUS" in - "$PR_STATUS_CREATED") - echo "${PR_COUNT}. Review and merge cleanup PR to $CLEANUP_TARGET_BRANCH:" - ;; - "$PR_STATUS_UPDATED") - echo "${PR_COUNT}. Review updated cleanup PR to $CLEANUP_TARGET_BRANCH:" - ;; - "$PR_STATUS_EXISTS") - echo "${PR_COUNT}. Review existing cleanup PR to $CLEANUP_TARGET_BRANCH:" - ;; - *) - echo "${PR_COUNT}. Review cleanup PR to $CLEANUP_TARGET_BRANCH (status: $CLEANUP_PR_STATUS):" - ;; - esac - echo " ${CLEANUP_PR_URL}" -fi - if [[ $PR_COUNT -gt 0 ]]; then echo "" echo "After merge: Verify OCP pipelines and catalog images" @@ -1129,7 +951,7 @@ elif [[ "$CATALOG_PR_STATUS" != "$PR_STATUS_PUSHED" ]]; then fi echo "" echo "$SEPARATOR_LINE" -if [[ "$CATALOG_PR_STATUS" = "$PR_STATUS_PUSHED" || "$CATALOG_PR_STATUS" = "$PR_STATUS_CREATED" || "$CATALOG_PR_STATUS" = "$PR_STATUS_UPDATED" ]]; then +if [[ "$CATALOG_PR_STATUS" = "$PR_STATUS_PUSHED" || "$CATALOG_PR_STATUS" = "$PR_STATUS_CREATED" || "$CATALOG_PR_STATUS" = "$PR_STATUS_UPDATED" || "$MAIN_PR_STATUS" = "$PR_STATUS_CREATED" || "$MAIN_PR_STATUS" = "$PR_STATUS_UPDATED" ]]; then echo "✅ SUCCESS" else echo "⚠️ COMPLETED WITH ISSUES" >&2 From 78ba7a163fa10bfed9fa1e216ede2edb14890d3e Mon Sep 17 00:00:00 2001 From: myan Date: Thu, 12 Mar 2026 04:44:55 -0400 Subject: [PATCH 7/8] fix: detect MGH release PR by title to get correct bundle content Previously MGH_MAIN_PR was hardcoded to empty, always falling back to upstream/main which may not have the latest bundle changes if the release PR is not yet merged. Now queries GitHub for the open PR with the release branch name in its title, so bundle content is taken from the correct PR branch (e.g. release-2.17-tekton-configs for release-2.17). Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: myan --- .claude/skills/new-release/scripts/03-bundle.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.claude/skills/new-release/scripts/03-bundle.sh b/.claude/skills/new-release/scripts/03-bundle.sh index 7664db705a..4e7b1379e1 100755 --- a/.claude/skills/new-release/scripts/03-bundle.sh +++ b/.claude/skills/new-release/scripts/03-bundle.sh @@ -117,9 +117,14 @@ cd "$MGH_REPO_PATH" # Check for PR to main branch (created by script 01) echo " Checking for multicluster-global-hub PR to main branch..." -# Use exact title match to avoid false positives from --search -# Since release PR is likely already merged to main, just use main branch directly -MGH_MAIN_PR="" +MGH_MAIN_PR=$(gh pr list \ + --repo "stolostron/multicluster-global-hub" \ + --base main \ + --state open \ + --author "$GITHUB_USER" \ + --search "\"$RELEASE_BRANCH\" in:title" \ + --json number,url,headRefName \ + --jq '.[0] | select(. != null) | "\(.number)|\(.url)|\(.headRefName)"' 2>/dev/null || echo "") if [[ -n "$MGH_MAIN_PR" && "$MGH_MAIN_PR" != "null|null|" ]]; then # PR exists - use bundle from PR branch (latest updates before merge) From 57eb498b3e22f8080b10b66f2bc8b88211c88d7a Mon Sep 17 00:00:00 2001 From: myan Date: Thu, 12 Mar 2026 04:48:36 -0400 Subject: [PATCH 8/8] docs: update bundle repo description with MGH PR detection and verification Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: myan --- .claude/skills/new-release/SKILL.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.claude/skills/new-release/SKILL.md b/.claude/skills/new-release/SKILL.md index 3a50453f99..883afc0f80 100644 --- a/.claude/skills/new-release/SKILL.md +++ b/.claude/skills/new-release/SKILL.md @@ -109,17 +109,18 @@ The skill manages releases across 6 repositories, each with its own dedicated sc **Repository**: [stolostron/multicluster-global-hub-operator-bundle](https://github.com/stolostron/multicluster-global-hub-operator-bundle) **What it does**: +- Detects open MGH release PR (e.g., PR to main with `release-2.17` in title) and copies bundle content (`manifests/`, `metadata/`, `tests/`) from that PR's branch; falls back to `upstream/main` if no open PR found - Checks out release branch (e.g., release-1.8) - Updates `images_digest_mirror_set.yaml` with new image tags - Renames tekton pipelines: globalhub-1-7 → globalhub-1-8 (pull-request and push) -- Updates bundle image labels and `konflux-patch.sh` image references +- Updates `konflux-patch.sh` image references and version replacement - Creates PR to the release branch **Expected PRs**: 1 | PR | Target Branch | Content | Verification | |----|--------------|---------|--------------| -| PR to release branch | `release-1.8` | tekton pipelines renamed globalhub-1-7 → globalhub-1-8; image tags updated to globalhub-1-8 | Check `.tekton/` has `*globalhub-1-8*.yaml` files | +| PR to release branch | `release-1.8` | Bundle content synced from MGH release PR branch; tekton pipelines renamed globalhub-1-7 → globalhub-1-8; image tags updated; konflux-patch.sh updated | Check `bundle/manifests/*.clusterserviceversion.yaml` has version `1.8.0-dev`, skipRange `>=1.7.0 <1.8.0`; `.tekton/` has `*globalhub-1-8*.yaml` | ---