Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 53 additions & 12 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -885,9 +885,11 @@ Use these commands to manage Actor build processes. They help you create, monito

```sh
DESCRIPTION
Create, inspect, tag, and delete Actor builds on the Apify platform.
Create, inspect, abort, tag, and delete Actor builds on the Apify platform.

SUBCOMMANDS
builds abort Aborts an Actor build that is currently in
progress.
builds add-tag Adds a tag to a specific Actor build.
builds remove-tag Removes a tag from a specific Actor build.
builds rm Permanently removes an Actor build from
Expand All @@ -900,6 +902,22 @@ SUBCOMMANDS
terminal status (SUCCEEDED, FAILED, ABORTED, TIMED-OUT).
```

##### `apify builds abort`

```sh
DESCRIPTION
Aborts an Actor build that is currently in progress.

USAGE
$ apify builds abort <buildId> [--json]

ARGUMENTS
buildId The build ID to abort.

FLAGS
--json Format the command output as JSON.
```

##### `apify builds add-tag`

```sh
Expand Down Expand Up @@ -981,7 +999,7 @@ USAGE
[--limit <value>] [--offset <value>]

ARGUMENTS
actorId Optional Actor ID or Name to list runs for. By default, it
actorId Optional Actor ID or Name to list builds for. By default, it
will use the Actor from the current directory.

FLAGS
Expand Down Expand Up @@ -1136,17 +1154,23 @@ DESCRIPTION
USAGE
$ apify runs ls [actorId] [-c] [--desc] [--json]
[--limit <value>] [--offset <value>]
[--status
READY|RUNNING|SUCCEEDED|FAILED|TIMING-OUT|TIMED-OUT|ABORTING|ABORTED]

ARGUMENTS
actorId Optional Actor ID or Name to list runs for. By default, it
will use the Actor from the current directory.

FLAGS
-c, --compact Display a compact table.
--desc Sort runs in descending order.
--json Format the command output as JSON.
--limit=<value> Number of runs that will be listed.
--offset=<value> Number of runs that will be skipped.
-c, --compact Display a compact table.
--desc Sort runs in descending order.
--json Format the command output as JSON.
--limit=<value> Number of runs that will be listed.
--offset=<value> Number of runs that will be skipped.
--status=<option> Filter runs by status (e.g. RUNNING,
SUCCEEDED, FAILED).
<options:
READY|RUNNING|SUCCEEDED|FAILED|TIMING-OUT|TIMED-OUT|ABORTING|ABORTED>
```

##### `apify runs resurrect`
Expand Down Expand Up @@ -1230,7 +1254,7 @@ DESCRIPTION
SUBCOMMANDS
datasets create Creates a new dataset for storing
structured data on your account.
datasets get-items Retrieves dataset items in specified
datasets get-items Retrieves dataset items in a specified
format (JSON, CSV, etc).
datasets ls Prints all datasets on your account.
datasets info Prints information about a specific
Expand Down Expand Up @@ -1262,24 +1286,41 @@ FLAGS

```sh
DESCRIPTION
Retrieves dataset items in specified format (JSON, CSV, etc).
Retrieves dataset items in a specified format (JSON, CSV, etc).
Supports field selection, cleaning empty/hidden values, and writing directly
to a file.

USAGE
$ apify datasets get-items <datasetId>
$ apify datasets get-items <datasetId> [--clean]
[--desc] [--fields <value>]
[--format json|jsonl|csv|html|rss|xml|xlsx]
[--limit <value>] [--offset <value>]
[--omit <value>] [-o <value>] [--unwind <value>]

ARGUMENTS
datasetId The ID of the Dataset to export the items for.

FLAGS
--clean Return only non-empty items and skip
hidden fields (fields starting with #).
--desc Return items in descending order (newest
first).
--fields=<value> Comma-separated list of fields to
include in each item (all other fields are omitted).
--format=<option> The format of the returned output. By
default, it is set to 'json'.
<options: json|jsonl|csv|html|rss|xml|xlsx>
--limit=<value> The amount of elements to get from the
dataset. By default, it will return all available items.
--offset=<value> The offset in the dataset where to start
getting items.
--omit=<value> Comma-separated list of fields to
exclude from each item.
-o, --output=<value> Write items to this file path
instead of stdout. Content-Type still goes to stderr.
--unwind=<value> Comma-separated list of fields to
unwind. Each array value creates a separate item (same as
the Dataset API).
```

##### `apify datasets info`
Expand Down Expand Up @@ -1341,7 +1382,7 @@ USAGE
$ apify datasets rename <nameOrId> [newName] [--unname]

ARGUMENTS
nameOrId The dataset ID or name to delete.
nameOrId The dataset ID or name to rename.
newName The new name for the dataset.

FLAGS
Expand Down Expand Up @@ -1536,7 +1577,7 @@ USAGE

ARGUMENTS
keyValueStoreNameOrId The key-value store ID or name to
delete.
rename.
newName The new name for the key-value
store.

Expand Down
1 change: 1 addition & 0 deletions scripts/generate-cli-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const categories: Record<string, CommandsInCategory[]> = {
'actor-build': [
//
{ command: Commands.builds },
{ command: Commands.buildsAbort },
{ command: Commands.buildsAddTag },
{ command: Commands.buildsCreate, aliases: [Commands.actorsBuild] },
{ command: Commands.buildsInfo },
Expand Down
4 changes: 3 additions & 1 deletion src/commands/builds/_index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
import { BuildsAbortCommand } from './abort.js';
import { BuildsAddTagCommand } from './add-tag.js';
import { BuildsCreateCommand } from './create.js';
import { BuildsInfoCommand } from './info.js';
Expand All @@ -11,14 +12,15 @@ import { BuildsWaitCommand } from './wait.js';
export class BuildsIndexCommand extends ApifyCommand<typeof BuildsIndexCommand> {
static override name = 'builds' as const;

static override description = 'Create, inspect, tag, and delete Actor builds on the Apify platform.';
static override description = 'Create, inspect, abort, tag, and delete Actor builds on the Apify platform.';

static override group = 'Apify Console';

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

static override subcommands = [
//
BuildsAbortCommand,
BuildsAddTagCommand,
BuildsRemoveTagCommand,
BuildsRmCommand,
Expand Down
85 changes: 85 additions & 0 deletions src/commands/builds/abort.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import type { ApifyApiError } from 'apify-client';

import { ACTOR_JOB_STATUSES } from '@apify/consts';

import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
import { Args } from '../../lib/command-framework/args.js';
import { error, success } from '../../lib/outputs.js';
import { getLoggedClientOrThrow, printJsonToStdout } from '../../lib/utils.js';

const runningStatuses = [ACTOR_JOB_STATUSES.READY, ACTOR_JOB_STATUSES.RUNNING];

const abortingStatuses = [ACTOR_JOB_STATUSES.ABORTING, ACTOR_JOB_STATUSES.TIMING_OUT];

export class BuildsAbortCommand extends ApifyCommand<typeof BuildsAbortCommand> {
static override name = 'abort' as const;

static override description = 'Aborts an Actor build that is currently in progress.';

static override examples = [
{
description: 'Abort a running Actor build.',
command: 'apify builds abort <buildId>',
},
];

static override docsUrl = 'https://docs.apify.com/cli/docs/reference#apify-builds-abort';

static override args = {
buildId: Args.string({
required: true,
description: 'The build ID to abort.',
}),
};

static override enableJsonFlag = true;

async run() {
const { buildId } = this.args;

const apifyClient = await getLoggedClientOrThrow();

const build = await apifyClient.build(buildId).get();

if (!build) {
error({ message: `Build with ID "${buildId}" was not found on your account.`, stdout: true });
return;
}

if (!runningStatuses.includes(build.status as never)) {
if (abortingStatuses.includes(build.status as never)) {
error({ message: `Build with ID "${buildId}" is already aborting.`, stdout: true });
} else if (build.status === ACTOR_JOB_STATUSES.ABORTED || build.status === ACTOR_JOB_STATUSES.TIMED_OUT) {
error({ message: `Build with ID "${buildId}" is already aborted.`, stdout: true });
} else {
error({
message: `Build with ID "${buildId}" cannot be aborted (status: ${build.status}).`,
stdout: true,
});
}

return;
}

try {
const result = await apifyClient.build(buildId).abort();

if (this.flags.json) {
printJsonToStdout(result);
return;
}

success({
message: `Triggered the abort of build "${buildId}".`,
stdout: true,
});
} catch (err) {
const casted = err as ApifyApiError;

error({
message: `Failed to abort build "${buildId}".\n ${casted.message || casted}`,
stdout: true,
});
}
}
}
20 changes: 16 additions & 4 deletions src/commands/builds/log.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import process from 'node:process';

import { ApifyCommand } from '../../lib/command-framework/apify-command.js';
import { Args } from '../../lib/command-framework/args.js';
import { info } from '../../lib/outputs.js';
import { error, info } from '../../lib/outputs.js';
import { getLoggedClientOrThrow, outputJobLog } from '../../lib/utils.js';

export class BuildsLogCommand extends ApifyCommand<typeof BuildsLogCommand> {
Expand Down Expand Up @@ -32,11 +34,21 @@ export class BuildsLogCommand extends ApifyCommand<typeof BuildsLogCommand> {
const build = await apifyClient.build(buildId).get();

if (!build) {
throw new Error(`Build with ID "${buildId}" was not found on your account.`);
error({ message: `Build with ID "${buildId}" was not found on your account.`, stdout: true });
process.exitCode = 1;
return;
}

info({ message: `Log for build with ID "${buildId}":\n` });
info({ message: `Log for build with ID "${buildId}":\n`, stdout: true });

await outputJobLog({ job: build, apifyClient });
try {
await outputJobLog({ job: build, apifyClient });
} catch (err) {
error({
message: `Failed to get log for build with ID "${buildId}": ${(err as Error).message}`,
stdout: true,
});
process.exitCode = 1;
}
Comment on lines +44 to +52

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This swallows log-fetch failures and reports success. Before, an exception from outputJobLog propagated and the command exited 1. Now, if the build exists but client.log(id).get() 5xx's or the log is gone, the user gets Info: Log for build with ID "x": on stdout, Error: Failed to get log… on stderr, and $? == 0.

Concretely: apify builds log $ID > build.log && next-step proceeds with an empty file.

I see this was copied from src/commands/runs/log.ts — but there the swallow is annotated (// This should never happen..., dropped in the copy), and regardless it's a new regression for builds log. Either rethrow, or process.exitCode = 1 in the catch.

Minor inconsistency while you're here: line 35 sends its error to stdout (stdout: true) and line 44 to stderr, in the same command.

}
}
2 changes: 1 addition & 1 deletion src/commands/builds/ls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class BuildsLsCommand extends ApifyCommand<typeof BuildsLsCommand> {
static override args = {
actorId: Args.string({
description:
'Optional Actor ID or Name to list runs for. By default, it will use the Actor from the current directory.',
'Optional Actor ID or Name to list builds for. By default, it will use the Actor from the current directory.',
}),
};

Expand Down
Loading