-
Notifications
You must be signed in to change notification settings - Fork 0
ci(docker): dual-publish nir-rs image to GHCR and Docker Hub #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
5475fd9
ci(docker): dual-publish image to GHCR and Docker Hub
rmems 1dfe67a
fix(docker): address review — tags, non-root, fixtures, slim image
rmems 19f3354
fix(docker): writable /src, no PR registry secrets, cancel races
rmems 207d72e
docs(docker): prefer concrete GHCR pull path in README
rmems b3d720a
fix(docker): codex — Main triggers, shared latest concurrency, GHCR p…
rmems 58ec8f0
fix(docker): accept Main ref; never cancel tag publishes
rmems 3f86a96
fix(docker): separate branch/tag publish concurrency groups
rmems 508f3e0
fix(docker): serialize all publishes for :latest without cancel
rmems 54b7c4f
fix(docker): queue multiple pending publishes (queue: max)
rmems 77d9d65
docs(changelog): fold Docker into 0.4.1 release notes
rmems File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| # Keep Docker context small and free of secrets / build junk. | ||
| .git | ||
| .github | ||
| target | ||
| **/target | ||
| fuzz/target | ||
| fuzz/corpus | ||
| fuzz/artifacts | ||
| .cursor | ||
| .devcontainer | ||
| *.md | ||
| !README.md | ||
| !CHANGELOG.md | ||
| !COMPATIBILITY.md | ||
| !TESTING.md | ||
| !LICENSE-* | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| REVIEW.md | ||
| cubic.yaml | ||
| qodana.yaml | ||
| scripts | ||
| .env | ||
| .env.* | ||
| **/.DS_Store |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,171 @@ | ||
| # Docker build + dual push (Docker Hub + GitHub Container Registry). | ||
| # Third-party Actions pinned to immutable commit SHAs. | ||
| # Local Buildx only (no Docker Build Cloud). | ||
| # | ||
| # PR: verify build only (contents: read; no registry secrets / packages: write). | ||
| # Upstream main: SHA + latest only (never overwrite :X.Y.Z). | ||
| # Upstream v* tag matching Cargo.toml: SHA + X.Y.Z + latest. | ||
| name: Docker | ||
|
|
||
| on: | ||
| push: | ||
| # REVIEW.md: workflows that change CI must keep Main + main targets. | ||
| branches: [main, Main] | ||
| tags: ["v*"] | ||
| pull_request: | ||
| branches: [main, Main] | ||
| types: [opened, synchronize, reopened] | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| docker-verify: | ||
| name: docker verify | ||
| runs-on: ubuntu-latest | ||
| if: github.event_name == 'pull_request' | ||
| concurrency: | ||
| group: docker-verify-${{ github.repository }}-${{ github.event.pull_request.number }} | ||
| cancel-in-progress: true | ||
| permissions: | ||
| contents: read | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| # No Docker Hub / GHCR login on PRs — never expose DOCKER_PAT to PR code. | ||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 | ||
|
|
||
| - name: Set image tags | ||
| id: image | ||
| run: | | ||
| set -euo pipefail | ||
| SHA="${{ github.sha }}" | ||
| echo "runtime_tag=nir-rs:pr-${SHA}" >> "$GITHUB_OUTPUT" | ||
|
|
||
| # Full Dockerfile build already runs cargo test in the builder stage. | ||
| - name: Build runtime image (load locally) | ||
| uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0 | ||
| with: | ||
| context: . | ||
| push: false | ||
| load: true | ||
| tags: ${{ steps.image.outputs.runtime_tag }} | ||
|
|
||
| - name: Smoke runtime image | ||
| run: | | ||
| set -euo pipefail | ||
| TAG="${{ steps.image.outputs.runtime_tag }}" | ||
| docker run --rm "${TAG}" rustc --version | ||
| docker run --rm "${TAG}" sh -c 'test -x /usr/local/bin/load_inspect_lif' | ||
| docker run --rm "${TAG}" sh -c 'pkg-config --exists hdf5' | ||
| # Default path uses fixtures under CARGO_MANIFEST_DIR=/src | ||
| docker run --rm "${TAG}" load_inspect_lif | ||
| # Runtime user can write target/ for agent cargo builds | ||
| docker run --rm "${TAG}" sh -c 'touch /src/.write-check && rm /src/.write-check' | ||
|
|
||
| docker-publish: | ||
| name: docker publish | ||
| runs-on: ubuntu-latest | ||
| if: > | ||
| github.repository == 'Limen-Neural/nir-rs' && | ||
| github.event_name == 'push' && | ||
| (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/Main' || startsWith(github.ref, 'refs/tags/v')) | ||
|
rmems marked this conversation as resolved.
|
||
| # One group for all :latest writers (main/Main + v* tags). Serializes pushes so | ||
| # branch and tag jobs cannot race on the mutable :latest tag. | ||
| # cancel-in-progress: false — never abort an in-flight publish (incl. immutable :X.Y.Z). | ||
| # queue: max — keep up to 100 pending runs (default is single: a later main push | ||
| # would replace a pending v* tag and skip the immutable image). | ||
| concurrency: | ||
| group: docker-publish-${{ github.repository }} | ||
|
cubic-dev-ai[bot] marked this conversation as resolved.
|
||
| cancel-in-progress: false | ||
| queue: max | ||
| permissions: | ||
| contents: read | ||
| packages: write | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| persist-credentials: false | ||
|
|
||
| - name: Log in to Docker Hub | ||
| uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 | ||
| with: | ||
| username: ${{ vars.DOCKER_USER }} | ||
| password: ${{ secrets.DOCKER_PAT }} | ||
|
|
||
| - name: Log in to GHCR | ||
| uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 | ||
|
|
||
| - name: Set image tags | ||
| id: image | ||
| env: | ||
| DOCKER_USER: ${{ vars.DOCKER_USER }} | ||
| REPO_OWNER: ${{ github.repository_owner }} | ||
| REF: ${{ github.ref }} | ||
| SHA: ${{ github.sha }} | ||
| run: | | ||
| set -euo pipefail | ||
| VER=$(grep -m1 '^version' Cargo.toml | sed -E 's/.*"([^"]+)".*/\1/') | ||
| if [ -z "${VER}" ] || ! printf '%s' "${VER}" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then | ||
| echo "::error::Failed to extract semver X.Y.Z from Cargo.toml (got: ${VER:-empty})" | ||
| exit 1 | ||
| fi | ||
|
|
||
| OWNER=$(printf '%s' "${REPO_OWNER}" | tr '[:upper:]' '[:lower:]') | ||
| HUB="${DOCKER_USER}/nir-rs" | ||
| GHCR="ghcr.io/${OWNER}/nir-rs" | ||
|
|
||
| if [ "${REF}" = "refs/heads/main" ] || [ "${REF}" = "refs/heads/Main" ]; then | ||
| TAGS="${HUB}:${SHA},${HUB}:latest,${GHCR}:${SHA},${GHCR}:latest" | ||
| elif [[ "${REF}" == refs/tags/v* ]]; then | ||
| TAG_NAME="${REF#refs/tags/}" | ||
| if [ "${TAG_NAME}" != "v${VER}" ]; then | ||
| echo "::error::Git tag ${TAG_NAME} does not match Cargo.toml version v${VER}" | ||
| exit 1 | ||
| fi | ||
| TAGS="${HUB}:${SHA},${HUB}:${VER},${HUB}:latest,${GHCR}:${SHA},${GHCR}:${VER},${GHCR}:latest" | ||
| else | ||
| echo "::error::Unexpected ref ${REF}" | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "tags=${TAGS}" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Build and push | ||
| uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0 | ||
| with: | ||
| context: . | ||
| push: true | ||
| tags: ${{ steps.image.outputs.tags }} | ||
|
|
||
| # First package creation is private by default; public pulls need public visibility. | ||
| - name: Ensure GHCR package is public | ||
| continue-on-error: true | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| set -euo pipefail | ||
| OWNER=$(printf '%s' "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') | ||
| # Org package API (works for org-owned containers). | ||
| if gh api --method PUT -H "Accept: application/vnd.github+json" "/orgs/${OWNER}/packages/container/nir-rs/visibility" -f visibility=public; then | ||
| echo "GHCR package set public (org API)" | ||
| exit 0 | ||
| fi | ||
| # User-owned fallback. | ||
| if gh api --method PUT -H "Accept: application/vnd.github+json" "/user/packages/container/nir-rs/visibility" -f visibility=public; then | ||
| echo "GHCR package set public (user API)" | ||
| exit 0 | ||
| fi | ||
| echo "::warning::Could not set GHCR visibility to public automatically; set ghcr.io/${OWNER}/nir-rs public in package settings." | ||
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| # syntax=docker/dockerfile:1 | ||
| # nir-rs — published image for GHCR + Docker Hub. | ||
| # | ||
| # Builder: cargo test --all-features + release example with system libhdf5. | ||
| # Runtime: Rust pin + libhdf5 + source (no target/) + example binary. | ||
| # WORKDIR stays /src so env!(CARGO_MANIFEST_DIR) from the builder still finds | ||
| # tests/fixtures. Non-root user owns /src so cargo can recreate target/. | ||
| # No Python (AGENTS.md). | ||
|
|
||
| ARG RUST_IMAGE=rust:1.97-bookworm | ||
|
|
||
| FROM ${RUST_IMAGE} AS builder | ||
|
|
||
| RUN apt-get update \ | ||
| && apt-get install -y --no-install-recommends \ | ||
| pkg-config \ | ||
| libhdf5-dev \ | ||
| build-essential \ | ||
| ca-certificates \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| WORKDIR /src | ||
| COPY . . | ||
|
|
||
| RUN rustup component add clippy rustfmt \ | ||
| && cargo test --all-features \ | ||
| && cargo build --release --example load_inspect_lif --features hdf5 \ | ||
| && cp target/release/examples/load_inspect_lif /tmp/load_inspect_lif \ | ||
| && rm -rf target | ||
|
|
||
| FROM ${RUST_IMAGE} | ||
|
|
||
| RUN apt-get update \ | ||
| && apt-get install -y --no-install-recommends \ | ||
| git \ | ||
| pkg-config \ | ||
| libhdf5-dev \ | ||
| build-essential \ | ||
| ca-certificates \ | ||
| curl \ | ||
| && rm -rf /var/lib/apt/lists/* \ | ||
| && rustup component add clippy rustfmt \ | ||
| && useradd --create-home --uid 10001 --shell /bin/bash nir | ||
|
|
||
| # Match builder path for CARGO_MANIFEST_DIR baked into the example binary. | ||
| # Own /src itself so the runtime user can recreate target/ for cargo build/test. | ||
| RUN mkdir -p /src && chown nir:nir /src | ||
| WORKDIR /src | ||
| COPY --from=builder --chown=nir:nir /src /src | ||
|
rmems marked this conversation as resolved.
cubic-dev-ai[bot] marked this conversation as resolved.
|
||
| COPY --from=builder /tmp/load_inspect_lif /usr/local/bin/load_inspect_lif | ||
| RUN chmod 755 /usr/local/bin/load_inspect_lif | ||
|
|
||
| USER nir | ||
| ENV CARGO_HOME=/home/nir/.cargo \ | ||
| CARGO_TERM_COLOR=always \ | ||
| PATH=/home/nir/.cargo/bin:/usr/local/cargo/bin:$PATH | ||
| # Pre-warm crate index for agent use; tolerate offline builders. | ||
| RUN cargo fetch || true | ||
|
|
||
| LABEL org.opencontainers.image.title="nir-rs" \ | ||
| org.opencontainers.image.description="Pure-Rust NIR graph + HDF5 I/O toolchain image" \ | ||
| org.opencontainers.image.source="https://github.com/Limen-Neural/nir-rs" \ | ||
| org.opencontainers.image.licenses="MIT OR Apache-2.0" | ||
|
|
||
| CMD ["rustc", "--version"] | ||
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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.