From 2513a015c9b49421e4a6eebe92406f5b9a87b28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Robert?= Date: Mon, 9 Mar 2026 12:34:38 +0100 Subject: [PATCH] SEC: fix exploitable template-injection surface --- .github/workflows/publish.yml | 10 +++++--- .github/workflows/tox.yml | 47 ++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 15 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 9e1c5a8..51fb5a5 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -129,8 +129,10 @@ jobs: env: LOAD_BUILD_TARGETS_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJjbGljaz09OC4yLjEiLAojICAgICAicHl5YW1sPT02LjAuMiIsCiMgXQojIC8vLwppbXBvcnQganNvbgppbXBvcnQgb3MKaW1wb3J0IHJlCgppbXBvcnQgY2xpY2sKaW1wb3J0IHlhbWwKCk1BQ0hJTkVfVFlQRSA9IHsKICAgICJsaW51eCI6ICJ1YnVudHUtbGF0ZXN0IiwKICAgICJtYWNvcyI6ICJtYWNvcy1sYXRlc3QiLAogICAgIndpbmRvd3MiOiAid2luZG93cy1sYXRlc3QiLAogICAgIndpbmRvd3MtYXJtIjogIndpbmRvd3MtMTEtYXJtIiwKfQoKQ0lCV19CVUlMRCA9IG9zLmVudmlyb24uZ2V0KCJDSUJXX0JVSUxEIiwgIioiKQpDSUJXX0FSQ0hTID0gb3MuZW52aXJvbi5nZXQoIkNJQldfQVJDSFMiLCAiYXV0byIpCgoKQGNsaWNrLmNvbW1hbmQoKQpAY2xpY2sub3B0aW9uKCItLXRhcmdldHMiLCBkZWZhdWx0PSIiKQpkZWYgbG9hZF9idWlsZF90YXJnZXRzKHRhcmdldHMpOgogICAgIiIiU2NyaXB0IHRvIGxvYWQgY2lidWlsZHdoZWVsIHRhcmdldHMgZm9yIEdpdEh1YiBBY3Rpb25zIHdvcmtmbG93LiIiIgogICAgIyBMb2FkIGxpc3Qgb2YgdGFyZ2V0cwogICAgdGFyZ2V0cyA9IHlhbWwubG9hZCh0YXJnZXRzLCBMb2FkZXI9eWFtbC5CYXNlTG9hZGVyKQogICAgcHJpbnQoanNvbi5kdW1wcyh0YXJnZXRzLCBpbmRlbnQ9MikpCgogICAgIyBDcmVhdGUgbWF0cml4CiAgICBtYXRyaXggPSB7ImluY2x1ZGUiOiBbXX0KICAgIGZvciB0YXJnZXQgaW4gdGFyZ2V0czoKICAgICAgICBtYXRyaXhbImluY2x1ZGUiXS5hcHBlbmQoZ2V0X21hdHJpeF9pdGVtKHRhcmdldCkpCgogICAgIyBPdXRwdXQgbWF0cml4CiAgICBwcmludChqc29uLmR1bXBzKG1hdHJpeCwgaW5kZW50PTIpKQogICAgd2l0aCBvcGVuKG9zLmVudmlyb25bIkdJVEhVQl9PVVRQVVQiXSwgImEiKSBhcyBmOgogICAgICAgIGYud3JpdGUoZiJtYXRyaXg9e2pzb24uZHVtcHMobWF0cml4KX1cbiIpCgoKZGVmIGdldF9vcyh0YXJnZXQpOgogICAgaWYgIm1hY29zIiBpbiB0YXJnZXQ6CiAgICAgICAgcmV0dXJuIE1BQ0hJTkVfVFlQRVsibWFjb3MiXQogICAgaWYgIndpbl9hcm0iIGluIHRhcmdldDoKICAgICAgICByZXR1cm4gTUFDSElORV9UWVBFWyJ3aW5kb3dzLWFybSJdCiAgICBpZiAid2luIiBpbiB0YXJnZXQ6CiAgICAgICAgcmV0dXJuIE1BQ0hJTkVfVFlQRVsid2luZG93cyJdCiAgICByZXR1cm4gTUFDSElORV9UWVBFWyJsaW51eCJdCgoKZGVmIGdldF9jaWJ3X2J1aWxkKHRhcmdldCk6CiAgICBpZiB0YXJnZXQgaW4geyJsaW51eCIsICJtYWNvcyIsICJ3aW5kb3dzIn06CiAgICAgICAgcmV0dXJuIENJQldfQlVJTEQKICAgIHJldHVybiB0YXJnZXQKCgpkZWYgZ2V0X2NpYndfYXJjaHModGFyZ2V0KToKICAgICIiIgogICAgSGFuZGxlIG5vbi1uYXRpdmUgYXJjaGl0ZWN0dXJlcwoKICAgIGNpYncgYWxsb3dzIHJ1bm5pbmcgbm9uLW5hdGl2ZSBidWlsZHMgb24gdmFyaW91cyBwbGF0Zm9ybXM6CiAgICBodHRwczovL2NpYnVpbGR3aGVlbC5weXBhLmlvL2VuL3N0YWJsZS9vcHRpb25zLyNhcmNocwoKICAgIFRoaXMgbG9naWMgb3ZlcnJpZGVzIHRoZSAiYXV0byIgZmxhZyBiYXNlZCBvbiBPUyBhbmQgYSBsaXN0IG9mIHN1cHBvcnRlZAogICAgbm9uLW5hdGl2ZSBhcmNoIGlmIGEgbm9uLW5hdGl2ZSBhcmNoIGlzIGdpdmVuIGZvciBhIHBhcnRpY3VsYXIgcGxhdGZvcm0gaW4KICAgIHRhcmdldHMsIHJhdGhlciB0aGFuIHRoZSB1c2VyIGhhdmluZyB0byBkbyB0aGlzIG1hbnVhbGx5LgogICAgIiIiCiAgICBwbGF0Zm9ybV9hcmNocyA9IHsKICAgICAgICAjIFdlIG5vdyBjcm9zcyBjb21waWxlIHg4Nl82NCBvbiBhcm02NCBieSBkZWZhdWx0CiAgICAgICAgIm1hY29zIjogWyJ1bml2ZXJzYWwyIiwgIng4Nl82NCJdLAogICAgICAgICMgVGhpcyBpcyBhIGxpc3Qgb2Ygc3VwcG9ydGVkIGV1bXVsYXRlZCBhcmNoZXMgb24gbGludXgKICAgICAgICAibGludXgiOiBbImFhcmNoNjQiLCAicHBjNjRsZSIsICJzMzkweCIsICJhcm12N2wiXSwKICAgIH0KICAgIGZvciBwbGF0Zm9ybSwgYXJjaHMgaW4gcGxhdGZvcm1fYXJjaHMuaXRlbXMoKToKICAgICAgICBpZiBwbGF0Zm9ybSBpbiB0YXJnZXQ6CiAgICAgICAgICAgIGZvciBhcmNoIGluIGFyY2hzOgogICAgICAgICAgICAgICAgaWYgdGFyZ2V0LmVuZHN3aXRoKGFyY2gpOgogICAgICAgICAgICAgICAgICAgIHJldHVybiBhcmNoCgogICAgIyBJZiBubyBleHBsaWN0IGFyY2ggaGFzIGJlZW4gc3BlY2lmaWVkIGJ1aWxkIGJvdGggYXJtNjQgYW5kIHg4Nl82NCBvbiBtYWNvcwogICAgaWYgIm1hY29zIiBpbiB0YXJnZXQ6CiAgICAgICAgcmV0dXJuIG9zLmVudmlyb24uZ2V0KCJDSUJXX0FSQ0hTIiwgImFybTY0IHg4Nl82NCIpCgogICAgcmV0dXJuIENJQldfQVJDSFMKCgpkZWYgZ2V0X2FydGlmYWN0X25hbWUodGFyZ2V0KToKICAgIGFydGlmYWN0X25hbWUgPSByZS5zdWIociJbXFwgLzo8PnwqP1wiJ10iLCAiLSIsIHRhcmdldCkKICAgIGFydGlmYWN0X25hbWUgPSByZS5zdWIociItKyIsICItIiwgYXJ0aWZhY3RfbmFtZSkKICAgIHJldHVybiBhcnRpZmFjdF9uYW1lCgoKZGVmIGdldF9tYXRyaXhfaXRlbSh0YXJnZXQpOgogICAgZXh0cmFfdGFyZ2V0X2FyZ3MgPSB7fQogICAgaWYgaXNpbnN0YW5jZSh0YXJnZXQsIGRpY3QpOgogICAgICAgIGV4dHJhX3RhcmdldF9hcmdzID0gdGFyZ2V0CiAgICAgICAgdGFyZ2V0ID0gZXh0cmFfdGFyZ2V0X2FyZ3MucG9wKCJ0YXJnZXQiKQogICAgcmV0dXJuIHsKICAgICAgICAidGFyZ2V0IjogdGFyZ2V0LAogICAgICAgICJydW5zLW9uIjogZ2V0X29zKHRhcmdldCksCiAgICAgICAgIkNJQldfQlVJTEQiOiBnZXRfY2lid19idWlsZCh0YXJnZXQpLAogICAgICAgICJDSUJXX0FSQ0hTIjogZ2V0X2NpYndfYXJjaHModGFyZ2V0KSwKICAgICAgICAiYXJ0aWZhY3QtbmFtZSI6IGdldF9hcnRpZmFjdF9uYW1lKHRhcmdldCksCiAgICAgICAgKipleHRyYV90YXJnZXRfYXJncywKICAgIH0KCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgbG9hZF9idWlsZF90YXJnZXRzKCkK - id: set-outputs - run: pipx run load_build_targets.py --targets "${{ inputs.targets }}" + run: pipx run load_build_targets.py --targets "${INPUTS_TARGETS}" shell: sh + env: + INPUTS_TARGETS: ${{ inputs.targets }} - id: set-upload run: | if [ $UPLOAD_TO_PYPI == "true" ] || [ $UPLOAD_TAG == "true" ]; @@ -203,11 +205,12 @@ jobs: if: ${{ inputs.env != '' }} run: | echo $SET_ENV_SCRIPT | base64 --decode > set_env.py - pipx run set_env.py "${{ inputs.env }}" + pipx run set_env.py "${INPUTS_ENV}" rm set_env.py shell: sh env: SET_ENV_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJweXlhbWw9PTYuMC4yIiwKIyBdCiMgLy8vCmltcG9ydCBqc29uCmltcG9ydCBvcwppbXBvcnQgc3lzCgppbXBvcnQgeWFtbAoKR0lUSFVCX0VOViA9IG9zLmdldGVudigiR0lUSFVCX0VOViIpCmlmIEdJVEhVQl9FTlYgaXMgTm9uZToKICAgIHJhaXNlIFZhbHVlRXJyb3IoIkdJVEhVQl9FTlYgbm90IHNldC4gTXVzdCBiZSBydW4gaW5zaWRlIEdpdEh1YiBBY3Rpb25zLiIpCgpERUxJTUlURVIgPSAiRU9GIgoKCmRlZiBzZXRfZW52KGVudik6CgogICAgZW52ID0geWFtbC5sb2FkKGVudiwgTG9hZGVyPXlhbWwuQmFzZUxvYWRlcikKICAgIHByaW50KGpzb24uZHVtcHMoZW52LCBpbmRlbnQ9MikpCgogICAgaWYgbm90IGlzaW5zdGFuY2UoZW52LCBkaWN0KToKICAgICAgICB0aXRsZSA9ICJgZW52YCBtdXN0IGJlIG1hcHBpbmciCiAgICAgICAgbWVzc2FnZSA9IGYiYGVudmAgbXVzdCBiZSBtYXBwaW5nIG9mIGVudiB2YXJpYWJsZXMgdG8gdmFsdWVzLCBnb3QgdHlwZSB7dHlwZShlbnYpfSIKICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICBleGl0KDEpCgogICAgZm9yIGssIHYgaW4gZW52Lml0ZW1zKCk6CgogICAgICAgIGlmIG5vdCBpc2luc3RhbmNlKHYsIHN0cik6CiAgICAgICAgICAgIHRpdGxlID0gImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MiCiAgICAgICAgICAgIG1lc3NhZ2UgPSBmImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MsIGJ1dCB2YWx1ZSBvZiB7a30gaGFzIHR5cGUge3R5cGUodil9IgogICAgICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICAgICAgZXhpdCgxKQoKICAgICAgICB2ID0gdi5zcGxpdCgiXG4iKQoKICAgICAgICB3aXRoIG9wZW4oR0lUSFVCX0VOViwgImEiKSBhcyBmOgogICAgICAgICAgICBpZiBsZW4odikgPT0gMToKICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7a309e3ZbMF19XG4iKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZm9yIGxpbmUgaW4gdjoKICAgICAgICAgICAgICAgICAgICBhc3NlcnQgbGluZS5zdHJpcCgpICE9IERFTElNSVRFUgogICAgICAgICAgICAgICAgZi53cml0ZShmIntrfTw8e0RFTElNSVRFUn1cbiIpCiAgICAgICAgICAgICAgICBmb3IgbGluZSBpbiB2OgogICAgICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7bGluZX1cbiIpCiAgICAgICAgICAgICAgICBmLndyaXRlKGYie0RFTElNSVRFUn1cbiIpCgogICAgICAgIHByaW50KGYie2t9IHdyaXR0ZW4gdG8gR0lUSFVCX0VOViIpCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIHNldF9lbnYoc3lzLmFyZ3ZbMV0pCg== + INPUTS_ENV: ${{ inputs.env }} - name: Run cibuildwheel uses: pypa/cibuildwheel@298ed2fb2c105540f5ed055e8a6ad78d82dd3a7e # v3.3.1 with: @@ -239,11 +242,12 @@ jobs: if: ${{ inputs.env != '' }} run: | echo $SET_ENV_SCRIPT | base64 --decode > set_env.py - pipx run set_env.py "${{ inputs.env }}" + pipx run set_env.py "${INPUTS_ENV}" rm set_env.py shell: sh env: SET_ENV_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJweXlhbWw9PTYuMC4yIiwKIyBdCiMgLy8vCmltcG9ydCBqc29uCmltcG9ydCBvcwppbXBvcnQgc3lzCgppbXBvcnQgeWFtbAoKR0lUSFVCX0VOViA9IG9zLmdldGVudigiR0lUSFVCX0VOViIpCmlmIEdJVEhVQl9FTlYgaXMgTm9uZToKICAgIHJhaXNlIFZhbHVlRXJyb3IoIkdJVEhVQl9FTlYgbm90IHNldC4gTXVzdCBiZSBydW4gaW5zaWRlIEdpdEh1YiBBY3Rpb25zLiIpCgpERUxJTUlURVIgPSAiRU9GIgoKCmRlZiBzZXRfZW52KGVudik6CgogICAgZW52ID0geWFtbC5sb2FkKGVudiwgTG9hZGVyPXlhbWwuQmFzZUxvYWRlcikKICAgIHByaW50KGpzb24uZHVtcHMoZW52LCBpbmRlbnQ9MikpCgogICAgaWYgbm90IGlzaW5zdGFuY2UoZW52LCBkaWN0KToKICAgICAgICB0aXRsZSA9ICJgZW52YCBtdXN0IGJlIG1hcHBpbmciCiAgICAgICAgbWVzc2FnZSA9IGYiYGVudmAgbXVzdCBiZSBtYXBwaW5nIG9mIGVudiB2YXJpYWJsZXMgdG8gdmFsdWVzLCBnb3QgdHlwZSB7dHlwZShlbnYpfSIKICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICBleGl0KDEpCgogICAgZm9yIGssIHYgaW4gZW52Lml0ZW1zKCk6CgogICAgICAgIGlmIG5vdCBpc2luc3RhbmNlKHYsIHN0cik6CiAgICAgICAgICAgIHRpdGxlID0gImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MiCiAgICAgICAgICAgIG1lc3NhZ2UgPSBmImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MsIGJ1dCB2YWx1ZSBvZiB7a30gaGFzIHR5cGUge3R5cGUodil9IgogICAgICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICAgICAgZXhpdCgxKQoKICAgICAgICB2ID0gdi5zcGxpdCgiXG4iKQoKICAgICAgICB3aXRoIG9wZW4oR0lUSFVCX0VOViwgImEiKSBhcyBmOgogICAgICAgICAgICBpZiBsZW4odikgPT0gMToKICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7a309e3ZbMF19XG4iKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZm9yIGxpbmUgaW4gdjoKICAgICAgICAgICAgICAgICAgICBhc3NlcnQgbGluZS5zdHJpcCgpICE9IERFTElNSVRFUgogICAgICAgICAgICAgICAgZi53cml0ZShmIntrfTw8e0RFTElNSVRFUn1cbiIpCiAgICAgICAgICAgICAgICBmb3IgbGluZSBpbiB2OgogICAgICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7bGluZX1cbiIpCiAgICAgICAgICAgICAgICBmLndyaXRlKGYie0RFTElNSVRFUn1cbiIpCgogICAgICAgIHByaW50KGYie2t9IHdyaXR0ZW4gdG8gR0lUSFVCX0VOViIpCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIHNldF9lbnYoc3lzLmFyZ3ZbMV0pCg== + INPUTS_ENV: ${{ inputs.env }} - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index c5b9873..21bd510 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -132,18 +132,33 @@ jobs: - run: cat tox_matrix.py - id: set-outputs run: | - pipx run tox_matrix.py --envs "${{ inputs.envs }}" --libraries "${{ inputs.libraries }}" \ - --posargs "${{ inputs.posargs }}" --toxdeps "${{ inputs.toxdeps }}" \ - --toxargs "${{ inputs.toxargs }}" --pytest "${{ inputs.pytest }}" \ + pipx run tox_matrix.py --envs "${INPUTS_ENVS}" --libraries "${INPUTS_LIBRARIES}" \ + --posargs "${INPUTS_POSARGS}" --toxdeps "${INPUTS_TOXDEPS}" \ + --toxargs "${INPUTS_TOXARGS}" --pytest "${{ inputs.pytest }}" \ --pytest-results-summary "${{ inputs.pytest-results-summary }}" \ - --coverage "${{ inputs.coverage }}" --conda "${{ inputs.conda }}" \ - --setenv "${{ inputs.setenv }}" \ - --display "${{ inputs.display }}" --cache-path "${{ inputs.cache-path }}" \ - --cache-key "${{ inputs.cache-key }}" --cache-restore-keys "${{ inputs.cache-restore-keys }}" \ - --artifact-path "${{ inputs.artifact-path }}" \ - --runs-on "${{ inputs.runs-on }}" --default-python "${{ inputs.default_python }}" \ + --coverage "${INPUTS_COVERAGE}" --conda "${INPUTS_CONDA}" \ + --setenv "${INPUTS_SETENV}" \ + --display "${{ inputs.display }}" --cache-path "${INPUTS_CACHE_PATH}" \ + --cache-key "${INPUTS_CACHE_KEY}" --cache-restore-keys "${INPUTS_CACHE_RESTORE_KEYS}" \ + --artifact-path "${INPUTS_ARTIFACT_PATH}" \ + --runs-on "${INPUTS_RUNS_ON}" --default-python "${INPUTS_DEFAULT_PYTHON}" \ --timeout-minutes "${{ inputs.timeout-minutes }}" shell: sh + env: + INPUTS_ENVS: ${{ inputs.envs }} + INPUTS_LIBRARIES: ${{ inputs.libraries }} + INPUTS_POSARGS: ${{ inputs.posargs }} + INPUTS_TOXDEPS: ${{ inputs.toxdeps }} + INPUTS_TOXARGS: ${{ inputs.toxargs }} + INPUTS_COVERAGE: ${{ inputs.coverage }} + INPUTS_CONDA: ${{ inputs.conda }} + INPUTS_SETENV: ${{ inputs.setenv }} + INPUTS_CACHE_PATH: ${{ inputs.cache-path }} + INPUTS_CACHE_KEY: ${{ inputs.cache-key }} + INPUTS_CACHE_RESTORE_KEYS: ${{ inputs.cache-restore-keys }} + INPUTS_ARTIFACT_PATH: ${{ inputs.artifact-path }} + INPUTS_RUNS_ON: ${{ inputs.runs-on }} + INPUTS_DEFAULT_PYTHON: ${{ inputs.default_python }} outputs: matrix: ${{ steps.set-outputs.outputs.matrix }} @@ -211,19 +226,27 @@ jobs: if: ${{ matrix.setenv != '' }} run: | echo $SET_ENV_SCRIPT | base64 --decode > set_env.py - pipx run set_env.py "${{ matrix.setenv }}" + pipx run set_env.py "${MATRIX_SETENV}" rm set_env.py env: SET_ENV_SCRIPT: IyAvLy8gc2NyaXB0CiMgcmVxdWlyZXMtcHl0aG9uID0gIj09My4xMiIKIyBkZXBlbmRlbmNpZXMgPSBbCiMgICAgICJweXlhbWw9PTYuMC4yIiwKIyBdCiMgLy8vCmltcG9ydCBqc29uCmltcG9ydCBvcwppbXBvcnQgc3lzCgppbXBvcnQgeWFtbAoKR0lUSFVCX0VOViA9IG9zLmdldGVudigiR0lUSFVCX0VOViIpCmlmIEdJVEhVQl9FTlYgaXMgTm9uZToKICAgIHJhaXNlIFZhbHVlRXJyb3IoIkdJVEhVQl9FTlYgbm90IHNldC4gTXVzdCBiZSBydW4gaW5zaWRlIEdpdEh1YiBBY3Rpb25zLiIpCgpERUxJTUlURVIgPSAiRU9GIgoKCmRlZiBzZXRfZW52KGVudik6CgogICAgZW52ID0geWFtbC5sb2FkKGVudiwgTG9hZGVyPXlhbWwuQmFzZUxvYWRlcikKICAgIHByaW50KGpzb24uZHVtcHMoZW52LCBpbmRlbnQ9MikpCgogICAgaWYgbm90IGlzaW5zdGFuY2UoZW52LCBkaWN0KToKICAgICAgICB0aXRsZSA9ICJgZW52YCBtdXN0IGJlIG1hcHBpbmciCiAgICAgICAgbWVzc2FnZSA9IGYiYGVudmAgbXVzdCBiZSBtYXBwaW5nIG9mIGVudiB2YXJpYWJsZXMgdG8gdmFsdWVzLCBnb3QgdHlwZSB7dHlwZShlbnYpfSIKICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICBleGl0KDEpCgogICAgZm9yIGssIHYgaW4gZW52Lml0ZW1zKCk6CgogICAgICAgIGlmIG5vdCBpc2luc3RhbmNlKHYsIHN0cik6CiAgICAgICAgICAgIHRpdGxlID0gImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MiCiAgICAgICAgICAgIG1lc3NhZ2UgPSBmImBlbnZgIHZhbHVlcyBtdXN0IGJlIHN0cmluZ3MsIGJ1dCB2YWx1ZSBvZiB7a30gaGFzIHR5cGUge3R5cGUodil9IgogICAgICAgICAgICBwcmludChmIjo6ZXJyb3IgdGl0bGU9e3RpdGxlfTo6e21lc3NhZ2V9IikKICAgICAgICAgICAgZXhpdCgxKQoKICAgICAgICB2ID0gdi5zcGxpdCgiXG4iKQoKICAgICAgICB3aXRoIG9wZW4oR0lUSFVCX0VOViwgImEiKSBhcyBmOgogICAgICAgICAgICBpZiBsZW4odikgPT0gMToKICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7a309e3ZbMF19XG4iKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgZm9yIGxpbmUgaW4gdjoKICAgICAgICAgICAgICAgICAgICBhc3NlcnQgbGluZS5zdHJpcCgpICE9IERFTElNSVRFUgogICAgICAgICAgICAgICAgZi53cml0ZShmIntrfTw8e0RFTElNSVRFUn1cbiIpCiAgICAgICAgICAgICAgICBmb3IgbGluZSBpbiB2OgogICAgICAgICAgICAgICAgICAgIGYud3JpdGUoZiJ7bGluZX1cbiIpCiAgICAgICAgICAgICAgICBmLndyaXRlKGYie0RFTElNSVRFUn1cbiIpCgogICAgICAgIHByaW50KGYie2t9IHdyaXR0ZW4gdG8gR0lUSFVCX0VOViIpCgoKaWYgX19uYW1lX18gPT0gIl9fbWFpbl9fIjoKICAgIHNldF9lbnYoc3lzLmFyZ3ZbMV0pCg== + MATRIX_SETENV: ${{ matrix.setenv }} - name: Setup headless display if: ${{ matrix.display == 'true' }} uses: pyvista/setup-headless-display-action@7d84ae825e6d9297a8e99bdbbae20d1b919a0b19 # v4.2 - name: Install tox - run: python -m pip install --upgrade tox ${{ matrix.toxdeps }} + run: python -m pip install --upgrade tox ${MATRIX_TOXDEPS} + env: + MATRIX_TOXDEPS: ${{ matrix.toxdeps }} - - run: python -m tox -e ${{ matrix.toxenv }} ${{ matrix.toxargs }} -- ${{ matrix.pytest_flag }} ${{ matrix.posargs }} + - run: python -m tox -e ${MATRIX_TOXENV} ${MATRIX_TOXARGS} -- ${MATRIX_PYTEST_FLAG} ${MATRIX_POSARGS} + env: + MATRIX_TOXENV: ${{ matrix.toxenv }} + MATRIX_TOXARGS: ${{ matrix.toxargs }} + MATRIX_PYTEST_FLAG: ${{ matrix.pytest_flag }} + MATRIX_POSARGS: ${{ matrix.posargs }} - if: ${{ (success() || failure()) && matrix.artifact-path != '' }} uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0