Repository navigation
Validate actor.json paths before push #1500
Description
Problem
apify push reads .actor/actor.json with plain JSON.parse and checks none of its path fields. The platform resolves dockerfile, readme, changelog, and every string-valued schema reference (input, output, webServerSchema, storages.*) relative to .actor/, and each must stay inside the uploaded source. The CLI resolves the schema references it reads that way (src/lib/input_schema.ts) and never reads the other three.
- A wrong
dockerfile,readme, orchangelogpath builds anyway: the worker logs the miss only internally, falls back to.actor/Dockerfile,Dockerfile, then its built-in default (Dockerfile not found, using the default one.), and the build goes green with the wrong image or README. A missing schema file fails the build (Schema property "input": File "..." does not exist!). - A path that leaves the uploaded folder fails only after the upload:
File: "<path>" is outside of Actor root directory!for a schema reference. Every push from an Actor folder ofapify/actor-monorepo-exampleends with the context error first;dockerContextDiritself is validated by the resolver of the push sub-issue (Makeapify pushwork for monorepo Actors that setdockerContextDir#595, stage 1), and this helper covers the file fields.
What we want
A CLI pre-flight that applies the worker's path rules before any Actor write. It needs no platform change.
- After reading the config and before the Actor is looked up or created,
apify pushchecks every file-path field of.actor/actor.json: relative to.actor/, not absolute, inside the upload root after symlinks are resolved, existing, and among the files push uploads (a CLI-only rule that catches a Dockerfile excluded by.gitignoreor.actorignore). The name matches case-insensitively fordockerfile,readme, andchangelog, as the worker finds those by directory listing, and exactly otherwise. Object-valued schema fields are skipped. - A failing check names the field, its value, and the resolved path, and exits with
CommandExitCodes.InvalidActorJson(5). A validdockerContextDirabove the upload root keeps the exit 255 (NotImplemented) and the stage 1 message of the push sub-issue (Makeapify pushwork for monorepo Actors that setdockerContextDir#595) until its stage 2 ships. - The check is one helper,
src/lib/actor-paths.ts, with the upload root as a parameter: push passes the Actor folder today; monorepo push (Makeapify pushwork for monorepo Actors that setdockerContextDir#595) passes its upload root (the Git repository root, or the Docker context root outside Git) and additionally requiresdockerfileinside the Docker context.
Design notes
The local Actor runtime branch (#1496) already calls resolveDockerContext in push.ts right after the config read: exit 5 for a dockerContextDir that is not a string, does not contain the Actor, or is missing or outside the Git repository; exit 255 against the platform for a valid context above the Actor folder. Stage 1 of the push sub-issue lifts that resolver to master as src/lib/docker-context.ts, and master is merged into actor-runtime afterward (never rebased); this helper lands after it and hooks in right after the resolver.
The ACTOR_PATH_IN_DOCKER_CONTEXT build arg has no documented value for an Actor at the context root: the worker computes path.relative(buildContextDir, actorSourcePath), which is "", the production value since the arg was introduced, while its unit tests set "." by hand. The value stays ""; the platform field sub-issue (apify-core) pins it in a worker test.
The worker only warns internally for a missing user-specified dockerfile, readme, or changelog and falls back; its code carries a TODO that calls the error a breaking change. That is why the check runs in the CLI.
Out of scope
- Uploading the Docker context and honoring
dockerContextDirin push (Makeapify pushwork for monorepo Actors that setdockerContextDir#595) - A platform field naming the Actor folder for pushed sources, and the build arg contract with it
- A platform-side failure for a missing
dockerfile,readme, orchangelog(apify-worker) - Validating schema contents (
apify validate-schema), and docs changes (the docs sub-issue (Monorepo docs: fix Docker context, build arg, andactor.jsonpath wording apify-docs#3082))
How it's tested
- Unit, new
test/local/lib/actor-paths.test.ts:./xand../xinside the root pass;../../x,/x, a missing file, a directory for a file field, and a file excluded by.actorignorefail; a wrong-casedockerfilepasses and a wrong-caseinputfails; object-valued fields are skipped; no path fields is a no-op. - Command, after
test/local/commands/push-git-source.test.ts(mocked client): a wrongdockerfilestops push with exit code 5 and no Actor read or write.
Links
- Epic: apify/apify-core#28685, refinement 3
- Push for monorepo Actors (Make
apify pushwork for monorepo Actors that setdockerContextDir#595), the failure in practice (How do you run these actors locally? actor-monorepo-example#3), the build arg set as an env var (how to run in apify platform actor-monorepo-example#5) - Worker resolution and fallback:
src/actor/build/act2_build_job.tsin apify-worker - Proposed separately for apify/actor-monorepo-example: a fail-fast guard in the shared Dockerfiles when the build arg is empty, for example
RUN test -n "$ACTOR_PATH_IN_DOCKER_CONTEXT"afterARG - Docs: https://docs.apify.com/platform/actors/development/actor-definition/actor-json and https://docs.apify.com/platform/actors/development/deployment/source-types
Activity