mirror of
https://github.com/cocoindex-io/cocoindex-code.git
synced 2026-09-14 16:39:38 +08:00
90d8ff9f08
The previous `type=gha` cache was scoped per Git ref, so each release tag created a new cache scope and never reused a previous release's layers. Add to that GHA's 10 GB per-repo limit (which we already hit at ~10 GB before the v0.2.26 release), and the cache effectively never helped consecutive releases. Move to `type=registry` cache stored as separate `buildcache-<variant>` tags on the same GHCR package. Branch/tag-independent, no LRU eviction, unlimited size for our purposes. Standard pattern for multi-arch buildx + multi-registry publishes. Per-variant cache tag (`buildcache-slim`, `buildcache-full`) so the two variants don't evict each other's layers. `mode=max` exports all intermediate layers, not just the final ones — needed for the per-RUN-layer reuse strategy in the Dockerfile. Also cleaned up 23 orphaned GHA cache entries on the deleted g/docker-layer-cache-v2 branch (3.4 GB freed).
231 lines
7.5 KiB
YAML
231 lines
7.5 KiB
YAML
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.
|
|
# Registry-backed BuildKit cache, stored as a separate tag
|
|
# (`buildcache-<variant>`) on the same GHCR package. Independent of
|
|
# branch/tag, so cache reuses across releases (every release tag is
|
|
# a different ref, which would have made GHA-scoped caching miss).
|
|
# `mode=max` exports all layers, including intermediate ones.
|
|
cache-from: type=registry,ref=ghcr.io/cocoindex-io/cocoindex-code:buildcache-${{ matrix.variant }}
|
|
cache-to: type=registry,ref=ghcr.io/cocoindex-io/cocoindex-code:buildcache-${{ matrix.variant }},mode=max
|