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

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 (77) hide show
  1. package/.github/cli/apify-test-tools.mjs +140 -140
  2. package/.github/scripts/run-with-apify-tokens.mjs +1 -1
  3. package/.github/workflows/public_pr-build-test.yaml +25 -25
  4. package/.github/workflows/public_push-build-latest.yaml +20 -4
  5. package/CHANGELOG.md +2 -0
  6. package/README.md +119 -14
  7. package/bin/affected-actors.ts +157 -0
  8. package/bin/build.ts +55 -38
  9. package/bin/diff-changes.ts +25 -17
  10. package/bin/git.ts +44 -44
  11. package/bin/main.ts +132 -106
  12. package/bin/slack.ts +24 -0
  13. package/bin/stdin-input.ts +65 -0
  14. package/dist/bin/affected-actors.d.ts +45 -0
  15. package/dist/bin/affected-actors.d.ts.map +1 -0
  16. package/dist/bin/affected-actors.js +87 -0
  17. package/dist/bin/affected-actors.js.map +1 -0
  18. package/dist/bin/build.d.ts +12 -5
  19. package/dist/bin/build.d.ts.map +1 -1
  20. package/dist/bin/build.js +45 -23
  21. package/dist/bin/build.js.map +1 -1
  22. package/dist/bin/diff-changes.d.ts +8 -2
  23. package/dist/bin/diff-changes.d.ts.map +1 -1
  24. package/dist/bin/diff-changes.js +16 -16
  25. package/dist/bin/diff-changes.js.map +1 -1
  26. package/dist/bin/git.d.ts +19 -14
  27. package/dist/bin/git.d.ts.map +1 -1
  28. package/dist/bin/git.js +37 -35
  29. package/dist/bin/git.js.map +1 -1
  30. package/dist/bin/main.js +110 -86
  31. package/dist/bin/main.js.map +1 -1
  32. package/dist/bin/slack.d.ts +8 -0
  33. package/dist/bin/slack.d.ts.map +1 -1
  34. package/dist/bin/slack.js +18 -0
  35. package/dist/bin/slack.js.map +1 -1
  36. package/dist/bin/stdin-input.d.ts +17 -0
  37. package/dist/bin/stdin-input.d.ts.map +1 -0
  38. package/dist/bin/stdin-input.js +54 -0
  39. package/dist/bin/stdin-input.js.map +1 -0
  40. package/dist/test/bundle/cli-bundle.test.js +36 -6
  41. package/dist/test/bundle/cli-bundle.test.js.map +1 -1
  42. package/dist/test/e2e/cli-bundle.e2e.test.js +16 -9
  43. package/dist/test/e2e/cli-bundle.e2e.test.js.map +1 -1
  44. package/dist/test/unit/bin/affected-actors.test.d.ts +2 -0
  45. package/dist/test/unit/bin/affected-actors.test.d.ts.map +1 -0
  46. package/dist/test/unit/bin/affected-actors.test.js +154 -0
  47. package/dist/test/unit/bin/affected-actors.test.js.map +1 -0
  48. package/dist/test/unit/bin/build-cli.test.d.ts +2 -0
  49. package/dist/test/unit/bin/build-cli.test.d.ts.map +1 -0
  50. package/dist/test/unit/bin/build-cli.test.js +52 -0
  51. package/dist/test/unit/bin/build-cli.test.js.map +1 -0
  52. package/dist/test/unit/bin/build.test.js +61 -4
  53. package/dist/test/unit/bin/build.test.js.map +1 -1
  54. package/dist/test/unit/bin/diff-changes.test.js +78 -49
  55. package/dist/test/unit/bin/diff-changes.test.js.map +1 -1
  56. package/dist/test/unit/bin/git.test.js +39 -54
  57. package/dist/test/unit/bin/git.test.js.map +1 -1
  58. package/dist/test/unit/bin/slack.test.js +39 -1
  59. package/dist/test/unit/bin/slack.test.js.map +1 -1
  60. package/dist/test/unit/bin/stdin-input.test.d.ts +2 -0
  61. package/dist/test/unit/bin/stdin-input.test.d.ts.map +1 -0
  62. package/dist/test/unit/bin/stdin-input.test.js +50 -0
  63. package/dist/test/unit/bin/stdin-input.test.js.map +1 -0
  64. package/dist/test/unit/should-built-and-test.test.js +23 -17
  65. package/dist/test/unit/should-built-and-test.test.js.map +1 -1
  66. package/dist/tsconfig.tsbuildinfo +1 -1
  67. package/package.json +1 -1
  68. package/test/bundle/cli-bundle.test.ts +59 -6
  69. package/test/e2e/cli-bundle.e2e.test.ts +26 -11
  70. package/test/unit/bin/affected-actors.test.ts +184 -0
  71. package/test/unit/bin/build-cli.test.ts +61 -0
  72. package/test/unit/bin/build.test.ts +71 -3
  73. package/test/unit/bin/diff-changes.test.ts +87 -49
  74. package/test/unit/bin/git.test.ts +44 -55
  75. package/test/unit/bin/slack.test.ts +44 -1
  76. package/test/unit/bin/stdin-input.test.ts +61 -0
  77. package/test/unit/should-built-and-test.test.ts +27 -17
