Skip to content

Commit b5bbc08

Browse files
authored
feat: add task publish and unpublish commands (#1317)
Part of apify/apify-core#29471 Add new commands to publish and un-publish Actor tasks apify/apify-core#29623 Blocked by apify/apify-client-js#989
1 parent afea2a5 commit b5bbc08

7 files changed

Lines changed: 198 additions & 13 deletions

File tree

docs/reference.md

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,12 +1651,15 @@ These commands help you manage scheduled and configured Actor runs. Use them to
16511651
16521652
```sh
16531653
DESCRIPTION
1654-
Run saved Apify tasks (named Actor configurations). Only 'task run' is
1655-
available; create and manage tasks in Apify Console.
1654+
Run and publish saved Apify tasks (named Actor configurations). Create and
1655+
manage tasks in Apify Console.
16561656
16571657
SUBCOMMANDS
1658-
task run Executes predefined Actor task remotely using local
1659-
key-value store for input.
1658+
task run Executes predefined Actor task remotely using
1659+
local key-value store for input.
1660+
task publish Publishes the task on its public landing page.
1661+
task unpublish Unpublishes the task from its public landing
1662+
page.
16601663
```
16611664
16621665
##### `apify task run`
@@ -1683,6 +1686,39 @@ FLAGS
16831686
-t, --timeout=<value> Timeout for the Task run in seconds.
16841687
Zero value means there is no timeout.
16851688
```
1689+
1690+
##### `apify task publish`
1691+
1692+
```sh
1693+
DESCRIPTION
1694+
Publishes the task on its public landing page.
1695+
The task must belong to a public Actor and have its public display
1696+
configuration set up on the task Publication tab in Apify Console. Requires
1697+
write access to the task and to its Actor.
1698+
1699+
USAGE
1700+
$ apify task publish <taskId>
1701+
1702+
ARGUMENTS
1703+
taskId Name of the task to publish. For example, "my-task" or
1704+
"username/my-task".
1705+
```
1706+
1707+
##### `apify task unpublish`
1708+
1709+
```sh
1710+
DESCRIPTION
1711+
Unpublishes the task from its public landing page.
1712+
The public display configuration is preserved, so the task can be published
1713+
again later. Requires write access to the task and to its Actor.
1714+
1715+
USAGE
1716+
$ apify task unpublish <taskId>
1717+
1718+
ARGUMENTS
1719+
taskId Name of the task to unpublish. For example, "my-task" or
1720+
"username/my-task".
1721+
```
16861722
<!-- task-commands-end -->
16871723
<!-- prettier-ignore-end -->
16881724

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
"@skyra/jaro-winkler": "^1.1.1",
8686
"adm-zip": "~0.6.0",
8787
"ajv": "~8.20.0",
88-
"apify-client": "^2.23.3",
88+
"apify-client": "^2.25.0",
8989
"archiver": "~8.0.0",
9090
"axios": "^1.15.0",
9191
"chalk": "~6.0.0",

pnpm-lock.yaml

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/generate-cli-docs.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ const categories: Record<string, CommandsInCategory[]> = {
116116
//
117117
{ command: Commands.task },
118118
{ command: Commands.taskRun },
119+
{ command: Commands.taskPublish },
120+
{ command: Commands.taskUnpublish },
119121
],
120122
'mcp': [
121123
//

src/commands/task/_index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
2+
import { TaskPublishCommand } from './publish.js';
23
import { TaskRunCommand } from './run.js';
4+
import { TaskUnpublishCommand } from './unpublish.js';
35

46
export class TasksIndexCommand extends ApifyCommand<typeof TasksIndexCommand> {
57
static override name = 'task' as const;
68

7-
static override description = `Run saved Apify tasks (named Actor configurations). Only 'task run' is available; create and manage tasks in Apify Console.`;
9+
static override description = `Run and publish saved Apify tasks (named Actor configurations). Create and manage tasks in Apify Console.`;
810

911
static override group = 'Apify Console';
1012

1113
static override docsUrl = 'https://docs.apify.com/cli/docs/reference#apify-task';
1214

13-
static override subcommands = [TaskRunCommand];
15+
static override subcommands = [TaskRunCommand, TaskPublishCommand, TaskUnpublishCommand];
1416

1517
async run() {
1618
this.printHelp();

src/commands/task/publish.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import process from 'node:process';
2+
3+
import type { ApifyApiError } from 'apify-client';
4+
import chalk from 'chalk';
5+
6+
import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
7+
import { Args } from '../../lib/command-framework/args.js';
8+
import { CommandExitCodes } from '../../lib/consts.js';
9+
import { error, success } from '../../lib/outputs.js';
10+
import { getLocalUserInfo, getLoggedClientOrThrow } from '../../lib/utils.js';
11+
12+
export class TaskPublishCommand extends ApifyCommand<typeof TaskPublishCommand> {
13+
static override name = 'publish' as const;
14+
15+
static override description =
16+
'Publishes the task on its public landing page.\n' +
17+
'The task must belong to a public Actor and have its public display configuration set up ' +
18+
'on the task Publication tab in Apify Console. ' +
19+
'Requires write access to the task and to its Actor.';
20+
21+
static override examples = [
22+
{
23+
description: 'Publish a task by name.',
24+
command: 'apify task publish my-task',
25+
},
26+
{
27+
description: 'Publish a task by full name.',
28+
command: 'apify task publish username/my-task',
29+
},
30+
];
31+
32+
static override docsUrl = 'https://docs.apify.com/cli/docs/reference#apify-task-publish';
33+
34+
static override args = {
35+
taskId: Args.string({
36+
required: true,
37+
description: 'Name of the task to publish. For example, "my-task" or "username/my-task".',
38+
}),
39+
};
40+
41+
async run() {
42+
const apifyClient = await getLoggedClientOrThrow();
43+
const userInfo = await getLocalUserInfo();
44+
const usernameOrId = userInfo.username || (userInfo.id as string);
45+
46+
const { taskId } = this.args;
47+
const idOrName = taskId.includes('/') ? taskId : `${usernameOrId}/${taskId.toLowerCase()}`;
48+
const taskClient = apifyClient.task(idOrName);
49+
50+
const task = await taskClient.get();
51+
if (!task) {
52+
error({ message: `Cannot find Task with name '${taskId}' in your account.` });
53+
process.exitCode = CommandExitCodes.NotFound;
54+
return;
55+
}
56+
57+
try {
58+
await taskClient.publish();
59+
60+
success({
61+
message: `Task ${chalk.yellow(task.name)} has been published.`,
62+
stdout: true,
63+
});
64+
} catch (err) {
65+
const casted = err as ApifyApiError;
66+
67+
error({
68+
message: `Failed to publish task ${chalk.yellow(task.name)}\n ${casted.message || casted}`,
69+
});
70+
process.exitCode = CommandExitCodes.RunFailed;
71+
}
72+
}
73+
}

src/commands/task/unpublish.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import process from 'node:process';
2+
3+
import type { ApifyApiError } from 'apify-client';
4+
import chalk from 'chalk';
5+
6+
import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
7+
import { Args } from '../../lib/command-framework/args.js';
8+
import { CommandExitCodes } from '../../lib/consts.js';
9+
import { error, success } from '../../lib/outputs.js';
10+
import { getLocalUserInfo, getLoggedClientOrThrow } from '../../lib/utils.js';
11+
12+
export class TaskUnpublishCommand extends ApifyCommand<typeof TaskUnpublishCommand> {
13+
static override name = 'unpublish' as const;
14+
15+
static override description =
16+
'Unpublishes the task from its public landing page.\n' +
17+
'The public display configuration is preserved, so the task can be published again later. ' +
18+
'Requires write access to the task and to its Actor.';
19+
20+
static override examples = [
21+
{
22+
description: 'Unpublish a task by name.',
23+
command: 'apify task unpublish my-task',
24+
},
25+
{
26+
description: 'Unpublish a task by full name.',
27+
command: 'apify task unpublish username/my-task',
28+
},
29+
];
30+
31+
static override docsUrl = 'https://docs.apify.com/cli/docs/reference#apify-task-unpublish';
32+
33+
static override args = {
34+
taskId: Args.string({
35+
required: true,
36+
description: 'Name of the task to unpublish. For example, "my-task" or "username/my-task".',
37+
}),
38+
};
39+
40+
async run() {
41+
const apifyClient = await getLoggedClientOrThrow();
42+
const userInfo = await getLocalUserInfo();
43+
const usernameOrId = userInfo.username || (userInfo.id as string);
44+
45+
const { taskId } = this.args;
46+
const idOrName = taskId.includes('/') ? taskId : `${usernameOrId}/${taskId.toLowerCase()}`;
47+
const taskClient = apifyClient.task(idOrName);
48+
49+
const task = await taskClient.get();
50+
if (!task) {
51+
error({ message: `Cannot find Task with name '${taskId}' in your account.` });
52+
process.exitCode = CommandExitCodes.NotFound;
53+
return;
54+
}
55+
56+
try {
57+
await taskClient.unpublish();
58+
59+
success({
60+
message: `Task ${chalk.yellow(task.name)} has been unpublished.`,
61+
stdout: true,
62+
});
63+
} catch (err) {
64+
const casted = err as ApifyApiError;
65+
66+
error({
67+
message: `Failed to unpublish task ${chalk.yellow(task.name)}\n ${casted.message || casted}`,
68+
});
69+
process.exitCode = CommandExitCodes.RunFailed;
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)