Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mikegerber/3a152875a05bae2494898fabc2bbf7e9 to your computer and use it in GitHub Desktop.
Save mikegerber/3a152875a05bae2494898fabc2bbf7e9 to your computer and use it in GitHub Desktop.
OCR-D - Python package versioning + publishing
theme
white

Agenda

πŸ’‘ Consistency πŸ’‘ Less manual work

  • Part 1: Dealing with versions

    • We have multiple places for the version! 🫠
  • Part 2: Automating the busywork

    • Publishing the package on GitHub
    • Publishing the package on PyPI

1: Dealing with versions – The challenge

We have multiple sources for the program version:

  • Python package (pyproject.toml)

  • ocrd-tool.json

    β†’ Part 1A

  • git tag

    β†’ Part 1B


1A: Sourcing the version from ocrd-tool.json

  • Before pyproject.toml, we programatically read the version in setup.py

  • ❌ Can't do that anymore with pyproject.toml

  • βœ… We now have setuptools-ocrd

    • setuptools plugin
    • reads version from ocrd-tool.json
    • makes sure ocrd-tool.json is in the sdist

How to use setuptools-ocrd

  • Include as part of the build-system in pyproject.toml:
[build-system]
requires = ["setuptools>=61.0.0", "wheel", "setuptools-ocrd"]

[project]
...
#version = "1.2.3" ← Remove this line 
dynamic = ["version", ...]  # 
  • Building the Python package (e.g. python -m build) should now produce a package (and sdist) with the correct version!

1B: Python package version vs git tag

  • ❌ Can't source the package version from the git tag, because we need it in ocrd-tool.json
  • πŸ’‘ Check git tag on tag push in CI

GitHub Action workflow release.yml (shortened!):

on:
  push:
    tags:
      - "v*.*.*"

jobs:
  # [...]
  build:
    needs: test
    runs-on: ubuntu-latest
    steps:
      # [...]
	  - name: Check git tag vs package version
        run: .github/workflows/release-check-version-tag

2: Automating the busywork

  • Goal: Have a consistent upload of

    • git tag
    • GitHub release
    • PyPI release
  • πŸ’‘ Trigger GitHub + PyPI releases by git tag


GitHub Actions workflow

Pasted image 20240826203540

  • These snippets are shortened!
  • Full example in the dinglehopper project
  • This should be possible to do with CircleCI, too

Trigger on git tag push

name: release

on:
  push:
    tags:
      - "v*.*.*"

# [continued]

Build Python package

jobs:
  ​build:
      # [... After check from part 1 ...]
      
	  - name: Build package
        run: |
          python3 -m pip install --upgrade build 
          python3 -m build
      
	  - name: Upload dist
        uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/

Create a GitHub release (incl. files)

  github-release:
  
    steps:
    
      - name: Download dist
        uses: actions/download-artifact@v4
        with: { name: dist, path: dist/ }
          
      - name: Create release on GitHub
        uses: softprops/action-gh-release@v1
        with:
          files: dist/*

(Uses GitHub's implicit credentials.)


Create a PyPI release

  pypi-publish:
    environment:
      name: pypi
      url: ${{ env.PYPI_URL }}
    permissions:
      id-token: write  
    
    steps:
      - name: Download dist
        uses: actions/download-artifact@v4
        with: { name: dist, path: dist/ }
      - name: Publish package distributions to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1

(Uses PyPI's trusted publishing.)


Future work?

  • Unfortunate that ocrd-tool.json requires a version

    • no single-sourcing from git!
  • .github/workflows/release-check-version-tag could be a reusable GitHub Action


Probably not:

  • It's good that the above release workflow is composed of different steps

    • Don't combine into a GitHub Action to retain flexibility
    • Copying the YAML is good enough
  • CircleCI


Questions?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment