Docker #43
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: Docker | |
| # Triggers: | |
| # 1. workflow_run after Release completes successfully -- THE canonical | |
| # path. We download the wheel artifact that release.yml uploaded and | |
| # install from it inside the container, bypassing PyPI entirely. | |
| # 2. workflow_dispatch -- manual retries. | |
| # | |
| # The push-tag trigger was REMOVED in v0.5.0. When a v*.*.* tag is | |
| # pushed, GitHub fires release.yml AND docker.yml in parallel; the | |
| # docker.yml run starts immediately and the dist/ artifact doesn't | |
| # exist yet (release.yml hasn't finished building it), AND PyPI | |
| # doesn't have the new version yet either. Both paths in the | |
| # Dockerfile fail. The workflow_run path waits for release.yml to | |
| # fully complete, then downloads the wheel artifact, which is the | |
| # reliable path. | |
| on: | |
| workflow_run: | |
| workflows: ["Release"] | |
| types: [completed] | |
| workflow_dispatch: | |
| inputs: | |
| ref: | |
| description: "Git ref to build (defaults to the workflow's default branch)." | |
| required: false | |
| default: "" | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| actions: read | |
| concurrency: | |
| # Dedupe push-tag + workflow_run firings for the same tag. | |
| group: docker-${{ github.event.workflow_run.head_sha || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build-and-push: | |
| name: Build + push container to GHCR | |
| runs-on: ubuntu-latest | |
| # When triggered by workflow_run, only proceed if Release succeeded. | |
| # Other triggers (push tag, workflow_dispatch) always run. | |
| if: >- | |
| github.event_name != 'workflow_run' || | |
| github.event.workflow_run.conclusion == 'success' | |
| steps: | |
| - name: Resolve checkout ref | |
| id: ref | |
| run: | | |
| set -e | |
| case "${{ github.event_name }}" in | |
| workflow_dispatch) | |
| ref="${{ github.event.inputs.ref }}" | |
| ;; | |
| workflow_run) | |
| ref="${{ github.event.workflow_run.head_branch }}" | |
| ;; | |
| *) | |
| ref="${GITHUB_REF}" | |
| ;; | |
| esac | |
| if [ -z "$ref" ]; then ref="${GITHUB_REF}"; fi | |
| echo "ref=$ref" >> "$GITHUB_OUTPUT" | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ steps.ref.outputs.ref }} | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Derive image metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ghcr.io/valani9/vstack | |
| tags: | | |
| type=ref,event=tag | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=semver,pattern={{major}} | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| labels: | | |
| org.opencontainers.image.title=vstack | |
| org.opencontainers.image.description=Organizational behavior, practiced on AI agents. | |
| org.opencontainers.image.licenses=MIT | |
| org.opencontainers.image.source=https://github.com/valani9/vstack | |
| org.opencontainers.image.url=https://pypi.org/project/valanistack/ | |
| org.opencontainers.image.authors=Ilhan Valani <valani@bu.edu> | |
| - name: Compute build argument VSTACK_VERSION | |
| id: ver | |
| run: | | |
| set -e | |
| ref="${{ steps.ref.outputs.ref }}" | |
| ref="${ref##*/}" | |
| case "$ref" in | |
| v[0-9]*) | |
| echo "version=${ref#v}" >> "$GITHUB_OUTPUT" | |
| ;; | |
| *) | |
| echo "version=" >> "$GITHUB_OUTPUT" | |
| ;; | |
| esac | |
| # On workflow_run, download the wheel that release.yml just built | |
| # and uploaded as an artifact (artifact name set in release.yml). | |
| # Skips the PyPI CDN race entirely. | |
| - name: Download wheel artifact from the triggering Release run | |
| if: github.event_name == 'workflow_run' | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: release-dist | |
| path: dist/ | |
| run-id: ${{ github.event.workflow_run.id }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Ensure dist/ exists for the docker build context | |
| run: | | |
| set -e | |
| mkdir -p dist | |
| ls -la dist/ || true | |
| - name: Build + push image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| build-args: | | |
| VSTACK_VERSION=${{ steps.ver.outputs.version }} | |
| provenance: true | |
| sbom: true |