From 0a47821ce00f933056f4c857656d04519a0f2ec5 Mon Sep 17 00:00:00 2001 From: Denis Angell Date: Wed, 1 Jul 2026 23:45:50 -0400 Subject: [PATCH] ci: add all-amendments supported workflow --- .github/scripts/strategy-matrix/generate.py | 11 +- .github/scripts/strategy-matrix/linux.json | 17 +++ .github/workflows/build-supported-image.yml | 101 ++++++++++++++++++ .../workflows/reusable-build-test-config.yml | 20 ++++ .github/workflows/reusable-build-test.yml | 1 + docker/supported.Dockerfile | 25 +++++ 6 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build-supported-image.yml create mode 100644 docker/supported.Dockerfile diff --git a/.github/scripts/strategy-matrix/generate.py b/.github/scripts/strategy-matrix/generate.py index a269cb25d4..42553a5d9b 100755 --- a/.github/scripts/strategy-matrix/generate.py +++ b/.github/scripts/strategy-matrix/generate.py @@ -54,6 +54,8 @@ class LinuxConfig: suffix: str = "" extra_cmake_args: str = "" image: str = "" # only used by package_configs entries + # Flip every amendment to Supported::Yes before building (perf/test only). + force_supported: bool = False # List of GitHub event names (e.g. "pull_request") on which this config # should NOT run. Empty means it runs on every event. exclude_event_types: list[str] = dataclasses.field(default_factory=list) @@ -142,6 +144,7 @@ class MatrixEntry: sanitizers: str image: str = "" # container image; empty for macOS/Windows (runs natively) compiler: str = "" # compiler name ("gcc" or "clang"); empty for macOS/Windows + force_supported: bool = False # flip amendments to Supported::Yes before build @dataclasses.dataclass @@ -211,6 +214,7 @@ def expand_linux_matrix( architecture=arch_info, sanitizers=sanitizer, compiler=compiler, + force_supported=cfg.force_supported, ) ) @@ -229,9 +233,14 @@ def expand_linux_packaging(linux: LinuxFile) -> list[PackagingEntry]: for distro, configs in linux.package_configs.items(): for cfg in configs: for compiler, build_type in itertools.product(cfg.compiler, cfg.build_type): + # Keep in sync with build config_name so the packaging job finds + # the matching binary artifact (e.g. the -supported variant). + artifact_name = f"xrpld-{distro}-{compiler}-{build_type.lower()}-amd64" + if cfg.suffix: + artifact_name += f"-{cfg.suffix}" entries.append( PackagingEntry( - artifact_name=f"xrpld-{distro}-{compiler}-{build_type.lower()}-amd64", + artifact_name=artifact_name, image=cfg.image, distro=distro, ) diff --git a/.github/scripts/strategy-matrix/linux.json b/.github/scripts/strategy-matrix/linux.json index 863b910dda..07faff04e9 100644 --- a/.github/scripts/strategy-matrix/linux.json +++ b/.github/scripts/strategy-matrix/linux.json @@ -43,6 +43,13 @@ "suffix": "unity", "extra_cmake_args": "-Dunity=ON", "exclude_event_types": ["pull_request"] + }, + { + "compiler": ["gcc"], + "build_type": ["Release"], + "arch": ["amd64"], + "suffix": "supported", + "force_supported": true } ], @@ -63,6 +70,16 @@ ] }, "package_configs": { + "ubuntu": [ + { + "compiler": ["gcc"], + "build_type": ["Release"], + "arch": ["amd64"], + "suffix": "supported", + "image": "ghcr.io/xrplf/xrpld/packaging-debian:sha-577d745" + } + ], + "debian": [ { "compiler": ["gcc"], diff --git a/.github/workflows/build-supported-image.yml b/.github/workflows/build-supported-image.yml new file mode 100644 index 0000000000..9c915ad4a0 --- /dev/null +++ b/.github/workflows/build-supported-image.yml @@ -0,0 +1,101 @@ +# Package the "all amendments Supported::Yes" build into a runtime Docker image +# and push it to GHCR, as a drop-in for the rippleci/xrpld image xrpl.js uses +# for standalone testing -- except every amendment is built Supported::Yes. +# +# This does NOT build or package anything: the Trigger workflow already builds +# the supported binary and the supported .deb (the force_supported build config +# and the matching supported package config in linux.json). This workflow waits +# for a successful Trigger run on develop, downloads that run's supported .deb +# artifact, installs it into a slim base (docker/supported.Dockerfile, which +# replicates rippleci's layout), and pushes ghcr.io/xrplf/xrpld/supported. +# +# Perf/test artifact only -- never run it on a production validator. +name: Build supported Docker image + +on: + workflow_run: + workflows: ["Trigger"] + types: [completed] + branches: [develop] + # Manual runs: point at a specific completed Trigger run via its run id. + workflow_dispatch: + inputs: + trigger_run_id: + description: "Run id of the Trigger workflow whose supported .deb to package." + required: true + type: string + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash + +env: + # The supported .deb artifact uploaded by reusable-package.yml: + # -pkg, where artifact_name carries the -supported suffix. + DEB_ARTIFACT: xrpld-ubuntu-gcc-release-amd64-supported-pkg + IMAGE_NAME: ghcr.io/xrplf/xrpld/supported + SOURCE_RUN_ID: ${{ github.event.workflow_run.id || inputs.trigger_run_id }} + +jobs: + image: + # Only for successful Trigger runs (workflow_run), and only on the canonical + # repo where GITHUB_TOKEN can push to ghcr.io/xrplf/*. + if: ${{ github.repository == 'XRPLF/rippled' && (github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success') }} + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + actions: read + steps: + - name: Checkout repository + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + + - name: Download the supported .deb from the Trigger run + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: ${{ env.DEB_ARTIFACT }} + path: dl + run-id: ${{ env.SOURCE_RUN_ID }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Assemble build context + run: | + set -euo pipefail + mkdir -p docker-context + deb="$(find dl -name '*.deb' | head -n1)" + [ -n "${deb}" ] || { echo "::error::no supported .deb found in run ${SOURCE_RUN_ID}"; exit 1; } + mv "${deb}" docker-context/xrpld.deb + echo "Packaging $(basename "${deb}") into ${IMAGE_NAME}" + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 + + - name: Login to GitHub Container Registry + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Docker metadata + id: meta + uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 + with: + images: ${{ env.IMAGE_NAME }} + tags: | + type=sha,prefix=sha-,format=short + type=raw,value=latest + + - name: Build and push + uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 + with: + context: docker-context + file: docker/supported.Dockerfile + platforms: linux/amd64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/reusable-build-test-config.yml b/.github/workflows/reusable-build-test-config.yml index e7a88a0e66..3e46402010 100644 --- a/.github/workflows/reusable-build-test-config.yml +++ b/.github/workflows/reusable-build-test-config.yml @@ -63,6 +63,12 @@ on: type: string default: "" + force_supported: + description: "Flip every amendment to Supported::Yes before building. For perf/test builds only; never for release artifacts." + required: false + type: boolean + default: false + secrets: CODECOV_TOKEN: description: "The Codecov token to use for uploading coverage reports." @@ -112,6 +118,20 @@ jobs: - name: Checkout repository uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + - name: Force all amendments to Supported::Yes + if: ${{ inputs.force_supported }} + run: | + set -euo pipefail + MACRO="include/xrpl/protocol/detail/features.macro" + echo "Flipping Supported::No -> Supported::Yes in ${MACRO}:" + grep -n 'Supported::No,' "${MACRO}" || echo " (none found)" + sed -i 's/Supported::No,/Supported::Yes,/g' "${MACRO}" + if grep -q 'Supported::No,' "${MACRO}"; then + echo "::error::Supported::No entries remain after sed" + exit 1 + fi + git diff -- "${MACRO}" || true + - name: Prepare runner uses: XRPLF/actions/prepare-runner@64ec3cf3b152b4444638f470bbd6df7a7a30c81c with: diff --git a/.github/workflows/reusable-build-test.yml b/.github/workflows/reusable-build-test.yml index 4b64c53521..f354e7c63f 100644 --- a/.github/workflows/reusable-build-test.yml +++ b/.github/workflows/reusable-build-test.yml @@ -50,5 +50,6 @@ jobs: config_name: ${{ matrix.config_name }} sanitizers: ${{ matrix.sanitizers }} compiler: ${{ matrix.compiler || '' }} + force_supported: ${{ matrix.force_supported || false }} secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/docker/supported.Dockerfile b/docker/supported.Dockerfile new file mode 100644 index 0000000000..080862993e --- /dev/null +++ b/docker/supported.Dockerfile @@ -0,0 +1,25 @@ +# Runtime image for the perf/test xrpld build with all amendments Supported::Yes. +# Installs the .deb into ubuntu:jammy (matching rippleci/xrpld): gives +# /usr/bin/xrpld, /etc/xrpld/xrpld.cfg, and the xrpld user. +# NOT for production validators. +ARG BASE_IMAGE=ubuntu:jammy +FROM ${BASE_IMAGE} + +# Build context must contain the supported package as xrpld.deb. +COPY xrpld.deb /tmp/xrpld.deb + +RUN set -eux; \ + id -u xrpld >/dev/null 2>&1 || \ + useradd --system --no-create-home --shell /usr/sbin/nologin xrpld; \ + apt-get update; \ + apt-get install -y --no-install-recommends ca-certificates jq /tmp/xrpld.deb; \ + rm -rf /var/lib/apt/lists/* /tmp/xrpld.deb; \ + mkdir -p /var/log/xrpld /var/lib/xrpld; \ + chown -R xrpld:xrpld /var/log/xrpld /var/lib/xrpld; \ + # Symlink for consumers that exec /opt/xrpld/bin/xrpld. + mkdir -p /opt/xrpld/bin; \ + ln -sf /usr/bin/xrpld /opt/xrpld/bin/xrpld + +EXPOSE 2459/tcp 5005/tcp 6006/tcp +USER xrpld +ENTRYPOINT ["/usr/bin/xrpld"]