Work towards doctestplus compat with a facade for stdlib doctest #18
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
| # This workflow is autogenerated by xcookie. | |
| # File kind: release | |
| # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions | |
| # Based on ~/code/xcookie/xcookie/builders/github_actions.py | |
| # See: https://github.com/Erotemic/xcookie | |
| name: PurePyRelease | |
| on: | |
| push: | |
| workflow_dispatch: | |
| jobs: | |
| build_sdist: | |
| ## | |
| # Build the sdist artifact used by the release workflow. | |
| # This workflow intentionally builds artifacts but does not run the | |
| # full test matrix. | |
| ## | |
| name: Build sdist | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@v6.0.2 | |
| - name: Set up Python 3.14 | |
| uses: actions/setup-python@v5.6.0 | |
| with: | |
| python-version: '3.14' | |
| - name: Build sdist | |
| shell: bash | |
| run: |- | |
| python -m pip install pip uv -U | |
| python -m uv pip install setuptools>=0.8 wheel build twine | |
| python -m build --sdist --outdir wheelhouse | |
| python -m twine check ./wheelhouse/xdoctest*.tar.gz | |
| - name: Show built files | |
| shell: bash | |
| run: ls -la wheelhouse | |
| - uses: actions/upload-artifact@v6.0.0 | |
| name: Upload sdist artifact | |
| with: | |
| name: sdist_wheels | |
| path: ./wheelhouse/xdoctest*.tar.gz | |
| build_purepy_wheels: | |
| ## | |
| # Build the pure-python wheels used by the release workflow. | |
| ## | |
| name: ${{ matrix.python-version }} on ${{ matrix.os }}, arch=${{ matrix.arch }} with ${{ matrix.install-extras }} | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: | |
| - ubuntu-latest | |
| python-version: | |
| - '3.14' | |
| arch: | |
| - auto | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@v6.0.2 | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3.7.0 | |
| if: runner.os == 'Linux' && matrix.arch != 'auto' | |
| with: | |
| platforms: all | |
| - name: Setup Python | |
| uses: actions/setup-python@v5.6.0 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Build pure wheel | |
| shell: bash | |
| run: |- | |
| python -m pip install pip uv -U | |
| python -m uv pip install setuptools>=0.8 wheel build twine | |
| python -m build --wheel --outdir wheelhouse | |
| python -m twine check ./wheelhouse/xdoctest*.whl | |
| - name: Show built files | |
| shell: bash | |
| run: ls -la wheelhouse | |
| - uses: actions/upload-artifact@v6.0.0 | |
| name: Upload wheels artifact | |
| with: | |
| name: wheels-${{ matrix.os }}-${{ matrix.arch }} | |
| path: ./wheelhouse/xdoctest*.whl | |
| test_deploy: | |
| name: Deploy Test | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'push' && github.event.ref == 'refs/heads/main' | |
| needs: | |
| - build_purepy_wheels | |
| - build_sdist | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@v6.0.2 | |
| - uses: actions/download-artifact@v4.1.8 | |
| name: Download wheels | |
| with: | |
| pattern: wheels-* | |
| merge-multiple: true | |
| path: wheelhouse | |
| - uses: actions/download-artifact@v4.1.8 | |
| name: Download sdist | |
| with: | |
| name: sdist_wheels | |
| path: wheelhouse | |
| - name: Show files to upload | |
| shell: bash | |
| run: ls -la wheelhouse | |
| - name: Sign distributions | |
| env: | |
| GPG_SECRET_SIGNING_SUBKEY_B64: ${{ secrets.GPG_SECRET_SIGNING_SUBKEY_B64 }} | |
| GPG_PUBLIC_KEY_B64: ${{ secrets.GPG_PUBLIC_KEY_B64 }} | |
| GPG_OWNER_TRUST_B64: ${{ secrets.GPG_OWNER_TRUST_B64 }} | |
| run: |- | |
| GPG_EXECUTABLE=gpg | |
| $GPG_EXECUTABLE --version | |
| openssl version | |
| $GPG_EXECUTABLE --list-keys | |
| echo "Importing GPG keys from CI secrets" | |
| printf '%s' "$GPG_PUBLIC_KEY_B64" | base64 -d | $GPG_EXECUTABLE --import | |
| printf '%s' "$GPG_OWNER_TRUST_B64" | base64 -d | $GPG_EXECUTABLE --import-ownertrust | |
| printf '%s' "$GPG_SECRET_SIGNING_SUBKEY_B64" | base64 -d | $GPG_EXECUTABLE --import | |
| echo "Finish importing GPG keys" | |
| $GPG_EXECUTABLE --list-keys || true | |
| $GPG_EXECUTABLE --list-keys | |
| GPG_KEYID=$(cat dev/public_gpg_key) | |
| echo "GPG_KEYID = '$GPG_KEYID'" | |
| IMPORTED_FPR=$($GPG_EXECUTABLE --list-keys --with-colons "$GPG_KEYID" | awk -F: '/^fpr/ { print $10; exit }') | |
| if [[ "$IMPORTED_FPR" != "$GPG_KEYID" ]]; then echo "ERROR: imported GPG fingerprint $IMPORTED_FPR does not match pinned $GPG_KEYID"; exit 1; fi | |
| echo "GPG fingerprint verified: $IMPORTED_FPR" | |
| VERSION=$(python -c "import setup; print(setup.VERSION)") | |
| python -m pip install pip uv -U | |
| python -m pip install packaging twine -U | |
| python -m pip install urllib3 requests[security] | |
| GPG_SIGN_CMD="$GPG_EXECUTABLE --batch --yes --detach-sign --armor --local-user $GPG_KEYID" | |
| WHEEL_PATHS=(wheelhouse/*.whl wheelhouse/*.tar.gz) | |
| WHEEL_PATHS_STR=$(printf '"%s" ' "${WHEEL_PATHS[@]}") | |
| echo "$WHEEL_PATHS_STR" | |
| for WHEEL_PATH in "${WHEEL_PATHS[@]}" | |
| do | |
| echo "------" | |
| echo "WHEEL_PATH = $WHEEL_PATH" | |
| $GPG_SIGN_CMD --output $WHEEL_PATH.asc $WHEEL_PATH | |
| $GPG_EXECUTABLE --verify $WHEEL_PATH.asc $WHEEL_PATH || echo "hack, the first run of gpg very fails" | |
| $GPG_EXECUTABLE --verify $WHEEL_PATH.asc $WHEEL_PATH | |
| done | |
| ls -la wheelhouse | |
| python -m pip install opentimestamps-client | |
| ots stamp wheelhouse/*.whl wheelhouse/*.tar.gz wheelhouse/*.asc | |
| ls -la wheelhouse | |
| - name: Prepare publish directory | |
| shell: bash | |
| run: |- | |
| mkdir -p publish_wheelhouse | |
| shopt -s nullglob | |
| for FPATH in wheelhouse/*.whl wheelhouse/*.tar.gz wheelhouse/*.zip | |
| do | |
| cp "$FPATH" publish_wheelhouse/ | |
| done | |
| ls -la publish_wheelhouse | |
| - name: Publish test artifacts to TestPyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| packages-dir: publish_wheelhouse | |
| skip-existing: true | |
| repository-url: https://test.pypi.org/legacy/ | |
| - uses: actions/upload-artifact@v6.0.0 | |
| name: Upload deploy artifacts | |
| with: | |
| name: deploy_artifacts | |
| path: |- | |
| wheelhouse/*.whl | |
| wheelhouse/*.zip | |
| wheelhouse/*.tar.gz | |
| wheelhouse/*.asc | |
| wheelhouse/*.ots | |
| permissions: | |
| contents: read | |
| id-token: write | |
| environment: testpypi | |
| live_deploy: | |
| name: Deploy Live | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'push' && (startsWith(github.event.ref, 'refs/tags') || startsWith(github.event.ref, 'refs/heads/release')) | |
| needs: | |
| - build_purepy_wheels | |
| - build_sdist | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@v6.0.2 | |
| - uses: actions/download-artifact@v4.1.8 | |
| name: Download wheels | |
| with: | |
| pattern: wheels-* | |
| merge-multiple: true | |
| path: wheelhouse | |
| - uses: actions/download-artifact@v4.1.8 | |
| name: Download sdist | |
| with: | |
| name: sdist_wheels | |
| path: wheelhouse | |
| - name: Show files to upload | |
| shell: bash | |
| run: ls -la wheelhouse | |
| - name: Sign distributions | |
| env: | |
| GPG_SECRET_SIGNING_SUBKEY_B64: ${{ secrets.GPG_SECRET_SIGNING_SUBKEY_B64 }} | |
| GPG_PUBLIC_KEY_B64: ${{ secrets.GPG_PUBLIC_KEY_B64 }} | |
| GPG_OWNER_TRUST_B64: ${{ secrets.GPG_OWNER_TRUST_B64 }} | |
| run: |- | |
| GPG_EXECUTABLE=gpg | |
| $GPG_EXECUTABLE --version | |
| openssl version | |
| $GPG_EXECUTABLE --list-keys | |
| echo "Importing GPG keys from CI secrets" | |
| printf '%s' "$GPG_PUBLIC_KEY_B64" | base64 -d | $GPG_EXECUTABLE --import | |
| printf '%s' "$GPG_OWNER_TRUST_B64" | base64 -d | $GPG_EXECUTABLE --import-ownertrust | |
| printf '%s' "$GPG_SECRET_SIGNING_SUBKEY_B64" | base64 -d | $GPG_EXECUTABLE --import | |
| echo "Finish importing GPG keys" | |
| $GPG_EXECUTABLE --list-keys || true | |
| $GPG_EXECUTABLE --list-keys | |
| GPG_KEYID=$(cat dev/public_gpg_key) | |
| echo "GPG_KEYID = '$GPG_KEYID'" | |
| IMPORTED_FPR=$($GPG_EXECUTABLE --list-keys --with-colons "$GPG_KEYID" | awk -F: '/^fpr/ { print $10; exit }') | |
| if [[ "$IMPORTED_FPR" != "$GPG_KEYID" ]]; then echo "ERROR: imported GPG fingerprint $IMPORTED_FPR does not match pinned $GPG_KEYID"; exit 1; fi | |
| echo "GPG fingerprint verified: $IMPORTED_FPR" | |
| VERSION=$(python -c "import setup; print(setup.VERSION)") | |
| python -m pip install pip uv -U | |
| python -m pip install packaging twine -U | |
| python -m pip install urllib3 requests[security] | |
| GPG_SIGN_CMD="$GPG_EXECUTABLE --batch --yes --detach-sign --armor --local-user $GPG_KEYID" | |
| WHEEL_PATHS=(wheelhouse/*.whl wheelhouse/*.tar.gz) | |
| WHEEL_PATHS_STR=$(printf '"%s" ' "${WHEEL_PATHS[@]}") | |
| echo "$WHEEL_PATHS_STR" | |
| for WHEEL_PATH in "${WHEEL_PATHS[@]}" | |
| do | |
| echo "------" | |
| echo "WHEEL_PATH = $WHEEL_PATH" | |
| $GPG_SIGN_CMD --output $WHEEL_PATH.asc $WHEEL_PATH | |
| $GPG_EXECUTABLE --verify $WHEEL_PATH.asc $WHEEL_PATH || echo "hack, the first run of gpg very fails" | |
| $GPG_EXECUTABLE --verify $WHEEL_PATH.asc $WHEEL_PATH | |
| done | |
| ls -la wheelhouse | |
| python -m pip install opentimestamps-client | |
| ots stamp wheelhouse/*.whl wheelhouse/*.tar.gz wheelhouse/*.asc | |
| ls -la wheelhouse | |
| - name: Prepare publish directory | |
| shell: bash | |
| run: |- | |
| mkdir -p publish_wheelhouse | |
| shopt -s nullglob | |
| for FPATH in wheelhouse/*.whl wheelhouse/*.tar.gz wheelhouse/*.zip | |
| do | |
| cp "$FPATH" publish_wheelhouse/ | |
| done | |
| ls -la publish_wheelhouse | |
| - name: Publish live artifacts to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| packages-dir: publish_wheelhouse | |
| skip-existing: true | |
| - uses: actions/upload-artifact@v6.0.0 | |
| name: Upload deploy artifacts | |
| with: | |
| name: deploy_artifacts | |
| path: |- | |
| wheelhouse/*.whl | |
| wheelhouse/*.zip | |
| wheelhouse/*.tar.gz | |
| wheelhouse/*.asc | |
| wheelhouse/*.ots | |
| permissions: | |
| contents: read | |
| id-token: write | |
| environment: pypi | |
| release: | |
| name: Create Github Release | |
| if: github.event_name == 'push' && (startsWith(github.event.ref, 'refs/tags') || startsWith(github.event.ref, 'refs/heads/release')) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| needs: | |
| - live_deploy | |
| steps: | |
| - name: Checkout source | |
| uses: actions/checkout@v6.0.2 | |
| - uses: actions/download-artifact@v4.1.8 | |
| name: Download artifacts | |
| with: | |
| name: deploy_artifacts | |
| path: wheelhouse | |
| - name: Show files to release | |
| shell: bash | |
| run: ls -la wheelhouse | |
| - run: 'echo "Automatic Release Notes. TODO: improve" > ${{ github.workspace }}-CHANGELOG.txt' | |
| - name: Tag Release Commit | |
| if: (startsWith(github.event.ref, 'refs/heads/release')) | |
| run: |- | |
| export VERSION=$(python -c "import setup; print(setup.VERSION)") | |
| git tag "v$VERSION" | |
| git push origin "v$VERSION" | |
| - uses: softprops/action-gh-release@v1 | |
| name: Create Release | |
| id: create_release | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| body_path: ${{ github.workspace }}-CHANGELOG.txt | |
| tag_name: ${{ github.ref }} | |
| name: Release ${{ github.ref }} | |
| body: Automatic Release | |
| generate_release_notes: true | |
| draft: true | |
| prerelease: false | |
| files: |- | |
| wheelhouse/*.whl | |
| wheelhouse/*.asc | |
| wheelhouse/*.ots | |
| wheelhouse/*.zip | |
| wheelhouse/*.tar.gz | |
| ### | |
| # Trusted publishing setup checklist | |
| # | |
| # This release workflow file: | |
| # .github/workflows/release.yml | |
| # Workflow page: | |
| # github.com/Erotemic/xdoctest/actions/workflows/release.yml | |
| # Workflow source: | |
| # github.com/Erotemic/xdoctest/blob/main/.github/workflows/release.yml | |
| # GitHub environments: | |
| # github.com/Erotemic/xdoctest/settings/environments | |
| # | |
| # Official references: | |
| # https://docs.pypi.org/trusted-publishers/ | |
| # https://docs.pypi.org/trusted-publishers/using-a-publisher/ | |
| # https://docs.pypi.org/trusted-publishers/security-model/ | |
| # https://docs.github.com/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect | |
| # https://docs.github.com/actions/deployment/targeting-different-environments/using-environments-for-deployment | |
| # | |
| # If trusted publishing is not configured yet: | |
| # | |
| # 1. In GitHub, create or review these protected environments: | |
| # - testpypi | |
| # - pypi | |
| # URL: | |
| # github.com/Erotemic/xdoctest/settings/environments | |
| # | |
| # Some xcookie setups will expect a setup like: | |
| # | |
| # - testpypi: | |
| # * environment name: testpypi | |
| # * use for non-release pushes that publish to TestPyPI | |
| # * usually no manual approval is needed | |
| # * optionally restrict deployment branches if you only want | |
| # TestPyPI publishes from selected branches | |
| # | |
| # - pypi: | |
| # * environment name: pypi | |
| # * use for real releases only | |
| # * require manual approval / required reviewers | |
| # * prevent self-review if your org supports it | |
| # * restrict deployments to release branches / version tags | |
| # | |
| # - do not put TWINE_* secrets in these environments when using | |
| # trusted publishing | |
| # | |
| # - if enable_gpg=true and ci_gpg_secret_transport=encrypted_repo: | |
| # store CI_SECRET as an environment secret (not repo-wide) | |
| # - if enable_gpg=true and ci_gpg_secret_transport=direct_ci: | |
| # store GPG_SECRET_SIGNING_SUBKEY_B64, GPG_PUBLIC_KEY_B64, and | |
| # GPG_OWNER_TRUST_B64 as environment secrets; no CI_SECRET needed | |
| # | |
| # 2. In PyPI, add a trusted publisher for this project: | |
| # owner: Erotemic | |
| # repository: xdoctest | |
| # workflow filename: release.yml | |
| # environment: pypi | |
| # Project publishing page: | |
| # https://pypi.org/manage/project/xdoctest/settings/publishing/ | |
| # Account publishing page: | |
| # https://pypi.org/manage/account/publishing/ | |
| # | |
| # 3. In TestPyPI, add a trusted publisher for this project: | |
| # owner: Erotemic | |
| # repository: xdoctest | |
| # workflow filename: release.yml | |
| # environment: testpypi | |
| # Project publishing page: | |
| # https://test.pypi.org/manage/project/xdoctest/settings/publishing/ | |
| # Account publishing page: | |
| # https://test.pypi.org/manage/account/publishing/ | |
| # | |
| # Notes: | |
| # - Keep the workflow filename stable after registration. | |
| # - The PyPI/TestPyPI project pages may not exist until the project | |
| # exists there; use the account publishing pages for pending publishers. | |
| # - Trusted publishing removes TWINE_* secrets. | |
| # - When enable_gpg=true and ci_gpg_secret_transport="encrypted_repo": | |
| # CI_SECRET is still required (environment-scoped to pypi/testpypi). | |
| # - When enable_gpg=true and ci_gpg_secret_transport="direct_ci": | |
| # GPG_SECRET_SIGNING_SUBKEY_B64, GPG_PUBLIC_KEY_B64, and GPG_OWNER_TRUST_B64 | |
| # are required (environment-scoped to pypi/testpypi). No CI_SECRET. | |
| # | |
| # Local act note: | |
| # Trusted publishing cannot be fully emulated with local act secrets. | |
| # The local approximation is to run the signing / build portions only. | |
| # load_secrets | |
| # unset GITHUB_TOKEN | |
| # $HOME/.local/opt/act/act \ | |
| # --secret=GPG_SECRET_SIGNING_SUBKEY_B64=$GPG_SECRET_SIGNING_SUBKEY_B64 \ | |
| # --secret=GPG_PUBLIC_KEY_B64=$GPG_PUBLIC_KEY_B64 \ | |
| # --secret=GPG_OWNER_TRUST_B64=$GPG_OWNER_TRUST_B64 |