diff --git a/.github/pr-consumer-config.yaml b/.github/pr-consumer-config.yaml new file mode 100644 index 0000000..d16f0f3 --- /dev/null +++ b/.github/pr-consumer-config.yaml @@ -0,0 +1,13 @@ +# Configuration for send-pr-to-consumer action +version_mapping_type: major + +version_branch_map: + "0": + - "main" + - "dev-v2.14" + - "dev-v2.13" + - "dev-v2.12" + +target: + repo: "rancher/rancher" + update_script: "./.github/scripts/update-build-yaml.sh" diff --git a/.github/scripts/update-build-yaml.sh b/.github/scripts/update-build-yaml.sh new file mode 100755 index 0000000..19d3944 --- /dev/null +++ b/.github/scripts/update-build-yaml.sh @@ -0,0 +1,120 @@ +#!/usr/bin/env bash +# Updates defaultSccOperatorImage in build.yaml to the specified tag. +# +# This script is called by the rancher/ecm-distro-tools create-pr action to +# update the SCC Operator image version in rancher/rancher's build.yaml file +# and regenerate any dependent code. +# +# Required env vars: +# TAG - SCC Operator tag (e.g. v0.4.2) +# RANCHER_DIR - Path to rancher/rancher clone +# +# Optional env vars (provided by PRBUILDER): +# PRBUILDER_TAG - The release tag (e.g., "v0.4.2") +# PRBUILDER_VERSION - Parsed version based on version_mapping_type +# PRBUILDER_TARGET_DIR - Absolute path to the cloned target repository +# PRBUILDER_TARGET_REPO - Target repository in "owner/repo" format +# PRBUILDER_TARGET_BRANCH - Target branch being updated (e.g., "dev-v2.14") +# PRBUILDER_SOURCE_DIR - Absolute path to the source repository + +set -euo pipefail + +# ============================================================================= +# ENVIRONMENT SETUP +# ============================================================================= + +# Use PRBUILDER_* variables if available, fall back to legacy names +TAG=${TAG:-${PRBUILDER_TAG}} +RANCHER_DIR=${RANCHER_DIR:-${PRBUILDER_TARGET_DIR}} +TARGET_BRANCH=${PRBUILDER_TARGET_BRANCH:-unknown} # For error message context only + +# ============================================================================= +# UTILITY FUNCTIONS +# ============================================================================= + +summary() { + if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then + echo "$@" >> "$GITHUB_STEP_SUMMARY" + fi + echo "$@" +} + +require_var() { + local var="$1" + if [ -z "${!var:-}" ]; then + echo "ERROR: $var is required" >&2 + exit 1 + fi +} + +require_binary() { + local bin="$1" + if ! command -v "$bin" &> /dev/null; then + echo "ERROR: Required binary '$bin' not found in PATH" >&2 + exit 1 + fi +} + +# ============================================================================= +# PREFLIGHT CHECKS +# ============================================================================= + +# Check required binaries +require_binary yq +require_binary grep +require_binary sed + +# Check required environment variables +require_var TAG + +require_var RANCHER_DIR +if [ ! -d "$RANCHER_DIR" ]; then + echo "ERROR: RANCHER_DIR '$RANCHER_DIR' does not exist" >&2 + exit 1 +fi + +# Check that build.yaml exists +BUILD_YAML="$RANCHER_DIR/build.yaml" +if [ ! -f "$BUILD_YAML" ]; then + echo "ERROR: build.yaml not found at $BUILD_YAML" >&2 + exit 1 +fi + +# ============================================================================= +# UPDATE BUILD.YAML +# ============================================================================= + +# Remove leading 'v' if present for consistency +TAG_NO_V="${TAG#v}" + +# Update the defaultSccOperatorImage field using yq for safe YAML editing +yq eval ".defaultSccOperatorImage = \"rancher/scc-operator:v${TAG_NO_V}\"" -i "$BUILD_YAML" + +summary " - Updated build.yaml: \`defaultSccOperatorImage: rancher/scc-operator:v${TAG_NO_V}\`" + +# ============================================================================= +# RUN GO GENERATE +# ============================================================================= + +# Check that generate.go exists +GENERATE_FILE="$RANCHER_DIR/generate.go" +if [ ! -f "$GENERATE_FILE" ]; then + summary " ⚠️ generate.go not found in branch '$TARGET_BRANCH' - cannot proceed" + exit 1 +fi + +# Extract first //go:generate directive +GENERATE_CMD=$(grep -m 1 '^//go:generate' "$GENERATE_FILE" | sed 's|^//go:generate ||') +if [ -z "$GENERATE_CMD" ]; then + summary " ⚠️ No go:generate directive found in generate.go on branch '$TARGET_BRANCH' - cannot proceed" + exit 1 +fi + +# Run the generate command +summary " - Running: \`$GENERATE_CMD\`" +if ! (cd "$RANCHER_DIR" && eval "$GENERATE_CMD"); then + summary " ⚠️ go generate failed on branch '$TARGET_BRANCH'" + exit 1 +fi + +summary " ✓ Successfully updated SCC Operator to v${TAG_NO_V}" \ No newline at end of file diff --git a/.github/workflows/push-to-rancher.yml b/.github/workflows/push-to-rancher.yml new file mode 100644 index 0000000..97a165d --- /dev/null +++ b/.github/workflows/push-to-rancher.yml @@ -0,0 +1,54 @@ +name: Push to rancher/rancher + +on: + workflow_dispatch: + inputs: + tag: + description: 'SCC Operator tag to sync (e.g. v0.4.2-rc.1)' + required: true + type: string + workflow_call: + inputs: + tag: + description: 'SCC Operator tag to sync' + required: true + type: string + +jobs: + push-to-rancher: + name: Push to rancher/rancher + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + container: + image: ghcr.io/rancher/ci-image/go1.25 + steps: + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Read GitHub App Credentials from Vault + if: github.repository == 'rancher/scc-operator' + uses: rancher-eio/read-vault-secrets@0da85151ad1f19ed7986c41587e45aac1ace74b6 # v3 + with: + secrets: | + secret/data/github/repo/${{ github.repository }}/github/app-credentials appId | APPID; + secret/data/github/repo/${{ github.repository }}/github/app-credentials privateKey | PRIVATEKEY + + - name: Generate GitHub App Token + if: github.repository == 'rancher/scc-operator' + id: generate_token + uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + with: + app-id: ${{ env.APPID }} + private-key: ${{ env.PRIVATEKEY }} + owner: ${{ github.repository_owner }} + repositories: rancher + + - name: Create PRs to rancher/rancher + if: github.repository == 'rancher/scc-operator' + uses: rancher/ecm-distro-tools/actions/create-pr@master + with: + tag: ${{ inputs.tag }} + config-file: .github/pr-consumer-config.yaml + github-token: ${{ steps.generate_token.outputs.token }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a7dfbdd..d6b59bc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -129,9 +129,18 @@ jobs: name: Un-draft release runs-on: ubuntu-latest needs: [ ci, goreleaser, image ] + outputs: + is_stable: ${{ steps.semver_check.outputs.HAS_PRERELEASE == 'false' }} permissions: contents: write steps: + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Check SemVer Characteristics + id: semver_check + run: bash ./.github/scripts/check-semver "${{ github.ref_name }}" >> "$GITHUB_OUTPUT" + - name: Fully publish release (retry until visible) env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -139,7 +148,7 @@ jobs: run: | set -euo pipefail tag="${{ github.ref_name }}" - + for i in {1..12}; do if gh release view -R "${{ github.repository }}" "$tag" >/dev/null 2>&1; then gh release edit -R "${{ github.repository }}" "$tag" --draft=false @@ -148,6 +157,14 @@ jobs: echo "Release '$tag' not found yet (attempt $i/12). Sleeping 10s..." sleep 10 done - + echo "Release '$tag' still not found after retries; failing." exit 1 + + push-to-rancher: + name: Push to rancher/rancher + needs: [ release ] + if: ${{ github.repository == 'rancher/scc-operator' && needs.release.outputs.is_stable == 'true' }} + uses: ./.github/workflows/push-to-rancher.yml + with: + tag: ${{ github.ref_name }}