feat: package taskito-server as a multiarch distroless image - #610
Conversation
|
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 (2)
🔗 Linked repositories identifiedCodeRabbit considers these linked repositories for cross-repo context during reviews:
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThe PR adds a multi-architecture distroless ChangesServer image packaging
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant ReleaseTrigger
participant PublishWorkflow
participant DockerBuild
participant GHCR
participant GitHubRelease
ReleaseTrigger->>PublishWorkflow: start release or manual dispatch
PublishWorkflow->>DockerBuild: build amd64 and arm64 images
DockerBuild->>PublishWorkflow: return version and OCI label checks
PublishWorkflow->>GHCR: push architecture images and multi-architecture manifests
PublishWorkflow->>GitHubRelease: create server-vVERSION tag and release
Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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/ci-server-image.yml:
- Line 28: Update the actions/checkout step in the CI workflow to set
persist-credentials to false, preventing GitHub token credentials from remaining
on the runner while preserving the existing checkout behavior.
In @.github/workflows/publish-server.yml:
- Line 113: Add persist-credentials: false to the actions/checkout step in the
publish job, matching the existing checkout configuration in the manifest job
while preserving the current build, test, and conditional image-push steps.
- Line 44: Update the actions/checkout step to set persist-credentials to false,
ensuring subsequent git ls-remote access uses anonymous HTTPS credentials.
🪄 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: fe94006b-ea45-4456-bb77-4f7f03f266b8
📒 Files selected for processing (8)
.github/workflows/ci-server-image.yml.github/workflows/ci.yml.github/workflows/publish-server.ymlCHANGELOG.mdcrates/taskito-server/README.mddocker/scheduler.Dockerfiledocker/scheduler.Dockerfile.dockerignorescripts/version.mjs
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
ByteVeda/taskito(manual)
Closes #554. S8 of the executor-attach plan: the scheduler ships as one image
that carries no language runtime, so a Python, Node or Java app all deploy the
same tag alongside their own container.
The image
docker/scheduler.Dockerfile, three stages:node:22-alpinebuilds the dashboard SPA —crates/taskito-server/build.rsembeds it at compile time, so it has to exist before cargo runs.
rust:1-alpinecompiles-p taskito-server --features postgres,redis.Alpine is musl natively on both architectures, so nothing cross-compiles;
the binary is static because
libsqlite3-sys,pq-sysandopenssl-sysarealready bundled/vendored workspace-wide. Both backends are compiled in, so
one image covers every DSN.
gcr.io/distroless/static-debian12:nonrootcarries the binary and nothingelse. The build fails itself if
readelf -lfinds aPT_INTERP, since thatbase has no dynamic loader — a dynamic binary would fail at
docker runinstead of at build time.
Result: 11.2 MB content, 43.7 MB on disk. glibc and musl variants would be
indistinguishable here, so there is only one. BuildKit reads the
docker/scheduler.Dockerfile.dockerignoresitting next to the Dockerfile, whichkeeps the repo root free of a global ignore file.
Workflows
publish-server.yml(tagserver-v*, or dispatch with a dry-run) builds eacharchitecture on its own native runner — a Rust build under QEMU takes the better
part of an hour — smoke-tests
--versionand the OCI label againstversion.mjsbefore anything reaches the registry, pushes per-architecturetags, and merges them into a manifest list with
imagetools create. Pullsresolve
ghcr.io/byteveda/taskito-server:<version>and:latest.ci-server-image.ymlbuilds both architectures on PRs and asserts the binaryreports the declared version. Its path filter is deliberately not the shared
crates/**anchor: an engine-crate change that breaks the server already turnsthe Rust suite red, and what only this suite covers is the Dockerfile and the
SPA it embeds.
Version
The binary's
--versioncomes from[workspace.package]via Cargo. The OCIlabel comes from
--build-arg VERSION=$(node scripts/version.mjs --current),and
version.mjs --checknow fails ifARG VERSIONever holds a semverliteral, the same way it guards the other manifests. The publish workflow
cross-checks the resolved tag against
--currentbefore it builds.Verification
Built and run locally on amd64:
taskito-server 0.21.0, label0.21.0,actionlint clean,
version.mjs --checkgreen. arm64 was not executed locally —all three base images publish
linux/arm64and nothing in the buildcross-compiles, so the CI job on
ubuntu-24.04-armis the first real run.Summary by CodeRabbit
New Features
taskito-servercontainer image for AMD64 and ARM64.Documentation
Chores