[Hotfix] [SCFD-5640] Separating the time averaged output from non time averaged ones in translated JSON (#1263) #118
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Create Hotfix PR | |
| on: | |
| pull_request: | |
| types: | |
| - closed # Trigger when a PR is closed | |
| branches: | |
| - 'release-candidate/*' # Trigger for any branch starting with 'release-candidate/' | |
| jobs: | |
| create_hotfix_pr: | |
| # Only run this job if the PR was actually merged | |
| if: github.event.pull_request.merged == true | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write # To push branches and commit changes | |
| pull-requests: write # To create the pull request | |
| env: | |
| BOT_NAME: "flow360-auto-hotfix-bot" # Name for the git committer | |
| BOT_EMAIL: "[email protected]" # Email for the git committer | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Configure Git | |
| run: | | |
| git config user.name "${{ env.BOT_NAME }}" | |
| git config user.email "${{ env.BOT_EMAIL }}" | |
| - name: Get Merged Commit SHA (Assuming Squash Merge) | |
| id: get_commit | |
| # This SHA reliably points to the single commit if squash-and-merge was used. | |
| # If using merge commits, this SHA points to the merge commit itself, | |
| # which might be harder to cherry-pick cleanly. | |
| run: | | |
| echo "sha=${{ github.event.pull_request.merge_commit_sha }}" >> $GITHUB_OUTPUT | |
| echo "branch_name=${{ github.event.pull_request.head.ref }}" >> $GITHUB_OUTPUT | |
| echo "base_branch=${{ github.event.pull_request.base.ref }}" >> $GITHUB_OUTPUT | |
| - name: Get Hotfix Target Branches | |
| id: get_target_branches | |
| run: | | |
| PR_BASE_BRANCH="${{ steps.get_commit.outputs.base_branch }}" | |
| echo "PR was merged into: $PR_BASE_BRANCH" | |
| TARGET_BRANCHES=("main") # Always target main for hotfix | |
| # Get all remote 'release-candidate' branches with version pattern as YY.I or YY.II | |
| ALL_RELEASE_CANDIDATE_BRANCHES=$(git branch -r | grep 'origin/release-candidate/' | sed 's/.*origin\///' | grep -E '^release-candidate/[0-9]{2}\.[0-9]{1,2}$' | sort -V) | |
| echo "Found release-candidate branches: $ALL_RELEASE_CANDIDATE_BRANCHES" | |
| # Determine the version of the current PR's base branch | |
| # Example: release-candidate/25.5 -> 25.05 (for proper numerical comparison) | |
| PR_BASE_VERSION=$(echo "$PR_BASE_BRANCH" | sed -n 's/release-candidate\/\([0-9]\{2\}\)\.\([0-9]\{1,2\}\)/\1.\2/p') | |
| # Handle cases like 25.5 vs 25.05 for comparison | |
| if [[ "$PR_BASE_VERSION" =~ ^[0-9]{2}\.[0-9]$ ]]; then | |
| PR_BASE_VERSION=$(echo "$PR_BASE_VERSION" | awk '{printf "%s%02d", substr($1,1,3), substr($1,4)}') | |
| fi | |
| if [[ -n "$PR_BASE_VERSION" ]]; then | |
| echo "Base branch version: $PR_BASE_VERSION" | |
| for branch in $ALL_RELEASE_CANDIDATE_BRANCHES; do | |
| # Extract version for comparison | |
| BRANCH_VERSION=$(echo "$branch" | sed -n 's/release-candidate\/\([0-9]\{2\}\)\.\([0-9]\{1,2\}\)/\1.\2/p') | |
| if [[ -n "$BRANCH_VERSION" ]]; then | |
| if [[ "$BRANCH_VERSION" =~ ^[0-9]{2}\.[0-9]$ ]]; then | |
| BRANCH_VERSION=$(echo "$BRANCH_VERSION" | awk '{printf "%s%02d", substr($1,1,3), substr($1,4)}') | |
| fi | |
| # Compare versions | |
| if (( $(echo "$BRANCH_VERSION > $PR_BASE_VERSION" | bc -l) )); then | |
| TARGET_BRANCHES+=("$branch") | |
| echo "Adding $branch (version $BRANCH_VERSION) as it's higher than $PR_BASE_BRANCH (version $PR_BASE_VERSION)" | |
| fi | |
| fi | |
| done | |
| fi | |
| # Prepare output for next step | |
| HOTFIX_BRANCHES_JSON=$(printf '%s\n' "${TARGET_BRANCHES[@]}" | jq -R . | jq -s .) | |
| DELIMITER=$(uuidgen) # Generate a unique delimiter | |
| echo "HOTFIX_BRANCHES<<$DELIMITER" >> $GITHUB_OUTPUT | |
| echo "$HOTFIX_BRANCHES_JSON" >> $GITHUB_OUTPUT | |
| echo "$DELIMITER" >> $GITHUB_OUTPUT | |
| echo "Calculated hotfix target branches: ${TARGET_BRANCHES[@]}" | |
| - name: Define Branch Names | |
| id: define_branches | |
| run: | | |
| ORIGINAL_PR_NUMBER=${{ github.event.pull_request.number }} | |
| # Convert JSON array to space-separated list | |
| BRANCHES=$(echo '${{ steps.get_target_branches.outputs.HOTFIX_BRANCHES }}' | jq -r '.[]') | |
| # Create outputs for all branches | |
| branch_list="" | |
| for branch in $BRANCHES; do | |
| new_branch="hotfix-${branch//\//-}-pr${ORIGINAL_PR_NUMBER}" # Replace '/' with '-' for new branch name | |
| branch_list+="${branch}:${new_branch} " | |
| done | |
| # Remove trailing space and store the list | |
| branch_list="${branch_list% }" | |
| echo "branch_pairs=${branch_list}" >> $GITHUB_OUTPUT | |
| - name: Create and Process Hotfix Branches | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PR_TITLE: ${{ github.event.pull_request.title }} | |
| run: | | |
| # Read branch pairs and process each one | |
| IFS=' ' read -r -a PAIRS <<< "${{ steps.define_branches.outputs.branch_pairs }}" | |
| for pair in "${PAIRS[@]}"; do | |
| IFS=':' read -r base_branch new_branch <<< "$pair" | |
| echo "Processing hotfix for branch: $base_branch" | |
| # Create and switch to new branch | |
| git checkout "$base_branch" | |
| git pull origin "$base_branch" | |
| git checkout -b "$new_branch" | |
| # Attempt cherry-pick | |
| if ! git cherry-pick ${{ steps.get_commit.outputs.sha }} --empty=keep; then | |
| echo "Cherry-pick encountered conflicts for $base_branch, attempting to resolve..." | |
| git add -A | |
| # Check if there are actual changes staged after conflict resolution attempt | |
| if git diff --cached --quiet; then | |
| echo "Conflict resolution resulted in no changes. Aborting cherry-pick." | |
| git cherry-pick --abort | |
| continue # Skip PR creation if no changes after resolution | |
| fi | |
| git cherry-pick --continue | |
| if [ $? -eq 0 ]; then | |
| echo "Successfully resolved conflicts for $base_branch" | |
| had_conflicts="true" | |
| else | |
| echo "Failed to resolve conflicts for $base_branch" | |
| git cherry-pick --abort | |
| continue | |
| fi | |
| else | |
| echo "Cherry-pick successful for $base_branch" | |
| had_conflicts="false" | |
| fi | |
| CHANGED_FILES=$(git diff-tree --no-commit-id --name-only -r HEAD) | |
| if [ -z "$CHANGED_FILES" ]; then | |
| echo "Cherry-pick resulted in no changes, skipping PR creation for $base_branch" | |
| git reset --hard HEAD^ # Discard the empty commit if one was created by cherry-pick | |
| continue | |
| fi | |
| echo "Changed files:" | |
| echo "$CHANGED_FILES" | |
| # Push branch | |
| if git push origin "$new_branch"; then | |
| echo "Successfully pushed branch $new_branch" | |
| # Create PR | |
| PR_NUMBER="${{ github.event.pull_request.number }}" | |
| PR_URL="${{ github.event.pull_request.html_url }}" | |
| PR_AUTHOR="${{ github.event.pull_request.user.login }}" | |
| # Adjust PR title based on the target branch | |
| if [[ "$base_branch" == "main" ]]; then | |
| HOTFIX_PR_TITLE="[Hotfix Main]: $PR_TITLE" | |
| else | |
| base_branch_name=${base_branch#"release-candidate/"} | |
| HOTFIX_PR_TITLE="[Hotfix $base_branch_name]: $PR_TITLE" | |
| fi | |
| PR_BODY="Hotfix of PR #${PR_NUMBER} (${PR_URL}) to the \`${base_branch}\` branch. | |
| Hey @${PR_AUTHOR}, please review this hotfix PR created from your original PR." | |
| # Add conflict warning if needed | |
| if [[ "$had_conflicts" == "true" ]]; then | |
| PR_BODY="${PR_BODY} | |
| ### ⚠️ **Note:** This PR had conflicts with the base branch and was resolved automatically. Please review the changes carefully." | |
| fi | |
| # Create PR using gh cli | |
| gh pr create \ | |
| --title "$HOTFIX_PR_TITLE" \ | |
| --body "$PR_BODY" \ | |
| --head "$new_branch" \ | |
| --base "$base_branch" \ | |
| --label "auto-hotfix" \ | |
| --assignee "$PR_AUTHOR" \ | |
| --draft | |
| else | |
| echo "Failed to push branch $new_branch" | |
| fi | |
| done |