From 9f0173462a6664da1be7dacece978fe88f824817 Mon Sep 17 00:00:00 2001 From: Dianjin Wang Date: Wed, 20 May 2026 14:06:44 +0800 Subject: [PATCH 1/2] Packaging: Enable RPM package relocation via --prefix Refactor the RPM spec to properly support rpm --prefix for custom install locations. - Split hardcoded install path into base_dir and name components - Set Prefix to the base directory (/usr/local) so RPM's relocate engine can substitute it correctly - Change symlink from absolute to relative so it remains valid after relocation - Update %post/%postun scriptlets to use RPM macro expansion for the actual relocated path instead of hardcoded paths Assisted-by: Claude Code --- .../rpm/apache-cloudberry-db-incubating.spec | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/devops/build/packaging/rpm/apache-cloudberry-db-incubating.spec b/devops/build/packaging/rpm/apache-cloudberry-db-incubating.spec index e228f8fe76a..6cc007858ca 100644 --- a/devops/build/packaging/rpm/apache-cloudberry-db-incubating.spec +++ b/devops/build/packaging/rpm/apache-cloudberry-db-incubating.spec @@ -15,7 +15,9 @@ # specific language governing permissions and limitations # under the License. -%define cloudberry_install_dir /usr/local/cloudberry-db +%define cloudberry_base_dir /usr/local +%define cloudberry_name cloudberry-db +%define cloudberry_install_dir %{cloudberry_base_dir}/%{cloudberry_name} # Add at the top of the spec file # Default to non-debug build @@ -41,7 +43,7 @@ License: ASL 2.0 URL: https://cloudberry.apache.org Vendor: Apache Cloudberry (Incubating) Group: Applications/Databases -Prefix: %{cloudberry_install_dir} +Prefix: %{cloudberry_base_dir} # Disabled as we are shipping GO programs (e.g. gpbackup) %define _missing_build_ids_terminate_build 0 @@ -161,25 +163,36 @@ cp %{_sourcedir}/NOTICE %{buildroot}%{cloudberry_install_dir}-%{version}/ cp %{_sourcedir}/DISCLAIMER %{buildroot}%{cloudberry_install_dir}-%{version}/ cp -R %{_sourcedir}/licenses %{buildroot}%{cloudberry_install_dir}-%{version}/ -# Create the symbolic link -ln -sfn %{cloudberry_install_dir}-%{version} %{buildroot}%{cloudberry_install_dir} +# Create the symbolic link (use relative link so it works after relocation) +ln -sfn %{cloudberry_name}-%{version} %{buildroot}%{cloudberry_install_dir} %files -%{prefix}-%{version} -%{prefix} +%{cloudberry_install_dir}-%{version} +%{cloudberry_install_dir} %debug_package %post +# Determine the actual installation base directory after possible relocation +INSTALL_BASE=%{cloudberry_base_dir} +INSTALL_DIR=${INSTALL_BASE}/%{cloudberry_name}-%{version} +LINK_PATH=${INSTALL_BASE}/%{cloudberry_name} + +# Recreate the symbolic link at the relocated path +ln -sfn %{cloudberry_name}-%{version} "${LINK_PATH}" + # Change ownership to gpadmin.gpadmin if the gpadmin user exists if id "gpadmin" &>/dev/null; then - chown -R gpadmin:gpadmin %{cloudberry_install_dir}-%{version} - chown gpadmin:gpadmin %{cloudberry_install_dir} + chown -R gpadmin:gpadmin "${INSTALL_DIR}" + chown -h gpadmin:gpadmin "${LINK_PATH}" fi %postun if [ $1 -eq 0 ] ; then - if [ "$(readlink -f "%{cloudberry_install_dir}")" == "%{cloudberry_install_dir}-%{version}" ]; then - unlink "%{cloudberry_install_dir}" || true + INSTALL_BASE=%{cloudberry_base_dir} + LINK_PATH=${INSTALL_BASE}/%{cloudberry_name} + VERSIONED_DIR=${INSTALL_BASE}/%{cloudberry_name}-%{version} + if [ "$(readlink -f "${LINK_PATH}")" == "${VERSIONED_DIR}" ]; then + unlink "${LINK_PATH}" || true fi fi From 655812bfa5f1bb33166d3c8a7c69fc6049b527df Mon Sep 17 00:00:00 2001 From: Dianjin Wang Date: Wed, 20 May 2026 15:12:54 +0800 Subject: [PATCH 2/2] Update --- .../rpm/apache-cloudberry-db-incubating.spec | 63 +++++++++++++------ 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/devops/build/packaging/rpm/apache-cloudberry-db-incubating.spec b/devops/build/packaging/rpm/apache-cloudberry-db-incubating.spec index 6cc007858ca..b5866f15b85 100644 --- a/devops/build/packaging/rpm/apache-cloudberry-db-incubating.spec +++ b/devops/build/packaging/rpm/apache-cloudberry-db-incubating.spec @@ -144,10 +144,18 @@ completeness or stability of the code, it does indicate that the project has yet to be fully endorsed by the ASF. %prep -# No prep needed for binary RPM +# Validate required macros are provided +if [ %{version} = '%%{version}' ] ; then + echo "The macro 'version' must be supplied as rpmbuild ... --define='version [VERSION]'" + exit 1 +fi +if [ %{release} = '%%{release}' ] ; then + echo "The macro 'release' must be supplied as rpmbuild ... --define='release [RELEASE]'" + exit 1 +fi %build -# No prep needed for binary RPM +# No build needed for binary RPM %install rm -rf %{buildroot} @@ -157,42 +165,57 @@ mkdir -p %{buildroot}%{cloudberry_install_dir}-%{version} cp -R %{cloudberry_install_dir}/* %{buildroot}%{cloudberry_install_dir}-%{version} +# Pre-compile Python bytecode to reduce first-run latency +if command -v python3 &>/dev/null; then + python3 -m compileall -q -x test %{buildroot}%{cloudberry_install_dir}-%{version} || : +fi + # Copy Apache mandatory compliance files from the SOURCES directory into the installation directory cp %{_sourcedir}/LICENSE %{buildroot}%{cloudberry_install_dir}-%{version}/ cp %{_sourcedir}/NOTICE %{buildroot}%{cloudberry_install_dir}-%{version}/ cp %{_sourcedir}/DISCLAIMER %{buildroot}%{cloudberry_install_dir}-%{version}/ cp -R %{_sourcedir}/licenses %{buildroot}%{cloudberry_install_dir}-%{version}/ -# Create the symbolic link (use relative link so it works after relocation) -ln -sfn %{cloudberry_name}-%{version} %{buildroot}%{cloudberry_install_dir} - %files %{cloudberry_install_dir}-%{version} -%{cloudberry_install_dir} +%config(noreplace) %{cloudberry_install_dir}-%{version}/cloudberry-env.sh %debug_package %post -# Determine the actual installation base directory after possible relocation -INSTALL_BASE=%{cloudberry_base_dir} -INSTALL_DIR=${INSTALL_BASE}/%{cloudberry_name}-%{version} -LINK_PATH=${INSTALL_BASE}/%{cloudberry_name} - -# Recreate the symbolic link at the relocated path -ln -sfn %{cloudberry_name}-%{version} "${LINK_PATH}" +# RPM_INSTALL_PREFIX is set dynamically by RPM to the actual --prefix value +LINK_PATH="${RPM_INSTALL_PREFIX}/%{cloudberry_name}" +VERSIONED_DIR="${RPM_INSTALL_PREFIX}/%{cloudberry_name}-%{version}" + +if [ ! -e "${LINK_PATH}" ]; then + # No existing link or file, create symlink + ln -fsT "${VERSIONED_DIR}" "${LINK_PATH}" || : +elif [ -L "${LINK_PATH}" ] && [ -e "${LINK_PATH}/bin/postgres" ] && [ -e "${LINK_PATH}/cloudberry-env.sh" ]; then + # Existing valid Cloudberry installation, check major version + original_version=$(source "${LINK_PATH}/cloudberry-env.sh"; "${LINK_PATH}/bin/postgres" --gp-version | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+') + original_major_version=${original_version%%.*} + current_major_version=%{version} + current_major_version=${current_major_version%%.*} + if [ "${original_major_version}" == "${current_major_version}" ]; then + ln -fsT "${VERSIONED_DIR}" "${LINK_PATH}" || : + else + echo "Warning: symlink ${LINK_PATH} not updated because it points to a different major version (${original_major_version})" + fi +else + echo "Warning: symlink ${LINK_PATH} not created because a file or directory already exists at that location" +fi # Change ownership to gpadmin.gpadmin if the gpadmin user exists if id "gpadmin" &>/dev/null; then - chown -R gpadmin:gpadmin "${INSTALL_DIR}" - chown -h gpadmin:gpadmin "${LINK_PATH}" + chown -R gpadmin:gpadmin "${VERSIONED_DIR}" + if [ -L "${LINK_PATH}" ]; then + chown -h gpadmin:gpadmin "${LINK_PATH}" + fi fi %postun if [ $1 -eq 0 ] ; then - INSTALL_BASE=%{cloudberry_base_dir} - LINK_PATH=${INSTALL_BASE}/%{cloudberry_name} - VERSIONED_DIR=${INSTALL_BASE}/%{cloudberry_name}-%{version} - if [ "$(readlink -f "${LINK_PATH}")" == "${VERSIONED_DIR}" ]; then - unlink "${LINK_PATH}" || true + if [ "$(readlink -f "${RPM_INSTALL_PREFIX}/%{cloudberry_name}")" == "${RPM_INSTALL_PREFIX}/%{cloudberry_name}-%{version}" ]; then + unlink "${RPM_INSTALL_PREFIX}/%{cloudberry_name}" || : fi fi