@@ -3,8 +3,10 @@ set -euo pipefail
33
44VERSION_FILE=" src/pyscipopt/_version.py"
55SETUP_FILE=" setup.py"
6+ PYPROJECT=" pyproject.toml"
67CHANGELOG=" CHANGELOG.md"
78REPO=" scipopt/PySCIPOpt"
9+ DEPLOY_REPO=" scipopt/scipoptsuite-deploy"
810
911# --- Pre-flight checks ---
1012
3133
3234git pull --ff-only
3335
34- # --- Read current version ---
36+ # --- Helper functions ---
37+
38+ validate_version () {
39+ if [[ ! " $1 " =~ ^[0-9]+\. [0-9]+\. [0-9]+$ ]]; then
40+ echo " Error: '$1 ' is not a valid version (expected X.Y.Z)"
41+ exit 1
42+ fi
43+ }
44+
45+ prompt_version () {
46+ local label=" $1 " current=" $2 "
47+ read -rp " ${label} [${current} ]: " value
48+ value=" ${value:- $current } "
49+ validate_version " $value "
50+ echo " $value "
51+ }
52+
53+ # --- Collect all inputs ---
54+
55+ # 1. New SCIP binaries?
56+
57+ CURRENT_DEPLOY_VERSION=$( grep -o ' scipoptsuite-deploy/releases/download/v[0-9.]*' " $PYPROJECT " | head -1 | sed ' s|.*/||' )
58+
59+ echo " Current scipoptsuite-deploy version: ${CURRENT_DEPLOY_VERSION} "
60+ read -rp " Does this release need new SCIP binaries? [y/N] " need_deploy
61+
62+ NEED_DEPLOY=false
63+ if [[ " ${need_deploy:- N} " =~ ^[Yy] ]]; then
64+ NEED_DEPLOY=true
65+
66+ echo " "
67+ echo " Enter component versions (press enter to keep current):"
68+
69+ # Fetch current defaults from the deploy workflow
70+ DEPLOY_WORKFLOW=$( gh api repos/${DEPLOY_REPO} /contents/.github/workflows/build_binaries.yml --jq ' .content' | base64 -d)
71+ current_deploy_default () {
72+ echo " $DEPLOY_WORKFLOW " | sed -n " /${1} :/,/default:/{s/.*default: \" \(.*\)\" /\1/p;}" | head -1
73+ }
74+
75+ CUR_SCIP=$( current_deploy_default " scip_version" )
76+ CUR_SOPLEX=$( current_deploy_default " soplex_version" )
77+ CUR_GCG=$( current_deploy_default " gcg_version" )
78+ CUR_IPOPT=$( current_deploy_default " ipopt_version" )
79+
80+ SCIP_VERSION=$( prompt_version " SCIP" " $CUR_SCIP " )
81+ SOPLEX_VERSION=$( prompt_version " SoPlex" " $CUR_SOPLEX " )
82+ GCG_VERSION=$( prompt_version " GCG" " $CUR_GCG " )
83+ IPOPT_VERSION=$( prompt_version " IPOPT" " $CUR_IPOPT " )
84+
85+ # Bump deploy version (increment minor)
86+ DEPLOY_MAJOR=$( echo " $CURRENT_DEPLOY_VERSION " | sed ' s/^v//' | cut -d. -f1)
87+ DEPLOY_MINOR=$( echo " $CURRENT_DEPLOY_VERSION " | sed ' s/^v//' | cut -d. -f2)
88+ DEPLOY_PATCH=$( echo " $CURRENT_DEPLOY_VERSION " | sed ' s/^v//' | cut -d. -f3)
89+ SUGGESTED_DEPLOY=" v$(( DEPLOY_MAJOR)) .$(( DEPLOY_MINOR + 1 )) .$(( DEPLOY_PATCH)) "
90+
91+ read -rp " New deploy release tag [${SUGGESTED_DEPLOY} ]: " NEW_DEPLOY_VERSION
92+ NEW_DEPLOY_VERSION=" ${NEW_DEPLOY_VERSION:- $SUGGESTED_DEPLOY } "
93+ fi
94+
95+ # 2. PySCIPOpt version bump
3596
3697CURRENT_VERSION=$( sed -n " s/^__version__.*'\(.*\)'/\1/p" " $VERSION_FILE " )
3798MAJOR=$( echo " $CURRENT_VERSION " | cut -d. -f1)
3899MINOR=$( echo " $CURRENT_VERSION " | cut -d. -f2)
39100PATCH=$( echo " $CURRENT_VERSION " | cut -d. -f3)
40101
41- echo " Current version: ${CURRENT_VERSION} "
42-
43- # --- Prompt for bump type ---
44-
102+ echo " "
103+ echo " Current PySCIPOpt version: ${CURRENT_VERSION} "
45104echo " "
46105echo " Release type:"
47106echo " 1) patch -> $(( MAJOR)) .$(( MINOR)) .$(( PATCH + 1 )) "
@@ -57,34 +116,88 @@ case "$bump_type" in
57116 * ) echo " Error: invalid selection '${bump_type} '" ; exit 1 ;;
58117esac
59118
60- # --- Check tag doesn't already exist ---
61-
62119if git rev-parse " v${NEW_VERSION} " & > /dev/null; then
63120 echo " Error: tag 'v${NEW_VERSION} ' already exists."
64121 exit 1
65122fi
66123
67- # --- Show changelog preview ---
124+ # --- Show summary and confirm ---
68125
69126echo " "
70127echo " Unreleased changelog entries:"
71128echo " -----------------------------"
72- # Print lines between "## Unreleased" and the next "## " header
73129sed -n ' /^## Unreleased$/,/^## [0-9]/{/^## [0-9]/!p;}' " $CHANGELOG " | head -30
74130echo " -----------------------------"
75- echo " "
76131
77132TODAY=$( date +%Y.%m.%d)
78133echo " "
79134echo " This script will:"
80- echo " 1. Update version ${CURRENT_VERSION} -> ${NEW_VERSION} in _version.py and setup.py"
81- echo " 2. Update CHANGELOG.md (${NEW_VERSION} - ${TODAY} )"
82- echo " 3. Commit, tag v${NEW_VERSION} , and push to origin"
83- echo " 4. Trigger the build wheels workflow (test-pypi)"
135+ if [[ " $NEED_DEPLOY " == true ]]; then
136+ echo " 1. Build new SCIP binaries (SCIP=${SCIP_VERSION} SoPlex=${SOPLEX_VERSION} GCG=${GCG_VERSION} IPOPT=${IPOPT_VERSION} )"
137+ echo " 2. Create scipoptsuite-deploy release ${NEW_DEPLOY_VERSION} "
138+ echo " 3. Update deploy version ${CURRENT_DEPLOY_VERSION} -> ${NEW_DEPLOY_VERSION} in pyproject.toml"
139+ echo " 4. Update PySCIPOpt version ${CURRENT_VERSION} -> ${NEW_VERSION} in _version.py and setup.py"
140+ echo " 5. Update CHANGELOG.md (${NEW_VERSION} - ${TODAY} )"
141+ echo " 6. Commit, tag v${NEW_VERSION} , and push to origin"
142+ echo " 7. Trigger the build wheels workflow (test-pypi)"
143+ else
144+ echo " 1. Update version ${CURRENT_VERSION} -> ${NEW_VERSION} in _version.py and setup.py"
145+ echo " 2. Update CHANGELOG.md (${NEW_VERSION} - ${TODAY} )"
146+ echo " 3. Commit, tag v${NEW_VERSION} , and push to origin"
147+ echo " 4. Trigger the build wheels workflow (test-pypi)"
148+ fi
84149echo " "
85150read -rp " Proceed? [Y/n] " confirm
86151[[ " ${confirm:- Y} " =~ ^[Nn] ]] && exit 0
87152
153+ # ============================================================
154+ # From here on, everything runs without further prompts.
155+ # ============================================================
156+
157+ # --- Build and release SCIP binaries (if needed) ---
158+
159+ if [[ " $NEED_DEPLOY " == true ]]; then
160+ echo " "
161+ echo " Triggering SCIP binary build..."
162+ gh workflow run build_binaries.yml --repo " $DEPLOY_REPO " \
163+ -f scip_version=" $SCIP_VERSION " \
164+ -f soplex_version=" $SOPLEX_VERSION " \
165+ -f gcg_version=" $GCG_VERSION " \
166+ -f ipopt_version=" $IPOPT_VERSION "
167+
168+ # Wait for the run to appear
169+ sleep 5
170+ RUN_ID=$( gh run list --workflow=build_binaries.yml --repo " $DEPLOY_REPO " --limit 1 --json databaseId --jq ' .[0].databaseId' )
171+
172+ echo " Waiting for build to complete (run ${RUN_ID} )..."
173+ echo " https://github.com/${DEPLOY_REPO} /actions/runs/${RUN_ID} "
174+ gh run watch " $RUN_ID " --repo " $DEPLOY_REPO " --exit-status
175+
176+ # Download artifacts and create release
177+ TMPDIR=$( mktemp -d)
178+ echo " Downloading artifacts..."
179+ gh run download " $RUN_ID " --repo " $DEPLOY_REPO " --dir " $TMPDIR "
180+
181+ RELEASE_NAME=" SCIP ${SCIP_VERSION} SOPLEX ${SOPLEX_VERSION} GCG ${GCG_VERSION} IPOPT ${IPOPT_VERSION} "
182+ echo " Creating release ${NEW_DEPLOY_VERSION} ..."
183+ gh release create " $NEW_DEPLOY_VERSION " \
184+ --repo " $DEPLOY_REPO " \
185+ --title " $RELEASE_NAME " \
186+ --notes " $RELEASE_NAME " \
187+ " $TMPDIR " /linux/* .zip \
188+ " $TMPDIR " /linux-arm/* .zip \
189+ " $TMPDIR " /macos-arm/* .zip \
190+ " $TMPDIR " /macos-intel/* .zip \
191+ " $TMPDIR " /windows/* .zip
192+
193+ rm -rf " $TMPDIR "
194+
195+ # Update deploy version in pyproject.toml
196+ sed -i.bak " s|scipoptsuite-deploy/releases/download/${CURRENT_DEPLOY_VERSION} |scipoptsuite-deploy/releases/download/${NEW_DEPLOY_VERSION} |g" " $PYPROJECT "
197+ rm -f " ${PYPROJECT} .bak"
198+ echo " Updated pyproject.toml: ${CURRENT_DEPLOY_VERSION} -> ${NEW_DEPLOY_VERSION} "
199+ fi
200+
88201# --- Update version files ---
89202
90203sed -i.bak " s/__version__.*=.*'.*'/__version__: str = '${NEW_VERSION} '/" " $VERSION_FILE "
@@ -97,24 +210,27 @@ echo "Updated version: ${CURRENT_VERSION} -> ${NEW_VERSION}"
97210
98211# --- Update changelog ---
99212
100- UNRELEASED_HEADER=" ## Unreleased"
101- NEW_HEADER=" ## ${NEW_VERSION} - ${TODAY} "
102- EMPTY_UNRELEASED=" ## Unreleased\n### Added\n### Fixed\n### Changed\n### Removed\n"
103-
104- sed -i.bak " s/^${UNRELEASED_HEADER} $/${NEW_HEADER} /" " $CHANGELOG "
213+ sed -i.bak " s/^## Unreleased$/## ${NEW_VERSION} - ${TODAY} /" " $CHANGELOG "
105214rm -f " ${CHANGELOG} .bak"
106215
107- # Add empty Unreleased section at the top (after "# CHANGELOG" line)
108216sed -i.bak " /^# CHANGELOG$/a\\
109217\\
110- ${EMPTY_UNRELEASED} " " $CHANGELOG "
218+ ## Unreleased\\
219+ ### Added\\
220+ ### Fixed\\
221+ ### Changed\\
222+ ### Removed\\
223+ " " $CHANGELOG "
111224rm -f " ${CHANGELOG} .bak"
112225
113226echo " Updated CHANGELOG.md"
114227
115228# --- Commit, tag, and push ---
116229
117- git add " $VERSION_FILE " " $SETUP_FILE " " $CHANGELOG "
230+ FILES_TO_COMMIT=(" $VERSION_FILE " " $SETUP_FILE " " $CHANGELOG " )
231+ [[ " $NEED_DEPLOY " == true ]] && FILES_TO_COMMIT+=(" $PYPROJECT " )
232+
233+ git add " ${FILES_TO_COMMIT[@]} "
118234git commit -m " release v${NEW_VERSION} "
119235git tag " v${NEW_VERSION} "
120236git push origin master
0 commit comments