package/bin/main.ts CHANGED
@@ -6,25 +6,15 @@ import yargs, { type Options } from 'yargs';
6
6
  // eslint-disable-next-line import/extensions --- With .js, it cannot find types
7
7
  import { hideBin } from 'yargs/helpers';
8
8
 
9
- import { deleteOldBuilds, runBuilds } from './build.js';
9
+ import { getAffectedActors, toAffectedActorsDocument } from './affected-actors.js';
10
+ import { buildActors, DEFAULT_VERSION_KEYWORD, deleteOldBuilds, TEST_VERSION_NUMBER } from './build.js';
10
11
  import { runBuildsFromLocal } from './build-from-local.js';
11
- import { getChangedActors } from './diff-changes.js';
12
- import {
13
- getBranchOnlyChangedFiles,
14
- getChangedFiles,
15
- getCommits,
16
- getCurrentBranch,
17
- getReleaseChanges,
18
- getRepoName,
19
- hasMergeFromTarget,
20
- resolveReleaseBaseCommit,
21
- resolveRepoUrl,
22
- } from './git.js';
12
+ import { getChangedFiles, getCommits, getCurrentBranch } from './git.js';
23
13
  import { logger, logLevels } from './logger.js';
24
14
  import { writeJson } from './output.js';
25
- import { notifyToSlack } from './slack.js';
15
+ import { announceRelease } from './slack.js';
16
+ import { parseBuildInput, parseReleaseChanges, readStdin } from './stdin-input.js';
26
17
  import { reportTestResults } from './test-report.js';
27
- import type { Config } from './types.js';
28
18
  import { readConfigFile } from './utils/config/load-config.js';
29
19
 
30
20
  /**
@@ -64,6 +54,23 @@ const actorSelectionOptions = {
64
54
  ignore: { type: 'string', array: true, default: [] as string[] },
65
55
  } as const satisfies Record<string, Options>;
66
56
 
57
+ /**
58
+ * Commit range for get-affected-actors, which always ends at the checked-out HEAD. `base` and `since` combine:
59
+ * `base` alone is a branch's own commits (a PR), `since` alone is everything after a commit (a release), both is
60
+ * a branch after its last validated commit.
61
+ */
62
+ const affectedRangeOptions = {
63
+ base: { type: 'string', describe: 'Only count commits on HEAD that are not on this branch' },
64
+ since: {
65
+ type: 'string',
66
+ describe: 'Only count commits after this one. Ignored with --base if it is not on the branch',
67
+ },
68
+ 'test-files-glob': {
69
+ type: 'string',
70
+ describe: 'Glob (from the repo root) of test files that count as changes even when .dockerignore lists them',
71
+ },
72
+ } as const satisfies Record<string, Options>;
73
+
67
74
  /**
68
75
  * For commands that change something (builds, deletes, Slack posts). A dry run still does every read and check
69
76
  * the real run does, credentials included, and only skips the writes. So it needs the same tokens, though
@@ -77,9 +84,34 @@ const dryRunOptions = {
77
84
  },
78
85
  } as const satisfies Record<string, Options>;
79
86
 
80
- /** Flags for commands that trigger Apify builds. */
87
+ /** Flags of `build`, which builds exactly the Actors it is given. */
81
88
  const buildOptions = {
82
- 'use-docker-cache': { type: 'boolean', default: false },
89
+ 'version-number': {
90
+ type: 'string',
91
+ demandOption: true,
92
+ describe: `Version to build, like 0.1, or "${DEFAULT_VERSION_KEYWORD}" for each Actor's default version`,
93
+ coerce: (value: string) => {
94
+ if (value !== DEFAULT_VERSION_KEYWORD && !/^\d+\.\d+$/.test(value)) {
95
+ throw new Error(
96
+ `--version-number must look like 0.1 or be "${DEFAULT_VERSION_KEYWORD}", got "${value}"`,
97
+ );
98
+ }
99
+ return value;
100
+ },
101
+ },
102
+ } as const satisfies Record<string, Options>;
103
+
104
+ /** Range of build-for-test: the checked-out branch's own commits, after its last validated one. */
105
+ const buildForTestOptions = {
106
+ 'target-branch': { type: 'string', demandOption: true },
107
+ 'base-commit': { type: 'string' },
108
+ 'test-files-glob': { type: 'string' },
109
+ } as const satisfies Record<string, Options>;
110
+
111
+ /** Where `release` and `notify-release` post the release. */
112
+ const releaseSlackOptions = {
113
+ 'report-slack-channel': { type: 'string', describe: 'Channel for the full report: commits and changed files' },
114
+ 'release-slack-channel': { type: 'string', describe: 'Channel for the changelog additions only' },
83
115
  } as const satisfies Record<string, Options>;
84
116
 
85
117
  /** Global flags, available to every command. */
