From b0fd9a9746e71612af00722d219796a45ca22a94 Mon Sep 17 00:00:00 2001 From: OlegWock Date: Tue, 4 Nov 2025 13:35:33 +0100 Subject: [PATCH 1/4] chore: Setup deploy workflow for VegaFusion Python package --- .../{build_test.yml => build-and-test.yml} | 41 ++++------ .github/workflows/pr.yml | 11 +++ .github/workflows/release.yml | 79 +++++++++++++++++++ 3 files changed, 104 insertions(+), 27 deletions(-) rename .github/workflows/{build_test.yml => build-and-test.yml} (89%) create mode 100644 .github/workflows/pr.yml create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/build_test.yml b/.github/workflows/build-and-test.yml similarity index 89% rename from .github/workflows/build_test.yml rename to .github/workflows/build-and-test.yml index 5f215d26..84278a1c 100644 --- a/.github/workflows/build_test.yml +++ b/.github/workflows/build-and-test.yml @@ -1,8 +1,14 @@ -name: build_test +name: build-and-test + on: - workflow_dispatch: - pull_request: - types: [opened, synchronize] + workflow_call: + inputs: + build-all-platforms: + description: 'Build wheels for all platforms (Linux ARM64, Windows, macOS)' + required: false + type: boolean + default: true + jobs: check-rust: runs-on: ubuntu-22.04 @@ -91,8 +97,6 @@ jobs: run: | pixi run type-check-py -v - # Use maturin action to build linux wheels within proper manylinux compatible containers - # (This is why we don't use the pixi "build-py" action) build-vegafusion-python-linux-64: runs-on: ubuntu-latest steps: @@ -118,6 +122,7 @@ jobs: if-no-files-found: error build-vegafusion-python-linux-arm64: + if: inputs.build-all-platforms runs-on: ubuntu-latest steps: - name: Check out repository code @@ -142,6 +147,7 @@ jobs: if-no-files-found: error build-vegafusion-python-win-64: + if: inputs.build-all-platforms runs-on: windows-2022 steps: - name: Check out repository code @@ -173,6 +179,7 @@ jobs: if-no-files-found: error build-vegafusion-python-osx-64: + if: inputs.build-all-platforms runs-on: macos-13 steps: - name: Check out repository code @@ -204,6 +211,7 @@ jobs: if-no-files-found: error build-vegafusion-python-osx-arm64: + if: inputs.build-all-platforms runs-on: macos-14 steps: - name: Check out repository code @@ -274,8 +282,6 @@ jobs: working-directory: vegafusion-python/ env: VEGAFUSION_TEST_HEADLESS: 1 - # Run only Spark end-to-end tests, as other tests interact with Altair which requires - # exact `vegafusion` library to be installed. Since our lib has different name, it fails. run: pytest -vv -rA tests/test_spark_e2e.py - name: Upload test artifacts uses: actions/upload-artifact@v4.4.3 @@ -285,22 +291,3 @@ jobs: path: | vegafusion-python/tests/output/* - # Bundle all python wheels into a single artifact for easier downloading - bundle-vegafusion-python-wheels: - needs: [ - # jobs that build but don't have test dependencies - build-vegafusion-python-linux-arm64, - build-vegafusion-python-osx-64, - - # job that tests the wheels - test-vegafusion-python-linux-64, - ] - runs-on: ubuntu-latest - steps: - - name: Merge Wheel Artifacts - uses: actions/upload-artifact/merge@v4.4.3 - with: - name: vegafusion-python-wheels-all - pattern: python-wheels-* - delete-merged: true - separate-directories: false diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 00000000..fb13155e --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,11 @@ +name: build_test +on: + workflow_dispatch: + pull_request: + types: [opened, synchronize] + +jobs: + build-and-test: + uses: ./.github/workflows/build-and-test.yml + with: + build-all-platforms: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..a992a73b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,79 @@ +name: release +on: + workflow_dispatch: + inputs: + pypi_environment: + description: 'PyPI environment to deploy to' + required: true + type: choice + options: + - pypi + - testpypi + default: testpypi + +permissions: + contents: write + id-token: write + +jobs: + build-and-test: + uses: ./.github/workflows/build-and-test.yml + + create-release: + name: Create GitHub Release + runs-on: ubuntu-latest + needs: [build-and-test] + permissions: + contents: write + outputs: + version: ${{ steps.get_version.outputs.version }} + steps: + - name: Check out repository code + uses: actions/checkout@v4.2.2 + - name: Get version from pyproject.toml + id: get_version + run: | + VERSION=$(grep '^version = ' vegafusion-python/pyproject.toml | sed 's/version = "\(.*\)"/\1/') + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Version: $VERSION" + - name: Download all wheel artifacts + uses: actions/download-artifact@v4.1.8 + with: + pattern: python-wheels-* + path: wheels/ + merge-multiple: true + - name: List downloaded wheels + run: ls -lR wheels/ + - name: Create Release with wheels + env: + GH_TOKEN: ${{ github.token }} + run: | + gh release create "v${{ steps.get_version.outputs.version }}" \ + --title "Release v${{ steps.get_version.outputs.version }}" \ + --notes "" \ + wheels/* + + publish-to-pypi: + name: Publish Python wheels to ${{ inputs.pypi_environment }} + runs-on: ubuntu-latest + needs: [create-release] + environment: + name: ${{ inputs.pypi_environment }} + url: ${{ inputs.pypi_environment == 'pypi' && 'https://pypi.org/p/deepnote-vegafusion' || 'https://test.pypi.org/p/deepnote-vegafusion' }} + permissions: + id-token: write + steps: + - name: Download all wheel artifacts + uses: actions/download-artifact@v4.1.8 + with: + pattern: python-wheels-* + path: dist/ + merge-multiple: true + - name: List files to be uploaded + run: ls -lR dist/ + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: ${{ inputs.pypi_environment == 'testpypi' && 'https://test.pypi.org/legacy/' || '' }} + skip-existing: true + verbose: true From 2e2e03c1bb1cf685db3d439348c0d3f1619bb4e1 Mon Sep 17 00:00:00 2001 From: OlegWock Date: Tue, 4 Nov 2025 13:56:15 +0100 Subject: [PATCH 2/4] Pin actions to commit hash instead of tags --- .github/workflows/build-and-test.yml | 78 ++++++++++++++-------------- .github/workflows/pr.yml | 2 +- .github/workflows/release.yml | 10 ++-- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 84278a1c..663649bc 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -14,17 +14,17 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Check out repository code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@6d653acede28d24f02e3cd41383119e8b1b35921 with: toolchain: stable components: rustfmt, clippy - - uses: prefix-dev/setup-pixi@v0.8.9 + - uses: prefix-dev/setup-pixi@97359467eae22a2d994114fe900db762fea86261 # v0.8.9 with: cache: true - name: Cache - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: key: ${{ runner.os }}-${{ hashFiles('pixi.lock', 'Cargo.lock', 'vegafusion-python/pyproject.toml') }}-check-rust path: | @@ -42,14 +42,14 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Check out repository code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@6d653acede28d24f02e3cd41383119e8b1b35921 with: toolchain: stable - - uses: prefix-dev/setup-pixi@v0.8.9 + - uses: prefix-dev/setup-pixi@97359467eae22a2d994114fe900db762fea86261 # v0.8.9 - name: Cache - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: key: ${{ runner.os }}-${{ hashFiles('pixi.lock', 'Cargo.lock', 'vegafusion-python/pyproject.toml') }}-test-rust2 path: | @@ -62,7 +62,7 @@ jobs: run: | pixi run test-rs --release - name: Upload test artifacts - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: failure() with: name: vegafusion-rt-test-images-linux @@ -73,14 +73,14 @@ jobs: runs-on: ubuntu-22.04 steps: - name: Check out repository code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@6d653acede28d24f02e3cd41383119e8b1b35921 with: toolchain: stable - - uses: prefix-dev/setup-pixi@v0.8.9 + - uses: prefix-dev/setup-pixi@97359467eae22a2d994114fe900db762fea86261 # v0.8.9 - name: Cache - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: key: ${{ runner.os }}-${{ hashFiles('pixi.lock', 'Cargo.lock', 'vegafusion-python/pyproject.toml') }}-build-vegafusion-wasm path: | @@ -101,18 +101,18 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Clear target/wheels run: rm -rf target/wheels - name: Build wheels (Linux) - uses: messense/maturin-action@v1.45.0 + uses: PyO3/maturin-action@ea5bac0f1ccd0ab11c805e2b804bfcb65dac2eab # v1.45.0 with: command: build manylinux: 2014 rust-toolchain: stable args: -m vegafusion-python/Cargo.toml --profile release-opt --features=protobuf-src --strip --sdist - name: Upload artifacts - uses: actions/upload-artifact@v4.4.3 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: python-wheels-linux-64 path: | @@ -126,18 +126,18 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out repository code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Clear target/wheels run: rm -rf target/wheels - name: Build arm64 wheels - uses: messense/maturin-action@v1.45.0 + uses: PyO3/maturin-action@ea5bac0f1ccd0ab11c805e2b804bfcb65dac2eab # v1.45.0 with: command: build manylinux: 2_28 rust-toolchain: stable args: -m vegafusion-python/Cargo.toml --profile release-opt --features=protobuf-src --strip --target aarch64-unknown-linux-gnu - name: Upload artifacts - uses: actions/upload-artifact@v4.4.3 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: python-wheels-linux-arm64 path: | @@ -151,14 +151,14 @@ jobs: runs-on: windows-2022 steps: - name: Check out repository code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@6d653acede28d24f02e3cd41383119e8b1b35921 with: toolchain: stable - - uses: prefix-dev/setup-pixi@v0.8.9 + - uses: prefix-dev/setup-pixi@97359467eae22a2d994114fe900db762fea86261 # v0.8.9 - name: Cache - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: key: ${{ runner.os }}-${{ hashFiles('pixi.lock', 'Cargo.lock', 'vegafusion-python/pyproject.toml') }}-build-vegafusion-python-win-64 path: | @@ -169,7 +169,7 @@ jobs: run: | pixi run build-py - name: Upload artifacts - uses: actions/upload-artifact@v4.4.3 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: python-wheels-win-64 path: | @@ -183,14 +183,14 @@ jobs: runs-on: macos-13 steps: - name: Check out repository code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@6d653acede28d24f02e3cd41383119e8b1b35921 with: toolchain: stable - - uses: prefix-dev/setup-pixi@v0.8.9 + - uses: prefix-dev/setup-pixi@97359467eae22a2d994114fe900db762fea86261 # v0.8.9 - name: Cache - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: key: ${{ runner.os }}-${{ hashFiles('pixi.lock', 'Cargo.lock', 'vegafusion-python/pyproject.toml') }}-build-vegafusion-python-osx-64 path: | @@ -201,7 +201,7 @@ jobs: run: | pixi run build-py - name: Upload artifacts - uses: actions/upload-artifact@v4.4.3 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: python-wheels-osx-64 path: | @@ -215,15 +215,15 @@ jobs: runs-on: macos-14 steps: - name: Check out repository code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Install Rust toolchain - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@6d653acede28d24f02e3cd41383119e8b1b35921 with: toolchain: stable targets: aarch64-apple-darwin - - uses: prefix-dev/setup-pixi@v0.8.9 + - uses: prefix-dev/setup-pixi@97359467eae22a2d994114fe900db762fea86261 # v0.8.9 - name: Cache - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: key: osx-arm64-${{ hashFiles('pixi.lock', 'Cargo.lock', 'vegafusion-python/pyproject.toml') }}-build-vegafusion-python-osx-arm64 path: | @@ -234,7 +234,7 @@ jobs: run: | pixi run build-py --target aarch64-apple-darwin - name: Upload artifacts - uses: actions/upload-artifact@v4.4.3 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: python-wheels-osx-arm64 path: | @@ -248,13 +248,13 @@ jobs: needs: [build-vegafusion-python-linux-64] steps: - name: Check out repository code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Setup Python - uses: actions/setup-python@v5.3.0 + uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 with: python-version: "3.11" - name: Install Chrome - uses: browser-actions/setup-chrome@v1 + uses: browser-actions/setup-chrome@c785b87e244131f27c9f19c1a33e2ead956ab7ce # v1.7.3 with: chrome-version: stable - name: Install fonts on Linux @@ -263,7 +263,7 @@ jobs: echo ttf-mscorefonts-installer msttcorefonts/accepted-mscorefonts-eula select true | sudo debconf-set-selections sudo apt-get install ttf-mscorefonts-installer - name: Download vegafusion-python wheel - uses: actions/download-artifact@v4.1.8 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: python-wheels-linux-64 path: target/wheels/ @@ -284,7 +284,7 @@ jobs: VEGAFUSION_TEST_HEADLESS: 1 run: pytest -vv -rA tests/test_spark_e2e.py - name: Upload test artifacts - uses: actions/upload-artifact@v4.4.3 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: failure() with: name: vegafusion-python-test-failures diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index fb13155e..6f4eca2d 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -1,4 +1,4 @@ -name: build_test +name: 'PR checks' on: workflow_dispatch: pull_request: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a992a73b..fd26df1b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,4 +1,4 @@ -name: release +name: 'Release' on: workflow_dispatch: inputs: @@ -29,7 +29,7 @@ jobs: version: ${{ steps.get_version.outputs.version }} steps: - name: Check out repository code - uses: actions/checkout@v4.2.2 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - name: Get version from pyproject.toml id: get_version run: | @@ -37,7 +37,7 @@ jobs: echo "version=$VERSION" >> $GITHUB_OUTPUT echo "Version: $VERSION" - name: Download all wheel artifacts - uses: actions/download-artifact@v4.1.8 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: pattern: python-wheels-* path: wheels/ @@ -64,7 +64,7 @@ jobs: id-token: write steps: - name: Download all wheel artifacts - uses: actions/download-artifact@v4.1.8 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: pattern: python-wheels-* path: dist/ @@ -72,7 +72,7 @@ jobs: - name: List files to be uploaded run: ls -lR dist/ - name: Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 with: repository-url: ${{ inputs.pypi_environment == 'testpypi' && 'https://test.pypi.org/legacy/' || '' }} skip-existing: true From 824d16230af5bb5e3c1a81e611b6b66d62ed8ace Mon Sep 17 00:00:00 2001 From: OlegWock Date: Wed, 5 Nov 2025 10:59:19 +0100 Subject: [PATCH 3/4] Trigger pipeline on release instead of manual --- .github/workflows/release.yml | 55 ++++------------------------------- 1 file changed, 6 insertions(+), 49 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fd26df1b..436a4d9a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,15 +1,7 @@ name: 'Release' on: - workflow_dispatch: - inputs: - pypi_environment: - description: 'PyPI environment to deploy to' - required: true - type: choice - options: - - pypi - - testpypi - default: testpypi + release: + types: [published] permissions: contents: write @@ -19,47 +11,13 @@ jobs: build-and-test: uses: ./.github/workflows/build-and-test.yml - create-release: - name: Create GitHub Release - runs-on: ubuntu-latest - needs: [build-and-test] - permissions: - contents: write - outputs: - version: ${{ steps.get_version.outputs.version }} - steps: - - name: Check out repository code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4.3.0 - - name: Get version from pyproject.toml - id: get_version - run: | - VERSION=$(grep '^version = ' vegafusion-python/pyproject.toml | sed 's/version = "\(.*\)"/\1/') - echo "version=$VERSION" >> $GITHUB_OUTPUT - echo "Version: $VERSION" - - name: Download all wheel artifacts - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - with: - pattern: python-wheels-* - path: wheels/ - merge-multiple: true - - name: List downloaded wheels - run: ls -lR wheels/ - - name: Create Release with wheels - env: - GH_TOKEN: ${{ github.token }} - run: | - gh release create "v${{ steps.get_version.outputs.version }}" \ - --title "Release v${{ steps.get_version.outputs.version }}" \ - --notes "" \ - wheels/* - publish-to-pypi: - name: Publish Python wheels to ${{ inputs.pypi_environment }} + name: Publish Python wheels to PyPI runs-on: ubuntu-latest - needs: [create-release] + needs: [build-and-test] environment: - name: ${{ inputs.pypi_environment }} - url: ${{ inputs.pypi_environment == 'pypi' && 'https://pypi.org/p/deepnote-vegafusion' || 'https://test.pypi.org/p/deepnote-vegafusion' }} + name: pypi + url: https://pypi.org/p/deepnote-vegafusion permissions: id-token: write steps: @@ -74,6 +32,5 @@ jobs: - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0 with: - repository-url: ${{ inputs.pypi_environment == 'testpypi' && 'https://test.pypi.org/legacy/' || '' }} skip-existing: true verbose: true From 0926fa3ba91c44911feb3e287d104cc5d3cd4a8c Mon Sep 17 00:00:00 2001 From: Oleh Date: Wed, 5 Nov 2025 12:06:15 +0100 Subject: [PATCH 4/4] Apply suggestions from code review Co-authored-by: Michal Baumgartner --- .github/workflows/build-and-test.yml | 4 +++- .github/workflows/pr.yml | 5 +++++ .github/workflows/release.yml | 9 ++++++--- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 663649bc..b704dd25 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -8,7 +8,9 @@ on: required: false type: boolean default: true - +permissions: + contents: read + actions: write jobs: check-rust: runs-on: ubuntu-22.04 diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 6f4eca2d..a7d924dd 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -4,8 +4,13 @@ on: pull_request: types: [opened, synchronize] +permissions: + contents: read + jobs: build-and-test: uses: ./.github/workflows/build-and-test.yml with: build-all-platforms: false + permissions: + contents: read diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 436a4d9a..1403de44 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,13 +3,14 @@ on: release: types: [published] -permissions: - contents: write - id-token: write + contents: read jobs: build-and-test: uses: ./.github/workflows/build-and-test.yml + permissions: + contents: read + actions: write publish-to-pypi: name: Publish Python wheels to PyPI @@ -20,6 +21,8 @@ jobs: url: https://pypi.org/p/deepnote-vegafusion permissions: id-token: write + contents: read + actions: read steps: - name: Download all wheel artifacts uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0