Skip to content

ci: multi-arch (linux/arm64) support for the Docker image - #36

Merged
HelgDemidov merged 3 commits into
mainfrom
feat/docker-arm64
Aug 22, 2026
Merged

ci: multi-arch (linux/arm64) support for the Docker image#36
HelgDemidov merged 3 commits into
mainfrom
feat/docker-arm64

Conversation

@HelgDemidov

Copy link
Copy Markdown
Owner

What & why

The Docker image (ghcr.io/helgdemidov/refigure) was linux/amd64-only,
an explicit non-goal in the original Docker distribution spec. Reversed
based on live-verified evidence, not assumption:

  • Market: DOCX/XLSX remain the dominant enterprise/institutional
    document-interchange format; Apple's iWork has asymmetric compatibility
    with Office (Office can't open .pages/.numbers at all), so Mac users
    sharing externally are forced through .docx/.xlsx regardless. macOS
    enterprise share is growing, and Microsoft brought native Office to
    macOS for enterprise in Jan 2025. PyPI/uvx/MCP-server already work
    natively on Apple Silicon (arm64 Python wheels) — Docker was the one
    format left depending on QEMU emulation for Apple Silicon.
  • Competitors: 2 of the project's 5 reference competitors
    (docling-serve, unstructured) already publish official multi-arch
    images including arm64; 3 of 5 publish no official image at all.
  • Feasibility: real end-to-end docker buildx build --platform linux/arm64 of the actual (unmodified) Dockerfile succeeded with
    zero dependencies falling back to a source build — every dependency
    (lxml, pypdfium2, pydantic-core, jiter, cryptography,
    pillow, cffi, rpds-py) resolved a real aarch64 wheel. The
    resulting image was smoke-tested under --platform linux/arm64:
    refigure --help, refigure-mcp --help, soffice --version all
    passed. GitHub-hosted ubuntu-24.04-arm runners are GA and free for
    public repos — CI builds arm64 natively, no QEMU anywhere in the
    pipeline.

Full spec (local-only, docs/ is gitignored):
docs/distribution/docker-arm64/docker-arm64-2026-08-22.md.

Changes

  • ci.yml: docker-build matrixed across linux/amd64 (ubuntu-latest)
    • linux/arm64 (ubuntu-24.04-arm) — same 4 existing smoke tests on
      both legs, unmodified logic. Note: this renames the job's check
      name on both legs (now platform-suffixed) — required_status_checks
      needs a matching update after merge (replace the old name, add the new
      arm64 leg), same precedent as the original docker-build/mcpb-build
      additions.
  • publish.yml: docker-publish split into a matrixed digest-push job
    (per platform, native runners) + a new docker-publish-merge job that
    combines both digests into one multi-arch manifest via docker buildx imagetools create, under the existing X.Y.Z/latest tags. Verifies
    the published manifest lists both platforms before finishing. The
    actual GHCR push path can only be fully verified live on the next real
    tagged release (same constraint the original job had).
  • README.md: Docker feature bullet + accordion body now mention the
    multi-arch manifest. No new commands for end users — docker pull
    resolves the right layer automatically, including on Apple Silicon.

Test plan

  • ruff check . / ruff format --check . / mypy refigure — clean
  • Full pytest --cov — 684 passed, 4 skipped, 99% coverage
  • .github/workflows/{ci,publish}.yml — YAML-validated, job
    dependency graph checked (publish → docker-publish → docker-publish-merge)
  • Real local docker buildx build --platform linux/arm64 of the
    unmodified Dockerfile — success, zero source-build fallbacks
  • Real smoke test of the built arm64 image (refigure --help,
    refigure-mcp --help, soffice --version) — all passed
  • Live verification of the actual multi-arch GHCR publish path
    (docker buildx imagetools create/inspect) — only possible on
    the next real tagged release, not before

After merge

required_status_checks needs updating (remove the old single
docker-build check name, add both platform-suffixed names) — same
process as prior distribution-format PRs, done post-merge once the new
check names exist on main.

🤖 Generated with Claude Code

HelgDemidov and others added 3 commits August 22, 2026 16:12
Native GitHub-hosted arm64 runner (ubuntu-24.04-arm, GA and free for
public repos), not QEMU — no emulation anywhere in this pipeline. Both
legs run the same 4 existing smoke tests unmodified.

Renames the job's check name (now suffixed with the platform on both
legs, including amd64) — required_status_checks needs a matching update
after merge, same as docker-build/mcpb-build's own precedent.

See docs/distribution/docker-arm64 spec.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Splits the single linux/amd64 build+push into 3 jobs:
- docker-publish (matrixed linux/amd64 + linux/arm64, native runners —
  ubuntu-24.04-arm for arm64, no QEMU) builds and pushes each platform
  by digest only, no final tag yet.
- docker-publish-merge combines both digests into one multi-arch
  manifest via `docker buildx imagetools create`, applying the real
  X.Y.Z + latest tags. Verifies the published manifest lists both
  platforms before finishing.

Digests cross the job boundary via upload/download-artifact — matrix-job
outputs don't reliably aggregate into a downstream job's needs.*.outputs,
this is docker/build-push-action's own documented pattern for this case.

End users see no change: `docker pull ghcr.io/helgdemidov/refigure:latest`
on Apple Silicon now resolves the arm64 layer automatically (one OCI
image index under the existing tags).

The actual GHCR push path (imagetools create/inspect) can only be fully
verified live on the next real tagged release — same constraint the
original docker-publish job had.

See docs/distribution/docker-arm64 spec.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Both the Features bullet and the Docker accordion body now note the
linux/amd64 + linux/arm64 multi-arch manifest — docker pull resolves
the right layer automatically, including on Apple Silicon, no new
commands for users.

See docs/distribution/docker-arm64 spec.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@HelgDemidov
HelgDemidov merged commit c9072e3 into main Aug 22, 2026
39 checks passed
@HelgDemidov
HelgDemidov deleted the feat/docker-arm64 branch August 22, 2026 15:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant