From e9f8d3642b4ceea8d65b4875c3409ce3de465963 Mon Sep 17 00:00:00 2001 From: Matyas Cimbulka Date: Tue, 15 Jul 2025 13:20:02 +0200 Subject: [PATCH 1/5] feat(apify): Show list of built tags in actor run action --- .../apify/actions/run-actor/run-actor.mjs | 132 ++++++++++-------- components/apify/apify.app.mjs | 35 +++-- pnpm-lock.yaml | 5 +- 3 files changed, 101 insertions(+), 71 deletions(-) diff --git a/components/apify/actions/run-actor/run-actor.mjs b/components/apify/actions/run-actor/run-actor.mjs index 84febb9e9b6a8..2b29dc586a1d2 100644 --- a/components/apify/actions/run-actor/run-actor.mjs +++ b/components/apify/actions/run-actor/run-actor.mjs @@ -6,32 +6,54 @@ import { EVENT_TYPES } from "../../common/constants.mjs"; export default { key: "apify-run-actor", name: "Run Actor", - description: "Performs an execution of a selected Actor in Apify. [See the documentation](https://docs.apify.com/api/v2#/reference/actors/run-collection/run-actor)", - version: "0.0.4", + description: "Performs an execution of a selected actor in Apify. [See the documentation](https://docs.apify.com/api/v2#/reference/actors/run-collection/run-actor)", + version: "0.0.20", type: "action", props: { apify, + actorSource: { + type: "string", + label: "Search Actors from", + description: "Where to search for Actors. Valid options are Store and Recently used Actors.", + options: [ + { + label: "Store", + value: "store", + }, + { + label: "Recently used Actors", + value: "recently-used", + }, + ], + reloadProps: true, + default: "recently-used", + }, actorId: { propDefinition: [ apify, "actorId", + (c) => ({ + actorSource: c.actorSource, + }), ], }, - buildId: { + buildTag: { propDefinition: [ apify, - "buildId", + "buildTag", (c) => ({ actorId: c.actorId, }), ], reloadProps: true, + optional: true, }, runAsynchronously: { type: "boolean", label: "Run Asynchronously", - description: "Set to `true` to run the Actor asynchronously", + description: "Set to `true` to run the actor asynchronously", reloadProps: true, + default: true, }, timeout: { type: "string", @@ -76,19 +98,19 @@ export default { ? type : "string[]"; }, - async getSchema(buildId) { - const { data: { inputSchema } } = await this.apify.getBuild(buildId); + async getSchema(actorId, buildId) { + const { data: { inputSchema } } = await this.apify.getBuild(actorId, buildId); return JSON.parse(inputSchema); }, async prepareData(data) { const newData = {}; - const { properties } = await this.getSchema(this.buildId); + const { properties } = await this.getSchema(this.actorId, this.buildId); for (const [ key, value, ] of Object.entries(data)) { - const editor = properties[key].editor; + const editor = properties[key]?.editor; newData[key] = (Array.isArray(value)) ? value.map((item) => this.setValue(editor, item)) : value; @@ -131,55 +153,54 @@ export default { }, async additionalProps() { const props = {}; - if (this.buildId) { - try { - const { - properties, required: requiredProps = [], - } = await this.getSchema(this.buildId); - for (const [ - key, - value, - ] of Object.entries(properties)) { - if (value.editor === "hidden") continue; + try { + const { + properties, required: requiredProps = [], + } = await this.getSchema(this.actorId, this.buildId); - props[key] = { - type: this.getType(value.type), - label: value.title, - description: value.description, - optional: !requiredProps.includes(key), - }; - const options = this.prepareOptions(value); - if (options) props[key].options = options; - if (value.default) { - props[key].description += ` Default: \`${JSON.stringify(value.default)}\``; - if (props[key].type !== "object") { // default values don't work properly for object props - props[key].default = value.default; - } + for (const [ + key, + value, + ] of Object.entries(properties)) { + if (value.editor === "hidden") continue; + + props[key] = { + type: this.getType(value.type), + label: value.title, + description: value.description, + optional: !requiredProps.includes(key), + }; + const options = this.prepareOptions(value); + if (options) props[key].options = options; + if (value.default) { + props[key].description += ` Default: \`${JSON.stringify(value.default)}\``; + if (props[key].type !== "object") { // default values don't work properly for object props + props[key].default = value.default; } } - } catch { - props.properties = { - type: "object", - label: "Properties", - description: "Properties to set for this Actor", - }; - } - if (this.runAsynchronously) { - props.outputRecordKey = { - type: "string", - label: "Output Record Key", - description: "Key of the record from run's default key-value store to be returned in the response. By default, it is OUTPUT.", - optional: true, - }; - } else { - props.waitForFinish = { - type: "string", - label: "Wait For Finish", - description: "The maximum number of seconds the server waits for the run to finish. By default, it is 0, the maximum value is 60. If the build finishes in time then the returned run object will have a terminal status (e.g. SUCCEEDED), otherwise it will have a transitional status (e.g. RUNNING).", - optional: true, - }; } + } catch { + props.properties = { + type: "object", + label: "Properties", + description: "Properties to set for this actor", + }; + } + if (this.runAsynchronously) { + props.outputRecordKey = { + type: "string", + label: "Output Record Key", + description: "Key of the record from run's default key-value store to be returned in the response. By default, it is OUTPUT.", + optional: true, + }; + } else { + props.waitForFinish = { + type: "string", + label: "Wait For Finish", + description: "The maximum number of seconds the server waits for the run to finish. By default, it is 0, the maximum value is 60. If the build finishes in time then the returned run object will have a terminal status (e.g. SUCCEEDED), otherwise it will have a transitional status (e.g. RUNNING).", + optional: true, + }; } if (this.webhook) { props.eventTypes = { @@ -230,6 +251,7 @@ export default { maxItems, maxTotalChargeUsd, waitForFinish, + build: buildId, webhooks: webhook ? btoa(JSON.stringify([ { @@ -241,8 +263,8 @@ export default { }, }); const summary = this.runAsynchronously - ? `Successfully started Actor run with ID: ${response.data.id}` - : `Successfully ran Actor with ID: ${this.actorId}`; + ? `Successfully started actor run with ID: ${response.data.id}` + : `Successfully ran actor with ID: ${this.actorId}`; $.export("$summary", `${summary}`); return response; }, diff --git a/components/apify/apify.app.mjs b/components/apify/apify.app.mjs index ad0fb25c9773d..30695cd863126 100644 --- a/components/apify/apify.app.mjs +++ b/components/apify/apify.app.mjs @@ -105,21 +105,21 @@ export default { })) || []; }, }, - buildId: { + buildTag: { type: "string", label: "Build", description: "Specifies the Actor build to run. It can be either a build tag or build number.", - async options({ - page, actorId, - }) { - const { data: { items } } = await this.listBuilds({ + async options({ actorId }) { + const { data: { taggedBuilds } } = await this.getActor({ actorId, - params: { - offset: LIMIT * page, - limit: LIMIT, - }, }); - return items?.map(({ id }) => id) || []; + return Object.entries(taggedBuilds).map(([ + name, + { buildId }, + ]) => ({ + label: name, + value: buildId, + })); }, }, clean: { @@ -211,9 +211,20 @@ export default { path: `/actor-tasks/${taskId}/runs`, }); }, - getBuild(build) { + getActor({ actorId }) { + return this._makeRequest({ + path: `/acts/${actorId}`, + }); + }, + getBuild(actorId, buildId) { + if (buildId) { + return this._makeRequest({ + path: `/actor-builds/${buildId}`, + }); + } + return this._makeRequest({ - path: `/actor-builds/${build}`, + path: `/acts/${actorId}/builds/default`, }); }, listActors(opts = {}) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d95be2f71e5a4..ea66ec975f858 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1078,10 +1078,7 @@ importers: version: 1.6.6 components/asters: - dependencies: - '@pipedream/platform': - specifier: ^3.1.0 - version: 3.1.0 + specifiers: {} components/astica_ai: dependencies: From dd179e2820067f0b8626da7e813e682857fc3577 Mon Sep 17 00:00:00 2001 From: Matyas Cimbulka Date: Wed, 23 Jul 2025 09:26:01 +0200 Subject: [PATCH 2/5] feat(apify): Allow selecting actor search source for run Actor action and change how Actor or task name is displayed --- components/apify/apify.app.mjs | 40 ++++++------------- .../new-finished-actor-run-instant.mjs | 2 +- 2 files changed, 14 insertions(+), 28 deletions(-) diff --git a/components/apify/apify.app.mjs b/components/apify/apify.app.mjs index 30695cd863126..74b668f827440 100644 --- a/components/apify/apify.app.mjs +++ b/components/apify/apify.app.mjs @@ -30,28 +30,14 @@ export default { type: "string", label: "Actor ID", description: "Actor ID or a tilde-separated owner's username and Actor name", - async options({ page }) { - const { data: { items } } = await this.listActors({ - params: { - offset: LIMIT * page, - limit: LIMIT, - }, - }); - - return items.map(({ - id: value, name: label, - }) => ({ - label, - value, - })); - }, - }, - userActorId: { - type: "string", - label: "Actor ID", - description: "The ID of the Actor to monitor.", - async options({ page }) { - const { data: { items } } = await this.listUserActors({ + async options({ + page, actorSource, + }) { + actorSource ??= "recently-used"; + const listFn = actorSource === "store" + ? this.listActors + : this.listUserActors; + const { data: { items } } = await listFn({ params: { offset: LIMIT * page, limit: LIMIT, @@ -59,9 +45,9 @@ export default { }); return items.map(({ - id: value, name: label, + id: value, title: title, username, name, }) => ({ - label, + label: `${title} (${username}/${name})`, value, })); }, @@ -79,9 +65,9 @@ export default { }); return items.map(({ - id: value, name: label, + id: value, title, username, name, }) => ({ - label, + label: `${title} (${username}/${name})`, value, })); }, @@ -235,7 +221,7 @@ export default { }, listUserActors(opts = {}) { return this._makeRequest({ - path: "/acts", + path: "/acts?desc=1&sortBy=stats.lastRunStartedAt", ...opts, }); }, diff --git a/components/apify/sources/new-finished-actor-run-instant/new-finished-actor-run-instant.mjs b/components/apify/sources/new-finished-actor-run-instant/new-finished-actor-run-instant.mjs index 0dbf18cabe02e..e79a84bbe984f 100644 --- a/components/apify/sources/new-finished-actor-run-instant/new-finished-actor-run-instant.mjs +++ b/components/apify/sources/new-finished-actor-run-instant/new-finished-actor-run-instant.mjs @@ -15,7 +15,7 @@ export default { actorId: { propDefinition: [ common.props.apify, - "userActorId", + "actorId", ], }, }, From 97b02c5fec89b2b25e5a3271772e4fe0d9d49c5b Mon Sep 17 00:00:00 2001 From: Matyas Cimbulka Date: Wed, 23 Jul 2025 12:01:46 +0200 Subject: [PATCH 3/5] feat(apif): Remove wait for finish prop in run Actor action --- components/apify/actions/run-actor/run-actor.mjs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/components/apify/actions/run-actor/run-actor.mjs b/components/apify/actions/run-actor/run-actor.mjs index 2b29dc586a1d2..24efc682c8c53 100644 --- a/components/apify/actions/run-actor/run-actor.mjs +++ b/components/apify/actions/run-actor/run-actor.mjs @@ -7,7 +7,7 @@ export default { key: "apify-run-actor", name: "Run Actor", description: "Performs an execution of a selected actor in Apify. [See the documentation](https://docs.apify.com/api/v2#/reference/actors/run-collection/run-actor)", - version: "0.0.20", + version: "0.0.25", type: "action", props: { apify, @@ -194,13 +194,6 @@ export default { description: "Key of the record from run's default key-value store to be returned in the response. By default, it is OUTPUT.", optional: true, }; - } else { - props.waitForFinish = { - type: "string", - label: "Wait For Finish", - description: "The maximum number of seconds the server waits for the run to finish. By default, it is 0, the maximum value is 60. If the build finishes in time then the returned run object will have a terminal status (e.g. SUCCEEDED), otherwise it will have a transitional status (e.g. RUNNING).", - optional: true, - }; } if (this.webhook) { props.eventTypes = { @@ -229,7 +222,6 @@ export default { memory, maxItems, maxTotalChargeUsd, - waitForFinish, webhook, eventTypes, ...data @@ -250,7 +242,6 @@ export default { memory, maxItems, maxTotalChargeUsd, - waitForFinish, build: buildId, webhooks: webhook ? btoa(JSON.stringify([ From b39f6f5ba0bf2f8de569ab749c98dee0fd0bf8d1 Mon Sep 17 00:00:00 2001 From: Matyas Cimbulka Date: Fri, 25 Jul 2025 08:42:47 +0200 Subject: [PATCH 4/5] fix(apify): Fix PR issues --- components/apify/actions/run-actor/run-actor.mjs | 6 +++--- components/apify/apify.app.mjs | 8 ++------ components/apify/package.json | 4 ++-- .../new-finished-actor-run-instant.mjs | 2 +- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/components/apify/actions/run-actor/run-actor.mjs b/components/apify/actions/run-actor/run-actor.mjs index 24efc682c8c53..f0966796eb9e5 100644 --- a/components/apify/actions/run-actor/run-actor.mjs +++ b/components/apify/actions/run-actor/run-actor.mjs @@ -7,7 +7,7 @@ export default { key: "apify-run-actor", name: "Run Actor", description: "Performs an execution of a selected actor in Apify. [See the documentation](https://docs.apify.com/api/v2#/reference/actors/run-collection/run-actor)", - version: "0.0.25", + version: "0.0.31", type: "action", props: { apify, @@ -214,7 +214,7 @@ export default { prepareData, apify, actorId, - buildId, + buildTag, properties, runAsynchronously, outputRecordKey, @@ -242,7 +242,7 @@ export default { memory, maxItems, maxTotalChargeUsd, - build: buildId, + build: buildTag, webhooks: webhook ? btoa(JSON.stringify([ { diff --git a/components/apify/apify.app.mjs b/components/apify/apify.app.mjs index 74b668f827440..86a95d148de71 100644 --- a/components/apify/apify.app.mjs +++ b/components/apify/apify.app.mjs @@ -45,7 +45,7 @@ export default { }); return items.map(({ - id: value, title: title, username, name, + id: value, title, username, name, }) => ({ label: `${title} (${username}/${name})`, value, @@ -101,11 +101,7 @@ export default { }); return Object.entries(taggedBuilds).map(([ name, - { buildId }, - ]) => ({ - label: name, - value: buildId, - })); + ]) => name); }, }, clean: { diff --git a/components/apify/package.json b/components/apify/package.json index 6fa6e927daca3..6ee7c4ad5e8d3 100644 --- a/components/apify/package.json +++ b/components/apify/package.json @@ -1,6 +1,6 @@ { "name": "@pipedream/apify", - "version": "0.2.2", + "version": "0.2.3", "description": "Pipedream Apify Components", "main": "apify.app.mjs", "keywords": [ @@ -14,6 +14,6 @@ }, "dependencies": { "@apify/consts": "^2.41.0", - "@pipedream/platform": "^3.0.3" + "@pipedream/platform": "^3.1.0" } } diff --git a/components/apify/sources/new-finished-actor-run-instant/new-finished-actor-run-instant.mjs b/components/apify/sources/new-finished-actor-run-instant/new-finished-actor-run-instant.mjs index e79a84bbe984f..14611eda57639 100644 --- a/components/apify/sources/new-finished-actor-run-instant/new-finished-actor-run-instant.mjs +++ b/components/apify/sources/new-finished-actor-run-instant/new-finished-actor-run-instant.mjs @@ -6,7 +6,7 @@ export default { key: "apify-new-finished-actor-run-instant", name: "New Finished Actor Run (Instant)", description: "Emit new event when a selected Actor is run and finishes.", - version: "0.0.4", + version: "0.0.5", type: "source", dedupe: "unique", props: { From dfb17761e5a7a5e3fe0a85923bda9c3e37b27853 Mon Sep 17 00:00:00 2001 From: Matyas Cimbulka Date: Tue, 29 Jul 2025 14:57:08 +0200 Subject: [PATCH 5/5] fix(apif): Fix PR issues --- .../apify/actions/run-actor/run-actor.mjs | 22 +++++++++++------ components/apify/apify.app.mjs | 24 +++++++++++-------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/components/apify/actions/run-actor/run-actor.mjs b/components/apify/actions/run-actor/run-actor.mjs index f0966796eb9e5..d34da2d29eb82 100644 --- a/components/apify/actions/run-actor/run-actor.mjs +++ b/components/apify/actions/run-actor/run-actor.mjs @@ -6,8 +6,8 @@ import { EVENT_TYPES } from "../../common/constants.mjs"; export default { key: "apify-run-actor", name: "Run Actor", - description: "Performs an execution of a selected actor in Apify. [See the documentation](https://docs.apify.com/api/v2#/reference/actors/run-collection/run-actor)", - version: "0.0.31", + description: "Performs an execution of a selected Actor in Apify. [See the documentation](https://docs.apify.com/api/v2#/reference/actors/run-collection/run-actor)", + version: "0.0.33", type: "action", props: { apify, @@ -17,7 +17,7 @@ export default { description: "Where to search for Actors. Valid options are Store and Recently used Actors.", options: [ { - label: "Store", + label: "Apify Store Actors", value: "store", }, { @@ -51,7 +51,7 @@ export default { runAsynchronously: { type: "boolean", label: "Run Asynchronously", - description: "Set to `true` to run the actor asynchronously", + description: "Set to `true` to run the Actor asynchronously", reloadProps: true, default: true, }, @@ -110,7 +110,15 @@ export default { key, value, ] of Object.entries(data)) { - const editor = properties[key]?.editor; + let editor; + + if (properties[key]) { + editor = properties[key].editor; + } else { + console.warn(`Property "${key}" is not defined in the schema`); + editor = "hidden"; // This will prevent it from showing up + } + newData[key] = (Array.isArray(value)) ? value.map((item) => this.setValue(editor, item)) : value; @@ -254,8 +262,8 @@ export default { }, }); const summary = this.runAsynchronously - ? `Successfully started actor run with ID: ${response.data.id}` - : `Successfully ran actor with ID: ${this.actorId}`; + ? `Successfully started Actor run with ID: ${response.data.id}` + : `Successfully ran Actor with ID: ${this.actorId}`; $.export("$summary", `${summary}`); return response; }, diff --git a/components/apify/apify.app.mjs b/components/apify/apify.app.mjs index 86a95d148de71..f4639504ed200 100644 --- a/components/apify/apify.app.mjs +++ b/components/apify/apify.app.mjs @@ -44,11 +44,9 @@ export default { }, }); - return items.map(({ - id: value, title, username, name, - }) => ({ - label: `${title} (${username}/${name})`, - value, + return items.map((actor) => ({ + label: this.formatActorOrTaskLabel(actor), + value: actor.id, })); }, }, @@ -64,11 +62,9 @@ export default { }, }); - return items.map(({ - id: value, title, username, name, - }) => ({ - label: `${title} (${username}/${name})`, - value, + return items.map((task) => ({ + label: this.formatActorOrTaskLabel(task), + value: task.id, })); }, }, @@ -269,5 +265,13 @@ export default { ...opts, }); }, + formatActorOrTaskLabel({ + title, username, name, + }) { + if (title) { + return `${title} (${username}/${name})`; + } + return `${username}/${name}`; + }, }, };