apify-test-tools 0.10.2-beta.0 → 0.10.2-beta.10

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.
Files changed (187) hide show
  1. package/.gitattributes +2 -0
  2. package/.github/actions/checkout-restore-dependencies/action.yaml +64 -27
  3. package/.github/cli/apify-test-tools.mjs +360 -0
  4. package/.github/scripts/check-major-tag-refs.mjs +1 -1
  5. package/.github/scripts/mask-config-secrets.sh +17 -0
  6. package/.github/scripts/run-with-apify-tokens.mjs +37 -12
  7. package/.github/workflows/_check_code.yaml +25 -0
  8. package/.github/workflows/_move_major_tag.yaml +3 -81
  9. package/.github/workflows/_tests.yaml +34 -0
  10. package/.github/workflows/_update_release_metadata.yaml +0 -12
  11. package/.github/workflows/manual_move_major_tag.yaml +3 -3
  12. package/.github/workflows/manual_release_stable.yaml +3 -13
  13. package/.github/workflows/on_master.yaml +9 -5
  14. package/.github/workflows/on_pull_request.yaml +3 -48
  15. package/.github/workflows/public_platform-tests-claude-investigate-and-fix.yaml +13 -2
  16. package/.github/workflows/public_platform-tests.yaml +24 -1
  17. package/.github/workflows/public_pr-build-test.yaml +62 -49
  18. package/.github/workflows/public_push-build-latest.yaml +41 -8
  19. package/.husky/pre-commit +5 -0
  20. package/.prettierignore +3 -0
  21. package/CHANGELOG.md +17 -0
  22. package/CONTRIBUTING.md +105 -21
  23. package/README.md +218 -597
  24. package/bin/affected-actors.ts +198 -0
  25. package/bin/build-from-local.ts +65 -13
  26. package/bin/build.ts +123 -41
  27. package/bin/diff-changes.ts +55 -25
  28. package/bin/diff-json-schema.ts +5 -6
  29. package/bin/git.ts +69 -99
  30. package/bin/main.ts +96 -122
  31. package/bin/slack.ts +43 -10
  32. package/bin/stdin-input.ts +65 -0
  33. package/bin/test-report.ts +6 -9
  34. package/bin/types.ts +16 -0
  35. package/dist/bin/affected-actors.d.ts +46 -0
  36. package/dist/bin/affected-actors.d.ts.map +1 -0
  37. package/dist/bin/affected-actors.js +135 -0
  38. package/dist/bin/affected-actors.js.map +1 -0
  39. package/dist/bin/build-from-local.d.ts +12 -3
  40. package/dist/bin/build-from-local.d.ts.map +1 -1
  41. package/dist/bin/build-from-local.js +34 -12
  42. package/dist/bin/build-from-local.js.map +1 -1
  43. package/dist/bin/build.d.ts +30 -7
  44. package/dist/bin/build.d.ts.map +1 -1
  45. package/dist/bin/build.js +85 -26
  46. package/dist/bin/build.js.map +1 -1
  47. package/dist/bin/diff-changes.d.ts +12 -4
  48. package/dist/bin/diff-changes.d.ts.map +1 -1
  49. package/dist/bin/diff-changes.js +31 -20
  50. package/dist/bin/diff-changes.js.map +1 -1
  51. package/dist/bin/diff-json-schema.d.ts +2 -2
  52. package/dist/bin/diff-json-schema.d.ts.map +1 -1
  53. package/dist/bin/diff-json-schema.js +1 -4
  54. package/dist/bin/diff-json-schema.js.map +1 -1
  55. package/dist/bin/git.d.ts +23 -21
  56. package/dist/bin/git.d.ts.map +1 -1
  57. package/dist/bin/git.js +60 -83
  58. package/dist/bin/git.js.map +1 -1
  59. package/dist/bin/main.js +82 -93
  60. package/dist/bin/main.js.map +1 -1
  61. package/dist/bin/slack.d.ts +14 -4
  62. package/dist/bin/slack.d.ts.map +1 -1
  63. package/dist/bin/slack.js +39 -6
  64. package/dist/bin/slack.js.map +1 -1
  65. package/dist/bin/stdin-input.d.ts +17 -0
  66. package/dist/bin/stdin-input.d.ts.map +1 -0
  67. package/dist/bin/stdin-input.js +54 -0
  68. package/dist/bin/stdin-input.js.map +1 -0
  69. package/dist/bin/test-report.d.ts.map +1 -1
  70. package/dist/bin/test-report.js +6 -8
  71. package/dist/bin/test-report.js.map +1 -1
  72. package/dist/bin/types.d.ts +14 -0
  73. package/dist/bin/types.d.ts.map +1 -1
  74. package/dist/lib/extend-expect.d.ts.map +1 -1
  75. package/dist/lib/extend-expect.js +37 -218
  76. package/dist/lib/extend-expect.js.map +1 -1
  77. package/dist/lib/lib.d.ts +1 -2
  78. package/dist/lib/lib.d.ts.map +1 -1
  79. package/dist/lib/lib.js +15 -22
  80. package/dist/lib/lib.js.map +1 -1
  81. package/dist/lib/run-checks.d.ts +14 -0
  82. package/dist/lib/run-checks.d.ts.map +1 -0
  83. package/dist/lib/run-checks.js +82 -0
  84. package/dist/lib/run-checks.js.map +1 -0
  85. package/dist/lib/run-test-result.d.ts +3 -6
  86. package/dist/lib/run-test-result.d.ts.map +1 -1
  87. package/dist/lib/run-test-result.js +41 -54
  88. package/dist/lib/run-test-result.js.map +1 -1
  89. package/dist/test/bundle/cli-bundle.test.d.ts +2 -0
  90. package/dist/test/bundle/cli-bundle.test.d.ts.map +1 -0
  91. package/dist/test/bundle/cli-bundle.test.js +190 -0
  92. package/dist/test/bundle/cli-bundle.test.js.map +1 -0
  93. package/dist/test/e2e/cli-bundle.e2e.test.d.ts +2 -0
  94. package/dist/test/e2e/cli-bundle.e2e.test.d.ts.map +1 -0
  95. package/dist/test/e2e/cli-bundle.e2e.test.js +138 -0
  96. package/dist/test/e2e/cli-bundle.e2e.test.js.map +1 -0
  97. package/dist/test/e2e/git-build-release.e2e.test.d.ts +2 -0
  98. package/dist/test/e2e/git-build-release.e2e.test.d.ts.map +1 -0
  99. package/dist/test/e2e/git-build-release.e2e.test.js +87 -0
  100. package/dist/test/e2e/git-build-release.e2e.test.js.map +1 -0
  101. package/dist/test/e2e/helpers.d.ts +37 -0
  102. package/dist/test/e2e/helpers.d.ts.map +1 -0
  103. package/dist/test/e2e/helpers.js +57 -0
  104. package/dist/test/e2e/helpers.js.map +1 -0
  105. package/dist/test/unit/bin/affected-actors-cli.test.d.ts +2 -0
  106. package/dist/test/unit/bin/affected-actors-cli.test.d.ts.map +1 -0
  107. package/dist/test/unit/bin/affected-actors-cli.test.js +167 -0
  108. package/dist/test/unit/bin/affected-actors-cli.test.js.map +1 -0
  109. package/dist/test/unit/bin/affected-actors.test.d.ts +2 -0
  110. package/dist/test/unit/bin/affected-actors.test.d.ts.map +1 -0
  111. package/dist/test/unit/bin/affected-actors.test.js +141 -0
  112. package/dist/test/unit/bin/affected-actors.test.js.map +1 -0
  113. package/dist/test/unit/bin/build-cli.test.d.ts +2 -0
  114. package/dist/test/unit/bin/build-cli.test.d.ts.map +1 -0
  115. package/dist/test/unit/bin/build-cli.test.js +44 -0
  116. package/dist/test/unit/bin/build-cli.test.js.map +1 -0
  117. package/dist/test/unit/bin/build-from-local.test.js +65 -1
  118. package/dist/test/unit/bin/build-from-local.test.js.map +1 -1
  119. package/dist/test/unit/bin/build.test.js +223 -3
  120. package/dist/test/unit/bin/build.test.js.map +1 -1
  121. package/dist/test/unit/bin/compiled-cli.d.ts +6 -0
  122. package/dist/test/unit/bin/compiled-cli.d.ts.map +1 -0
  123. package/dist/test/unit/bin/compiled-cli.js +16 -0
  124. package/dist/test/unit/bin/compiled-cli.js.map +1 -0
  125. package/dist/test/unit/bin/diff-changes.test.js +205 -85
  126. package/dist/test/unit/bin/diff-changes.test.js.map +1 -1
  127. package/dist/test/unit/bin/diff.test.js +25 -28
  128. package/dist/test/unit/bin/diff.test.js.map +1 -1
  129. package/dist/test/unit/bin/git.test.js +69 -152
  130. package/dist/test/unit/bin/git.test.js.map +1 -1
  131. package/dist/test/unit/bin/slack.test.d.ts +2 -0
  132. package/dist/test/unit/bin/slack.test.d.ts.map +1 -0
  133. package/dist/test/unit/bin/slack.test.js +71 -0
  134. package/dist/test/unit/bin/slack.test.js.map +1 -0
  135. package/dist/test/unit/bin/stdin-input.test.d.ts +2 -0
  136. package/dist/test/unit/bin/stdin-input.test.d.ts.map +1 -0
  137. package/dist/test/unit/bin/stdin-input.test.js +50 -0
  138. package/dist/test/unit/bin/stdin-input.test.js.map +1 -0
  139. package/dist/test/unit/github-scripts/mask-config-secrets.test.d.ts +2 -0
  140. package/dist/test/unit/github-scripts/mask-config-secrets.test.d.ts.map +1 -0
  141. package/dist/test/unit/github-scripts/mask-config-secrets.test.js +50 -0
  142. package/dist/test/unit/github-scripts/mask-config-secrets.test.js.map +1 -0
  143. package/dist/test/unit/github-scripts/run-with-apify-tokens.test.d.ts +2 -0
  144. package/dist/test/unit/github-scripts/run-with-apify-tokens.test.d.ts.map +1 -0
  145. package/dist/test/unit/github-scripts/run-with-apify-tokens.test.js +102 -0
  146. package/dist/test/unit/github-scripts/run-with-apify-tokens.test.js.map +1 -0
  147. package/dist/test/unit/run-checks.test.d.ts +2 -0
  148. package/dist/test/unit/run-checks.test.d.ts.map +1 -0
  149. package/dist/test/unit/run-checks.test.js +62 -0
  150. package/dist/test/unit/run-checks.test.js.map +1 -0
  151. package/dist/test/unit/run-test-result.test.d.ts +2 -0
  152. package/dist/test/unit/run-test-result.test.d.ts.map +1 -0
  153. package/dist/test/unit/run-test-result.test.js +34 -0
  154. package/dist/test/unit/run-test-result.test.js.map +1 -0
  155. package/dist/test/unit/should-built-and-test.test.js +41 -38
  156. package/dist/test/unit/should-built-and-test.test.js.map +1 -1
  157. package/dist/tsconfig.tsbuildinfo +1 -1
  158. package/docs/cli.md +373 -0
  159. package/docs/lib.md +271 -0
  160. package/docs/workflows.md +367 -0
  161. package/lib/extend-expect.ts +48 -258
  162. package/lib/lib.ts +24 -28
  163. package/lib/run-checks.ts +101 -0
  164. package/lib/run-test-result.ts +45 -55
  165. package/package.json +15 -3
  166. package/test/bundle/cli-bundle.test.ts +235 -0
  167. package/test/e2e/cli-bundle.e2e.test.ts +207 -0
  168. package/test/e2e/git-build-release.e2e.test.ts +113 -0
  169. package/test/e2e/helpers.ts +82 -0
  170. package/test/unit/bin/affected-actors-cli.test.ts +201 -0
  171. package/test/unit/bin/affected-actors.test.ts +182 -0
  172. package/test/unit/bin/build-cli.test.ts +55 -0
  173. package/test/unit/bin/build-from-local.test.ts +71 -0
  174. package/test/unit/bin/build.test.ts +279 -3
  175. package/test/unit/bin/compiled-cli.ts +17 -0
  176. package/test/unit/bin/diff-changes.test.ts +229 -85
  177. package/test/unit/bin/diff.test.ts +25 -28
  178. package/test/unit/bin/git.test.ts +85 -176
  179. package/test/unit/bin/slack.test.ts +84 -0
  180. package/test/unit/bin/stdin-input.test.ts +61 -0
  181. package/test/unit/github-scripts/mask-config-secrets.test.ts +61 -0
  182. package/test/unit/github-scripts/run-with-apify-tokens.test.ts +115 -0
  183. package/test/unit/run-checks.test.ts +76 -0
  184. package/test/unit/run-test-result.test.ts +44 -0
  185. package/test/unit/should-built-and-test.test.ts +46 -39
  186. package/.github/scripts/check-package-version-bump.mjs +0 -74
  187. package/.github/workflows-package-version +0 -1
@@ -0,0 +1,367 @@
1
+ # Workflow API
2
+
3
+ Ready-made GitHub Actions workflows built on the [CLI](cli.md) and the [vitest library](lib.md). They are the
4
+ `public_`-prefixed files in this repo's `.github/workflows`. Call them from a job with `uses:` and pass the secrets
5
+ the workflow lists, see [Secrets](#secrets):
6
+
7
+ ```yaml
8
+ jobs:
9
+ myJob:
10
+ uses: apify/apify-test-tools/.github/workflows/<workflow>.yaml@workflows-v0
11
+ with:
12
+ # inputs, if any
13
+ secrets:
14
+ # the secrets the workflow lists
15
+ ```
16
+
17
+ Always reference them at the `@workflows-v0` major tag, never at `@master` — see [Versioning](#versioning).
18
+
19
+ They only run on GitHub Actions. On another CI platform, build the same steps with the [CLI](cli.md); each workflow
20
+ The build, release and test workflows below list the CLI commands they run.
21
+
22
+ | Workflow | Typical trigger | What it does |
23
+ | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------- | -------------------------------------------------------------------------------- |
24
+ | [`public_pr-build-test.yaml`](#public_pr-build-testyaml) | `pull_request` | Builds the Actors a PR changes into `0.99` and tests them, plus static checks |
25
+ | [`public_push-build-latest.yaml`](#public_push-build-latestyaml) | `push` to `master` | Builds the changed Actors into their default version and announces the release |
26
+ | [`public_platform-tests.yaml`](#public_platform-testsyaml) | `schedule` | Runs platform tests against the released builds and reports results to Slack |
27
+ | [`public_review.yaml`](#public_reviewyaml) | `pull_request` (labeled) | Claude reviews the PR against the shared guidelines |
28
+ | [`public_claude.yaml`](#public_claudeyaml) | issue and PR comments, issue labels | Claude acts on `@claude` mentions |
29
+ | [`public_platform-tests-claude-investigate-and-fix.yaml`](#public_platform-tests-claude-investigate-and-fixyaml) | after a failed platform test job | Claude investigates a failing platform test, opens an issue, and tries to fix it |
30
+
31
+ All of them run on `ubuntu-latest` with Node.js 24. The ones that need the repo's dependencies install them with
32
+ `npm ci`, or with pnpm when the repo has a `pnpm-lock.yaml` and no `package-lock.json`.
33
+
34
+ ## `public_pr-build-test.yaml`
35
+
36
+ Validates a pull request. It runs two jobs in parallel.
37
+
38
+ **`platformTest`** builds and tests the Actors the PR changes:
39
+
40
+ 1. Finds the affected Actors with [`get-affected-actors`](cli.md#finding-affected-actors-get-affected-actors),
41
+ comparing the PR branch with its base branch. Changed files under `test/platform/**` count even when
42
+ `.dockerignore` lists them.
43
+ 2. Builds the functionally changed Actors into the test version `0.99` with [`build`](cli.md#building-actors-build).
44
+ Cosmetic-only changes (README, CHANGELOG, schema formatting) need no tests, so they're not built.
45
+ 3. Runs `npx vitest ./test/platform/<test-files-glob>` with those builds in `ACTOR_BUILDS`, so only the tests of
46
+ the built Actors run.
47
+ 4. On success, caches the tested commit as the "last validated commit". The next push to the PR then only builds
48
+ and tests the Actors that changed since it (see `--since` in
49
+ [`get-affected-actors`](cli.md#finding-affected-actors-get-affected-actors)).
50
+
51
+ **`unitTest`** runs static checks against the repo, using the repo's own scripts where they exist:
52
+
53
+ | Check | Runs |
54
+ | -------------- | ------------------------------------------------------------------------------------------- |
55
+ | TypeScript | `npm run build-check` if the script exists, else `npx tsc --noEmit` |
56
+ | Lint | `npm run lint` |
57
+ | Test | `npm test` |
58
+ | Formatter | `npm run format:check` if it exists, else `npx prettier --check .` if prettier is installed |
59
+ | Unused exports | `npm run check-unused` if it exists |
60
+
61
+ In a repo whose Actors aren't written in JavaScript or TypeScript, define the `build-check`, `lint` and `test`
62
+ scripts, e.g. to run your language's own checks: without them, the TypeScript, Lint and Test checks fail.
63
+
64
+ | Input | Type | Default | Description |
65
+ | -------------------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------ |
66
+ | `skip-platform-tests` | boolean | `false` | Skip the `platformTest` job and run the static checks only |
67
+ | `test-files-glob` | string | `''` | Which tests to run, relative to `test/platform`. Empty runs everything in it |
68
+ | `require-env-vars-in-sync` | boolean | `true` | Fail the build unless the env var names of `0.99` match the default version's, see [Env var check](cli.md#env-var-check) |
69
+
70
+ Secrets: `TESTER_APIFY_TOKEN`, the Actor tokens in `CONFIG_SECRETS`, and optionally `NPM_TOKEN`. With
71
+ `skip-platform-tests`, only `NPM_TOKEN`.
72
+
73
+ A new push to the same PR cancels the run in progress.
74
+
75
+ ```yaml
76
+ name: PR Test
77
+
78
+ on:
79
+ pull_request:
80
+ branches: [master]
81
+
82
+ jobs:
83
+ buildDevelAndTest:
84
+ uses: apify/apify-test-tools/.github/workflows/public_pr-build-test.yaml@workflows-v0
85
+ secrets:
86
+ TESTER_APIFY_TOKEN: ${{ secrets.TESTER_APIFY_TOKEN }}
87
+ # One entry per secret apify-test-tools.config.json names, today each `tokenEnvVar`
88
+ CONFIG_SECRETS: |
89
+ {
90
+ "APIFY_TOKEN_MYTEAM": "${{ secrets.APIFY_TOKEN_MYTEAM }}",
91
+ "APIFY_TOKEN_PARTNER": "${{ secrets.APIFY_TOKEN_PARTNER }}"
92
+ }
93
+ ```
94
+
95
+ ## `public_push-build-latest.yaml`
96
+
97
+ Releases the Actors a push changed. Skipped when the head commit message contains `[skip ci]` or
98
+ `[skip platform-test]`. It runs one step per CLI command:
99
+
100
+ 1. `get-affected-actors --since ${{ github.event.before }}` finds everything the push changed. See
101
+ [Releasing Actors](cli.md#releasing-actors) for how the released range is determined.
102
+ 2. `build --version-number default` builds both the functionally and the cosmetically changed Actors into their
103
+ default version, the one users run.
104
+ 3. `notify-release` posts the changelog additions to `#delivery-public-actors`, and the commits and changed files to
105
+ the report channel. It posts nothing when the push brought no new commits.
106
+ 4. `delete-old-builds` deletes old builds of every Actor in the config (see
107
+ [`delete-old-builds`](cli.md#deleting-old-builds-delete-old-builds)).
108
+
109
+ | Input | Type | Default | Description |
110
+ | ---------------------- | ------ | ------- | ------------------------------------------------------------- |
111
+ | `report-slack-channel` | string | `''` | Slack channel for the report. Empty uses `#notif-<repo-name>` |
112
+
113
+ Secrets: `SLACK_TOKEN_RELEASES_BOT`, the Actor tokens in `CONFIG_SECRETS`, and optionally `NPM_TOKEN`.
114
+
115
+ A failed release isn't retried by the next push: that push's "before" commit is the failed one's head, so its changes
116
+ are skipped. Re-run the failed workflow run, or release the Actors manually.
117
+
118
+ ```yaml
119
+ name: Release latest
120
+
121
+ on:
122
+ push:
123
+ branches: [master]
124
+
125
+ jobs:
126
+ buildLatest:
127
+ uses: apify/apify-test-tools/.github/workflows/public_push-build-latest.yaml@workflows-v0
128
+ secrets:
129
+ SLACK_TOKEN_RELEASES_BOT: ${{ secrets.SLACK_TOKEN_RELEASES_BOT }}
130
+ # One entry per secret apify-test-tools.config.json names, today each `tokenEnvVar`
131
+ CONFIG_SECRETS: |
132
+ {
133
+ "APIFY_TOKEN_MYTEAM": "${{ secrets.APIFY_TOKEN_MYTEAM }}",
134
+ "APIFY_TOKEN_PARTNER": "${{ secrets.APIFY_TOKEN_PARTNER }}"
135
+ }
136
+ ```
137
+
138
+ ## `public_platform-tests.yaml`
139
+
140
+ Runs the platform tests against the Actors' current default builds, with `RUN_ALL_PLATFORM_TESTS=1` so every test
141
+ runs, not only those of built Actors. It then reports the results to Slack with
142
+ [`report-tests`](cli.md#reporting-test-results-report-tests) and uploads the vitest JSON report as the
143
+ `vitest-results` artifact. Runs only on `master` or `main`.
144
+
145
+ | Input | Type | Default | Description |
146
+ | ---------------------- | ------ | ------- | ---------------------------------------------------------------------------- |
147
+ | `test-files-glob` | string | `''` | Which tests to run, relative to `test/platform`. Empty runs everything in it |
148
+ | `subtest` | string | `''` | Deprecated, use `test-files-glob` |
149
+ | `report-slack-channel` | string | `''` | Slack channel for the results. Empty uses `#notif-<repo-name>` |
150
+
151
+ Secrets: `TESTER_APIFY_TOKEN` (required), `SLACK_TOKEN_TESTS_BOT`, and optionally `NPM_TOKEN`.
152
+
153
+ How often to run which tests is up to you. For example, every test once a day:
154
+
155
+ ```yaml
156
+ name: Platform tests - Daily
157
+
158
+ on:
159
+ schedule:
160
+ # Runs at 00:00 UTC every day
161
+ - cron: '0 0 * * *'
162
+ workflow_dispatch:
163
+
164
+ jobs:
165
+ platformTestsDaily:
166
+ uses: apify/apify-test-tools/.github/workflows/public_platform-tests.yaml@workflows-v0
167
+ secrets:
168
+ TESTER_APIFY_TOKEN: ${{ secrets.TESTER_APIFY_TOKEN }}
169
+ SLACK_TOKEN_TESTS_BOT: ${{ secrets.SLACK_TOKEN_TESTS_BOT }}
170
+ ```
171
+
172
+ and a few critical tests, kept in e.g. `test/platform/hourly`, every hour:
173
+
174
+ ```yaml
175
+ name: Platform tests - Hourly
176
+
177
+ on:
178
+ schedule:
179
+ # Runs at the start of every hour
180
+ - cron: '0 * * * *'
181
+ workflow_dispatch:
182
+
183
+ jobs:
184
+ platformTestsHourly:
185
+ uses: apify/apify-test-tools/.github/workflows/public_platform-tests.yaml@workflows-v0
186
+ with:
187
+ test-files-glob: hourly
188
+ secrets:
189
+ TESTER_APIFY_TOKEN: ${{ secrets.TESTER_APIFY_TOKEN }}
190
+ SLACK_TOKEN_TESTS_BOT: ${{ secrets.SLACK_TOKEN_TESTS_BOT }}
191
+ ```
192
+
193
+ ## `public_review.yaml`
194
+
195
+ Optional. Reviews a PR against the shared guidelines when you add the trigger label, and again on every push while
196
+ that label is on. The trigger label is removed once the review finishes, so re-applying it asks for another review.
197
+
198
+ | Input | Type | Default | Description |
199
+ | ---------------- | ------ | ------------------- | --------------------------------------------------------------------------------------------- |
200
+ | `label` | string | `Ask claude review` | Label that triggers a review |
201
+ | `reviewed-label` | string | `claude reviewed` | Label added after a successful review and never removed. Set to `''` to disable |
202
+ | `prompt-ref` | string | `workflows-v0` | Ref of this repo to fetch the review instructions from. Override only to test a prompt change |
203
+ | `model` | string | `sonnet` | Claude Code model (`best`, `sonnet`, `opus`, `haiku`, `sonnet[1m]`, `opus[1m]`, `opusplan`) |
204
+
205
+ Secrets: `ANTHROPIC_API_KEY`.
206
+
207
+ ```yaml
208
+ name: Claude review
209
+
210
+ on:
211
+ pull_request:
212
+ types: [labeled, synchronize]
213
+
214
+ jobs:
215
+ review:
216
+ uses: apify/apify-test-tools/.github/workflows/public_review.yaml@workflows-v0
217
+ secrets:
218
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
219
+ ```
220
+
221
+ The review instructions live in `.github/review-prompt.md` in this repo and are fetched at run time, because a
222
+ reusable workflow doesn't get its own repo checked out. `prompt-ref` defaults to `workflows-v0`, so the
223
+ instructions match the workflow you're calling — point it at a branch only to test a prompt change.
224
+
225
+ ## `public_claude.yaml`
226
+
227
+ Optional. Runs Claude Code when someone mentions `@claude` in an issue, an issue or PR comment, or a PR review, or
228
+ labels an issue `claude` (unless it is also labeled `claude:done`). On a PR it pushes to the PR's branch; on an issue
229
+ it opens a PR. It also picks up a "changes requested" review on PRs Claude opened.
230
+
231
+ | Input | Type | Default | Description |
232
+ | --------------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------ |
233
+ | `model` | string | `sonnet` | Claude Code model (`best`, `sonnet`, `opus`, `haiku`, `sonnet[1m]`, `opus[1m]`, `opusplan`) |
234
+ | `extra_allowed_tools` | string | `''` | Comma-separated tool patterns appended to `--allowedTools`, e.g. `Bash(npm run e2e),Bash(npm run typecheck)` |
235
+
236
+ Secrets: `ANTHROPIC_API_KEY`.
237
+
238
+ ```yaml
239
+ name: Claude
240
+
241
+ on:
242
+ issue_comment:
243
+ types: [created]
244
+ pull_request_review_comment:
245
+ types: [created]
246
+ pull_request_review:
247
+ types: [submitted]
248
+ issues:
249
+ types: [opened, labeled]
250
+
251
+ jobs:
252
+ claude:
253
+ uses: apify/apify-test-tools/.github/workflows/public_claude.yaml@workflows-v0
254
+ secrets:
255
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
256
+ ```
257
+
258
+ ## `public_platform-tests-claude-investigate-and-fix.yaml`
259
+
260
+ Optional. Call it after a failed platform test job. It runs in two phases:
261
+
262
+ 1. **investigate** — Claude reviews the test logs, recent workflow runs and existing issues, and investigates the
263
+ failing run on the Apify platform (its log, dataset and key-value store). It opens a GitHub issue with its
264
+ findings and labels it `claude`, or does nothing if a matching issue already exists.
265
+ 2. **fix** — runs only when the first phase opened an issue. Claude implements a fix, opens a PR, and labels the
266
+ issue `claude:done`.
267
+
268
+ Scheduled runs use a `GITHUB_TOKEN` that cannot trigger other workflows, so the fix phase is a direct job
269
+ dependency rather than a label-triggered run of `public_claude.yaml`.
270
+
271
+ | Input | Type | Default | Description |
272
+ | -------------------- | ------ | ---------- | -------------------------------------------------------------------------------------------------------- |
273
+ | `model` | string | `sonnet` | Claude model for both phases |
274
+ | `effort` | string | `''` | Claude effort level (`low`, `medium`, `high`, `xhigh`, `max`). Empty uses the Claude Code default |
275
+ | `max_flakiness_runs` | number | `200` | The most times Claude may re-run the failing Actor run to measure how often the failure happens |
276
+ | `investigate_prompt` | string | (built in) | Prompt for the investigation phase. Override to change how issues are investigated, titled and described |
277
+
278
+ Secrets: `ANTHROPIC_API_KEY`, `TESTER_APIFY_TOKEN`, and optionally `NPM_TOKEN`.
279
+
280
+ ```yaml
281
+ jobs:
282
+ platformTestsHourly:
283
+ uses: apify/apify-test-tools/.github/workflows/public_platform-tests.yaml@workflows-v0
284
+ with:
285
+ test-files-glob: hourly
286
+ secrets:
287
+ TESTER_APIFY_TOKEN: ${{ secrets.TESTER_APIFY_TOKEN }}
288
+ SLACK_TOKEN_TESTS_BOT: ${{ secrets.SLACK_TOKEN_TESTS_BOT }}
289
+
290
+ handle-failure:
291
+ needs: platformTestsHourly
292
+ if: ${{ failure() }}
293
+ uses: apify/apify-test-tools/.github/workflows/public_platform-tests-claude-investigate-and-fix.yaml@workflows-v0
294
+ secrets:
295
+ ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
296
+ TESTER_APIFY_TOKEN: ${{ secrets.TESTER_APIFY_TOKEN }}
297
+ ```
298
+
299
+ ## Secrets
300
+
301
+ The workflows take two kinds of secrets:
302
+
303
+ - **Secrets a workflow always reads**, like `TESTER_APIFY_TOKEN` for the tests or `NPM_TOKEN` for installing private
304
+ packages. Each workflow declares these, and you pass them by name.
305
+ - **Secrets your `apify-test-tools.config.json` names**, today each Actor's `tokenEnvVar`. Their names differ per
306
+ repo, and a reusable workflow only accepts secrets it declares by name, so they go packed in one JSON object,
307
+ `CONFIG_SECRETS`, with one entry per name the config uses. A name the config declares but the object leaves out
308
+ is reported as a warning in the build step.
309
+
310
+ The examples above show both. If you'd rather not keep `CONFIG_SECRETS` in sync with the config, you can pass all of
311
+ the repo's secrets in it:
312
+
313
+ ```yaml
314
+ secrets:
315
+ TESTER_APIFY_TOKEN: ${{ secrets.TESTER_APIFY_TOKEN }}
316
+ CONFIG_SECRETS: ${{ toJSON(secrets) }}
317
+ ```
318
+
319
+ Only the names the config declares are used. The cost is that every secret the repo can read, deploy keys and publish
320
+ tokens included, goes to code at a tag this repo moves, and you are trusting it to use only those.
321
+
322
+ Repos in the `apify` org can keep using `secrets: inherit`, which GitHub only allows when the caller is in the same
323
+ organization or enterprise as this repo. The config's secrets are then looked up among the inherited ones whenever
324
+ `CONFIG_SECRETS` doesn't have them.
325
+
326
+ `required` on a reusable workflow's secret only checks that the caller lists it, not that it has a value: the repo
327
+ may not have the secret, and PRs from forks never get secrets. The test workflows check that `TESTER_APIFY_TOKEN` is
328
+ not empty before doing anything else, and fail with a message saying so.
329
+
330
+ Values that arrive inside `CONFIG_SECRETS` are registered as masks one by one before anything uses them. The runner
331
+ masks a secret by its exact value, so it would otherwise only recognise the whole JSON blob, not a single token taken
332
+ out of it.
333
+
334
+ The workflows do not turn the secrets they receive into job-wide environment variables, so a secret is only visible
335
+ to the step that needs it:
336
+
337
+ | Secret | Reaches |
338
+ | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
339
+ | `NPM_TOKEN` | dependency install steps only, as both `NPM_TOKEN` and `NODE_AUTH_TOKEN`. Use a read-only token: npm granular tokens can be read-only, classic automation tokens can publish. |
340
+ | the Actor tokens named by `tokenEnvVar` in `apify-test-tools.config.json` | the build and `delete-old-builds` steps only |
341
+ | `TESTER_APIFY_TOKEN` | the vitest step, and the Claude investigation step: the Apify MCP server's bearer token for reading the failing run, its log and its storages, and Claude's token for re-running it to measure how often the failure happens |
342
+ | `SLACK_TOKEN_TESTS_BOT` / `SLACK_TOKEN_RELEASES_BOT` | the reporting and announcement steps only |
343
+ | `ANTHROPIC_API_KEY` | the Claude steps of the Claude workflows only |
344
+
345
+ The Actor tokens reach the build only for the Actors your config declares: a secret that merely looks like an Actor
346
+ token is not passed on. A token the config declares but the repo hasn't set is a warning, not a failure: a repo can
347
+ carry an Actor whose token isn't configured and still build fine as long as that Actor never changes. The build fails
348
+ with an error naming the Actor once it actually needs the token.
349
+
350
+ The `unitTest` job runs static checks and needs `NPM_TOKEN` only. No job runs `npm ci` or `pnpm install` with Apify
351
+ or Slack credentials in scope, so a postinstall script in the dependency tree cannot read them.
352
+
353
+ ## Versioning
354
+
355
+ The workflows and the vitest library ship separately:
356
+
357
+ | What | You get it through | Updates when |
358
+ | ------------------------------------------------ | ----------------------------------------- | -------------------------------- |
359
+ | the workflows and the CLI they run | the `@workflows-v0` tag in `uses:` | every change merged to this repo |
360
+ | the library (`testActor`, `describe`, matchers…) | `apify-test-tools` in your `package.json` | you update the package |
361
+
362
+ The workflows bring their own copy of the CLI, so they don't use or change the `apify-test-tools` version in your
363
+ `node_modules`, and your tests keep the library version you locked.
364
+
365
+ `@workflows-v0` always points at the latest workflows, so fixes and new features reach you without any change on your
366
+ side. Changes that would break callers go to a new tag (`@workflows-v1`), and `@workflows-v0` keeps working, so you
367
+ can migrate when it suits you.