Skip to content

feat: Add publish-actor and unpublish-actor tools - #1438

Draft
DaveHanns wants to merge 8 commits into
refactor/actor-resolutionfrom
feat/publish-actor
Draft

DaveHanns wants to merge 8 commits into
refactor/actor-resolutionfrom
feat/publish-actor

Conversation

@DaveHanns

Copy link
Copy Markdown
Contributor

What

publish-actor and unpublish-actor: make an Actor public in Apify Store or private again. Both return the Actor's name and visibility; publishing also returns the Store URL.

Why

Publishing lists the Actor in Store and counts against a daily quota, so it should not hide inside a general update. Closes #1419. Part of Epic #1412.

How

  • Mimic publish-actor-task and unpublish-actor-task: one argument, actor, as an ID or a name within the caller's own account. An Actor already in the requested state returns at once without an API call.
  • publish-actor checks title and categories first. The other platform rejections (a tagged build, a README and schemas in the default build, a successful run, accepted Store terms, the daily limit of 5 per rolling 24 hours) come back as soft failures with the platform's message.
  • The generic "cannot be published" rejection, which the platform uses for an Actor without a successful run, gets an explanation instead of the support hint.
  • Publishing goes through a client with retries off and the session's API host: apify-client retries every 429, and the daily limit answers with one, so the call would otherwise take minutes.
  • destructiveHint: true on both, as agreed on the Epic.

Testing

Unit tests cover the short-circuits, a missing title or categories, each rejection type, the payloads, the Store URL, another account refused, not found, and schema conformance. type-check, lint, format, test:unit, check:agents pass.

Notes

AI disclosure: implemented with Claude Code; awaiting human review.

🤖 Generated with Claude Code

Over MCP there was no way to make an Actor public in Apify Store or take
it off again, and the Epic keeps this out of update-actor because
publishing is public and counts against the daily publication limit.

Both tools take an Actor ID or name of the caller's own account and flip
isPublic with an update that sends nothing else. An Actor already in the
requested state is answered without an API call. publish-actor checks
the title and categories first, because the API rejects a missing one
with a generic schema-validation message; every other 4xx rejection
(tagged build, Store terms, README, schemas, runs, daily limit, paid or
critical Actor on unpublish) comes back as a soft failure carrying the
API's own message. The publish result includes the Store page URL.

Both are in the actors category, so they are served by default, and
both are marked destructive so clients confirm with the user.

Closes #1419
The catch that turns an API 4xx into a soft failure also wrapped the
account and Actor lookups, so a 401 or 403 there (a bad or scoped token)
came back as invalid input without the token hint. It now wraps only the
isPublic update, whose rejections name the unmet requirement; a failed
read reaches the generic mapper, which reports it as an auth failure.
The same applies to unpublish-actor.
apify-client retries every 429, and the API answers a sixth publication
in 24 hours with a 429. The limit message therefore arrived only after
nine attempts over two to four minutes, past the MCP request timeout,
and each attempt made the API notify Apify admins. The isPublic update
now goes through a client built with maxRetries 0; the lookups keep the
session client. Publishing is idempotent, so the agent can repeat it
after a transient failure.
The API answers an Actor with no run, or no successful run, with
'cannot-publish-actor' and a message that only says to contact support.
That is the usual state right after push and build, and the tool passed
the message on as the whole answer. It now adds that this usually means
no successful run yet and that running the Actor once fixes it, naming
call-actor only when the session has it.
A name lookup matches case-insensitively, and the resolver hands back
the caller's spelling, so input 'my-actor' for an Actor named 'My-Actor'
returned fullName and a Store URL in the wrong case. Both tools now build
fullName from the resolved Actor's username and name.
The description said the Actor could simply be published again later.
Publishing again repeats every publication check, including the input
and output schemas that Actors published before that rule never had to
pass, and counts against the daily limit; unpublishing also notifies the
users who ran the Actor recently. The description now says so, so an
agent does not treat unpublish and republish as a free round trip.
The no-retry client used for publishing took the default API base URL, so a server configured with another API host would publish against the wrong one. It now takes the session client's base URL.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants