From 80214ce8a4e59c58537bce3c57a8999a1aecb271 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 25 Aug 2026 12:53:21 +0200 Subject: [PATCH 1/2] debugpy: add build-debugpy.yml for riscv64 wheels debugpy publishes per-interpreter manylinux wheels containing pydevd's two Cython speedups (pydevd_cython, _pydevd_sys_monitoring_cython) but no riscv64 build. Build-from-checkout via cibuildwheel; the pre-generated .c files ship in the tree, so no Cython is needed. REQUIRE_CYTHON_BUILD=1 is load-bearing: setup.py runs the pydevd extension build in a subprocess and swallows failures, shipping a wheel with no .so. Tests run upstream's own suite (tox drives the same pytest invocation) with PYDEVD_USE_CYTHON=yes so pydevd raises rather than falling back to the pure-Python tracer. --- .github/workflows/build-debugpy.yml | 108 ++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 .github/workflows/build-debugpy.yml diff --git a/.github/workflows/build-debugpy.yml b/.github/workflows/build-debugpy.yml new file mode 100644 index 00000000..e180a6a7 --- /dev/null +++ b/.github/workflows/build-debugpy.yml @@ -0,0 +1,108 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# Based on: https://github.com/microsoft/debugpy/blob/v1.8.21/azure-pipelines/pipelines.yaml +# (wheels come from a separate internal pipeline; the public one runs the tox +# suite this workflow drives through cibuildwheel). +name: Build debugpy wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'debugpy version to build (e.g. 1.8.21)' + required: true + default: '1.8.21' + pull_request: + paths: + - '.github/workflows/build-debugpy.yml' + +concurrency: + group: ${{ github.workflow }}-${{ inputs.version || '1.8.21' }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + DEBUGPY_VERSION: ${{ inputs.version || '1.8.21' }} + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + +jobs: + build_wheels: + name: Build debugpy ${{ inputs.version || '1.8.21' }} ${{ matrix.python }}-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 300 + strategy: + fail-fast: false + matrix: + # pydevd's Cython speedups are plain per-interpreter extensions. + python: [cp312, cp313, cp314, cp314t] + + steps: + - name: Checkout debugpy ${{ env.DEBUGPY_VERSION }} + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + repository: microsoft/debugpy + ref: v${{ env.DEBUGPY_VERSION }} + persist-credentials: false + + - name: Build wheels + uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 + with: + output-dir: wheelhouse/ + only: ${{ matrix.python }}-manylinux_riscv64 + env: + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + # setup.py swallows the pydevd Cython build failure and ships a wheel + # with no .so unless this is set (CLAUDE.md gotcha 20). + CIBW_ENVIRONMENT: >- + REQUIRE_CYTHON_BUILD=1 + PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ + # tests/ is a package whose conftest registers tests.* plugins, so it has + # to sit in the (empty) test cwd; pytest.ini carries testpaths and -n8. + CIBW_TEST_SOURCES: tests pytest.ini + # tests/requirements.txt minus gevent (no riscv64 wheel; its one test is + # deselected below) and the Windows/build-only vswhere and Cython. + CIBW_TEST_REQUIRES: >- + pytest pytest-xdist pytest-timeout pytest-retry + importlib_metadata psutil untangle + django flask numpy requests typing_extensions + # PYDEVD_USE_CYTHON=yes makes pydevd raise instead of silently falling + # back to the pure-Python tracer, so the whole suite exercises the .so. + CIBW_TEST_ENVIRONMENT: >- + DEBUGPY_TEST=1 + PYDEVD_USE_CYTHON=yes + DEBUGPY_PROCESS_SPAWN_TIMEOUT=180 + CIBW_TEST_COMMAND: >- + python -c "import debugpy._vendored.force_pydevd; + import _pydevd_bundle.pydevd_cython_wrapper as w; + import _pydevd_sys_monitoring._pydevd_sys_monitoring_cython as m; + assert w.mod.__file__.endswith('.so'), w.mod.__file__; + assert m.__file__.endswith('.so'), m.__file__" && + python -Xfrozen_modules=off -m pytest --timeout=600 + --ignore=tests/debugpy/test_gevent.py + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: debugpy-${{ env.DEBUGPY_VERSION }}-${{ matrix.python }}-manylinux_riscv64 + path: wheelhouse/*.whl + if-no-files-found: error + + publish: + name: Publish debugpy ${{ inputs.version || '1.8.21' }} to GitLab + needs: [build_wheels] + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Publish wheels and open docs PR + uses: riseproject-dev/python-wheels/actions/publish-wheels@main + with: + artifact-pattern: debugpy-${{ env.DEBUGPY_VERSION }}-*-manylinux_riscv64 + gitlab-username: ${{ vars.GITLAB_DEPLOY_USER }} + gitlab-token: ${{ secrets.GITLAB_DEPLOY_TOKEN }} + gitlab-project-id: ${{ vars.GITLAB_PROJECT_ID }} + gh-token: ${{ secrets.GITHUB_TOKEN }} From c997ca3dcdb0e0ad27ef05eaf9965e2b2ee412d2 Mon Sep 17 00:00:00 2001 From: Ludovic Henry Date: Tue, 25 Aug 2026 16:09:56 +0200 Subject: [PATCH 2/2] debugpy: skip attach-by-PID tests below 3.14, drop free-threaded build pydevd injects its attach shim with a per-arch prebuilt library and add_code_to_python_process.py only accepts x86/i386/x86_64/amd64/arm64, so attach-by-PID cannot work on riscv64. CPython 3.14 goes through sys.remote_exec() instead (debugpy/server/cli.py), which is why the cp314 job passed all 1330 tests while cp312/cp313 failed exactly the 100 attach_pid ones. Drop cp314t: debugpy publishes no free-threaded wheel, its tox envlist stops at py314, and the free-threaded job crashed 40 pytest-xdist workers spread across every test module. --- .github/workflows/build-debugpy.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-debugpy.yml b/.github/workflows/build-debugpy.yml index e180a6a7..b5bd313e 100644 --- a/.github/workflows/build-debugpy.yml +++ b/.github/workflows/build-debugpy.yml @@ -36,8 +36,14 @@ jobs: strategy: fail-fast: false matrix: - # pydevd's Cython speedups are plain per-interpreter extensions. - python: [cp312, cp313, cp314, cp314t] + # pydevd's Cython speedups are plain per-interpreter extensions, and + # upstream ships no free-threaded wheel (tox envlist stops at py314). + include: + # attach-by-PID injects pydevd's shim, which upstream compiles for + # x86/arm64 only; 3.14 attaches through sys.remote_exec instead. + - {python: cp312, pytest_k: 'not attach_pid'} + - {python: cp313, pytest_k: 'not attach_pid'} + - {python: cp314, pytest_k: ''} steps: - name: Checkout debugpy ${{ env.DEBUGPY_VERSION }} @@ -81,6 +87,7 @@ jobs: assert w.mod.__file__.endswith('.so'), w.mod.__file__; assert m.__file__.endswith('.so'), m.__file__" && python -Xfrozen_modules=off -m pytest --timeout=600 + -k "${{ matrix.pytest_k }}" --ignore=tests/debugpy/test_gevent.py - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1