@@ -92,48 +124,6 @@ const globalOptions = {
92
124
  },
93
125
  } as const satisfies Record<string, Options>;
94
126
 
95
- const resolveChangedActors = async (config: Config, { isLatest }: { isLatest: boolean }) => {
96
- const actorConfigs = await readConfigFile(config);
97
-
98
- // This is an optimization for the common case where a branch only has cosmetic changes but had to smerge in
99
- // functional changes from master (being up-to-date is a CI requirement). Master is already validated, and
100
- // since the branch has no functional changes of its own, there is nothing new to validate.
101
- // Exception: if the branch has any functional changes alongside the merge, we must re-test — even
102
- // individually validated changes can have novel interactions when combined.
103
- if (await hasMergeFromTarget(config.sourceBranch, config.targetBranch)) {
104
- logger.info(
105
- '[MERGE-FROM-TARGET-OPTIMIZATION]: There is merge from target branch, checking if there are no functional changes in our own branch. If so, we can skip tests',
106
- );
107
- const branchOnlyFiles = await getBranchOnlyChangedFiles(config.sourceBranch, config.targetBranch);
108
- // Omit baseCommit to get full branch history. Validated functional commits can still interact with merged ones
109
- const allBranchCommits = await getCommits({ ...config, baseCommit: undefined });
110
- const branchOnlyActorsChanged = await getChangedActors({
111
- filepathsChanged: branchOnlyFiles,
112
- actorConfigs,
113
- commits: allBranchCommits,
114
- testFilesGlob: config.testFilesGlob,
115
- });
116
- if (branchOnlyActorsChanged.length === 0) {
117
- logger.info('[MERGE-FROM-TARGET-OPTIMIZATION]: Branch itself has no functional changes, skipping tests');
118
- return [];
119
- }
120
- logger.info(
121
- `[MERGE-FROM-TARGET-OPTIMIZATION]: Branch has ${branchOnlyActorsChanged.length} functional changes, cannot optimize, we continue with full check`,
122
- );
123
- }
124
-
125
- // If the optimization doesn't apply, we check all branch commits including merges for full coverage. We don't reuse the merge optimization results because here we can apply baseCommit and check merge commits (they might be functional or just cosmetic)
126
- const commits = await getCommits(config);
127
- const changedFiles = await getChangedFiles(commits);
128
- return getChangedActors({
129
- filepathsChanged: changedFiles,
130
- actorConfigs,
131
- isLatest,
132
- commits,
133
- testFilesGlob: config.testFilesGlob,
134
- });
135
- };
136
-
137
127
  await yargs()
138
128
  .scriptName('public-actors-utils')
139
129
  .options(globalOptions)
@@ -179,11 +169,10 @@ await yargs()
179
169
  )
