apify-test-tools 0.10.2-beta.2 → 0.10.2-beta.21

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 (275) hide show
  1. package/.gitattributes +1 -0
  2. package/.github/actionlint.yaml +11 -0
  3. package/.github/actions/checkout-restore-dependencies/action.yaml +58 -6
  4. package/.github/cli/apify-test-tools.mjs +135 -142
  5. package/.github/scripts/mask-config-secrets.sh +17 -0
  6. package/.github/scripts/run-with-apify-tokens.mjs +63 -103
  7. package/.github/workflows/_check_code.yaml +5 -21
  8. package/.github/workflows/_move_major_tag.yaml +2 -2
  9. package/.github/workflows/public_platform-tests-claude-investigate-and-fix.yaml +89 -8
  10. package/.github/workflows/public_platform-tests.yaml +68 -30
  11. package/.github/workflows/public_pr-build-test.yaml +77 -38
  12. package/.github/workflows/public_push-build-latest.yaml +49 -11
  13. package/.github/workflows/public_review.yaml +5 -4
  14. package/.github/workflows/public_stale-issues.yaml +51 -0
  15. package/.husky/pre-commit +4 -4
  16. package/.prettierignore +2 -1
  17. package/CHANGELOG.md +23 -0
  18. package/CONTRIBUTING.md +117 -17
  19. package/README.md +221 -595
  20. package/bin/actor-ids.ts +41 -0
  21. package/bin/affected-actors.ts +211 -0
  22. package/bin/build-from-local.ts +19 -1
  23. package/bin/build.ts +105 -39
  24. package/bin/diff-changes.ts +69 -36
  25. package/bin/diff-json-schema.ts +5 -6
  26. package/bin/git.ts +73 -175
  27. package/bin/main.ts +142 -189
  28. package/bin/notify.ts +198 -0
  29. package/bin/run-tests.ts +182 -0
  30. package/bin/slack.ts +16 -76
  31. package/bin/stdin-input.ts +156 -0
  32. package/bin/test-files-glob.ts +126 -0
  33. package/bin/test-report.ts +141 -140
  34. package/bin/types.ts +4 -7
  35. package/bin/utils/config/load-config.ts +20 -2
  36. package/bin/utils/config/parser.ts +40 -8
  37. package/bin/utils/config/structures/grouped.ts +2 -2
  38. package/bin/utils/config/structures/legacy.ts +1 -1
  39. package/dist/bin/actor-ids.d.ts +15 -0
  40. package/dist/bin/actor-ids.d.ts.map +1 -0
  41. package/dist/bin/actor-ids.js +30 -0
  42. package/dist/bin/actor-ids.js.map +1 -0
  43. package/dist/bin/affected-actors.d.ts +55 -0
  44. package/dist/bin/affected-actors.d.ts.map +1 -0
  45. package/dist/bin/affected-actors.js +142 -0
  46. package/dist/bin/affected-actors.js.map +1 -0
  47. package/dist/bin/build-from-local.d.ts +2 -1
  48. package/dist/bin/build-from-local.d.ts.map +1 -1
  49. package/dist/bin/build-from-local.js +6 -2
  50. package/dist/bin/build-from-local.js.map +1 -1
  51. package/dist/bin/build.d.ts +18 -5
  52. package/dist/bin/build.d.ts.map +1 -1
  53. package/dist/bin/build.js +74 -24
  54. package/dist/bin/build.js.map +1 -1
  55. package/dist/bin/diff-changes.d.ts +21 -5
  56. package/dist/bin/diff-changes.d.ts.map +1 -1
  57. package/dist/bin/diff-changes.js +41 -28
  58. package/dist/bin/diff-changes.js.map +1 -1
  59. package/dist/bin/diff-json-schema.d.ts +2 -2
  60. package/dist/bin/diff-json-schema.d.ts.map +1 -1
  61. package/dist/bin/diff-json-schema.js +1 -4
  62. package/dist/bin/diff-json-schema.js.map +1 -1
  63. package/dist/bin/git.d.ts +26 -34
  64. package/dist/bin/git.d.ts.map +1 -1
  65. package/dist/bin/git.js +60 -143
  66. package/dist/bin/git.js.map +1 -1
  67. package/dist/bin/main.js +126 -140
  68. package/dist/bin/main.js.map +1 -1
  69. package/dist/bin/notify.d.ts +35 -0
  70. package/dist/bin/notify.d.ts.map +1 -0
  71. package/dist/bin/notify.js +131 -0
  72. package/dist/bin/notify.js.map +1 -0
  73. package/dist/bin/run-tests.d.ts +21 -0
  74. package/dist/bin/run-tests.d.ts.map +1 -0
  75. package/dist/bin/run-tests.js +149 -0
  76. package/dist/bin/run-tests.js.map +1 -0
  77. package/dist/bin/slack.d.ts +2 -14
  78. package/dist/bin/slack.d.ts.map +1 -1
  79. package/dist/bin/slack.js +17 -46
  80. package/dist/bin/slack.js.map +1 -1
  81. package/dist/bin/stdin-input.d.ts +79 -0
  82. package/dist/bin/stdin-input.d.ts.map +1 -0
  83. package/dist/bin/stdin-input.js +124 -0
  84. package/dist/bin/stdin-input.js.map +1 -0
  85. package/dist/bin/test-files-glob.d.ts +18 -0
  86. package/dist/bin/test-files-glob.d.ts.map +1 -0
  87. package/dist/bin/test-files-glob.js +108 -0
  88. package/dist/bin/test-files-glob.js.map +1 -0
  89. package/dist/bin/test-report.d.ts +69 -8
  90. package/dist/bin/test-report.d.ts.map +1 -1
  91. package/dist/bin/test-report.js +76 -67
  92. package/dist/bin/test-report.js.map +1 -1
  93. package/dist/bin/types.d.ts +4 -7
  94. package/dist/bin/types.d.ts.map +1 -1
  95. package/dist/bin/utils/config/load-config.d.ts +8 -0
  96. package/dist/bin/utils/config/load-config.d.ts.map +1 -1
  97. package/dist/bin/utils/config/load-config.js +14 -1
  98. package/dist/bin/utils/config/load-config.js.map +1 -1
  99. package/dist/bin/utils/config/parser.d.ts +15 -2
  100. package/dist/bin/utils/config/parser.d.ts.map +1 -1
  101. package/dist/bin/utils/config/parser.js +29 -8
  102. package/dist/bin/utils/config/parser.js.map +1 -1
  103. package/dist/bin/utils/config/structures/grouped.js +2 -2
  104. package/dist/bin/utils/config/structures/grouped.js.map +1 -1
  105. package/dist/bin/utils/config/structures/legacy.js +1 -1
  106. package/dist/bin/utils/config/structures/legacy.js.map +1 -1
  107. package/dist/lib/extend-expect.d.ts.map +1 -1
  108. package/dist/lib/extend-expect.js +37 -218
  109. package/dist/lib/extend-expect.js.map +1 -1
  110. package/dist/lib/lib.d.ts +1 -5
  111. package/dist/lib/lib.d.ts.map +1 -1
  112. package/dist/lib/lib.js +19 -31
  113. package/dist/lib/lib.js.map +1 -1
  114. package/dist/lib/run-checks.d.ts +14 -0
  115. package/dist/lib/run-checks.d.ts.map +1 -0
  116. package/dist/lib/run-checks.js +82 -0
  117. package/dist/lib/run-checks.js.map +1 -0
  118. package/dist/lib/run-test-result.d.ts +3 -6
  119. package/dist/lib/run-test-result.d.ts.map +1 -1
  120. package/dist/lib/run-test-result.js +41 -54
  121. package/dist/lib/run-test-result.js.map +1 -1
  122. package/dist/test/bundle/cli-bundle.test.js +76 -56
  123. package/dist/test/bundle/cli-bundle.test.js.map +1 -1
  124. package/dist/test/bundle/token-wrapper.test.d.ts +2 -0
  125. package/dist/test/bundle/token-wrapper.test.d.ts.map +1 -0
  126. package/dist/test/bundle/token-wrapper.test.js +80 -0
  127. package/dist/test/bundle/token-wrapper.test.js.map +1 -0
  128. package/dist/test/e2e/cli-bundle.e2e.test.js +33 -68
  129. package/dist/test/e2e/cli-bundle.e2e.test.js.map +1 -1
  130. package/dist/test/e2e/git-build-release.e2e.test.d.ts +2 -0
  131. package/dist/test/e2e/git-build-release.e2e.test.d.ts.map +1 -0
  132. package/dist/test/e2e/git-build-release.e2e.test.js +87 -0
  133. package/dist/test/e2e/git-build-release.e2e.test.js.map +1 -0
  134. package/dist/test/e2e/helpers.d.ts +37 -0
  135. package/dist/test/e2e/helpers.d.ts.map +1 -0
  136. package/dist/test/e2e/helpers.js +57 -0
  137. package/dist/test/e2e/helpers.js.map +1 -0
  138. package/dist/test/unit/bin/actor-filtering.test.js +7 -0
  139. package/dist/test/unit/bin/actor-filtering.test.js.map +1 -1
  140. package/dist/test/unit/bin/actor-ids.test.d.ts +2 -0
  141. package/dist/test/unit/bin/actor-ids.test.d.ts.map +1 -0
  142. package/dist/test/unit/bin/actor-ids.test.js +40 -0
  143. package/dist/test/unit/bin/actor-ids.test.js.map +1 -0
  144. package/dist/test/unit/bin/affected-actors-cli.test.d.ts +2 -0
  145. package/dist/test/unit/bin/affected-actors-cli.test.d.ts.map +1 -0
  146. package/dist/test/unit/bin/affected-actors-cli.test.js +224 -0
  147. package/dist/test/unit/bin/affected-actors-cli.test.js.map +1 -0
  148. package/dist/test/unit/bin/affected-actors.test.d.ts +2 -0
  149. package/dist/test/unit/bin/affected-actors.test.d.ts.map +1 -0
  150. package/dist/test/unit/bin/affected-actors.test.js +153 -0
  151. package/dist/test/unit/bin/affected-actors.test.js.map +1 -0
  152. package/dist/test/unit/bin/build-cli.test.d.ts +2 -0
  153. package/dist/test/unit/bin/build-cli.test.d.ts.map +1 -0
  154. package/dist/test/unit/bin/build-cli.test.js +49 -0
  155. package/dist/test/unit/bin/build-cli.test.js.map +1 -0
  156. package/dist/test/unit/bin/build-from-local.test.js +12 -0
  157. package/dist/test/unit/bin/build-from-local.test.js.map +1 -1
  158. package/dist/test/unit/bin/build.test.js +116 -6
  159. package/dist/test/unit/bin/build.test.js.map +1 -1
  160. package/dist/test/unit/bin/compiled-cli.d.ts +6 -0
  161. package/dist/test/unit/bin/compiled-cli.d.ts.map +1 -0
  162. package/dist/test/unit/bin/compiled-cli.js +23 -0
  163. package/dist/test/unit/bin/compiled-cli.js.map +1 -0
  164. package/dist/test/unit/bin/diff-changes.test.js +168 -114
  165. package/dist/test/unit/bin/diff-changes.test.js.map +1 -1
  166. package/dist/test/unit/bin/diff.test.js +25 -28
  167. package/dist/test/unit/bin/diff.test.js.map +1 -1
  168. package/dist/test/unit/bin/git.test.js +67 -288
  169. package/dist/test/unit/bin/git.test.js.map +1 -1
  170. package/dist/test/unit/bin/notify.test.d.ts +2 -0
  171. package/dist/test/unit/bin/notify.test.d.ts.map +1 -0
  172. package/dist/test/unit/bin/notify.test.js +222 -0
  173. package/dist/test/unit/bin/notify.test.js.map +1 -0
  174. package/dist/test/unit/bin/stdin-input.test.d.ts +2 -0
  175. package/dist/test/unit/bin/stdin-input.test.d.ts.map +1 -0
  176. package/dist/test/unit/bin/stdin-input.test.js +92 -0
  177. package/dist/test/unit/bin/stdin-input.test.js.map +1 -0
  178. package/dist/test/unit/bin/test-cli.test.d.ts +2 -0
  179. package/dist/test/unit/bin/test-cli.test.d.ts.map +1 -0
  180. package/dist/test/unit/bin/test-cli.test.js +165 -0
  181. package/dist/test/unit/bin/test-cli.test.js.map +1 -0
  182. package/dist/test/unit/bin/test-files-glob.test.d.ts +2 -0
  183. package/dist/test/unit/bin/test-files-glob.test.d.ts.map +1 -0
  184. package/dist/test/unit/bin/test-files-glob.test.js +102 -0
  185. package/dist/test/unit/bin/test-files-glob.test.js.map +1 -0
  186. package/dist/test/unit/bin/test-report.test.d.ts +2 -0
  187. package/dist/test/unit/bin/test-report.test.d.ts.map +1 -0
  188. package/dist/test/unit/bin/test-report.test.js +100 -0
  189. package/dist/test/unit/bin/test-report.test.js.map +1 -0
  190. package/dist/test/unit/bin/utils/config/load-config.test.js +19 -1
  191. package/dist/test/unit/bin/utils/config/load-config.test.js.map +1 -1
  192. package/dist/test/unit/bin/utils/config/parser.test.js +36 -4
  193. package/dist/test/unit/bin/utils/config/parser.test.js.map +1 -1
  194. package/dist/test/unit/bin/utils/config/structures/grouped.test.js +6 -0
  195. package/dist/test/unit/bin/utils/config/structures/grouped.test.js.map +1 -1
  196. package/dist/test/unit/bin/utils/config/structures/legacy.test.js +1 -0
  197. package/dist/test/unit/bin/utils/config/structures/legacy.test.js.map +1 -1
  198. package/dist/test/unit/github-scripts/mask-config-secrets.test.d.ts +2 -0
  199. package/dist/test/unit/github-scripts/mask-config-secrets.test.d.ts.map +1 -0
  200. package/dist/test/unit/github-scripts/mask-config-secrets.test.js +50 -0
  201. package/dist/test/unit/github-scripts/mask-config-secrets.test.js.map +1 -0
  202. package/dist/test/unit/github-scripts/run-with-apify-tokens.test.d.ts +2 -0
  203. package/dist/test/unit/github-scripts/run-with-apify-tokens.test.d.ts.map +1 -0
  204. package/dist/test/unit/github-scripts/run-with-apify-tokens.test.js +102 -0
  205. package/dist/test/unit/github-scripts/run-with-apify-tokens.test.js.map +1 -0
  206. package/dist/test/unit/run-checks.test.d.ts +2 -0
  207. package/dist/test/unit/run-checks.test.d.ts.map +1 -0
  208. package/dist/test/unit/run-checks.test.js +62 -0
  209. package/dist/test/unit/run-checks.test.js.map +1 -0
  210. package/dist/test/unit/run-test-result.test.d.ts +2 -0
  211. package/dist/test/unit/run-test-result.test.d.ts.map +1 -0
  212. package/dist/test/unit/run-test-result.test.js +34 -0
  213. package/dist/test/unit/run-test-result.test.js.map +1 -0
  214. package/dist/test/unit/should-built-and-test.test.js +41 -38
  215. package/dist/test/unit/should-built-and-test.test.js.map +1 -1
  216. package/dist/tsconfig.tsbuildinfo +1 -1
  217. package/dist/workflow-scripts-src/run-with-apify-tokens.d.ts +3 -0
  218. package/dist/workflow-scripts-src/run-with-apify-tokens.d.ts.map +1 -0
  219. package/dist/workflow-scripts-src/run-with-apify-tokens.js +100 -0
  220. package/dist/workflow-scripts-src/run-with-apify-tokens.js.map +1 -0
  221. package/docs/cli.md +473 -0
  222. package/docs/lib.md +276 -0
  223. package/docs/workflows.md +455 -0
  224. package/eslint.config.mjs +10 -1
  225. package/lib/extend-expect.ts +48 -258
  226. package/lib/lib.ts +25 -34
  227. package/lib/run-checks.ts +101 -0
  228. package/lib/run-test-result.ts +45 -55
  229. package/package.json +4 -2
  230. package/platform-tests-investigate-and-fix/skills/assess-impact/SKILL.md +42 -0
  231. package/platform-tests-investigate-and-fix/skills/measure-flakiness/SKILL.md +4 -2
  232. package/test/bundle/cli-bundle.test.ts +97 -67
  233. package/test/bundle/token-wrapper.test.ts +110 -0
  234. package/test/e2e/cli-bundle.e2e.test.ts +60 -93
  235. package/test/e2e/git-build-release.e2e.test.ts +113 -0
  236. package/test/e2e/helpers.ts +82 -0
  237. package/test/unit/bin/actor-filtering.test.ts +8 -0
  238. package/test/unit/bin/actor-ids.test.ts +47 -0
  239. package/test/unit/bin/affected-actors-cli.test.ts +271 -0
  240. package/test/unit/bin/affected-actors.test.ts +221 -0
  241. package/test/unit/bin/build-cli.test.ts +61 -0
  242. package/test/unit/bin/build-from-local.test.ts +16 -0
  243. package/test/unit/bin/build.test.ts +149 -5
  244. package/test/unit/bin/compiled-cli.ts +23 -0
  245. package/test/unit/bin/diff-changes.test.ts +181 -114
  246. package/test/unit/bin/diff.test.ts +25 -28
  247. package/test/unit/bin/git.test.ts +76 -361
  248. package/test/unit/bin/notify.test.ts +299 -0
  249. package/test/unit/bin/stdin-input.test.ts +120 -0
  250. package/test/unit/bin/test-cli.test.ts +207 -0
  251. package/test/unit/bin/test-files-glob.test.ts +118 -0
  252. package/test/unit/bin/test-report.test.ts +118 -0
  253. package/test/unit/bin/utils/config/load-config.test.ts +26 -1
  254. package/test/unit/bin/utils/config/parser.test.ts +46 -5
  255. package/test/unit/bin/utils/config/structures/grouped.test.ts +12 -0
  256. package/test/unit/bin/utils/config/structures/legacy.test.ts +1 -0
  257. package/test/unit/github-scripts/mask-config-secrets.test.ts +61 -0
  258. package/test/unit/github-scripts/run-with-apify-tokens.test.ts +115 -0
  259. package/test/unit/run-checks.test.ts +76 -0
  260. package/test/unit/run-test-result.test.ts +44 -0
  261. package/test/unit/should-built-and-test.test.ts +46 -39
  262. package/tsconfig.json +1 -1
  263. package/vitest.config.ts +9 -0
  264. package/workflow-scripts-src/run-with-apify-tokens.ts +112 -0
  265. package/.github/scripts/check-major-tag-refs.mjs +0 -72
  266. package/dist/test/unit/bin/logging.test.d.ts +0 -2
  267. package/dist/test/unit/bin/logging.test.d.ts.map +0 -1
  268. package/dist/test/unit/bin/logging.test.js +0 -43
  269. package/dist/test/unit/bin/logging.test.js.map +0 -1
  270. package/dist/test/unit/bin/slack.test.d.ts +0 -2
  271. package/dist/test/unit/bin/slack.test.d.ts.map +0 -1
  272. package/dist/test/unit/bin/slack.test.js +0 -54
  273. package/dist/test/unit/bin/slack.test.js.map +0 -1
  274. package/test/unit/bin/logging.test.ts +0 -52
  275. package/test/unit/bin/slack.test.ts +0 -65
