apify-test-tools 0.10.2-beta.2 → 0.10.2-beta.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +1 -0
- package/.github/actionlint.yaml +11 -0
- package/.github/actions/checkout-restore-dependencies/action.yaml +58 -6
- package/.github/cli/apify-test-tools.mjs +135 -142
- package/.github/scripts/mask-config-secrets.sh +17 -0
- package/.github/scripts/run-with-apify-tokens.mjs +63 -103
- package/.github/workflows/_check_code.yaml +5 -21
- package/.github/workflows/_move_major_tag.yaml +2 -2
- package/.github/workflows/public_platform-tests-claude-investigate-and-fix.yaml +89 -8
- package/.github/workflows/public_platform-tests.yaml +68 -30
- package/.github/workflows/public_pr-build-test.yaml +77 -38
- package/.github/workflows/public_push-build-latest.yaml +49 -11
- package/.github/workflows/public_review.yaml +5 -4
- package/.github/workflows/public_stale-issues.yaml +51 -0
- package/.husky/pre-commit +4 -4
- package/.prettierignore +2 -1
- package/CHANGELOG.md +22 -0
- package/CONTRIBUTING.md +117 -17
- package/README.md +221 -595
- package/bin/actor-ids.ts +41 -0
- package/bin/affected-actors.ts +211 -0
- package/bin/build-from-local.ts +19 -1
- package/bin/build.ts +105 -39
- package/bin/diff-changes.ts +69 -36
- package/bin/diff-json-schema.ts +5 -6
- package/bin/git.ts +73 -175
- package/bin/main.ts +142 -189
- package/bin/notify.ts +198 -0
- package/bin/run-tests.ts +167 -0
- package/bin/slack.ts +16 -76
- package/bin/stdin-input.ts +156 -0
- package/bin/test-files-glob.ts +126 -0
- package/bin/test-report.ts +141 -140
- package/bin/types.ts +4 -7
- package/bin/utils/config/load-config.ts +20 -2
- package/bin/utils/config/parser.ts +40 -8
- package/bin/utils/config/structures/grouped.ts +2 -2
- package/bin/utils/config/structures/legacy.ts +1 -1
- package/dist/bin/actor-ids.d.ts +15 -0
- package/dist/bin/actor-ids.d.ts.map +1 -0
- package/dist/bin/actor-ids.js +30 -0
- package/dist/bin/actor-ids.js.map +1 -0
- package/dist/bin/affected-actors.d.ts +55 -0
- package/dist/bin/affected-actors.d.ts.map +1 -0
- package/dist/bin/affected-actors.js +142 -0
- package/dist/bin/affected-actors.js.map +1 -0
- package/dist/bin/build-from-local.d.ts +2 -1
- package/dist/bin/build-from-local.d.ts.map +1 -1
- package/dist/bin/build-from-local.js +6 -2
- package/dist/bin/build-from-local.js.map +1 -1
- package/dist/bin/build.d.ts +18 -5
- package/dist/bin/build.d.ts.map +1 -1
- package/dist/bin/build.js +74 -24
- package/dist/bin/build.js.map +1 -1
- package/dist/bin/diff-changes.d.ts +21 -5
- package/dist/bin/diff-changes.d.ts.map +1 -1
- package/dist/bin/diff-changes.js +41 -28
- package/dist/bin/diff-changes.js.map +1 -1
- package/dist/bin/diff-json-schema.d.ts +2 -2
- package/dist/bin/diff-json-schema.d.ts.map +1 -1
- package/dist/bin/diff-json-schema.js +1 -4
- package/dist/bin/diff-json-schema.js.map +1 -1
- package/dist/bin/git.d.ts +26 -34
- package/dist/bin/git.d.ts.map +1 -1
- package/dist/bin/git.js +60 -143
- package/dist/bin/git.js.map +1 -1
- package/dist/bin/main.js +126 -140
- package/dist/bin/main.js.map +1 -1
- package/dist/bin/notify.d.ts +35 -0
- package/dist/bin/notify.d.ts.map +1 -0
- package/dist/bin/notify.js +131 -0
- package/dist/bin/notify.js.map +1 -0
- package/dist/bin/run-tests.d.ts +21 -0
- package/dist/bin/run-tests.d.ts.map +1 -0
- package/dist/bin/run-tests.js +138 -0
- package/dist/bin/run-tests.js.map +1 -0
- package/dist/bin/slack.d.ts +2 -14
- package/dist/bin/slack.d.ts.map +1 -1
- package/dist/bin/slack.js +17 -46
- package/dist/bin/slack.js.map +1 -1
- package/dist/bin/stdin-input.d.ts +79 -0
- package/dist/bin/stdin-input.d.ts.map +1 -0
- package/dist/bin/stdin-input.js +124 -0
- package/dist/bin/stdin-input.js.map +1 -0
- package/dist/bin/test-files-glob.d.ts +18 -0
- package/dist/bin/test-files-glob.d.ts.map +1 -0
- package/dist/bin/test-files-glob.js +108 -0
- package/dist/bin/test-files-glob.js.map +1 -0
- package/dist/bin/test-report.d.ts +69 -8
- package/dist/bin/test-report.d.ts.map +1 -1
- package/dist/bin/test-report.js +76 -67
- package/dist/bin/test-report.js.map +1 -1
- package/dist/bin/types.d.ts +4 -7
- package/dist/bin/types.d.ts.map +1 -1
- package/dist/bin/utils/config/load-config.d.ts +8 -0
- package/dist/bin/utils/config/load-config.d.ts.map +1 -1
- package/dist/bin/utils/config/load-config.js +14 -1
- package/dist/bin/utils/config/load-config.js.map +1 -1
- package/dist/bin/utils/config/parser.d.ts +15 -2
- package/dist/bin/utils/config/parser.d.ts.map +1 -1
- package/dist/bin/utils/config/parser.js +29 -8
- package/dist/bin/utils/config/parser.js.map +1 -1
- package/dist/bin/utils/config/structures/grouped.js +2 -2
- package/dist/bin/utils/config/structures/grouped.js.map +1 -1
- package/dist/bin/utils/config/structures/legacy.js +1 -1
- package/dist/bin/utils/config/structures/legacy.js.map +1 -1
- package/dist/lib/extend-expect.d.ts.map +1 -1
- package/dist/lib/extend-expect.js +37 -218
- package/dist/lib/extend-expect.js.map +1 -1
- package/dist/lib/lib.d.ts +1 -5
- package/dist/lib/lib.d.ts.map +1 -1
- package/dist/lib/lib.js +19 -31
- package/dist/lib/lib.js.map +1 -1
- package/dist/lib/run-checks.d.ts +14 -0
- package/dist/lib/run-checks.d.ts.map +1 -0
- package/dist/lib/run-checks.js +82 -0
- package/dist/lib/run-checks.js.map +1 -0
- package/dist/lib/run-test-result.d.ts +3 -6
- package/dist/lib/run-test-result.d.ts.map +1 -1
- package/dist/lib/run-test-result.js +41 -54
- package/dist/lib/run-test-result.js.map +1 -1
- package/dist/test/bundle/cli-bundle.test.js +76 -56
- package/dist/test/bundle/cli-bundle.test.js.map +1 -1
- package/dist/test/bundle/token-wrapper.test.d.ts +2 -0
- package/dist/test/bundle/token-wrapper.test.d.ts.map +1 -0
- package/dist/test/bundle/token-wrapper.test.js +80 -0
- package/dist/test/bundle/token-wrapper.test.js.map +1 -0
- package/dist/test/e2e/cli-bundle.e2e.test.js +33 -68
- package/dist/test/e2e/cli-bundle.e2e.test.js.map +1 -1
- package/dist/test/e2e/git-build-release.e2e.test.d.ts +2 -0
- package/dist/test/e2e/git-build-release.e2e.test.d.ts.map +1 -0
- package/dist/test/e2e/git-build-release.e2e.test.js +87 -0
- package/dist/test/e2e/git-build-release.e2e.test.js.map +1 -0
- package/dist/test/e2e/helpers.d.ts +37 -0
- package/dist/test/e2e/helpers.d.ts.map +1 -0
- package/dist/test/e2e/helpers.js +57 -0
- package/dist/test/e2e/helpers.js.map +1 -0
- package/dist/test/unit/bin/actor-filtering.test.js +7 -0
- package/dist/test/unit/bin/actor-filtering.test.js.map +1 -1
- package/dist/test/unit/bin/actor-ids.test.d.ts +2 -0
- package/dist/test/unit/bin/actor-ids.test.d.ts.map +1 -0
- package/dist/test/unit/bin/actor-ids.test.js +40 -0
- package/dist/test/unit/bin/actor-ids.test.js.map +1 -0
- package/dist/test/unit/bin/affected-actors-cli.test.d.ts +2 -0
- package/dist/test/unit/bin/affected-actors-cli.test.d.ts.map +1 -0
- package/dist/test/unit/bin/affected-actors-cli.test.js +224 -0
- package/dist/test/unit/bin/affected-actors-cli.test.js.map +1 -0
- package/dist/test/unit/bin/affected-actors.test.d.ts +2 -0
- package/dist/test/unit/bin/affected-actors.test.d.ts.map +1 -0
- package/dist/test/unit/bin/affected-actors.test.js +153 -0
- package/dist/test/unit/bin/affected-actors.test.js.map +1 -0
- package/dist/test/unit/bin/build-cli.test.d.ts +2 -0
- package/dist/test/unit/bin/build-cli.test.d.ts.map +1 -0
- package/dist/test/unit/bin/build-cli.test.js +49 -0
- package/dist/test/unit/bin/build-cli.test.js.map +1 -0
- package/dist/test/unit/bin/build-from-local.test.js +12 -0
- package/dist/test/unit/bin/build-from-local.test.js.map +1 -1
- package/dist/test/unit/bin/build.test.js +116 -6
- package/dist/test/unit/bin/build.test.js.map +1 -1
- package/dist/test/unit/bin/compiled-cli.d.ts +6 -0
- package/dist/test/unit/bin/compiled-cli.d.ts.map +1 -0
- package/dist/test/unit/bin/compiled-cli.js +23 -0
- package/dist/test/unit/bin/compiled-cli.js.map +1 -0
- package/dist/test/unit/bin/diff-changes.test.js +168 -114
- package/dist/test/unit/bin/diff-changes.test.js.map +1 -1
- package/dist/test/unit/bin/diff.test.js +25 -28
- package/dist/test/unit/bin/diff.test.js.map +1 -1
- package/dist/test/unit/bin/git.test.js +67 -288
- package/dist/test/unit/bin/git.test.js.map +1 -1
- package/dist/test/unit/bin/notify.test.d.ts +2 -0
- package/dist/test/unit/bin/notify.test.d.ts.map +1 -0
- package/dist/test/unit/bin/notify.test.js +222 -0
- package/dist/test/unit/bin/notify.test.js.map +1 -0
- package/dist/test/unit/bin/stdin-input.test.d.ts +2 -0
- package/dist/test/unit/bin/stdin-input.test.d.ts.map +1 -0
- package/dist/test/unit/bin/stdin-input.test.js +92 -0
- package/dist/test/unit/bin/stdin-input.test.js.map +1 -0
- package/dist/test/unit/bin/test-cli.test.d.ts +2 -0
- package/dist/test/unit/bin/test-cli.test.d.ts.map +1 -0
- package/dist/test/unit/bin/test-cli.test.js +146 -0
- package/dist/test/unit/bin/test-cli.test.js.map +1 -0
- package/dist/test/unit/bin/test-files-glob.test.d.ts +2 -0
- package/dist/test/unit/bin/test-files-glob.test.d.ts.map +1 -0
- package/dist/test/unit/bin/test-files-glob.test.js +102 -0
- package/dist/test/unit/bin/test-files-glob.test.js.map +1 -0
- package/dist/test/unit/bin/test-report.test.d.ts +2 -0
- package/dist/test/unit/bin/test-report.test.d.ts.map +1 -0
- package/dist/test/unit/bin/test-report.test.js +100 -0
- package/dist/test/unit/bin/test-report.test.js.map +1 -0
- package/dist/test/unit/bin/utils/config/load-config.test.js +19 -1
- package/dist/test/unit/bin/utils/config/load-config.test.js.map +1 -1
- package/dist/test/unit/bin/utils/config/parser.test.js +36 -4
- package/dist/test/unit/bin/utils/config/parser.test.js.map +1 -1
- package/dist/test/unit/bin/utils/config/structures/grouped.test.js +6 -0
- package/dist/test/unit/bin/utils/config/structures/grouped.test.js.map +1 -1
- package/dist/test/unit/bin/utils/config/structures/legacy.test.js +1 -0
- package/dist/test/unit/bin/utils/config/structures/legacy.test.js.map +1 -1
- package/dist/test/unit/github-scripts/mask-config-secrets.test.d.ts +2 -0
- package/dist/test/unit/github-scripts/mask-config-secrets.test.d.ts.map +1 -0
- package/dist/test/unit/github-scripts/mask-config-secrets.test.js +50 -0
- package/dist/test/unit/github-scripts/mask-config-secrets.test.js.map +1 -0
- package/dist/test/unit/github-scripts/run-with-apify-tokens.test.d.ts +2 -0
- package/dist/test/unit/github-scripts/run-with-apify-tokens.test.d.ts.map +1 -0
- package/dist/test/unit/github-scripts/run-with-apify-tokens.test.js +102 -0
- package/dist/test/unit/github-scripts/run-with-apify-tokens.test.js.map +1 -0
- package/dist/test/unit/run-checks.test.d.ts +2 -0
- package/dist/test/unit/run-checks.test.d.ts.map +1 -0
- package/dist/test/unit/run-checks.test.js +62 -0
- package/dist/test/unit/run-checks.test.js.map +1 -0
- package/dist/test/unit/run-test-result.test.d.ts +2 -0
- package/dist/test/unit/run-test-result.test.d.ts.map +1 -0
- package/dist/test/unit/run-test-result.test.js +34 -0
- package/dist/test/unit/run-test-result.test.js.map +1 -0
- package/dist/test/unit/should-built-and-test.test.js +41 -38
- package/dist/test/unit/should-built-and-test.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/workflow-scripts-src/run-with-apify-tokens.d.ts +3 -0
- package/dist/workflow-scripts-src/run-with-apify-tokens.d.ts.map +1 -0
- package/dist/workflow-scripts-src/run-with-apify-tokens.js +100 -0
- package/dist/workflow-scripts-src/run-with-apify-tokens.js.map +1 -0
- package/docs/cli.md +469 -0
- package/docs/lib.md +276 -0
- package/docs/workflows.md +455 -0
- package/eslint.config.mjs +10 -1
- package/lib/extend-expect.ts +48 -258
- package/lib/lib.ts +25 -34
- package/lib/run-checks.ts +101 -0
- package/lib/run-test-result.ts +45 -55
- package/package.json +4 -2
- package/platform-tests-investigate-and-fix/skills/assess-impact/SKILL.md +42 -0
- package/platform-tests-investigate-and-fix/skills/measure-flakiness/SKILL.md +4 -2
- package/test/bundle/cli-bundle.test.ts +97 -67
- package/test/bundle/token-wrapper.test.ts +110 -0
- package/test/e2e/cli-bundle.e2e.test.ts +60 -93
- package/test/e2e/git-build-release.e2e.test.ts +113 -0
- package/test/e2e/helpers.ts +82 -0
- package/test/unit/bin/actor-filtering.test.ts +8 -0
- package/test/unit/bin/actor-ids.test.ts +47 -0
- package/test/unit/bin/affected-actors-cli.test.ts +271 -0
- package/test/unit/bin/affected-actors.test.ts +221 -0
- package/test/unit/bin/build-cli.test.ts +61 -0
- package/test/unit/bin/build-from-local.test.ts +16 -0
- package/test/unit/bin/build.test.ts +149 -5
- package/test/unit/bin/compiled-cli.ts +23 -0
- package/test/unit/bin/diff-changes.test.ts +181 -114
- package/test/unit/bin/diff.test.ts +25 -28
- package/test/unit/bin/git.test.ts +76 -361
- package/test/unit/bin/notify.test.ts +299 -0
- package/test/unit/bin/stdin-input.test.ts +120 -0
- package/test/unit/bin/test-cli.test.ts +175 -0
- package/test/unit/bin/test-files-glob.test.ts +118 -0
- package/test/unit/bin/test-report.test.ts +118 -0
- package/test/unit/bin/utils/config/load-config.test.ts +26 -1
- package/test/unit/bin/utils/config/parser.test.ts +46 -5
- package/test/unit/bin/utils/config/structures/grouped.test.ts +12 -0
- package/test/unit/bin/utils/config/structures/legacy.test.ts +1 -0
- package/test/unit/github-scripts/mask-config-secrets.test.ts +61 -0
- package/test/unit/github-scripts/run-with-apify-tokens.test.ts +115 -0
- package/test/unit/run-checks.test.ts +76 -0
- package/test/unit/run-test-result.test.ts +44 -0
- package/test/unit/should-built-and-test.test.ts +46 -39
- package/tsconfig.json +1 -1
- package/vitest.config.ts +9 -0
- package/workflow-scripts-src/run-with-apify-tokens.ts +112 -0
- package/.github/scripts/check-major-tag-refs.mjs +0 -72
- package/dist/test/unit/bin/logging.test.d.ts +0 -2
- package/dist/test/unit/bin/logging.test.d.ts.map +0 -1
- package/dist/test/unit/bin/logging.test.js +0 -43
- package/dist/test/unit/bin/logging.test.js.map +0 -1
- package/dist/test/unit/bin/slack.test.d.ts +0 -2
- package/dist/test/unit/bin/slack.test.d.ts.map +0 -1
- package/dist/test/unit/bin/slack.test.js +0 -54
- package/dist/test/unit/bin/slack.test.js.map +0 -1
- package/test/unit/bin/logging.test.ts +0 -52
- package/test/unit/bin/slack.test.ts +0 -65
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-with-apify-tokens.d.ts","sourceRoot":"","sources":["../../workflow-scripts-src/run-with-apify-tokens.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Runs apify-test-tools and passes it only secrets needed for the Actors, no other secrets are leaked.
|
|
3
|
+
//
|
|
4
|
+
// jq ... | node .github/scripts/run-with-apify-tokens.mjs apify-test-tools build --version-number 0.99
|
|
5
|
+
//
|
|
6
|
+
// The step passes the reusable workflow's whole secrets map as WORKFLOW_SECRETS. The token names
|
|
7
|
+
// come from `tokenEnvVar` in the repo's apify-test-tools.config.json, which is the same file
|
|
8
|
+
// apify-test-tools itself reads, so the two can't drift. Everything else in the secrets map (npm,
|
|
9
|
+
// Slack, GitHub, anything else the repo holds) is left out, and WORKFLOW_SECRETS itself is dropped,
|
|
10
|
+
// so the blob never reaches the CLI or anything under node_modules.
|
|
11
|
+
//
|
|
12
|
+
// Each token is looked up in the CONFIG_SECRETS secret first, a JSON object of secret name -> value,
|
|
13
|
+
// and then among the top-level secrets, which is where `secrets: inherit` puts them. The secrets the
|
|
14
|
+
// workflows read by name (NPM_TOKEN, TESTER_APIFY_TOKEN, ...) never come from CONFIG_SECRETS.
|
|
15
|
+
//
|
|
16
|
+
// The command runs without a shell, so branch names and other interpolated arguments are passed
|
|
17
|
+
// through as literal argv entries.
|
|
18
|
+
import { spawnSync } from 'node:child_process';
|
|
19
|
+
import { CONFIG_FILE_NAME, readBaseConfigFile } from '../bin/utils/config/load-config.js';
|
|
20
|
+
function fail(message) {
|
|
21
|
+
console.error(message);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
function isRecord(value) {
|
|
25
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
26
|
+
}
|
|
27
|
+
const [command, ...args] = process.argv.slice(2);
|
|
28
|
+
if (!command)
|
|
29
|
+
fail('Usage: run-with-apify-tokens.mjs <command> [args...]');
|
|
30
|
+
const { WORKFLOW_SECRETS, ...baseEnv } = process.env;
|
|
31
|
+
if (!WORKFLOW_SECRETS) {
|
|
32
|
+
fail('WORKFLOW_SECRETS is not set. Add `WORKFLOW_SECRETS: ${{ toJSON(secrets) }}` to the step env.');
|
|
33
|
+
}
|
|
34
|
+
let workflowSecrets;
|
|
35
|
+
try {
|
|
36
|
+
workflowSecrets = JSON.parse(WORKFLOW_SECRETS);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
fail(`WORKFLOW_SECRETS is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
40
|
+
}
|
|
41
|
+
const workflowSecretsMap = workflowSecrets;
|
|
42
|
+
if (!isRecord(workflowSecretsMap)) {
|
|
43
|
+
fail('WORKFLOW_SECRETS must be a JSON object of secret names and values.');
|
|
44
|
+
}
|
|
45
|
+
// Never includes the parse error: Node quotes the input in it, and the input is a secret.
|
|
46
|
+
const unpackConfigSecrets = () => {
|
|
47
|
+
const packed = workflowSecretsMap.CONFIG_SECRETS;
|
|
48
|
+
if (!packed)
|
|
49
|
+
return {};
|
|
50
|
+
if (typeof packed !== 'string')
|
|
51
|
+
fail('The CONFIG_SECRETS secret is not valid JSON.');
|
|
52
|
+
let value;
|
|
53
|
+
try {
|
|
54
|
+
value = JSON.parse(packed);
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
fail('The CONFIG_SECRETS secret is not valid JSON.');
|
|
58
|
+
}
|
|
59
|
+
if (!isRecord(value)) {
|
|
60
|
+
fail('The CONFIG_SECRETS secret must be a JSON object.');
|
|
61
|
+
}
|
|
62
|
+
return value;
|
|
63
|
+
};
|
|
64
|
+
const secrets = { ...workflowSecretsMap, ...unpackConfigSecrets() };
|
|
65
|
+
let actorConfigs;
|
|
66
|
+
try {
|
|
67
|
+
actorConfigs = await readBaseConfigFile();
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
fail(error instanceof Error ? error.message : String(error));
|
|
71
|
+
}
|
|
72
|
+
const tokenNames = [...new Set(actorConfigs.map(({ tokenEnvVar }) => tokenEnvVar))].sort();
|
|
73
|
+
// Declared but absent is a warning, not an error. A repo can carry an Actor whose token isn't
|
|
74
|
+
// configured and still build fine as long as that Actor never changes, and apify-test-tools raises
|
|
75
|
+
// a precise error naming the Actor at the point it actually needs the token.
|
|
76
|
+
const missing = tokenNames.filter((name) => !(name in secrets));
|
|
77
|
+
if (missing.length > 0) {
|
|
78
|
+
console.error(`Warning: ${CONFIG_FILE_NAME} declares ${missing.join(', ')}, but no such secret was passed ` +
|
|
79
|
+
`to this workflow, neither inside CONFIG_SECRETS nor inherited. Check the repository secrets ` +
|
|
80
|
+
`and the workflow's \`secrets:\` if a build fails on a missing token.`);
|
|
81
|
+
}
|
|
82
|
+
const present = tokenNames.filter((name) => name in secrets);
|
|
83
|
+
// Names only. The values are secrets and must never be printed, even though the runner masks
|
|
84
|
+
// registered secrets in logs.
|
|
85
|
+
console.error(`Passing ${present.length} Actor token(s) to \`${command}\`: ${present.join(', ') || '(none)'}`);
|
|
86
|
+
const env = { ...baseEnv };
|
|
87
|
+
for (const name of present) {
|
|
88
|
+
const value = secrets[name];
|
|
89
|
+
if (typeof value !== 'string')
|
|
90
|
+
fail(`Secret "${name}" must be a string.`);
|
|
91
|
+
env[name] = value;
|
|
92
|
+
}
|
|
93
|
+
const result = spawnSync(command, args, { stdio: 'inherit', env });
|
|
94
|
+
if (result.error) {
|
|
95
|
+
fail(`Failed to run \`${command}\`: ${result.error.message}`);
|
|
96
|
+
}
|
|
97
|
+
// Preserve the child's exit code so the step fails exactly when the command does. A child killed
|
|
98
|
+
// by a signal reports a null status, which would otherwise be read as success.
|
|
99
|
+
process.exit(result.status ?? 1);
|
|
100
|
+
//# sourceMappingURL=run-with-apify-tokens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-with-apify-tokens.js","sourceRoot":"","sources":["../../workflow-scripts-src/run-with-apify-tokens.ts"],"names":[],"mappings":"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"}
|
package/docs/cli.md
ADDED
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
# CLI API
|
|
2
|
+
|
|
3
|
+
The package includes the `apify-test-tools` binary. The [reusable workflows](workflows.md) call it to find changed
|
|
4
|
+
Actors, build them, and report results, and you can run it locally the same way:
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npx apify-test-tools <command> [flags]
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Run every command from the root of the Actor repository; it reads `apify-test-tools.config.json` from there.
|
|
11
|
+
Results are written to stdout as JSON, diagnostics to stderr, so commands can be piped into each other and into `jq`.
|
|
12
|
+
|
|
13
|
+
| Command | Does | Needs |
|
|
14
|
+
| --------------------------------------------------------------------- | ------------------------------------------------------- | -------------------- |
|
|
15
|
+
| [`get-affected-actors`](#finding-affected-actors-get-affected-actors) | Lists the Actors changed in a commit range | git only |
|
|
16
|
+
| [`build`](#building-actors-build) | Builds the Actors given on stdin from the pushed branch | Actor tokens |
|
|
17
|
+
| [`build-from-local`](#build-from-local-source-build-from-local) | Builds Actors from local files | Actor tokens |
|
|
18
|
+
| [`test`](#running-tests-test) | Runs the platform tests on the builds given on stdin | `TESTER_APIFY_TOKEN` |
|
|
19
|
+
| [`notify`](#notifying-notify) | Posts a test report or a release to Slack | a Slack token |
|
|
20
|
+
| [`delete-old-builds`](#deleting-old-builds-delete-old-builds) | Deletes old builds of the Actors | Actor tokens |
|
|
21
|
+
| [`get-actor-configs`](#listing-actors-get-actor-configs) | Prints the resolved config | nothing |
|
|
22
|
+
|
|
23
|
+
"Actor tokens" are the environment variables named by each Actor's `tokenEnvVar` in the config. A command only needs
|
|
24
|
+
the tokens of the Actors it touches.
|
|
25
|
+
|
|
26
|
+
## Global flags
|
|
27
|
+
|
|
28
|
+
| Flag | Default | Meaning |
|
|
29
|
+
| ------------- | ------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
30
|
+
| `--log-level` | `info` | Minimum level written to stderr: `debug`, `info`, `warn`, `error`, or `silent`. Results on stdout are unaffected |
|
|
31
|
+
|
|
32
|
+
## Selecting Actors (`--actors`, `--ignore`)
|
|
33
|
+
|
|
34
|
+
Commands that read the config take `--actors` and `--ignore`, each a list of `actorFullName`s (space-separated,
|
|
35
|
+
or the flag repeated). `--actors` keeps only the listed Actors, `--ignore` drops them. An unknown
|
|
36
|
+
name is an error rather than silently selecting nothing.
|
|
37
|
+
|
|
38
|
+
## Dry runs (`--dry-run`)
|
|
39
|
+
|
|
40
|
+
Every command that changes something (`build`, `build-from-local`, `notify`, `delete-old-builds`) takes
|
|
41
|
+
`--dry-run`. A dry run:
|
|
42
|
+
|
|
43
|
+
- **Changes nothing.** No versions or builds are created, nothing is uploaded or deleted, and no Slack message is
|
|
44
|
+
posted.
|
|
45
|
+
- **Does every read and check the real run does**, so it fails wherever the real run would: change detection, the
|
|
46
|
+
Apify token and Actor lookup, the [repository check](#repository-check), collecting and zipping local sources, and
|
|
47
|
+
the Slack token (verified with Slack's read-only `auth.test`).
|
|
48
|
+
- **Needs the same tokens as the real run.** Read-only tokens are enough, since nothing is written. A dry run can't
|
|
49
|
+
tell whether a token is also allowed to write, because the Apify API has no dry-run mode of its own.
|
|
50
|
+
- **Prints a plan, not results.** Logs start with `[DRY RUN] Would …`. `build` and `build-from-local` write
|
|
51
|
+
`{ "dryRun": true, "builds": [...] }` to stdout instead of the build array, so the plan can't be passed to tests as
|
|
52
|
+
`ACTOR_BUILDS` by mistake.
|
|
53
|
+
|
|
54
|
+
## Change detection
|
|
55
|
+
|
|
56
|
+
When a PR is opened or code is pushed, the tool determines which Actors need to be built and tested based on the
|
|
57
|
+
changed files. For each changed file, for each Actor:
|
|
58
|
+
|
|
59
|
+
1. **Sibling exclusion** — files inside another Actor's `folder` are excluded first. This prevents an Actor with
|
|
60
|
+
broad context from being triggered by changes that belong to a sibling Actor.
|
|
61
|
+
2. **CHANGELOG classification** — a `CHANGELOG.md` file is always `cosmetic` (only triggers a release build, not
|
|
62
|
+
tests), for every Actor, regardless of context or folder. (See
|
|
63
|
+
[issue #106](https://github.com/apify/apify-test-tools/issues/106).)
|
|
64
|
+
3. **Context matching** — the file must fall within one of the Actor's context paths (`dockerContextDir` from
|
|
65
|
+
`actor.json` by default, or `overrideActorContext` from config if set). Files outside every context path are
|
|
66
|
+
skipped.
|
|
67
|
+
4. **Hardcoded ignore list, context-aware** — the file path is first "hoisted" relative to the context path it
|
|
68
|
+
matched (e.g. a standalone Actor's own `.eslintrc` is checked as just `.eslintrc`, not the full
|
|
69
|
+
repo-root-relative path), then checked against repo-level dev file patterns (`.vscode/`, `.gitignore`, `.husky/`,
|
|
70
|
+
`.eslintrc`, `eslint.config.mjs`, `.prettierrc`, `.editorconfig`). Directories like `code/` or `shared/`
|
|
71
|
+
get no special treatment: to treat them as top-level, list them in `overrideActorContext`.
|
|
72
|
+
5. **`.dockerignore` filtering** — if a `.dockerignore` exists at the root of the Actor's `dockerContextDir`,
|
|
73
|
+
matching files are ignored. Patterns are resolved relative to `dockerContextDir`, matching Docker's own behavior.
|
|
74
|
+
Platform test files are the exception, see the next step.
|
|
75
|
+
**Platform test files** — a file that matches `platformTestsGlob` from the config file (a glob from the repo root,
|
|
76
|
+
default `test/platform/**`, helpers included) is a `test` change, also when `.dockerignore` lists it. This is
|
|
77
|
+
checked before the `.dockerignore` filtering. A test change puts the Actor in `testChangedActors`, so its tests
|
|
78
|
+
run, but it is neither functional nor cosmetic, so a release doesn't build it. Context matching still applies, so
|
|
79
|
+
tests outside an Actor's `dockerContextDir` (e.g. a root `test/` with standalone Actors) need to be listed in its
|
|
80
|
+
`overrideActorContext`; `get-affected-actors` logs a warning for changed test files outside every Actor's context.
|
|
81
|
+
6. **README classification** — a `README.md` file is `cosmetic` (only triggers a release build, not tests) if it
|
|
82
|
+
lives inside the Actor's own `folder`; otherwise it's ignored entirely, since it isn't documentation for this
|
|
83
|
+
Actor.
|
|
84
|
+
7. **Cosmetic JSON classification** — `.json` files inside the Actor's own `.actor/` directory with only cosmetic
|
|
85
|
+
schema changes (whitespace, key ordering) only trigger a release build.
|
|
86
|
+
8. **Functional** — everything else triggers both build and tests.
|
|
87
|
+
|
|
88
|
+
## Finding affected Actors (`get-affected-actors`)
|
|
89
|
+
|
|
90
|
+
`get-affected-actors` lists the Actors whose context changed in a commit range, using the rules in
|
|
91
|
+
[Change detection](#change-detection). It only reads git and the config file, so it needs no tokens. The range always
|
|
92
|
+
ends at the checked-out `HEAD`, so check out the branch you want to inspect first.
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# A PR: the branch's own changes, narrowed to the Actors that changed since its last validated commit
|
|
96
|
+
npx apify-test-tools get-affected-actors --base origin/master --since <sha>
|
|
97
|
+
|
|
98
|
+
# A release: everything after the last released commit
|
|
99
|
+
npx apify-test-tools get-affected-actors --since <sha>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
| Flag | Default | Meaning |
|
|
103
|
+
| ---------- | ------- | -------------------------------------------------------------------------------------- |
|
|
104
|
+
| `--base` | | Only what `HEAD` changes compared to this branch counts, like `git diff <base>...HEAD` |
|
|
105
|
+
| `--since` | | Only changes after this commit count (see below) |
|
|
106
|
+
| `--actors` | all | Only report these Actors |
|
|
107
|
+
| `--ignore` | none | Never report these Actors |
|
|
108
|
+
|
|
109
|
+
Pass `--base`, `--since`, or both:
|
|
110
|
+
|
|
111
|
+
- **`--base` only** inspects what the branch changes, the same files GitHub's "Files changed" tab shows: the diff
|
|
112
|
+
from where the branch forked from `--base`, or the last commit of `--base` it merged in. What it merged in from
|
|
113
|
+
`--base` is already validated there, so it doesn't count.
|
|
114
|
+
- **`--base` and `--since`** also inspects what changed after the branch's last validated commit, and reports only
|
|
115
|
+
the Actors that changed in both. An Actor in only one of them is already validated, by this branch or on `--base`.
|
|
116
|
+
When both changed an Actor, the changes can interact, so it is reported, but as functional only when both changes
|
|
117
|
+
are functional. A validated functional change followed by README edits is cosmetic, and so is a functional
|
|
118
|
+
change merged in from `--base` that meets only cosmetic changes of the branch. `--since` doesn't have to be on
|
|
119
|
+
the branch, so a rebase only re-checks the Actors that `--base` changed too. If `--since` is not in the local
|
|
120
|
+
history (a force-push), or it is `HEAD` (a rerun), it is ignored and the whole branch is checked.
|
|
121
|
+
- **`--since` only** inspects everything after it up to `HEAD`. It must be an ancestor of `HEAD` and fails
|
|
122
|
+
otherwise, see [Releasing Actors](#releasing-actors). If `HEAD` is `--since`, nothing is reported.
|
|
123
|
+
|
|
124
|
+
`commits`, `changedFiles` and `changelog` describe the whole range, `--base...HEAD` or `--since..HEAD`: `--since`
|
|
125
|
+
together with `--base` only narrows the Actor lists.
|
|
126
|
+
|
|
127
|
+
The output is a JSON document:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"version": 1,
|
|
132
|
+
"head": "<sha of HEAD>",
|
|
133
|
+
"commits": [{ "sha": "…", "author": "…", "date": "…", "message": "…" }],
|
|
134
|
+
"changedFiles": ["src/main.ts", "CHANGELOG.md"],
|
|
135
|
+
"changelog": "Lines added to CHANGELOG.md, or null",
|
|
136
|
+
"functionallyChangedActors": [{ "actorFullName": "john.doe/my-actor" }],
|
|
137
|
+
"cosmeticallyChangedActors": [{ "actorFullName": "john.doe/other-actor" }],
|
|
138
|
+
"testChangedActors": [{ "actorFullName": "john.doe/my-actor" }]
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`functionallyChangedActors` have at least one functional change, so they need a new build and tests.
|
|
143
|
+
`cosmeticallyChangedActors` have cosmetic changes and no functional one (see [Change detection](#change-detection)), so
|
|
144
|
+
they need a new build only when released. An Actor is in at most one of these two lists. `testChangedActors` have a
|
|
145
|
+
changed platform test (`platformTestsGlob` in the config) in their context, whatever else changed, so their tests need
|
|
146
|
+
to run. A test change alone needs no release. The PR workflow builds `functionallyChangedActors` and
|
|
147
|
+
`testChangedActors`. The release workflow builds `functionallyChangedActors` and `cosmeticallyChangedActors`.
|
|
148
|
+
|
|
149
|
+
With `--base` and `--since`, an Actor is in `testChangedActors` when its tests changed on the branch and again since
|
|
150
|
+
`--since`, the same rule as for functional changes.
|
|
151
|
+
|
|
152
|
+
## Building Actors (`build`)
|
|
153
|
+
|
|
154
|
+
`build` builds exactly the Actors it is given on stdin, from the checked-out branch as it is on the remote, and
|
|
155
|
+
prints the builds as the same JSON array `build-from-local` prints. An Actor listed twice is built once, so the lists
|
|
156
|
+
of `get-affected-actors` can be joined without removing duplicates first. A detached HEAD is an error, since there is
|
|
157
|
+
no branch to build from. It doesn't look at git history: which Actors to build is up to you, usually picked from the
|
|
158
|
+
output of [`get-affected-actors`](#finding-affected-actors-get-affected-actors).
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# A PR: the Actors whose code or platform tests the branch changed, built into the test version
|
|
162
|
+
npx apify-test-tools get-affected-actors --base origin/master \
|
|
163
|
+
| jq '{ actors: (.functionallyChangedActors + .testChangedActors) }' \
|
|
164
|
+
| npx apify-test-tools build --version-number 0.99
|
|
165
|
+
|
|
166
|
+
# A release: every Actor changed since the last release, into the version users run
|
|
167
|
+
npx apify-test-tools get-affected-actors --since <sha> \
|
|
168
|
+
| jq '{ actors: (.functionallyChangedActors + .cosmeticallyChangedActors) }' \
|
|
169
|
+
| npx apify-test-tools build --version-number default
|
|
170
|
+
|
|
171
|
+
# One Actor, whatever changed
|
|
172
|
+
echo '{ "actors": [{ "actorFullName": "john.doe/my-actor" }] }' | npx apify-test-tools build --version-number 0.99
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The input is `{ "actors": [{ "actorFullName": "<owner/name>" }] }`; other fields are ignored. An empty `actors` list
|
|
176
|
+
builds nothing and prints `[]`. Empty or invalid input is an error, so a failed command earlier in the pipe can't turn
|
|
177
|
+
into a successful run that built nothing. In GitHub Actions, give such a step `shell: bash` so the pipe also fails on
|
|
178
|
+
its own (the default shell has no `pipefail`).
|
|
179
|
+
|
|
180
|
+
| Flag | Default | Meaning |
|
|
181
|
+
| ---------------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
|
182
|
+
| `--version-number` | required | Version to build, like `0.99`, or `default` for each Actor's default version (the one its default build tag points to) |
|
|
183
|
+
| `--repo-url` | the `origin` remote | Repository to build from, see [Repository check](#repository-check) |
|
|
184
|
+
| `--require-env-vars-in-sync` | `false` | Fail unless the built version's env var names match the default version's, see [Env var check](#env-var-check) |
|
|
185
|
+
| `--dry-run` | `false` | See [Dry runs](#dry-runs---dry-run) |
|
|
186
|
+
|
|
187
|
+
The output is the build array the vitest library reads from `ACTOR_BUILDS`:
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
[{ "buildId": "...", "actorRawId": "...", "buildNumber": "...", "actorFullName": "john.doe/my-actor" }]
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
`build` never sets or changes build tags. A build gets the tag its version is configured with on the platform, so
|
|
194
|
+
building the default version moves its tag (usually `latest`) to the new build, and building a version without a
|
|
195
|
+
tag leaves every tag where it is. Builds always use the Docker cache.
|
|
196
|
+
|
|
197
|
+
### Repository check
|
|
198
|
+
|
|
199
|
+
`build` points each Actor's version at the `origin` remote. Because a build overwrites the version's Git URL,
|
|
200
|
+
building from a fork or a mirror would repoint the Actor. So, before building, the remote is compared with the Git
|
|
201
|
+
URL of the Actor's default version (the one its default build tag points to), and the command fails if they differ
|
|
202
|
+
or if the default version isn't built from a Git repository. The URL form doesn't matter
|
|
203
|
+
(`https://github.com/org/repo` equals `git@github.com:org/repo.git`).
|
|
204
|
+
|
|
205
|
+
To build from a different repository on purpose, e.g. when moving an Actor, pass `--repo-url`. That skips the check.
|
|
206
|
+
|
|
207
|
+
### Env var check
|
|
208
|
+
|
|
209
|
+
Tests should run the Actor with the same env vars users run it with. Pass `--require-env-vars-in-sync` to `build` or
|
|
210
|
+
`build-from-local` to compare the env vars of the version they build (e.g. `0.99`, or `0.98` for `build-from-local`)
|
|
211
|
+
with those of the default version, and fail if a name is missing or extra. Only names are compared, since the API
|
|
212
|
+
doesn't return secret values. A version that doesn't exist yet counts as having no env vars, so if the default
|
|
213
|
+
version has any, create the test version on the platform with the same env vars first. A dry run checks the env vars
|
|
214
|
+
too.
|
|
215
|
+
|
|
216
|
+
The CLI leaves it off by default, so a one-off build, e.g. of a debug branch, isn't held up by it.
|
|
217
|
+
[`public_pr-build-test.yaml`](workflows.md#public_pr-build-testyaml) turns it on by default; set its
|
|
218
|
+
`require-env-vars-in-sync` input to `false` to turn it off.
|
|
219
|
+
|
|
220
|
+
## Build from local source (`build-from-local`)
|
|
221
|
+
|
|
222
|
+
Builds Actors directly from your local files, with no push needed: the sources are zipped into the Actor's
|
|
223
|
+
`actor-<id>-source` key-value store and built as `TARBALL`, like `apify push`. It prints the same build array as
|
|
224
|
+
`build`.
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
APIFY_TOKEN_JOHN_DOE=<token> npx apify-test-tools build-from-local --actors john.doe/my-actor
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
| Flag | Default | Meaning |
|
|
231
|
+
| ---------------------------- | ------- | -------------------------------------------------------------------------------------------------------- |
|
|
232
|
+
| `--actors` | all | Only build these Actors. Point vitest at their tests only, for quicker feedback |
|
|
233
|
+
| `--ignore` | none | Never build these Actors |
|
|
234
|
+
| `--require-env-vars-in-sync` | `false` | Fail unless the env var names of `0.98` match the default version's, see [Env var check](#env-var-check) |
|
|
235
|
+
| `--dry-run` | `false` | Check the token, the Actor and the zipped sources without uploading or building |
|
|
236
|
+
|
|
237
|
+
## Releasing Actors
|
|
238
|
+
|
|
239
|
+
A release is three commands: find what changed since the last released commit, build those Actors into their
|
|
240
|
+
default version (the one users run), and announce it.
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
npx apify-test-tools get-affected-actors --since <sha> > affected.json
|
|
244
|
+
|
|
245
|
+
jq '{ actors: (.functionallyChangedActors + .cosmeticallyChangedActors) }' affected.json \
|
|
246
|
+
| npx apify-test-tools build --version-number default --dry-run
|
|
247
|
+
|
|
248
|
+
npx apify-test-tools notify --slack-channel "#notif-my-repo" --dry-run < affected.json
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
[`notify`](#notifying-notify) says what it posts for a release.
|
|
252
|
+
|
|
253
|
+
### The last released commit (`--since`)
|
|
254
|
+
|
|
255
|
+
The last commit that is **already released**. Everything after it, up to `HEAD`, is released. Git alone can't tell
|
|
256
|
+
which commits a push brought, and guessing wrong silently leaves Actors on old code, so it has to be passed.
|
|
257
|
+
|
|
258
|
+
The changed files come from diffing `--since` and `HEAD` directly, so this works for every merge strategy as long as
|
|
259
|
+
`--since` is the branch tip from **before** the push:
|
|
260
|
+
|
|
261
|
+
| Merge strategy | What lands on the branch | What to pass |
|
|
262
|
+
| ------------------------------ | --------------------------------- | ---------------------------------------------------------------------- |
|
|
263
|
+
| Squash and merge | 1 new commit | the push's "before" commit (`HEAD~1` also works) |
|
|
264
|
+
| Merge commit | the PR's commits + 1 merge commit | the push's "before" commit (`HEAD^1`, the first parent, also works) |
|
|
265
|
+
| Rebase and merge / direct push | N new commits | the push's "before" commit (`HEAD~1` would miss the first N-1 commits) |
|
|
266
|
+
|
|
267
|
+
On GitHub, the push's "before" commit is `${{ github.event.before }}`, which the reusable workflow passes for you.
|
|
268
|
+
On other CIs use the equivalent, e.g. `$CI_COMMIT_BEFORE_SHA` on GitLab. The checkout needs the full history
|
|
269
|
+
(`fetch-depth: 0` in `actions/checkout`) so the commit is available locally.
|
|
270
|
+
|
|
271
|
+
`get-affected-actors --since` without `--base` fails instead of guessing when:
|
|
272
|
+
|
|
273
|
+
- the commit is all zeros (GitHub sends this for a push that created the branch)
|
|
274
|
+
- the commit isn't in the local history (shallow checkout) or isn't an ancestor of `HEAD` (the branch was
|
|
275
|
+
force-pushed)
|
|
276
|
+
|
|
277
|
+
In those cases, rerun it with a `--since` you pick yourself: an ancestor of `HEAD` from before the changes you want
|
|
278
|
+
to release (for a shallow checkout, fetch the full history instead). `--actors` only narrows which of the changed
|
|
279
|
+
Actors are reported; it never forces a build, so on its own it doesn't get past these errors. If `HEAD` is
|
|
280
|
+
`--since`, nothing is reported, so nothing is built or announced.
|
|
281
|
+
|
|
282
|
+
A failed release isn't retried by the next push: that push's base commit is the failed one's head, so its changes
|
|
283
|
+
are skipped. Re-run the failed workflow run, or release the Actors manually.
|
|
284
|
+
|
|
285
|
+
## Running tests (`test`)
|
|
286
|
+
|
|
287
|
+
`test` runs the repository's own vitest (the version in its `node_modules`, so the tests keep the lib version
|
|
288
|
+
the repository locked) on the Actors it is given on stdin, and prints a report of the run for
|
|
289
|
+
[`notify`](#notifying-notify). Only the tests of those Actors run.
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
# A PR: test what was just built
|
|
293
|
+
... | npx apify-test-tools build --version-number 0.99 | npx apify-test-tools test > test-report.json
|
|
294
|
+
|
|
295
|
+
# Scheduled tests: every Actor in the config, on its default build
|
|
296
|
+
npx apify-test-tools get-actor-configs \
|
|
297
|
+
| npx apify-test-tools test --test-files-glob 'test/platform/{hourly,hourly-without-pr}/**' > test-report.json
|
|
298
|
+
|
|
299
|
+
# Only some of them
|
|
300
|
+
npx apify-test-tools get-actor-configs --actors john.doe/my-actor | npx apify-test-tools test > test-report.json
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
The input is a JSON array of Actors, each given by its full name, its raw ID or both:
|
|
304
|
+
`[{ "actorFullName": "<owner/name>" }]` or `[{ "actorRawId": "<id>" }]`. An Actor's tests run against the build given
|
|
305
|
+
with it (`buildId` and `buildNumber`, as `build` and `build-from-local` print them), or against its default build
|
|
306
|
+
without one. Other fields are ignored, so the output of [`get-actor-configs`](#listing-actors-get-actor-configs) works
|
|
307
|
+
as it is. `test` looks up the ID an Actor is listed without with `TESTER_APIFY_TOKEN`, so its tests run whichever ID
|
|
308
|
+
they name it by. An Actor the token can't see keeps only the ID it was listed with, and a warning names it, so an
|
|
309
|
+
Actor no test uses doesn't stop the run. A dry-run plan, empty or invalid input is an error, as with `build`. So is a
|
|
310
|
+
missing `TESTER_APIFY_TOKEN`: without it the lib skips every platform test, and the run would pass having tested
|
|
311
|
+
nothing. `test` passes the Actors to vitest as `ACTOR_BUILDS`, in place of any
|
|
312
|
+
`ACTOR_BUILDS` in its own environment.
|
|
313
|
+
|
|
314
|
+
It runs vitest with `--maxConcurrency=20 --fileParallelism --maxWorkers=100`, since platform tests mostly wait on
|
|
315
|
+
Actor runs rather than the CPU, and with the default reporter plus the JSON one the report is read from. These
|
|
316
|
+
replace any `reporters` in the repository's vitest config; add more with `--reporter`, e.g. `github-actions` to
|
|
317
|
+
annotate the failing tests in a GitHub Actions run. It takes no other vitest options; for those, e.g. `-t` to run one
|
|
318
|
+
test by name, run vitest directly with the builds in `ACTOR_BUILDS` (see
|
|
319
|
+
[Running tests locally](lib.md#running-tests-locally)).
|
|
320
|
+
|
|
321
|
+
| Flag | Default | Meaning |
|
|
322
|
+
| ---------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
323
|
+
| `--test-files-glob` | `test/platform/**` | Glob from the repo root of the test files to run, see below |
|
|
324
|
+
| `--vitest-output-file` | | Also keep vitest's own JSON report there, e.g. to upload it |
|
|
325
|
+
| `--reporter` | | [Vitest reporter](https://vitest.dev/guide/reporters) to add to `default` and `json`, e.g. `github-actions`. Repeat it for more |
|
|
326
|
+
|
|
327
|
+
`test` takes no test paths as arguments, only `--test-files-glob`. The glob is read the same way as
|
|
328
|
+
`platformTestsGlob` in the config file. Vitest filters are parts of a file path, not globs, so `test` finds the files
|
|
329
|
+
the glob matches and passes vitest as few paths as it can: each folder whose files all match, with a trailing `/`, and
|
|
330
|
+
the other matched files one by one. `test/platform/{daily,hourly}/**` becomes two folders however many tests they
|
|
331
|
+
hold, so the command line stays short. Vitest still applies its own `include` and `exclude`, so helper files in the
|
|
332
|
+
glob run nothing. A glob that matches no file is an error, because vitest without filters would run every test of the
|
|
333
|
+
repo. Quote the glob, so the shell doesn't expand it.
|
|
334
|
+
|
|
335
|
+
Vitest's own output goes to stderr, followed by a summary that lists every test with the link to its run. Stdout
|
|
336
|
+
gets only the report:
|
|
337
|
+
|
|
338
|
+
```json
|
|
339
|
+
{
|
|
340
|
+
"kind": "test-report",
|
|
341
|
+
"version": 1,
|
|
342
|
+
"success": false,
|
|
343
|
+
"summary": { "total": 3, "passed": 1, "failed": 1, "skipped": 1 },
|
|
344
|
+
"tests": [
|
|
345
|
+
{
|
|
346
|
+
"name": "john.doe/my-actor: finishes",
|
|
347
|
+
"file": "test/platform/my-actor.test.ts",
|
|
348
|
+
"status": "failed",
|
|
349
|
+
"durationMs": 61234,
|
|
350
|
+
"failureMessages": ["AssertionError: expected 'FAILED' to be 'SUCCEEDED'"],
|
|
351
|
+
"run": { "actorId": "john.doe/my-actor", "runId": "…", "runLink": "https://console.apify.com/view/runs/…" }
|
|
352
|
+
}
|
|
353
|
+
],
|
|
354
|
+
"errors": ["test/platform/other.test.ts: Cannot find package 'foo'"]
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
`failureMessages` keeps the first line of each failure; diffs and stack traces are in the vitest output. `run` is
|
|
359
|
+
`null` for a test that started no run. `errors` lists what failed outside of any test: a test file that failed to
|
|
360
|
+
load, or vitest exiting without a report. `test` exits with 1 whenever `success` is false, and prints the report
|
|
361
|
+
anyway, so `notify` still hears about the failure.
|
|
362
|
+
|
|
363
|
+
## Notifying (`notify`)
|
|
364
|
+
|
|
365
|
+
`notify` tells one target about what it reads on stdin: a test run, as [`test`](#running-tests-test) reports it,
|
|
366
|
+
or a release, as [`get-affected-actors`](#finding-affected-actors-get-affected-actors) reports it. It tells the two
|
|
367
|
+
apart by the report's `kind` and the release's `commits`, so either can be piped in as it is. Slack is the only target for now. To post to more
|
|
368
|
+
places, call it once for each.
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
# A test run: posts only when the tests failed, the failure counts and the first failure, linked to its run,
|
|
372
|
+
# with the other failures in the message's thread
|
|
373
|
+
npx apify-test-tools notify --slack-channel '#notif-my-repo' < test-report.json
|
|
374
|
+
npx apify-test-tools notify --slack-channel '#my-team' < test-report.json
|
|
375
|
+
|
|
376
|
+
# Or straight from test. With `set -o pipefail` (`shell: bash` in GitHub Actions), failed tests still fail the pipe
|
|
377
|
+
npx apify-test-tools get-actor-configs | npx apify-test-tools test | npx apify-test-tools notify --slack-channel '#notif-my-repo'
|
|
378
|
+
|
|
379
|
+
# A release, see Releasing Actors
|
|
380
|
+
npx apify-test-tools get-affected-actors --since <sha> | npx apify-test-tools notify --slack-channel '#notif-my-repo'
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
| Flag | Input | Default | Meaning |
|
|
384
|
+
| ----------------- | ------- | ------------------- | ----------------------------------------------------------------- |
|
|
385
|
+
| `--slack-channel` | both | | Slack channel to post to |
|
|
386
|
+
| `--on` | tests | `failure` | `failure` posts only when the tests failed, `always` on every run |
|
|
387
|
+
| `--title` | tests | `-` | What the message calls the run, e.g. the CI workflow name |
|
|
388
|
+
| `--job-url` | tests | | Link to the CI job, included in the message |
|
|
389
|
+
| `--repo-url` | release | the `origin` remote | The repository the release is named after and its commits link to |
|
|
390
|
+
|
|
391
|
+
A flag the input has no use for, e.g. `--repo-url` with a test report, is an error rather than ignored. Both kinds
|
|
392
|
+
of notification post with `SLACK_BOT_TOKEN`.
|
|
393
|
+
|
|
394
|
+
Without a target, `notify` posts nothing and needs no token. With one, it checks the token on every run, also when
|
|
395
|
+
there is nothing to post, so a broken token shows up on a green run rather than on the day tests fail. A release
|
|
396
|
+
with no new commits is the exception: there is nothing to announce, so it needs no token either.
|
|
397
|
+
|
|
398
|
+
For a release, `notify` posts the changelog additions, then the commits, oldest first. Each commit is its title (cut
|
|
399
|
+
at 200 characters) linked to its page on GitHub, and its author. A merge commit or a squash merge is one commit; a
|
|
400
|
+
rebase merge lists every commit it brought. A repository hosted elsewhere gets the titles without links. The release
|
|
401
|
+
is named after the `origin` remote (or `--repo-url`) and the author of the newest commit. Nothing is posted when there
|
|
402
|
+
are no new commits:
|
|
403
|
+
|
|
404
|
+
```text
|
|
405
|
+
*my-repo* – New release (by Jane Doe):
|
|
406
|
+
|
|
407
|
+
- Fixed pagination on the search page
|
|
408
|
+
|
|
409
|
+
*Commits*:
|
|
410
|
+
1. <https://github.com/my-org/my-repo/commit/1a2b3c…|fix: pagination on the search page> – Jane Doe
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
## Deleting old builds (`delete-old-builds`)
|
|
414
|
+
|
|
415
|
+
Deletes builds older than 30 days of every selected Actor. It never deletes the default build, or a build tagged
|
|
416
|
+
`latest`, `version…`, `v-…` or `v0`–`v9…`. A build tagged `devel` is kept for only 7 days.
|
|
417
|
+
|
|
418
|
+
| Flag | Default | Meaning |
|
|
419
|
+
| ----------- | ------- | ----------------------------------------------------------- |
|
|
420
|
+
| `--actors` | all | Only these Actors |
|
|
421
|
+
| `--ignore` | none | Never these Actors |
|
|
422
|
+
| `--dry-run` | `false` | List the builds that would be deleted without deleting them |
|
|
423
|
+
|
|
424
|
+
## Listing Actors (`get-actor-configs`)
|
|
425
|
+
|
|
426
|
+
Prints the [config](../README.md#config-file) as the tool resolves it: one entry per Actor, with the group's values
|
|
427
|
+
applied and `actor.json` read. Takes `--actors` and `--ignore`. Useful to check a config change.
|
|
428
|
+
|
|
429
|
+
## Running locally
|
|
430
|
+
|
|
431
|
+
Running the tests locally is useful when you only want to update the testing code in `test/`, because you can
|
|
432
|
+
iterate on it without pushing new code to the remote. If you only change tests, skip the builds entirely and run
|
|
433
|
+
them against the default builds, see [Running tests locally](lib.md#running-tests-locally).
|
|
434
|
+
|
|
435
|
+
To test changed Actor source, you need builds of it. The quickest way is
|
|
436
|
+
[`build-from-local`](#build-from-local-source-build-from-local), which needs no push:
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
APIFY_TOKEN_JOHN_DOE=apify_api_xxx \
|
|
440
|
+
npx apify-test-tools build-from-local --actors john.doe/my-actor > builds.json
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
To build from git, like CI does:
|
|
444
|
+
|
|
445
|
+
1. Switch to a dummy branch that you will push and can later delete
|
|
446
|
+
2. `npm i apify-test-tools@latest -D`
|
|
447
|
+
3. Push your code (changes you want to test)
|
|
448
|
+
4. Build the Actors on Apify (with your new code)
|
|
449
|
+
5. Run tests against those builds. You can change tests and run on the same builds.
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
npx apify-test-tools get-affected-actors --base origin/master \
|
|
453
|
+
| jq '{ actors: (.functionallyChangedActors + .testChangedActors) }' \
|
|
454
|
+
| APIFY_TOKEN_JOHN_DOE=apify_api_xxx npx apify-test-tools build --version-number 0.99 > builds.json
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
Run it with your dummy branch checked out: it builds the Actors that branch changed functionally, from the branch as
|
|
458
|
+
it is on the remote, into the test version `0.99`. Add `--dry-run` to `build` to print the plan (the version and Git
|
|
459
|
+
URL each Actor would be built from) first, and update `--base` to the branch you compare against. Tests only run for
|
|
460
|
+
Actors in `ACTOR_BUILDS`, so the `jq` filter also builds the Actors whose platform tests changed.
|
|
461
|
+
|
|
462
|
+
If you want to test against existing builds instead, skip the build and write the build array by hand, only for the
|
|
463
|
+
Actors you need to test.
|
|
464
|
+
|
|
465
|
+
Then run the tests against the builds with [`test`](#running-tests-test), as often as you like:
|
|
466
|
+
|
|
467
|
+
```bash
|
|
468
|
+
TESTER_APIFY_TOKEN=apify_api_yyy npx apify-test-tools test < builds.json
|
|
469
|
+
```
|