mirror of
https://github.com/XRPLF/rippled.git
synced 2026-09-27 15:28:03 +00:00
build: Add assert-enabled builds and packages
This commit is contained in:
46
.github/scripts/strategy-matrix/generate.py
vendored
46
.github/scripts/strategy-matrix/generate.py
vendored
@@ -15,6 +15,14 @@ _BASE_CMAKE_ARGS = [
|
||||
"-Drust=ON",
|
||||
]
|
||||
|
||||
# The package formats a config can be packaged as, each with its own
|
||||
# install-test job in reusable-package.yml.
|
||||
PACKAGE_TYPES = ("deb", "rpm")
|
||||
|
||||
# The package name a variant suffixes, as build_pkg.py's BASE_NAME spells it:
|
||||
# the two have to agree, or the artifact globs miss what was built.
|
||||
BASE_NAME = "xrpld"
|
||||
|
||||
# Maps sanitizer names (as used in cmake) to short config-name suffixes.
|
||||
_SANITIZER_SUFFIX: dict[str, str] = {
|
||||
"address": "asan",
|
||||
@@ -62,10 +70,20 @@ def get_cmake_args(build_type: str, extra_args: str) -> str:
|
||||
class PackageConfig:
|
||||
"""The 'package' map of a config whose binaries are also packaged."""
|
||||
|
||||
type: str # "deb" or "rpm"; has to match what the image provides
|
||||
type: str # has to match what the image provides
|
||||
# The packaging container image: a vanilla distro image, not the nix image
|
||||
# the config itself builds in.
|
||||
image: str
|
||||
# A flavour of the package, named xrpld-<variant>, for a config whose
|
||||
# binaries are not the plain release build. A variant needs no counterpart
|
||||
# in the other format.
|
||||
variant: str = ""
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
assert self.type in PACKAGE_TYPES, (
|
||||
f"unsupported package type {self.type!r}: "
|
||||
f"use one of {', '.join(PACKAGE_TYPES)}."
|
||||
)
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
@@ -178,6 +196,8 @@ class PackagingEntry:
|
||||
validator_keys_artifact_name: str
|
||||
image: str
|
||||
package_type: str # "deb" or "rpm"; drives the format-specific steps
|
||||
package_variant: str # passed to build_pkg.py --variant; empty for xrpld
|
||||
package_name: str # the name it builds under, which the artifact globs use
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -267,12 +287,32 @@ def expand_linux_packaging(linux: LinuxFile) -> list[PackagingEntry]:
|
||||
validator_keys_artifact_name=f"validator-keys-{name}",
|
||||
image=cfg.package.image,
|
||||
package_type=cfg.package.type,
|
||||
package_variant=cfg.package.variant,
|
||||
package_name=(
|
||||
f"{BASE_NAME}-{cfg.package.variant}"
|
||||
if cfg.package.variant
|
||||
else BASE_NAME
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
return entries
|
||||
|
||||
|
||||
def package_names_by_type(entries: list[PackagingEntry]) -> dict[str, list[str]]:
|
||||
"""The names of the packages in 'entries', keyed by format.
|
||||
|
||||
Derived from the packaging matrix rather than listed again, so the packages
|
||||
the install-test jobs look for are the packages that were built.
|
||||
"""
|
||||
return {
|
||||
package_type: sorted(
|
||||
{e.package_name for e in entries if e.package_type == package_type}
|
||||
)
|
||||
for package_type in PACKAGE_TYPES
|
||||
}
|
||||
|
||||
|
||||
def expand_platform_matrix(pf: PlatformFile, minimal: bool) -> list[MatrixEntry]:
|
||||
"""Expand a PlatformFile (macOS or Windows) into matrix entries.
|
||||
|
||||
@@ -341,6 +381,10 @@ if __name__ == "__main__":
|
||||
|
||||
if args.packaging:
|
||||
matrix = expand_linux_packaging(LinuxFile.load(THIS_DIR / "linux.json"))
|
||||
# One list per format, so each install-test job installs the packages its
|
||||
# own format produced.
|
||||
for package_type, names in package_names_by_type(matrix).items():
|
||||
print(f"{package_type}_package_names={json.dumps(names)}")
|
||||
else:
|
||||
if args.config in ("linux", None):
|
||||
matrix += expand_linux_matrix(
|
||||
|
||||
13
.github/scripts/strategy-matrix/linux.json
vendored
13
.github/scripts/strategy-matrix/linux.json
vendored
@@ -76,6 +76,19 @@
|
||||
"type": "deb",
|
||||
"image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-49cdc10"
|
||||
}
|
||||
},
|
||||
{
|
||||
"compiler": ["gcc"],
|
||||
"build_type": ["Release"],
|
||||
"arch": ["amd64"],
|
||||
"minimal": false,
|
||||
"suffix": "assert",
|
||||
"extra_cmake_args": "-Dvalidator_keys=ON -Dassert=ON",
|
||||
"package": {
|
||||
"type": "deb",
|
||||
"image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-49cdc10",
|
||||
"variant": "assert"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
|
||||
1
.github/workflows/on-pr.yml
vendored
1
.github/workflows/on-pr.yml
vendored
@@ -85,6 +85,7 @@ jobs:
|
||||
.github/workflows/reusable-build-test.yml
|
||||
.github/workflows/reusable-check-autogen.yml
|
||||
.github/workflows/reusable-clang-tidy.yml
|
||||
.github/workflows/reusable-package-test-install.yml
|
||||
.github/workflows/reusable-package.yml
|
||||
.github/workflows/reusable-rust.yml
|
||||
.github/workflows/reusable-strategy-matrix.yml
|
||||
|
||||
1
.github/workflows/on-trigger.yml
vendored
1
.github/workflows/on-trigger.yml
vendored
@@ -23,6 +23,7 @@ on:
|
||||
- ".github/workflows/reusable-build-test.yml"
|
||||
- ".github/workflows/reusable-check-autogen.yml"
|
||||
- ".github/workflows/reusable-clang-tidy.yml"
|
||||
- ".github/workflows/reusable-package-test-install.yml"
|
||||
- ".github/workflows/reusable-package.yml"
|
||||
- ".github/workflows/reusable-rust.yml"
|
||||
- ".github/workflows/reusable-strategy-matrix.yml"
|
||||
|
||||
103
.github/workflows/reusable-package-test-install.yml
vendored
Normal file
103
.github/workflows/reusable-package-test-install.yml
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
# Install one package format on every distro family it targets, one job per
|
||||
# package name and image, and run the binaries there. Called once per format by
|
||||
# reusable-package.yml, which owns the names and the image lists.
|
||||
name: Install packages
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
package_type:
|
||||
description: 'The package format to install ("deb" or "rpm").'
|
||||
required: true
|
||||
type: string
|
||||
package_names:
|
||||
description: "JSON array of package names built for this format."
|
||||
required: true
|
||||
type: string
|
||||
images:
|
||||
description: "JSON array of container images to install in."
|
||||
required: true
|
||||
type: string
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
PACKAGE_DIR: packages
|
||||
|
||||
jobs:
|
||||
install:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
package_name: ${{ fromJson(inputs.package_names) }}
|
||||
image: ${{ fromJson(inputs.images) }}
|
||||
name: "${{ matrix.package_name }} on ${{ matrix.image }}"
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
container: ${{ matrix.image }}
|
||||
timeout-minutes: 5
|
||||
|
||||
steps:
|
||||
# Every package lands in one directory; the step below picks its own,
|
||||
# which keeps this independent of the artifact names.
|
||||
- name: Download package artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
pattern: "*-pkg"
|
||||
merge-multiple: true
|
||||
path: ${{ env.PACKAGE_DIR }}
|
||||
|
||||
- name: Find the package
|
||||
id: find
|
||||
env:
|
||||
PACKAGE_NAME: ${{ matrix.package_name }}
|
||||
PACKAGE_TYPE: ${{ inputs.package_type }}
|
||||
run: |
|
||||
# The version follows the name, separated by '_' in a DEB and '-' in an
|
||||
# RPM. Requiring a digit after it is what keeps 'xrpld' from picking up
|
||||
# another package, such as 'xrpld-assert'.
|
||||
pattern="${PACKAGE_NAME}[_-][0-9]*.${PACKAGE_TYPE}"
|
||||
package="$(find "${PACKAGE_DIR}" -type f -name "${pattern}" -print -quit)"
|
||||
test -n "${package}" || {
|
||||
echo "no ${pattern} found in ${PACKAGE_DIR}" >&2
|
||||
exit 1
|
||||
}
|
||||
echo "package=${package}" >>"${GITHUB_OUTPUT}"
|
||||
|
||||
- name: Install the DEB
|
||||
if: ${{ inputs.package_type == 'deb' }}
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
PACKAGE: ${{ steps.find.outputs.package }}
|
||||
run: |
|
||||
# Stock Debian and Ubuntu images carry no package lists, so apt has
|
||||
# nothing to resolve the systemd dependency from until it fetches them.
|
||||
apt-get update -qq
|
||||
apt-get install -y "./${PACKAGE}"
|
||||
|
||||
- name: Install the RPM
|
||||
if: ${{ inputs.package_type == 'rpm' }}
|
||||
env:
|
||||
PACKAGE: ${{ steps.find.outputs.package }}
|
||||
run: dnf install -y "./${PACKAGE}"
|
||||
|
||||
- name: Run xrpld
|
||||
run: xrpld --version
|
||||
|
||||
- name: Run validator-keys
|
||||
run: validator-keys --version
|
||||
|
||||
- name: Run rippled, the legacy compatibility symlink
|
||||
run: rippled --version
|
||||
|
||||
- name: Check the service account
|
||||
run: id xrpld
|
||||
|
||||
- name: Check the state directory
|
||||
run: test -d /var/lib/xrpld
|
||||
|
||||
- name: Check the log directory
|
||||
run: test -d /var/log/xrpld
|
||||
178
.github/workflows/reusable-package.yml
vendored
178
.github/workflows/reusable-package.yml
vendored
@@ -3,8 +3,10 @@
|
||||
#
|
||||
# - 'package' builds and signs one format per config that carries a "package"
|
||||
# map in linux.json; that map names the container image and the format
|
||||
# - 'test-install' installs what was built on a range of distros and runs the
|
||||
# binaries there, so a package that cannot be installed never reaches Nexus
|
||||
# - 'test-install-deb' and 'test-install-rpm' call
|
||||
# reusable-package-test-install.yml to install what was built on a range of
|
||||
# distros and run the binaries there, so a package that cannot be installed
|
||||
# never reaches Nexus
|
||||
# - 'publish' uploads with the image's publish_pkg.py, doing a --dry-run
|
||||
# unless 'publish: true'
|
||||
#
|
||||
@@ -49,6 +51,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.generate.outputs.matrix }}
|
||||
deb_package_names: ${{ steps.generate.outputs.deb_package_names }}
|
||||
rpm_package_names: ${{ steps.generate.outputs.rpm_package_names }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
@@ -107,6 +111,7 @@ jobs:
|
||||
- name: Build package
|
||||
env:
|
||||
PACKAGE_TYPE: ${{ matrix.package_type }}
|
||||
PACKAGE_VARIANT: ${{ matrix.package_variant }}
|
||||
PKG_RELEASE: ${{ steps.release_info.outputs.pkg_release }}
|
||||
CHANNEL: ${{ steps.release_info.outputs.channel }}
|
||||
run: |
|
||||
@@ -114,6 +119,7 @@ jobs:
|
||||
--package-type "${PACKAGE_TYPE}" \
|
||||
--build-dir "${BUILD_DIR}" \
|
||||
--pkg-release "${PKG_RELEASE}" \
|
||||
--variant "${PACKAGE_VARIANT}" \
|
||||
--channel "${CHANNEL}"
|
||||
|
||||
# Before the upload, so the artifact, the tested package and the published
|
||||
@@ -125,14 +131,17 @@ jobs:
|
||||
run: ./package/sign_rpm.py --package-dir "${BUILD_DIR}"
|
||||
|
||||
# Split from the debug symbols, which are an order of magnitude larger, so
|
||||
# that test-install downloads only what it installs.
|
||||
# that test-install downloads only what it installs. In the globs below the
|
||||
# version follows the name, separated by '_' in a DEB and '-' in an RPM. A
|
||||
# version starts with a digit and a longer name does not, so that one digit
|
||||
# is what tells 'xrpld-3.4.1-...' from 'xrpld-assert-3.4.1-...'.
|
||||
- name: Upload package artifact
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: ${{ matrix.xrpld_artifact_name }}-pkg
|
||||
path: |
|
||||
${{ env.BUILD_DIR }}/debbuild/xrpld_*.deb
|
||||
${{ env.BUILD_DIR }}/rpmbuild/RPMS/**/xrpld-[0-9]*.rpm
|
||||
${{ env.BUILD_DIR }}/debbuild/${{ matrix.package_name }}_[0-9]*.deb
|
||||
${{ env.BUILD_DIR }}/rpmbuild/RPMS/**/${{ matrix.package_name }}-[0-9]*.rpm
|
||||
if-no-files-found: error
|
||||
|
||||
- name: Upload debug symbol artifact
|
||||
@@ -140,129 +149,52 @@ jobs:
|
||||
with:
|
||||
name: ${{ matrix.xrpld_artifact_name }}-pkg-debug
|
||||
path: |
|
||||
${{ env.BUILD_DIR }}/debbuild/xrpld-dbgsym_*.deb
|
||||
${{ env.BUILD_DIR }}/debbuild/xrpld-dbgsym_*.ddeb
|
||||
${{ env.BUILD_DIR }}/rpmbuild/RPMS/**/xrpld-debuginfo-*.rpm
|
||||
${{ env.BUILD_DIR }}/debbuild/${{ matrix.package_name }}-dbgsym_[0-9]*.deb
|
||||
${{ env.BUILD_DIR }}/debbuild/${{ matrix.package_name }}-dbgsym_[0-9]*.ddeb
|
||||
${{ env.BUILD_DIR }}/rpmbuild/RPMS/**/${{ matrix.package_name }}-debuginfo-[0-9]*.rpm
|
||||
if-no-files-found: error
|
||||
|
||||
# Every distro family the packages target, oldest release first, so both ends
|
||||
# of the dependency range they declare are exercised.
|
||||
test-install:
|
||||
needs: [package]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- package_type: deb
|
||||
image: debian:11
|
||||
- package_type: deb
|
||||
image: debian:12
|
||||
- package_type: deb
|
||||
image: debian:13
|
||||
- package_type: deb
|
||||
image: ubuntu:20.04
|
||||
- package_type: deb
|
||||
image: ubuntu:22.04
|
||||
- package_type: deb
|
||||
image: ubuntu:24.04
|
||||
- package_type: deb
|
||||
image: ubuntu:26.04
|
||||
# One call per format, so a variant packaged for one format is installed for
|
||||
# that format alone. The images are every distro family that format targets,
|
||||
# oldest release first, so both ends of the dependency range the packages
|
||||
# declare are exercised.
|
||||
test-install-deb:
|
||||
needs: [generate-matrix, package]
|
||||
name: install deb
|
||||
uses: ./.github/workflows/reusable-package-test-install.yml
|
||||
with:
|
||||
package_type: deb
|
||||
package_names: ${{ needs.generate-matrix.outputs.deb_package_names }}
|
||||
images: |
|
||||
[
|
||||
"debian:11",
|
||||
"debian:12",
|
||||
"debian:13",
|
||||
"ubuntu:20.04",
|
||||
"ubuntu:22.04",
|
||||
"ubuntu:24.04",
|
||||
"ubuntu:26.04"
|
||||
]
|
||||
|
||||
- package_type: rpm
|
||||
image: almalinux:9
|
||||
- package_type: rpm
|
||||
image: almalinux:10
|
||||
- package_type: rpm
|
||||
image: rockylinux/rockylinux:9
|
||||
- package_type: rpm
|
||||
image: rockylinux/rockylinux:10
|
||||
- package_type: rpm
|
||||
image: registry.access.redhat.com/ubi9/ubi
|
||||
- package_type: rpm
|
||||
image: registry.access.redhat.com/ubi10/ubi
|
||||
name: "install ${{ matrix.package_type }} on ${{ matrix.image }}"
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ubuntu-latest
|
||||
container: ${{ matrix.image }}
|
||||
timeout-minutes: 5
|
||||
|
||||
steps:
|
||||
# Both formats land in one directory; the step below picks its own by
|
||||
# extension, so this stays independent of the artifact names.
|
||||
- name: Download package artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
pattern: "*-pkg"
|
||||
merge-multiple: true
|
||||
path: ${{ env.PACKAGE_DIR }}
|
||||
|
||||
- name: Find the package
|
||||
id: find
|
||||
env:
|
||||
PACKAGE_TYPE: ${{ matrix.package_type }}
|
||||
run: |
|
||||
package="$(find "${PACKAGE_DIR}" -type f -name "*.${PACKAGE_TYPE}" -print -quit)"
|
||||
test -n "${package}" || {
|
||||
echo "no .${PACKAGE_TYPE} found in ${PACKAGE_DIR}" >&2
|
||||
exit 1
|
||||
}
|
||||
echo "package=${package}" >>"${GITHUB_OUTPUT}"
|
||||
|
||||
# Debian 11 went end-of-life on 2026-08-31
|
||||
# (https://www.debian.org/News/2026/20260831) and its packages are
|
||||
# already partly gone from deb.debian.org, so switch to the
|
||||
# snapshot.debian.org entries the image ships commented out in its
|
||||
# sources.list: they are pinned to the snapshot the image was built
|
||||
# from, so they serve every version it needs and never go away.
|
||||
# Snapshots keep their original, long-passed Valid-Until, hence the
|
||||
# disabled check; the retries absorb snapshot.debian.org's throttling.
|
||||
- name: Switch Debian 11 to snapshot.debian.org
|
||||
if: ${{ matrix.image == 'debian:11' }}
|
||||
run: |
|
||||
sed -i 's|^deb |# deb |; s|^# deb http://snapshot|deb http://snapshot|' /etc/apt/sources.list
|
||||
printf '%s\n' \
|
||||
'Acquire::Check-Valid-Until "false";' \
|
||||
'Acquire::Retries "3";' \
|
||||
>/etc/apt/apt.conf.d/99snapshot
|
||||
|
||||
- name: Install the DEB
|
||||
if: ${{ matrix.package_type == 'deb' }}
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
PACKAGE: ${{ steps.find.outputs.package }}
|
||||
run: |
|
||||
# Stock Debian and Ubuntu images carry no package lists, so apt has
|
||||
# nothing to resolve the systemd dependency from until it fetches them.
|
||||
apt-get update -qq
|
||||
apt-get install -y "./${PACKAGE}"
|
||||
|
||||
- name: Install the RPM
|
||||
if: ${{ matrix.package_type == 'rpm' }}
|
||||
env:
|
||||
PACKAGE: ${{ steps.find.outputs.package }}
|
||||
run: dnf install -y "./${PACKAGE}"
|
||||
|
||||
- name: Run xrpld
|
||||
run: xrpld --version
|
||||
|
||||
- name: Run validator-keys
|
||||
run: validator-keys --version
|
||||
|
||||
- name: Run rippled, the legacy compatibility symlink
|
||||
run: rippled --version
|
||||
|
||||
- name: Check the service account
|
||||
run: id xrpld
|
||||
|
||||
- name: Check the state directory
|
||||
run: test -d /var/lib/xrpld
|
||||
|
||||
- name: Check the log directory
|
||||
run: test -d /var/log/xrpld
|
||||
test-install-rpm:
|
||||
needs: [generate-matrix, package]
|
||||
name: install rpm
|
||||
uses: ./.github/workflows/reusable-package-test-install.yml
|
||||
with:
|
||||
package_type: rpm
|
||||
package_names: ${{ needs.generate-matrix.outputs.rpm_package_names }}
|
||||
images: |
|
||||
[
|
||||
"almalinux:9",
|
||||
"almalinux:10",
|
||||
"rockylinux/rockylinux:9",
|
||||
"rockylinux/rockylinux:10",
|
||||
"registry.access.redhat.com/ubi9/ubi",
|
||||
"registry.access.redhat.com/ubi10/ubi"
|
||||
]
|
||||
|
||||
publish:
|
||||
needs: [generate-matrix, package, test-install]
|
||||
needs: [generate-matrix, package, test-install-deb, test-install-rpm]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
|
||||
|
||||
@@ -44,12 +44,18 @@ else()
|
||||
set(pkg_type rpm)
|
||||
endif()
|
||||
|
||||
# Unquoted below, so an empty value adds no argument at all.
|
||||
set(pkg_variant_option "")
|
||||
if(assert)
|
||||
set(pkg_variant_option --variant=assert)
|
||||
endif()
|
||||
|
||||
add_custom_target(
|
||||
package
|
||||
COMMAND
|
||||
${CMAKE_SOURCE_DIR}/package/build_pkg.py --package-type=${pkg_type}
|
||||
--build-dir=${CMAKE_BINARY_DIR} --pkg-release=${pkg_release}
|
||||
--channel=UNRELEASED
|
||||
${pkg_variant_option} --channel=UNRELEASED
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
DEPENDS xrpld validator-keys
|
||||
COMMENT "Building Linux ${pkg_type} package"
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
|
||||
`xrpld` is published as DEB and RPM packages for 64-bit x86 Linux.
|
||||
Use APT on Debian-based distributions such as Debian and Ubuntu,
|
||||
and YUM on Red Hat-based distributions such as RHEL, AlmaLinux, and Rocky Linux.
|
||||
and DNF on Red Hat-based distributions such as RHEL, AlmaLinux, and Rocky Linux,
|
||||
where `yum` is a symlink to `dnf`.
|
||||
To build from source instead, see [BUILD.md](../BUILD.md).
|
||||
|
||||
## Release channels
|
||||
@@ -81,7 +82,7 @@ wherever it appears in the repository configuration.
|
||||
sudo apt -y install xrpld
|
||||
```
|
||||
|
||||
### With the YUM package manager
|
||||
### With the DNF package manager
|
||||
|
||||
1. Add the XRPL Foundation package-signing key:
|
||||
|
||||
@@ -109,9 +110,23 @@ wherever it appears in the repository configuration.
|
||||
3. Install the `xrpld` package:
|
||||
|
||||
```bash
|
||||
sudo yum install -y xrpld
|
||||
sudo dnf install -y xrpld
|
||||
```
|
||||
|
||||
### Optional: the assert-enabled build
|
||||
|
||||
Every channel also carries `xrpld-assert` as a DEB, the same build with assertions
|
||||
enabled, for diagnosing a problem on a non-production server.
|
||||
It installs the same files as `xrpld` and replaces it, so install one or the other:
|
||||
|
||||
```bash
|
||||
sudo apt -y install xrpld-assert # APT removes xrpld itself
|
||||
```
|
||||
|
||||
Switching stops the service, since it is a removal and an installation rather than an upgrade,
|
||||
and APT starts it again.
|
||||
Install `xrpld` the same way to switch back.
|
||||
|
||||
## The xrpld service
|
||||
|
||||
Both package managers install a systemd unit and enable it, so `xrpld` starts on boot.
|
||||
@@ -121,7 +136,7 @@ Check whether it is already running:
|
||||
systemctl status xrpld.service
|
||||
```
|
||||
|
||||
The APT packages start it immediately as well; the YUM packages do not, so start it yourself:
|
||||
The DEB packages start it immediately as well; the RPM packages do not, so start it yourself:
|
||||
|
||||
```bash
|
||||
sudo systemctl start xrpld.service
|
||||
|
||||
@@ -15,7 +15,8 @@ package/
|
||||
publish_pkg.py Uploads built packages to the XRPLF Nexus repositories (called by CI, and shipped in that image)
|
||||
rpm/
|
||||
xrpld.spec RPM spec
|
||||
debian/ Debian control files (control, rules, copyright, xrpld.docs, xrpld.links, xrpld.lintian-overrides, source/format)
|
||||
debian/ Debian control files (control.in, lintian-overrides.in, rules, copyright, docs, links, source/format).
|
||||
The `.in` files are templates rendered by `build_pkg.py`; `docs` and `links` are staged under the package name
|
||||
shared/
|
||||
xrpld.service systemd unit file (used by both RPM and DEB)
|
||||
xrpld.sysusers sysusers.d config (used by both RPM and DEB)
|
||||
@@ -32,20 +33,74 @@ packaging job cannot drift apart. Today only `linux/amd64` is emitted. The map
|
||||
pins the full container image in `image` — edit that field to move to a new
|
||||
image and both CI and local builds pick it up — and names the format that image
|
||||
builds in `type`, which CI passes to `build_pkg.py` as `--package-type`; the two
|
||||
have to stay in step.
|
||||
have to stay in step. An optional `variant` names a flavour of the package (see
|
||||
[Package variants](#package-variants)), and CI passes it as `--variant`.
|
||||
|
||||
| Package type | Image (`configs.<distro>[].package.image` in `linux.json`) | Tools required |
|
||||
| ------------ | ---------------------------------------------------------- | -------------------------------------------------------------- |
|
||||
| RPM | `ghcr.io/xrplf/xrpld/packaging-rhel:sha-<sha>` | `rpmbuild`, `rpmsign` |
|
||||
| DEB | `ghcr.io/xrplf/xrpld/packaging-debian:sha-<sha>` | `dpkg-buildpackage`, debhelper with compat level 13, `lintian` |
|
||||
|
||||
To print the full packaging matrix (artifact names and images) for the current
|
||||
`linux.json`:
|
||||
To print the full packaging matrix (artifact names, images and package names)
|
||||
for the current `linux.json`:
|
||||
|
||||
```bash
|
||||
./.github/scripts/strategy-matrix/generate.py --packaging
|
||||
```
|
||||
|
||||
## Package variants
|
||||
|
||||
A config whose binaries are not the plain release build cannot be packaged as
|
||||
`xrpld`: both would carry the same name and version, so whichever published last
|
||||
would win. It is packaged as a **variant** instead — `variant: "assert"` in its
|
||||
`package` map, which CI passes to `build_pkg.py` as `--variant assert`,
|
||||
producing `xrpld-assert`. What the build option itself does is a build concern,
|
||||
not a packaging one; see the options table in [`BUILD.md`](../BUILD.md).
|
||||
|
||||
A variant ships the same paths as `xrpld` — `/usr/bin/xrpld`, `/etc/xrpld`,
|
||||
`xrpld.service`, `/etc/logrotate.d/xrpld` — differing only in the per-package
|
||||
documentation directory, so it declares itself a stand-in for the plain package
|
||||
rather than something installable next to it: `Conflicts`, `Replaces` and a
|
||||
versioned `Provides: xrpld` on Debian, `Conflicts` and `Provides` on RPM.
|
||||
Neither format declares `Obsoletes`, so `apt upgrade` and `dnf upgrade` keep an
|
||||
installed flavour on its own flavour, and switching is always explicit:
|
||||
|
||||
```bash
|
||||
apt-get install xrpld-assert # apt removes the plain package itself
|
||||
dnf swap xrpld xrpld-VARIANT # 'dnf install' alone stops at the conflict
|
||||
```
|
||||
|
||||
Only the DEB packages carry a variant today — `xrpld-assert` comes from the
|
||||
`debian` config alone, there being no call for an assert build on RHEL-based
|
||||
distributions — but the RPM side works the same way if one is added.
|
||||
|
||||
A switch is a removal plus an installation rather than an upgrade, so unlike a
|
||||
version upgrade it stops the service: Debian's scriptlets start it again, while
|
||||
on RPM the operator runs `systemctl start xrpld`. Configuration survives either
|
||||
way, being conffiles on Debian and `%config(noreplace)` on RPM.
|
||||
|
||||
`dnf` installs the replacement before erasing the old flavour, whose `%preun`
|
||||
would leave `xrpld.service` disabled, so `%postun` re-applies the preset when
|
||||
the unit file outlives the erase — which, since rpm keeps a file another
|
||||
installed package owns, happens only during a swap. The cost is that a
|
||||
deliberate `systemctl disable` is not carried across an RPM switch.
|
||||
|
||||
The alternative is an `xrpld-common` package owning the unit, the sysusers and
|
||||
tmpfiles snippets and the configuration, required by both flavours at an exact
|
||||
version: nothing is erased mid-swap, so no scriptlet has to detect one. It is
|
||||
not worth it for a single variant — it moves files out of the production
|
||||
package, and a sanitizer flavour would likely need its own unit anyway, putting
|
||||
the lifecycle back where it is now.
|
||||
|
||||
Adding a variant is the flavour in `VARIANTS` in `build_pkg.py`, which is the
|
||||
list `--variant` accepts, plus a config in `linux.json` with the CMake arguments
|
||||
and a `package` map naming it, for one format or for both: `generate.py
|
||||
--packaging` emits the package names per format, and the `test-install-deb` and
|
||||
`test-install-rpm` jobs install what their own format produced.
|
||||
|
||||
Operators switch between the flavours as described in
|
||||
[`docs/install.md`](../docs/install.md#optional-the-assert-enabled-build).
|
||||
|
||||
## Building packages
|
||||
|
||||
### Via CI
|
||||
@@ -56,9 +111,11 @@ Caller workflows (`on-pr.yml`, `on-tag.yml`, `on-trigger.yml`) call
|
||||
1. `package` fans out one job per config carrying a `package` map, building and
|
||||
signing in that config's container, and uploading `<config>-pkg` alongside
|
||||
`<config>-pkg-debug` for the much larger debug symbols.
|
||||
2. `test-install` installs `<config>-pkg` in the container of every distro the
|
||||
packages target and runs the binaries there, so one that cannot be installed
|
||||
never reaches Nexus.
|
||||
2. `test-install-deb` and `test-install-rpm` call
|
||||
[`reusable-package-test-install.yml`](../.github/workflows/reusable-package-test-install.yml)
|
||||
with their format's package names and distro images, installing each package
|
||||
in the container of every distro that format targets and running the binaries
|
||||
there, so one that cannot be installed never reaches Nexus.
|
||||
3. `publish` uploads both artifacts, or lists what it would upload.
|
||||
|
||||
The packaging script derives the package version from the downloaded binary's
|
||||
@@ -104,6 +161,9 @@ docker run --rm \
|
||||
# build/rpmbuild/RPMS/x86_64/*.rpm
|
||||
```
|
||||
|
||||
Add `--variant assert` to package binaries built with `-Dassert=ON`; the package
|
||||
is then named `xrpld-assert`.
|
||||
|
||||
### Via CMake (host-side target)
|
||||
|
||||
If you run CMake configure on a host that has `rpmbuild` or `dpkg-buildpackage`
|
||||
@@ -133,6 +193,9 @@ The package version is not a CMake input on this path: `build_pkg.py` derives it
|
||||
from the just-built `xrpld` binary's `xrpld --version` output. The package
|
||||
release defaults to 1 and is overridable with `-Dpkg_release=N`.
|
||||
|
||||
`-Dassert=ON` passes `--variant assert`, so such a build packages as
|
||||
`xrpld-assert` without anything else being asked for.
|
||||
|
||||
## Publishing packages
|
||||
|
||||
Packages are published to the XRPLF repositories on Sonatype Nexus at
|
||||
@@ -147,6 +210,9 @@ the event, and `publish_pkg.py` maps that channel to its repositories:
|
||||
| push to `develop` | `xrpld --version` | `develop` | `deb-develop` | `rpm-develop-hosted` |
|
||||
| tag, non-public codebase | _any_ | `private` | `deb-private` | `rpm-private-hosted` |
|
||||
|
||||
A variant is published to the same channel under its own name, so
|
||||
`xrpld-assert` never overwrites `xrpld`.
|
||||
|
||||
Only a tag names a channel — do not extend that to `develop`, where
|
||||
`BuildInfo.cpp`'s `versionString` moves through `-bN`, `-rcN` and even the final
|
||||
version during a release cycle, which would send develop builds into `stable`.
|
||||
@@ -160,7 +226,7 @@ the last, and the date and hash say which commit a package on
|
||||
`packages.xrplf.org` came from. Both reach the packaging scripts as arguments,
|
||||
so neither script derives anything itself.
|
||||
|
||||
Publishing is its own job, gated behind `test-install`, uploading from the same
|
||||
Publishing is its own job, gated behind the install tests, uploading from the same
|
||||
image that built the packages with the `publish_pkg.py` shipped in it — the
|
||||
same copy other repositories run. Without `publish: true` the job is a
|
||||
`--dry-run`, listing the uploads it would make without needing credentials, so
|
||||
@@ -175,7 +241,7 @@ Nexus owns the repository metadata; nothing here indexes anything. Worth knowing
|
||||
- Each apt-hosted repository needs a distribution (ours use `any`) and a PGP
|
||||
signing keypair configured in Nexus, which rejects one created without a
|
||||
keypair. Nexus signs the apt metadata with it, never the packages.
|
||||
- Hosted yum repositories cannot be signed by Nexus, so each `rpm-<channel>-hosted`
|
||||
- yum-hosted repositories cannot be signed by Nexus, so each `rpm-<channel>-hosted`
|
||||
repository sits behind a `rpm-<channel>` yum group repository whose metadata
|
||||
Nexus signs. Uploads go to the hosted repository; clients point at the group
|
||||
and verify the metadata with `repo_gpgcheck=1`. Nexus never signs the RPMs
|
||||
@@ -244,6 +310,19 @@ pre-release ordering convention, so RPM filenames/NVRs begin with forms like
|
||||
`xrpld-3.2.0~b1-...` and `xrpld-3.2.0~rc1-...` instead of encoding
|
||||
pre-releases with an older `0.<release>.<suffix>` RPM `Release` value.
|
||||
|
||||
`--variant` is the flavour of the package, empty by default and accepting only
|
||||
the flavours in `VARIANTS`; see [Package variants](#package-variants). The RPM
|
||||
path passes it to the spec as the `pkg_variant` macro, which suffixes `Name` and
|
||||
adds the `Conflicts`/`Provides` pair. Debian control files have no conditionals, so the DEB path renders
|
||||
`debian/control.in` and `debian/lintian-overrides.in` instead, substituting
|
||||
`@PKG@` with the package name and `@VARIANT_FIELDS@` with the
|
||||
`Conflicts`/`Replaces`/`Provides` block, empty for the plain package; a token
|
||||
with no value fails the build rather than reaching dpkg. The files debhelper
|
||||
keys by package name (`docs`, `links`, and the units) are staged under that same
|
||||
name. The paths inside the package are unchanged either way, so `debian/rules`
|
||||
reads its package name from `dh_listpackages` and names the unit, sysusers,
|
||||
tmpfiles and logrotate files with `--name xrpld`.
|
||||
|
||||
The package format is `--package-type`, either `deb` or `rpm`. It is required,
|
||||
so a job never silently builds the wrong format for the image it runs in; the
|
||||
matching build tool still has to be on PATH.
|
||||
@@ -286,8 +365,13 @@ service restart.
|
||||
1. Creates a staging source tree at `debbuild/source/` inside the build directory.
|
||||
2. Stages the binaries, configs, `README.md`, `LICENSE.md`, and
|
||||
`validator-keys-LICENSE`.
|
||||
3. Copies `package/debian/` control files into `debbuild/source/debian/`.
|
||||
4. Copies shared service/sysusers/tmpfiles/logrotate into `debian/` where `dh_installsystemd`, `dh_installsysusers`, `dh_installtmpfiles` and `dh_installlogrotate` pick them up automatically.
|
||||
3. Stages `package/debian/` into `debbuild/source/debian/`: the `.in` templates
|
||||
are rendered, and the files debhelper keys by package name (`docs`, `links`,
|
||||
`lintian-overrides`) are staged under the name being built.
|
||||
4. Copies shared service/sysusers/tmpfiles/logrotate into `debian/` as
|
||||
`<package>.xrpld.*`, which `dh_installsystemd`, `dh_installsysusers`,
|
||||
`dh_installtmpfiles` and `dh_installlogrotate` read because `debian/rules`
|
||||
passes them `--name xrpld`.
|
||||
5. Generates a minimal `debian/changelog` using `${pkg_version}-${PKG_RELEASE}`,
|
||||
where `pkg_version` is derived from the binary-reported `xrpld` version.
|
||||
6. Runs `dpkg-buildpackage -b --no-sign -d` (`-d` skips the build-dependency check, since the binary is already built). `debian/rules` uses manual `install` commands.
|
||||
|
||||
@@ -21,6 +21,14 @@ SRC_DIR = Path(__file__).resolve().parents[1]
|
||||
|
||||
PRE_RELEASE = re.compile(r"^(b|rc)(0|[1-9][0-9]*)(\+.*)?$")
|
||||
|
||||
# The package name a variant suffixes, and the name every variant keeps for its
|
||||
# on-disk paths (/usr/bin/xrpld, /etc/xrpld, xrpld.service).
|
||||
BASE_NAME = "xrpld"
|
||||
|
||||
# The flavours that can be built, '' being the plain xrpld package. A variant
|
||||
# needs a config in linux.json to be built by CI; see package/README.md.
|
||||
VARIANTS = ("", "assert")
|
||||
|
||||
# Files both packaging systems consume, staged under the same names.
|
||||
STAGED_FROM_BUILD = ("xrpld", "validator-keys", "validator-keys-LICENSE")
|
||||
STAGED_FROM_SRC = {
|
||||
@@ -31,6 +39,18 @@ STAGED_FROM_SRC = {
|
||||
}
|
||||
STAGED_UNITS = ("xrpld.service", "xrpld.sysusers", "xrpld.tmpfiles", "xrpld.logrotate")
|
||||
|
||||
# debian/ files debhelper keys by package name, staged as '<package>.<name>'.
|
||||
DEBIAN_PKG_FILES = ("docs", "links")
|
||||
|
||||
# Debian control files have no conditionals, so what makes a variant replace the
|
||||
# plain package is rendered into control.in rather than written there.
|
||||
DEB_VARIANT_FIELDS = """\
|
||||
Conflicts: xrpld
|
||||
Replaces: xrpld
|
||||
Provides: xrpld (= ${binary:Version})"""
|
||||
|
||||
TOKEN = re.compile(r"@[A-Z_]+@")
|
||||
|
||||
|
||||
def run(*command: object, cwd: Path | None = None) -> None:
|
||||
"""Echo a command and run it."""
|
||||
@@ -75,6 +95,28 @@ def package_version(reported: str) -> str:
|
||||
return version
|
||||
|
||||
|
||||
def render(template: Path, dest: Path, values: dict[str, str]) -> None:
|
||||
"""Write template to dest with its @TOKEN@ placeholders substituted.
|
||||
|
||||
A token left without a value fails the build rather than reaching dpkg.
|
||||
"""
|
||||
text = template.read_text()
|
||||
for token, value in values.items():
|
||||
text = text.replace(f"@{token}@", value)
|
||||
|
||||
missing = sorted(set(TOKEN.findall(text)))
|
||||
assert not missing, f"{template}: no value for {', '.join(missing)}"
|
||||
|
||||
# An empty value at the end of a stanza would otherwise leave a blank line,
|
||||
# which is what ends a stanza.
|
||||
dest.write_text(text.rstrip("\n") + "\n")
|
||||
|
||||
|
||||
def package_name(variant: str) -> str:
|
||||
"""The binary package name for a variant: '' -> xrpld, 'assert' -> xrpld-assert."""
|
||||
return f"{BASE_NAME}-{variant}" if variant else BASE_NAME
|
||||
|
||||
|
||||
def read_version(xrpld: Path) -> str:
|
||||
"""Read the version from the binary that is about to be packaged."""
|
||||
fields = capture(xrpld, "--version").partition("\n")[0].split()
|
||||
@@ -135,17 +177,18 @@ def stage_common(build_dir: Path, dest: Path) -> None:
|
||||
shutil.copy2(SRC_DIR / source, dest / name)
|
||||
|
||||
|
||||
def stage_units(dest: Path) -> None:
|
||||
def stage_units(dest: Path, *, prefix: str = "") -> None:
|
||||
"""Copy the systemd, sysusers, tmpfiles and logrotate files into dest.
|
||||
|
||||
Each format wants them somewhere else: rpmbuild reads them from SOURCES,
|
||||
debhelper from debian/.
|
||||
Each format wants them somewhere else: rpmbuild reads them from SOURCES by
|
||||
path, debhelper from debian/ by package name -- hence 'prefix', which makes
|
||||
the copies 'xrpld-assert.xrpld.service' and so on.
|
||||
"""
|
||||
for name in STAGED_UNITS:
|
||||
shutil.copy2(SRC_DIR / "package" / "shared" / name, dest / name)
|
||||
shutil.copy2(SRC_DIR / "package" / "shared" / name, dest / f"{prefix}{name}")
|
||||
|
||||
|
||||
def build_rpm(build_dir: Path, *, version: str, pkg_release: str) -> None:
|
||||
def build_rpm(build_dir: Path, *, version: str, pkg_release: str, variant: str) -> None:
|
||||
"""Stage the spec and its sources, then build the binary RPMs."""
|
||||
topdir = build_dir / "rpmbuild"
|
||||
for name in ("BUILD", "BUILDROOT", "RPMS", "SOURCES", "SPECS", "SRPMS"):
|
||||
@@ -156,6 +199,9 @@ def build_rpm(build_dir: Path, *, version: str, pkg_release: str) -> None:
|
||||
stage_common(build_dir, topdir / "SOURCES")
|
||||
stage_units(topdir / "SOURCES")
|
||||
|
||||
# The spec defaults it to nothing, so a plain build is unchanged.
|
||||
variant_defines = ["--define", f"pkg_variant {variant}"] if variant else []
|
||||
|
||||
run(
|
||||
"rpmbuild",
|
||||
"-bb",
|
||||
@@ -168,10 +214,29 @@ def build_rpm(build_dir: Path, *, version: str, pkg_release: str) -> None:
|
||||
# The image tracks the newest distro, but the packages target el9.
|
||||
"--define",
|
||||
"dist .el9",
|
||||
*variant_defines,
|
||||
spec,
|
||||
)
|
||||
|
||||
|
||||
def stage_debian(dest: Path, name: str) -> None:
|
||||
"""Stage the debian directory for the package name being built."""
|
||||
source = SRC_DIR / "package" / "debian"
|
||||
shutil.copytree(
|
||||
source, dest, ignore=shutil.ignore_patterns("*.in", *DEBIAN_PKG_FILES)
|
||||
)
|
||||
|
||||
values = {
|
||||
"PKG": name,
|
||||
"VARIANT_FIELDS": "" if name == BASE_NAME else DEB_VARIANT_FIELDS,
|
||||
}
|
||||
render(source / "control.in", dest / "control", values)
|
||||
render(source / "lintian-overrides.in", dest / f"{name}.lintian-overrides", values)
|
||||
|
||||
for suffix in DEBIAN_PKG_FILES:
|
||||
shutil.copy2(source / suffix, dest / f"{name}.{suffix}")
|
||||
|
||||
|
||||
def build_deb(
|
||||
build_dir: Path,
|
||||
*,
|
||||
@@ -180,21 +245,23 @@ def build_deb(
|
||||
pkg_release: str,
|
||||
channel: str,
|
||||
epoch: int,
|
||||
name: str,
|
||||
) -> None:
|
||||
"""Stage the debian directory and its sources, then build the binary DEBs."""
|
||||
staging = build_dir / "debbuild" / "source"
|
||||
stage_common(build_dir, staging)
|
||||
shutil.copytree(SRC_DIR / "package" / "debian", staging / "debian")
|
||||
stage_debian(staging / "debian", name)
|
||||
|
||||
# debhelper picks these up from debian/ automatically.
|
||||
stage_units(staging / "debian")
|
||||
# Prefixed whether it is a variant's name or not: debian/rules names them
|
||||
# explicitly either way.
|
||||
stage_units(staging / "debian", prefix=f"{name}.")
|
||||
|
||||
date = datetime.fromtimestamp(epoch, timezone.utc).strftime(
|
||||
"%a, %d %b %Y %H:%M:%S %z"
|
||||
)
|
||||
# The leading spaces are significant to dpkg.
|
||||
changelog = textwrap.dedent(f"""\
|
||||
xrpld ({version}-{pkg_release}) {channel}; urgency=medium
|
||||
{name} ({version}-{pkg_release}) {channel}; urgency=medium
|
||||
* Release {reported}.
|
||||
|
||||
-- XRPL Foundation <contact@xrplf.org> {date}
|
||||
@@ -223,6 +290,14 @@ def main() -> None:
|
||||
default="1",
|
||||
help="package release iteration (default: %(default)s)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--variant",
|
||||
default="",
|
||||
choices=VARIANTS,
|
||||
help="the flavour of the package to build: 'assert' produces "
|
||||
"xrpld-assert, which ships the same paths as xrpld and replaces it "
|
||||
"(default: the plain xrpld package)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--channel",
|
||||
required=True,
|
||||
@@ -234,6 +309,8 @@ def main() -> None:
|
||||
build_dir: Path = args.build_dir.resolve()
|
||||
pkg_release: str = args.pkg_release
|
||||
channel: str = args.channel
|
||||
variant: str = args.variant
|
||||
name = package_name(variant)
|
||||
|
||||
assert build_dir.is_dir(), (
|
||||
f"build directory not found: {build_dir}. Build the binaries before "
|
||||
@@ -253,6 +330,8 @@ def main() -> None:
|
||||
for tree in ("debbuild", "rpmbuild"):
|
||||
shutil.rmtree(build_dir / tree, ignore_errors=True)
|
||||
|
||||
print(f"Building {package_type} {name} {version}-{pkg_release}", flush=True)
|
||||
|
||||
if package_type == "deb":
|
||||
build_deb(
|
||||
build_dir,
|
||||
@@ -261,9 +340,10 @@ def main() -> None:
|
||||
pkg_release=pkg_release,
|
||||
channel=channel,
|
||||
epoch=epoch,
|
||||
name=name,
|
||||
)
|
||||
else:
|
||||
build_rpm(build_dir, version=version, pkg_release=pkg_release)
|
||||
build_rpm(build_dir, version=version, pkg_release=pkg_release, variant=variant)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Source: xrpld
|
||||
Source: @PKG@
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: XRPL Foundation <contact@xrplf.org>
|
||||
@@ -11,7 +11,7 @@ Homepage: https://github.com/XRPLF/rippled
|
||||
Vcs-Git: https://github.com/XRPLF/rippled.git
|
||||
Vcs-Browser: https://github.com/XRPLF/rippled
|
||||
|
||||
Package: xrpld
|
||||
Package: @PKG@
|
||||
Architecture: any
|
||||
Depends:
|
||||
${shlibs:Depends},
|
||||
@@ -22,3 +22,4 @@ Description: XRP Ledger daemon
|
||||
transactions, and maintains the ledger database.
|
||||
This package also includes the validator-keys tool for validator key
|
||||
management.
|
||||
@VARIANT_FIELDS@
|
||||
6
package/debian/lintian-overrides.in
Normal file
6
package/debian/lintian-overrides.in
Normal file
@@ -0,0 +1,6 @@
|
||||
# The /usr/local/bin/rippled symlink is deliberate compatibility for pre-FHS
|
||||
# layouts, so the Policy 9.1.2 tags it raises are expected.
|
||||
# TODO: remove alongside debian/links after rippled fully deprecated.
|
||||
@PKG@: dir-in-usr-local [usr/local/bin/]
|
||||
@PKG@: file-in-usr-local [usr/local/bin/rippled]
|
||||
@PKG@: file-in-unusual-dir [usr/local/bin/rippled]
|
||||
@@ -8,33 +8,58 @@ export DH_VERBOSE = 1
|
||||
# the binaries actually run on.
|
||||
LIBC_MIN = 2.31
|
||||
|
||||
# The binary package's name, which a variant build changes to e.g. xrpld-assert,
|
||||
# and the directory debhelper expects its files staged in.
|
||||
PKG := $(firstword $(shell dh_listpackages))
|
||||
PKG_DIR = debian/$(PKG)
|
||||
|
||||
# The base name, which every package ships under whatever it is called itself.
|
||||
BASE_NAME = xrpld
|
||||
|
||||
# What build_pkg.py stages beside this directory, each installed under its own
|
||||
# name. The binaries are also the ones checked against LIBC_MIN below.
|
||||
BINARIES = $(BASE_NAME) validator-keys
|
||||
CONFIGS = $(BASE_NAME).cfg validators.txt
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
override_dh_auto_configure override_dh_auto_build override_dh_auto_test:
|
||||
@:
|
||||
|
||||
# The unit, sysusers, tmpfiles and logrotate files are named after the daemon
|
||||
# rather than after the package, so a variant still ships xrpld.service and
|
||||
# /etc/logrotate.d/xrpld. debhelper only reads debian/$(PKG).$(BASE_NAME).* when told
|
||||
# the name.
|
||||
override_dh_installsystemd:
|
||||
dh_installsystemd --no-stop-on-upgrade xrpld.service
|
||||
dh_installsystemd --no-stop-on-upgrade --name $(BASE_NAME)
|
||||
|
||||
# The tmpfiles snippet sets ownership to the xrpld user, so the sysusers snippet
|
||||
# has to be emitted first: run it early and make its own sequence slot a no-op.
|
||||
execute_before_dh_installtmpfiles:
|
||||
dh_installsysusers
|
||||
dh_installsysusers --name $(BASE_NAME)
|
||||
|
||||
override_dh_installsysusers:
|
||||
|
||||
override_dh_installtmpfiles:
|
||||
dh_installtmpfiles --name $(BASE_NAME)
|
||||
|
||||
override_dh_installlogrotate:
|
||||
dh_installlogrotate --name $(BASE_NAME)
|
||||
|
||||
override_dh_install:
|
||||
install -D -m 0755 xrpld debian/xrpld/usr/bin/xrpld
|
||||
install -D -m 0755 validator-keys debian/xrpld/usr/bin/validator-keys
|
||||
install -D -m 0644 xrpld.cfg debian/xrpld/etc/xrpld/xrpld.cfg
|
||||
install -D -m 0644 validators.txt debian/xrpld/etc/xrpld/validators.txt
|
||||
for binary in $(BINARIES); do \
|
||||
install -D -m 0755 "$$binary" "$(PKG_DIR)/usr/bin/$$binary"; \
|
||||
done
|
||||
for config in $(CONFIGS); do \
|
||||
install -D -m 0644 "$$config" "$(PKG_DIR)/etc/$(BASE_NAME)/$$config"; \
|
||||
done
|
||||
|
||||
override_dh_shlibdeps:
|
||||
dh_shlibdeps
|
||||
# Guards against the toolchain moving past LIBC_MIN and the packages then
|
||||
# claiming a floor they do not meet.
|
||||
for binary in xrpld validator-keys; do \
|
||||
for binary in $(BINARIES); do \
|
||||
needed=$$(readelf --dyn-syms --wide $$binary \
|
||||
| grep -o 'GLIBC_[0-9.]*' | sed 's/GLIBC_//' | sort -uV | tail -1); \
|
||||
if [ -z "$$needed" ]; then \
|
||||
@@ -46,7 +71,7 @@ override_dh_shlibdeps:
|
||||
exit 1; \
|
||||
fi; \
|
||||
done
|
||||
sed -i 's/libc6 (>= [0-9.]*)/libc6 (>= $(LIBC_MIN))/' debian/xrpld.substvars
|
||||
sed -i 's/libc6 (>= [0-9.]*)/libc6 (>= $(LIBC_MIN))/' debian/$(PKG).substvars
|
||||
|
||||
override_dh_dwz:
|
||||
@:
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# The /usr/local/bin/rippled symlink is deliberate compatibility for pre-FHS
|
||||
# layouts, so the Policy 9.1.2 tags it raises are expected.
|
||||
# TODO: remove alongside debian/xrpld.links after rippled fully deprecated.
|
||||
xrpld: dir-in-usr-local [usr/local/bin/]
|
||||
xrpld: file-in-usr-local [usr/local/bin/rippled]
|
||||
xrpld: file-in-unusual-dir [usr/local/bin/rippled]
|
||||
@@ -6,10 +6,14 @@
|
||||
%{error:pkg_release must be defined}
|
||||
%endif
|
||||
|
||||
Name: xrpld
|
||||
# The base name, which every package ships under. A variant build
|
||||
# (build_pkg.py --variant) only suffixes the package name, e.g. xrpld-assert.
|
||||
%global base_name xrpld
|
||||
|
||||
Name: %{base_name}%{?pkg_variant:-%{pkg_variant}}
|
||||
Version: %{pkg_version}
|
||||
Release: %{pkg_release}%{?dist}
|
||||
Summary: XRP Ledger daemon
|
||||
Summary: XRP Ledger daemon%{?pkg_variant: (%{pkg_variant} build)}
|
||||
|
||||
License: ISC
|
||||
URL: https://github.com/XRPLF/rippled
|
||||
@@ -17,6 +21,12 @@ URL: https://github.com/XRPLF/rippled
|
||||
ExclusiveArch: x86_64 aarch64
|
||||
BuildRequires: systemd-rpm-macros
|
||||
|
||||
# A variant owns the same paths, so it stands in for the plain package.
|
||||
%if "%{?pkg_variant}" != ""
|
||||
Conflicts: %{base_name}
|
||||
Provides: %{base_name} = %{version}-%{release}
|
||||
%endif
|
||||
|
||||
# These have to precede %%debug_package: it opens the debuginfo subpackage, and
|
||||
# any tag after it is silently dropped from the main package.
|
||||
%{?systemd_requires}
|
||||
@@ -52,22 +62,22 @@ management.
|
||||
:
|
||||
|
||||
%install
|
||||
install -Dm0755 %{_sourcedir}/xrpld %{buildroot}%{_bindir}/%{name}
|
||||
install -Dm0755 %{_sourcedir}/xrpld %{buildroot}%{_bindir}/%{base_name}
|
||||
install -Dm0755 %{_sourcedir}/validator-keys %{buildroot}%{_bindir}/validator-keys
|
||||
install -Dm0644 %{_sourcedir}/xrpld.cfg %{buildroot}%{_sysconfdir}/%{name}/xrpld.cfg
|
||||
install -Dm0644 %{_sourcedir}/validators.txt %{buildroot}%{_sysconfdir}/%{name}/validators.txt
|
||||
install -Dm0644 %{_sourcedir}/xrpld.cfg %{buildroot}%{_sysconfdir}/%{base_name}/xrpld.cfg
|
||||
install -Dm0644 %{_sourcedir}/validators.txt %{buildroot}%{_sysconfdir}/%{base_name}/validators.txt
|
||||
|
||||
# systemd units, sysusers, tmpfiles, preset
|
||||
install -Dm0644 %{_sourcedir}/xrpld.service %{buildroot}%{_unitdir}/xrpld.service
|
||||
install -Dm0644 %{_sourcedir}/xrpld.sysusers %{buildroot}%{_sysusersdir}/xrpld.conf
|
||||
install -Dm0644 %{_sourcedir}/xrpld.tmpfiles %{buildroot}%{_tmpfilesdir}/xrpld.conf
|
||||
install -d %{buildroot}%{_presetdir}
|
||||
cat >%{buildroot}%{_presetdir}/50-xrpld.preset <<'EOF'
|
||||
cat >%{buildroot}%{_presetdir}/50-%{base_name}.preset <<'EOF'
|
||||
enable xrpld.service
|
||||
EOF
|
||||
|
||||
# Logrotate config
|
||||
install -Dm0644 %{_sourcedir}/xrpld.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/%{name}
|
||||
install -Dm0644 %{_sourcedir}/xrpld.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/%{base_name}
|
||||
|
||||
# Docs
|
||||
install -Dm0644 %{_sourcedir}/LICENSE.md %{buildroot}%{_docdir}/%{name}/LICENSE.md
|
||||
@@ -78,13 +88,13 @@ install -Dm0644 %{_sourcedir}/validator-keys-LICENSE %{buildroot}%{_docdir}/%{na
|
||||
# Legacy compatibility for pre-FHS package layouts.
|
||||
# TODO: remove after rippled fully deprecated.
|
||||
install -d %{buildroot}/usr/local/bin
|
||||
ln -s %{_bindir}/%{name} %{buildroot}/usr/local/bin/rippled
|
||||
ln -s %{_bindir}/%{base_name} %{buildroot}/usr/local/bin/rippled
|
||||
|
||||
%pre
|
||||
%sysusers_create_package %{name} %{_sourcedir}/xrpld.sysusers
|
||||
%sysusers_create_package %{base_name} %{_sourcedir}/xrpld.sysusers
|
||||
|
||||
%post
|
||||
%tmpfiles_create_package %{name} %{_sourcedir}/xrpld.tmpfiles
|
||||
%tmpfiles_create_package %{base_name} %{_sourcedir}/xrpld.tmpfiles
|
||||
%systemd_post xrpld.service
|
||||
|
||||
%preun
|
||||
@@ -92,6 +102,13 @@ ln -s %{_bindir}/%{name} %{buildroot}/usr/local/bin/rippled
|
||||
|
||||
%postun
|
||||
%systemd_postun xrpld.service
|
||||
# A flavour swap installs the replacement before erasing this package, so the
|
||||
# %%preun above has just disabled a unit the replacement still owns. rpm keeps a
|
||||
# file that another installed package owns, so the unit outliving our own erase
|
||||
# means exactly that; a plain erase takes it with us and re-presets nothing.
|
||||
if [ $1 -eq 0 ] && [ -f %{_unitdir}/xrpld.service ]; then
|
||||
systemctl preset xrpld.service >/dev/null 2>&1 || :
|
||||
fi
|
||||
|
||||
%files
|
||||
%attr(0755,root,root) %dir %{_docdir}/%{name}
|
||||
@@ -99,18 +116,18 @@ ln -s %{_bindir}/%{name} %{buildroot}/usr/local/bin/rippled
|
||||
%license %{_docdir}/%{name}/validator-keys-LICENSE
|
||||
%doc %{_docdir}/%{name}/README.md
|
||||
|
||||
%attr(0755,root,root) %dir %{_sysconfdir}/%{name}
|
||||
%attr(0755,root,root) %dir %{_sysconfdir}/%{base_name}
|
||||
|
||||
%{_bindir}/%{name}
|
||||
%{_bindir}/%{base_name}
|
||||
%{_bindir}/validator-keys
|
||||
|
||||
%config(noreplace) %{_sysconfdir}/%{name}/xrpld.cfg
|
||||
%config(noreplace) %{_sysconfdir}/%{name}/validators.txt
|
||||
%config(noreplace) %{_sysconfdir}/logrotate.d/%{name}
|
||||
%config(noreplace) %{_sysconfdir}/%{base_name}/xrpld.cfg
|
||||
%config(noreplace) %{_sysconfdir}/%{base_name}/validators.txt
|
||||
%config(noreplace) %{_sysconfdir}/logrotate.d/%{base_name}
|
||||
|
||||
|
||||
%{_unitdir}/xrpld.service
|
||||
%attr(0644,root,root) %{_presetdir}/50-xrpld.preset
|
||||
%attr(0644,root,root) %{_presetdir}/50-%{base_name}.preset
|
||||
%{_sysusersdir}/xrpld.conf
|
||||
%{_tmpfilesdir}/xrpld.conf
|
||||
%ghost %dir /var/lib/xrpld
|
||||
|
||||
Reference in New Issue
Block a user