Skip to content

ci(release): ship Linux openhuman-core tarballs and push GHCR image - #1442

Merged
senamakel merged 3 commits into
tinyhumansai:mainfrom
senamakel:issue/1439-production-release-workflow-should-ship
May 9, 2026
Merged

senamakel merged 3 commits into
tinyhumansai:mainfrom
senamakel:issue/1439-production-release-workflow-should-ship

Conversation

@senamakel

@senamakel senamakel commented May 9, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Production build-docker now actually builds and pushes ghcr.io/tinyhumansai/openhuman-core (:latest, :v<version>, :<version>) instead of just logging into GHCR and exiting.
  • New build-cli-linux matrix builds standalone openhuman-core for x86_64-unknown-linux-gnu and aarch64-unknown-linux-gnu and attaches openhuman-core-<version>-<target>.tar.gz (+ .sha256) to the GitHub Release.
  • publish-release asset validation now requires both Linux tarballs alongside the Tauri installers; cleanup-failed-release deletes the pushed GHCR image versions if a downstream phase fails.
  • Mirror non-pushing build-docker job in release-staging.yml so a Dockerfile regression fails staging before promotion.
  • Updated stale staging comment about future GHCR work and pointed cloud-deploy.md at the actually-published image plus a no-Docker tarball install path.

Problem

release-production.yml invoked build-desktop.yml with build_sidecar: false, so the optional Linux openhuman-core artifact path never ran on the production cut, and build-docker stopped after docker login — no docker build / docker push step. Self-hosters following gitbooks/features/cloud-deploy.md, anyone automating headless Linux servers, and release hygiene (one tag = all shipping surfaces) all paid the cost.

Solution

  • GHCR: complete build-docker with docker/build-push-action (linux/amd64), three tags per release, OCI labels (source, revision, version, title), GHA-scoped buildx cache, and a post-push docker pull/docker image inspect smoke step. Stayed single-arch — QEMU emulation triples Rust build time; arm64 users pull the standalone tarball or build from source. Documented as a follow-up.
  • Linux CLI tarballs: new build-cli-linux matrix using ubuntu-22.04 (x86_64) and ubuntu-24.04-arm (aarch64). Reuses the existing scripts/release/package-cli-tarball.sh (the same script release-packages.yml already drives), with the same Sentry DSN guard, OPENHUMAN_BUILD_SHA (12-char) baking, and OPENHUMAN_APP_ENV=production.
  • Wiring: added both jobs to publish-release.needs + if. Asset validation appends openhuman-core-.*-x86_64-unknown-linux-gnu.tar.gz and ...-aarch64-...tar.gz. cleanup-failed-release walks the freshly pushed :v<version> and :<version> GHCR tags and deletes their package versions (:latest is left alone — clobbering the moving tag would orphan downstream pulls of the previous release).
  • Staging parity: added a build-docker job to release-staging.yml that mirrors the production build but with push: false, load: true. deploy-smoke.yml already covers Dockerfile regressions on PRs that touch core sources; this is the equivalent gate at the staging-tag boundary so a green staging cut means the next prod promotion's GHCR push will succeed.
  • Docs: rewrote the staging comment in release-staging.yml (no longer claims GHCR is future work). Cloud-deploy doc now leads with docker pull ghcr.io/tinyhumansai/openhuman-core:latest and adds a no-Docker tarball install snippet.

Submission Checklist

  • N/A: pure CI YAML + markdown change. The Verify pushed image is pullable step plus publish-release asset validation enforce both new outputs at run time, and the staging build-docker job exercises the Dockerfile build path on every staging cut.
  • N/A: pure YAML + markdown change, no executable source under app/src or src/ modified. Issue Production release workflow should ship Linux openhuman-core binaries and a real GHCR Docker image #1439 acceptance criteria explicitly exempts pure YAML from the diff-coverage gate.
  • N/A: behaviour-only release-pipeline change — no feature rows added, removed, or renamed.
  • N/A: no feature IDs from the coverage matrix are touched by this PR.
  • N/A: no new external network dependencies. docker/build-push-action and docker/login-action are already used in deploy-smoke.yml; actions/checkout, Swatinem/rust-cache, and dtolnay/rust-toolchain mirror what release-packages.yml already pins.
  • N/A in this PR: will sweep docs/RELEASE-MANUAL-SMOKE.md once the next prod cut produces real GHCR + tarball artifacts to verify against.
  • Linked issue closed via Closes #1439 in the ## Related section.

Impact

  • Runtime: desktop bundles unchanged. New surfaces are headless: GHCR image + Linux core tarballs. arm64 hosts that previously had nothing now have a shipped tarball.
  • Performance: build-cli-linux adds ~one cargo release build per arch in parallel. build-docker adds the cached image build. No effect on build-desktop runtime.
  • Security: GHCR push uses the workflow's existing packages: write permission and secrets.GITHUB_TOKEN; OCI labels expose the build SHA + version for provenance. Sentry DSN validation matches the pattern already used by release-packages.yml.
  • Migration: tagged :latest will start moving on the next prod cut. Compose users who pinned to a built-locally image are unaffected; those who switch to image: ghcr.io/tinyhumansai/openhuman-core:latest (now documented) get the published bits.

Related


AI Authored PR Metadata (required for Codex/Linear PRs)

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: issue/1439-production-release-workflow-should-ship
  • Commit SHA: f65978f

Validation Run

  • N/A: pure YAML / markdown change — pnpm --filter openhuman-app format:check not affected.
  • N/A: pnpm typecheck — no TypeScript modified.
  • N/A: focused tests — no executable source modified.
  • N/A: Rust fmt/check — no Rust touched.
  • N/A: Tauri fmt/check — no Tauri code touched.

Validation Blocked

  • command: N/A
  • error: N/A
  • impact: N/A

Behavior Changes

  • Intended behavior change: production releases now actually publish a GHCR image and Linux openhuman-core tarballs in addition to Tauri desktop installers; staging cuts now also exercise the Dockerfile build path (without pushing).
  • User-visible effect: docker pull ghcr.io/tinyhumansai/openhuman-core:vX.Y.Z works; release pages list openhuman-core-<version>-{x86_64,aarch64}-unknown-linux-gnu.tar.gz.

Parity Contract

  • Legacy behavior preserved: desktop matrix invocation is unchanged (build_sidecar stays false); existing macOS / Windows / Linux .deb outputs and latest.json validation are untouched. release-packages.yml is left disabled — its build-cli-linux-arm64 job is the model the new matrix mirrors but does not duplicate.
  • Guard/fallback/dispatch parity checks: publish-release still requires every existing installer pattern; the two new patterns are additive. cleanup-failed-release retains its existing tag/release deletion and only refines the GHCR cleanup that was previously dead code.

Duplicate / Superseded PR Handling

  • Duplicate PR(s): none known
  • Canonical PR: this PR
  • Resolution: N/A

Production release-production.yml previously left two surfaces unshipped:

- build-docker logged into GHCR but had no docker build / push step, so
  ghcr.io/tinyhumansai/openhuman-core was never published per release.
- build-desktop ran with build_sidecar: false, so headless Linux operators
  had no openhuman-core CLI artifact on the GitHub Release.

This commit:

- Completes build-docker with docker/build-push-action, pushes
  :latest, :v<version>, :<version> tags to GHCR (linux/amd64), and
  verifies the pushed image is pullable.
- Adds build-cli-linux matrix (x86_64 + aarch64 ubuntu runners) that
  reuses scripts/release/package-cli-tarball.sh to attach
  openhuman-core-<version>-<target>.tar.gz + .sha256 to the GitHub
  Release.
- Wires both jobs into publish-release (asset validation now requires
  the two Linux tarballs) and cleanup-failed-release (deletes the
  pushed GHCR image versions if a downstream phase fails).
- Updates the stale staging comment about future GHCR work and points
  cloud-deploy.md at the actually-published image plus the new
  headless-tarball install path.

Closes tinyhumansai#1439
@senamakel
senamakel requested a review from a team May 9, 2026 22:55
@coderabbitai

coderabbitai Bot commented May 9, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Production release pipeline now explicitly orchestrates Docker image publishing to GHCR with multi-tag support (:latest, :v<version>, :<version>), validates Linux CLI tarball assets for both architectures, updates failed-release cleanup to target published Docker tags, and provides deployment documentation for Docker Compose and headless Linux installation paths.

Changes

Production Release with Docker Publishing and Linux CLI Distribution

