@@ -340,6 +340,10 @@ has_unmanaged_changes() {
340340 ! git diff-index --quiet HEAD -- . " ${exclude_args[@]} "
341341}
342342
343+ has_release_managed_changes () {
344+ ! git diff --quiet HEAD -- " ${RELEASE_MANAGED_FILES[@]} "
345+ }
346+
343347# Check if working directory is clean outside release-managed files
344348if ! $DRY_RUN ; then
345349 if has_unmanaged_changes; then
@@ -454,15 +458,13 @@ else
454458 if [[ " $CURRENT_SERVER_VERSION " != " $VERSION " ]]; then
455459 echo " 📝 Aligning server.json to $VERSION ..."
456460 run node -e " const fs=require('fs');const f='server.json';const j=JSON.parse(fs.readFileSync(f,'utf8'));j.version='${VERSION} ';if(Array.isArray(j.packages)){j.packages=j.packages.map(p=>({...p,version:'${VERSION} '}));}fs.writeFileSync(f,JSON.stringify(j,null,2)+'\n');"
457- run git add server.json
458- run env XCODEBUILDMCP_DOCS_CHECK_WARN_ONLY=1 git commit -m " Align server.json for v$VERSION "
459461 fi
460462 fi
461463
462- if $CHANGELOG_RENAMED_ON_DISK ; then
463- echo " 📝 Committing changelog release heading update ..."
464- run git add CHANGELOG.md
465- run env XCODEBUILDMCP_DOCS_CHECK_WARN_ONLY=1 git commit -m " Finalize changelog for v$VERSION "
464+ if has_release_managed_changes ; then
465+ echo " 📦 Committing release-managed changes ..."
466+ run git add " ${RELEASE_MANAGED_FILES[@]} "
467+ run env XCODEBUILDMCP_DOCS_CHECK_WARN_ONLY=1 git commit -m " Release v$VERSION "
466468 fi
467469fi
468470
@@ -473,6 +475,8 @@ run git tag -f "v$VERSION"
473475echo " "
474476echo " 🚀 Pushing to origin..."
475477run git push origin " $BRANCH "
478+ RELEASE_HEAD_SHA=$( git rev-parse HEAD)
479+ WORKFLOW_SEARCH_STARTED_AT=$( date -u +" %Y-%m-%dT%H:%M:%SZ" )
476480run git push origin " v$VERSION "
477481
478482# In dry-run, stop here (don't monitor workflows, and don't claim a release happened).
@@ -490,8 +494,8 @@ echo "This may take a few minutes..."
490494# Poll for the workflow run triggered by this tag (may take a few seconds to appear)
491495RUN_ID=" "
492496for i in $( seq 1 12) ; do
493- RUN_ID=$( gh run list --workflow=release.yml --branch=" v$VERSION " --limit=1 --json databaseId --jq ' .[ 0].databaseId' )
494- if [[ -n " $RUN_ID " ]]; then
497+ RUN_ID=$( gh run list --workflow=release.yml --branch=" v$VERSION " --limit=20 --json databaseId,headSha,createdAt --jq " [.[] | select(.headSha == \" $RELEASE_HEAD_SHA \" and .createdAt >= \" $WORKFLOW_SEARCH_STARTED_AT \" )] | .[ 0].databaseId // \"\" " )
498+ if [[ -n " $RUN_ID " && " $RUN_ID " != " null " ]]; then
495499 break
496500 fi
497501 echo " Waiting for workflow to appear... (attempt $i /12)"
@@ -505,7 +509,9 @@ if [[ -n "$RUN_ID" ]]; then
505509 echo " "
506510
507511 # Watch the workflow with exit status
508- if gh run watch " $RUN_ID " --exit-status; then
512+ WATCH_EXIT=0
513+ gh run watch " $RUN_ID " --exit-status || WATCH_EXIT=$?
514+ if [[ $WATCH_EXIT -eq 0 ]]; then
509515 echo " "
510516 echo " ✅ Release v$VERSION completed successfully!"
511517 echo " 📦 View on NPM: https://www.npmjs.com/package/xcodebuildmcp/v/$VERSION "
@@ -518,6 +524,13 @@ if [[ -n "$RUN_ID" ]]; then
518524 echo " ℹ️ This may be a transient API error. The workflow may still be running."
519525 echo " Check manually: gh run view $RUN_ID "
520526 echo " "
527+ RUN_STATUS=$( gh run view " $RUN_ID " --json status --jq ' .status' || echo " unknown" )
528+ if [[ " $RUN_STATUS " != " completed" ]]; then
529+ echo " ⚠️ Workflow is still '$RUN_STATUS '. Keeping tag v$VERSION ."
530+ echo " Re-run monitoring manually: gh run watch $RUN_ID --exit-status"
531+ exit $WATCH_EXIT
532+ fi
533+
521534 # Prefer job state: if the primary 'release' job succeeded, treat as success.
522535 RELEASE_JOB_CONCLUSION=$( gh run view " $RUN_ID " --json jobs --jq ' .jobs[] | select(.name=="release") | .conclusion' )
523536 if [ " $RELEASE_JOB_CONCLUSION " = " success" ]; then
0 commit comments