@@ -26,22 +26,6 @@ jobs:
26
26
  # - name: Check spelling with typos
27
27
  # uses: crate-ci/typos@v1
28
28
 
29
- major_tag_refs:
30
- name: Major tag refs
31
- runs-on: ubuntu-latest
32
- steps:
33
- - name: Checkout repository
34
- uses: actions/checkout@v6
35
- - name: Use Node.js
36
- uses: actions/setup-node@v6
37
- with:
38
- node-version: 24
39
- # `uses:` takes no expressions, so the major tag is repeated in every ref into this repo.
40
- # Missing one during a bump is silent while both tags exist: the new workflows quietly
41
- # run the old composite action.
42
- - name: Check refs match MAJOR_TAG
43
- run: node .github/scripts/check-major-tag-refs.mjs
44
-
45
29
  lint_check:
46
30
  name: Lint check
47
31
  runs-on: ubuntu-latest
@@ -93,10 +77,10 @@ jobs:
93
77
  - name: Build
94
78
  run: npm run build
95
79
 
96
- # The composite action runs the CLI from .github/cli/apify-test-tools.mjs, which the pre-commit
97
- # hook rebuilds. This catches commits that skipped the hook, so a stale bundle never ships.
80
+ # The composite action runs the CLI and workflow helper bundles, which the pre-commit hook rebuilds.
81
+ # This catches commits that skipped the hook, so stale bundles never ship.
98
82
  cli_bundle:
