diff --git a/.github/actions/build-deps/action.yml b/.github/actions/build-deps/action.yml index 12d80e859c..272af0f97d 100644 --- a/.github/actions/build-deps/action.yml +++ b/.github/actions/build-deps/action.yml @@ -3,46 +3,37 @@ # provided. name: Build Conan dependencies +# Note that actions do not support 'type' and all inputs are strings, see +# https://docs.github.com/en/actions/reference/workflows-and-actions/metadata-syntax#inputs. inputs: build_dir: description: 'The directory where to build.' required: true - type: string build_type: - description: 'The build type to use.' + description: 'The build type to use ("Debug", "Release").' required: true - type: choice - options: - - 'Debug' - - 'Release' conan_remote_name: description: 'The name of the Conan remote to use.' required: true - type: string conan_remote_url: description: 'The URL of the Conan endpoint to use.' required: true - type: string conan_remote_username: description: 'The username for logging into the Conan remote. If not provided, the dependencies will not be uploaded.' required: false - type: string default: '' conan_remote_password: description: 'The password for logging into the Conan remote. If not provided, the dependencies will not be uploaded.' required: false - type: string default: '' force_build: - description: 'Force building of all dependencies.' + description: 'Force building of all dependencies ("true", "false").' required: false - type: boolean - default: false + default: 'false' force_upload: - description: 'Force uploading of all dependencies.' + description: 'Force uploading of all dependencies ("true", "false").' required: false - type: boolean - default: false + default: 'false' runs: using: composite @@ -55,17 +46,17 @@ runs: cd ${{ inputs.build_dir }} conan install \ --output-folder . \ - --build ${{ inputs.force_build && '"*"' || 'missing' }} \ + --build ${{ inputs.force_build == 'true' && '"*"' || 'missing' }} \ --options:host '&:tests=True' \ --options:host '&:xrpld=True' \ --settings:all build_type=${{ inputs.build_type }} \ --format=json .. - name: Upload Conan dependencies - if: ${{ inputs.conan_remote_username && inputs.conan_remote_password }} + if: ${{ inputs.conan_remote_username != '' && inputs.conan_remote_password != '' }} shell: bash working-directory: ${{ inputs.build_dir }} run: | echo "Logging into Conan remote '${{ inputs.conan_remote_name }}' at ${{ inputs.conan_remote_url }}." conan remote login ${{ inputs.conan_remote_name }} "${{ inputs.conan_remote_username }}" --password "${{ inputs.conan_remote_password }}" echo 'Uploading dependencies.' - conan upload '*' --confirm --check ${{ inputs.force_upload && '--force' || '' }} --remote=${{ inputs.conan_remote_name }} + conan upload '*' --confirm --check ${{ inputs.force_upload == 'true' && '--force' || '' }} --remote=${{ inputs.conan_remote_name }} diff --git a/.github/actions/build-test/action.yml b/.github/actions/build-test/action.yml index 30337ddb98..fc01d81091 100644 --- a/.github/actions/build-test/action.yml +++ b/.github/actions/build-test/action.yml @@ -2,40 +2,33 @@ # already been installed (see the build-deps action). name: Build and Test +# Note that actions do not support 'type' and all inputs are strings, see +# https://docs.github.com/en/actions/reference/workflows-and-actions/metadata-syntax#inputs. inputs: build_dir: description: 'The directory where to build.' required: true - type: string + build_only: + description: 'Whether to only build or to build and test the code ("true", "false").' + required: false + default: 'false' build_type: - description: 'The build type to use.' + description: 'The build type to use ("Debug", "Release").' required: true - type: choice - options: - - 'Debug' - - 'Release' cmake_args: description: 'Additional arguments to pass to CMake.' required: false - type: string default: '' cmake_target: description: 'The CMake target to build.' required: true - type: string codecov_token: description: 'The Codecov token to use for uploading coverage reports.' required: false - type: string default: '' os: - description: 'The operating system to use for the build (linux, macos, or windows).' + description: 'The operating system to use for the build ("linux", "macos", "windows").' required: true - type: choice - options: - - 'linux' - - 'macos' - - 'windows' runs: using: composite @@ -82,7 +75,7 @@ runs: echo 'Verifying presence of instrumentation.' ./rippled --version | grep libvoidstar - name: Test the binary - if: ${{ inputs.cmake_target != 'coverage' }} + if: ${{ inputs.build_only == 'true' }} shell: bash working-directory: ${{ inputs.build_dir }}/${{ inputs.os == 'windows' && inputs.build_type || '' }} run: | diff --git a/.github/scripts/strategy-matrix/generate.py b/.github/scripts/strategy-matrix/generate.py index a5180c942d..42927b5ccd 100644 --- a/.github/scripts/strategy-matrix/generate.py +++ b/.github/scripts/strategy-matrix/generate.py @@ -9,7 +9,7 @@ Generate a strategy matrix for GitHub Actions CI. On each PR commit we will build a selection of Debian, RHEL, Ubuntu, MacOS, and Windows configurations, while upon merge into the develop, release, or master -branches, we will build all configurations. +branches, we will build all configurations, and test most of them. We will further set additional CMake arguments as follows: - All builds will have the `tests`, `werr`, and `xrpld` options. @@ -25,6 +25,13 @@ def generate_strategy_matrix(all: bool, architecture: list[dict], os: list[dict] # for Windows, but it can get overridden for certain configurations. cmake_target = 'install' if os["distro_name"] == 'windows' else 'all' + # We build and test all configurations by default, except for Windows in + # Debug, because it is too slow, as well as when code coverage is + # enabled as that mode already runs the tests. + build_only = False + if os['distro_name'] == 'windows' and build_type == 'Debug': + build_only = True + # Only generate a subset of configurations in PRs. if not all: # Debian: @@ -46,6 +53,7 @@ def generate_strategy_matrix(all: bool, architecture: list[dict], os: list[dict] if f'{os['compiler_name']}-{os['compiler_version']}' == 'gcc-15' and build_type == 'Debug' and '-Dunity=OFF' in cmake_args and architecture['platform'] == 'linux/amd64': cmake_args = f'{cmake_args} -Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_C_FLAGS=-O0 -DCMAKE_CXX_FLAGS=-O0' cmake_target = 'coverage' + build_only = True skip = False if f'{os['compiler_name']}-{os['compiler_version']}' == 'clang-16' and build_type == 'Debug' and '-Dunity=OFF' in cmake_args and architecture['platform'] == 'linux/arm64': cmake_args = f'{cmake_args} -Dvoidstar=ON' @@ -110,6 +118,11 @@ def generate_strategy_matrix(all: bool, architecture: list[dict], os: list[dict] if build_type == 'Release': cmake_args = f'{cmake_args} -Dassert=ON' + # We skip all RHEL on arm64 due to a build failure that needs further + # investigation. + if os['distro_name'] == 'rhel' and architecture['platform'] == 'linux/arm64': + continue + # Generate a unique name for the configuration, e.g. macos-arm64-debug # or debian-bookworm-gcc-12-amd64-release-unity. config_name = os['distro_name'] @@ -128,6 +141,7 @@ def generate_strategy_matrix(all: bool, architecture: list[dict], os: list[dict] 'architecture': architecture, 'os': os, 'build_type': build_type, + 'build_only': 'true' if build_only else 'false', 'cmake_args': cmake_args, 'cmake_target': cmake_target, 'config_name': config_name, diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 3fb8f057a2..a330f5decb 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -1,7 +1,10 @@ # This workflow builds and tests the binary for various configurations. name: Build and test -# This workflow can only be triggered by other workflows. +# This workflow can only be triggered by other workflows. Note that the +# workflow_call event does not support the 'choice' input type, see +# https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#onworkflow_callinputsinput_idtype, +# so we use 'string' instead. on: workflow_call: inputs: @@ -29,14 +32,15 @@ on: type: boolean default: false os: - description: 'The operating system to use for the build (linux, macos, or windows).' + description: 'The operating system to use for the build ("linux", "macos", "windows").' required: true type: string - strategy_matrix_all: - description: 'Generate a strategy matrix containing all configurations.' + strategy_matrix: + # TODO: Support additional strategies, e.g. "ubuntu" for generating all Ubuntu configurations. + description: 'The strategy matrix to use for generating the configurations ("minimal", "all").' required: false - type: boolean - default: false + type: string + default: 'minimal' secrets: codecov_token: description: 'The Codecov token to use for uploading coverage reports.' @@ -70,7 +74,7 @@ jobs: - name: Generate strategy matrix working-directory: .github/scripts/strategy-matrix id: generate - run: python generate.py ${{ inputs.strategy_matrix_all && '--all' || '' }} --config=${{ inputs.os }}.json >> "${GITHUB_OUTPUT}" + run: python generate.py ${{ inputs.strategy_matrix == 'all' && '--all' || '' }} --config=${{ inputs.os }}.json >> "${GITHUB_OUTPUT}" outputs: matrix: ${{ steps.generate.outputs.matrix }} @@ -101,9 +105,11 @@ jobs: uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: 3.13 - - name: Install Conan (Windows) + - name: Install build tools (Windows) if: ${{ inputs.os == 'windows' }} - run: pip install wheel conan + run: | + echo 'Installing build tools.' + pip install wheel conan - name: Check configuration (Windows) if: ${{ inputs.os == 'windows' }} run: | @@ -115,6 +121,11 @@ jobs: echo 'Checking Conan version.' conan --version + - name: Install build tools (MacOS) + if: ${{ inputs.os == 'macos' }} + run: | + echo 'Installing build tools.' + brew install cmake conan ninja coreutils - name: Check configuration (Linux and MacOS) if: ${{ inputs.os == 'linux' || inputs.os == 'macos' }} run: | @@ -135,6 +146,9 @@ jobs: echo 'Checking Ninja version.' ninja --version + + echo 'Checking nproc version.' + nproc --version - name: Set up Conan home directory (MacOS) if: ${{ inputs.os == 'macos' }} run: | @@ -184,6 +198,7 @@ jobs: uses: ./.github/actions/build-test with: build_dir: ${{ inputs.build_dir }} + build_only: ${{ matrix.build_only }} build_type: ${{ matrix.build_type }} cmake_args: ${{ matrix.cmake_args }} cmake_target: ${{ matrix.cmake_target }} diff --git a/.github/workflows/notify-clio.yml b/.github/workflows/notify-clio.yml index ae95d04db0..6ccf527ea6 100644 --- a/.github/workflows/notify-clio.yml +++ b/.github/workflows/notify-clio.yml @@ -44,10 +44,11 @@ jobs: - name: Generate outputs id: generate run: | - echo 'Generating channel.' - echo channel="clio/pr_${{ github.event.pull_request.number }}" >> "${GITHUB_OUTPUT}" + echo 'Generating user and channel.' + echo "user=clio" >> "${GITHUB_OUTPUT}" + echo "channel=pr_${{ github.event.pull_request.number }}" >> "${GITHUB_OUTPUT}" echo 'Extracting version.' - echo version="$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')" >> "${GITHUB_OUTPUT}" + echo "version=$(cat src/libxrpl/protocol/BuildInfo.cpp | grep "versionString =" | awk -F '"' '{print $2}')" >> "${GITHUB_OUTPUT}" - name: Add Conan remote run: | echo "Adding Conan remote '${{ inputs.conan_remote_name }}' at ${{ inputs.conan_remote_url }}." @@ -58,10 +59,8 @@ jobs: run: conan remote login ${{ inputs.conan_remote_name }} "${{ secrets.conan_remote_username }}" --password "${{ secrets.conan_remote_password }}" - name: Upload package run: | - echo 'Exporting package to channel ${{ steps.generate.outputs.channel }}.' - conan export --channel=${{ steps.generate.outputs.channel }} . - echo 'Uploading package version ${{ steps.generate.outputs.version }} on channel ${{ steps.generate.outputs.channel }}.' - conan upload --confirm --check --remote=${{ inputs.conan_remote_name }} xrpl/${{ steps.generate.outputs.version }}@${{ steps.generate.outputs.channel }} + conan export --user=${{ steps.generate.outputs.user }} --channel=${{ steps.generate.outputs.channel }} . + conan upload --confirm --check --remote=${{ inputs.conan_remote_name }} xrpl/${{ steps.generate.outputs.version }}@${{ steps.generate.outputs.user }}/${{ steps.generate.outputs.channel }} outputs: channel: ${{ steps.generate.outputs.channel }} version: ${{ steps.generate.outputs.version }} @@ -76,5 +75,5 @@ jobs: run: | gh api --method POST -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \ /repos/xrplf/clio/dispatches -f "event_type=check_libxrpl" \ - -F "client_payload[version]=${{ needs.upload.outputs.version }}@${{ needs.upload.outputs.channel }}" \ + -F "client_payload[version]=${{ needs.upload.outputs.version }}@${{ needs.upload.outputs.user }}/${{ needs.upload.outputs.channel }}" \ -F "client_payload[pr]=${{ github.event.pull_request.number }}" diff --git a/.github/workflows/on-pr.yml b/.github/workflows/on-pr.yml index 10bc61797a..9d7bbbf89c 100644 --- a/.github/workflows/on-pr.yml +++ b/.github/workflows/on-pr.yml @@ -71,7 +71,7 @@ jobs: - name: No-op run: echo '' - check-clang-format: + check-format: needs: should-run uses: ./.github/workflows/check-format.yml @@ -91,38 +91,23 @@ jobs: conan_remote_name: ${{ env.CONAN_REMOTE_NAME }} conan_remote_url: ${{ env.CONAN_REMOTE_URL }} - build-linux: + build-test: needs: generate-outputs uses: ./.github/workflows/build-test.yml + strategy: + matrix: + os: [linux, macos, windows] with: conan_remote_name: ${{ needs.generate-outputs.outputs.conan_remote_name }} conan_remote_url: ${{ needs.generate-outputs.outputs.conan_remote_url }} - os: 'linux' + os: ${{ matrix.os }} secrets: codecov_token: ${{ secrets.CODECOV_TOKEN }} - build-macos: - needs: generate-outputs - uses: ./.github/workflows/build-test.yml - with: - conan_remote_name: ${{ needs.generate-outputs.outputs.conan_remote_name }} - conan_remote_url: ${{ needs.generate-outputs.outputs.conan_remote_url }} - os: 'macos' - - build-windows: - needs: generate-outputs - uses: ./.github/workflows/build-test.yml - with: - conan_remote_name: ${{ needs.generate-outputs.outputs.conan_remote_name }} - conan_remote_url: ${{ needs.generate-outputs.outputs.conan_remote_url }} - os: 'windows' - notify-clio: needs: - generate-outputs - - build-linux - - build-macos - - build-windows + - build-test uses: ./.github/workflows/notify-clio.yml with: conan_remote_name: ${{ needs.generate-outputs.outputs.conan_remote_name }} diff --git a/.github/workflows/on-trigger.yml b/.github/workflows/on-trigger.yml index 004e44c1fb..ed9a794985 100644 --- a/.github/workflows/on-trigger.yml +++ b/.github/workflows/on-trigger.yml @@ -81,10 +81,10 @@ jobs: - name: Check inputs and set outputs id: generate run: | - if [[ "${{ github.event_name }}" == 'push' ]]; then + if [[ '${{ github.event_name }}' == 'push' ]]; then echo 'dependencies_force_build=false' >> "${GITHUB_OUTPUT}" echo 'dependencies_force_upload=false' >> "${GITHUB_OUTPUT}" - elif [[ "${{ github.event_name }}" == 'schedule' ]]; then + elif [[ '${{ github.event_name }}' == 'schedule' ]]; then echo 'dependencies_force_build=true' >> "${GITHUB_OUTPUT}" echo 'dependencies_force_upload=false' >> "${GITHUB_OUTPUT}" else @@ -97,44 +97,19 @@ jobs: dependencies_force_build: ${{ steps.generate.outputs.dependencies_force_build }} dependencies_force_upload: ${{ steps.generate.outputs.dependencies_force_upload }} - build-linux: + build-test: needs: generate-outputs uses: ./.github/workflows/build-test.yml + strategy: + matrix: + os: [linux, macos, windows] with: conan_remote_name: ${{ needs.generate-outputs.outputs.conan_remote_name }} conan_remote_url: ${{ needs.generate-outputs.outputs.conan_remote_url }} - dependencies_force_build: ${{ needs.generate-outputs.outputs.dependencies_force_build }} - dependencies_force_upload: ${{ needs.generate-outputs.outputs.dependencies_force_upload }} - os: 'linux' - strategy_matrix_all: true - secrets: - conan_remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }} - conan_remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }} - - build-macos: - needs: generate-outputs - uses: ./.github/workflows/build-test.yml - with: - conan_remote_name: ${{ needs.generate-outputs.outputs.conan_remote_name }} - conan_remote_url: ${{ needs.generate-outputs.outputs.conan_remote_url }} - dependencies_force_build: ${{ needs.generate-outputs.outputs.dependencies_force_build }} - dependencies_force_upload: ${{ needs.generate-outputs.outputs.dependencies_force_upload }} - os: 'macos' - strategy_matrix_all: true - secrets: - conan_remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }} - conan_remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }} - - build-windows: - needs: generate-outputs - uses: ./.github/workflows/build-test.yml - with: - conan_remote_name: ${{ needs.generate-outputs.outputs.conan_remote_name }} - conan_remote_url: ${{ needs.generate-outputs.outputs.conan_remote_url }} - dependencies_force_build: ${{ needs.generate-outputs.outputs.dependencies_force_build }} - dependencies_force_upload: ${{ needs.generate-outputs.outputs.dependencies_force_upload }} - os: 'windows' - strategy_matrix_all: true + dependencies_force_build: ${{ needs.generate-outputs.outputs.dependencies_force_build == 'true' }} + dependencies_force_upload: ${{ needs.generate-outputs.outputs.dependencies_force_upload == 'true' }} + os: ${{ matrix.os }} + strategy_matrix: 'all' secrets: conan_remote_username: ${{ secrets.CONAN_REMOTE_USERNAME }} conan_remote_password: ${{ secrets.CONAN_REMOTE_PASSWORD }} diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml index a2c24bd076..509644e6b5 100644 --- a/.github/workflows/publish-docs.yml +++ b/.github/workflows/publish-docs.yml @@ -28,6 +28,8 @@ jobs: publish: runs-on: ubuntu-latest container: ghcr.io/xrplf/ci/tools-rippled-documentation + permissions: + contents: write steps: - name: Checkout repository uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0