Add deployment workflow for OpenHuman#3178
Conversation
This workflow handles deployment of the Rust core and React + Tauri desktop app, including validation, pre-deployment checks, builds for multiple platforms, and publishing release assets.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds a manual Deploy GitHub Actions workflow that validates inputs, resolves platform matrices, optionally runs pre-checks, builds Rust core and Tauri desktop artifacts per-target, optionally builds/pushes Docker images, aggregates checksums, creates a production release, and verifies completion. ChangesDeployment Pipeline
Sequence DiagramsequenceDiagram
participant User
participant GitHubActions
participant Validate
participant ResolveMatrix
participant PreChecks
participant BuildRust
participant BuildDesktop
participant BuildDocker
participant PublishRelease
participant Verify
User->>GitHubActions: workflow_dispatch(environment, platforms, skip_tests)
GitHubActions->>Validate: run validate job (version, shortSHA, releaseDate, platforms)
Validate->>ResolveMatrix: emit JSON includes & include_docker
ResolveMatrix->>GitHubActions: provide matrices and docker flag
GitHubActions->>PreChecks: run if skip_tests==false
GitHubActions->>BuildRust: run per-target Rust builds (matrix)
GitHubActions->>BuildDesktop: run per-target desktop builds (matrix)
ResolveMatrix->>BuildDocker: if include_docker == true
BuildDocker->>PublishRelease: push image and produce metadata
BuildRust->>PublishRelease: upload artifacts
BuildDesktop->>PublishRelease: upload artifacts (signed when prod)
PublishRelease->>Verify: create release (prod-only) and output checksums
Verify->>GitHubActions: summarize completion
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
.github/workflows/deploy.yml (1)
43-45: 💤 Low valueConsider scoping permissions to specific jobs.
Workflow-level
contents: writeandpackages: writeare broader than necessary. Onlypublish-releaseneedscontents: write(for GitHub Releases), and onlybuild-dockerneedspackages: write(for GHCR push). Moving these to job-level permissions follows the principle of least privilege.♻️ Suggested job-level permissions
-permissions: - contents: write - packages: write +permissions: + contents: readThen add to specific jobs:
# In build-docker: build-docker: permissions: packages: write ... # In publish-release: publish-release: permissions: contents: write ...🤖 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 @.github/workflows/deploy.yml around lines 43 - 45, The workflow currently sets broad repository-level permissions (permissions: contents: write and packages: write); move these to the specific jobs that require them by removing or narrowing the top-level permissions and adding job-level permissions blocks: add permissions: packages: write to the build-docker job and permissions: contents: write to the publish-release job (use the exact job names build-docker and publish-release and the exact permission keys packages and contents) so each job has least-privilege access only where needed.
🤖 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/deploy.yml:
- Around line 509-510: The publish-release job's if condition requires
build-rust-core, build-desktop, and build-docker to be exactly 'success', so
when build-docker (or others) is skipped the publish-release job never runs;
update the deploy.yml publish-release job's if expression (the one referencing
needs.build-rust-core.result, needs.build-desktop.result, and
needs.build-docker.result) to allow 'skipped' as well as 'success' (or
equivalently assert none of those needs have result == 'failure' or 'cancelled')
so publish-release runs when builds were successful or skipped rather than only
when all are 'success'.
- Around line 521-532: The workflow step named "Create checksum manifest" uses
the non-existent GitHub Actions command `::info::`; update the last log line to
use a valid command such as `::notice::Checksums generated` (or
`::warning::`/`::error::` as appropriate) so the message is interpreted as a
workflow command rather than literal text, and keep the existing fallback `cat
CHECKSUMS.txt || echo "(no artifacts found)"` unchanged; locate the step by the
step name "Create checksum manifest" and the CHECKSUMS.txt usage when making the
change.
- Around line 158-181: The job-level if expression using the matrix context is
invalid—update the build-rust-core job to remove or replace if:
contains(needs.validate.outputs.platforms, matrix.platform_filter) by either (A)
moving that contains(...) check into the individual steps (use step-level if
with matrix.platform_filter available) or (B) having the validate job emit a
JSON array of allowed platform_filters and use that output (e.g.,
fromJson(needs.validate.outputs.platforms)) to generate a strategy.matrix or to
drive a job-level decision without referencing matrix; apply the same change for
the build-desktop job if it currently uses matrix.* in a job-level if. Ensure
you reference the existing job name build-rust-core and the exact condition
contains(needs.validate.outputs.platforms, matrix.platform_filter) when making
the edits.
---
Nitpick comments:
In @.github/workflows/deploy.yml:
- Around line 43-45: The workflow currently sets broad repository-level
permissions (permissions: contents: write and packages: write); move these to
the specific jobs that require them by removing or narrowing the top-level
permissions and adding job-level permissions blocks: add permissions: packages:
write to the build-docker job and permissions: contents: write to the
publish-release job (use the exact job names build-docker and publish-release
and the exact permission keys packages and contents) so each job has
least-privilege access only where needed.
🪄 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: fe53c553-4459-45f6-9478-2398efc02bb2
📒 Files selected for processing (1)
.github/workflows/deploy.yml
|
hey not sure what's the point of this as we already have some stable deploy scripts. |
|
cause we already have https://github.com/tinyhumansai/openhuman/blob/main/.github/workflows/release-production.yml jfyi |
I'm just trying to improve with another patch, because the E2E bug should be treated as a test, and I'm contributing a backup patch in case the Release Production version has bugs or is no longer suitable. Thanks if you have any contributions. |
sanil-23
left a comment
There was a problem hiding this comment.
Thanks for putting this together, @manucian-official — it's a thorough, well-structured workflow and the multi-phase layout (validate -> pre-checks -> build -> docker -> release -> verify) reads cleanly.
My main concern is at the architecture level rather than the YAML.
Summary
| Area | Assessment |
|---|---|
| Structure / readability | Good — clear phases, sensible concurrency and permissions |
| Overlap with existing release infra | Major concern — see below |
| Correctness | A few real issues (Docker tags, job filters) |
| CI | Green |
Biggest issue: this overlaps the existing release pipeline
The repo already ships a fairly complete release/deploy setup:
release-staging.ymlandrelease-production.yml— built around a staging-tag promotion model (production builds the exact tag QA already exercised, rather than rebuildingmain@HEAD).release-packages.yml— GitHub Release creation.build-desktop.yml— Tauri builds with the project's established signing/notarization approach.- A
Dockerfileat the repo root.
This new deploy.yml reimplements all of that as a parallel pipeline that builds main@HEAD and creates v<version> releases directly. Two release systems that both cut GitHub releases and push images for the same version will collide and drift over time. Before this can land, it'd help to clarify the intent: is this meant to replace the existing release workflows, extend one of them, or is it solving a gap they don't cover? Right now it reads as a third, divergent path, which is a maintainability risk.
Other notes
- The matrix-context-in-job-
ifproblem CodeRabbit flagged onbuild-rust-core(L181) applies identically tobuild-desktop(L278) —matrix.settings.platform_filterisn't available in a job-levelif, so that platform filter won't work there either. - A couple of smaller correctness items are inline.
Happy to help reconcile this with the existing release-* workflows if you want to go that route.
|
I've just made some minor improvements and fixes as you mentioned. Thank you very much. I hope you'll continue to provide feedback so I can learn from it. |
### Context
Code review surfaced a cluster of bugs — some silent (the platform filter never actually filtered anything), some latent (hung runners, broken Docker tags). This PR addresses all of them.
---
### Changes
#### [F-1] CRITICAL — platform filter silently skipped every matrix leg
`matrix.*` context is only resolved inside **step-level** expressions. Using it in a job-level `if` — as the old code did:
```yaml
# Before — matrix context unavailable here, always evaluates to ""
if: contains(needs.validate.outputs.platforms, matrix.platform_filter)
```
means the condition always evaluates against an empty string, so the filter is a no-op: either all legs run or all are silently skipped depending on how GitHub evaluates the expression.
Fix: added a `resolve-matrix` job (Phase 0b) that converts the `deploy_platforms` input string into explicit JSON `include` arrays via a Python one-liner. The build jobs now consume `needs.resolve-matrix.outputs.rust_matrix` / `.desktop_matrix` / `.include_docker` — these are job outputs, which **are** available at job-level `if`.
```yaml
# After — uses job output, safe at job level
if: |
fromJSON(needs.resolve-matrix.outputs.rust_matrix).include[0] != null &&
(needs.pre-checks.result == 'success' || needs.pre-checks.result == 'skipped')
strategy:
matrix: ${{ fromJSON(needs.resolve-matrix.outputs.rust_matrix) }}
```
---
#### [F-2] `skip_tests=true` stalled all build jobs
When `skip_tests` is `true`, the `pre-checks` job is conditionally skipped. GitHub marks any downstream job that lists a skipped job in `needs` as **not run** unless the condition explicitly allows it. The build jobs had no such allowance.
Fix: all three build jobs (`build-rust-core`, `build-desktop`, `build-docker`) now include:
```yaml
if: |
... &&
(needs.pre-checks.result == 'success' || needs.pre-checks.result == 'skipped')
```
---
#### [F-3] `publish-release` blocked when Docker was excluded
The old condition:
```yaml
if: needs.build-rust-core.result == 'success' && needs.build-desktop.result == 'success' && needs.build-docker.result == 'success'
```
required `build-docker` to be `success`. If `docker` is absent from `deploy_platforms`, that job is `skipped`, not `success` — so `publish-release` would never run for partial-platform deployments.
Fix:
```yaml
if: |
always() &&
needs.build-rust-core.result != 'failure' &&
needs.build-desktop.result != 'failure' &&
needs.build-docker.result != 'failure'
```
---
#### [F-4] Docker `type=semver` tag broken on `workflow_dispatch`
`docker/metadata-action`'s `type=semver` pattern only resolves when the trigger is a **pushed git tag** (e.g. `refs/tags/v1.2.3`). On a `workflow_dispatch` trigger it produces an empty or no-op tag, meaning images were pushed without a version tag.
Fix: replaced with explicit raw tags that work on any trigger:
```yaml
tags: |
type=raw,value=${{ needs.validate.outputs.version }}
type=raw,value=${{ needs.validate.outputs.version }}-${{ needs.validate.outputs.short_sha }}
type=raw,value=${{ inputs.environment }}-${{ needs.validate.outputs.short_sha }}
type=ref,event=branch
```
---
#### [F-5] Non-existent action versions
- `actions/checkout@v5` — does not exist; latest stable is `v4`
- `softprops/action-gh-release@v3.0.0` — does not exist; latest is `v2`
Both would cause immediate workflow failures. Pinned to correct versions throughout.
---
#### [F-6] Rust toolchain version duplicated — drift risk
`env.RUST_VERSION: 1.83.0` was defined at the top level but the `dtolnay/rust-toolchain` action steps hard-coded `@1.93.0` inline (a different version), creating a mismatch and a maintenance footgun.
Fix: all toolchain steps now use:
```yaml
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.RUST_VERSION }}
```
One place to update when bumping the Rust version.
---
#### [F-7] No timeouts on long-running build jobs
A hung runner (network stall during CEF download, cargo registry timeout, etc.) would block the entire workflow with no automatic recovery.
Fix: added `timeout-minutes` to all three long-running build jobs:
| Job | Timeout |
|---|---|
| `build-rust-core` | 60 min |
| `build-desktop` | 90 min |
| `build-docker` | 45 min |
---
### Testing
- [ ] `workflow_dispatch` with all platforms — verify all 5 Rust + 5 desktop + docker legs run
- [ ] `workflow_dispatch` with `deploy_platforms: linux-x64` — verify only linux leg runs, `publish-release` still completes
- [ ] `workflow_dispatch` with `skip_tests: true` — verify build jobs proceed without waiting on `pre-checks`
- [ ] `workflow_dispatch` with `deploy_platforms: macos-arm64,macos-x64` (no docker) — verify `publish-release` runs despite `build-docker` being skipped
- [ ] Production run — verify Docker image is tagged with correct version string
ContextCode review surfaced a cluster of bugs — some silent (the platform filter never actually filtered anything), some latent (hung runners, broken Docker tags). This PR addresses all of them. Changes[F-1] CRITICAL — platform filter silently skipped every matrix leg
# Before — matrix context unavailable here, always evaluates to ""
if: contains(needs.validate.outputs.platforms, matrix.platform_filter)means the condition always evaluates against an empty string, so the filter is a no-op: either all legs run or all are silently skipped depending on how GitHub evaluates the expression. Fix: added a # After — uses job output, safe at job level
if: |
fromJSON(needs.resolve-matrix.outputs.rust_matrix).include[0] != null &&
(needs.pre-checks.result == 'success' || needs.pre-checks.result == 'skipped')
strategy:
matrix: ${{ fromJSON(needs.resolve-matrix.outputs.rust_matrix) }}[F-2]
|
| Job | Timeout |
|---|---|
build-rust-core |
60 min |
build-desktop |
90 min |
build-docker |
45 min |
Testing
-
workflow_dispatchwith all platforms — verify all 5 Rust + 5 desktop + docker legs run -
workflow_dispatchwithdeploy_platforms: linux-x64— verify only linux leg runs,publish-releasestill completes -
workflow_dispatchwithskip_tests: true— verify build jobs proceed without waiting onpre-checks -
workflow_dispatchwithdeploy_platforms: macos-arm64,macos-x64(no docker) — verifypublish-releaseruns despitebuild-dockerbeing skipped - Production run — verify Docker image is tagged with correct version string
|
check yall |
|
well done brother |
Summary
deploy.ymlGitHub Actions workflow for multi-platform deploymentProblem
OpenHuman requires a robust deployment automation system to:
Solution
Implemented a comprehensive 6-phase deployment workflow:
Key features:
Impact
Related
Summary by CodeRabbit