99
- name: CLI bundle
83
+ name: CLI and workflow bundles
100
84
  runs-on: ubuntu-latest
101
85
  steps:
102
86
  - name: Checkout repository
@@ -112,8 +96,8 @@ jobs:
112
96
  - name: Check the bundle is up to date
113
97
  run: |
114
98
  npm run bundle
115
- if ! git diff --quiet -- .github/cli/; then
116
- echo "::error::.github/cli/apify-test-tools.mjs is out of date. Run \`npm run bundle\` and commit the result."
99
+ if ! git diff --quiet -- .github/cli/ .github/scripts/run-with-apify-tokens.mjs; then
100
+ echo "::error::A CLI or workflow script bundle is out of date. Run \`npm run bundle\` and commit the result."
117
101
  exit 1
118
102
  fi
119
103
  node .github/cli/apify-test-tools.mjs --help > /dev/null
@@ -42,8 +42,8 @@ jobs:
42
42
  # it. Depending on a regex in another repo to keep releases working is not a dependency
43
43
  # worth having, and `v1` beside a package `v1.0.0` would be worse still.
44
44
  #
45
- # `uses:` cannot take an expression, so every ref into this repo hardcodes this same tag;
46
- # check-major-tag-refs.mjs fails the build if one of them drifts.
45
+ # The workflows load this repo with `$/`, so they never name the tag. Only the usage
46
+ # examples in the workflows, README and docs do: update them by hand when bumping it.
47
47
  MAJOR_TAG: workflows-v0
48
48
  steps:
49
49
  - name: Checkout repository
@@ -22,14 +22,19 @@ name: 'Platform tests: Claude failure investigation and fix'
22
22
  # platformTestsCore:
23
23
  # uses: apify/apify-test-tools/.github/workflows/public_platform-tests.yaml@workflows-v0
24
24
  # with:
25
- # subtest: core
26
- # secrets: inherit
25
+ # test-files-glob: 'test/platform/hourly/**'
26
+ # report-slack-channel: '#notif-my-repo'
27
+ # secrets:
28
+ # TESTER_APIFY_TOKEN: ${{ secrets.TESTER_APIFY_TOKEN }}
29
+ # SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
27
30
  #
28
31
  # handle-failure:
29
32
  # needs: platformTestsCore
30
33
  # if: ${{ failure() }}
31
34
  # uses: apify/apify-test-tools/.github/workflows/public_platform-tests-claude-investigate-and-fix.yaml@workflows-v0
32
- # secrets: inherit
35
+ # secrets:
36
+ # ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
37
+ # TESTER_APIFY_TOKEN: ${{ secrets.TESTER_APIFY_TOKEN }}
33
38
 
34
39
  on:
35
40
  workflow_call:
@@ -39,6 +44,11 @@ on:
39
44
  type: string
40
45
  default: sonnet
41
46
  description: Claude model to use for investigation and fix
47
+ effort:
48
+ required: false
49
+ type: string
50
+ default: ''
51
+ description: Claude effort level (low, medium, high, xhigh, max) to use for investigation and fix. Uses the Claude Code default when empty.
42
52
  max_flakiness_runs:
43
53
  required: false
44
54
  type: number
@@ -59,14 +69,34 @@ on:
59
69
 
60
70
  Before you create a new issue, check whether the `platform-tests-investigate-and-fix:measure-flakiness` skill applies, and follow it if it does.
61
71
 
72
+ At the end of your investigation, before you create a new issue, follow the `platform-tests-investigate-and-fix:assess-impact` skill.
73
+
62
74
  When you create the issue, write it like an incident postmortem: a short summary and impact up top for anyone skimming, full technical detail below for whoever fixes it. Don't water down the engineering detail to make the top readable.
63
75
  - Title: short and clean, describing the actual problem in plain terms — no dates, run numbers, or other noise. Prefix it with a conventional-commit-style type, e.g. "fix: blocking issue on detail endpoint".
64
- - Body, section 1 ("## Summary"): one line stating what's broken plus its impact, in plain language a PM can understand at a glance — no jargon, internal field names, or stack traces (e.g. "Scraping product detail pages fails when a listing has no reviews, affecting N% of runs").
76
+ - Body, section 1 ("## Summary"): one line stating what's broken plus its impact, in plain language a PM can understand at a glance — no jargon, internal field names, or stack traces (e.g. "Scraping product detail pages fails when a listing has no reviews").
65
77
  - If you measured flakiness, a "## Flakiness" section right after the Summary, as the `measure-flakiness` skill describes.
78
+ - An "## Impact" section under the Flakiness section (or under the Summary if there's none), as the `assess-impact` skill describes.
66
79
  - A `---` divider, then section 2 ("## Details"): the engineering bug report — root cause, relevant log lines, links to the failing run, and any other internals an engineer needs. If a single item/request failed among otherwise-good ones, show or link that specific one (e.g. the dataset item index/id, or its matching debug snapshot) rather than just describing the run as failed.
67
80
 
68
81
  If you create a new issue, you MUST write its issue number (just the number, nothing else) to $GITHUB_WORKSPACE/issue-number.txt as the very last thing you do. If you skip creating one because a duplicate already exists, do not create the file.
69
82
  description: Prompt given to Claude for the investigation phase. Override to customize how issues are investigated, titled, and described.
83
+ priority_prompt:
84
+ required: false
85
+ type: string
86
+ # The prio prompt here is purposefully vague; you can adjust it to
87
+ # use custom thresholds based on measured impact metrics.
88
+ default: |
89
+ After you create a new issue and before you write its issue number to $GITHUB_WORKSPACE/issue-number.txt, set its Priority field from the failure's impact and flakiness:
90
+
91
+ To do so, exercise your best judgement. Issues marked with higher priority will be reacted to first.
92
+ Here are guidelines:
93
+ - Determine priority based on combined severity and revenue actually at risk: a less severe bug can outrank a more severe one if much more revenue is actually at risk, and vice versa.
94
+ - If the Impact section considers the bug from several points of view, each in its own sub-section, base the priority on the most impactful one.
95
+ - If it helps you, you can base your assessment off priorities of already existing bugs in the repo.
96
+ - Invisible to the user or Test severity always receives lowest priority.
97
+
98
+ Priority is an organization-level issue field. If the revenue actually at risk can't be determined, e.g. the Impact section says "Cannot be determined", leave Priority unset, unless the relative severity is Invisible to the user or Test.
99
+ description: Prompt given to Claude for setting a new issue's Priority field from its impact and flakiness. Override to customize how priority is judged, e.g. to set revenue thresholds.
70
100
  secrets:
71
101
  ANTHROPIC_API_KEY:
72
102
  required: true
@@ -77,6 +107,12 @@ on:
77
107
  NPM_TOKEN:
78
108
  required: false
79
109
  description: Read-only token for installing private npm packages before Claude runs.
110
+ REDASH_API_KEY:
111
+ required: false
112
+ description: Redash API key for measuring the failure's impact — affected runs, high-touch customers and revenue — from Snowflake.
113
+ AGENT_SKILLS_INTERNAL_GITHUB_TOKEN:
114
+ required: false
115
+ description: GitHub token with read access to apify/agent-skills-internal, for installing its redash-analyst plugin.
80
116
 
81
117
  jobs:
82
118
  investigate:
@@ -92,29 +128,71 @@ jobs:
92
128
  - name: Checkout repository
93
129
  uses: actions/checkout@v5
94
130
 
131
+ - name: Check which optional secrets are set
132
+ id: optional-secrets
133
+ run: |
134
+ echo "agent-skills-token=${{ secrets.AGENT_SKILLS_INTERNAL_GITHUB_TOKEN != '' }}" >> "$GITHUB_OUTPUT"
135
+ echo "redash-api-key=${{ secrets.REDASH_API_KEY != '' }}" >> "$GITHUB_OUTPUT"
136
+
137
+ - name: Checkout internal agent skills
138
+ id: agent-skills-internal
139
+ if: steps.optional-secrets.outputs.agent-skills-token == 'true'
140
+ continue-on-error: true
141
+ uses: actions/checkout@v5
142
+ with:
143
+ repository: apify/agent-skills-internal
144
+ token: ${{ secrets.AGENT_SKILLS_INTERNAL_GITHUB_TOKEN }}
145
+ path: .agent-skills-internal
146
+ sparse-checkout: |
147
+ .claude-plugin
148
+ skills/redash-analyst
149
+ persist-credentials: false
150
+
151
+ - uses: actions/setup-node@v6
152
+ if: steps.optional-secrets.outputs.redash-api-key == 'true'
153
+ with:
154
+ node-version: 24
155
+
156
+ - name: Install Redash MCP server
157
+ if: steps.optional-secrets.outputs.redash-api-key == 'true'
158
+ continue-on-error: true
159
+ working-directory: ${{ runner.temp }}
160
+ run: npm install --prefix redash-mcp --ignore-scripts --no-audit --no-fund @suthio/redash-mcp@0.1.0
161
+
95
162
  - name: Run Claude Code
96
163
  id: claude
97
164
  uses: anthropics/claude-code-action@8251c103ac8c1d761882c86aba1412c7f583c844 # v1.0.213
98
165
  env:
99
166
  TESTER_APIFY_TOKEN: ${{ secrets.TESTER_APIFY_TOKEN }}
167
+ REDASH_API_KEY: ${{ secrets.REDASH_API_KEY }}
100
168
  MAX_FLAKINESS_RUNS: ${{ inputs.max_flakiness_runs }}
101
169
  with:
102
170
  prompt: |
103
171
  The failing E2E platform test ran in workflow run ${{ github.run_id }} of this repo.
104
172
 
105
173
  ${{ inputs.investigate_prompt }}
174
+
175
+ ${{ inputs.priority_prompt }}
106
176
  github_token: ${{ secrets.GITHUB_TOKEN }}
107
177
  anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
108
- plugin_marketplaces: https://github.com/apify/apify-test-tools.git
109
- plugins: platform-tests-investigate-and-fix@apify-test-tools
178
+ plugin_marketplaces: |
179
+ https://github.com/apify/apify-test-tools.git
180
+ ${{ steps.agent-skills-internal.outcome == 'success' && format('{0}/.agent-skills-internal', github.workspace) || '' }}
181
+ plugins: |
182
+ platform-tests-investigate-and-fix@apify-test-tools
183
+ ${{ steps.agent-skills-internal.outcome == 'success' && 'redash-analyst@apify-agent-skills-internal' || '' }}
110
184
  # The `tools` query parameter below selects which tools the Apify MCP server
111
185
  # exposes: reading an Actor run — its status, exit code, storage ids and log — and
112
186
  # reading that run's dataset items and its key-value store keys and records, e.g.
113
187
  # INPUT, OUTPUT and error snapshots. WARN: the server adds `abort-actor-run` on top
114
188
  # even when not listed here, see https://github.com/apify/apify-mcp-server
189
+ # `--disallowedTools` removes the Redash MCP server's tools that change Redash: creating,
190
+ # editing, sharing or deleting queries, visualizations, dashboards, widgets, alerts and snippets.
115
191
  claude_args: |
116
- --mcp-config '{"mcpServers":{"apify":{"type":"http","url":"https://mcp.apify.com/?tools=get-actor-run,get-actor-run-log,get-dataset-list,get-dataset,get-dataset-items,get-key-value-store-list,get-key-value-store,get-key-value-store-keys,get-key-value-store-record","headers":{"Authorization":"Bearer ${TESTER_APIFY_TOKEN}"}}}}'
192
+ --mcp-config '{"mcpServers":{"apify":{"type":"http","url":"https://mcp.apify.com/?tools=get-actor-run,get-actor-run-log,get-dataset-list,get-dataset,get-dataset-items,get-key-value-store-list,get-key-value-store,get-key-value-store-keys,get-key-value-store-record","headers":{"Authorization":"Bearer ${TESTER_APIFY_TOKEN}"}},"redash":{"type":"stdio","command":"${{ runner.temp }}/redash-mcp/node_modules/.bin/redash-mcp","env":{"REDASH_URL":"https://charts.apify.com/","REDASH_API_KEY":"${REDASH_API_KEY}"}}}}'
193
+ --disallowedTools mcp__redash__create_query,mcp__redash__update_query,mcp__redash__update_query_parameters,mcp__redash__archive_query,mcp__redash__fork_query,mcp__redash__add_query_favorite,mcp__redash__remove_query_favorite,mcp__redash__create_visualization,mcp__redash__update_visualization,mcp__redash__update_chart_visualization,mcp__redash__delete_visualization,mcp__redash__create_dashboard,mcp__redash__update_dashboard,mcp__redash__update_dashboard_parameters,mcp__redash__archive_dashboard,mcp__redash__fork_dashboard,mcp__redash__share_dashboard,mcp__redash__unshare_dashboard,mcp__redash__add_dashboard_favorite,mcp__redash__remove_dashboard_favorite,mcp__redash__create_alert,mcp__redash__update_alert,mcp__redash__delete_alert,mcp__redash__mute_alert,mcp__redash__add_alert_subscription,mcp__redash__remove_alert_subscription,mcp__redash__create_widget,mcp__redash__update_widget,mcp__redash__update_widget_layout,mcp__redash__update_dashboard_layout,mcp__redash__update_widget_parameter_mappings,mcp__redash__delete_widget,mcp__redash__create_query_snippet,mcp__redash__update_query_snippet,mcp__redash__delete_query_snippet
117
194
  --model ${{ inputs.model }}
195
+ ${{ inputs.effort && format('--effort {0}', inputs.effort) || '' }}
118
196
  --dangerously-skip-permissions
119
197
 
120
198
  - name: Upload Claude output (for debugging)
@@ -177,7 +255,9 @@ jobs:
177
255
  actions: read
178
256
  steps:
179
257
  - name: Setup repository and dependencies
180
- uses: apify/apify-test-tools/.github/actions/checkout-restore-dependencies@workflows-v0
258
+ # `$/` loads the action from this repo at the commit this workflow was called at, so a caller
259
+ # pinned to a SHA or a branch gets that commit's action and CLI, not whatever the major tag is on.
260
+ uses: $/.github/actions/checkout-restore-dependencies
181
261
  with:
182
262
  npm-token: ${{ secrets.NPM_TOKEN }}
183
263
 
@@ -190,6 +270,7 @@ jobs:
190
270
  prompt: 'Open a pull request to address GitHub issue #${{ needs.investigate.outputs.issue_number }}. Use `gh issue view ${{ needs.investigate.outputs.issue_number }}` to read the issue details first, then implement the fix and create a PR.'
191
271
  claude_args: |
192
272
  --model ${{ inputs.model }}
273
+ ${{ inputs.effort && format('--effort {0}', inputs.effort) || '' }}
193
274
  --dangerously-skip-permissions
194
275
 
195
276
  - name: Upload Claude output (for debugging)
@@ -3,21 +3,27 @@ name: Platform tests
3
3
  on:
4
4
  workflow_call:
5
5
  inputs:
6
- # Deprecated, use `test-files-glob`
7
- subtest:
8
- type: string
9
- default: ''
10
- required: false
11
- # Specify what tests you want to run, relative to `test/platform`
6
+ # Glob of the test files to run, from the repo root, e.g. `test/platform/{hourly,hourly-without-pr}/**`
12
7
  test-files-glob:
13
8
  type: string
14
- default: ''
9
+ default: 'test/platform/**'
15
10
  required: false
16
- # Defaults to #notif-<repo-name> when empty, matching the previous behavior.
11
+ # Slack channel for failed tests. Empty skips Slack.
17
12
  report-slack-channel:
18
13
  type: string
19
14
  default: ''
20
15
  required: false
16
+ # Only TESTER_APIFY_TOKEN is required, every test needs it. See the Secrets section of docs/workflows.md.
17
+ secrets:
18
+ NPM_TOKEN:
19
+ required: false
20
+ description: Read-only token for installing private npm packages.
21
+ TESTER_APIFY_TOKEN:
22
+ required: true
23
+ description: Apify token the platform tests run Actors with.
24
+ SLACK_BOT_TOKEN:
25
+ required: false
26
+ description: Slack token for reporting test results.
21
27
 
22
28
  jobs:
23
29
  scheduledPlatformTests:
@@ -26,37 +32,69 @@ jobs:
26
32
  runs-on: ubuntu-latest
27
33
  steps:
28
34
  - name: Setup repository and dependencies
29
- # For testing, you have to temporarily change the branch
30
- uses: apify/apify-test-tools/.github/actions/checkout-restore-dependencies@workflows-v0
35
+ # `$/` loads the action from this repo at the commit this workflow was called at, so a caller
36
+ # pinned to a SHA or a branch gets that commit's action and CLI, not whatever the major tag is on.
37
+ uses: $/.github/actions/checkout-restore-dependencies
31
38
  with:
32
39
  npm-token: ${{ secrets.NPM_TOKEN }}
33
40
 
41
+ # Fails here with a clear message rather than deep in vitest. `required: true` alone doesn't
42
+ # catch it: a caller can list the secret while the repo doesn't have it, and PRs from forks
43
+ # never get secrets.
44
+ - name: Check TESTER_APIFY_TOKEN
45
+ env:
46
+ TESTER_APIFY_TOKEN: ${{ secrets.TESTER_APIFY_TOKEN }}
47
+ run: |
48
+ if [ -z "$TESTER_APIFY_TOKEN" ]; then
49
+ echo "::error::TESTER_APIFY_TOKEN is empty. Pass it in the secrets: block of the job that calls this workflow."
50
+ exit 1
51
+ fi
52
+
53
+ # Runs the repo's test code and its whole import graph, so it gets the tester token only.
54
+ # Fails on failing tests, but writes the report anyway for the notification below.
55
+ # Every Actor in the config, on its default build: the one users run
34
56
  - name: Test
57
+ id: test
58
+ # bash rather than the default shell, for pipefail
59
+ shell: bash
35
60
  env:
36
61
  TESTER_APIFY_TOKEN: ${{ secrets.TESTER_APIFY_TOKEN }}
37
- SLACK_TOKEN_TESTS_BOT: ${{ secrets.SLACK_TOKEN_TESTS_BOT }}
62
+ # Passed through the environment and quoted, so the shell doesn't expand the glob itself
63
+ # An empty input, e.g. from an expression that picks the glob, runs everything, like the default
64
+ TEST_FILES_GLOB: ${{ inputs.test-files-glob || 'test/platform/**' }}
65
+ run: |
66
+ apify-test-tools get-actor-configs \
67
+ | apify-test-tools test --test-files-glob "$TEST_FILES_GLOB" \
68
+ --reporter github-actions --vitest-output-file ./test-output.json > test-report.json
69
+
70
+ # Posts only when the tests failed, but checks the Slack token on every run that has a channel. Runs
71
+ # whenever the tests did, also after a failure, but not when the token check stopped the job before them.
72
+ - name: Notify
73
+ if: ${{ !cancelled() && steps.test.outcome != 'skipped' }}
74
+ env:
75
+ SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
76
+ # Passed through the environment, so a quote in the workflow name can't break the command
77
+ WORKFLOW_NAME: ${{ github.workflow }}
78
+ JOB_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
79
+ # Empty makes notify skip Slack
80
+ SLACK_CHANNEL: ${{ inputs.report-slack-channel }}
38
81
  run: |
39
- set +e
40
- export RUN_ALL_PLATFORM_TESTS=1
41
- npx vitest ./test/platform/${{ inputs.test-files-glob || inputs.subtest }} \
42
- --run \
43
- --reporter=default \
44
- --reporter=json \
45
- --outputFile=./test-output.json \
46
- --maxConcurrency 20 \
47
- --fileParallelism=true \
48
- --maxWorkers 100
49
- return_code=$?
50
- apify-test-tools report-tests \
51
- --report-file ./test-output.json \
52
- --workflow-name "${{ github.workflow }}" \
53
- --job-url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
54
- --report-slack-channel "${{ inputs.report-slack-channel || format('#notif-{0}', github.event.repository.name) }}"
55
- exit $return_code
82
+ # Empty when `test` itself failed before running vitest, its error is in the Test step
83
+ if [ ! -s test-report.json ]; then
84
+ echo "No test report, so there is nothing to notify about"
85
+ exit 0
86
+ fi
87
+ apify-test-tools notify \
88
+ --slack-channel "$SLACK_CHANNEL" \
89
+ --title "$WORKFLOW_NAME" \
90
+ --job-url "$JOB_URL" \
91
+ < test-report.json
56
92
 
57
- - name: Upload Vitest JSON artifact
93
+ - name: Upload test reports
58
94
  uses: actions/upload-artifact@v6
59
95
  if: always()
60
96
  with:
61
97
  name: vitest-results
62
- path: ./test-output.json
98
+ path: |
99
+ ./test-output.json
100
+ ./test-report.json
@@ -7,11 +7,33 @@ on:
7
7
  type: boolean
8
8
  default: false
9
9
  required: false
10
- # Specify what tests you want to run, relative to `test/platform`
10
+ # Glob of the test files to run, from the repo root, e.g. `test/platform/{daily,hourly}/**`. Which changed
11
+ # files count as test changes is `platformTestsGlob` in apify-test-tools.config.json, not this.
11
12
  test-files-glob:
12
13
  type: string
13
- default: ''
14
+ default: 'test/platform/**'
14
15
  required: false
16
+ # Fail the build unless the env var names of version 0.99 match the default version's
17
+ require-env-vars-in-sync:
18
+ type: boolean
19
+ default: true
20
+ required: false
21
+ # Every secret is optional. The ones this workflow reads are declared by name. The secrets that
22
+ # apify-test-tools.config.json names (e.g. each Actor's `tokenEnvVar`) differ per repo, so they
23
+ # come packed in CONFIG_SECRETS. See the Secrets section of docs/workflows.md.
24
+ secrets:
25
+ NPM_TOKEN:
26
+ required: false
27
+ description: Read-only token for installing private npm packages.
28
+ TESTER_APIFY_TOKEN:
29
+ required: false
30
+ description: Apify token the platform tests run Actors with.
31
+ CONFIG_SECRETS:
32
+ required: false
33
+ description: >-
34
+ JSON object of the secrets apify-test-tools.config.json names, secret name -> value.
35
+ Today that is each Actor's `tokenEnvVar`. Passing `toJSON(secrets)` works too, only
36
+ the names the config declares are used.
15
37
 
16
38
  concurrency:
17
39
  group: ${{ github.workflow }}-${{ github.ref }}
@@ -24,11 +46,25 @@ jobs:
24
46
  steps:
25
47
  - name: Setup repository and dependencies
26
48
  id: setup
27
- # For testing, you have to temporarily change the branch
28
- uses: apify/apify-test-tools/.github/actions/checkout-restore-dependencies@workflows-v0
49
+ # `$/` loads the action from this repo at the commit this workflow was called at, so a caller
50
+ # pinned to a SHA or a branch gets that commit's action and CLI, not whatever the major tag is on.
51
+ uses: $/.github/actions/checkout-restore-dependencies
29
52
  with:
30
53
  # Some repos use private npm packages, they need to pass NPM_TOKEN secret to this workflow
31
54
  npm-token: ${{ secrets.NPM_TOKEN }}
55
+ config-secrets: ${{ secrets.CONFIG_SECRETS }}
56
+
57
+ # Fails here with a clear message rather than deep in vitest. `required: true` alone doesn't
58
+ # catch it: a caller can list the secret while the repo doesn't have it, and PRs from forks
59
+ # never get secrets.
60
+ - name: Check TESTER_APIFY_TOKEN
61
+ env:
62
+ TESTER_APIFY_TOKEN: ${{ secrets.TESTER_APIFY_TOKEN }}
63
+ run: |
64
+ if [ -z "$TESTER_APIFY_TOKEN" ]; then
65
+ echo "::error::TESTER_APIFY_TOKEN is empty. Pass it in the secrets: block of the job that calls this workflow."
66
+ exit 1
67
+ fi
32
68
 
33
69
  - name: Pick last validated commit from cache
34
70
  id: base_commit
@@ -41,54 +77,56 @@ jobs:
41
77
  # This is needed to force overriding the cache with new entry at the end
42
78
  restore-keys: base_commit-
43
79
 
44
- # run-with-apify-tokens.mjs reads the token names from in apify-test-tools.config.json
45
- # and hands the build those secrets and nothing else, so the tokens stay in this one command instead of the whole job.
46
- # The library never sees secrets it doesn't need
47
- - name: Build
48
- id: build
80
+ # Needs no tokens, it only reads git and apify-test-tools.config.json. The setup action checks out
81
+ # the PR branch itself (not GitHub's merge commit), so the range ends at the branch's HEAD.
82
+ - name: Find affected Actors
49
83
  env:
50
- ALL_SECRETS: ${{ toJSON(secrets) }}
51
84
  # Branch names are attacker-controlled on fork PRs, so they reach the script as
52
85
  # environment variables rather than being interpolated into it.
53
- HEAD_REF: ${{ github.head_ref }}
54
86
  BASE_REF: ${{ github.base_ref }}
55
- SCRIPTS_PATH: ${{ steps.setup.outputs.scripts-path }}
56
87
  run: |
57
88
  base_commit=$(cat base_commit.txt 2>/dev/null || echo "")
58
89
  echo "Last validated (base) commit to be used for build & test: $base_commit"
59
- args=(
60
- --source-branch "origin/$HEAD_REF"
61
- --target-branch "origin/$BASE_REF"
62
- # TODO: Temporary hotfix until build glob matching aligns with Vitest's test selection glob.
63
- --test-files-glob 'test/platform/**'
64
- --use-docker-cache
65
- )
66
- [ -n "$base_commit" ] && args+=(--base-commit "$base_commit")
67
- actor_builds=$(node "$SCRIPTS_PATH/run-with-apify-tokens.mjs" \
68
- apify-test-tools build "${args[@]}")
69
- echo "actor_builds=$actor_builds" | tee -a "$GITHUB_OUTPUT"
90
+ args=(--base "origin/$BASE_REF")
91
+ [ -n "$base_commit" ] && args+=(--since "$base_commit")
92
+ apify-test-tools get-affected-actors "${args[@]}" > affected.json
93
+
94
+ # Cosmetic-only changes need no tests, so only the Actors with functional or platform test changes are
95
+ # built, into the test version 0.99 that users never run.
96
+ # run-with-apify-tokens.mjs reads the token names from in apify-test-tools.config.json
97
+ # and hands the build those secrets and nothing else, so the tokens stay in this one command instead of the whole job.
98
+ # The library never sees secrets it doesn't need
99
+ - name: Build
100
+ # bash rather than the default shell, for pipefail
101
+ shell: bash
102
+ env:
103
+ WORKFLOW_SECRETS: ${{ toJSON(secrets) }}
104
+ SCRIPTS_PATH: ${{ steps.setup.outputs.scripts-path }}
105
+ REQUIRE_ENV_VARS_IN_SYNC: ${{ inputs.require-env-vars-in-sync }}
106
+ run: |
107
+ jq '{ actors: (.functionallyChangedActors + .testChangedActors) }' affected.json \
108
+ | node "$SCRIPTS_PATH/run-with-apify-tokens.mjs" apify-test-tools build --version-number 0.99 \
109
+ --require-env-vars-in-sync="$REQUIRE_ENV_VARS_IN_SYNC" \
110
+ | tee builds.json
70
111
 
71
112
  # Runs the repo's test code and its whole import graph, so it gets the tester token only.
72
113
  - name: Test
73
114
  env:
74
- ACTOR_BUILDS: ${{ steps.build.outputs.actor_builds }}
75
115
  TESTER_APIFY_TOKEN: ${{ secrets.TESTER_APIFY_TOKEN }}
76
- run: npx vitest ./test/platform/${{ inputs.test-files-glob }} --run --maxConcurrency 20 --fileParallelism=true --maxWorkers 100
116
+ # Passed through the environment and quoted, so the shell doesn't expand the glob itself
117
+ # An empty input, e.g. from an expression that picks the glob, runs everything, like the default
118
+ TEST_FILES_GLOB: ${{ inputs.test-files-glob || 'test/platform/**' }}
119
+ # The github-actions reporter annotates the PR with the failing tests
120
+ run: |
121
+ apify-test-tools test --test-files-glob "$TEST_FILES_GLOB" --reporter github-actions \
122
+ < builds.json > test-report.json
77
123
 
78
124
  # NOTE: This is an optimization that if we did functional changes and later only cosmetic changes (e.g. dev readme), we will compare changes files only for the last commit. This must run after tests because we want to cache the latest commit only if the tests are successful
79
125
  - name: Store last validated commit to cache
80
- env:
81
- HEAD_REF: ${{ github.head_ref }}
82
- BASE_REF: ${{ github.base_ref }}
83
126
  run: |
84
- base_commit=$(cat base_commit.txt 2>/dev/null || echo "")
85
- echo "Old last validated (base) commit: $base_commit"
86
- args=(
87
- --source-branch "origin/$HEAD_REF"
88
- --target-branch "origin/$BASE_REF"
89
- )
90
- [ -n "$base_commit" ] && args+=(--base-commit "$base_commit")
91
- apify-test-tools get-latest-commit "${args[@]}" > ./base_commit.txt
127
+ echo "Old last validated (base) commit: $(cat base_commit.txt 2>/dev/null || echo "")"
128
+ # The HEAD that was just built and tested
129
+ jq -r .head affected.json > base_commit.txt
92
130
  echo "New last validated (base) commit: $(cat base_commit.txt)"
93
131
 
94
132
  # Pure static checks against the repo. Needs no Apify or Slack credentials, only the npm
@@ -98,8 +136,9 @@ jobs:
98
136
  runs-on: ubuntu-latest
99
137
  steps:
100
138
  - name: Setup repository and dependencies
101
- # For testing, you have to temporarily change the branch
102
- uses: apify/apify-test-tools/.github/actions/checkout-restore-dependencies@workflows-v0
139
+ # `$/` loads the action from this repo at the commit this workflow was called at, so a caller
140
+ # pinned to a SHA or a branch gets that commit's action and CLI, not whatever the major tag is on.
141
+ uses: $/.github/actions/checkout-restore-dependencies
103
142
  with:
104
143
  npm-token: ${{ secrets.NPM_TOKEN }}
105
144
 
@@ -3,11 +3,27 @@ name: Build latest and report to slack
3
3
  on:
4
4
  workflow_call:
5
5
  inputs:
6
- # Defaults to #notif-<repo-name> when empty, matching the previous behavior.
6
+ # Slack channel for release announcements. Empty skips Slack.
7
7
  report-slack-channel:
8
8
  type: string
9
9
  default: ''
10
10
  required: false
11
+ # Every secret is optional. The ones this workflow reads are declared by name. The secrets that
12
+ # apify-test-tools.config.json names (e.g. each Actor's `tokenEnvVar`) differ per repo, so they
13
+ # come packed in CONFIG_SECRETS. See the Secrets section of docs/workflows.md.
14
+ secrets:
15
+ NPM_TOKEN:
16
+ required: false
17
+ description: Read-only token for installing private npm packages.
18
+ SLACK_BOT_TOKEN:
19
+ required: false
20
+ description: Slack token for announcing releases.
21
+ CONFIG_SECRETS:
22
+ required: false
23
+ description: >-
24
+ JSON object of the secrets apify-test-tools.config.json names, secret name -> value.
25
+ Today that is each Actor's `tokenEnvVar`. Passing `toJSON(secrets)` works too, only
26
+ the names the config declares are used.
11
27
 
12
28
  jobs:
13
29
  pushBuildLatest:
@@ -20,27 +36,49 @@ jobs:
20
36
  steps:
21
37
  - name: Setup repository and dependencies
22
38
  id: setup
23
- # For testing, you have to temporarily change the branch
24
- uses: apify/apify-test-tools/.github/actions/checkout-restore-dependencies@workflows-v0
39
+ # `$/` loads the action from this repo at the commit this workflow was called at, so a caller
40
+ # pinned to a SHA or a branch gets that commit's action and CLI, not whatever the major tag is on.
41
+ uses: $/.github/actions/checkout-restore-dependencies
25
42
  with:
26
43
  npm-token: ${{ secrets.NPM_TOKEN }}
44
+ config-secrets: ${{ secrets.CONFIG_SECRETS }}
45
+
46
+ # --since is the last commit that is already released: the push's "before" commit.
47
+ # Everything after it up to HEAD gets released. See the "Releasing Actors" section of docs/cli.md.
48
+ # Needs no tokens, it only reads git and apify-test-tools.config.json.
49
+ - name: Find changes since the last release
50
+ run: |
51
+ apify-test-tools get-affected-actors --since ${{ github.event.before }} > affected.json
27
52
 
28
- # --base-commit is the last commit that is already released: the push's "before" commit.
29
- # Everything after it up to HEAD gets released. See the "Releasing Actors" section of the README.
53
+ # A release ships cosmetic changes too (README, input schema descriptions), so both lists are built,
54
+ # into each Actor's default version: the one its default build tag points to, which users run.
55
+ # testChangedActors is left out: a change to platform tests alone needs no release.
30
56
  # run-with-apify-tokens.mjs reads the token names from in apify-test-tools.config.json
31
57
  # and hands the build those secrets and nothing else, so the tokens stay in this one command instead of the whole job.
32
58
  # The library never sees secrets it doesn't need
33
- - name: Release Actors and notify
59
+ - name: Build the default versions
60
+ # bash rather than the default shell, for pipefail
61
+ shell: bash
34
62
  env:
35
- ALL_SECRETS: ${{ toJSON(secrets) }}
36
- SLACK_TOKEN_RELEASES_BOT: ${{ secrets.SLACK_TOKEN_RELEASES_BOT }}
63
+ WORKFLOW_SECRETS: ${{ toJSON(secrets) }}
37
64
  run: |
38
- node "${{ steps.setup.outputs.scripts-path }}/run-with-apify-tokens.mjs" \
39
- apify-test-tools release --base-commit ${{ github.event.before }} --release-slack-channel "#delivery-public-actors" --report-slack-channel "${{ inputs.report-slack-channel || format('#notif-{0}', github.event.repository.name) }}" --use-docker-cache
65
+ jq '{ actors: (.functionallyChangedActors + .cosmeticallyChangedActors) }' affected.json \
66
+ | node "${{ steps.setup.outputs.scripts-path }}/run-with-apify-tokens.mjs" \
67
+ apify-test-tools build --version-number default
68
+
69
+ # Skips the announcement when the push brought no new commits, or when no channel is set
70
+ - name: Announce the release on Slack
71
+ env:
72
+ SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
73
+ SLACK_CHANNEL: ${{ inputs.report-slack-channel }}
74
+ run: |
75
+ apify-test-tools notify \
76
+ --slack-channel "$SLACK_CHANNEL" \
77
+ < affected.json
40
78
 
41
79
  - name: Delete old builds
42
80
  env:
43
- ALL_SECRETS: ${{ toJSON(secrets) }}
81
+ WORKFLOW_SECRETS: ${{ toJSON(secrets) }}
44
82
  run: |
45
83
  node "${{ steps.setup.outputs.scripts-path }}/run-with-apify-tokens.mjs" \
46
84
  apify-test-tools delete-old-builds