Layer / File(s) Summary
Workflow Structure and Job Dependencies
.github/workflows/release-production.yml
Documented job dependency graph now explicitly models build-cli-linux, build-docker, and build-desktop as parallel prerequisites for publish-updater-manifest and publish-release.
Docker Image Publishing Implementation
.github/workflows/release-production.yml
Docker publishing step computes multi-tag string (:latest, :v<version>, :<version>), builds and pushes image with all tags, and verifies image is pullable post-push.
Release Asset Validation
.github/workflows/release-production.yml
publish-release job now depends on build-cli-linux success and validates that Linux CLI tarballs exist for both x86_64-unknown-linux-gnu and aarch64-unknown-linux-gnu architectures.
Failed Release Cleanup Logic
.github/workflows/release-production.yml
cleanup-failed-release job now depends on build-docker, build-cli-linux, and publish-updater-manifest outcomes, and replaces staging Docker tag deletion with logic to delete published production Docker tags (:v<version> and :<version>) while preserving :latest.
Staging Workflow Alignment
.github/workflows/release-staging.yml
release-staging.yml comments expanded to clarify that standalone openhuman-core CLI is production-only, staging does not publish CLI surfaces, and build_sidecar: false is the staging default.
Deployment Documentation
gitbooks/features/cloud-deploy.md
cloud-deploy.md expanded with GHCR image pulling guidance (latest, release tag, SemVer variants), docker run example with environment variables and persistent volume, and new headless CLI installation section with architecture detection, tarball download/install, and systemd service setup.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • tinyhumansai/openhuman#175: Both PRs modify the Linux CLI tarball packaging path; main PR adds/depends on a build-cli-linux job and tarball validation while the retrieved PR extracts/introduces scripts like package-cli-tarball.sh.
  • tinyhumansai/openhuman#1094: Both PRs modify release-production.yml and release-staging.yml to implement overlapping CI release flow changes (splitting staging vs production, tag handling, and Docker/release job wiring).
  • tinyhumansai/openhuman#1066: Both PRs modify release-staging.yml to adjust staging behavior and CI artifact configuration, so they share workflow governance overlap.

Poem

🐰 With Docker tags and Linux tarballs in hand,
The release pipeline now spans every land,
From GHCR's vault to /usr/local/bin,
Production deployments, let the joy begin!
A headless hop forward, no desktop required—
Self-hosters rejoice, the artifacts they desired! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title directly summarizes the main changes: shipping Linux openhuman-core tarballs and pushing a GHCR image, which are the primary objectives of this PR.
Linked Issues check ✅ Passed All coding objectives from issue #1439 are met: Linux CLI tarballs for x86_64/aarch64 are produced and attached to releases; build-docker builds and pushes versioned GHCR images with documented tags; staging comments updated for consistency; publish-release requires the new Linux artifacts; and cleanup-failed-release removes published image versions.
Out of Scope Changes check ✅ Passed All changes are directly related to the PR objectives: workflow modifications for Linux builds and Docker publishing, staging consistency updates, and documentation updates for the new deployment paths (GHCR image and tarball installation).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Mirror the production `build-docker` job in `release-staging.yml` but
with `push: false`. `deploy-smoke.yml` already exercises the Dockerfile
on PRs that touch core sources; this adds the equivalent gate at the
staging-tag boundary so a green staging cut means the next prod
promotion's GHCR push will succeed too. No `:staging-*` GHCR tag
pollution.

Refs tinyhumansai#1439

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
gitbooks/features/cloud-deploy.md (1)

161-176: ⚡ Quick win

Document checksum verification before extracting the tarball.

This new install path pipes a release artifact straight into tar, even though the release workflow now publishes checksum companions for these Linux artifacts. Please show a sha256sum -c step before installation.

Safer example
BASE="openhuman-core-${VERSION}-${TARGET}.tar.gz"
CHECKSUM="${BASE}.sha256" # adjust if the uploaded checksum file uses a different name

