refactor: include what these two files use, and reverse by range #3708
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: build-test | |
| on: | |
| push: | |
| # branches only: publishing a release pushes a tag, which is not a change | |
| branches: ['**'] | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} | |
| cancel-in-progress: true | |
| # Cache keys, in short: `actions/cache` never overwrites an existing key, so a | |
| # key that stays the same forever is written exactly once and then frozen — | |
| # every later run restores that first snapshot and rebuilds whatever is missing | |
| # from source. Both caches therefore vary their key: | |
| # * conan — keyed on what determines its content (recipes + profile), so it is | |
| # rewritten precisely when the dependencies change. | |
| # * ccache — keyed per run and restored via prefix, so it keeps growing. Only | |
| # the default branch writes it; branch-scoped entries are invisible to other | |
| # branches and would just churn the 10 GB repo quota. | |
| # `CACHE_FLAVOR` separates jobs that resolve a *different* dependency set for the | |
| # same profile — without it they overwrite each other and both keep rebuilding. | |
| # The `*_KEY_SUFFIX` variables stay as a manual "throw it all away" knob. | |
| env: | |
| CCACHE_DIR: ${{ github.workspace }}/.ccache | |
| CCACHE_MAXSIZE: 1G | |
| CCACHE_KEY_SUFFIX: r1 | |
| CONAN_HOME: ${{ github.workspace }}/.conan2 | |
| CONAN_KEY_SUFFIX: r1 | |
| jobs: | |
| # Builds the core once per profile and, where `bindings` is set, the JNI and | |
| # Python bindings out of the same configure. They used to live in their own | |
| # workflows, which meant compiling the core and resolving its dependencies | |
| # three times over for the same two profiles. | |
| build: | |
| runs-on: ${{ matrix.os }} | |
| env: | |
| CACHE_FLAVOR: main${{ matrix.bindings && '-bindings' || '' }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - { os: ubuntu-24.04, build_profile: ubuntu-24.04-clang-18, host_profile: ubuntu-24.04-clang-18, bindings: true } | |
| - { os: ubuntu-24.04, build_profile: ubuntu-24.04-gcc-14, host_profile: ubuntu-24.04-gcc-14 } | |
| - { os: macos-15, build_profile: macos-15-armv8-clang-14, host_profile: macos-15-armv8-clang-14 } | |
| - { os: macos-26, build_profile: macos-26-armv8-clang-14, host_profile: macos-26-armv8-clang-14, bindings: true } | |
| - { os: windows-2022, build_profile: windows-2022-msvc-1940, host_profile: windows-2022-msvc-1940 } | |
| # android is covered by `android.yml`, which cross compiles the core | |
| # *and* the JNI bindings for every ABI the AAR ships and runs them on | |
| # an emulator | |
| steps: | |
| - name: checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: ubuntu install ccache | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt install ccache | |
| ccache -V | |
| - name: macos install ccache | |
| if: runner.os == 'macOS' | |
| run: | | |
| brew install ccache | |
| ccache -V | |
| - name: setup java | |
| if: matrix.bindings | |
| uses: actions/setup-java@f4f1212c880fdec8162ea9a6493f4495191887b4 # v5 | |
| with: | |
| distribution: temurin | |
| java-version: 21 | |
| - name: setup python 3.14 | |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 | |
| with: | |
| python-version: 3.14 | |
| - name: install python dependencies | |
| run: pip install conan ${{ matrix.bindings && 'pytest' || '' }} | |
| - name: conan cache key | |
| shell: bash | |
| run: echo "CONAN_CACHE_KEY=${{ hashFiles('conanfile.py', '.github/config/conan/**') }}" >> "$GITHUB_ENV" | |
| - name: cache conan | |
| uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5 | |
| with: | |
| path: ${{ env.CONAN_HOME }} | |
| key: conan-${{ env.CACHE_FLAVOR }}-${{ matrix.host_profile }}-${{ env.CONAN_KEY_SUFFIX }}-${{ env.CONAN_CACHE_KEY }} | |
| restore-keys: | | |
| conan-${{ env.CACHE_FLAVOR }}-${{ matrix.host_profile }}-${{ env.CONAN_KEY_SUFFIX }}- | |
| - name: conan config | |
| run: conan config install .github/config/conan | |
| - name: restore ccache | |
| uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5 | |
| with: | |
| path: ${{ env.CCACHE_DIR }} | |
| key: ccache-${{ env.CACHE_FLAVOR }}-${{ matrix.host_profile }}-${{ env.CCACHE_KEY_SUFFIX }}-${{ github.run_id }} | |
| restore-keys: | | |
| ccache-${{ env.CACHE_FLAVOR }}-${{ matrix.host_profile }}-${{ env.CCACHE_KEY_SUFFIX }}- | |
| - name: conan install | |
| run: > | |
| conan install . | |
| ${{ matrix.bindings && '-o "&:with_jni=True" -o "&:with_python=True"' || '' }} | |
| --profile:host '${{ matrix.host_profile }}' | |
| --profile:build '${{ matrix.build_profile }}' | |
| --build missing | |
| - name: cmake | |
| if: runner.os != 'Windows' | |
| run: > | |
| cmake -B build -S . | |
| -DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake" | |
| -DCMAKE_CXX_COMPILER_LAUNCHER=ccache | |
| -DCMAKE_BUILD_TYPE=Release | |
| -DCMAKE_CXX_FLAGS="-Werror" | |
| -DCMAKE_INSTALL_PREFIX=install | |
| -DODR_TEST=ON | |
| ${{ matrix.bindings && '-DODR_JNI=ON -DODR_PYTHON=ON' || '' }} | |
| - name: cmake | |
| if: runner.os == 'Windows' | |
| run: > | |
| cmake -B build -S . | |
| -DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake" | |
| -DCMAKE_CXX_COMPILER_LAUNCHER=ccache | |
| -DCMAKE_BUILD_TYPE=Release | |
| -DCMAKE_INSTALL_PREFIX=install | |
| -DODR_TEST=ON | |
| - name: build | |
| run: cmake --build build --config Release | |
| - name: save ccache | |
| if: github.ref == 'refs/heads/main' | |
| uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5 | |
| with: | |
| path: ${{ env.CCACHE_DIR }} | |
| key: ccache-${{ env.CACHE_FLAVOR }}-${{ matrix.host_profile }}-${{ env.CCACHE_KEY_SUFFIX }}-${{ github.run_id }} | |
| # Both suites run in seconds, so they stay in this job rather than paying | |
| # an artifact round-trip. The heavy `odr_test` still runs in `test`, which | |
| # needs firefox and the reference output — this job compiles `odr_test` | |
| # but never runs it, so it never fetches the data either. | |
| - name: junit | |
| if: matrix.bindings | |
| run: ctest --test-dir build/jni --output-on-failure | |
| - name: pytest | |
| if: matrix.bindings | |
| run: ctest --test-dir build/python --output-on-failure | |
| - name: install | |
| run: cmake --build build --target install --config Release | |
| - name: upload binaries to github | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: bin-${{ matrix.host_profile }} | |
| path: | | |
| install | |
| build/test/odr_test | |
| build/test/Release/odr_test.exe | |
| if-no-files-found: error | |
| include-hidden-files: true | |
| docker: | |
| needs: build | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - { os: ubuntu-24.04, host_profile: ubuntu-24.04-clang-18 } | |
| steps: | |
| - name: checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 | |
| - uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Docker meta | |
| id: meta | |
| uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6 | |
| with: | |
| # list of Docker images to use as base name for tags | |
| images: | | |
| ghcr.io/${{ github.repository_owner }}/odr_core_cli | |
| # generate Docker tags based on the following events/attributes | |
| tags: | | |
| type=schedule | |
| type=ref,event=branch | |
| type=ref,event=pr | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=semver,pattern={{major}} | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| type=sha | |
| - name: download binaries | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: bin-${{ matrix.host_profile }} | |
| path: cli | |
| - name: Build and push | |
| uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7 | |
| with: | |
| context: cli | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=registry,ref=ghcr.io/${{ github.repository_owner }}/odr_core_cli:buildcache | |
| cache-to: type=registry,ref=ghcr.io/${{ github.repository_owner }}/odr_core_cli:buildcache,mode=max | |
| # TODO try to run it | |
| test: | |
| needs: build | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # Disabled while pdf2htmlEX was still built; that blocker is gone, but | |
| # the reference output is generated on macOS, so re-enabling needs a | |
| # cross-platform comparison run first. | |
| #- { os: ubuntu-24.04, host_profile: ubuntu-24.04-clang-18 } | |
| #- { os: ubuntu-24.04, host_profile: ubuntu-24.04-gcc-14 } | |
| - { os: macos-26, host_profile: macos-26-armv8-clang-14 } | |
| # Windows test disabled because: | |
| # Running main() from C:\Users\runneradmin\.conan2\p\b\gtestdd9407d368b89\b\src\googletest\src\gtest_main.cc | |
| # [ FATAL ] C:/Users/runneradmin/.conan2/p/gtest28fa6787e7f6e/p/include\gtest/internal/gtest-param-util.h(585):: Condition IsValidParamName(param_name) failed. Parameterized test name 'odr_private\docx\03_smpldap_docx' is invalid, in D:\a\OpenDocument.core\OpenDocument.core\test\src\html_output_test.cpp line 129 | |
| #- { os: windows-2022, host_profile: windows-2022-msvc-1940 } | |
| env: | |
| # read by the git credential helper, on every step that runs git | |
| GH_TOKEN: ${{ secrets.PAT_ANDIWAND }} | |
| steps: | |
| - name: checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| # The test data stopped being submodules (see cmake/test_data.cmake), so | |
| # the PAT is no longer the checkout token — it authenticates the two | |
| # private clones instead. A credential helper rather than a url rewrite, | |
| # so the token never lands in a git config file. | |
| # | |
| # `GH_TOKEN` is on the job rather than this step: the helper | |
| # `gh auth setup-git` installs shells back out to `gh auth git-credential`, | |
| # which reads the token from the environment at the moment git asks it. | |
| # Set only here, the fetch below falls through to prompting and dies with | |
| # "could not read Username for 'https://github.com'". | |
| - name: authenticate to the private test data | |
| run: gh auth setup-git | |
| - name: fetch test data | |
| run: cmake -DODR_TEST_DATA_UPDATE=ON -P cmake/test_data.cmake | |
| - name: ubuntu install tidy | |
| if: runner.os == 'Linux' | |
| run: sudo apt install tidy | |
| - name: macos install tidy | |
| if: runner.os == 'macOS' | |
| run: brew install tidy-html5 | |
| - name: set up python 3.14 | |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 | |
| with: | |
| python-version: 3.14 | |
| - name: install python dependencies | |
| run: pip install htmlcmp==2.2.0 opentype-sanitizer==9.2.0 | |
| - name: download binaries | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: bin-${{ matrix.host_profile }} | |
| path: . | |
| - name: fix artifact permissions | |
| if: runner.os != 'Windows' | |
| run: chmod +x build/test/odr_test | |
| - name: test | |
| if: runner.os != 'Windows' | |
| working-directory: build/test | |
| run: ./odr_test | |
| - name: windows fix artifact permissions | |
| if: runner.os == 'Windows' | |
| run: chmod +x build/test/Release/odr_test.exe | |
| - name: windows test | |
| if: runner.os == 'Windows' | |
| working-directory: build/test | |
| run: ./Release/odr_test.exe | |
| # OTS is what every browser puts in front of an `@font-face`, and a font | |
| # it rejects is dropped whole. Deterministic, needs no browser, and — the | |
| # point — needs no reference output, so regenerating that cannot bury a | |
| # regression here. See #765. | |
| - name: check embedded fonts survive OTS | |
| run: python test/scripts/check_fonts.py build/test/output | |
| - name: tidy public test outputs | |
| run: html-tidy --html-tidy-config test/scripts/html-tidy-config build/test/output/odr-public/output | |
| - name: compare public test outputs | |
| shell: bash | |
| run: | | |
| compare-html \ | |
| --driver firefox \ | |
| --max-workers 2 \ | |
| test/data/reference-output/odr-public/output \ | |
| build/test/output/odr-public/output | |
| - name: tidy private test outputs | |
| run: html-tidy --html-tidy-config test/scripts/html-tidy-config build/test/output/odr-private/output | |
| - name: compare private test outputs | |
| shell: bash | |
| run: | | |
| compare-html \ | |
| --driver firefox \ | |
| --max-workers 2 \ | |
| test/data/reference-output/odr-private/output \ | |
| build/test/output/odr-private/output | |
| build-test-downstream: | |
| runs-on: ${{ matrix.os }} | |
| # Exports odrcore and builds a consumer against it, resolving through | |
| # `conan.lock`, so its dependency set differs from the `build` job's. | |
| env: | |
| CACHE_FLAVOR: downstream | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - { os: ubuntu-24.04, build_profile: ubuntu-24.04-clang-18, host_profile: ubuntu-24.04-clang-18 } | |
| steps: | |
| - name: checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: ubuntu install ccache | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt install ccache | |
| ccache -V | |
| - name: macos install ccache | |
| if: runner.os == 'macOS' | |
| run: | | |
| brew install ccache | |
| ccache -V | |
| - name: set up python 3.14 | |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 | |
| with: | |
| python-version: 3.14 | |
| - name: install python dependencies | |
| run: pip install conan | |
| - name: conan cache key | |
| shell: bash | |
| run: echo "CONAN_CACHE_KEY=${{ hashFiles('conanfile.py', 'conan.lock', '.github/config/conan/**') }}" >> "$GITHUB_ENV" | |
| - name: cache conan | |
| uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5 | |
| with: | |
| path: ${{ env.CONAN_HOME }} | |
| key: conan-${{ env.CACHE_FLAVOR }}-${{ matrix.host_profile }}-${{ env.CONAN_KEY_SUFFIX }}-${{ env.CONAN_CACHE_KEY }} | |
| restore-keys: | | |
| conan-${{ env.CACHE_FLAVOR }}-${{ matrix.host_profile }}-${{ env.CONAN_KEY_SUFFIX }}- | |
| - name: conan config | |
| run: conan config install .github/config/conan | |
| - name: conan odrcore | |
| run: conan export . --name odrcore --version 0.0.0 | |
| - name: restore ccache | |
| uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5 | |
| with: | |
| path: ${{ env.CCACHE_DIR }} | |
| key: ccache-${{ env.CACHE_FLAVOR }}-${{ matrix.host_profile }}-${{ env.CCACHE_KEY_SUFFIX }}-${{ github.run_id }} | |
| restore-keys: | | |
| ccache-${{ env.CACHE_FLAVOR }}-${{ matrix.host_profile }}-${{ env.CCACHE_KEY_SUFFIX }}- | |
| - name: conan install | |
| run: > | |
| conan install . | |
| --lockfile conan.lock | |
| --profile:host '${{ matrix.host_profile }}' | |
| --profile:build '${{ matrix.build_profile }}' | |
| --output-folder build | |
| --build missing | |
| - name: conan downstream | |
| run: > | |
| conan install test/downstream | |
| --profile:host '${{ matrix.host_profile }}' | |
| --profile:build '${{ matrix.build_profile }}' | |
| --output-folder test/downstream/build | |
| --build missing | |
| - name: cmake | |
| run: > | |
| cmake -S test/downstream -B test/downstream/build | |
| -DCMAKE_TOOLCHAIN_FILE="conan_toolchain.cmake" | |
| -DCMAKE_BUILD_TYPE=Release | |
| - name: build | |
| run: cmake --build test/downstream/build --config Release | |
| - name: save ccache | |
| if: github.ref == 'refs/heads/main' | |
| uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5 | |
| with: | |
| path: ${{ env.CCACHE_DIR }} | |
| key: ccache-${{ env.CACHE_FLAVOR }}-${{ matrix.host_profile }}-${{ env.CCACHE_KEY_SUFFIX }}-${{ github.run_id }} | |
| - name: run | |
| if: matrix.build_profile == matrix.host_profile && (runner.os == 'Linux' || runner.os == 'macOS') | |
| run: test/downstream/build/odr-test-downstream | |
| - name: run | |
| if: matrix.build_profile == matrix.host_profile && runner.os == 'Windows' | |
| run: test/downstream/build/Release/odr-test-downstream.exe |