Skip to content

Packaging: Enable RPM package relocation via --prefix#1758

Open
tuhaihe wants to merge 2 commits into
apache:mainfrom
tuhaihe:update-rpm-relocate
Open

Packaging: Enable RPM package relocation via --prefix#1758
tuhaihe wants to merge 2 commits into
apache:mainfrom
tuhaihe:update-rpm-relocate

Conversation

@tuhaihe

@tuhaihe tuhaihe commented May 20, 2026

Copy link
Copy Markdown
Member

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

Fixes #ISSUE_Number

What does this PR do?

Type of Change

  • Bug fix (non-breaking change)
  • New feature (non-breaking change)
  • Breaking change (fix or feature with breaking changes)
  • Documentation update

Breaking Changes

Test Plan

  • Unit tests added/updated
  • Integration tests added/updated
  • Passed make installcheck
  • Passed make -C src/test installcheck-cbdb-parallel

Impact

Performance:

User-facing changes:

Dependencies:

Checklist

Additional Context

CI Skip Instructions


@tuhaihe

tuhaihe commented May 20, 2026

Copy link
Copy Markdown
Member Author

No rush to review. I will test it by packaging a new RPM.

@tuhaihe
tuhaihe marked this pull request as draft May 20, 2026 06:09
@tuhaihe
tuhaihe force-pushed the update-rpm-relocate branch from 655812b to 4a76ab5 Compare July 21, 2026 10:44
Rework the RPM packaging so Cloudberry can be installed to a custom
location and so multiple major versions can coexist, aligning the
behavior with Greenplum's packaging model.

Relocation (rpm --prefix):
- Split the hardcoded install path into base_dir + name components and
  set Prefix to the base directory (/usr/local) so RPM's relocate
  engine can substitute it correctly.
- Move the convenience symlink out of %files and create it in %post
  using RPM_INSTALL_PREFIX, so it follows the actual --prefix (with a
  fallback to the default base_dir). %postun removes the symlink only
  when it still points to the version being erased.
- Disable build-id links so they are not emitted outside the
  relocatable prefix.

Major-version coexistence:
- Embed the major version in the package Name
  (apache-cloudberry-db-incubating-<major>), derived from %{version},
  so different major versions register as distinct packages and can be
  installed side by side (dnf) or under separate prefixes (rpm -i).
- Obsolete the previous unversioned package name on upgrade; this does
  not match the versioned names, so majors still coexist.
- In %post, move the generic symlink only when the existing target is
  the same major version, leaving other majors untouched. The version
  is parsed from the target directory name rather than by sourcing
  environment files or executing installed binaries.
- Keep the published file name in the historical format (without the
  "-<major>" segment) by renaming artifacts in build-rpm.sh; the file
  name does not affect the Name/Version stored in the RPM header.

Packaging correctness and hardening:
- Stop changing installed files to gpadmin ownership in %post; the
  package tree stays root-owned.
- Do not expose bundled private shared libraries (libpq.so.5, etc.) as
  Provides, and do not require them from the system; they ship in the
  package and are resolved via RPATH.
- Validate that version/release macros are supplied, mark
  cloudberry-env.sh as %config(noreplace), copy the tree with cp -a to
  preserve hidden files and attributes, add coreutils scriptlet
  dependencies, add python3 to the el9 runtime requires, and update the
  license tag to the SPDX identifier Apache-2.0.

CI workflows:
- Query the installed package by glob (rpm -qa 'apache-...*') instead of
  the fixed name, since the registered Name now carries the major.
- Keep locating the published artifact by its historical file name,
  which build-rpm.sh restores after the build.

Assisted-by: Claude Code
Assisted-by: DeepSeek
@tuhaihe
tuhaihe force-pushed the update-rpm-relocate branch from c000d97 to 93a9c03 Compare July 23, 2026 06:36
@tuhaihe
tuhaihe marked this pull request as ready for review July 23, 2026 08:54
@tuhaihe

tuhaihe commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

Updates:

Rework the RPM packaging so Cloudberry can be installed to a custom
location and so multiple major versions can coexist, aligning the
behavior with Greenplum's packaging model.

Relocation (rpm --prefix):
- Split the hardcoded install path into base_dir + name components and
  set Prefix to the base directory (/usr/local) so RPM's relocate
  engine can substitute it correctly.
- Move the convenience symlink out of %files and create it in %post
  using RPM_INSTALL_PREFIX, so it follows the actual --prefix (with a
  fallback to the default base_dir). %postun removes the symlink only
  when it still points to the version being erased.
- Disable build-id links so they are not emitted outside the
  relocatable prefix.

Major-version coexistence:
- Embed the major version in the package Name
  (apache-cloudberry-db-incubating-<major>), derived from %{version},
  so different major versions register as distinct packages and can be
  installed side by side (dnf) or under separate prefixes (rpm -i).
