From ab745550544c7819200787bd9763183b181fcb7c Mon Sep 17 00:00:00 2001 From: kalebbroo Date: Sun, 30 Aug 2026 00:03:21 -0400 Subject: [PATCH] Publish AI Toolkit worker image from CI --- .dockerignore | 6 ++- .github/workflows/publish-image.yml | 81 +++++++++++++++++++++++++++++ README.md | 18 +++++++ 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/publish-image.yml diff --git a/.dockerignore b/.dockerignore index b943e2c..7b0b5ae 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,7 @@ +.git +.github __pycache__ -*.pyc +*.py[cod] .pytest_cache +.venv +venv diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml new file mode 100644 index 0000000..2fad3e4 --- /dev/null +++ b/.github/workflows/publish-image.yml @@ -0,0 +1,81 @@ +name: Build and publish worker image + +on: + push: + branches: + - main + pull_request: + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: worker-image-${{ github.ref }} + cancel-in-progress: true + +env: + IMAGE_NAME: docker.io/kalebbroo/runpod-serverless-aitoolkit + +jobs: + test: + name: Test worker + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v5 + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.12" + cache: pip + + - name: Install worker dependencies + run: python -m pip install --requirement requirements.txt + + - name: Run worker tests + run: | + python -m unittest discover -s tests -v + python -m py_compile handler.py tests/test_handler.py + + image: + name: Build worker image + needs: test + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v5 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v4 + + - name: Sign in to Docker Hub + if: github.event_name != 'pull_request' + uses: docker/login-action@v4 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Generate image metadata + id: metadata + uses: docker/metadata-action@v6 + with: + images: ${{ env.IMAGE_NAME }} + tags: | + type=sha,format=long,prefix=sha- + type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }} + + - name: Build and publish worker image + uses: docker/build-push-action@v7 + with: + context: . + file: ./Dockerfile + platforms: linux/amd64 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.metadata.outputs.tags }} + labels: ${{ steps.metadata.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + provenance: ${{ github.event_name != 'pull_request' && 'mode=max' || 'false' }} + sbom: ${{ github.event_name != 'pull_request' }} diff --git a/README.md b/README.md index 2a118a1..7e44f2f 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,24 @@ docker build --pull --build-arg AI_TOOLKIT_REVISION=be995185f598c83abb990a088e9f docker push your-registry/hartsy-ai-toolkit:be995185 ``` +## Automatic Docker Hub publishing + +The `Build and publish worker image` GitHub Actions workflow tests and builds every pull request. A push to `main`, or a manual workflow dispatch, publishes the Linux AMD64 image to: + +```text +docker.io/kalebbroo/runpod-serverless-aitoolkit:latest +docker.io/kalebbroo/runpod-serverless-aitoolkit:sha- +``` + +Configure these GitHub Actions repository secrets before merging the workflow: + +- `DOCKERHUB_USERNAME`: `kalebbroo` +- `DOCKERHUB_TOKEN`: a Docker Hub personal access token with Read & Write permission + +Create the `kalebbroo/runpod-serverless-aitoolkit` Docker Hub repository first. Do not store a Docker Hub password or token in the repository. Use the immutable `sha-` tag in the RunPod template; `latest` is a convenience tag for inspection and manual testing. + +The workflow publishes BuildKit provenance and an SBOM with release images and uses the GitHub Actions cache for subsequent builds. + Create a queue-based RunPod Serverless endpoint from that immutable image. Use one concurrent request per worker because `/dataset` and `/workspace/output` are intentionally reset for every request. Allocate enough container disk for the model cache plus dataset/output and choose a GPU configuration appropriate for the largest model families you enable. Hartsy sends a 24-hour execution policy and seven-day status TTL by default; the endpoint must permit those limits. Required worker environment: