chore: release 9.11.4 (security patch — GHSA-q2hj-ggqm-4g62, GHSA-946… #242
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: Python Checks | |
| # Unified workflow for Python wheel-dependent CI: | |
| # - Forward/backward model compatibility checks | |
| # - Python type checking (pytype) | |
| # - Python + C++ documentation builds | |
| # Consolidates what was previously 3 separate workflows + 2 lint jobs, | |
| # reducing Python wheel builds from 6 to 2 per CI run. | |
| on: | |
| push: | |
| branches: | |
| - master | |
| - 'releases/**' | |
| pull_request: | |
| branches: | |
| - '*' | |
| release: | |
| types: | |
| - published | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.head_ref || github.sha }} | |
| cancel-in-progress: true | |
| env: | |
| # apt on the hosted images can block forever on an interactive | |
| # needrestart/debconf prompt; -y does not suppress those. | |
| DEBIAN_FRONTEND: noninteractive | |
| NEEDRESTART_MODE: a | |
| permissions: | |
| contents: read | |
| jobs: | |
| build-wheel: | |
| name: Build python wheel (current) | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 90 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| persist-credentials: false | |
| submodules: false | |
| - name: Init submodules with retry | |
| shell: bash | |
| run: | | |
| git config --global --add safe.directory "$(pwd)" | |
| for attempt in 1 2 3 4 5; do | |
| if git submodule update --init --recursive; then | |
| echo "Submodule init succeeded on attempt $attempt" | |
| exit 0 | |
| fi | |
| echo "Attempt $attempt failed, retrying in 15s..." | |
| sleep 15 | |
| done | |
| echo "Submodule init failed after 5 attempts" | |
| exit 1 | |
| - name: Install build dependencies | |
| run: | | |
| bash "$GITHUB_WORKSPACE/.github/scripts/apt-install.sh" cmake ninja-build libboost-test-dev python3-dev python3-pip zlib1g-dev | |
| python3 -m pip install pybind11 | |
| - name: Build wheel | |
| shell: bash | |
| run: | | |
| # patchelf from pip: ubuntu-22.04 ships 0.14.3, current auditwheel needs >= 0.14.5 | |
| python3 -m pip install wheel auditwheel patchelf | |
| export PYBIND11_DIR=$(python3 -m pybind11 --cmakedir) | |
| CMAKE_ARGS="-DSTATIC_LINK_VW_JAVA=On -DCMAKE_BUILD_TYPE=Release -DVW_ZLIB_SYS_DEP=OFF -DVW_FEAT_CSV=ON -Dpybind11_DIR=${PYBIND11_DIR}" python3 -m pip wheel . -w wheel_output/ --verbose | |
| auditwheel repair wheel_output/*whl -w audit_output/ | |
| - name: Upload built wheel | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: wheel-current | |
| path: audit_output/ | |
| build-wheel-master: | |
| name: Build python wheel (master) | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 90 | |
| steps: | |
| # Only the apt retry helper; the rest of this job does not need the repo. | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| sparse-checkout: .github/scripts | |
| submodules: false | |
| persist-credentials: false | |
| - name: Install dependencies | |
| run: | | |
| bash "$GITHUB_WORKSPACE/.github/scripts/apt-install.sh" cmake ninja-build libboost-test-dev python3-dev python3-pip zlib1g-dev | |
| # patchelf from pip: ubuntu-22.04 ships 0.14.3, current auditwheel needs >= 0.14.5 | |
| python3 -m pip install build wheel setuptools auditwheel patchelf pybind11 | |
| - name: Build wheel | |
| shell: bash | |
| run: | | |
| git clone --recursive https://github.com/VowpalWabbit/vowpal_wabbit.git | |
| cd vowpal_wabbit | |
| export PYBIND11_DIR=$(python3 -m pybind11 --cmakedir) | |
| CMAKE_ARGS="-DSTATIC_LINK_VW_JAVA=On -DCMAKE_BUILD_TYPE=Release -DVW_ZLIB_SYS_DEP=OFF -DVW_FEAT_CSV=ON -Dpybind11_DIR=${PYBIND11_DIR}" python3 -m pip wheel . -w wheel_last_commit/ --verbose | |
| cd .. | |
| auditwheel repair vowpal_wabbit/wheel_last_commit/*whl -w audit_last_commit/ | |
| - name: Upload built wheel | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: wheel-master | |
| path: audit_last_commit/ | |
| # --- Model compatibility checks --- | |
| forward-generate: | |
| name: Generate models from current code | |
| needs: build-wheel | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 90 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | |
| with: | |
| python-version: '3.10' | |
| - name: Download artifact | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| name: wheel-current | |
| path: built_wheel | |
| - name: Install dependencies | |
| run: | | |
| bash "$GITHUB_WORKSPACE/.github/scripts/apt-install.sh" python3-pip | |
| - name: Generate models | |
| shell: bash | |
| env: | |
| PR_TITLE: ${{ github.event.pull_request.title }} | |
| run: | | |
| set -x | |
| python3 -m pip install setuptools wheel | |
| echo "=== Installing wheel ===" | |
| python3 -m pip install built_wheel/*.whl | |
| echo "=== Verifying vowpalwabbit import ===" | |
| python3 -c "import vowpalwabbit; print('vowpalwabbit imported successfully')" | |
| echo "=== Running model generation script ===" | |
| python3 ./test/run_tests_model_gen_and_load.py --generate_models --skip_pr_tests "$PR_TITLE" || (echo "Model generation failed with exit code $?" && exit 1) | |
| echo "=== Checking generated files ===" | |
| ls -la ~/.vw_runtests_model_gen_working_dir/ || echo "Working directory not found" | |
| - name: Copy generated files to workspace | |
| run: | | |
| cp -r ~/.vw_runtests_model_gen_working_dir ./vw_generated_models_upload | |
| ls -la ./vw_generated_models_upload/ | |
| - name: Upload generated models | |
| if: success() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: forward-generated-models | |
| path: vw_generated_models_upload/* | |
| if-no-files-found: error | |
| forward-test: | |
| name: Test current models with master code | |
| needs: [build-wheel-master, forward-generate] | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 90 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| persist-credentials: false | |
| submodules: false | |
| - name: Init submodules with retry | |
| shell: bash | |
| run: | | |
| git config --global --add safe.directory "$(pwd)" | |
| for attempt in 1 2 3 4 5; do | |
| if git submodule update --init --recursive; then | |
| echo "Submodule init succeeded on attempt $attempt" | |
| exit 0 | |
| fi | |
| echo "Attempt $attempt failed, retrying in 15s..." | |
| sleep 15 | |
| done | |
| echo "Submodule init failed after 5 attempts" | |
| exit 1 | |
| - name: Install python | |
| run: | | |
| bash "$GITHUB_WORKSPACE/.github/scripts/apt-install.sh" python3-pip | |
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| name: forward-generated-models | |
| path: .vw_runtests_model_gen_working_dir | |
| - name: Download master wheel | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| name: wheel-master | |
| path: master_wheel | |
| - name: Test loading models with master | |
| shell: bash | |
| env: | |
| PR_TITLE: ${{ github.event.pull_request.title }} | |
| run: | | |
| mv .vw_runtests_model_gen_working_dir ~ | |
| python3 -m pip install setuptools wheel | |
| python3 -m pip install master_wheel/*.whl | |
| python3 ./test/run_tests_model_gen_and_load.py --load_models --skip_missing_args --skip_pr_tests "$PR_TITLE" | |
| backward-generate: | |
| name: Generate models from master code | |
| needs: build-wheel-master | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 90 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | |
| with: | |
| python-version: '3.10' | |
| - name: Download artifact | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| name: wheel-master | |
| path: built_wheel | |
| - name: Install dependencies | |
| run: | | |
| bash "$GITHUB_WORKSPACE/.github/scripts/apt-install.sh" libboost-test-dev | |
| - name: Generate models | |
| shell: bash | |
| env: | |
| PR_TITLE: ${{ github.event.pull_request.title }} | |
| run: | | |
| set -x | |
| pip install setuptools wheel | |
| echo "=== Installing wheel ===" | |
| pip install built_wheel/*.whl | |
| echo "=== Verifying vowpalwabbit import ===" | |
| python -c "import vowpalwabbit; print('vowpalwabbit imported successfully')" | |
| echo "=== Running model generation script ===" | |
| python ./test/run_tests_model_gen_and_load.py --generate_models --skip_missing_args --skip_pr_tests "$PR_TITLE" || (echo "Model generation failed with exit code $?" && exit 1) | |
| echo "=== Checking generated files ===" | |
| ls -la ~/.vw_runtests_model_gen_working_dir/ || echo "Working directory not found" | |
| - name: Copy generated files to workspace | |
| run: | | |
| cp -r ~/.vw_runtests_model_gen_working_dir ./vw_generated_models_upload | |
| ls -la ./vw_generated_models_upload/ | |
| - name: Upload generated models | |
| if: success() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: backward-generated-models | |
| path: vw_generated_models_upload/* | |
| if-no-files-found: error | |
| backward-test: | |
| name: Test master models with current code | |
| needs: [build-wheel, backward-generate] | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 90 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| persist-credentials: false | |
| submodules: false | |
| - name: Init submodules with retry | |
| shell: bash | |
| run: | | |
| git config --global --add safe.directory "$(pwd)" | |
| for attempt in 1 2 3 4 5; do | |
| if git submodule update --init --recursive; then | |
| echo "Submodule init succeeded on attempt $attempt" | |
| exit 0 | |
| fi | |
| echo "Attempt $attempt failed, retrying in 15s..." | |
| sleep 15 | |
| done | |
| echo "Submodule init failed after 5 attempts" | |
| exit 1 | |
| - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| name: backward-generated-models | |
| path: .vw_runtests_model_gen_working_dir | |
| - name: Download current wheel | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| name: wheel-current | |
| path: current_wheel | |
| - name: Test loading models with current code | |
| shell: bash | |
| env: | |
| PR_TITLE: ${{ github.event.pull_request.title }} | |
| run: | | |
| mv .vw_runtests_model_gen_working_dir ~ | |
| python3 -m pip install setuptools wheel | |
| python3 -m pip install current_wheel/*.whl | |
| python3 ./test/run_tests_model_gen_and_load.py --load_models --skip_pr_tests "$PR_TITLE" | |
| # --- Type checking --- | |
| typecheck: | |
| name: Python typecheck | |
| needs: build-wheel | |
| container: | |
| image: python:3.10 | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 90 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| persist-credentials: false | |
| submodules: false | |
| - name: Init submodules with retry | |
| shell: bash | |
| run: | | |
| git config --global --add safe.directory "$(pwd)" | |
| for attempt in 1 2 3 4 5; do | |
| if git submodule update --init --recursive; then | |
| echo "Submodule init succeeded on attempt $attempt" | |
| exit 0 | |
| fi | |
| echo "Attempt $attempt failed, retrying in 15s..." | |
| sleep 15 | |
| done | |
| echo "Submodule init failed after 5 attempts" | |
| exit 1 | |
| - name: Download Wheel | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| name: wheel-current | |
| path: wheel-current | |
| - name: Install dependencies | |
| shell: bash | |
| run: | | |
| pip install -r requirements.txt | |
| pip install pytype | |
| # required for test and utl directory typecheck | |
| pip install hyperopt matplotlib seaborn | |
| - name: Install wheel | |
| shell: bash | |
| run: | | |
| export wheel_files=(wheel-current/*) | |
| export wheel_file="${wheel_files[0]}" | |
| echo Installing ${wheel_file}... | |
| pip install ${wheel_file} | |
| - name: Run pytype | |
| shell: bash | |
| run: | | |
| python -m pytype ./python/vowpalwabbit/ --verbosity=2 | |
| python -m pytype ./test/ --verbosity=2 | |
| python -m pytype ./utl/ --verbosity=2 | |
| # --- Documentation --- | |
| cpp-docs: | |
| name: Build C++ docs | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 90 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| persist-credentials: false | |
| - uses: cachix/install-nix-action@daddc62a2e67d1decb56e028c9fa68344b9b7c2a # v18 | |
| - name: Build docs | |
| run: nix build --print-build-logs .#vw-cpp-docs | |
| - name: Upload built docs | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: cxx_docs | |
| path: result/html/ | |
| dump-options: | |
| name: Build vw-dump-options | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 90 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| persist-credentials: false | |
| submodules: false | |
| - name: Init submodules with retry | |
| shell: bash | |
| run: | | |
| git config --global --add safe.directory "$(pwd)" | |
| for attempt in 1 2 3 4 5; do | |
| if git submodule update --init --recursive; then | |
| echo "Submodule init succeeded on attempt $attempt" | |
| exit 0 | |
| fi | |
| echo "Attempt $attempt failed, retrying in 15s..." | |
| sleep 15 | |
| done | |
| echo "Submodule init failed after 5 attempts" | |
| exit 1 | |
| - name: Install Ninja | |
| uses: seanmiddleditch/gha-setup-ninja@3b1f8f94a2f8254bd26914c4ab9474d4f0015f67 # v6 | |
| - name: Configure | |
| run: cmake -S . -B build -G Ninja -DBUILD_TESTING=OFF | |
| - name: Build dump options | |
| run: cmake --build build -t vw-dump-options | |
| - name: Upload vw-dump-options | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: vw-dump-options | |
| path: build/utl/dump_options/vw-dump-options | |
| python-docs: | |
| name: Build Python docs | |
| needs: [build-wheel, dump-options] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 90 | |
| steps: | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| persist-credentials: false | |
| submodules: false | |
| - name: Init submodules with retry | |
| shell: bash | |
| run: | | |
| git config --global --add safe.directory "$(pwd)" | |
| for attempt in 1 2 3 4 5; do | |
| if git submodule update --init --recursive; then | |
| echo "Submodule init succeeded on attempt $attempt" | |
| exit 0 | |
| fi | |
| echo "Attempt $attempt failed, retrying in 15s..." | |
| sleep 15 | |
| done | |
| echo "Submodule init failed after 5 attempts" | |
| exit 1 | |
| # actions/setup-node only caches when a `cache:` input is given, and none is | |
| # given here, so this step restores nothing. zizmor's cache-poisoning | |
| # heuristic fires on the workflow's publishing-shaped trigger rather than on | |
| # any cache this workflow actually uses. | |
| - name: Set up Node | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 # zizmor: ignore[cache-poisoning] | |
| - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 | |
| with: | |
| python-version: '3.10' | |
| - name: If this is a push build then set version to latest | |
| if: ${{ github.event_name == 'push' }} | |
| run: echo "VW_SPHINX_VERSION_OVERRIDE=latest" >> $GITHUB_ENV | |
| - name: Download Wheel | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| name: wheel-current | |
| path: wheel-current | |
| - name: Download vw-dump-options | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| name: vw-dump-options | |
| path: vw-dump-options | |
| - name: Change permissions to vw-dump-options | |
| shell: bash | |
| run: chmod +x ./vw-dump-options/vw-dump-options | |
| - name: Install system dependencies | |
| run: | | |
| sudo timeout -k 30 300 apt-get update -o Acquire::Retries=3 || true | |
| - name: Install dependencies | |
| shell: bash | |
| run: | | |
| pip install setuptools wheel | |
| pip install -r python/docs/build-requirements.txt | |
| pip install -r requirements.txt | |
| pip install PyYAML | |
| npm install -g handlebars | |
| - name: Install wheel | |
| shell: bash | |
| run: | | |
| pip install wheel-current/vowpalwabbit-*.whl | |
| - name: Generate CLI docs | |
| run: | | |
| cd python/docs/cmd_options_template | |
| python generate_cmdline_docs.py --dump-options-bin ../../../vw-dump-options/vw-dump-options --template ./command_line_args.hbs --out ../source/ --extra-info ./cmdline_help_overrides.yml | |
| - name: Build docs | |
| run: | | |
| cd python/docs | |
| make html | |
| - name: Upload built docs | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: python_docs | |
| path: python/docs/build/ | |
| upload-docs: | |
| name: Upload documentation | |
| needs: [cpp-docs, python-docs] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 90 | |
| if: ${{ github.repository == 'VowpalWabbit/vowpal_wabbit' && (github.event_name == 'push' || github.event_name == 'release' || github.event_name == 'workflow_dispatch') }} | |
| steps: | |
| - name: Set folder name to latest if push | |
| if: ${{ github.event_name == 'push' }} | |
| run: echo "FOLDER_NAME=latest" >> $GITHUB_ENV | |
| - name: Set folder name to version if release | |
| if: ${{ github.event_name == 'release' || github.event_name == 'workflow_dispatch' }} | |
| run: echo "FOLDER_NAME=$(echo ${GITHUB_REF:10})" >> $GITHUB_ENV | |
| - name: Download c++ Docs | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| name: cxx_docs | |
| path: cxx_docs | |
| - name: Download Python Docs | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 | |
| with: | |
| name: python_docs | |
| path: python_docs | |
| - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 | |
| with: | |
| submodules: false | |
| repository: VowpalWabbit/docs | |
| ref: master | |
| path: docs | |
| token: ${{ secrets.DOCS_DEPLOY_TOKEN }} | |
| persist-credentials: true | |
| - name: Init submodules with retry | |
| shell: bash | |
| working-directory: docs | |
| run: | | |
| git config --global --add safe.directory "$(pwd)" | |
| for attempt in 1 2 3 4 5; do | |
| if git submodule update --init --recursive; then | |
| echo "Submodule init succeeded on attempt $attempt" | |
| exit 0 | |
| fi | |
| echo "Attempt $attempt failed, retrying in 15s..." | |
| sleep 15 | |
| done | |
| echo "Submodule init failed after 5 attempts" | |
| exit 1 | |
| - name: Copy c++ Docs | |
| shell: bash | |
| run: | | |
| rm -rf docs/vowpal_wabbit/cpp/$FOLDER_NAME/ | |
| mkdir -p docs/vowpal_wabbit/cpp/$FOLDER_NAME/ | |
| cp -r cxx_docs/* docs/vowpal_wabbit/cpp/$FOLDER_NAME/ | |
| - name: Copy Python Docs | |
| shell: bash | |
| run: | | |
| rm -rf docs/vowpal_wabbit/python/$FOLDER_NAME/ | |
| mkdir -p docs/vowpal_wabbit/python/$FOLDER_NAME/ | |
| cp -r python_docs/html/* docs/vowpal_wabbit/python/$FOLDER_NAME/ | |
| - name: Checkout master | |
| shell: bash | |
| run: | | |
| cd docs | |
| git checkout master | |
| - name: Commit changes | |
| shell: bash | |
| run: | | |
| cd docs | |
| git add --all | |
| git config --local user.email "WoboWabbit@hunch.net" | |
| git config --local user.name "WoboWabbit" | |
| git commit -m "Update documentation for commit: VowpalWabbit/vowpal_wabbit@${{ github.sha }}" | |
| - name: Push changes | |
| shell: bash | |
| run: | | |
| cd docs | |
| git push origin master |