Release to PyPI #38
Workflow file for this run
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
| name: Release to PyPI | |
| on: | |
| release: | |
| types: [published] | |
| workflow_dispatch: | |
| inputs: | |
| test_pypi_only: | |
| description: 'Publish to TestPyPI only' | |
| required: false | |
| type: boolean | |
| default: false | |
| test_docker: | |
| description: 'Build & push the Docker image (tagged :test) without running PyPI publish — use to verify Docker Hub / GHCR credentials' | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| build: | |
| name: Build distribution | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v5 | |
| - name: Build package | |
| run: uv build | |
| - name: Store the distribution packages | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: python-package-distributions | |
| path: dist/ | |
| publish-to-testpypi: | |
| name: Publish to TestPyPI | |
| if: github.event_name == 'workflow_dispatch' && inputs.test_pypi_only | |
| needs: | |
| - build | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: testpypi | |
| url: https://test.pypi.org/p/cocoindex-code | |
| permissions: | |
| id-token: write | |
| steps: | |
| - name: Download all the dists | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: python-package-distributions | |
| path: dist/ | |
| - name: Publish distribution to TestPyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| with: | |
| repository-url: https://test.pypi.org/legacy/ | |
| publish-to-pypi: | |
| name: Publish to PyPI | |
| if: github.event_name == 'release' | |
| needs: | |
| - build | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: pypi | |
| url: https://pypi.org/p/cocoindex-code | |
| permissions: | |
| id-token: write | |
| steps: | |
| - name: Download all the dists | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: python-package-distributions | |
| path: dist/ | |
| - name: Publish distribution to PyPI | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| github-release: | |
| name: Upload distribution to GitHub Release | |
| needs: | |
| - publish-to-pypi | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download all the dists | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: python-package-distributions | |
| path: dist/ | |
| - name: Upload distributions to GitHub Release | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| run: >- | |
| gh release upload | |
| '${{ github.ref_name }}' dist/* | |
| --repo '${{ github.repository }}' | |
| publish-docker: | |
| name: Build & push Docker image (${{ matrix.variant }}) | |
| # Runs on real releases, and on manual dispatch with `test_docker=true` | |
| # for verifying registry credentials before the first release. | |
| if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.test_docker) | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: docker-hub | |
| url: https://hub.docker.com/r/cocoindex/cocoindex-code | |
| permissions: | |
| contents: read | |
| packages: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # slim (default) — LiteLLM-only, ~300 MB. Publishes as `:latest`. | |
| - variant: slim | |
| install_spec: /ccc-src | |
| # full — bundles sentence-transformers + torch + baked model, | |
| # ~2 GB. Publishes as `:full`. | |
| - variant: full | |
| install_spec: /ccc-src[full] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| # QEMU lets buildx cross-compile linux/arm64 on the x86_64 runner. | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| with: | |
| platforms: arm64 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: docker.io | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Compute image tags | |
| id: tags | |
| # Tag scheme: | |
| # slim on release: :latest, :<version> | |
| # full on release: :full, :<version>-full | |
| # slim on dispatch: :test | |
| # full on dispatch: :test-full | |
| # Dispatched tags stay out of the `:latest` / `:<version>` namespace | |
| # so manual test runs don't clobber what users pull. | |
| run: | | |
| variant="${{ matrix.variant }}" | |
| if [ "$variant" = "slim" ]; then | |
| slim_suffix="" | |
| else | |
| slim_suffix="-$variant" | |
| fi | |
| if [ "${{ github.event_name }}" = "release" ]; then | |
| version="${{ github.ref_name }}" | |
| if [ "$variant" = "slim" ]; then | |
| latest_tag="latest" | |
| else | |
| latest_tag="$variant" | |
| fi | |
| { | |
| echo "tags<<EOF" | |
| echo "cocoindex/cocoindex-code:${latest_tag}" | |
| echo "cocoindex/cocoindex-code:${version}${slim_suffix}" | |
| echo "ghcr.io/cocoindex-io/cocoindex-code:${latest_tag}" | |
| echo "ghcr.io/cocoindex-io/cocoindex-code:${version}${slim_suffix}" | |
| echo "EOF" | |
| } >> "$GITHUB_OUTPUT" | |
| else | |
| test_tag="test${slim_suffix}" | |
| { | |
| echo "tags<<EOF" | |
| echo "cocoindex/cocoindex-code:${test_tag}" | |
| echo "ghcr.io/cocoindex-io/cocoindex-code:${test_tag}" | |
| echo "EOF" | |
| } >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Build and push to both registries | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: docker/Dockerfile | |
| push: true | |
| # Native amd64 for Linux servers + Intel Macs; arm64 (cross-compiled | |
| # via QEMU) for Apple Silicon Macs and arm64 Linux hosts. | |
| platforms: linux/amd64,linux/arm64 | |
| # Install cocoindex-code from the checked-out source tree, not PyPI. | |
| # Avoids a race where a just-published version hasn't propagated to | |
| # PyPI's CDN yet (which happened on v0.2.24 release), and ensures | |
| # the image matches the tagged commit byte-for-byte. | |
| build-args: | | |
| CCC_VARIANT=${{ matrix.variant }} | |
| CCC_INSTALL_SPEC=${{ matrix.install_spec }} | |
| tags: ${{ steps.tags.outputs.tags }} | |
| # Per-variant BuildKit cache so slim and full don't evict each | |
| # other's layers. The heavy `deps` layer (torch + friends for | |
| # full; empty for slim) reuses across releases. | |
| cache-from: type=gha,scope=${{ matrix.variant }} | |
| cache-to: type=gha,mode=max,scope=${{ matrix.variant }} |