- Obsolete the previous unversioned package name on upgrade; this does
  not match the versioned names, so majors still coexist.
- In %post, move the generic symlink only when the existing target is
  the same major version, leaving other majors untouched. The version
  is parsed from the target directory name rather than by sourcing
  environment files or executing installed binaries.
- Keep the published file name in the historical format (without the
  "-<major>" segment) by renaming artifacts in build-rpm.sh; the file
  name does not affect the Name/Version stored in the RPM header.

Packaging correctness and hardening:
- Stop changing installed files to gpadmin ownership in %post; the
  package tree stays root-owned.
- Do not expose bundled private shared libraries (libpq.so.5, etc.) as
  Provides, and do not require them from the system; they ship in the
  package and are resolved via RPATH.
- Validate that version/release macros are supplied, mark
  cloudberry-env.sh as %config(noreplace), copy the tree with cp -a to
  preserve hidden files and attributes, add coreutils scriptlet
  dependencies, add python3 to the el9 runtime requires, and update the
  license tag to the SPDX identifier Apache-2.0.

CI workflows:
- Query the installed package by glob (rpm -qa 'apache-...*') instead of
  the fixed name, since the registered Name now carries the major.
- Keep locating the published artifact by its historical file name,
  which build-rpm.sh restores after the build.

@tuhaihe

tuhaihe commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

Now this PR is ready for review.

cc @leborchuk @my-ship-it PTAL, thanks!

Would like to have these changes for coming 2.2 release.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the RPM packaging for Apache Cloudberry DB to support relocatable installs via rpm --prefix, while also introducing a major-version-suffixed RPM Name to allow side-by-side installation of different major versions. It also adjusts the build script and CI workflows to handle the new RPM metadata while keeping historical artifact filenames.

Changes:

  • Refactor the RPM spec to split install path into base/name components, set Prefix to the base dir, and update %post/%postun to compute paths based on the (relocated) prefix.
  • Version the RPM Name with the major version and add a build step to rename produced RPM files back to the historical published filename format.
  • Update GitHub Actions workflows to query/install packages by wildcard name and ensure gpadmin can write to the installed tree during tests.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
devops/build/packaging/rpm/build-rpm.sh Renames generated RPM artifacts to preserve historical published filenames despite versioned RPM Name.
devops/build/packaging/rpm/apache-cloudberry-db-incubating.spec Refactors RPM metadata and scriptlets to support --prefix relocation and major-versioned package naming.
.github/workflows/build-dbg-cloudberry.yml Updates RPM query steps to handle the new versioned package name and documents artifact renaming.
.github/workflows/build-cloudberry.yml Updates RPM query steps and adds install-tree ownership adjustment for tests.
.github/workflows/build-cloudberry-rocky8.yml Same as above for Rocky 8 workflow variant.
.github/workflows/build-cloudberry-rocky10.yml Same as above for Rocky 10 workflow variant.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +53 to 58
Name: apache-cloudberry-db-incubating-%{cloudberry_major_version}
# Replace the previous unversioned package on upgrade. This targets only the
# old fixed name; it does NOT match apache-cloudberry-db-incubating-<major>,
# so different major versions still coexist.
Obsoletes: apache-cloudberry-db-incubating < %{version}-%{release}
Version: %{version}
Comment on lines 197 to +199
%files
%{prefix}-%{version}
%{prefix}
%{cloudberry_install_dir}-%{version}
%config(noreplace) %{cloudberry_install_dir}-%{version}/cloudberry-env.sh
Comment on lines +209 to +228
LINK_PATH="${INSTALL_BASE}/%{cloudberry_name}"
VERSIONED_DIR="${INSTALL_BASE}/%{cloudberry_name}-%{version}"

if [ ! -e "${LINK_PATH}" ] && [ ! -L "${LINK_PATH}" ]; then
# Nothing at the symlink location yet — create it.
ln -s "${VERSIONED_DIR}" "${LINK_PATH}" || :
elif [ -L "${LINK_PATH}" ]; then
# A symlink already exists. Update it when it points to a
# recognized Cloudberry versioned directory.
EXISTING_TARGET=$(readlink -f -- "${LINK_PATH}" 2>/dev/null || :)
EXISTING_NAME=${EXISTING_TARGET##*/}

case "${EXISTING_NAME}" in
%{cloudberry_name}-*)
EXISTING_VERSION=${EXISTING_NAME#%{cloudberry_name}-}
EXISTING_MAJOR=${EXISTING_VERSION%%.*}
if [ "${EXISTING_MAJOR}" = "%{cloudberry_major_version}" ]; then
# Same major version: move the generic symlink to this build.
ln -sfnT "${VERSIONED_DIR}" "${LINK_PATH}" || :
else

@leborchuk leborchuk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants