Repository navigation
Make apify push work for monorepo Actors that set dockerContextDir #595
Description
Problem
apify push uploads the files under the Actor folder (the cwd or --dir), so that folder is the root the platform builds from. Both Actors of apify/actor-monorepo-example set "dockerContextDir": "../../.." with dockerfile and input under ../../../shared/, so:
- From the Actor folder, the build fails with
Actor context path "../../.." is outside of Actor root directory!(exit code 1). - From the repository root, the push stops with
A valid Actor could not be found in the current directory. Please make sure you are in the correct directory.(exit code 4). - On a version built from a Git repository (the documented route),
--forcereplaces the Git source with that broken upload.
apify/push-actor-action only runs apify push in working-directory, so it inherits this. The local Actor runtime branch (#1496) resolves dockerContextDir but refuses the Apify platform (exit 255).
What we want
apify push from a monorepo Actor folder deploys that Actor, honoring dockerContextDir as the platform does. Push stays single-Actor; the Git repository is the upload root.
Stage 1, on master, no platform change:
- The branch's
resolveDockerContext,getContextFilePaths, andreadGitProvenanceland onmasterassrc/lib/docker-context.ts; push runs the resolver right after readingactor.json, before any Actor read or write. - A
dockerContextDirthat is not a string, does not exist, does not contain the Actor folder, or lies outside the Git repository exits 5 (InvalidActorJson) with the branch's message (the branch checks existence only inside Git). - A context above the Actor folder exits 255 (
NotImplemented) with the branch's message minus its runtime clause. - A context at or below the Actor folder (
"..",".","../src") is an ordinary push; the branch returnsinvalidbelow the folder, which the platform accepts.
Stage 2, once SOURCE_FILES and TARBALL versions accept actorPath (the platform field sub-issue (apify/apify-core#31473)):
- The push uploads the Git repository root with
actorPathas that sub-issue defines it (POSIX, relative to that root, never empty); both example Actors build. - Under 3 MB (
MAX_MULTIFILE_BYTES) the version isSOURCE_FILESwith repository-relative names; otherwise the existing zip upload andTARBALLwith thetarballUrl(signed when the store has a signing key). - In context mode, push runs the
actor.jsonpath check of the path validation sub-issue (Validateactor.jsonpaths before push #1500) with the upload root;dockerfilemust also lie inside the Docker context. Exit 5 before any upload. - A 400 naming
actorPath(a platform without the field) maps to the stage 1 message and exit 255; a just-created Actor is deleted.--jsonkeeps its envelope and a clean stdout.
Design notes
- The upload is what a Git clone has, as on disk: tracked plus untracked-not-ignored files, symlinks kept, sibling Actors included, uncommitted changes uploaded with a warning, no
.actorignore. Outside Git, the Docker context root is the upload root and the ordinary file list (with.actorignore) applies. - A repository upload can exceed 3 MB; the zip goes to the OS temp directory, not
temp_file.zipinprocess.cwd(). The newer-changes check scans the upload root and, in context mode, also runs on the zip path; the Git-source prompt and--forceare unchanged. - The platform's root
.actor/actor.jsonreaders (namerewrite, Standby auto-enable) look underactorPathonce the platform field sub-issue ships; the CLI already setsactorStandby. - Stage 1 lands first; the path validation helper hooks in after the resolver.
Out of scope
- Choosing which Actors to push (
--all, a picker): the selection sub-issue (apify push: select which Actors to push in a repository with several #1499); a root push keeps exiting 4. - The
actorPathfield in the API and the build: the platform field sub-issue. apify import(apify import: turn an existing repository into an Actor #1452),apify create --into(apify create assumes a greenfield standalone repo — no monorepo or existing-repo path #1425),apify run, changes toapify/push-actor-action, and tar.gz uploads (the platform accepts zip only).
How it's tested
test/local/lib/docker-context.test.ts(new): the resolver cases above, a missing context outside Git,/separators on Windows.test/local/lib/docker-context-files.test.ts(new, modeled onutils-gitignore-fallback.test.ts): the file rules above, including the no-Git fallback (vi.mock('node:child_process')).test/local/commands/push-monorepo.test.ts(new, from the branch's file, mocked client as inpush-git-source.test.ts): every checklist item and the 400 rollback.test/api/commands/push.test.ts: one[api]case pushing a two-Actor fixture like the example (needsTEST_USER_TOKENand the platform change).pnpm run update-docsregeneratesdocs/reference.md.
Links
- Epic: apify/apify-core#28685
- Local Actor runtime branch: feat: Add local Actor runtime (
apify runtime) #1496 (monorepo push merged by feat(runtime): push monorepo Actors to the local Actor runtime #1470) - Failure report: How do you run these actors locally? actor-monorepo-example#3; duplicate: Allow modifying the actor root path #277
- Docs: https://docs.apify.com/platform/actors/development/deployment/source-types
- CI action: https://github.com/apify/push-actor-action
Activity
patrikbraborec commentedon Jul 21, 2025
I talked about it with @JJetmar, and here is the description of the actual problem:
apify-clipush doesn't support monorepo structures because it only processes the current directory and ignores thedockerContextDirpath specified in actor.json.Solution could be to correctly respect
dockerContextDirinactor.jsonfor proper build context.cc. @vladfrangu, @B4nan.
patrikbraborec commentedon Jul 23, 2025
For the context, the current solution is that they push to the Git repository and build it in the Console with a Source set to Git.
JJetmar commentedon Dec 26, 2025
This is still being requested by the devs in apify/actor-monorepo-example#3
[-]Support usage of `apify push` with monorepo projects[/-][+]Make `apify push` work for monorepo Actors that set `dockerContextDir`[/+]DaveHanns commentedon Oct 27, 2026
This work is now tracked in two smaller issues:
apify push: refuse monorepo Actors before any write #1524:apify pushrefuses monorepo Actors before any write. Implemented in feat: detectdockerContextDirinapify pushand refuse monorepo Actors before any write #1502.apify push: upload monorepo Actors with the repository root andactorPath#1525:apify pushuploads monorepo Actors with the repository root andactorPath. Implemented in feat: push monorepo Actors by uploading the repository root withactorPath#1505, and needs the platform field from apify/apify-core#31473.