diff --git a/.claude/.claude-plugin/plugin.json b/.claude/.claude-plugin/plugin.json new file mode 100644 index 0000000000..2ee99567c8 --- /dev/null +++ b/.claude/.claude-plugin/plugin.json @@ -0,0 +1,225 @@ +{ + "name": "openshift-branching", + "version": "1.0.0", + "description": "Automates OpenShift release branching tasks", + "author": "TestPlatform Team", + "commands": [ + { + "name": "branching-day", + "description": "Execute Branching Day tasks for OpenShift X.Y release", + "usage": "/branching-day", + "examples": [ + "/branching-day" + ] + }, + { + "name": "post-branching", + "description": "Execute Post-Branching tasks - bootstrap config and content for X.Y+2", + "usage": "/post-branching", + "examples": [ + "/post-branching" + ] + } + ], + "skills": [ + { + "name": "create-branch-from-master", + "description": "Fetch latest from master, rebase/reset master, and create a new branch", + "script": "skills/common/create-branch-from-master.sh" + }, + { + "name": "build-branching-tooling", + "description": "Build all branching tools (config-brancher, tide-config-manager, rpm-repo-mirroring-service, ci-operator-config-mirror)", + "script": "skills/common/build-branching-tooling.sh" + }, + { + "name": "get-current-release", + "description": "Verify branching readiness and get target release version (checks for 3+ accepted nightlies)", + "script": "skills/common/get-current-release.sh" + }, + { + "name": "run-config-brancher", + "description": "Run config-brancher to bump CI operator configurations", + "script": "skills/branching-day/run-config-brancher.sh" + }, + { + "name": "verify-config-brancher", + "description": "Verify config-brancher output (re-run after fixes)", + "script": "skills/branching-day/verify-config-brancher.sh" + }, + { + "name": "update-infra-periodics", + "description": "Update infra-periodics.yaml and jira config for config-brancher PR", + "script": "skills/branching-day/update-infra-periodics.sh" + }, + { + "name": "verify-infra-periodics", + "description": "Verify infra-periodics and jira config updates (re-run after fixes)", + "script": "skills/branching-day/verify-infra-periodics.sh" + }, + { + "name": "commit-config-brancher-pr", + "description": "Create commits for config-brancher PR", + "script": "skills/branching-day/commit-config-brancher-pr.sh" + }, + { + "name": "run-tide-config-manager", + "description": "Run tide-config-manager to update merge criteria for branching", + "script": "skills/branching-day/run-tide-config-manager.sh" + }, + { + "name": "verify-tide-config-manager", + "description": "Verify tide-config-manager output (re-run after fixes)", + "script": "skills/branching-day/verify-tide-config-manager.sh" + }, + { + "name": "update-tide-and-infra-jobs", + "description": "Update infrastructure periodic jobs for tide config PR", + "script": "skills/branching-day/update-tide-and-infra-jobs.sh" + }, + { + "name": "verify-tide-and-infra-jobs", + "description": "Verify tide and infra jobs updates (re-run after fixes)", + "script": "skills/branching-day/verify-tide-and-infra-jobs.sh" + }, + { + "name": "update-etcd-config", + "description": "Update etcd tide config for branching (etcd special case)", + "script": "skills/branching-day/update-etcd-config.sh" + }, + { + "name": "verify-etcd-config", + "description": "Verify etcd config updates (re-run after fixes)", + "script": "skills/branching-day/verify-etcd-config.sh" + }, + { + "name": "commit-tide-config-pr", + "description": "Create commits for tide config PR", + "script": "skills/branching-day/commit-tide-config-pr.sh" + }, + { + "name": "update-image-mirroring", + "description": "Helper to update image mirroring configuration", + "script": "skills/branching-day/update-image-mirroring.sh" + }, + { + "name": "commit-image-mirroring-pr", + "description": "Create commits for image mirroring PR", + "script": "skills/branching-day/commit-image-mirroring-pr.sh" + }, + { + "name": "trigger-periodic-jobs", + "description": "Trigger periodic jobs via gangway with optional polling", + "script": "skills/common/trigger-periodic-jobs.sh" + }, + { + "name": "update-jira-validation-post-branching", + "description": "Configure Jira validation criteria for X.Y+2 branches (post-branching)", + "script": "skills/post-branching/update-jira-validation-post-branching.sh" + }, + { + "name": "verify-jira-validation", + "description": "Verify Jira validation config (re-run after fixes)", + "script": "skills/post-branching/verify-jira-validation.sh" + }, + { + "name": "commit-jira-validation-pr", + "description": "Create commit and branch for Jira validation PR (post-branching)", + "script": "skills/post-branching/commit-jira-validation-pr.sh" + }, + { + "name": "update-merge-blockers-job", + "description": "Update merge blockers job to track X.Y+2 (post-branching)", + "script": "skills/post-branching/update-merge-blockers-job.sh" + }, + { + "name": "verify-merge-blockers-job", + "description": "Verify merge blockers job update (re-run after fixes)", + "script": "skills/post-branching/verify-merge-blockers-job.sh" + }, + { + "name": "commit-merge-blockers-pr", + "description": "Create commit and branch for merge blockers PR (post-branching)", + "script": "skills/post-branching/commit-merge-blockers-pr.sh" + }, + { + "name": "update-fast-forward-job", + "description": "Update fast-forward job for X.Y+2 (post-branching)", + "script": "skills/post-branching/update-fast-forward-job.sh" + }, + { + "name": "verify-fast-forward-job", + "description": "Verify fast-forward job update (re-run after fixes)", + "script": "skills/post-branching/verify-fast-forward-job.sh" + }, + { + "name": "commit-fast-forward-pr", + "description": "Create commit and branch for fast-forward PR (post-branching)", + "script": "skills/post-branching/commit-fast-forward-pr.sh" + }, + { + "name": "create-config-jobs-x-y-plus-2", + "description": "Create CI operator configs and jobs for X.Y+2 (post-branching)", + "script": "skills/post-branching/create-config-jobs-x-y-plus-2.sh" + }, + { + "name": "verify-config-jobs-x-y-plus-2", + "description": "Verify CI configs and jobs creation (re-run after fixes)", + "script": "skills/post-branching/verify-config-jobs-x-y-plus-2.sh" + }, + { + "name": "commit-ci-configs-jobs-pr", + "description": "Create branch for CI configs and jobs PR (post-branching)", + "script": "skills/post-branching/commit-ci-configs-jobs-pr.sh" + }, + { + "name": "update-auto-config-brancher-x-y-plus-2", + "description": "Update auto-config-brancher to maintain X.Y+2 (post-branching)", + "script": "skills/post-branching/update-auto-config-brancher-x-y-plus-2.sh" + }, + { + "name": "verify-auto-config-brancher", + "description": "Verify auto-config-brancher job update (re-run after fixes)", + "script": "skills/post-branching/verify-auto-config-brancher.sh" + }, + { + "name": "commit-auto-config-brancher-pr", + "description": "Create commit and branch for auto-config-brancher PR (post-branching)", + "script": "skills/post-branching/commit-auto-config-brancher-pr.sh" + }, + { + "name": "update-image-mirroring-x-y-plus-2", + "description": "Update image mirroring config for X.Y+2 (post-branching)", + "script": "skills/post-branching/update-image-mirroring-x-y-plus-2.sh" + }, + { + "name": "verify-image-mirroring-x-y-plus-2", + "description": "Verify image mirroring config update (re-run after fixes)", + "script": "skills/post-branching/verify-image-mirroring-x-y-plus-2.sh" + }, + { + "name": "commit-image-mirroring-x-y-plus-2-pr", + "description": "Create commit and branch for image mirroring X.Y+2 PR (post-branching)", + "script": "skills/post-branching/commit-image-mirroring-x-y-plus-2-pr.sh" + }, + { + "name": "verify-imagestream-tags", + "description": "Verify image stream tag counts match between versions (re-run after tagging)", + "script": "skills/post-branching/verify-imagestream-tags.sh" + }, + { + "name": "tag-imagestreams", + "description": "Tag image streams from old version to new version", + "script": "skills/post-branching/tag-imagestreams.sh" + }, + { + "name": "mirror-imagestreams-to-quay", + "description": "Mirror all image streams to Quay (7 streams: ocp, origin, ocp-private, and 4 variants)", + "script": "skills/post-branching/mirror-imagestreams-to-quay.sh" + } + ], + "config": { + "RELEASE_REPO": "../release", + "CI_TOOLS_REPO": "." + } +} diff --git a/.claude/.claude-plugin/skills/branching-day/commit-config-brancher-pr.sh b/.claude/.claude-plugin/skills/branching-day/commit-config-brancher-pr.sh new file mode 100755 index 0000000000..5abc9b35af --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/commit-config-brancher-pr.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 + +cd "$3" +[ "$(git branch --show-current)" != "config-brancher-$2" ] && echo "Error: Wrong branch" && exit 1 + +git diff --staged --quiet || git reset HEAD + +git add ci-operator/config/ && \ + git diff --staged --quiet || \ + git commit -m "config-brancher --config-dir ./ci-operator/config --current-release=$1 --future-release=$2 --bump-release=$2 --confirm" + +git add -A && \ + git reset HEAD ci-operator/jobs/infra-periodics.yaml 2>/dev/null || true && \ + git reset HEAD core-services/jira-lifecycle-plugin/config.yaml 2>/dev/null || true && \ + git diff --staged --quiet || \ + git commit -m "make update" + +[ -f "ci-operator/jobs/infra-periodics.yaml" ] && \ + git add ci-operator/jobs/infra-periodics.yaml && \ + git diff --staged --quiet || \ + git commit -m "bump periodic-prow-auto-config-brancher and periodic-openshift-release-fast-forward" + +[ -f "core-services/jira-lifecycle-plugin/config.yaml" ] && \ + git add core-services/jira-lifecycle-plugin/config.yaml && \ + git diff --staged --quiet || \ + git commit -m "bump versions in jira config" + +echo "✓ Commits: $(git log --oneline origin/master..HEAD | wc -l)" diff --git a/.claude/.claude-plugin/skills/branching-day/commit-image-mirroring-pr.sh b/.claude/.claude-plugin/skills/branching-day/commit-image-mirroring-pr.sh new file mode 100755 index 0000000000..5d5dcb2da0 --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/commit-image-mirroring-pr.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 + +cd "$3" +[ "$(git branch --show-current)" != "image-mirroring-$2" ] && echo "Error: Wrong branch" && exit 1 + +git add core-services/image-mirroring/openshift/_config.yaml && git commit -m "bump image-mirroring config" +git add -A && git commit -m "make openshift-image-mirror-mappings" + +echo "✓ Commits: $(git log --oneline origin/master..HEAD | wc -l)" diff --git a/.claude/.claude-plugin/skills/branching-day/commit-tide-config-pr.sh b/.claude/.claude-plugin/skills/branching-day/commit-tide-config-pr.sh new file mode 100755 index 0000000000..8d58089bb1 --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/commit-tide-config-pr.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 + +cd "$3" +[ "$(git branch --show-current)" != "tide-config-$2" ] && echo "Error: Wrong branch" && exit 1 + +git add core-services/prow/ && git commit -m "tide-config-manager make prow-config" +git add ci-operator/jobs/infra-periodics.yaml && git commit -m "bump periodic-openshift-release-merge-blockers" +git add ci-operator/jobs/infra-periodics.yaml && git commit -m "bump periodic-ocp-build-data-enforcer" + +git diff --quiet core-services/prow/02_config/openshift/etcd/_prowconfig.yaml || \ + (git add core-services/prow/02_config/openshift/etcd/_prowconfig.yaml && git commit -m "etcd manual change") + +echo "✓ Commits: $(git log --oneline origin/master..HEAD | wc -l)" diff --git a/.claude/.claude-plugin/skills/branching-day/run-config-brancher.sh b/.claude/.claude-plugin/skills/branching-day/run-config-brancher.sh new file mode 100755 index 0000000000..3778ae7a2a --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/run-config-brancher.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 +[ ! -d "$2" ] && echo "Error: Release repo not found" && exit 1 + +config-brancher \ + --config-dir "$3/ci-operator/config" \ + --current-release="$1" \ + --future-release="$2" \ + --bump-release="$2" \ + --confirm + +echo "✓ config-brancher: $1 → $2" diff --git a/.claude/.claude-plugin/skills/branching-day/run-tide-config-manager.sh b/.claude/.claude-plugin/skills/branching-day/run-tide-config-manager.sh new file mode 100755 index 0000000000..5733dc1c98 --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/run-tide-config-manager.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 2 ] && echo "Usage: $0 " && exit 1 +[ ! -d "$2" ] && echo "Error: Release repo not found" && exit 1 + +RELEASE_REPO=$(cd "$2" && pwd) + +tide-config-manager \ + --current-release="$1" \ + --lifecycle-phase=branching \ + --prow-config-dir="$RELEASE_REPO/core-services/prow/02_config/" \ + --sharded-prow-config-base-dir="$RELEASE_REPO/core-services/prow/02_config/" + +echo "✓ tide-config-manager: $1" diff --git a/.claude/.claude-plugin/skills/branching-day/update-etcd-config.sh b/.claude/.claude-plugin/skills/branching-day/update-etcd-config.sh new file mode 100755 index 0000000000..2a2ba7cd4e --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/update-etcd-config.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 + +CURRENT="$1" +FUTURE="$2" +ETCD="$3/core-services/prow/02_config/openshift/etcd/_prowconfig.yaml" + +[ ! -f "$ETCD" ] && echo "Error: etcd config not found" && exit 1 + +sed -i "/- openshift-4.20$/a\ - openshift-${CURRENT}" "$ETCD" +sed -i "s/- openshift-${CURRENT}$/- openshift-${FUTURE}/" "$ETCD" +sed -i "/excludedBranches:/,/labels:/ { + /- openshift-${CURRENT}$/a\ - openshift-${FUTURE} +}" "$ETCD" + +echo "✓ etcd config: $CURRENT → $FUTURE" diff --git a/.claude/.claude-plugin/skills/branching-day/update-image-mirroring.sh b/.claude/.claude-plugin/skills/branching-day/update-image-mirroring.sh new file mode 100755 index 0000000000..a153a1d0e5 --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/update-image-mirroring.sh @@ -0,0 +1,13 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 + +CONFIG="$3/core-services/image-mirroring/openshift/_config.yaml" +[ ! -f "$CONFIG" ] && echo "Error: Image mirroring config not found" && exit 1 + +echo "⚠ MANUAL EDIT REQUIRED" +echo "" +echo "Edit $CONFIG:" +echo " Remove 'latest' from: $1 (all variants)" +echo " Add 'latest' to: $2 (all variants)" diff --git a/.claude/.claude-plugin/skills/branching-day/update-infra-periodics.sh b/.claude/.claude-plugin/skills/branching-day/update-infra-periodics.sh new file mode 100755 index 0000000000..7184e0efea --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/update-infra-periodics.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 + +CURRENT="$1" +FUTURE="$2" +INFRA="$3/ci-operator/jobs/infra-periodics.yaml" +JIRA="$3/core-services/jira-lifecycle-plugin/config.yaml" + +[ ! -f "$INFRA" ] && echo "Error: infra-periodics.yaml not found" && exit 1 +[ ! -f "$JIRA" ] && echo "Error: Jira config not found" && exit 1 + +sed -i "/name: periodic-prow-auto-config-brancher/,/name:/ { + s/base_ref: openshift-${CURRENT}/base_ref: openshift-${FUTURE}/ + s/--current-release=${CURRENT}/--current-release=${FUTURE}/ + s/--future-release=${CURRENT}/--future-release=${FUTURE}/ +}" "$INFRA" + +sed -i "/name: periodic-openshift-release-fast-forward$/,/secretName:/ { + s/--current-release=${CURRENT}/--current-release=${FUTURE}/ + s/--future-release=${CURRENT}/--future-release=${FUTURE}/ +}" "$INFRA" + +sed -i "/^ main:/,/^ [a-z]/ { + s/target_version: ${CURRENT}\.0/target_version: ${FUTURE}.0/ +}" "$JIRA" +sed -i "/^ master:/,/^ [a-z]/ { + s/target_version: ${CURRENT}\.0/target_version: ${FUTURE}.0/ +}" "$JIRA" + +echo "✓ infra-periodics + jira: $CURRENT → $FUTURE" diff --git a/.claude/.claude-plugin/skills/branching-day/update-tide-and-infra-jobs.sh b/.claude/.claude-plugin/skills/branching-day/update-tide-and-infra-jobs.sh new file mode 100755 index 0000000000..a42cfacc5a --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/update-tide-and-infra-jobs.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 + +CURRENT="$1" +FUTURE="$2" +CURRENT_MINOR="${CURRENT#*.}" +FUTURE_MINOR="${FUTURE#*.}" +INFRA="$3/ci-operator/jobs/infra-periodics.yaml" + +[ ! -f "$INFRA" ] && echo "Error: infra-periodics.yaml not found" && exit 1 + +sed -i "/name: periodic-openshift-release-merge-blockers/,/secretName:/ { + s/--current-release=${CURRENT}/--current-release=${FUTURE}/ + s/--future-release=${CURRENT}/--future-release=${FUTURE}/ +}" "$INFRA" + +sed -i "/name: periodic-ocp-build-data-enforcer/,/secretName:/ { + s/base_ref: openshift-${CURRENT}/base_ref: openshift-${FUTURE}/ + s/--minor=${CURRENT_MINOR}/--minor=${FUTURE_MINOR}/ +}" "$INFRA" + +echo "✓ tide + infra jobs: $CURRENT → $FUTURE" diff --git a/.claude/.claude-plugin/skills/branching-day/verify-config-brancher.sh b/.claude/.claude-plugin/skills/branching-day/verify-config-brancher.sh new file mode 100755 index 0000000000..4fcbc25fed --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/verify-config-brancher.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# verify-config-brancher.sh +# Verifies that config-brancher successfully created config files + +set -euo pipefail + +if [ "$#" -ne 2 ]; then + echo "Usage: $0 " + echo "Example: $0 4.22 ../release" + exit 1 +fi + +FUTURE_RELEASE="$1" +RELEASE_REPO="$2" + +echo "==========================================" +echo "Verifying config-brancher output" +echo "==========================================" + +VERIFICATION_FAILED=0 + +# Check if any config files were modified +cd "$RELEASE_REPO" +if git diff --quiet ci-operator/config/; then + echo "✗ FAILED: No changes detected in ci-operator/config/" + VERIFICATION_FAILED=1 +else + echo "✓ Changes detected in ci-operator/config/" + + # Count new config files for the future release + NEW_CONFIGS=$(git diff --name-only ci-operator/config/ | grep -c "release-${FUTURE_RELEASE}" || true) + if [ "$NEW_CONFIGS" -gt 0 ]; then + echo "✓ Found $NEW_CONFIGS new config files for release-${FUTURE_RELEASE}" + else + echo "⚠ Warning: No new config files found for release-${FUTURE_RELEASE}" + fi +fi + +echo "==========================================" + +if [ $VERIFICATION_FAILED -eq 1 ]; then + echo "Verification FAILED" + exit 1 +fi + +echo "✓ Verification passed!" +exit 0 diff --git a/.claude/.claude-plugin/skills/branching-day/verify-etcd-config.sh b/.claude/.claude-plugin/skills/branching-day/verify-etcd-config.sh new file mode 100755 index 0000000000..e2a02df058 --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/verify-etcd-config.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# verify-etcd-config.sh +# Verifies that etcd tide config was updated correctly + +set -euo pipefail + +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " + echo "Example: $0 4.21 4.22 ../release" + exit 1 +fi + +CURRENT_RELEASE="$1" +FUTURE_RELEASE="$2" +RELEASE_REPO="$3" + +ETCD_CONFIG="$RELEASE_REPO/core-services/prow/02_config/openshift/etcd/_prowconfig.yaml" + +echo "==========================================" +echo "Verifying etcd config updates" +echo "==========================================" + +VERIFICATION_FAILED=0 + +# Verify current release was added to older releases query +if grep -B 5 "backport-risk-assessed" "$ETCD_CONFIG" | grep -q "openshift-${CURRENT_RELEASE}"; then + echo "✓ openshift-${CURRENT_RELEASE} added to older releases query" +else + echo "✗ FAILED: openshift-${CURRENT_RELEASE} not found in older releases query" + VERIFICATION_FAILED=1 +fi + +# Verify future release is in the development branch query +if grep -A 5 "without backport-risk-assessed" "$ETCD_CONFIG" | grep -q "openshift-${FUTURE_RELEASE}"; then + echo "✓ openshift-${FUTURE_RELEASE} set as development branch" +else + echo "✗ FAILED: openshift-${FUTURE_RELEASE} not found in development query" + VERIFICATION_FAILED=1 +fi + +# Verify future release was added to excluded branches +if grep -A 10 "excludedBranches:" "$ETCD_CONFIG" | grep -q "openshift-${FUTURE_RELEASE}"; then + echo "✓ openshift-${FUTURE_RELEASE} added to excluded branches" +else + echo "✗ FAILED: openshift-${FUTURE_RELEASE} not found in excluded branches" + VERIFICATION_FAILED=1 +fi + +echo "==========================================" + +if [ $VERIFICATION_FAILED -eq 1 ]; then + echo "Verification FAILED" + exit 1 +fi + +echo "✓ Verification passed!" +exit 0 diff --git a/.claude/.claude-plugin/skills/branching-day/verify-infra-periodics.sh b/.claude/.claude-plugin/skills/branching-day/verify-infra-periodics.sh new file mode 100755 index 0000000000..5c006380b1 --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/verify-infra-periodics.sh @@ -0,0 +1,61 @@ +#!/bin/bash +# verify-infra-periodics.sh +# Verifies that infra-periodics and jira config were updated correctly + +set -euo pipefail + +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " + echo "Example: $0 4.21 4.22 ../release" + exit 1 +fi + +CURRENT_RELEASE="$1" +FUTURE_RELEASE="$2" +RELEASE_REPO="$3" + +INFRA_PERIODICS="$RELEASE_REPO/ci-operator/jobs/infra-periodics.yaml" +JIRA_CONFIG="$RELEASE_REPO/core-services/jira-lifecycle-plugin/config.yaml" + +echo "==========================================" +echo "Verifying infra-periodics and jira config" +echo "==========================================" + +VERIFICATION_FAILED=0 + +# Verify periodic-prow-auto-config-brancher was updated +if grep -q "base_ref: openshift-${FUTURE_RELEASE}" "$INFRA_PERIODICS" && \ + grep -q -- "--current-release=${FUTURE_RELEASE}" "$INFRA_PERIODICS"; then + echo "✓ periodic-prow-auto-config-brancher updated correctly" +else + echo "✗ FAILED: periodic-prow-auto-config-brancher not updated correctly" + VERIFICATION_FAILED=1 +fi + +# Verify periodic-openshift-release-fast-forward was updated +if grep -A 10 "name: periodic-openshift-release-fast-forward" "$INFRA_PERIODICS" | \ + grep -q -- "--current-release=${FUTURE_RELEASE}"; then + echo "✓ periodic-openshift-release-fast-forward updated correctly" +else + echo "✗ FAILED: periodic-openshift-release-fast-forward not updated correctly" + VERIFICATION_FAILED=1 +fi + +# Verify Jira config was updated for main and master +if grep -A 5 "^ main:" "$JIRA_CONFIG" | grep -q "target_version: ${FUTURE_RELEASE}.0" && \ + grep -A 5 "^ master:" "$JIRA_CONFIG" | grep -q "target_version: ${FUTURE_RELEASE}.0"; then + echo "✓ Jira config updated for main and master branches" +else + echo "✗ FAILED: Jira config not updated correctly" + VERIFICATION_FAILED=1 +fi + +echo "==========================================" + +if [ $VERIFICATION_FAILED -eq 1 ]; then + echo "Verification FAILED" + exit 1 +fi + +echo "✓ Verification passed!" +exit 0 diff --git a/.claude/.claude-plugin/skills/branching-day/verify-tide-and-infra-jobs.sh b/.claude/.claude-plugin/skills/branching-day/verify-tide-and-infra-jobs.sh new file mode 100755 index 0000000000..c526b7897b --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/verify-tide-and-infra-jobs.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# verify-tide-and-infra-jobs.sh +# Verifies that tide and infra jobs were updated correctly + +set -euo pipefail + +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " + echo "Example: $0 4.21 4.22 ../release" + exit 1 +fi + +CURRENT_RELEASE="$1" +FUTURE_RELEASE="$2" +RELEASE_REPO="$3" + +# Extract minor versions +FUTURE_MINOR="${FUTURE_RELEASE#*.}" + +INFRA_PERIODICS="$RELEASE_REPO/ci-operator/jobs/infra-periodics.yaml" + +echo "==========================================" +echo "Verifying tide and infra jobs updates" +echo "==========================================" + +VERIFICATION_FAILED=0 + +# Verify periodic-openshift-release-merge-blockers was updated +if grep -A 10 "name: periodic-openshift-release-merge-blockers" "$INFRA_PERIODICS" | \ + grep -q -- "--current-release=${FUTURE_RELEASE}"; then + echo "✓ periodic-openshift-release-merge-blockers updated correctly" +else + echo "✗ FAILED: periodic-openshift-release-merge-blockers not updated correctly" + VERIFICATION_FAILED=1 +fi + +# Verify periodic-ocp-build-data-enforcer was updated +if grep -q "base_ref: openshift-${FUTURE_RELEASE}" "$INFRA_PERIODICS" && \ + grep -q -- "--minor=${FUTURE_MINOR}" "$INFRA_PERIODICS"; then + echo "✓ periodic-ocp-build-data-enforcer updated correctly" +else + echo "✗ FAILED: periodic-ocp-build-data-enforcer not updated correctly" + VERIFICATION_FAILED=1 +fi + +echo "==========================================" + +if [ $VERIFICATION_FAILED -eq 1 ]; then + echo "Verification FAILED" + exit 1 +fi + +echo "✓ Verification passed!" +exit 0 diff --git a/.claude/.claude-plugin/skills/branching-day/verify-tide-config-manager.sh b/.claude/.claude-plugin/skills/branching-day/verify-tide-config-manager.sh new file mode 100755 index 0000000000..4f5ac78389 --- /dev/null +++ b/.claude/.claude-plugin/skills/branching-day/verify-tide-config-manager.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# verify-tide-config-manager.sh +# Verifies that tide-config-manager modified prow config files + +set -euo pipefail + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " + echo "Example: $0 ../release" + exit 1 +fi + +RELEASE_REPO="$1" + +RELEASE_REPO_ABSOLUTE=$(cd "$RELEASE_REPO" && pwd) + +echo "==========================================" +echo "Verifying tide-config-manager output" +echo "==========================================" + +VERIFICATION_FAILED=0 + +cd "$RELEASE_REPO_ABSOLUTE" + +# Check if prow config files were modified +if git diff --quiet core-services/prow/02_config/; then + echo "✗ FAILED: No changes detected in core-services/prow/02_config/" + VERIFICATION_FAILED=1 +else + echo "✓ Changes detected in prow config files" + + MODIFIED_FILES=$(git diff --name-only core-services/prow/02_config/ | wc -l) + echo "✓ Modified $MODIFIED_FILES prow config file(s)" +fi + +echo "==========================================" + +if [ $VERIFICATION_FAILED -eq 1 ]; then + echo "Verification FAILED" + exit 1 +fi + +echo "✓ Verification passed!" +exit 0 diff --git a/.claude/.claude-plugin/skills/common/build-branching-tooling.sh b/.claude/.claude-plugin/skills/common/build-branching-tooling.sh new file mode 100755 index 0000000000..6e3503197d --- /dev/null +++ b/.claude/.claude-plugin/skills/common/build-branching-tooling.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -euo pipefail + +CI_TOOLS="${1:-.}" +[ ! -f "$CI_TOOLS/Makefile" ] && echo "Error: Not a valid ci-tools repo" && exit 1 + +cd "$CI_TOOLS" + +TOOLS=(config-brancher tide-config-manager rpm-repo-mirroring-service ci-operator-config-mirror) +FAILED=0 + +for tool in "${TOOLS[@]}"; do + if make install WHAT="cmd/$tool" >/dev/null 2>&1; then + echo "✓ $tool" + else + echo "✗ $tool" + FAILED=1 + fi +done + +[ $FAILED -eq 1 ] && echo "Some tools failed to build" && exit 1 +echo "✓ All tools built" diff --git a/.claude/.claude-plugin/skills/common/create-branch-from-master.sh b/.claude/.claude-plugin/skills/common/create-branch-from-master.sh new file mode 100755 index 0000000000..f44941173c --- /dev/null +++ b/.claude/.claude-plugin/skills/common/create-branch-from-master.sh @@ -0,0 +1,27 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -lt 2 ] || [ "$#" -gt 3 ] && echo "Usage: $0 [--reset]" && exit 1 + +BRANCH="$1" +USE_RESET=false +[ "$#" -eq 3 ] && [ "$3" = "--reset" ] && USE_RESET=true + +cd "$2" +git rev-parse --git-dir >/dev/null 2>&1 || { echo "Error: Not a git repo"; exit 1; } + +REMOTE=$(git remote | grep -q "^upstream$" && echo "upstream" || echo "origin") +git fetch $REMOTE + +[ "$(git branch --show-current)" != "master" ] && git checkout master + +if [ "$USE_RESET" = true ]; then + git reset --hard $REMOTE/master +else + git rebase $REMOTE/master || { echo "Error: Rebase failed"; exit 1; } +fi + +git show-ref --verify --quiet "refs/heads/$BRANCH" && git branch -D "$BRANCH" + +git checkout -b "$BRANCH" +echo "✓ Branch: $BRANCH" diff --git a/.claude/.claude-plugin/skills/common/get-current-release.sh b/.claude/.claude-plugin/skills/common/get-current-release.sh new file mode 100755 index 0000000000..4b0b06068b --- /dev/null +++ b/.claude/.claude-plugin/skills/common/get-current-release.sh @@ -0,0 +1,30 @@ +#!/bin/bash +set -euo pipefail + +RELEASE_REPO="${1:-../release}" +INFRA_PERIODICS="$RELEASE_REPO/ci-operator/jobs/infra-periodics.yaml" + +[ ! -f "$INFRA_PERIODICS" ] && echo "Error: infra-periodics.yaml not found at $INFRA_PERIODICS" && exit 1 + +VERSION=$(grep -A 20 "name: periodic-prow-auto-config-brancher" "$INFRA_PERIODICS" | grep "current-release=" | head -1 | sed 's/.*--current-release=//' | awk '{print $1}') + +[ -z "$VERSION" ] && echo "Error: Failed to extract current-release from periodic-prow-auto-config-brancher" && exit 1 + +NIGHTLY_API="https://amd64.ocp.releases.ci.openshift.org/api/v1/releasestream/${VERSION}.0-0.nightly/tags" + +ACCEPTED_COUNT=$(curl -s "$NIGHTLY_API" | jq '[.tags[] | select(.phase == "Accepted")] | length') + +[ -z "$ACCEPTED_COUNT" ] && echo "Error: Failed to fetch nightly releases for $VERSION" && exit 1 + +if [ "$ACCEPTED_COUNT" -lt 3 ]; then + echo "✗ Branching cannot proceed!" + echo "✗ Target version: $VERSION" + echo "✗ Accepted nightlies: $ACCEPTED_COUNT/3 required" + echo "✗ Wait for at least 3 accepted nightlies in the $VERSION.0-0.nightly stream" + echo "✗ Check: $NIGHTLY_API" + exit 1 +fi + +echo "✓ Ready to branch: $VERSION" +echo "✓ Accepted nightlies: $ACCEPTED_COUNT/3 required" +echo "$VERSION" diff --git a/.claude/.claude-plugin/skills/common/trigger-periodic-jobs.sh b/.claude/.claude-plugin/skills/common/trigger-periodic-jobs.sh new file mode 100644 index 0000000000..d59dfe2f21 --- /dev/null +++ b/.claude/.claude-plugin/skills/common/trigger-periodic-jobs.sh @@ -0,0 +1,113 @@ +#!/bin/bash +set -euo pipefail + +usage() { + echo "Usage: $0 [--polling MINUTES] [job-name...]" + echo " --polling MINUTES Wait for job completion (timeout in minutes, default: no polling)" + exit 1 +} + +[ "$#" -lt 1 ] && usage + +POLLING=0 +JOBS=() + +while [ "$#" -gt 0 ]; do + case "$1" in + --polling) + shift + POLLING="$1" + shift + ;; + *) + JOBS+=("$1") + shift + ;; + esac +done + +[ ${#JOBS[@]} -eq 0 ] && usage + +GANGWAY_URL="https://gangway-ci.apps.ci.l2s4.p1.openshiftapps.com" +TOKEN=$(oc --context app.ci whoami -t 2>/dev/null) || { echo "Error: Failed to get oc token"; exit 1; } + +trigger_job() { + local job_name="$1" + local payload=$(cat < " && exit 1 + +cd "$2" +[ "$(git branch --show-current)" != "auto-config-brancher-$1" ] && echo "Error: Wrong branch" && exit 1 + +git add ci-operator/jobs/infra-periodics.yaml && \ + git diff --staged --quiet || \ + git commit -m "Update auto-config-brancher for $1 + +Configure periodic-prow-auto-config-brancher to maintain $1 configs." + +echo "✓ Committed" diff --git a/.claude/.claude-plugin/skills/post-branching/commit-fast-forward-pr.sh b/.claude/.claude-plugin/skills/post-branching/commit-fast-forward-pr.sh new file mode 100755 index 0000000000..cd7401e0a4 --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/commit-fast-forward-pr.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 2 ] && echo "Usage: $0 " && exit 1 + +cd "$2" +[ "$(git branch --show-current)" != "fast-forward-$1" ] && echo "Error: Wrong branch" && exit 1 + +git add ci-operator/jobs/infra-periodics.yaml && \ + git diff --staged --quiet || \ + git commit -m "Update fast-forward job for $1 + +Configure periodic-openshift-release-fast-forward to maintain $1 branches." + +echo "✓ Committed" diff --git a/.claude/.claude-plugin/skills/post-branching/commit-image-mirroring-x-y-plus-2-pr.sh b/.claude/.claude-plugin/skills/post-branching/commit-image-mirroring-x-y-plus-2-pr.sh new file mode 100755 index 0000000000..e77f07ac07 --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/commit-image-mirroring-x-y-plus-2-pr.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 2 ] && echo "Usage: $0 " && exit 1 + +cd "$2" +[ "$(git branch --show-current)" != "image-mirror-$1" ] && echo "Error: Wrong branch" && exit 1 + +git add core-services/image-mirroring/ && \ + git diff --staged --quiet || \ + git commit -m "Update image mirroring config for $1 + +Add $1 version to image mirroring configuration." + +echo "✓ Committed" diff --git a/.claude/.claude-plugin/skills/post-branching/commit-jira-validation-pr.sh b/.claude/.claude-plugin/skills/post-branching/commit-jira-validation-pr.sh new file mode 100755 index 0000000000..42aa50d132 --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/commit-jira-validation-pr.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 2 ] && echo "Usage: $0 " && exit 1 + +cd "$2" +[ "$(git branch --show-current)" != "jira-validation-$1" ] && echo "Error: Wrong branch" && exit 1 + +git add core-services/jira-lifecycle-plugin/config.yaml && \ + git diff --staged --quiet || \ + git commit -m "Configure Jira validation for $1 branches + +Add validation criteria for openshift-$1 and release-$1 branches." + +echo "✓ Committed" diff --git a/.claude/.claude-plugin/skills/post-branching/commit-merge-blockers-pr.sh b/.claude/.claude-plugin/skills/post-branching/commit-merge-blockers-pr.sh new file mode 100755 index 0000000000..24d4c2cfe8 --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/commit-merge-blockers-pr.sh @@ -0,0 +1,15 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 2 ] && echo "Usage: $0 " && exit 1 + +cd "$2" +[ "$(git branch --show-current)" != "merge-blockers-$1" ] && echo "Error: Wrong branch" && exit 1 + +git add ci-operator/jobs/infra-periodics.yaml && \ + git diff --staged --quiet || \ + git commit -m "Update merge blockers job for $1 + +Configure periodic-openshift-release-merge-blockers to track $1 branches." + +echo "✓ Committed" diff --git a/.claude/.claude-plugin/skills/post-branching/create-config-jobs-x-y-plus-2.sh b/.claude/.claude-plugin/skills/post-branching/create-config-jobs-x-y-plus-2.sh new file mode 100755 index 0000000000..f0c26a9afb --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/create-config-jobs-x-y-plus-2.sh @@ -0,0 +1,61 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 + +CURRENT="$1" +NEXT="$2" +CI_TOOLS=$(pwd) +RELEASE=$(cd "$3" && pwd) + +[ ! -d "$RELEASE" ] && echo "Error: Release repo not found" && exit 1 + +cd "$CI_TOOLS" +for tool in config-brancher ci-operator-config-mirror rpm-deps-mirroring-services; do + command -v $tool &>/dev/null || go install ./cmd/$tool +done + +cd "$RELEASE" +git fetch upstream && git reset --hard upstream/master + +config-brancher --config-dir ci-operator/config --current-release=$CURRENT --future-release=$NEXT --confirm +git add ci-operator/config && git commit -m "[$NEXT] Generate ci-operator configuration" + +ci-operator-config-mirror --config-dir ./ci-operator/config --to-org openshift-priv --only-org openshift --whitelist-file ./core-services/openshift-priv/_whitelist.yaml +git add ci-operator/config && git commit -m "[$NEXT] Generate ci-operator configuration for openshift-priv" + +make jobs +git add ci-operator/jobs && git commit -m "[$NEXT] Generate vanilla jobs for $NEXT" + +rpm-deps-mirroring-services --current-release "$CURRENT" --release-repo "$RELEASE" +git add . && git commit -m "[$NEXT] rpm dependency update" + +cat <<'EOF' >/tmp/filter.py +#!/usr/bin/env python3 +import yaml, sys +with open(sys.argv[1]) as f: + all = yaml.full_load(f) + for t in ("presubmits", "postsubmits"): + for repo in all.get(t, {}): + all[t][repo] = [j for j in all.get(t, {}).get(repo, []) if j.get("agent", "") == "kubernetes"] +with open(sys.argv[1], 'w') as f: + yaml.dump(all, f, default_flow_style=False) +EOF +chmod +x /tmp/filter.py + +find ci-operator/jobs/ -name '*-release-'$CURRENT'-*submits.yaml' -or -name '*-'$CURRENT'-periodics.yaml' | while read item; do + for main in master main; do + [ -e "${item/release-$CURRENT/$main}" ] || continue + cp "${item/release-$CURRENT/$main}" "${item/$CURRENT/$NEXT}" + sed -i "s/-$main-/-release-$NEXT-/g; s/- \^$main/- \^release-$NEXT/g" "${item/$CURRENT/$NEXT}" + /tmp/filter.py "${item/$CURRENT/$NEXT}" + break + done +done + +rm -f ci-operator/jobs/openshift/release/openshift-release-release-$NEXT-periodics.yaml +make jobs +git add ci-operator/jobs && git commit -m "[$NEXT] Carry job customization over from master/main jobs" + +echo "✓ CI configs + jobs: $CURRENT → $NEXT" +git log --oneline origin/master..HEAD diff --git a/.claude/.claude-plugin/skills/post-branching/mirror-imagestreams-to-quay.sh b/.claude/.claude-plugin/skills/post-branching/mirror-imagestreams-to-quay.sh new file mode 100755 index 0000000000..e82b37516a --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/mirror-imagestreams-to-quay.sh @@ -0,0 +1,57 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 2 ] && echo "Usage: $0 " && exit 1 + +NEW_VERSION="$1" +RELEASE_REPO="$2" + +[ ! -f "$RELEASE_REPO/hack/mirror_integration_stream.sh" ] && echo "Error: Release repo not found" && exit 1 + +cd "$RELEASE_REPO" + +STREAMS=( + "origin:${NEW_VERSION}" + "ocp:${NEW_VERSION}" + "ocp-private:${NEW_VERSION}-priv" + "origin:sriov-${NEW_VERSION}" + "origin:scos-${NEW_VERSION}" + "origin:ptp-${NEW_VERSION}" + "origin:metallb-${NEW_VERSION}" +) + +MAX_RETRIES=3 + +mirror_stream() { + local namespace="$1" + local name="$2" + local retries=0 + + while [ $retries -lt $MAX_RETRIES ]; do + if DRY_RUN=false IMAGESTREAM_NAMESPACE="$namespace" IMAGESTREAM_NAME="$name" ./hack/mirror_integration_stream.sh; then + return 0 + fi + retries=$((retries + 1)) + [ $retries -lt $MAX_RETRIES ] && echo "Retry $retries/$((MAX_RETRIES - 1)) for $namespace/$name..." && sleep 5 + done + return 1 +} + +FAILED=0 + +for stream in "${STREAMS[@]}"; do + NAMESPACE="${stream%%:*}" + NAME="${stream##*:}" + + echo "Mirroring $NAMESPACE/$NAME..." + + if mirror_stream "$NAMESPACE" "$NAME"; then + echo "✓ $NAMESPACE/$NAME" + else + echo "✗ $NAMESPACE/$NAME failed after $MAX_RETRIES attempts" + FAILED=1 + fi +done + +[ $FAILED -eq 1 ] && exit 1 +echo "✓ All image streams mirrored to Quay" diff --git a/.claude/.claude-plugin/skills/post-branching/tag-imagestreams.sh b/.claude/.claude-plugin/skills/post-branching/tag-imagestreams.sh new file mode 100755 index 0000000000..93a3ba307d --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/tag-imagestreams.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -lt 3 ] && echo "Usage: $0 [is-prefix] [is-suffix]" && exit 1 + +OLD_VERSION="$1" +NEW_VERSION="$2" +NAMESPACE="$3" +IS_PREFIX="${4:-}" +IS_SUFFIX="${5:-}" + +OLD_IS="${IS_PREFIX}${OLD_VERSION}${IS_SUFFIX}" +NEW_IS="${IS_PREFIX}${NEW_VERSION}${IS_SUFFIX}" + +for tag in $(oc --context=app.ci get is "$OLD_IS" -n "$NAMESPACE" -o json | jq -r '.status.tags[].tag'); do + echo "Seeding ${NAMESPACE}/${NEW_IS}:$tag" + oc --context=app.ci tag \ + --as system:admin \ + "${NAMESPACE}/${OLD_IS}:$tag" \ + "${NAMESPACE}/${NEW_IS}:$tag" +done + +echo "✓ Tagged ${NAMESPACE}/${NEW_IS}" diff --git a/.claude/.claude-plugin/skills/post-branching/update-auto-config-brancher-x-y-plus-2.sh b/.claude/.claude-plugin/skills/post-branching/update-auto-config-brancher-x-y-plus-2.sh new file mode 100755 index 0000000000..7cf55c16ee --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/update-auto-config-brancher-x-y-plus-2.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 + +XY_PLUS_1="$1" +XY_PLUS_2="$2" +INFRA="$3/ci-operator/jobs/infra-periodics.yaml" + +[ ! -f "$INFRA" ] && echo "Error: infra-periodics.yaml not found" && exit 1 + +sed -i "/name: periodic-prow-auto-config-brancher/,/name:/ { + s/--future-release=${XY_PLUS_1}/--future-release=${XY_PLUS_2}/ +}" "$INFRA" + +echo "✓ auto-config-brancher: $XY_PLUS_1 → $XY_PLUS_2" diff --git a/.claude/.claude-plugin/skills/post-branching/update-fast-forward-job.sh b/.claude/.claude-plugin/skills/post-branching/update-fast-forward-job.sh new file mode 100755 index 0000000000..6feddea742 --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/update-fast-forward-job.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 + +XY_PLUS_2="$2" +XY_PLUS_1=$(echo "$1" | awk -F. '{printf "%d.%d", $1, $2+1}') +INFRA="$3/ci-operator/jobs/infra-periodics.yaml" + +[ ! -f "$INFRA" ] && echo "Error: infra-periodics.yaml not found" && exit 1 + +sed -i "/name: periodic-openshift-release-fast-forward$/,/secretName:/ { + s/--future-release=${XY_PLUS_1}/--future-release=${XY_PLUS_2}/ +}" "$INFRA" + +echo "✓ fast-forward: $XY_PLUS_1 → $XY_PLUS_2" diff --git a/.claude/.claude-plugin/skills/post-branching/update-image-mirroring-x-y-plus-2.sh b/.claude/.claude-plugin/skills/post-branching/update-image-mirroring-x-y-plus-2.sh new file mode 100755 index 0000000000..5e26ecdda5 --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/update-image-mirroring-x-y-plus-2.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 + +XY_PLUS_1="$1" +XY_PLUS_2="$2" +CONFIG="$3/core-services/image-mirroring/openshift/_config.yaml" + +[ ! -f "$CONFIG" ] && echo "Error: Image mirroring config not found" && exit 1 + +add_version() { + local prefix="$1" after="$2" new="$3" + local after_key="${prefix}${after}" new_key="${prefix}${new}" + + grep -q "\"${new_key}\":" "$CONFIG" && return 0 + + awk -v after_key="$after_key" -v new_key="$new_key" -v new_ver="$new" ' + /^ "'"$after_key"'":/ { in_section = 1 } + in_section && /^ "/ && !/^ "'"$after_key"'":/ { + print " \"" new_key "\":" + print " - \"" new_ver "\"" + print " - \"" new_ver ".0\"" + in_section = 0 + } + { print } + ' "$CONFIG" > "${CONFIG}.tmp" + + mv "${CONFIG}.tmp" "$CONFIG" +} + +for prefix in "" "sriov-" "metallb-" "ptp-" "scos-"; do + add_version "$prefix" "$XY_PLUS_1" "$XY_PLUS_2" +done + +echo "✓ image-mirroring: $XY_PLUS_1 → $XY_PLUS_2 (all variants)" diff --git a/.claude/.claude-plugin/skills/post-branching/update-jira-validation-post-branching.sh b/.claude/.claude-plugin/skills/post-branching/update-jira-validation-post-branching.sh new file mode 100755 index 0000000000..9319499c23 --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/update-jira-validation-post-branching.sh @@ -0,0 +1,51 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 + +XY_PLUS_2="$2" +XY_PLUS_3=$(echo "$XY_PLUS_2" | awk -F. '{printf "%d.%d", $1, $2+1}') +XY_PLUS_1=$(echo "$XY_PLUS_2" | awk -F. '{printf "%d.%d", $1, $2-1}') +JIRA="$3/core-services/jira-lifecycle-plugin/config.yaml" + +[ ! -f "$JIRA" ] && echo "Error: Jira config not found" && exit 1 +grep -q "openshift-${XY_PLUS_2}:" "$JIRA" && echo "Warning: Already exists, skipping" && exit 0 + +OPENSHIFT_STANZA=" openshift-${XY_PLUS_2}: + dependent_bug_states: + - status: MODIFIED + - status: ON_QA + - status: VERIFIED + dependent_bug_target_versions: + - ${XY_PLUS_3}.0 + target_version: ${XY_PLUS_2}.0 + validate_by_default: true" + +RELEASE_STANZA=" release-${XY_PLUS_2}: + dependent_bug_states: + - status: MODIFIED + - status: ON_QA + - status: VERIFIED + dependent_bug_target_versions: + - ${XY_PLUS_3}.0 + target_version: ${XY_PLUS_2}.0 + validate_by_default: true" + +awk -v new_stanza="$OPENSHIFT_STANZA" -v prev="openshift-${XY_PLUS_1}:" ' +{ + if ($0 ~ prev) { in_stanza = 1 } + else if (in_stanza && /^ [a-z]/ && !/^ /) { print new_stanza; in_stanza = 0 } + print +}' "$JIRA" > "${JIRA}.tmp" + +awk -v new_stanza="$RELEASE_STANZA" -v prev="release-${XY_PLUS_1}:" ' +{ + if ($0 ~ prev) { in_stanza = 1 } + else if (in_stanza && (/^ [a-z]/ && !/^ / || /^[a-z]/)) { print new_stanza; in_stanza = 0 } + print +}' "${JIRA}.tmp" > "${JIRA}.tmp2" + +mv "${JIRA}.tmp2" "$JIRA" +rm -f "${JIRA}.tmp" + +echo "✓ Jira validation: openshift-$XY_PLUS_2, release-$XY_PLUS_2" diff --git a/.claude/.claude-plugin/skills/post-branching/update-merge-blockers-job.sh b/.claude/.claude-plugin/skills/post-branching/update-merge-blockers-job.sh new file mode 100755 index 0000000000..5825b85d66 --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/update-merge-blockers-job.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -ne 3 ] && echo "Usage: $0 " && exit 1 + +XY_PLUS_2="$2" +XY_PLUS_1=$(echo "$1" | awk -F. '{printf "%d.%d", $1, $2+1}') +INFRA="$3/ci-operator/jobs/infra-periodics.yaml" + +[ ! -f "$INFRA" ] && echo "Error: infra-periodics.yaml not found" && exit 1 + +sed -i "/name: periodic-openshift-release-merge-blockers$/,/name:/ { + s/--future-release=${XY_PLUS_1}/--future-release=${XY_PLUS_2}/ +}" "$INFRA" + +echo "✓ merge-blockers: $XY_PLUS_1 → $XY_PLUS_2" diff --git a/.claude/.claude-plugin/skills/post-branching/verify-auto-config-brancher.sh b/.claude/.claude-plugin/skills/post-branching/verify-auto-config-brancher.sh new file mode 100755 index 0000000000..e03ced30fb --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/verify-auto-config-brancher.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# verify-auto-config-brancher.sh +# Verifies that auto-config-brancher job was updated correctly + +set -euo pipefail + +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " + echo "Example: $0 4.22 4.23 ../release" + exit 1 +fi + +XY_PLUS_1="$1" +XY_PLUS_2="$2" +RELEASE_REPO="$3" + +INFRA_PERIODICS="$RELEASE_REPO/ci-operator/jobs/infra-periodics.yaml" + +echo "==========================================" +echo "Verifying auto-config-brancher job update" +echo "==========================================" + +VERIFICATION_FAILED=0 + +# Verify the update was successful +if grep -A 10 "name: periodic-prow-auto-config-brancher" "$INFRA_PERIODICS" | \ + grep -q -- "--future-release=${XY_PLUS_2}"; then + echo "✓ --future-release updated to ${XY_PLUS_2}" +else + echo "✗ FAILED: --future-release not updated correctly" + VERIFICATION_FAILED=1 +fi + +# Verify old value is gone +if grep -A 10 "name: periodic-prow-auto-config-brancher" "$INFRA_PERIODICS" | \ + grep -q -- "--future-release=${XY_PLUS_1}"; then + echo "✗ FAILED: Old value ${XY_PLUS_1} still present" + VERIFICATION_FAILED=1 +else + echo "✓ Old value ${XY_PLUS_1} removed" +fi + +echo "==========================================" + +if [ $VERIFICATION_FAILED -eq 1 ]; then + echo "Verification FAILED" + exit 1 +fi + +echo "✓ Verification passed!" +exit 0 diff --git a/.claude/.claude-plugin/skills/post-branching/verify-config-jobs-x-y-plus-2.sh b/.claude/.claude-plugin/skills/post-branching/verify-config-jobs-x-y-plus-2.sh new file mode 100755 index 0000000000..ea6a9f75b5 --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/verify-config-jobs-x-y-plus-2.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# verify-config-jobs-x-y-plus-2.sh +# Verifies that CI operator configs and jobs were created correctly + +set -euo pipefail + +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " + echo "Example: $0 4.22 4.23 ../release" + exit 1 +fi + +XY_PLUS_1="$1" +NEXT="$2" +RELEASE_REPO="$3" + +cd "$RELEASE_REPO" + +echo "==========================================" +echo "Verifying CI configs and jobs creation" +echo "==========================================" + +VERIFICATION_FAILED=0 + +# Verify commits were created +COMMIT_COUNT=$(git log --oneline origin/master..HEAD | wc -l) +if [ "$COMMIT_COUNT" -ge 4 ]; then + echo "✓ Created $COMMIT_COUNT commits (expected at least 4)" +else + echo "✗ FAILED: Only $COMMIT_COUNT commits created (expected at least 4)" + VERIFICATION_FAILED=1 +fi + +# Verify ci-operator config files for X.Y+2 were created +CONFIG_COUNT=$(find ci-operator/config -name "*release-${NEXT}*.yaml" | wc -l) +if [ "$CONFIG_COUNT" -gt 0 ]; then + echo "✓ Created $CONFIG_COUNT ci-operator config files for release-${NEXT}" +else + echo "✗ FAILED: No ci-operator config files found for release-${NEXT}" + VERIFICATION_FAILED=1 +fi + +# Verify jobs were created for X.Y+2 +JOB_COUNT=$(find ci-operator/jobs -name "*${NEXT}*.yaml" | wc -l) +if [ "$JOB_COUNT" -gt 0 ]; then + echo "✓ Created $JOB_COUNT job files for ${NEXT}" +else + echo "✗ FAILED: No job files found for ${NEXT}" + VERIFICATION_FAILED=1 +fi + +# Verify openshift-priv configs were created +PRIV_CONFIG_COUNT=$(find ci-operator/config/openshift-priv -name "*release-${NEXT}*.yaml" 2>/dev/null | wc -l) +if [ "$PRIV_CONFIG_COUNT" -gt 0 ]; then + echo "✓ Created $PRIV_CONFIG_COUNT openshift-priv config files" +else + echo "⚠ Warning: No openshift-priv config files found" +fi + +# Verify template deprecation allowlist was updated +if git diff origin/master..HEAD core-services/template-deprecation/_allowlist.yaml | grep -q "+"; then + echo "✓ Template deprecation allowlist updated" +else + echo "⚠ Warning: Template deprecation allowlist may not have been updated" +fi + +echo "==========================================" + +if [ $VERIFICATION_FAILED -eq 1 ]; then + echo "Verification FAILED" + exit 1 +fi + +echo "✓ Verification passed!" +exit 0 diff --git a/.claude/.claude-plugin/skills/post-branching/verify-fast-forward-job.sh b/.claude/.claude-plugin/skills/post-branching/verify-fast-forward-job.sh new file mode 100755 index 0000000000..4cf93f43c5 --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/verify-fast-forward-job.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# verify-fast-forward-job.sh +# Verifies that fast-forward job was updated correctly + +set -euo pipefail + +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " + echo "Example: $0 4.21 4.23 ../release" + exit 1 +fi + +CURRENT_RELEASE="$1" +XY_PLUS_2="$2" +RELEASE_REPO="$3" + +# Calculate X.Y+1 +XY_PLUS_1=$(echo "$CURRENT_RELEASE" | awk -F. '{printf "%d.%d", $1, $2+1}') + +INFRA_PERIODICS="$RELEASE_REPO/ci-operator/jobs/infra-periodics.yaml" + +echo "==========================================" +echo "Verifying fast-forward job update" +echo "==========================================" + +VERIFICATION_FAILED=0 + +# Verify the update was successful +if grep -A 10 "name: periodic-openshift-release-fast-forward" "$INFRA_PERIODICS" | \ + grep -q -- "--future-release=${XY_PLUS_2}"; then + echo "✓ --future-release updated to ${XY_PLUS_2}" +else + echo "✗ FAILED: --future-release not updated correctly" + VERIFICATION_FAILED=1 +fi + +# Verify old value is gone +if grep -A 10 "name: periodic-openshift-release-fast-forward" "$INFRA_PERIODICS" | \ + grep -q -- "--future-release=${XY_PLUS_1}"; then + echo "✗ FAILED: Old value ${XY_PLUS_1} still present" + VERIFICATION_FAILED=1 +else + echo "✓ Old value ${XY_PLUS_1} removed" +fi + +echo "==========================================" + +if [ $VERIFICATION_FAILED -eq 1 ]; then + echo "Verification FAILED" + exit 1 +fi + +echo "✓ Verification passed!" +exit 0 diff --git a/.claude/.claude-plugin/skills/post-branching/verify-image-mirroring-x-y-plus-2.sh b/.claude/.claude-plugin/skills/post-branching/verify-image-mirroring-x-y-plus-2.sh new file mode 100755 index 0000000000..f49f751925 --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/verify-image-mirroring-x-y-plus-2.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# verify-image-mirroring-x-y-plus-2.sh +# Verifies that image mirroring config was updated correctly + +set -euo pipefail + +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " + echo "Example: $0 4.22 4.23 ../release" + exit 1 +fi + +XY_PLUS_1="$1" +XY_PLUS_2="$2" +RELEASE_REPO="$3" + +IMAGE_MIRROR_CONFIG="$RELEASE_REPO/core-services/image-mirroring/openshift/_config.yaml" + +echo "==========================================" +echo "Verifying image mirroring config" +echo "==========================================" + +VERIFICATION_FAILED=0 + +# Verify base version section was added +if grep -q "\"${XY_PLUS_2}\":" "$IMAGE_MIRROR_CONFIG"; then + echo "✓ Base version \"${XY_PLUS_2}\" added" +else + echo "✗ FAILED: Base version \"${XY_PLUS_2}\" not found" + VERIFICATION_FAILED=1 +fi + +# Verify variant sections were added +VARIANTS=("sriov" "metallb" "ptp" "scos") +for variant in "${VARIANTS[@]}"; do + if grep -q "\"${variant}-${XY_PLUS_2}\":" "$IMAGE_MIRROR_CONFIG"; then + echo "✓ Variant \"${variant}-${XY_PLUS_2}\" added" + else + echo "✗ FAILED: Variant \"${variant}-${XY_PLUS_2}\" not found" + VERIFICATION_FAILED=1 + fi +done + +# Verify each section has the correct version tags +for prefix in "" "sriov-" "metallb-" "ptp-" "scos-"; do + key="${prefix}${XY_PLUS_2}" + if grep -q "\"${key}\":" "$IMAGE_MIRROR_CONFIG"; then + # Check if it has both version and version.0 tags + if grep -A 3 "\"${key}\":" "$IMAGE_MIRROR_CONFIG" | grep -q "\"${XY_PLUS_2}\"" && \ + grep -A 3 "\"${key}\":" "$IMAGE_MIRROR_CONFIG" | grep -q "\"${XY_PLUS_2}.0\""; then + echo "✓ \"${key}\" has correct version tags" + else + echo "⚠ Warning: \"${key}\" may have incorrect version tags" + fi + fi +done + +echo "==========================================" + +if [ $VERIFICATION_FAILED -eq 1 ]; then + echo "Verification FAILED" + exit 1 +fi + +echo "✓ Verification passed!" +exit 0 diff --git a/.claude/.claude-plugin/skills/post-branching/verify-imagestream-tags.sh b/.claude/.claude-plugin/skills/post-branching/verify-imagestream-tags.sh new file mode 100755 index 0000000000..13aa3e5dea --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/verify-imagestream-tags.sh @@ -0,0 +1,27 @@ +#!/bin/bash +set -euo pipefail + +[ "$#" -lt 3 ] && echo "Usage: $0 [is-prefix] [is-suffix]" && exit 1 + +OLD_VERSION="$1" +NEW_VERSION="$2" +NAMESPACE="$3" +IS_PREFIX="${4:-}" +IS_SUFFIX="${5:-}" + +OLD_IS="${IS_PREFIX}${OLD_VERSION}${IS_SUFFIX}" +NEW_IS="${IS_PREFIX}${NEW_VERSION}${IS_SUFFIX}" + +OLD_COUNT=$(oc --context=app.ci get is "$OLD_IS" -n "$NAMESPACE" -o json 2>/dev/null | jq '.status.tags | length' || echo "0") +NEW_COUNT=$(oc --context=app.ci get is "$NEW_IS" -n "$NAMESPACE" -o json 2>/dev/null | jq '.status.tags | length' || echo "0") + +echo "$NAMESPACE/$OLD_IS: $OLD_COUNT tags" +echo "$NAMESPACE/$NEW_IS: $NEW_COUNT tags" + +if [ "$OLD_COUNT" -eq "$NEW_COUNT" ] && [ "$NEW_COUNT" -gt 0 ]; then + echo "✓ Tag counts match" + exit 0 +else + echo "✗ Tag count mismatch or zero tags" + exit 1 +fi diff --git a/.claude/.claude-plugin/skills/post-branching/verify-jira-validation.sh b/.claude/.claude-plugin/skills/post-branching/verify-jira-validation.sh new file mode 100755 index 0000000000..36bc232b46 --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/verify-jira-validation.sh @@ -0,0 +1,76 @@ +#!/bin/bash +# verify-jira-validation.sh +# Verifies that Jira validation stanzas were added correctly + +set -euo pipefail + +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " + echo "Example: $0 4.21 4.23 ../release" + exit 1 +fi + +CURRENT_RELEASE="$1" +XY_PLUS_2="$2" +RELEASE_REPO="$3" + +# Calculate X.Y+3 +XY_PLUS_3=$(echo "$XY_PLUS_2" | awk -F. '{printf "%d.%d", $1, $2+1}') + +JIRA_CONFIG="$RELEASE_REPO/core-services/jira-lifecycle-plugin/config.yaml" + +echo "==========================================" +echo "Verifying Jira validation config" +echo "==========================================" + +VERIFICATION_FAILED=0 + +# Verify openshift-X.Y+2 stanza exists +if grep -q "openshift-${XY_PLUS_2}:" "$JIRA_CONFIG"; then + echo "✓ openshift-${XY_PLUS_2} stanza added" + + # Verify it has correct target_version + if grep -A 10 "openshift-${XY_PLUS_2}:" "$JIRA_CONFIG" | grep -q "target_version: ${XY_PLUS_2}.0"; then + echo "✓ openshift-${XY_PLUS_2} has correct target_version" + else + echo "✗ FAILED: openshift-${XY_PLUS_2} has incorrect target_version" + VERIFICATION_FAILED=1 + fi + + # Verify it has correct dependent_bug_target_versions + if grep -A 10 "openshift-${XY_PLUS_2}:" "$JIRA_CONFIG" | grep -q "${XY_PLUS_3}.0"; then + echo "✓ openshift-${XY_PLUS_2} has correct dependent_bug_target_versions (${XY_PLUS_3}.0)" + else + echo "✗ FAILED: openshift-${XY_PLUS_2} missing dependent_bug_target_versions" + VERIFICATION_FAILED=1 + fi +else + echo "✗ FAILED: openshift-${XY_PLUS_2} stanza not found" + VERIFICATION_FAILED=1 +fi + +# Verify release-X.Y+2 stanza exists +if grep -q "release-${XY_PLUS_2}:" "$JIRA_CONFIG"; then + echo "✓ release-${XY_PLUS_2} stanza added" + + # Verify it has correct target_version + if grep -A 10 "release-${XY_PLUS_2}:" "$JIRA_CONFIG" | grep -q "target_version: ${XY_PLUS_2}.0"; then + echo "✓ release-${XY_PLUS_2} has correct target_version" + else + echo "✗ FAILED: release-${XY_PLUS_2} has incorrect target_version" + VERIFICATION_FAILED=1 + fi +else + echo "✗ FAILED: release-${XY_PLUS_2} stanza not found" + VERIFICATION_FAILED=1 +fi + +echo "==========================================" + +if [ $VERIFICATION_FAILED -eq 1 ]; then + echo "Verification FAILED" + exit 1 +fi + +echo "✓ Verification passed!" +exit 0 diff --git a/.claude/.claude-plugin/skills/post-branching/verify-merge-blockers-job.sh b/.claude/.claude-plugin/skills/post-branching/verify-merge-blockers-job.sh new file mode 100755 index 0000000000..d617826853 --- /dev/null +++ b/.claude/.claude-plugin/skills/post-branching/verify-merge-blockers-job.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# verify-merge-blockers-job.sh +# Verifies that merge blockers job was updated correctly + +set -euo pipefail + +if [ "$#" -ne 3 ]; then + echo "Usage: $0 " + echo "Example: $0 4.21 4.23 ../release" + exit 1 +fi + +CURRENT_RELEASE="$1" +XY_PLUS_2="$2" +RELEASE_REPO="$3" + +# Calculate X.Y+1 +XY_PLUS_1=$(echo "$CURRENT_RELEASE" | awk -F. '{printf "%d.%d", $1, $2+1}') + +INFRA_PERIODICS="$RELEASE_REPO/ci-operator/jobs/infra-periodics.yaml" + +echo "==========================================" +echo "Verifying merge blockers job update" +echo "==========================================" + +VERIFICATION_FAILED=0 + +# Verify the update was successful +if grep -A 10 "name: periodic-openshift-release-merge-blockers" "$INFRA_PERIODICS" | \ + grep -q -- "--future-release=${XY_PLUS_2}"; then + echo "✓ --future-release updated to ${XY_PLUS_2}" +else + echo "✗ FAILED: --future-release not updated correctly" + VERIFICATION_FAILED=1 +fi + +# Verify old value is gone +if grep -A 10 "name: periodic-openshift-release-merge-blockers" "$INFRA_PERIODICS" | \ + grep -q -- "--future-release=${XY_PLUS_1}"; then + echo "✗ FAILED: Old value ${XY_PLUS_1} still present" + VERIFICATION_FAILED=1 +else + echo "✓ Old value ${XY_PLUS_1} removed" +fi + +echo "==========================================" + +if [ $VERIFICATION_FAILED -eq 1 ]; then + echo "Verification FAILED" + exit 1 +fi + +echo "✓ Verification passed!" +exit 0 diff --git a/.claude/commands/branching-day.md b/.claude/commands/branching-day.md new file mode 100644 index 0000000000..5e5232c224 --- /dev/null +++ b/.claude/commands/branching-day.md @@ -0,0 +1,321 @@ +--- +name: branching-day +description: Execute Branching Day tasks for OpenShift release - transition from Normal Development to Feature Freeze +usage: /branching-day +examples: + - /branching-day +--- + +# Branching Day Orchestration Instructions + +You are the orchestrator for OpenShift Branching Day. When this command is invoked, you will automatically determine the current release version from the 4-stable stream and guide the user through all the steps required to transition from Normal Development to Feature Freeze. + +## Your Role + +- **Verify branching readiness**: Check that at least 3 accepted nightlies exist for the target release +- **Fetch target release**: Extract version from periodic-prow-auto-config-brancher configuration +- **Calculate versions**: Current release (from config), Future release (current + 0.01) +- **Use TodoWrite**: Track all steps and mark them as you progress +- **Use AskUserQuestion**: Confirm prerequisites and manual steps +- **Invoke skills**: Call the automation scripts when appropriate +- **Guide the user**: Provide clear instructions for manual steps +- **Handle failures**: When skills fail verification, diagnose and help recover + +## Error Handling and Recovery + +When a skill fails verification (exits with non-zero code): + +1. **STOP the workflow immediately** - Do not proceed to the next step +2. **Analyze the verification output**: + - Read the verification section carefully + - Identify which specific check failed (✗ indicators) + - Understand what was expected vs. what actually happened +3. **Provide clear diagnosis to the user**: + - Explain what failed in plain language + - Show the relevant verification output + - Explain the impact (e.g., "Config files were not updated correctly") +4. **Suggest remediation**: + - **Option A - Automated fix**: If you can identify the issue, offer to: + - Manually inspect the files to diagnose the problem + - Fix the issue (e.g., run sed commands, edit files) + - Re-run the failed skill to verify the fix + - **Option B - Manual fix**: If the issue requires user intervention: + - Provide specific commands to investigate (e.g., `git diff`, `grep`) + - Explain what the user should look for + - Once fixed, offer to re-run the skill verification + - **Option C - Abort**: If the failure is critical or unclear: + - Suggest rolling back changes (`git reset --hard`) + - Recommend investigating root cause before retrying +5. **Re-run verification**: After fixing, always re-run the failed skill to confirm success +6. **Update TodoWrite**: Mark the task as still in_progress until verification passes + +### Common Failure Scenarios + +**Scenario 1: No files were modified** +- **Cause**: Tool didn't run correctly, wrong parameters, or files already up-to-date +- **Action**: Check tool output, verify parameters, inspect git status +- **Recovery**: Fix parameters and re-run + +**Scenario 2: Old values still present** +- **Cause**: sed regex didn't match, file format changed +- **Action**: Manually inspect file, adjust sed command +- **Recovery**: Run corrected sed command, re-run verification + +**Scenario 3: New values not found** +- **Cause**: Insertion logic failed, wrong location targeted +- **Action**: Check file structure, verify insertion point exists +- **Recovery**: Manually add missing content, re-run verification + +**Scenario 4: Partial success** +- **Cause**: Multi-step operation partially completed +- **Action**: Identify what succeeded and what failed +- **Recovery**: Complete only the failed parts, re-run full verification + +## What is Branching Day? + +**Branching Day** marks a major transition in the OpenShift release cycle: + +- **Before Branching Day:** X.Y development happens on `master` branch with relaxed merge criteria +- **After Branching Day:** + - X.Y development moves to `release-x.y` branches with stricter merge criteria (requires valid bugs and approvals) + - `master` branch opens for X.Y+1 development with relaxed merge criteria + +## Environment Setup + +Use these paths (from plugin.json config): +- `RELEASE_REPO`: ../release +- `CI_TOOLS_REPO`: . (current directory) + +## Branching Day Workflow + +### Prerequisites (Verify Before Starting) + +Use AskUserQuestion to confirm: +1. Exact date/time confirmed with management (usually 10 AM EST)? +2. 24h pre-notification email sent to aos-leads/devel? +3. 24h pre-notification posted to #announce-testplatform Slack? + +### Step 0: Determine Version and Build Tooling + +**First, verify branching readiness and get the target release version:** + +Invoke skill: `get-current-release` with args: `../release` + +This verifies that at least 3 accepted nightlies exist for the target release before proceeding. If verification fails, the workflow cannot continue until TRT creates more accepted nightlies. + +**Then, build the required tooling:** + +Invoke skill: `build-branching-tooling` with args: `. ` + +This will build all required tools: +- config-brancher +- tide-config-manager +- rpm-repo-mirroring-service +- ci-operator-config-mirror + +### Step 1: Fetch and Update Repositories + +Run these commands: +```bash +# Update ci-tools repo +git fetch upstream && git checkout master && git rebase -i upstream/main master + +# Update release repo +cd ../release && git fetch upstream && git checkout master && git rebase -i upstream/master master && cd - +``` + +### Step 2: Send Start Notifications + +Use AskUserQuestion to confirm: +- [ ] Email sent to aos-leads/devel: "Branching Day activities have started" +- [ ] Slack posted to #announce-testplatform: "OCP {FUTURE_RELEASE} Branching activities have started :openshift-intensifies:" + +### Step 3: Trigger Final Fast-Forward Job + +**Trigger fast-forward job via gangway:** + +Invoke skill: `trigger-periodic-jobs` with args: `--polling 20 periodic-openshift-release-fast-forward` + +This triggers the final fast-forward job before branching and waits up to 20 minutes for completion. + +**View job status:** https://prow.ci.openshift.org/?job=periodic-openshift-release-fast-forward + +Use AskUserQuestion to confirm job completed successfully + +### Step 4: Prepare Config Brancher PR + +**Run automation skills in sequence:** +1. Invoke skill: `create-branch-from-master` with args: `config-brancher- ../release --reset` +2. Invoke skill: `run-config-brancher` with args: ` ../release` +3. **Invoke skill: `verify-config-brancher` with args: ` ../release`** +4. **If verification fails: STOP, diagnose the issue, fix it (manually or with edits), then re-run `verify-config-brancher` until it passes** +5. Run: `cd ../release && make update` +6. Invoke skill: `update-infra-periodics` with args: ` ../release` +7. **Invoke skill: `verify-infra-periodics` with args: ` ../release`** +8. **If verification fails: STOP, diagnose the issue, fix it (manually or with edits), then re-run `verify-infra-periodics` until it passes** +9. Run: `cd ../release && make update` +10. Invoke skill: `commit-config-brancher-pr` with args: ` ../release` + +**Guide user for manual steps:** +```bash +cd ../release +git log --oneline origin/master..HEAD # Review commits +git push -u origin config-brancher-{FUTURE_RELEASE} +gh pr create --title "OCP {CURRENT_RELEASE} Branching Day: bump ci-operator configurations" --body "Branching Day: Bump CI operator configs for {FUTURE_RELEASE} + +This PR includes: + +- config-brancher output for {FUTURE_RELEASE} +- make update for generated files +- Bump periodic jobs (config-brancher and fast-forward) +- Bump versions in jira config" +``` + + +**Example PR:** https://github.com/openshift/release/pull/58981 + +### Step 5: Refresh Open PRs + +**Trigger periodic jobs via gangway:** + +Invoke skill: `trigger-periodic-jobs` with args: `--polling 20 periodic-bugzilla-refresh-main periodic-jira-refresh-main` + +These jobs revalidate all open PRs on master/main branches against the new target version. The skill will: +- Trigger both jobs via gangway +- Poll their status every 30 seconds +- Report success when both complete (20 minute timeout) +- Fail if either job fails + +**View job status:** https://prow.ci.openshift.org/?job=periodic-bugzilla-refresh-main +**View job status:** https://prow.ci.openshift.org/?job=periodic-jira-refresh-main + +### Step 6: Prepare Tide Config PR + +**Run automation skills in sequence:** +1. Invoke skill: `create-branch-from-master` with args: `tide-config- ../release --reset` +2. Invoke skill: `run-tide-config-manager` with args: `../release` +3. **Invoke skill: `verify-tide-config-manager` with args: `../release`** +4. **If verification fails: STOP, diagnose the issue, fix it (manually or with edits), then re-run `verify-tide-config-manager` until it passes** +5. Invoke skill: `update-tide-and-infra-jobs` with args: ` ../release` +6. **Invoke skill: `verify-tide-and-infra-jobs` with args: ` ../release`** +7. **If verification fails: STOP, diagnose the issue, fix it (manually or with edits), then re-run `verify-tide-and-infra-jobs` until it passes** +8. Invoke skill: `update-etcd-config` with args: ` ../release` +9. **Invoke skill: `verify-etcd-config` with args: ` ../release`** +10. **If verification fails: STOP, diagnose the issue, fix it (manually or with edits), then re-run `verify-etcd-config` until it passes** +11. Run: `cd ../release && make prow-config` +12. Invoke skill: `commit-tide-config-pr` with args: ` ../release` + +**Guide user for manual steps:** +```bash +cd ../release +git log --oneline origin/master..HEAD # Review commits +git push -u origin tide-config-{FUTURE_RELEASE} +gh pr create --title "OCP {CURRENT_RELEASE} Branching Day: Update Tide merge criteria and Infra jobs" --body "Update merge criteria for {FUTURE_RELEASE} and adjust Infra jobs accordingly. +- tide-config-manager executed for branching phase +- make prow-config executed +- Bump periodic-openshift-release-merge-blockers +- Bump periodic-ocp-build-data-enforcer +- etcd manual change" +``` + + +**Example PR:** https://github.com/openshift/release/pull/59015 + +### Step 7: Prepare Image Mirroring PR + +**Run automation skill:** +1. Invoke skill: `create-branch-from-master` with args: `image-mirroring- ../release --reset` +2. Invoke skill: `update-image-mirroring` with args: ` ../release` + +**Guide user for MANUAL file edit:** +Instruct user to edit: `../release/core-services/image-mirroring/openshift/_config.yaml` +- Remove "latest" from {CURRENT_RELEASE} buckets +- Add "latest" to {FUTURE_RELEASE} buckets +- Update ALL version buckets for current release and its variants (standard, sriov, metallb, ptp, scos) + +Use AskUserQuestion to confirm file edited. + +**Continue automation:** +1. Run: `cd ../release && make openshift-image-mirror-mappings` +2. Invoke skill: `commit-image-mirroring-pr` with args: ` ../release` + +**Guide user for manual steps:** +```bash +cd ../release +git log --oneline origin/master..HEAD # Review commits +git push -u origin image-mirroring-{FUTURE_RELEASE} +gh pr create --title "OCP {CURRENT_RELEASE} Branching Day: Update image mirror mappings" --body "Update image mirroring 'latest' tags for {FUTURE_RELEASE} +This PR includes: +- Updated _config.yaml to move 'latest' tags from {CURRENT_RELEASE} to {FUTURE_RELEASE} buckets +- Generated image mirror mappings via make openshift-image-mirror-mappings +``` + +Use AskUserQuestion to confirm: +- [ ] PR created and link provided? +- [ ] PR reviewed, approved, and merged? + +**Example PR:** https://github.com/openshift/release/pull/59017 + +### Step 8: Trigger Merge Blocker Job + +**Trigger merge blocker job via gangway:** + +Invoke skill: `trigger-periodic-jobs` with args: `periodic-openshift-release-merge-blockers` + +This job takes ~2 hours to complete. The skill will trigger it and return the execution ID immediately. + +**View job status:** https://prow.ci.openshift.org/?job=periodic-openshift-release-merge-blockers + +Use AskUserQuestion to confirm job completed before proceeding + +### Step 9: Create DPP Ticket + +Instruct user to: +1. Visit https://devservices.dpp.openshift.com/support/ (VPN required) +2. Create ticket requesting: + - New Target Release: {FUTURE_RELEASE}.0 in Bugzilla and Jira + - Previous z Target Release: {CURRENT_RELEASE}.z in Bugzilla and Jira + - New Version: {FUTURE_RELEASE} in Bugzilla and Jira +3. Reference previous ticket: https://issues.redhat.com/browse/DPP-10598 + +Use AskUserQuestion to confirm ticket created. + +### Step 10: Send Completion Notifications + +Use AskUserQuestion to confirm: +- [ ] Email sent to aos-leads/devel: + - Subject: "Branching activities completed" + - Body: "The Test Platform team has completed branching activities." +- [ ] Slack posted to #announce-testplatform: + - "OCP {FUTURE_RELEASE} Branching activities are now completed :openshifty: !" + +### Final Summary + +Display summary: +``` +Branching Day Complete! + +✓ Config Brancher PR: [link] +✓ Tide Config PR: [link] +✓ Image Mirroring PR: [link] +✓ Merge blocker job triggered and completed +✓ DPP ticket created +✓ Notifications sent + +OpenShift {CURRENT_RELEASE} → {FUTURE_RELEASE} branching complete! +``` + +## Important Notes + +- **Always use TodoWrite** to track progress through all steps +- **Use AskUserQuestion** for all confirmations and manual steps +- **Version is automatically determined** from periodic-prow-auto-config-brancher configuration +- **Branching readiness is verified** by checking for 3+ accepted nightlies +- **Calculate future version** automatically (current + 0.01) +- **Verify prerequisites** before starting any work +- **Wait for user confirmation** before proceeding to next major step +- **Provide PR links** from example PRs for reference + +## References + +- [Release Schedule](https://docs.google.com/spreadsheets/d/19cEcXH10gXgLMB98fCkQm-kB8xEHQQdKcXnPJiKQbwg/edit) diff --git a/.claude/commands/post-branching.md b/.claude/commands/post-branching.md new file mode 100644 index 0000000000..d400f84acd --- /dev/null +++ b/.claude/commands/post-branching.md @@ -0,0 +1,412 @@ +--- +name: post-branching +description: Execute Post-Branching tasks for OpenShift X.Y release - bootstrap config and content for X.Y+2 +usage: /post-branching +examples: + - /post-branching +--- + +# Post-Branching Orchestration Instructions + +You are the orchestrator for OpenShift Post-Branching tasks. When this command is invoked, you will automatically determine the current release version and guide the user through all the steps required to bootstrap configuration and content for X.Y+2. + +## Your Role + +- **Fetch current release**: Extract version from periodic-prow-auto-config-brancher configuration +- **Calculate versions**: Current release (from config), Future release X.Y+1 (current + 0.01), Bootstrap release X.Y+2 (current + 0.02), X.Y+3 (current + 0.03) +- **Use TodoWrite**: Track all 10 steps and mark them as you progress +- **Use AskUserQuestion**: Confirm prerequisites and manual steps +- **Invoke skills**: Call the automation scripts when appropriate +- **Guide the user**: Provide clear instructions for manual steps +- **Handle failures**: When skills fail verification, diagnose and help recover + +## Error Handling and Recovery + +When a skill fails verification (exits with non-zero code): + +1. **STOP the workflow immediately** - Do not proceed to the next step +2. **Analyze the verification output**: + - Read the verification section carefully + - Identify which specific check failed (✗ indicators) + - Understand what was expected vs. what actually happened +3. **Provide clear diagnosis to the user**: + - Explain what failed in plain language + - Show the relevant verification output + - Explain the impact (e.g., "Jira stanza missing target_version") +4. **Suggest remediation**: + - **Option A - Automated fix**: If you can identify the issue, offer to: + - Manually inspect the files to diagnose the problem + - Fix the issue (e.g., run sed commands, edit files) + - Re-run the failed skill to verify the fix + - **Option B - Manual fix**: If the issue requires user intervention: + - Provide specific commands to investigate (e.g., `git diff`, `grep`) + - Explain what the user should look for + - Once fixed, offer to re-run the skill verification + - **Option C - Abort**: If the failure is critical or unclear: + - Suggest rolling back changes (`git reset --hard`) + - Recommend investigating root cause before retrying +5. **Re-run verification**: After fixing, always re-run the failed skill to confirm success +6. **Update TodoWrite**: Mark the task as still in_progress until verification passes + +### Common Failure Scenarios + +**Scenario 1: Stanza not found in config** +- **Cause**: awk/sed insertion logic failed, previous stanza missing +- **Action**: Check config file structure, verify insertion point +- **Recovery**: Manually add missing stanza, re-run verification + +**Scenario 2: Version mismatch in updates** +- **Cause**: Wrong calculation of X.Y+1, X.Y+2, or X.Y+3 +- **Action**: Verify version arithmetic +- **Recovery**: Recalculate versions, re-run skill with correct values + +**Scenario 3: No config/job files created** +- **Cause**: config-brancher didn't run, tool missing, wrong path +- **Action**: Check tool exists, verify release repo path +- **Recovery**: Build tools, fix paths, re-run skill + +**Scenario 4: Image stream sections incomplete** +- **Cause**: One or more variants failed to add +- **Action**: Check which variants are missing +- **Recovery**: Manually add missing variants, re-run verification + +## What is Post-Branching? + +**Post-Branching** happens some time after the main branching is complete. Its purpose is to bootstrap all necessary configuration and infrastructure for the X.Y+2 release. + +## Environment Setup + +Use these paths: +- `RELEASE_REPO`: ../release +- `CI_TOOLS_REPO`: . (current directory) + +## Post-Branching Workflow Overview + +This workflow consists of **10 steps** that create **5 Pull Requests**: + +| Step | PR # | Configuration Update Skill | PR Commit Skill | Description | +|------|------|---------------------------|-----------------|-------------| +| 1 | PR #1 | `update-jira-validation-post-branching` | `commit-jira-validation-pr` | Configure Jira validation for X.Y+2 branches | +| 2 | PR #2 | `update-merge-blockers-job` | `commit-merge-blockers-pr` | Update merge blockers job to track X.Y+2 | +| 3 | - | `trigger-periodic-jobs` | - | Trigger merge blockers job immediately | +| 4 | PR #3 | `update-fast-forward-job` | `commit-fast-forward-pr` | Enable fast-forwarding for X.Y+2 branches | +| 5 | - | `tag-imagestreams` | `verify-imagestream-tags` | Tag OCP image streams | +| 6 | - | `tag-imagestreams` (5x) | `verify-imagestream-tags` (5x) | Tag Origin image streams (5 variants) | +| 7 | - | `tag-imagestreams` | `verify-imagestream-tags` | Tag OCP-private image streams | +| 8 | - | `mirror-imagestreams-to-quay` | - | Mirror all image streams to Quay (7 streams) | +| 9 | PR #4 | `create-config-jobs-x-y-plus-2` | `commit-ci-configs-jobs-pr` | Create CI operator configs and jobs for X.Y+2 | +| 10 | PR #5 | `update-auto-config-brancher-x-y-plus-2` | `commit-auto-config-brancher-pr` | Enable automatic config maintenance | + +**The 5 Pull Requests:** +1. **Jira Validation** - Configure validation criteria for openshift-X.Y+2 and release-X.Y+2 +2. **Merge Blockers** - Update periodic-openshift-release-merge-blockers job +3. **Fast-Forward** - Update periodic-openshift-release-fast-forward job +4. **CI Configs & Jobs** - Bootstrap complete CI infrastructure (most complex) +5. **Auto-Config-Brancher** - Update periodic-prow-auto-config-brancher job + +## Detailed Steps + +### Step 0: Determine Version and Build Tooling + +**First, get the current release version:** + +Invoke skill: `get-current-release` with args: `../release` + +This determines the current release version from the periodic-prow-auto-config-brancher configuration. + +**Then, build the required tooling:** + +Invoke skill: `build-branching-tooling` with args: `. ` + +This will build all required tools: +- config-brancher +- tide-config-manager +- rpm-repo-mirroring-service +- ci-operator-config-mirror + + +### Step 1: Configure Jira Validation for X.Y+2 Branches + +**Purpose:** Set up Jira validation criteria for openshift-X.Y+2 and release-X.Y+2 branches. + +**Run automation skills in sequence:** +1. Invoke skill: `create-branch-from-master` with args: `jira-validation- ../release --reset` +2. Invoke skill: `update-jira-validation-post-branching` with args: ` ../release` +3. **Invoke skill: `verify-jira-validation` with args: ` ../release`** +4. **If verification fails: STOP, diagnose the issue, fix it (manually or with edits), then re-run `verify-jira-validation` until it passes** +5. Invoke skill: `commit-jira-validation-pr` with args: ` ../release` + +**Expected changes in** `core-services/jira-lifecycle-plugin/config.yaml`: +```yaml +default: + ... + # Add the two stanzas below + openshift-X.Y+2: + dependent_bug_states: + - status: MODIFIED + - status: ON_QA + - status: VERIFIED + dependent_bug_target_releases: + - X.Y+3.0 + target_release: X.Y+2.0 + validate_by_default: true + release-X.Y+2: + dependent_bug_states: + - status: MODIFIED + - status: ON_QA + - status: VERIFIED + dependent_bug_target_releases: + - X.Y+3.0 + target_release: X.Y+2.0 + validate_by_default: true +``` + +**Guide user to push and create PR:** +```bash +cd ../release +git log --oneline origin/master..HEAD # Review commit +git push -u origin jira-validation-X.Y+2 +gh pr create --title "Post-Branching: Add Jira validation criteria for X.Y+2 branches" \ + --body "This PR adds Jira validation stanzas for: + - openshift-X.Y+2 + - release-X.Y+2 +Part of the post-branching process, step 1." +``` + +### Step 2: Update Merge Blockers Job to Track X.Y+2 + +**Purpose:** Configure periodic-openshift-release-merge-blockers to start maintaining blocker issues for release-X.Y+2 branches. + +**Run automation skills in sequence:** +1. Invoke skill: `create-branch-from-master` with args: `merge-blockers- ../release --reset` +2. Invoke skill: `update-merge-blockers-job` with args: ` ../release` +3. **Invoke skill: `verify-merge-blockers-job` with args: ` ../release`** +4. **If verification fails: STOP, diagnose the issue, fix it (manually or with edits), then re-run `verify-merge-blockers-job` until it passes** +5. Invoke skill: `commit-merge-blockers-pr` with args: ` ../release` + +**Expected change in** `ci-operator/jobs/infra-periodics.yaml`: +```yaml +name: periodic-openshift-release-merge-blockers + spec: + containers: + - args: + ... + - --current-release=X.Y+1 + - --future-release=X.Y+2 # Changed from X.Y+1 +``` + +**Guide user to push and create PR:** +```bash +cd ../release +git log --oneline origin/master..HEAD # Review commit +git push -u origin merge-blockers-X.Y+2 +gh pr create --title "Post-Branching: Start tracking merge blockers for X.Y+2 branches" \ + --body "This PR updates the periodic-openshift-release-merge-blockers job to track 4.23 branches. + Changes: + - Updated --future-release flag from X.Y+1 to X.Y+2 + Part of the post-branching process, step 2." +``` + + +### Step 3: Trigger Merge Blockers Job + +**Purpose:** After Step 2 PR merges, trigger the job to immediately establish X.Y+2 merge blockers. + +**Trigger merge blocker job via gangway:** + +Invoke skill: `trigger-periodic-jobs` with args: `periodic-openshift-release-merge-blockers` + +The skill will trigger the job and return the execution ID immediately. + +**View job status:** https://prow.ci.openshift.org/?job=periodic-openshift-release-merge-blockers + + +### Step 4: Update Fast-Forward Job for X.Y+2 + +**Purpose:** Once X.Y+2 merge blockers are in place, configure periodic-openshift-release-fast-forward to create and start fast-forwarding release-X.Y+2 branches. + +**Run automation skills in sequence:** +1. Invoke skill: `create-branch-from-master` with args: `fast-forward- ../release --reset` +2. Invoke skill: `update-fast-forward-job` with args: ` ../release` +3. **Invoke skill: `verify-fast-forward-job` with args: ` ../release`** +4. **If verification fails: STOP, diagnose the issue, fix it (manually or with edits), then re-run `verify-fast-forward-job` until it passes** +5. Invoke skill: `commit-fast-forward-pr` with args: ` ../release` + +**Expected change in** `ci-operator/jobs/infra-periodics.yaml`: +```yaml +name: periodic-openshift-release-fast-forward +spec: + containers: + - args: + ... + - --current-release=X.Y+1 + - --future-release=X.Y+2 # Changed from X.Y+1 +``` + +**Guide user to push and create PR:** +```bash +cd ../release +git log --oneline origin/master..HEAD # Review commit +git push -u origin fast-forward-X.Y+2 +gh pr create --title "Post-Branching: Start fast-forwarding X.Y+2 branches from master" \ + --body "This PR updates the periodic-openshift-release-fast-forward job to track X.Y+2 branches. +Changes: +- Updated --future-release flag from X.Y+1 to X.Y+2 +Part of the post-branching process, step 4." +``` + +### Step 5: Tag OCP Streams + +**Purpose:** Seed ocp namespace image streams for X.Y+2. + +**IMPORTANT:** This step requires cluster access (app.ci context)! + +Invoke skill: `tag-imagestreams` with args: ` ocp` + +Invoke skill: `verify-imagestream-tags` with args: ` ocp` + +**If verification fails: Re-run `tag-imagestreams`, then re-run `verify-imagestream-tags` until it passes** + + +### Step 6: Tag Origin Streams (Multiple Variants) + +**Purpose:** Seed origin namespace image streams for X.Y+2, including all variants. + +**Tag each variant:** + +Invoke skill: `tag-imagestreams` with args: ` origin` (standard) +Invoke skill: `tag-imagestreams` with args: ` origin sriov-` +Invoke skill: `tag-imagestreams` with args: ` origin ptp-` +Invoke skill: `tag-imagestreams` with args: ` origin metallb-` +Invoke skill: `tag-imagestreams` with args: ` origin scos-` + +**Verify each variant:** + +Invoke skill: `verify-imagestream-tags` with args: ` origin` (standard) +Invoke skill: `verify-imagestream-tags` with args: ` origin sriov-` +Invoke skill: `verify-imagestream-tags` with args: ` origin ptp-` +Invoke skill: `verify-imagestream-tags` with args: ` origin metallb-` +Invoke skill: `verify-imagestream-tags` with args: ` origin scos-` + +**If any verification fails: Re-run `tag-imagestreams` for that variant, then re-run `verify-imagestream-tags` until it passes** + + +### Step 7: Tag OCP-Private Streams + +**Purpose:** Seed ocp-private namespace image streams for X.Y+2. + +Invoke skill: `tag-imagestreams` with args: ` ocp-private '' -priv` + +Invoke skill: `verify-imagestream-tags` with args: ` ocp-private '' -priv` + +**If verification fails: Re-run `tag-imagestreams`, then re-run `verify-imagestream-tags` until it passes** + +### Step 8: Mirror Created Image Streams to Quay + +**Purpose:** Mirror all newly created X.Y+2 image streams to Quay registry. + +Invoke skill: `mirror-imagestreams-to-quay` with args: ` ../release` + +This mirrors all 7 image streams (with automatic retry on failure, up to 3 attempts per stream): +- ocp/X.Y+2 +- origin/X.Y+2 (+ 4 variants: sriov, scos, ptp, metallb) +- ocp-private/X.Y+2-priv + + +### Step 9: Create CI Operator Configs and Jobs for X.Y+2 + +**Purpose:** Generate CI operator configuration files and Prow jobs for X.Y+2 branches. + +**IMPORTANT:** This is a complex step. Use previous PR as reference (example: 4.11 PR). + +**Run automation skills in sequence:** +1. Invoke skill: `create-branch-from-master` with args: `ci-configs- ../release --reset` +2. Invoke skill: `create-config-jobs-x-y-plus-2` with args: ` ../release` +3. **Invoke skill: `verify-config-jobs-x-y-plus-2` with args: ` ../release`** +4. **If verification fails: STOP, diagnose the issue, fix it (manually or with edits), then re-run `verify-config-jobs-x-y-plus-2` until it passes** + +This will: +1. Run config-brancher to create X.Y+2 config files +2. Run ci-operator-config-mirror for openshift-priv org +3. Generate vanilla jobs +4. Copy job customization from master/main to release-X.Y+2 +5. Update the rpm dependency +6. Create commits and branch for the PR + +**Guide user to push and create PR:** +```bash +cd ../release +git log --oneline origin/master..HEAD # Review commits +git push -u origin ci-configs-X.Y+2 +gh pr create --title "Post-Branching: Generate ci-operator configs and jobs" \ + --body "Generate X.Y+2 configuration files with config-brancher +- Create X.Y+2 configs for openshift-priv org +- Generate vanilla jobs for X.Y+2 +- Add rpm repository files for X.Y+2 +- Carry job customization over from master/main jobs +- Part of the post-branching process, step 9. +``` + +### Step 10: Update Auto-Config-Brancher to Maintain X.Y+2 + +**Purpose:** After Step 9 PR merges, configure periodic-prow-auto-config-brancher to automatically maintain X.Y+2 CI configuration files. + +**Run automation skills in sequence:** +1. Invoke skill: `create-branch-from-master` with args: `auto-config-brancher- ../release --reset` +2. Invoke skill: `update-auto-config-brancher-x-y-plus-2` with args: ` ../release` +3. **Invoke skill: `verify-auto-config-brancher` with args: ` ../release`** +4. **If verification fails: STOP, diagnose the issue, fix it (manually or with edits), then re-run `verify-auto-config-brancher` until it passes** +5. Invoke skill: `commit-auto-config-brancher-pr` with args: ` ../release` + +**Expected change in** `ci-operator/jobs/infra-periodics.yaml`: +```yaml +name: periodic-prow-auto-config-brancher +spec: + containers: + - args: + ... + - --current-release=X.Y+1 + - --future-release=X.Y+2 +``` + +**Guide user to push and create PR:** +```bash +cd ../release +git log --oneline origin/master..HEAD # Review commit +git push -u origin auto-config-brancher-X.Y+2 +gh pr create --title "Post-Branching: Updating periodic-prow-auto-config-brancher" \ + --body "This updates the periodic-prow-auto-config-brancher job to automatically maintain CI configuration files for the X.Y+2 release. +Part of the post-branching process, step 10." +``` + +### Final Summary + +Display summary: +``` +Post-Branching Day Complete! (10 Steps) + +✓ Step 1: Jira validation configured for X.Y+2 +✓ Step 2: Merge blockers job updated for X.Y+2 +✓ Step 3: Merge blockers job triggered +✓ Step 4: Fast-forward job configured for X.Y+2 +✓ Step 5: OCP image streams tagged +✓ Step 6: Origin image streams tagged (5 variants) +✓ Step 7: OCP-private image streams tagged +✓ Step 8: All image streams mirrored to Quay (7 streams) +✓ Step 9: CI operator configs and jobs created for X.Y+2 +✓ Step 10: Auto-config-brancher updated + +All PRs: +1. Jira validation: [link] +2. Merge blockers: [link] +3. Fast-forward: [link] +4. CI configs and jobs: [link] +5. Auto-config-brancher: [link] + +OpenShift X.Y+2 infrastructure bootstrapped successfully! +``` + +## References + +- [OpenShift CI Documentation](https://docs.ci.openshift.org/) +- [Release Schedule Spreadsheet](https://docs.google.com/spreadsheets/d/19cEcXH10gXgLMB98fCkQm-kB8xEHQQdKcXnPJiKQbwg/edit)