180
170
  .command(
181
171
  'get-affected-actors',
182
- '',
183
- (y) => y.options(gitRangeOptions).options(actorSelectionOptions),
184
- async (config) => {
185
- const actorsChanged = await resolveChangedActors(config, { isLatest: false });
186
- writeJson(actorsChanged);
172
+ 'Find the Actors whose context changed in a commit range ending at the checked-out HEAD',
173
+ (y) => y.options(affectedRangeOptions).options(actorSelectionOptions),
174
+ async (args) => {
175
+ writeJson(toAffectedActorsDocument(await getAffectedActors(args)));
187
176
  },
188
177
  )
189
178
  .command(
@@ -202,85 +191,122 @@ await yargs()
202
191
  )
203
192
  .command(
204
193
  'build',
205
- '',
194
+ 'Build the Actors listed on stdin, as {"actors": [{"actorFullName": ...}]}, from the checked-out branch',
195
+ (y) => y.options(buildOptions).options(repoUrlOptions).options(dryRunOptions),
196
+ async (args) => {
197
+ const input = parseBuildInput(await readStdin());
198
+ const names = input.actors.map(({ actorFullName }) => actorFullName);
199
+ // An empty --actors selects every Actor, but an empty list here means there is nothing to build
200
+ const actorConfigs = names.length > 0 ? await readConfigFile({ actors: names, ignore: [] }) : [];
201
+ const builds = await buildActors({
202
+ actorConfigs,
203
+ versionNumber: args.versionNumber,
204
+ repoUrl: args.repoUrl,
205
+ dryRun: args.dryRun,
206
+ });
207
+ writeJson(builds);
208
+ },
209
+ )
210
+ .command(
211
+ 'build-for-test',
212
+ 'Build the Actors the checked-out branch changed functionally, for testing',
206
213
  (y) =>
207
214
  y
208
- .options(gitRangeOptions)
215
+ .options(buildForTestOptions)
209
216
  .options(actorSelectionOptions)
210
- .options(buildOptions)
211
217
  .options(repoUrlOptions)
212
- .options(dryRunOptions)
213
- .option('test-files-glob', { type: 'string' }),
218
+ .options(dryRunOptions),
214
219
  async (config) => {
215
- const actorsChanged = await resolveChangedActors(config, { isLatest: false });
216
- const builds = await runBuilds({
217
- ...(await resolveRepoUrl(config.repoUrl)),
218
- actorConfigs: actorsChanged,
219
- branch: config.sourceBranch.replace('origin/', ''),
220
+ logger.info(
221
+ '[BUILD-FOR-TEST]: Same as get-affected-actors --base <target-branch> [--since <base-commit>] ' +
222
+ `| jq '{ actors: .functionallyChangedActors }' | build --version-number ${TEST_VERSION_NUMBER}`,
223
+ );
224
+ // Cosmetic-only changes don't need testing, so they don't need a build either
225
+ const { functionallyChangedActors } = await getAffectedActors({
226
+ base: config.targetBranch,
227
+ since: config.baseCommit,
228
+ testFilesGlob: config.testFilesGlob,
229
+ actors: config.actors,
230
+ ignore: config.ignore,
231
+ });
232
+ const builds = await buildActors({
233
+ actorConfigs: functionallyChangedActors,
234
+ versionNumber: TEST_VERSION_NUMBER,
235
+ repoUrl: config.repoUrl,
220
236
  dryRun: config.dryRun,
221
- useDockerCache: config.useDockerCache,
222
237
  });
223
238
  writeJson(builds);
224
239
  },
225
240
  )
226
241
  .command(
227
242
  'release',
228
- '',
243
+ 'Build the default version of the Actors changed since the last release and announce it on Slack',
229
244
  (y) =>
230
245
  y
231
246
  .options(actorSelectionOptions)
232
- .options(buildOptions)
233
247
  .options(repoUrlOptions)
234
248
  .options(dryRunOptions)
235
249
  // The last commit that is already released, everything after it up to HEAD gets released.
236
250
  // Required, see the README section "Releasing Actors" for how to set it for each merge strategy.
237
251
  .option('base-commit', { type: 'string', demandOption: true })
238
- .option('report-slack-channel', { type: 'string' })
239
- .option('release-slack-channel', { type: 'string' }),
252
+ .options(releaseSlackOptions),
240
253
  async (args) => {
241
- const baseSha = await resolveReleaseBaseCommit(args.baseCommit);
242
- const branch = await getCurrentBranch();
243
- const changes = await getReleaseChanges(baseSha);
244
- if (!changes) {
245
- logger.info(`HEAD is the base commit ${baseSha}, there is nothing new to release`);
254
+ logger.info(
255
+ '[RELEASE]: Same as get-affected-actors --since <base-commit> > affected.json, then ' +
256
+ "jq '{ actors: (.functionallyChangedActors + .cosmeticallyChangedActors) }' affected.json " +
257
+ `| build --version-number ${DEFAULT_VERSION_KEYWORD}, then notify-release < affected.json`,
258
+ );
259
+ // Fail before anything else on a detached HEAD: there is no branch to release
260
+ await getCurrentBranch();
261
+ const { commits, changedFiles, changelog, functionallyChangedActors, cosmeticallyChangedActors } =
262
+ await getAffectedActors({
263
+ since: args.baseCommit,
264
+ actors: args.actors,
265
+ ignore: args.ignore,
266
+ });
267
+ if (commits.length === 0) {
268
+ logger.info(`HEAD is the base commit ${args.baseCommit}, there is nothing new to release`);
246
269
  return;
247
270
  }
248
- const { commits, changedFiles, changelog } = changes;
249
- const { repoUrl, shouldVerifyRepoUrl } = await resolveRepoUrl(args.repoUrl);
250
271
 
251
- const isLatest = true;
252
- const actorConfigs = await readConfigFile(args);
253
- const actorsChanged = await getChangedActors({
254
- filepathsChanged: changedFiles,
255
- actorConfigs,
256
- isLatest,
257
- commits,
258
- });
259
272
  const { dryRun, reportSlackChannel, releaseSlackChannel } = args;
260
- const builds = await runBuilds({
261
- isLatest,
262
- repoUrl,
263
- shouldVerifyRepoUrl,
264
- actorConfigs: actorsChanged,
265
- branch,
273
+ const builds = await buildActors({
274
+ // A release ships cosmetic changes (README, input schema descriptions, ...) too
275
+ actorConfigs: [...functionallyChangedActors, ...cosmeticallyChangedActors],
276
+ versionNumber: DEFAULT_VERSION_KEYWORD,
277
+ repoUrl: args.repoUrl,
266
278
  dryRun,
267
- useDockerCache: args.useDockerCache,
268
279
  });
269
280
  logger.info(JSON.stringify(builds));
270
281
 
271
- await notifyToSlack({
272
- changedFiles,
282
+ await announceRelease({
273
283
  commits,
284
+ changedFiles,
274
285
  changelog,
275
- repository: getRepoName(repoUrl),
286
+ repoUrl: args.repoUrl,
276
287
  dryRun,
277
- // The newest commit, same as the pushed head commit
278
- author: commits[commits.length - 1].author,
279
288
  reportSlackChannel,
280
289
  releaseSlackChannel,
281
290
  });
282
291
  },
283
292
  )
293
+ .command(
294
+ 'notify-release',
295
+ 'Announce a release on Slack, from the get-affected-actors output on stdin',
296
+ (y) => y.options(releaseSlackOptions).options(repoUrlOptions).options(dryRunOptions),
297
+ async (args) => {
298
+ const { commits, changedFiles, changelog } = parseReleaseChanges(await readStdin());
299
+ await announceRelease({
300
+ commits,
301
+ changedFiles,
302
+ changelog,
303
+ repoUrl: args.repoUrl,
304
+ dryRun: args.dryRun,
305
+ reportSlackChannel: args.reportSlackChannel,
306
+ releaseSlackChannel: args.releaseSlackChannel,
307
+ });
308
+ },
309
+ )
284
310
  .command(
285
311
  'build-from-local',
286
312
  '',
package/bin/slack.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { WebClient } from '@slack/web-api';
2
2
 
3
+ import { getRepoName, resolveRepoUrl } from './git.js';
3
4
  import { logger } from './logger.js';
4
5
  import type { Commit } from './types.js';
5
6
  import { getEnvVar } from './utils.js';
@@ -96,6 +97,29 @@ export const notifyToSlack = async ({
96
97
  }
97
98
  };
98
99
 
100
+ type AnnounceReleaseOptions = Omit<NotifyToSlackOptions, 'author' | 'repository'> & {
101
+ // Defaults to the `origin` remote, see resolveRepoUrl
102
+ repoUrl?: string;
103
+ };
104
+
105
+ /**
106
+ * Posts what a release changed: its commits, changed files and changelog, as get-affected-actors reports them.
107
+ * Posts nothing when there are no commits, which means there is nothing new to release.
108
+ */
109
+ export const announceRelease = async ({ commits, repoUrl, ...options }: AnnounceReleaseOptions) => {
110
+ if (commits.length === 0) {
111
+ logger.info('No new commits, so there is no release to announce');
112
+ return;
113
+ }
114
+ await notifyToSlack({
115
+ ...options,
116
+ commits,
117
+ repository: getRepoName((await resolveRepoUrl(repoUrl)).repoUrl),
118
+ // The newest commit, same as the pushed head commit
119
+ author: commits[commits.length - 1].author,
120
+ });
121
+ };
122
+
99
123
  export const sendSlackMessage = async (slack: WebClient, channel: string, text: string, blocks: string[]) => {
100
124
  const { ts } = await slack.chat.postMessage({ text, channel });
101
125
  if (blocks.length > 0 && ts) {
@@ -0,0 +1,65 @@
1
+ import process from 'node:process';
2
+
3
+ import z, { prettifyError, type ZodType } from 'zod';
4
+
5
+ export const readStdin = async (): Promise<string> => {
6
+ // Nothing piped in: fail right away instead of waiting for someone to type
7
+ if (process.stdin.isTTY) {
8
+ throw new Error('Expected JSON on stdin, but nothing was piped in.');
9
+ }
10
+ let raw = '';
11
+ for await (const chunk of process.stdin) {
12
+ raw += chunk;
13
+ }
14
+ return raw;
15
+ };
16
+
17
+ const parseStdinJson = <T>(
18
+ raw: string,
19
+ schema: ZodType<T>,
20
+ { expected, example }: { expected: string; example: string },
21
+ ) => {
22
+ // Empty input is an error, not "nothing to do": it is what a failed command earlier in the pipe leaves behind
23
+ if (!raw.trim()) {
24
+ throw new Error(`Expected ${expected} as JSON on stdin, got nothing (${example}).`);
25
+ }
26
+ let json: unknown;
27
+ try {
28
+ json = JSON.parse(raw);
29
+ } catch (error) {
30
+ throw new Error(`The input on stdin is not valid JSON: ${(error as Error).message}`);
31
+ }
32
+ const result = schema.safeParse(json);
33
+ if (!result.success) {
34
+ throw new Error(`The input on stdin is not ${expected} (${example}):\n${prettifyError(result.error)}`);
35
+ }
36
+ return result.data;
37
+ };
38
+
39
+ /**
40
+ * What `build` reads: the Actors to build. Only their names are read, the config file stays the source of truth
41
+ * for everything else about them. Other fields are ignored, so a get-affected-actors document only needs its Actor
42
+ * list picked, e.g. `jq '{ actors: .functionallyChangedActors }'`.
43
+ */
44
+ const buildInputSchema = z.object({
45
+ actors: z.array(z.object({ actorFullName: z.string() })),
46
+ });
47
+
48
+ export const parseBuildInput = (raw: string) =>
49
+ parseStdinJson(raw, buildInputSchema, {
50
+ expected: 'the Actors to build',
51
+ example: `e.g. echo '{"actors":[{"actorFullName":"owner/name"}]}' | apify-test-tools build --version-number 0.1`,
52
+ });
53
+
54
+ /** What `notify-release` reads: the parts of a get-affected-actors document that describe what changed. */
55
+ const releaseChangesSchema = z.object({
56
+ commits: z.array(z.object({ sha: z.string(), author: z.string(), date: z.string(), message: z.string() })),
57
+ changedFiles: z.array(z.string()),
58
+ changelog: z.string().nullable(),
59
+ });
60
+
61
+ export const parseReleaseChanges = (raw: string) =>
62
+ parseStdinJson(raw, releaseChangesSchema, {
63
+ expected: 'the output of get-affected-actors',
64
+ example: 'e.g. apify-test-tools get-affected-actors --since <sha> | apify-test-tools notify-release',
65
+ });
@@ -0,0 +1,45 @@
1
+ import type { ActorConfig, Commit } from './types.js';
2
+ interface AffectedActorsOptions {
3
+ /** Only the commits on HEAD that are not on base count, i.e. the branch's own changes. */
4
+ base?: string;
5
+ /**
6
+ * Only changes after this commit count. With `base` it's the last validated commit of the branch and is
7
+ * ignored when it isn't on the branch. Without `base` it must be an ancestor of HEAD (e.g. the last release).
8
+ */
9
+ since?: string;
10
+ /** Glob relative to the repo root. Matching files count as changes even when .dockerignore lists them. */
11
+ testFilesGlob?: string;
12
+ actors: string[];
13
+ ignore: string[];
14
+ }
15
+ interface AffectedActors {
16
+ headSha: string;
17
+ commits: Commit[];
18
+ changedFiles: string[];
19
+ changelog: string | null;
20
+ /** Actors with at least one functional change. They need a new build and tests. */
21
+ functionallyChangedActors: ActorConfig[];
22
+ /** Actors whose changes are all cosmetic (README, CHANGELOG, cosmetic .actor JSON). They only need a release build. */
23
+ cosmeticallyChangedActors: ActorConfig[];
24
+ }
25
+ /**
26
+ * Finds the Actors whose context changed in the given range. `base` selects the branch's own commits
27
+ * (a PR), `since` the commits after a known one (a release, or the last validated commit of a PR).
28
+ */
29
+ export declare const getAffectedActors: ({ base, since: sinceOption, testFilesGlob, actors, ignore, }: AffectedActorsOptions) => Promise<AffectedActors>;
30
+ /** The JSON document `get-affected-actors` prints. Versioned, since other commands and workflows consume it. */
31
+ export declare const toAffectedActorsDocument: ({ headSha, commits, changedFiles, changelog, functionallyChangedActors, cosmeticallyChangedActors, }: AffectedActors) => {
32
+ version: number;
33
+ head: string;
34
+ commits: Commit[];
35
+ changedFiles: string[];
36
+ changelog: string | null;
37
+ functionallyChangedActors: {
38
+ actorFullName: string;
39
+ }[];
40
+ cosmeticallyChangedActors: {
41
+ actorFullName: string;
42
+ }[];
43
+ };
44
+ export {};
45
+ //# sourceMappingURL=affected-actors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"affected-actors.d.ts","sourceRoot":"","sources":["../../bin/affected-actors.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAMtD,UAAU,qBAAqB;IAC3B,0FAA0F;IAC1F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0GAA0G;IAC1G,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,UAAU,cAAc;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mFAAmF;IACnF,yBAAyB,EAAE,WAAW,EAAE,CAAC;IACzC,uHAAuH;IACvH,yBAAyB,EAAE,WAAW,EAAE,CAAC;CAC5C;AA2DD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAU,8DAMrC,qBAAqB,KAAG,OAAO,CAAC,cAAc,CAyBhD,CAAC;AAEF,gHAAgH;AAChH,eAAO,MAAM,wBAAwB,GAAI,sGAOtC,cAAc;;;;;;;;;;;;CAWhB,CAAC"}
@@ -0,0 +1,87 @@
1
+ import { getChangedActors } from './diff-changes.js';
2
+ import { getBranchOnlyChangedFiles, getChangedFilesBetween, getChangelogAdditions, getCommits, getCommitsBetween, hasMergeFromTarget, resolveCommitSha, resolveReleaseBaseCommit, } from './git.js';
3
+ import { logger } from './logger.js';
4
+ import { readConfigFile } from './utils/config/load-config.js';
5
+ // The range always ends at the checked-out commit: check out what you want to inspect
6
+ const HEAD = 'HEAD';
7
+ /** The branch's own commits, after `since` when it is on the branch (see getCommits). */
8
+ const getBranchRange = async (base, since) => {
9
+ const commits = await getCommits({ sourceBranch: HEAD, targetBranch: base, baseCommit: since });
10
+ return { commits, fromRef: `${commits[0].sha}~`, toRef: commits[commits.length - 1].sha };
11
+ };
12
+ /** Everything after `since` up to HEAD. Unlike on a branch, `since` must be an ancestor of HEAD. */
13
+ const getRangeSince = async (headSha, since) => {
14
+ const sinceSha = await resolveReleaseBaseCommit(since);
15
+ const commits = sinceSha === headSha ? [] : await getCommitsBetween(sinceSha, headSha);
16
+ return { commits, fromRef: sinceSha, toRef: headSha };
17
+ };
18
+ /**
19
+ * This is an optimization for the common case where a branch only has cosmetic changes but had to merge in
20
+ * functional changes from base (being up-to-date is a CI requirement). Base is already validated, and
21
+ * since the branch has no functional changes of its own, there is nothing new to validate.
22
+ * Exception: if the branch has any functional changes alongside the merge, we must re-test — even
23
+ * individually validated changes can have novel interactions when combined.
24
+ * Returns the Actors the branch's own commits changed, or undefined when it didn't merge base in.
25
+ *
26
+ * TODO: Apply this per Actor instead of to the whole branch. Changes merged in from base only interact with the
27
+ * branch's own changes in Actors whose context both touch, so an Actor that only base changed is already validated
28
+ * and can be skipped even when the branch changes other Actors functionally. Today any functional change of the
29
+ * branch's own keeps every Actor, and the log messages below describe the whole branch.
30
+ */
31
+ const getOwnChangesIfMergedFromBase = async (base, actorConfigs, testFilesGlob) => {
32
+ if (!(await hasMergeFromTarget(HEAD, base)))
33
+ return undefined;
34
+ logger.info('[MERGE-FROM-TARGET-OPTIMIZATION]: There is merge from target branch, checking if there are no functional changes in our own branch. If so, we can skip tests');
35
+ const own = await getChangedActors({
36
+ filepathsChanged: await getBranchOnlyChangedFiles(HEAD, base),
37
+ actorConfigs,
38
+ // Omit since to get full branch history. Validated functional commits can still interact with merged ones
39
+ commits: await getCommits({ sourceBranch: HEAD, targetBranch: base }),
40
+ testFilesGlob,
41
+ });
42
+ logger.info(own.functional.length > 0
43
+ ? `[MERGE-FROM-TARGET-OPTIMIZATION]: Branch has ${own.functional.length} functional changes, cannot optimize, we continue with full check`
44
+ : '[MERGE-FROM-TARGET-OPTIMIZATION]: Branch itself has no functional changes, skipping tests');
45
+ return own;
46
+ };
47
+ /**
48
+ * Finds the Actors whose context changed in the given range. `base` selects the branch's own commits
49
+ * (a PR), `since` the commits after a known one (a release, or the last validated commit of a PR).
50
+ */
51
+ export const getAffectedActors = async ({ base, since: sinceOption, testFilesGlob, actors, ignore, }) => {
52
+ // An empty --since (e.g. an empty cache file) means the same as not passing it
53
+ const since = sinceOption || undefined;
54
+ if (!base && !since) {
55
+ throw new Error('Pass --base, --since, or both to select the commits to inspect.');
56
+ }
57
+ const headSha = await resolveCommitSha(HEAD);
58
+ const { commits, fromRef, toRef } = base ? await getBranchRange(base, since) : await getRangeSince(headSha, since);
59
+ const actorConfigs = await readConfigFile({ actors, ignore });
60
+ // What the branch only merged in from base is already validated. Without functional changes of its own
61
+ // the branch has nothing to test, and without any changes of its own nothing to release either.
62
+ const own = base ? await getOwnChangesIfMergedFromBase(base, actorConfigs, testFilesGlob) : undefined;
63
+ const changedFiles = await getChangedFilesBetween(fromRef, toRef);
64
+ const changed = await getChangedActors({ filepathsChanged: changedFiles, actorConfigs, commits, testFilesGlob });
65
+ return {
66
+ headSha,
67
+ commits,
68
+ changedFiles,
69
+ changelog: await getChangelogAdditions(fromRef, toRef, changedFiles),
70
+ functionallyChangedActors: own && own.functional.length === 0 ? [] : changed.functional,
71
+ cosmeticallyChangedActors: own && own.functional.length + own.cosmetic.length === 0 ? [] : changed.cosmetic,
72
+ };
73
+ };
74
+ /** The JSON document `get-affected-actors` prints. Versioned, since other commands and workflows consume it. */
75
+ export const toAffectedActorsDocument = ({ headSha, commits, changedFiles, changelog, functionallyChangedActors, cosmeticallyChangedActors, }) => {
76
+ const names = (configs) => configs.map(({ actorFullName }) => ({ actorFullName }));
77
+ return {
78
+ version: 1,
79
+ head: headSha,
80
+ commits,
81
+ changedFiles,
82
+ changelog,
83
+ functionallyChangedActors: names(functionallyChangedActors),
84
+ cosmeticallyChangedActors: names(cosmeticallyChangedActors),
85
+ };
86
+ };
87
+ //# sourceMappingURL=affected-actors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"affected-actors.js","sourceRoot":"","sources":["../../bin/affected-actors.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,8 @@
1
1
  import type * as ApifyClientTypes from 'apify-client';
2
2
  import type { ActorConfig, BuildData, DryRunPlan } from './types.js';
3
3
  export declare const LOCAL_SOURCE_VERSION_NUMBER = "0.98";
4
+ export declare const TEST_VERSION_NUMBER = "0.99";
5
+ export declare const DEFAULT_VERSION_KEYWORD = "default";
4
6
  /**
5
7
  * Finds the Actor's default version: the one whose build the default build tag points to.
6
8
  * Usually tagged 'latest' but not necessarily (can be e.g. 'version-0').
@@ -47,20 +49,25 @@ export declare const runAndSummarizeBuilds: (actorConfigs: ActorConfig[], label:
47
49
  type GitBuildPlan = {
48
50
  actorFullName: string;
49
51
  versionNumber: string;
50
- buildTag?: string;
51
52
  gitRepoUrl: string;
52
- useDockerCache: boolean;
53
53
  };
54
54
  type RunBuildsOptions = {
55
55
  actorConfigs: ActorConfig[];
56
- isLatest?: boolean;
56
+ versionNumber: string;
57
57
  repoUrl: string;
58
58
  shouldVerifyRepoUrl: boolean;
59
59
  branch: string;
60
60
  dryRun: boolean;
61
- useDockerCache: boolean;
62
61
  };
63
- export declare const runBuilds: ({ repoUrl, shouldVerifyRepoUrl, branch, actorConfigs, isLatest, dryRun, useDockerCache, }: RunBuildsOptions) => Promise<BuildData[] | DryRunPlan<GitBuildPlan>>;
62
+ export declare const runBuilds: ({ repoUrl, shouldVerifyRepoUrl, branch, actorConfigs, versionNumber, dryRun, }: RunBuildsOptions) => Promise<BuildData[] | DryRunPlan<GitBuildPlan>>;
63
+ type BuildActorsOptions = Omit<RunBuildsOptions, 'repoUrl' | 'shouldVerifyRepoUrl' | 'branch'> & {
64
+ repoUrl?: string;
65
+ };
66
+ /**
67
+ * Builds exactly the given Actors from the checked-out Git branch, as it is on the remote. Fails on a detached HEAD,
68
+ * where there is no branch to build. Used by `build` and the commands built on top of it.
69
+ */
70
+ export declare const buildActors: ({ actorConfigs, repoUrl, ...options }: BuildActorsOptions) => Promise<BuildData[] | DryRunPlan<GitBuildPlan>>;
64
71
  export declare const deleteOldBuilds: (actorConfigs: ActorConfig[], { dryRun }: {
65
72
  dryRun: boolean;
66
73
  }) => Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../bin/build.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,gBAAgB,MAAM,cAAc,CAAC;AAKtD,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAYrE,eAAO,MAAM,2BAA2B,SAAS,CAAC;AAQlD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAAI,eAAe,MAAM,EAAE,WAAW,gBAAgB,CAAC,KAAK;;;;;CAsB7F,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,kCAAkC,GAC3C,eAAe,MAAM,EACrB,gBAAgB,gBAAgB,CAAC,YAAY,GAAG,SAAS,EACzD,SAAS,MAAM,SAoBlB,CAAC;AAEF,qBAAa,YAAY;IAEjB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAFlC,OAAO;IAKP,YAAY,QAAa,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAQtD;IAEF,uBAAuB;;;;;OAAoF;IAI3G,eAAe,GAAU,eAAe,MAAM,EAAE,KAAK,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC,CAY3E;IAGF,qBAAqB,GACjB,eAAe,MAAM,EACrB,cAAc,gBAAgB,CAAC,YAAY,EAC3C,UAAU,OAAO,EACjB,YAAY,gBAAgB,CAAC,KAAK,KACnC,OAAO,CAAC,SAAS,CAAC,CAmBnB;IAEF,oBAAoB,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAmB7E;IAEF,MAAM,CAAC,eAAe,GAAI,aAAa,WAAW,KAAG,YAAY,CAQ/D;IAEF;;;OAGG;IACG,eAAe,CAAC,EAAE,MAAM,EAAE,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CA4FxE;AAED,eAAO,MAAM,sBAAsB,GAC/B,eAAe,SAAS,EAAE,EAC1B,aAAa,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,EACtC,OAAO,MAAM,KACd,OAAO,CAAC,SAAS,EAAE,CAkBrB,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAC9B,cAAc,WAAW,EAAE,EAC3B,OAAO,MAAM,EACb,eAAe,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY,KAAK,OAAO,CAAC,SAAS,CAAC,KACvF,OAAO,CAAC,SAAS,EAAE,CAarB,CAAC;AAEF,KAAK,YAAY,GAAG;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACpB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAEhB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,OAAO,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,SAAS,GAAU,2FAQ7B,gBAAgB,KAAG,OAAO,CAAC,SAAS,EAAE,GAAG,UAAU,CAAC,YAAY,CAAC,CAqEnE,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,cAAc,WAAW,EAAE,EAAE,YAAY;IAAE,MAAM,EAAE,OAAO,CAAA;CAAE,kBAIjG,CAAC"}
1
+ {"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../bin/build.ts"],"names":[],"mappings":"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"}