This is an automated email from the ASF dual-hosted git repository.
jiayu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/sedona-db.git
The following commit(s) were added to refs/heads/main by this push:
new 9f36d8b chore(dev/release): Add release verification script (#107)
9f36d8b is described below
commit 9f36d8b114f75560b1f7fc6b23116c118c822be7
Author: Dewey Dunnington <[email protected]>
AuthorDate: Thu Sep 18 13:29:15 2025 -0500
chore(dev/release): Add release verification script (#107)
Co-authored-by: Copilot <[email protected]>
---
.github/workflows/packaging.yml | 1 +
c/sedona-geoarrow-c/src/geoarrow_c.rs | 2 +-
c/sedona-proj/src/proj.rs | 8 +-
ci/scripts/build-source.sh | 15 ++
dev/release/README.md | 51 +++++
dev/release/verify-release-candidate.sh | 351 ++++++++++++++++++++++++++++++++
sedona-cli/Cargo.toml | 2 +-
7 files changed, 421 insertions(+), 9 deletions(-)
diff --git a/.github/workflows/packaging.yml b/.github/workflows/packaging.yml
index a1c88a4..c4c116e 100644
--- a/.github/workflows/packaging.yml
+++ b/.github/workflows/packaging.yml
@@ -42,6 +42,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
+ submodules: 'true'
- uses: actions/setup-python@v5
with:
python-version: "3.x"
diff --git a/c/sedona-geoarrow-c/src/geoarrow_c.rs
b/c/sedona-geoarrow-c/src/geoarrow_c.rs
index e3c5d9f..0956172 100644
--- a/c/sedona-geoarrow-c/src/geoarrow_c.rs
+++ b/c/sedona-geoarrow-c/src/geoarrow_c.rs
@@ -268,7 +268,7 @@ impl Default for Visitor {
impl From<&str> for GeoArrowStringView {
fn from(value: &str) -> Self {
Self {
- data: value.as_ptr() as *const i8,
+ data: value.as_ptr() as *const _,
size_bytes: value.len() as i64,
}
}
diff --git a/c/sedona-proj/src/proj.rs b/c/sedona-proj/src/proj.rs
index 31dfbb5..c597ec0 100644
--- a/c/sedona-proj/src/proj.rs
+++ b/c/sedona-proj/src/proj.rs
@@ -552,13 +552,7 @@ impl ProjApi {
));
inner.proj_create_crs_to_crs_from_pj = Some(std::mem::transmute(
proj_create_crs_to_crs_from_pj
- as unsafe extern "C" fn(
- *mut _,
- *const _,
- *const _,
- *mut _,
- *const *const i8,
- ) -> _,
+ as unsafe extern "C" fn(*mut _, *const _, *const _, *mut
_, *const _) -> _,
));
inner.proj_create = Some(std::mem::transmute(
proj_create as unsafe extern "C" fn(*mut _, *const _) -> _,
diff --git a/ci/scripts/build-source.sh b/ci/scripts/build-source.sh
index c2e7e05..31c7192 100755
--- a/ci/scripts/build-source.sh
+++ b/ci/scripts/build-source.sh
@@ -40,6 +40,21 @@ main() {
rm -rf "${base_name}/"
git archive "${revision}" --prefix "${base_name}/" | tar xf -
+ # Resolve all submodules for sedona-s2geography. In the future we probably
+ # want to improve the packaging of sedona-s2geography such that we don't
need
+ # this step:
+ # https://github.com/apache/sedona-db/issues/109
+ while read SUBMODULE; do
+ SUBMODULE_REV=$(echo "${SUBMODULE}" | awk '{print $1}')
+ SUBMODULE_PATH=$(echo "${SUBMODULE}" | awk '{print $2}')
+ # Check if submodule path starts with "submodules/"
+ if [[ "${SUBMODULE_PATH}" == submodules/* ]]; then
+ echo "Skipping testing submodule ${SUBMODULE}"
+ else
+ git -C "${SUBMODULE_PATH}" archive
--prefix="${base_name}/${SUBMODULE_PATH}/" "${SUBMODULE_REV}" | tar xf - -C
"${source_top_dir}"
+ fi
+ done < <(git submodule status)
+
# Create new tarball
tar czf "${tar_ball}" "${base_name}/"
rm -rf "${base_name}/"
diff --git a/dev/release/README.md b/dev/release/README.md
index f6eda14..f468146 100644
--- a/dev/release/README.md
+++ b/dev/release/README.md
@@ -19,6 +19,50 @@
# Releasing SedonaDB
+## Verifying a release candidate
+
+Release candidates are verified using the script `verify-release-candidate.sh
<version> <rc_num>`.
+For example, to verify SedonaDB 0.1.0 RC0, run:
+
+```shell
+# git clone https://github.com/apache/sedona-db.git && cd sedona-db
+# or
+# cd existing/sedona-db && git fetch upstream && git switch main && git pull
upstream main
+dev/release/verify-release-candidate.sh 0.1.0 0
+```
+
+Release verification requires a recent Rust toolchain. This toolchain can be
installed
+by following instructions from <https://rustup.rs/>.
+
+MacOS users can use [Homebrew](https://brew.sh) to install the required
dependencies.
+
+```shell
+brew install geos proj openssl abseil
+```
+
+Linux users (e.g., `docker run --rm -it condaforge/mambaforge`) can use
`conda` to
+install the required dependencies:
+
+```shell
+conda create -y --name verify-sedona-db
+conda activate verify-sedona-db
+conda install -y curl gnupg geos proj openssl libabseil cmake pkg-config
+export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$CONDA_PREFIX/lib"
+```
+
+Currently system libclang is required to generate C bindings at build time:
+
+```shell
+apt-get update && apt-get install -y libclang-dev
+```
+
+When verifying via Docker or on a smaller machine it may be necessary to limit
the
+number of parallel jobs to avoid running out of memory:
+
+```shell
+export CARGO_BUILD_JOBS=4
+```
+
## Creating a release
Create a release branch on the corresponding remote pointing to the official
Apache
@@ -43,6 +87,13 @@ are considered a "packaging" step (i.e., the artifacts
aren't uploaded to the
release or voted on), although those CI jobs are important to ensuring
the release is ready for a vote.
+Before creating a tag, download the tarball from the latest packaging run and
+check it locally:
+
+```shell
+dev/release/verify-release-candidate.sh path/to/tarball.tar.gz
+```
+
When the state of the `branch-x.x.x` branch is clean and checks are complete,
the release candidate tag can be created:
diff --git a/dev/release/verify-release-candidate.sh
b/dev/release/verify-release-candidate.sh
new file mode 100755
index 0000000..003f737
--- /dev/null
+++ b/dev/release/verify-release-candidate.sh
@@ -0,0 +1,351 @@
+#!/usr/bin/env bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+set -e
+set -o pipefail
+
+if [ ${VERBOSE:-0} -gt 0 ]; then
+ set -x
+fi
+
+# Check that required dependencies are installed
+check_dependencies() {
+ local missing_deps=0
+
+ local required_deps=("curl" "git" "gpg" "cc" "cargo" "cmake")
+ for dep in "${required_deps[@]}"; do
+ if ! command -v $dep &> /dev/null; then
+ echo "Error: $dep is not installed or not in PATH"
+ missing_deps=1
+ fi
+ done
+
+ # pkg-config doesn't work with the above check
+ if ! pkg-config --version &> /dev/null; then
+ echo "Error: pkg-config is not installed or not in PATH"
+ missing_deps=1
+ fi
+
+ # Check for either shasum or sha256sum/sha512sum
+ local has_sha_tools=0
+ if command -v shasum &> /dev/null; then
+ has_sha_tools=1
+ elif command -v sha256sum &> /dev/null && command -v sha512sum &> /dev/null;
then
+ has_sha_tools=1
+ else
+ echo "Error: Neither shasum nor sha256sum/sha512sum are installed or in
PATH"
+ missing_deps=1
+ fi
+
+ if [ $missing_deps -ne 0 ]; then
+ echo "Please install missing dependencies and try again"
+ exit 1
+ fi
+}
+
+
+# Check that required native dependencies are installed. For the purposes of
this
+# script we require geos, proj, absl_base, and openssl via pkg-config, even
though
+# technically absl_base and openssl are resolved via CMake for
sedona-s2geography.
+check_pkg_config_dependencies() {
+ local missing_deps=0
+ local required_deps=(geos proj openssl absl_base)
+ for dep in "${required_deps[@]}"; do
+ if ! pkg-config --modversion $dep &> /dev/null; then
+ echo "Error: $dep is not installed or not in PKG_CONFIG_PATH"
+ missing_deps=1
+ fi
+ done
+
+ local absl_version=$(pkg-config --modversion absl_base)
+ # Check if Abseil version is sufficient (need at least version 20230802)
+ if [ "$absl_version" -lt "20230802" ]; then
+ echo "Error: Abseil version $absl_version is too old, need at least
20230802"
+ echo "On Linux, this typically requires verification within a conda
environment"
+ echo "or by installing Abseil via vcpkg and ensuring PKG_CONFIG_PATH and"
+ echo "CMAKE_TOOLCHAIN_FILE are updated appropriately."
+ missing_deps=1
+ fi
+
+ if [ $missing_deps -ne 0 ]; then
+ echo "Please install or update missing dependencies and try again"
+ echo "Using Homebrew: brew install geos proj openssl abseil"
+ echo "Using conda: conda install geos proj openssl libabseil"
+ exit 1
+ fi
+}
+
+case $# in
+ 0) VERSION="HEAD"
+ SOURCE_KIND="local"
+ ;;
+ 1) VERSION="TARBALL"
+ SOURCE_KIND="local_tarball"
+ LOCAL_TARBALL="$(realpath $1)"
+ ;;
+ 2) VERSION="$1"
+ RC_NUMBER="$2"
+ SOURCE_KIND="tarball"
+ ;;
+ *) echo "Usage:"
+ echo " Verify release candidate:"
+ echo " $0 X.Y.Z RC_NUMBER"
+ echo ""
+ echo " Run the source verification tasks on this sedona-db checkout:"
+ echo " $0"
+ exit 1
+ ;;
+esac
+
+# Check dependencies early
+check_dependencies
+check_pkg_config_dependencies
+
+# Note that these point to the current verify-release-candidate.sh directories
+# which is different from the SEDONADB_SOURCE_DIR set in
ensure_source_directory()
+SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" && pwd)"
+SEDONADB_DIR="$(cd "${SOURCE_DIR}/../.." && pwd)"
+
+show_header() {
+ if [ -z "$GITHUB_ACTIONS" ]; then
+ echo ""
+ printf '=%.0s' $(seq ${#1}); printf '\n'
+ echo "${1}"
+ printf '=%.0s' $(seq ${#1}); printf '\n'
+ else
+ echo "::group::${1}"; printf '\n'
+ fi
+}
+
+show_info() {
+ echo "└ ${1}"
+}
+
+SEDONADB_DIST_URL='https://dist.apache.org/repos/dist/dev/sedona'
+
+download_dist_file() {
+ curl \
+ --silent \
+ --show-error \
+ --fail \
+ --location \
+ --remote-name $SEDONADB_DIST_URL/$1
+}
+
+download_rc_file() {
+ download_dist_file apache-sedona-db-${VERSION}-rc${RC_NUMBER}/$1
+}
+
+import_gpg_keys() {
+ if [ "${GPGKEYS_ALREADY_IMPORTED:-0}" -gt 0 ]; then
+ return 0
+ fi
+ download_dist_file KEYS
+
+ if [ "${SEDONADB_ACCEPT_IMPORT_GPG_KEYS_ERROR:-0}" -gt 0 ]; then
+ gpg --import KEYS || true
+ else
+ gpg --import KEYS
+ fi
+
+ GPGKEYS_ALREADY_IMPORTED=1
+}
+
+if type shasum >/dev/null 2>&1; then
+ sha512_verify="shasum -a 512 -c"
+else
+ sha512_verify="sha512sum -c"
+fi
+
+fetch_archive() {
+ import_gpg_keys
+
+ local dist_name=$1
+ download_rc_file ${dist_name}.tar.gz
+ download_rc_file ${dist_name}.tar.gz.asc
+ download_rc_file ${dist_name}.tar.gz.sha512
+ gpg --verify ${dist_name}.tar.gz.asc ${dist_name}.tar.gz
+ ${sha512_verify} ${dist_name}.tar.gz.sha512
+}
+
+verify_dir_artifact_signatures() {
+ import_gpg_keys
+
+ # verify the signature and the checksums of each artifact
+ find $1 -name '*.asc' | while read sigfile; do
+ artifact=${sigfile/.asc/}
+ gpg --verify $sigfile $artifact || exit 1
+
+ # go into the directory because the checksum files contain only the
+ # basename of the artifact
+ pushd $(dirname $artifact)
+ base_artifact=$(basename $artifact)
+ if [ -f $base_artifact.sha512 ]; then
+ ${sha512_verify} $base_artifact.sha512 || exit 1
+ fi
+ popd
+ done
+}
+
+setup_tempdir() {
+ cleanup() {
+ if [ "${TEST_SUCCESS}" = "yes" ]; then
+ rm -fr "${SEDONADB_TMPDIR}"
+ else
+ echo "Failed to verify release candidate. See ${SEDONADB_TMPDIR} for
details."
+ fi
+ }
+
+ show_header "Creating temporary directory"
+
+ if [ -z "${SEDONADB_TMPDIR}" ]; then
+ # clean up automatically if SEDONADB_TMPDIR is not defined
+ SEDONADB_TMPDIR=$(mktemp -d -t "sedonadb-${VERSION}.XXXXXX")
+ trap cleanup EXIT
+ else
+ # don't clean up automatically
+ mkdir -p "${SEDONADB_TMPDIR}"
+ fi
+
+ echo "Working in sandbox ${SEDONADB_TMPDIR}"
+}
+
+test_rust() {
+ show_header "Build and test Rust libraries"
+
+ pushd "${SEDONADB_SOURCE_DIR}"
+ cargo test --workspace --exclude sedona-s2geography
+ popd
+}
+
+activate_or_create_venv() {
+ if [ ! -z "${SEDONADB_PYTHON_VENV}" ]; then
+ show_info "Activating virtual environment at ${SEDONADB_PYTHON_VENV}"
+ source "${SEDONADB_PYTHON_VENV}/bin/activate"
+ else
+ # Try python3 first, then try regular python (e.g., already in a venv)
+ if [ -z "${PYTHON_BIN}" ] && python3 --version >/dev/null; then
+ PYTHON_BIN=python3
+ elif [ -z "${PYTHON_BIN}" ]; then
+ PYTHON_BIN=python
+ fi
+
+ show_info "Creating temporary virtual environment using ${PYTHON_BIN}..."
+ "${PYTHON_BIN}" -m venv "${SEDONADB_TMPDIR}/venv"
+ source "${SEDONADB_TMPDIR}/venv/bin/activate"
+ python -m pip install --upgrade pip
+ fi
+}
+
+test_python() {
+ show_header "Build and test Python package"
+ activate_or_create_venv
+
+ pushd "${SEDONADB_SOURCE_DIR}/python"
+
+ show_info "Installing Python package"
+ rm -rf "${SEDONADB_TMPDIR}/python"
+ pip install "sedonadb/[test]" -v
+
+ show_info "Testing Python package"
+ python -m pytest -vv
+
+ popd
+}
+
+ensure_source_directory() {
+ show_header "Ensuring source directory"
+
+ dist_name="apache-sedona-db-${VERSION}"
+
+ if [ "${SOURCE_KIND}" = "local" ]; then
+ # Local repository
+ if [ -z "$SEDONADB_SOURCE_DIR" ]; then
+ export SEDONADB_SOURCE_DIR="${SEDONADB_DIR}"
+ fi
+ echo "Verifying local sedona-db checkout at ${SEDONADB_SOURCE_DIR}"
+ elif [ "${SOURCE_KIND}" = "local_tarball" ]; then
+ # Local tarball
+ pushd $SEDONADB_TMPDIR
+ tar xf "$LOCAL_TARBALL"
+ dist_name=$(ls)
+ export SEDONADB_SOURCE_DIR="${SEDONADB_TMPDIR}/${dist_name}"
+
+ # Ensure submodules are where tests expect them to be
+ pushd "$SEDONADB_SOURCE_DIR/submodules"
+ git clone https://github.com/apache/sedona-testing.git
+ git clone https://github.com/geoarrow/geoarrow-data.git
+ popd
+
+ popd
+
+ echo "Verifying local tarball at $LOCAL_TARBALL"
+ else
+ # Release tarball
+ echo "Verifying official SedonaDB release candidate
${VERSION}-rc${RC_NUMBER}"
+ export SEDONADB_SOURCE_DIR="${SEDONADB_TMPDIR}/${dist_name}"
+ if [ ! -d "${SEDONADB_SOURCE_DIR}" ]; then
+ pushd $SEDONADB_TMPDIR
+ fetch_archive ${dist_name}
+ tar xf ${dist_name}.tar.gz
+
+ # Ensure submodules are where tests expect them to be
+ pushd "${SEDONADB_SOURCE_DIR}/submodules"
+ git clone https://github.com/apache/sedona-testing.git
+ git clone https://github.com/geoarrow/geoarrow-data.git
+ popd
+
+ popd
+ fi
+ fi
+}
+
+test_source_distribution() {
+ pushd $SEDONADB_SOURCE_DIR
+
+ if [ ${TEST_RUST} -gt 0 ]; then
+ test_rust
+ fi
+
+ if [ ${TEST_PYTHON} -gt 0 ]; then
+ test_python
+ fi
+
+ popd
+}
+
+# By default test all functionalities.
+# To deactivate one test, deactivate the test and all of its dependents
+# To explicitly select one test, set TEST_DEFAULT=0 TEST_X=1
+: ${TEST_DEFAULT:=1}
+
+: ${TEST_SOURCE:=${TEST_DEFAULT}}
+: ${TEST_RUST:=${TEST_SOURCE}}
+: ${TEST_PYTHON:=${TEST_SOURCE}}
+
+TEST_SUCCESS=no
+
+setup_tempdir
+ensure_source_directory
+test_source_distribution
+
+TEST_SUCCESS=yes
+
+echo "Release candidate ${VERSION}-RC${RC_NUMBER} looks good!"
+exit 0
diff --git a/sedona-cli/Cargo.toml b/sedona-cli/Cargo.toml
index 3a48b53..08ac0bb 100644
--- a/sedona-cli/Cargo.toml
+++ b/sedona-cli/Cargo.toml
@@ -60,6 +60,6 @@ mimalloc = { workspace = true, optional = true }
libmimalloc-sys = { workspace = true, optional = true }
regex = { workspace = true }
rustyline = "15.0"
-sedona = { path = "../rust/sedona", features = ["aws", "gcp", "http", "proj",
"s2geography"] }
+sedona = { path = "../rust/sedona", features = ["aws", "gcp", "http", "proj"] }
sedona-tg = { path = "../c/sedona-tg" }
tokio = { workspace = true, features = ["macros", "rt", "rt-multi-thread",
"sync", "parking_lot", "signal"] }