This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new d5d7df993c5 Add releaseDryRun.sh: CI dry run of the release process
(#5252)
d5d7df993c5 is described below
commit d5d7df993c541e8cf6f299cbbddbc45cc45a951f
Author: David Smiley <[email protected]>
AuthorDate: Mon Nov 2 09:32:52 2026 -0500
Add releaseDryRun.sh: CI dry run of the release process (#5252)
It's for the Solr-Smoketest-* Jenkins jobs.
* smokeTestRelease.py: SMOKETEST_SRC_TEST_TASK to reduce/eliminate unit
tests to run
* git-status.gradle: allow source only execution in a subdirectory of
another git checkout
Co-authored-by: Claude Opus 5.5 <[email protected]>
---
dev-tools/scripts/README.md | 8 +++++++
dev-tools/scripts/releaseDryRun.sh | 42 +++++++++++++++++++++++++++++++++++
dev-tools/scripts/smokeTestRelease.py | 6 +++--
gradle/validation/git-status.gradle | 25 ++++++++++++---------
4 files changed, 69 insertions(+), 12 deletions(-)
diff --git a/dev-tools/scripts/README.md b/dev-tools/scripts/README.md
index b32b63c4a56..47c82582e14 100644
--- a/dev-tools/scripts/README.md
+++ b/dev-tools/scripts/README.md
@@ -38,6 +38,14 @@ the full tests.
python3 -u dev-tools/scripts/smokeTestRelease.py
https://dist.apache.org/repos/dist/dev/solr/solr-10.0.0-RC1-rev-c7510a0...
+### releaseDryRun.sh
+
+Dry run of the release process for the version in `build.gradle`, without
signing or
+publishing anything: prepares the changelog on a local branch, builds an RC
with
+`buildAndPushRelease.py`, and smoke tests it. Used by the `Solr-Smoketest-*`
Jenkins jobs.
+
+ Usage: dev-tools/scripts/releaseDryRun.sh [TMP_DIR]
+
### releaseWizard.py
The Release Wizard guides the Release Manager through the release process step
diff --git a/dev-tools/scripts/releaseDryRun.sh
b/dev-tools/scripts/releaseDryRun.sh
new file mode 100755
index 00000000000..b34d78a87b9
--- /dev/null
+++ b/dev-tools/scripts/releaseDryRun.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# Dry run of the release process for the version in build.gradle: prepares the
+# changelog (committed to a local "release-dry-run" branch, never pushed),
builds
+# an unsigned RC with buildAndPushRelease.py, then runs smokeTestRelease.py on
it.
+# Used by the Solr-Smoketest-* Jenkins jobs.
+#
+# Usage: dev-tools/scripts/releaseDryRun.sh [TMP_DIR]
+# TMP_DIR must be outside the git checkout; it is deleted first.
+
+set -euo pipefail
+cd "$(git rev-parse --show-toplevel)"
+
+TMP_ROOT="${1:-${WORKSPACE:-$(pwd)}_smoke}"
+
+if [[ -n "$(git status --porcelain --untracked-files=no)" ]]; then
+ echo "Working tree has uncommitted changes" >&2
+ exit 1
+fi
+
+pip3 install -r dev-tools/scripts/requirements.txt
+
+[[ -e "$TMP_ROOT" ]] && chmod -R u+w "$TMP_ROOT"
+rm -rf "$TMP_ROOT"
+mkdir -p "$TMP_ROOT"
+
+VERSION=$(cd dev-tools/scripts && python3 -c 'import
scriptutil;print(scriptutil.find_current_version())')
+echo "Dry run of release $VERSION in $TMP_ROOT"
+
+ORIG_REF=$(git symbolic-ref -q --short HEAD || git rev-parse HEAD)
+trap 'git checkout -q "$ORIG_REF"' EXIT
+
+export GIT_AUTHOR_NAME=ci GIT_AUTHOR_EMAIL=ci@localhost GIT_COMMITTER_NAME=ci
GIT_COMMITTER_EMAIL=ci@localhost
+git checkout -B release-dry-run
+python3 -u dev-tools/scripts/logchange.py prepare --version "$VERSION"
--release-branch release-dry-run --commit
+
+python3 -u dev-tools/scripts/buildAndPushRelease.py --dev-mode --push-local
"$TMP_ROOT/dist" --rc-num 1
+
+# Unit tests run in the regular CI jobs; here just check that the source
release compiles.
+export SMOKETEST_SRC_TEST_TASK=testClasses
+
+python3 -u dev-tools/scripts/smokeTestRelease.py --not-signed --tmp-dir
"$TMP_ROOT/smoke" \
+ "file://$TMP_ROOT/dist/solr-$VERSION-RC1-rev-$(git rev-parse HEAD)"
diff --git a/dev-tools/scripts/smokeTestRelease.py
b/dev-tools/scripts/smokeTestRelease.py
index 746138fb103..e451f1cdacc 100755
--- a/dev-tools/scripts/smokeTestRelease.py
+++ b/dev-tools/scripts/smokeTestRelease.py
@@ -651,8 +651,10 @@ def verifySrcUnpacked(java, artifact, unpackPath, version,
testArgs, tmpDir):
print(' run "%s"' % validateCmd)
java.run_java(validateCmd, '%s/documentation.log' % logDir)
- print(" run tests w/ Java %s and testArgs='%s'..." % (java.version,
testArgs))
- java.run_java('./gradlew test %s' % testArgs, '%s/test.log' % logDir)
+ # SMOKETEST_SRC_TEST_TASK lets CI swap the full test run for something
lighter
+ testTask = os.environ.get('SMOKETEST_SRC_TEST_TASK', 'test')
+ print(" run %s w/ Java %s and testArgs='%s'..." % (testTask,
java.version, testArgs))
+ java.run_java('./gradlew %s %s' % (testTask, testArgs), '%s/test.log' %
logDir)
# Some integration tests need the Docker image of the binary release, and
skip without it
if subprocess.call('docker info', shell=True, stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL) == 0:
print(" build docker image from solr-%s.tgz" % version)
diff --git a/gradle/validation/git-status.gradle
b/gradle/validation/git-status.gradle
index 3dc28394019..55dd7092907 100644
--- a/gradle/validation/git-status.gradle
+++ b/gradle/validation/git-status.gradle
@@ -37,14 +37,23 @@ buildscript {
}
configure(rootProject) {
+ // Only a repository rooted at the project dir counts, not a parent checkout
that merely contains it
+ // (e.g. an unpacked source release inside a clone).
+ def findGitRepository = {
+ if (!rootProject.file(".git").exists()) {
+ throw new RepositoryNotFoundException(rootProject.projectDir)
+ }
+ return new FileRepositoryBuilder()
+ .findGitDir(rootProject.projectDir)
+ .setWorkTree(rootProject.projectDir)
+ .setMustExist(true)
+ .build()
+ }
+
task gitStatus() {
doFirst {
try {
- def repository = new FileRepositoryBuilder()
- .findGitDir(rootProject.projectDir)
- .setWorkTree(rootProject.projectDir)
- .setMustExist(true)
- .build()
+ def repository = findGitRepository()
def ref = repository.findRef("HEAD").getObjectId()
project.ext.gitRev = ref.name()
@@ -65,11 +74,7 @@ configure(rootProject) {
doFirst {
def status
try {
- def repository = new FileRepositoryBuilder()
- .findGitDir(rootProject.projectDir)
- .setWorkTree(rootProject.projectDir)
- .setMustExist(true)
- .build()
+ def repository = findGitRepository()
status = new Git(repository).status().call()
} catch (RepositoryNotFoundException | NoWorkTreeException e) {
status = null