Skip to content

Commit

Permalink
Merge pull request kubernetes#139 from chiukapoor/release-sync-automa…
Browse files Browse the repository at this point in the history
…tion

Automate creation of new ingress-nginx release branches, cherry-pick commits, CI, and push tags
  • Loading branch information
kinarashah authored Oct 9, 2024
2 parents 8e5e8be + c2c72fa commit fdc6ba2
Show file tree
Hide file tree
Showing 3 changed files with 309 additions and 0 deletions.
135 changes: 135 additions & 0 deletions .github/workflows/upstream-release-sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
name: Sync with upstream ingress-nginx releases and cherry-pick Rancher-specific changes

on:
schedule:
- cron: "0 0 * * *" # Runs daily at midnight
workflow_dispatch:

jobs:
create-branches:
runs-on: ubuntu-latest
outputs:
new-release-branches: ${{ steps.create-release-branches.outputs.NEW_RELEASE_BRANCHES }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
path: 'rancher-ingress-nginx'
fetch-depth: 0
fetch-tags: true

- name: Configure git user
run: |
echo "[INFO] Setting up git user in git repository."
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
- name: Fetch the new tags from kubernetes/ingress-nginx repository
run: |
cd rancher-ingress-nginx
$GITHUB_WORKSPACE/rancher-ingress-nginx/scripts/check-for-new-tag.sh
- name: Create new release branches in rancher/ingress-nginx
id: create-release-branches
run: |
cd rancher-ingress-nginx
$GITHUB_WORKSPACE/rancher-ingress-nginx/scripts/create-release-branch.sh
- name: 'Tar files'
run: |
tar -czf rancher-ingress-nginx.tar.gz -C rancher-ingress-nginx .
- name: Push git repo to artifacts
uses: actions/upload-artifact@v4
with:
name: git-repo
path: rancher-ingress-nginx.tar.gz

build-and-validate:
needs: create-branches
runs-on: runs-on,runner=4cpu-linux-x64,run-id=${{ github.run_id }}
container:
image: rancher/dapper:v0.6.0
permissions:
contents: write
strategy:
matrix:
branches: ${{ fromJSON(needs.create-branches.outputs.new-release-branches) }}
fail-fast: false
steps:
- name: Fix the not-a-git-repository issue
run: |
apk -U add git
git config --global --add safe.directory "$GITHUB_WORKSPACE"
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --global user.name "github-actions[bot]"
- name: Checkout repository with branch ${{ matrix.branches }}
uses: actions/checkout@v4
with:
ref: ${{ matrix.branches }}

- name: Download git repo from artifact
uses: actions/download-artifact@v4
with:
name: git-repo

- name: Extract Artifact
run: |
tar -zxf rancher-ingress-nginx.tar.gz
rm rancher-ingress-nginx.tar.gz
- name: Read App Secrets
uses: rancher-eio/read-vault-secrets@main
with:
secrets: |
secret/data/github/repo/${{ github.repository }}/github/app-credentials appId | APP_ID ;
secret/data/github/repo/${{ github.repository }}/github/app-credentials privateKey | PRIVATE_KEY
- name: Create App Token
uses: actions/create-github-app-token@v1
id: app-token
with:
app-id: ${{ env.APP_ID }}
private-key: ${{ env.PRIVATE_KEY }}

- name: Validate with Dapper for ${{ matrix.branches }}
run: dapper validate

- name: Build with Dapper for ${{ matrix.branches }}
run: |
git stash --all
dapper build
- name: Push release tag for ${{ matrix.branches }}
run: |
# To stash any changes created by dapper CI run
git stash --all
if ! $(git push --quiet --no-progress origin $RELEASE_BRANCH > /dev/null); then
echo "[ERROR] Failed while pushing the branch $RELEASE_BRANCH to rancher repository."
exit 1
else
echo "[INFO] Successfully pushed branch $RELEASE_BRANCH: https://github.com/rancher/ingress-nginx/tree/$RELEASE_BRANCH"
fi
# Remove the '-fix' suffix to create the tag name
TAG="${RELEASE_BRANCH%-fix*}"
TAG="$TAG-rancher1"
echo "[INFO] Creating the tag: $TAG for branch: $RELEASE_BRANCH"
# Create the tag
if ! git tag "$TAG" "$RELEASE_BRANCH"; then
echo "[ERROR] Failed while creating the tag $TAG in the repository."
exit 1
fi
# Push the tag to origin
if ! git push origin "$TAG"; then
echo "[ERROR] Failed while pushing the tag $TAG to the repository."
exit 1
else
echo "[INFO] Successfully pushed tag $TAG: https://github.com/rancher/ingress-nginx/releases/tag/$TAG"
fi
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
RELEASE_BRANCH: ${{ matrix.branches }}
76 changes: 76 additions & 0 deletions scripts/check-for-new-tag.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/bin/bash

set -e

new_tags=()

# Define temporary files
rancher_tags_file=$(mktemp -p /tmp)
upstream_tags_file=$(mktemp -p /tmp)

# Fetch tags from the rancher/ingress-nginx repository and save to a temp file
git for-each-ref --sort='-creatordate' --format '%(refname:short)' refs/tags | grep rancher | head -n 10 > "$rancher_tags_file"

echo "[INFO] Setting up git kubernetes/ingress-nginx upstream in rancher/ingress-nginx git repository."
# Add upstream remote if not already added
if ! git remote get-url upstream &>/dev/null; then
git remote add "upstream" https://github.com/kubernetes/ingress-nginx.git
fi

# Fetch upstream tags
git fetch --tags --quiet upstream || true

# Fetch tags from the upstream kubernetes/ingress-nginx repository and save to a temp file
git for-each-ref --sort='-creatordate' --format '%(refname:short)' refs/tags | grep controller | head -n 5 | awk '{gsub(/controller-v/, ""); print $0}'> "$upstream_tags_file"

# Check if upstream_tags_file is empty
if [ ! -s "$upstream_tags_file" ]; then
echo "[ERROR] Could not get tags from kubernetes/ingress-nginx."
cat $upstream_tags_file
rm -f "$rancher_tags_file" "$upstream_tags_file"
exit 1
fi

# Process each tag
while read -r tag; do
# Skip tags with "rc", "alpha", or "beta"
if [[ "$tag" == *"rc"* || "$tag" == *"alpha"* || "$tag" == *"beta"* ]]; then
continue
fi

# Check if the tag already exists in the rancher repository
if grep -q "${tag}" "$rancher_tags_file"; then
continue
else
# Check if the tag has a newer patch release already available
latest_patch_in_rancher=$(grep "$(echo "${tag}" | cut -d '.' -f 1,2)" "$rancher_tags_file" | head -n 1)
latest_patch_in_rancher=${latest_patch_in_rancher#nginx-}
latest_patch_in_rancher=${latest_patch_in_rancher%-rancher*}
if [ "$(printf '%s\n' "${tag}" "${latest_patch_in_rancher}" | sort -V | tail -n 1)" = "${tag}" ]; then
new_tags+=( "${tag}" )
fi
fi
done < "$upstream_tags_file"

# In-place reverse so that the latest ingress-nginx version is processed last and stays latest as per the tagged date time.
for (( i=0, j=${#new_tags[@]}-1; i<j; i++, j-- )); do
temp="${new_tags[i]}"
new_tags[i]="${new_tags[j]}"
new_tags[j]="$temp"
done

# Print the new tags
if [ ${#new_tags[@]} -eq 0 ]; then
echo "[ERROR] No new tags found in upstream kubernetes/ingress-nginx."
exit 1
else
echo "[INFO] New tags to create branches in rancher/ingress-nginx:"
for tag in "${new_tags[@]}"; do
echo "- $tag"
done
fi

echo "NEW_TAGS=${new_tags[@]}" >> $GITHUB_ENV

# Clean up temporary files
rm -f "$rancher_tags_file" "$upstream_tags_file"
98 changes: 98 additions & 0 deletions scripts/create-release-branch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#!/bin/bash

set -e

NEW_RELEASE_BRANCHES=()

# Define temporary files
rancher_tags_file=$(mktemp -p /tmp)

# Cherry pick label
cherry_pick_label="(cherry-pick)"

# Extract the latest tag from rancher/ingress-nginx
git for-each-ref --sort='-creatordate' --format '%(refname:short)' refs/tags | grep rancher > "$rancher_tags_file"

# Check if upstream_tags_file is empty
if [ ! -s "$rancher_tags_file" ]; then
echo "[ERROR] No tags found in rancher/ingress-nginx."
rm -f "$rancher_tags_file"
exit 1
fi

# Process each tag
for tag in $NEW_TAGS; do
echo "========================================================================================"
echo "[INFO] Processing version: ${tag}"

# Check if the branch already exist
if git show-ref --verify --quiet refs/remotes/origin/nginx-${tag}-fix; then
echo "[WARN] Branch nginx-${tag}-fix already exist. Skipping the version ${tag}."
continue
fi

if ! $(git checkout -qb "nginx-${tag}-fix" controller-v$tag); then
echo "[WARN] Could not checkout a local branch release-${tag} from the upstream tag ${tag}."
continue
fi
echo "[INFO] Checkout to a local branch nginx-${tag}-fix from the upstream tag controller-v$tag."


# Extract major and minor version from the tag
major_minor=$(echo "${tag}" | cut -d '.' -f 1,2)

# Try to find the latest tag with the same major and minor version
last_latest_tag=$(grep "${major_minor}" "$rancher_tags_file" | head -1)

# If not found, look for the previous minor version
if [ -z "$last_latest_tag" ]; then
major_minor=$(echo "${major_minor}" | awk -F. '{print $1 "." $2-1}')
last_latest_tag=$(grep "${major_minor}" "$rancher_tags_file" | head -1)
fi
echo "[INFO] Latest ingress-nginx version in rancher/ingress-nginx prior ${tag}: ${last_latest_tag}"

# List of commits to cherry pick
cherry_pick_commits=$(git log --reverse ${last_latest_tag} --grep="^${cherry_pick_label}" --pretty=format:"%H")

if [ -z "$cherry_pick_commits" ]; then
echo "[WARN] No commit found with label ${cherry_pick_label} in tag ${last_latest_tag}. Skipping the version ${tag}"
continue
fi

FAIL=0
# Cherry-pick all commits before the user's commit
for commit in $cherry_pick_commits; do
echo "[INFO] Cherry pick commit: $commit to branch: nginx-${tag}-fix"
if ! git cherry-pick "$commit" > /dev/null; then
echo "[WARN] Failed during cherry-pick of commit $commit in branch nginx-${tag}-fix. Skipping the version ${tag}."
FAIL=1
break
fi
done

if [[ $FAIL == 0 ]]; then
echo "[INFO] Cherry pick completed successfully."
NEW_RELEASE_BRANCHES+=( "nginx-${tag}-fix" )
else
git cherry-pick --abort
fi
done

echo "========================================================================================"

# Print the new branches
if [ ${#NEW_RELEASE_BRANCHES[@]} -eq 0 ]; then
echo "[ERROR] No new release branches."
exit 1
else
echo "[INFO] New release branches:"
for branch in "${NEW_RELEASE_BRANCHES[@]}"; do
echo "- $branch"
done
fi

# Convert NEW_RELEASE_BRANCHES array to JSON string
echo "NEW_RELEASE_BRANCHES=$(printf '%s\n' "${NEW_RELEASE_BRANCHES[@]}" | awk '{printf "\"%s\",", $0}' | sed 's/,$/]/' | sed 's/^/[/' )" >> $GITHUB_OUTPUT

# Clean up temporary files
rm -f "$rancher_tags_file"

0 comments on commit fdc6ba2

Please sign in to comment.