curl -fsSLO "https://github.com/tinyhumansai/openhuman/releases/download/v${VERSION}/${BASE}"
curl -fsSLO "https://github.com/tinyhumansai/openhuman/releases/download/v${VERSION}/${CHECKSUM}"
sha256sum -c "${CHECKSUM}"
sudo tar -xz -C /usr/local/bin -f "${BASE}"
openhuman-core --version
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gitbooks/features/cloud-deploy.md` around lines 161 - 176, Replace the direct
curl | tar pipeline with a two-step download-and-verify flow: download the
release tarball and its checksum companion (use the same VERSION and TARGET
variables from the snippet), run sha256sum -c against the downloaded checksum
file to verify integrity, and only if verification succeeds run tar -xz -C
/usr/local/bin -f "<tarball>"; keep the ARCH/TARGET detection and the final
openhuman-core --version invocation unchanged so the flow remains ARCH/TARGET ->
download .tar.gz and .sha256 -> sha256sum -c -> tar -xzf -> openhuman-core
--version.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release-production.yml:
- Around line 568-572: The current release asset validation only allows the
Linux CLI tarballs (the regexes
/^openhuman-core-.*-x86_64-unknown-linux-gnu\.tar\.gz$/ and
/^openhuman-core-.*-aarch64-unknown-linux-gnu\.tar\.gz$/) but does not require
their checksum companions; update the validation to also require the checksum
asset patterns (for example add regexes matching the checksum files such as
/^openhuman-core-.*-x86_64-unknown-linux-gnu\.tar\.gz\.sha256$/ and
/^openhuman-core-.*-aarch64-unknown-linux-gnu\.tar\.gz\.sha256$/) and include
them in the same allowed/required assets list or gate that block so the release
cannot pass without those checksum artifacts.
- Around line 389-420: The workflow currently emits and pushes the mutable
:latest tag during the build, which can point to an unreleased image; change the
image-tags step (id: image-tags) to omit emitting "${base}:latest" so tags only
include "${base}:${TAG}" and "${base}:${VERSION}", and keep the
docker/build-push-action@v6 step using those immutable tags; then add a new
post-release step (run after the publish-release job succeeds) that
retags/pushes "${base}:latest" to GHCR so :latest is only applied after a
successful publish. Also update the publish-release job's asset validation
patterns to require the Linux tarballs and their checksum files by adding the
corresponding "*.tar.gz" and "*.sha256" patterns to the required assets list.

---

Nitpick comments:
In `@gitbooks/features/cloud-deploy.md`:
- Around line 161-176: Replace the direct curl | tar pipeline with a two-step
download-and-verify flow: download the release tarball and its checksum
companion (use the same VERSION and TARGET variables from the snippet), run
sha256sum -c against the downloaded checksum file to verify integrity, and only
if verification succeeds run tar -xz -C /usr/local/bin -f "<tarball>"; keep the
ARCH/TARGET detection and the final openhuman-core --version invocation
unchanged so the flow remains ARCH/TARGET -> download .tar.gz and .sha256 ->
sha256sum -c -> tar -xzf -> openhuman-core --version.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e530cef2-6e4e-402e-9fc4-c9149e148340

📥 Commits

Reviewing files that changed from the base of the PR and between 97089a6 and decbead.

📒 Files selected for processing (3)
  • .github/workflows/release-production.yml
  • .github/workflows/release-staging.yml
  • gitbooks/features/cloud-deploy.md

Comment thread .github/workflows/release-production.yml
Comment thread .github/workflows/release-production.yml
… assets

CodeRabbit review on PR tinyhumansai#1442:

- Move `:latest` push out of `build-docker` and into a new
  `tag-docker-latest` job that runs after `publish-release` succeeds.
  `build-docker` now only pushes immutable `:v<version>` / `:<version>`
  tags. If a downstream phase (build-cli-linux, publish-updater-manifest,
  asset-validation) fails, `cleanup-failed-release` deletes the tagged
  image versions and `:latest` is never moved — previously, `:latest`
  could point at a build whose release got rolled back.
- Add the `.tar.gz.sha256` checksum companions to the
  `publish-release` asset validation. `package-cli-tarball.sh` already
  uploads them; gating on them prevents a partial release without the
  integrity files.

Refs tinyhumansai#1439
@senamakel

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 9, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@senamakel
senamakel merged commit 1d28f2c into tinyhumansai:main May 9, 2026
18 of 19 checks passed
AusAgentSmith pushed a commit to AusAgentSmith/openhuman that referenced this pull request May 23, 2026
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.

Production release workflow should ship Linux openhuman-core binaries and a real GHCR Docker image

1 participant