From 8f181c80f840129ba2f6b3ea362c99411bd91ea6 Mon Sep 17 00:00:00 2001 From: Hunter Bown Date: Thu, 7 May 2026 15:16:23 -0500 Subject: [PATCH] feat(release): publish supported Docker image --- .github/workflows/release.yml | 38 +++++++++++++++++++++++++------ Dockerfile | 6 +++-- README.md | 9 ++++++++ docs/DOCKER.md | 42 ++++++++++++++++++++++++++--------- 4 files changed, 76 insertions(+), 19 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5bb28cea..c84ea768 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -139,10 +139,6 @@ jobs: docker: needs: build if: ${{ !cancelled() && needs.build.result == 'success' }} - # Docker/GHCR is experimental and not a supported release channel yet. - # Keep binary GitHub Releases publishable while the arm64 image build path - # is hardened separately. - continue-on-error: true runs-on: ubuntu-latest permissions: contents: read @@ -159,17 +155,24 @@ jobs: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Normalize image name + id: image + shell: bash + run: echo "name=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT" - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: | - ghcr.io/${{ github.repository }} + ${{ steps.image.outputs.name }} tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern=v{{major}} type=ref,event=tag + type=raw,value=${{ inputs.version }},enable=${{ github.event_name == 'workflow_dispatch' }} + type=raw,value=v${{ inputs.version }},enable=${{ github.event_name == 'workflow_dispatch' }} + type=raw,value=latest - name: Build and push uses: docker/build-push-action@v6 with: @@ -182,8 +185,8 @@ jobs: cache-to: type=gha,mode=max release: - needs: build - if: ${{ !cancelled() && needs.build.result == 'success' }} + needs: [build, docker] + if: ${{ !cancelled() && needs.build.result == 'success' && needs.docker.result == 'success' }} runs-on: ubuntu-latest permissions: contents: write @@ -205,8 +208,18 @@ jobs: printf '%s %s\n' "${hash}" "${base}" >> "${manifest}" done < <(find artifacts -type f ! -path 'artifacts/checksums/*' -print0 | sort -z) cat "${manifest}" + - name: Resolve release tag + id: release_tag + shell: bash + run: | + if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then + echo "tag=v${{ inputs.version }}" >> "$GITHUB_OUTPUT" + else + echo "tag=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT" + fi - uses: softprops/action-gh-release@v1 with: + tag_name: ${{ steps.release_tag.outputs.tag }} files: artifacts/*/* prerelease: false body: | @@ -220,6 +233,17 @@ jobs: The wrapper downloads both binaries from this Release and places them in the same directory. + ### Docker / GHCR + + ```bash + docker run --rm -it \ + -e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \ + -v ~/.deepseek:/home/deepseek/.deepseek \ + ghcr.io/hmbown/deepseek-tui:${{ steps.release_tag.outputs.tag }} + ``` + + The image ships the `deepseek` dispatcher and `deepseek-tui` runtime. The `latest` tag is also updated on release. + ### Cargo (Linux / macOS) ```bash diff --git a/Dockerfile b/Dockerfile index 79c386f5..89216529 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,6 +18,7 @@ ARG RUST_VERSION=1.88 # ── Stage 1: Build ──────────────────────────────────────────────────── FROM --platform=$BUILDPLATFORM rust:${RUST_VERSION}-slim-bookworm AS builder ARG TARGETPLATFORM +ARG TARGETARCH ARG BUILDPLATFORM RUN apt-get update && apt-get install -y --no-install-recommends \ @@ -40,8 +41,9 @@ COPY . . # Build both binaries for the target platform. --locked ensures # reproducible builds from the committed lockfile. -RUN --mount=type=cache,target=/build/target \ - --mount=type=cache,target=/usr/local/cargo/registry \ +RUN --mount=type=cache,id=deepseek-tui-target-${TARGETARCH},target=/build/target,sharing=locked \ + --mount=type=cache,id=deepseek-tui-cargo-registry-${TARGETARCH},target=/usr/local/cargo/registry,sharing=locked \ + --mount=type=cache,id=deepseek-tui-cargo-git-${TARGETARCH},target=/usr/local/cargo/git,sharing=locked \ cargo build --release --locked --target "$(cat /rust-target)" \ && mkdir -p /out \ && cp target/$(cat /rust-target)/release/deepseek /out/ \ diff --git a/README.md b/README.md index 21124356..9201fb4c 100644 --- a/README.md +++ b/README.md @@ -274,6 +274,15 @@ deepseek mcp-server # run dispatcher MCP stdio serv deepseek update # check for and apply binary updates ``` +Docker images are published to GHCR for release builds: + +```bash +docker run --rm -it \ + -e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \ + -v ~/.deepseek:/home/deepseek/.deepseek \ + ghcr.io/hmbown/deepseek-tui:latest +``` + ### Zed / ACP DeepSeek can run as a custom Agent Client Protocol server for editors that diff --git a/docs/DOCKER.md b/docs/DOCKER.md index 4cc9d2a3..5f51d225 100644 --- a/docs/DOCKER.md +++ b/docs/DOCKER.md @@ -1,11 +1,33 @@ # Docker -Docker support is currently a local-build/devcontainer path, not a supported -release channel. The release workflow may try an experimental GHCR publish, but -no public `ghcr.io/hmbown/deepseek-tui` image should be treated as available -until this page says so. +DeepSeek-TUI publishes a multi-arch Linux image to GitHub Container Registry +for each release. -## Local quick start +```bash +docker pull ghcr.io/hmbown/deepseek-tui:latest +``` + +## Quick start + +Run the published image with your existing config directory mounted: + +```bash +docker run --rm -it \ + -e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \ + -v ~/.deepseek:/home/deepseek/.deepseek \ + ghcr.io/hmbown/deepseek-tui:latest +``` + +Use a pinned release tag for reproducible installs: + +```bash +docker run --rm -it \ + -e DEEPSEEK_API_KEY="$DEEPSEEK_API_KEY" \ + -v ~/.deepseek:/home/deepseek/.deepseek \ + ghcr.io/hmbown/deepseek-tui:v0.8.18 +``` + +## Local build Build the image locally from a checkout: @@ -22,7 +44,8 @@ docker run --rm -it \ deepseek-tui ``` -Docker Hub publishing is not configured. +Docker Hub publishing is not configured; GHCR is the supported prebuilt image +registry. ## Environment variables @@ -50,7 +73,7 @@ When stdin is not a TTY, `deepseek` drops to the dispatcher's one-shot mode ```bash echo "Explain the Cargo.toml in structured English." | \ - docker run --rm -i -e DEEPSEEK_API_KEY deepseek-tui + docker run --rm -i -e DEEPSEEK_API_KEY ghcr.io/hmbown/deepseek-tui:latest ``` ## Building locally @@ -73,6 +96,5 @@ ready-to-use development environment. ## Release status -Docker image publishing is experimental and non-blocking for releases. The -supported distribution channels are npm, Cargo, Homebrew, GitHub Release -assets, and Scoop's independently maintained main-bucket manifest. +Docker image publishing is part of the release gate. The image is published to +GHCR for `linux/amd64` and `linux/arm64` with semver tags plus `latest`.