@@ -122,6 +122,8 @@ jobs:
122122
123123 BASE_MAJOR="$(echo "${BASE}" | cut -d'.' -f1)"
124124 TAG_MAJOR="$(echo "${TAG}" | cut -d'.' -f1)"
125+ TAG_MINOR="$(echo "${TAG}" | cut -d'.' -f2)"
126+ TAG_PATCH="$(echo "${TAG}" | cut -d'.' -f3)"
125127 TAG_PARTS_COUNT="$(echo "${TAG}" | awk -F'.' '{print NF}')"
126128
127129 RELEASE_KIND=""
@@ -133,9 +135,6 @@ jobs:
133135 exit 1
134136 fi
135137
136- TAG_MINOR="$(echo "${TAG}" | cut -d'.' -f2)"
137- TAG_PATCH="$(echo "${TAG}" | cut -d'.' -f3)"
138-
139138 if [[ "${TAG_MAJOR}" != "${BASE_MAJOR}" ]]; then
140139 RELEASE_KIND="major"
141140 # Major releases must be X.0.0
@@ -154,6 +153,15 @@ jobs:
154153 fi
155154 fi
156155 else
156+ BASE_MINOR="$(echo "${BASE}" | cut -d'.' -f2)"
157+ if ! [[ "${BASE_MINOR}" =~ ^[0-9]+$ ]]; then
158+ echo "Invalid base_branch format. Expected X.Y for maintenance branches, got: ${BASE}" >> "$GITHUB_STEP_SUMMARY"
159+ exit 1
160+ fi
161+ if [[ "${TAG_MAJOR}" != "${BASE_MAJOR}" || "${TAG_MINOR}" != "${BASE_MINOR}" ]]; then
162+ echo "Invalid tag for maintenance base. Expected ${BASE_MAJOR}.${BASE_MINOR}.* for base ${BASE}, got: ${TAG}" >> "$GITHUB_STEP_SUMMARY"
163+ exit 1
164+ fi
157165 if [[ "${TAG_PARTS_COUNT}" -eq 4 ]]; then
158166 RELEASE_KIND="hotfix"
159167 elif [[ "${TAG_PARTS_COUNT}" -eq 3 ]]; then
@@ -388,10 +396,6 @@ jobs:
388396
389397 echo "close_title=${TAG}" >> "$GITHUB_OUTPUT"
390398 echo "do_milestones=true" >> "$GITHUB_OUTPUT"
391- echo "create_titles=" >> "$GITHUB_OUTPUT"
392- echo "move_from_title=" >> "$GITHUB_OUTPUT"
393- echo "move_to_title=" >> "$GITHUB_OUTPUT"
394- echo "minor_move_prefix=" >> "$GITHUB_OUTPUT"
395399
396400 if [[ "${KIND}" == "hotfix" ]]; then
397401 echo "do_milestones=false" >> "$GITHUB_OUTPUT"
@@ -402,8 +406,11 @@ jobs:
402406 NEXT_MAJOR="$((A+1)).0.0"
403407 NEXT_PATCH="${A}.${B}.$((C+1))"
404408 echo "create_titles=${NEXT_MAJOR},${NEXT_PATCH}" >> "$GITHUB_OUTPUT"
405- echo "move_from_title=" >> "$GITHUB_OUTPUT"
406- echo "move_to_title=" >> "$GITHUB_OUTPUT"
409+ if [[ "${A}" =~ ^[0-9]+$ && "${A}" -gt 0 ]]; then
410+ PREV_MAJOR="$((A-1))."
411+ echo "major_move_prefix=${PREV_MAJOR}" >> "$GITHUB_OUTPUT"
412+ echo "move_to_title=${NEXT_PATCH}" >> "$GITHUB_OUTPUT"
413+ fi
407414 elif [[ "${KIND}" == "minor" ]]; then
408415 NEXT_MINOR="${A}.$((B+1)).0"
409416 NEXT_PATCH="${A}.${B}.$((C+1))"
@@ -727,6 +734,111 @@ jobs:
727734 echo "No open issues found in milestones starting with '${PREFIX}'" >> "$GITHUB_STEP_SUMMARY"
728735 fi
729736
737+ - name : Move issues (major)
738+ if : ${{ steps.plan.outputs.do_milestones == 'true' && env.RELEASE_KIND == 'major' && steps.plan.outputs.major_move_prefix != '' && steps.plan.outputs.move_to_title != '' }}
739+ shell : bash
740+ run : |
741+ set -euo pipefail
742+ PREFIX="${{ steps.plan.outputs.major_move_prefix }}"
743+ TO_TITLE="${{ steps.plan.outputs.move_to_title }}"
744+
745+ PAGE=1
746+ TO_NUM=""
747+ while true; do
748+ RESP=$(curl -s --location \
749+ "https://api.github.com/repos/${OWNER}/${REPO}/milestones?state=all&per_page=100&page=${PAGE}" \
750+ -H "X-GitHub-Api-Version: 2022-11-28" \
751+ -H "Accept: application/vnd.github+json" \
752+ -H "Authorization: Bearer ${RELEASE_TOKEN}")
753+ LEN=$(echo "${RESP}" | jq '. | length')
754+ if [[ "${LEN}" -eq 0 ]]; then
755+ break
756+ fi
757+ TO_NUM=$(echo "${RESP}" | jq -r --arg t "${TO_TITLE}" '.[] | select(.title == $t) | .number' | head -n 1)
758+ if [[ -n "${TO_NUM}" && "${TO_NUM}" != "null" ]]; then
759+ break
760+ fi
761+ PAGE=$((PAGE+1))
762+ if [[ "${PAGE}" -gt 20 ]]; then
763+ break
764+ fi
765+ done
766+
767+ if [[ -z "${TO_NUM}" || "${TO_NUM}" == "null" ]]; then
768+ echo "⚠️ Cannot move major issues: target milestone '${TO_TITLE}' not found" >> "$GITHUB_STEP_SUMMARY"
769+ exit 0
770+ fi
771+
772+ PAGE=1
773+ MOVED=0
774+
775+ while true; do
776+ MS=$(curl -s --location \
777+ "https://api.github.com/repos/${OWNER}/${REPO}/milestones?state=open&per_page=100&page=${PAGE}" \
778+ -H "X-GitHub-Api-Version: 2022-11-28" \
779+ -H "Accept: application/vnd.github+json" \
780+ -H "Authorization: Bearer ${RELEASE_TOKEN}")
781+
782+ LEN=$(echo "${MS}" | jq '. | length')
783+ if [[ "${LEN}" -eq 0 ]]; then
784+ break
785+ fi
786+
787+ while IFS= read -r MS_TITLE; do
788+ [[ -z "${MS_TITLE}" ]] && continue
789+
790+ MS_NUM=$(echo "${MS}" | jq -r --arg t "${MS_TITLE}" '.[] | select(.title == $t) | .number' | head -n 1)
791+ if [[ -z "${MS_NUM}" || "${MS_NUM}" == "null" ]]; then
792+ continue
793+ fi
794+
795+ ISSUE_PAGE=1
796+ while true; do
797+ ISSUES=$(curl -s --location \
798+ "https://api.github.com/repos/${OWNER}/${REPO}/issues?state=open&milestone=${MS_NUM}&per_page=100&page=${ISSUE_PAGE}" \
799+ -H "X-GitHub-Api-Version: 2022-11-28" \
800+ -H "Accept: application/vnd.github+json" \
801+ -H "Authorization: Bearer ${RELEASE_TOKEN}")
802+
803+ ISSUE_LEN=$(echo "${ISSUES}" | jq '. | length')
804+ if [[ "${ISSUE_LEN}" -eq 0 ]]; then
805+ break
806+ fi
807+
808+ IDS=$(echo "${ISSUES}" | jq -r '.[].number')
809+ for N in ${IDS}; do
810+ RES=$(curl -s -o /dev/null -w "%{http_code}" -X PATCH --location \
811+ "https://api.github.com/repos/${OWNER}/${REPO}/issues/${N}" \
812+ -H "X-GitHub-Api-Version: 2022-11-28" \
813+ -H "Accept: application/vnd.github+json" \
814+ -H "Authorization: Bearer ${RELEASE_TOKEN}" \
815+ -d "$(jq -n --argjson m "${TO_NUM}" '{milestone:$m}')")
816+ if [[ "${RES}" -eq 200 ]]; then
817+ MOVED=$((MOVED+1))
818+ fi
819+ done
820+
821+ ISSUE_PAGE=$((ISSUE_PAGE+1))
822+ if [[ "${ISSUE_PAGE}" -gt 50 ]]; then
823+ echo "⚠️ Stopped after 50 pages for milestone '${MS_TITLE}'" >> "$GITHUB_STEP_SUMMARY"
824+ break
825+ fi
826+ done
827+ done <<< "$(echo "${MS}" | jq -r --arg p "${PREFIX}" '.[] | select(.title | startswith($p)) | .title')"
828+
829+ PAGE=$((PAGE+1))
830+ if [[ "${PAGE}" -gt 20 ]]; then
831+ echo "⚠️ Stopped major issue move after 20 pages of milestones" >> "$GITHUB_STEP_SUMMARY"
832+ break
833+ fi
834+ done
835+
836+ if [[ "${MOVED}" -gt 0 ]]; then
837+ echo "Moved ${MOVED} open issues from milestones starting with '${PREFIX}' -> '${TO_TITLE}'" >> "$GITHUB_STEP_SUMMARY"
838+ else
839+ echo "No open issues found in milestones starting with '${PREFIX}'" >> "$GITHUB_STEP_SUMMARY"
840+ fi
841+
730842 - name : Close current milestone (after issue moves)
731843 if : ${{ steps.plan.outputs.do_milestones == 'true' && steps.ms_find.outputs.close_ms_number != '' }}
732844 shell : bash
@@ -772,19 +884,14 @@ jobs:
772884 PREV_MAJOR=$((A-1))
773885 CLONE_FROM="${PREV_MAJOR}.x"
774886 CLONE_TO="${A}.0"
775- RENAME_FROM="${PREV_MAJOR}.x"
776- RENAME_TO="${A}.x"
777887 else
778888 echo "Cannot determine previous major version for tag ${TAG}" >> "$GITHUB_STEP_SUMMARY"
779889 exit 1
780890 fi
781891
782892 echo "clone_from=${CLONE_FROM}" >> "$GITHUB_OUTPUT"
783893 echo "clone_to=${CLONE_TO}" >> "$GITHUB_OUTPUT"
784- echo "rename_from=${RENAME_FROM}" >> "$GITHUB_OUTPUT"
785- echo "rename_to=${RENAME_TO}" >> "$GITHUB_OUTPUT"
786894 echo "do_clone=true" >> "$GITHUB_OUTPUT"
787- echo "do_rename=true" >> "$GITHUB_OUTPUT"
788895
789896 elif [[ "${KIND}" == "minor" ]]; then
790897 CLONE_FROM="${A}.x"
@@ -793,7 +900,6 @@ jobs:
793900 echo "clone_from=${CLONE_FROM}" >> "$GITHUB_OUTPUT"
794901 echo "clone_to=${CLONE_TO}" >> "$GITHUB_OUTPUT"
795902 echo "do_clone=true" >> "$GITHUB_OUTPUT"
796- echo "do_rename=false" >> "$GITHUB_OUTPUT"
797903 fi
798904
799905 - name : Clone branch for maintenance
@@ -840,23 +946,6 @@ jobs:
840946 echo "$(echo "${CREATE_RESP}" | sed '$d' | head -c 2000)" >> "$GITHUB_STEP_SUMMARY"
841947 fi
842948
843- - name : Rename branch (manual)
844- if : ${{ steps.plan.outputs.do_rename == 'true' }}
845- shell : bash
846- run : |
847- set -euo pipefail
848- FROM="${{ steps.plan.outputs.rename_from }}"
849- TO="${{ steps.plan.outputs.rename_to }}"
850-
851- echo "⚠️ **Manual Action Required**: Rename branch '${FROM}' to '${TO}'" >> "$GITHUB_STEP_SUMMARY"
852- echo "" >> "$GITHUB_STEP_SUMMARY"
853- echo "After renaming, please check and update:" >> "$GITHUB_STEP_SUMMARY"
854- echo "- composer.json (branch-alias)" >> "$GITHUB_STEP_SUMMARY"
855- echo "- Workflow files (any hardcoded version references)" >> "$GITHUB_STEP_SUMMARY"
856- echo "- Documentation files" >> "$GITHUB_STEP_SUMMARY"
857- echo "" >> "$GITHUB_STEP_SUMMARY"
858- echo "See: https://github.com/${OWNER}/${REPO}/branches" >> "$GITHUB_STEP_SUMMARY"
859-
860949 summary :
861950 name : Release summary
862951 runs-on : ubuntu-latest
0 commit comments