apify-test-tools 0.10.2-beta.3 → 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 (64) hide show
  1. package/.github/cli/apify-test-tools.mjs +126 -125
  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 +1 -0
  6. package/README.md +67 -17
  7. package/bin/affected-actors.ts +16 -25
  8. package/bin/build.ts +55 -38
  9. package/bin/git.ts +3 -14
  10. package/bin/main.ts +96 -40
  11. package/bin/slack.ts +24 -0
  12. package/bin/stdin-input.ts +65 -0
  13. package/dist/bin/affected-actors.d.ts +4 -9
  14. package/dist/bin/affected-actors.d.ts.map +1 -1
  15. package/dist/bin/affected-actors.js +17 -19
  16. package/dist/bin/affected-actors.js.map +1 -1
  17. package/dist/bin/build.d.ts +12 -5
  18. package/dist/bin/build.d.ts.map +1 -1
  19. package/dist/bin/build.js +45 -23
  20. package/dist/bin/build.js.map +1 -1
  21. package/dist/bin/git.d.ts +1 -6
  22. package/dist/bin/git.d.ts.map +1 -1
  23. package/dist/bin/git.js +3 -13
  24. package/dist/bin/git.js.map +1 -1
  25. package/dist/bin/main.js +78 -40
  26. package/dist/bin/main.js.map +1 -1
  27. package/dist/bin/slack.d.ts +8 -0
  28. package/dist/bin/slack.d.ts.map +1 -1
  29. package/dist/bin/slack.js +18 -0
  30. package/dist/bin/slack.js.map +1 -1
  31. package/dist/bin/stdin-input.d.ts +17 -0
  32. package/dist/bin/stdin-input.d.ts.map +1 -0
  33. package/dist/bin/stdin-input.js +54 -0
  34. package/dist/bin/stdin-input.js.map +1 -0
  35. package/dist/test/bundle/cli-bundle.test.js +27 -4
  36. package/dist/test/bundle/cli-bundle.test.js.map +1 -1
  37. package/dist/test/e2e/cli-bundle.e2e.test.js +16 -9
  38. package/dist/test/e2e/cli-bundle.e2e.test.js.map +1 -1
  39. package/dist/test/unit/bin/affected-actors.test.js +7 -13
  40. package/dist/test/unit/bin/affected-actors.test.js.map +1 -1
  41. package/dist/test/unit/bin/build-cli.test.d.ts +2 -0
  42. package/dist/test/unit/bin/build-cli.test.d.ts.map +1 -0
  43. package/dist/test/unit/bin/build-cli.test.js +52 -0
  44. package/dist/test/unit/bin/build-cli.test.js.map +1 -0
  45. package/dist/test/unit/bin/build.test.js +61 -4
  46. package/dist/test/unit/bin/build.test.js.map +1 -1
  47. package/dist/test/unit/bin/git.test.js +2 -14
  48. package/dist/test/unit/bin/git.test.js.map +1 -1
  49. package/dist/test/unit/bin/slack.test.js +39 -1
  50. package/dist/test/unit/bin/slack.test.js.map +1 -1
  51. package/dist/test/unit/bin/stdin-input.test.d.ts +2 -0
  52. package/dist/test/unit/bin/stdin-input.test.d.ts.map +1 -0
  53. package/dist/test/unit/bin/stdin-input.test.js +50 -0
  54. package/dist/test/unit/bin/stdin-input.test.js.map +1 -0
  55. package/dist/tsconfig.tsbuildinfo +1 -1
  56. package/package.json +1 -1
  57. package/test/bundle/cli-bundle.test.ts +50 -4
  58. package/test/e2e/cli-bundle.e2e.test.ts +26 -11
  59. package/test/unit/bin/affected-actors.test.ts +7 -13
  60. package/test/unit/bin/build-cli.test.ts +61 -0
  61. package/test/unit/bin/build.test.ts +71 -3
  62. package/test/unit/bin/git.test.ts +1 -15
  63. package/test/unit/bin/slack.test.ts +44 -1
  64. package/test/unit/bin/stdin-input.test.ts +61 -0
package/bin/main.ts CHANGED
@@ -7,12 +7,13 @@ import yargs, { type Options } from 'yargs';
7
7
  import { hideBin } from 'yargs/helpers';
8
8
 
9
9
  import { getAffectedActors, toAffectedActorsDocument } from './affected-actors.js';
10
- import { deleteOldBuilds, runBuilds } from './build.js';
10
+ import { buildActors, DEFAULT_VERSION_KEYWORD, deleteOldBuilds, TEST_VERSION_NUMBER } from './build.js';
11
11
  import { runBuildsFromLocal } from './build-from-local.js';
12
- import { getChangedFiles, getCommits, getCurrentBranch, getRepoName, resolveRepoUrl } from './git.js';
12
+ import { getChangedFiles, getCommits, getCurrentBranch } from './git.js';
13
13
  import { logger, logLevels } from './logger.js';
14
14
  import { writeJson } from './output.js';
15
- import { notifyToSlack } from './slack.js';
15
+ import { announceRelease } from './slack.js';
16
+ import { parseBuildInput, parseReleaseChanges, readStdin } from './stdin-input.js';
16
17
  import { reportTestResults } from './test-report.js';
17
18
  import { readConfigFile } from './utils/config/load-config.js';
18
19
 
@@ -83,9 +84,34 @@ const dryRunOptions = {
83
84
  },
84
85
  } as const satisfies Record<string, Options>;
85
86
 
86
- /** Flags for commands that trigger Apify builds. */
87
+ /** Flags of `build`, which builds exactly the Actors it is given. */
87
88
  const buildOptions = {
88
- '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' },
89
115
  } as const satisfies Record<string, Options>;
90
116
 
91
117
  /** Global flags, available to every command. */
@@ -146,7 +172,7 @@ await yargs()
146
172
  'Find the Actors whose context changed in a commit range ending at the checked-out HEAD',
147
173
  (y) => y.options(affectedRangeOptions).options(actorSelectionOptions),
148
174
  async (args) => {
149
- writeJson(toAffectedActorsDocument(await getAffectedActors({ ...args, head: 'HEAD' })));
175
+ writeJson(toAffectedActorsDocument(await getAffectedActors(args)));
150
176
  },
151
177
  )
152
178
  .command(
@@ -165,92 +191,122 @@ await yargs()
165
191
  )
166
192
  .command(
167
193
  'build',
168
- '',
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',
169
213
  (y) =>
170
214
  y
171
- .options(gitRangeOptions)
215
+ .options(buildForTestOptions)
172
216
  .options(actorSelectionOptions)
173
- .options(buildOptions)
174
217
  .options(repoUrlOptions)
175
- .options(dryRunOptions)
176
- .option('test-files-glob', { type: 'string' }),
218
+ .options(dryRunOptions),
177
219
  async (config) => {
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
+ );
178
224
  // Cosmetic-only changes don't need testing, so they don't need a build either
179
- const { functionallyChangedActors: actorsChanged } = await getAffectedActors({
180
- head: config.sourceBranch,
225
+ const { functionallyChangedActors } = await getAffectedActors({
181
226
  base: config.targetBranch,
182
227
  since: config.baseCommit,
183
228
  testFilesGlob: config.testFilesGlob,
184
229
  actors: config.actors,
185
230
  ignore: config.ignore,
186
231
  });
187
- const builds = await runBuilds({
188
- ...(await resolveRepoUrl(config.repoUrl)),
189
- actorConfigs: actorsChanged,
190
- branch: config.sourceBranch.replace('origin/', ''),
232
+ const builds = await buildActors({
233
+ actorConfigs: functionallyChangedActors,
234
+ versionNumber: TEST_VERSION_NUMBER,
235
+ repoUrl: config.repoUrl,
191
236
  dryRun: config.dryRun,
192
- useDockerCache: config.useDockerCache,
193
237
  });
194
238
  writeJson(builds);
195
239
  },
196
240
  )
197
241
  .command(
198
242
  'release',
199
- '',
243
+ 'Build the default version of the Actors changed since the last release and announce it on Slack',
200
244
  (y) =>
201
245
  y
202
246
  .options(actorSelectionOptions)
203
- .options(buildOptions)
204
247
  .options(repoUrlOptions)
205
248
  .options(dryRunOptions)
206
249
  // The last commit that is already released, everything after it up to HEAD gets released.
207
250
  // Required, see the README section "Releasing Actors" for how to set it for each merge strategy.
208
251
  .option('base-commit', { type: 'string', demandOption: true })
209
- .option('report-slack-channel', { type: 'string' })
210
- .option('release-slack-channel', { type: 'string' }),
252
+ .options(releaseSlackOptions),
211
253
  async (args) => {
212
- const branch = await getCurrentBranch();
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();
213
261
  const { commits, changedFiles, changelog, functionallyChangedActors, cosmeticallyChangedActors } =
214
262
  await getAffectedActors({
215
- head: 'HEAD',
216
263
  since: args.baseCommit,
217
264
  actors: args.actors,
218
265
  ignore: args.ignore,
219
266
  });
220
- // A release ships cosmetic changes (README, input schema descriptions, ...) too
221
- const actorsChanged = [...functionallyChangedActors, ...cosmeticallyChangedActors];
222
267
  if (commits.length === 0) {
223
268
  logger.info(`HEAD is the base commit ${args.baseCommit}, there is nothing new to release`);
224
269
  return;
225
270
  }
226
- const { repoUrl, shouldVerifyRepoUrl } = await resolveRepoUrl(args.repoUrl);
227
271
 
228
- const isLatest = true;
229
272
  const { dryRun, reportSlackChannel, releaseSlackChannel } = args;
230
- const builds = await runBuilds({
231
- isLatest,
232
- repoUrl,
233
- shouldVerifyRepoUrl,
234
- actorConfigs: actorsChanged,
235
- 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,
236
278
  dryRun,
237
- useDockerCache: args.useDockerCache,
238
279
  });
239
280
  logger.info(JSON.stringify(builds));
240
281
 
241
- await notifyToSlack({
242
- changedFiles,
282
+ await announceRelease({
243
283
  commits,
284
+ changedFiles,
244
285
  changelog,
245
- repository: getRepoName(repoUrl),
286
+ repoUrl: args.repoUrl,
246
287
  dryRun,
247
- // The newest commit, same as the pushed head commit
248
- author: commits[commits.length - 1].author,
249
288
  reportSlackChannel,
250
289
  releaseSlackChannel,
251
290
  });
252
291
  },
253
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
+ )
254
310
  .command(
255
311
  'build-from-local',
256
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
+ });
@@ -1,12 +1,10 @@
1
1
  import type { ActorConfig, Commit } from './types.js';
2
2
  interface AffectedActorsOptions {
3
- /** End of the range. */
4
- head: string;
5
- /** Only the commits on head that are not on base count, i.e. the branch's own changes. */
3
+ /** Only the commits on HEAD that are not on base count, i.e. the branch's own changes. */
6
4
  base?: string;
7
5
  /**
8
6
  * Only changes after this commit count. With `base` it's the last validated commit of the branch and is
9
- * ignored when it isn't on the branch. Without `base` it must be an ancestor of head (e.g. the last release).
7
+ * ignored when it isn't on the branch. Without `base` it must be an ancestor of HEAD (e.g. the last release).
10
8
  */
11
9
  since?: string;
12
10
  /** Glob relative to the repo root. Matching files count as changes even when .dockerignore lists them. */
@@ -16,8 +14,6 @@ interface AffectedActorsOptions {
16
14
  }
17
15
  interface AffectedActors {
18
16
  headSha: string;
19
- /** Branch head points to, which is what git builds are made from. Null for a SHA or a detached HEAD. */
20
- ref: string | null;
21
17
  commits: Commit[];
22
18
  changedFiles: string[];
23
19
  changelog: string | null;
@@ -30,11 +26,10 @@ interface AffectedActors {
30
26
  * Finds the Actors whose context changed in the given range. `base` selects the branch's own commits
31
27
  * (a PR), `since` the commits after a known one (a release, or the last validated commit of a PR).
32
28
  */
33
- export declare const getAffectedActors: ({ head, base, since: sinceOption, testFilesGlob, actors, ignore, }: AffectedActorsOptions) => Promise<AffectedActors>;
29
+ export declare const getAffectedActors: ({ base, since: sinceOption, testFilesGlob, actors, ignore, }: AffectedActorsOptions) => Promise<AffectedActors>;
34
30
  /** The JSON document `get-affected-actors` prints. Versioned, since other commands and workflows consume it. */
35
- export declare const toAffectedActorsDocument: ({ headSha, ref, commits, changedFiles, changelog, functionallyChangedActors, cosmeticallyChangedActors, }: AffectedActors) => {
31
+ export declare const toAffectedActorsDocument: ({ headSha, commits, changedFiles, changelog, functionallyChangedActors, cosmeticallyChangedActors, }: AffectedActors) => {
36
32
  version: number;
37
- ref: string | null;
38
33
  head: string;
39
34
  commits: Commit[];
40
35
  changedFiles: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"affected-actors.d.ts","sourceRoot":"","sources":["../../bin/affected-actors.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGtD,UAAU,qBAAqB;IAC3B,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,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,wGAAwG;IACxG,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,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;AA4DD;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAAU,oEAOrC,qBAAqB,KAAG,OAAO,CAAC,cAAc,CA4BhD,CAAC;AAEF,gHAAgH;AAChH,eAAO,MAAM,wBAAwB,GAAI,2GAQtC,cAAc;;;;;;;;;;;;;CAYhB,CAAC"}
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"}
@@ -1,15 +1,17 @@
1
1
  import { getChangedActors } from './diff-changes.js';
2
- import { getBranchOnlyChangedFiles, getChangedFilesBetween, getChangelogAdditions, getCommits, getCommitsBetween, hasMergeFromTarget, resolveBranchName, resolveCommitSha, resolveReleaseBaseCommit, } from './git.js';
2
+ import { getBranchOnlyChangedFiles, getChangedFilesBetween, getChangelogAdditions, getCommits, getCommitsBetween, hasMergeFromTarget, resolveCommitSha, resolveReleaseBaseCommit, } from './git.js';
3
3
  import { logger } from './logger.js';
4
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';
5
7
  /** The branch's own commits, after `since` when it is on the branch (see getCommits). */
6
- const getBranchRange = async (head, base, since) => {
7
- const commits = await getCommits({ sourceBranch: head, targetBranch: base, baseCommit: since });
8
+ const getBranchRange = async (base, since) => {
9
+ const commits = await getCommits({ sourceBranch: HEAD, targetBranch: base, baseCommit: since });
8
10
  return { commits, fromRef: `${commits[0].sha}~`, toRef: commits[commits.length - 1].sha };
9
11
  };
10
- /** Everything after `since` up to head. Unlike on a branch, `since` must be an ancestor of head. */
11
- const getRangeSince = async (head, headSha, since) => {
12
- const sinceSha = await resolveReleaseBaseCommit(since, head);
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);
13
15
  const commits = sinceSha === headSha ? [] : await getCommitsBetween(sinceSha, headSha);
14
16
  return { commits, fromRef: sinceSha, toRef: headSha };
15
17
  };
@@ -26,15 +28,15 @@ const getRangeSince = async (head, headSha, since) => {
26
28
  * and can be skipped even when the branch changes other Actors functionally. Today any functional change of the
27
29
  * branch's own keeps every Actor, and the log messages below describe the whole branch.
28
30
  */
29
- const getOwnChangesIfMergedFromBase = async (head, base, actorConfigs, testFilesGlob) => {
30
- if (!(await hasMergeFromTarget(head, base)))
31
+ const getOwnChangesIfMergedFromBase = async (base, actorConfigs, testFilesGlob) => {
32
+ if (!(await hasMergeFromTarget(HEAD, base)))
31
33
  return undefined;
32
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');
33
35
  const own = await getChangedActors({
34
- filepathsChanged: await getBranchOnlyChangedFiles(head, base),
36
+ filepathsChanged: await getBranchOnlyChangedFiles(HEAD, base),
35
37
  actorConfigs,
36
38
  // Omit since to get full branch history. Validated functional commits can still interact with merged ones
37
- commits: await getCommits({ sourceBranch: head, targetBranch: base }),
39
+ commits: await getCommits({ sourceBranch: HEAD, targetBranch: base }),
38
40
  testFilesGlob,
39
41
  });
40
42
  logger.info(own.functional.length > 0
@@ -46,25 +48,22 @@ const getOwnChangesIfMergedFromBase = async (head, base, actorConfigs, testFiles
46
48
  * Finds the Actors whose context changed in the given range. `base` selects the branch's own commits
47
49
  * (a PR), `since` the commits after a known one (a release, or the last validated commit of a PR).
48
50
  */
49
- export const getAffectedActors = async ({ head, base, since: sinceOption, testFilesGlob, actors, ignore, }) => {
51
+ export const getAffectedActors = async ({ base, since: sinceOption, testFilesGlob, actors, ignore, }) => {
50
52
  // An empty --since (e.g. an empty cache file) means the same as not passing it
51
53
  const since = sinceOption || undefined;
52
54
  if (!base && !since) {
53
55
  throw new Error('Pass --base, --since, or both to select the commits to inspect.');
54
56
  }
55
- const headSha = await resolveCommitSha(head);
56
- const { commits, fromRef, toRef } = base
57
- ? await getBranchRange(head, base, since)
58
- : await getRangeSince(head, headSha, since);
57
+ const headSha = await resolveCommitSha(HEAD);
58
+ const { commits, fromRef, toRef } = base ? await getBranchRange(base, since) : await getRangeSince(headSha, since);
59
59
  const actorConfigs = await readConfigFile({ actors, ignore });
60
60
  // What the branch only merged in from base is already validated. Without functional changes of its own
61
61
  // the branch has nothing to test, and without any changes of its own nothing to release either.
62
- const own = base ? await getOwnChangesIfMergedFromBase(head, base, actorConfigs, testFilesGlob) : undefined;
62
+ const own = base ? await getOwnChangesIfMergedFromBase(base, actorConfigs, testFilesGlob) : undefined;
63
63
  const changedFiles = await getChangedFilesBetween(fromRef, toRef);
64
64
  const changed = await getChangedActors({ filepathsChanged: changedFiles, actorConfigs, commits, testFilesGlob });
65
65
  return {
66
66
  headSha,
67
- ref: await resolveBranchName(head),
68
67
  commits,
69
68
  changedFiles,
70
69
  changelog: await getChangelogAdditions(fromRef, toRef, changedFiles),
@@ -73,11 +72,10 @@ export const getAffectedActors = async ({ head, base, since: sinceOption, testFi
73
72
  };
74
73
  };
75
74
  /** The JSON document `get-affected-actors` prints. Versioned, since other commands and workflows consume it. */
76
- export const toAffectedActorsDocument = ({ headSha, ref, commits, changedFiles, changelog, functionallyChangedActors, cosmeticallyChangedActors, }) => {
75
+ export const toAffectedActorsDocument = ({ headSha, commits, changedFiles, changelog, functionallyChangedActors, cosmeticallyChangedActors, }) => {
77
76
  const names = (configs) => configs.map(({ actorFullName }) => ({ actorFullName }));
78
77
  return {
79
78
  version: 1,
80
- ref,
81
79
  head: headSha,
82
80
  commits,
83
81
  changedFiles,
@@ -1 +1 @@
1
- {"version":3,"file":"affected-actors.js","sourceRoot":"","sources":["../../bin/affected-actors.ts"],"names":[],"mappings":"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"}
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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"}
package/dist/bin/build.js CHANGED
@@ -1,9 +1,12 @@
1
1
  import { ActorSourceType, ApifyClient } from 'apify-client';
2
- import { normalizeRepoUrl } from './git.js';
2
+ import { getCurrentBranch, normalizeRepoUrl, resolveRepoUrl } from './git.js';
3
3
  import { logger } from './logger.js';
4
4
  // Fixed version number used to build from local source files, since there is no real version to track.
5
5
  export const LOCAL_SOURCE_VERSION_NUMBER = '0.98';
6
- const DEFAULT_TEST_VERSION_NUMBER = '0.99';
6
+ // Version that build-for-test builds, so tests never touch the version users run
7
+ export const TEST_VERSION_NUMBER = '0.99';
8
+ // Stands for each Actor's default version: the one its default build tag points to
9
+ export const DEFAULT_VERSION_KEYWORD = 'default';
7
10
  // Shown whenever an Actor isn't set up the way CI builds need it
8
11
  const ACTOR_SETUP_REQUIREMENT = 'Before using apify-test-tools, every Actor needs at least one build under its default build tag (usually "latest"), ' +
9
12
  'built from a Git repository version whose URL points to this repository. Build it once manually on the platform.';
@@ -222,11 +225,18 @@ export const runAndSummarizeBuilds = async (actorConfigs, label, buildOneActor)
222
225
  const startedBuilds = await Promise.all(actorConfigs.map(async (actorConfig) => buildOneActor(actorConfig, buildersByActorFullName.get(actorConfig.actorFullName))));
223
226
  return waitAndSummarizeBuilds(startedBuilds, buildersByActorFullName, label);
224
227
  };
225
- export const runBuilds = async ({ repoUrl, shouldVerifyRepoUrl, branch, actorConfigs, isLatest = false, dryRun, useDockerCache, }) => {
228
+ export const runBuilds = async ({ repoUrl, shouldVerifyRepoUrl, branch, actorConfigs, versionNumber, dryRun, }) => {
226
229
  // Fetched once per Actor and reused for the checks, the version numbers and the build itself
227
230
  const buildConfigs = await Promise.all(actorConfigs.map(async (actorConfig) => {
228
231
  const actorInfo = await ApifyBuilder.fromActorConfig(actorConfig).getActorInfo();
229
232
  const { defaultVersionNumber, defaultBuildTag, defaultVersion } = resolveDefaultVersion(actorConfig.actorFullName, actorInfo);
233
+ // Builds keep the tags their version gives them, so a default version without the default build tag
234
+ // would build fine but leave users on the previous build
235
+ if (versionNumber === DEFAULT_VERSION_KEYWORD && defaultVersion?.buildTag !== defaultBuildTag) {
236
+ logger.warn(`[${actorConfig.actorFullName}] Default version ${defaultVersionNumber} has build tag ` +
237
+ `"${defaultVersion?.buildTag ?? 'none'}", not "${defaultBuildTag}", so users keep running the previous build. ` +
238
+ 'Set the build tag of the version on the platform to change that.');
239
+ }
230
240
  if (shouldVerifyRepoUrl) {
231
241
  assertRepoUrlMatchesDefaultVersion(actorConfig.actorFullName, defaultVersion, repoUrl);
232
242
  }
@@ -239,38 +249,50 @@ export const runBuilds = async ({ repoUrl, shouldVerifyRepoUrl, branch, actorCon
239
249
  actorConfig,
240
250
  actorInfo,
241
251
  gitRepoUrl,
242
- versionNumber: isLatest ? defaultVersionNumber : DEFAULT_TEST_VERSION_NUMBER,
243
- buildTag: isLatest ? defaultBuildTag : undefined,
244
- useDockerCache,
252
+ versionNumber: versionNumber === DEFAULT_VERSION_KEYWORD ? defaultVersionNumber : versionNumber,
245
253
  };
246
254
  }));
247
255
  // Everything above only reads, so a dry run has checked what the real run would, short of writing
248
256
  if (dryRun) {
249
257
  logger.info('[DRY RUN] Would build:');
250
- for (const { actorConfig, versionNumber, gitRepoUrl } of buildConfigs) {
251
- logger.info(` ${actorConfig.actorFullName} (${versionNumber}) from ${gitRepoUrl}`);
258
+ const builds = buildConfigs.map((buildConfig) => ({
259
+ actorFullName: buildConfig.actorConfig.actorFullName,
260
+ versionNumber: buildConfig.versionNumber,
261
+ gitRepoUrl: buildConfig.gitRepoUrl,
262
+ }));
263
+ for (const build of builds) {
264
+ logger.info(` ${build.actorFullName} (${build.versionNumber}) from ${build.gitRepoUrl}`);
252
265
  }
253
- return {
254
- dryRun: true,
255
- builds: buildConfigs.map(({ actorConfig, versionNumber, buildTag, gitRepoUrl, useDockerCache: useCache }) => ({
256
- actorFullName: actorConfig.actorFullName,
257
- versionNumber,
258
- buildTag,
259
- gitRepoUrl,
260
- useDockerCache: useCache,
261
- })),
262
- };
266
+ return { dryRun: true, builds };
263
267
  }
264
268
  const buildConfigsByActorFullName = new Map(buildConfigs.map((buildConfig) => [buildConfig.actorConfig.actorFullName, buildConfig]));
265
269
  return runAndSummarizeBuilds(actorConfigs, 'BUILDS', async (actorConfig, builder) => {
266
- const { actorInfo, buildTag, versionNumber, gitRepoUrl, useDockerCache: useCache, } = buildConfigsByActorFullName.get(actorConfig.actorFullName);
270
+ const buildConfig = buildConfigsByActorFullName.get(actorConfig.actorFullName);
271
+ // No buildTag: the version keeps the one it has, so its build gets the tag the version already gives it
267
272
  const actorVersion = {
268
- buildTag,
269
- versionNumber,
270
- gitRepoUrl,
273
+ versionNumber: buildConfig.versionNumber,
274
+ gitRepoUrl: buildConfig.gitRepoUrl,
271
275
  sourceType: ActorSourceType.GitRepo,
272
276
  };
273
- return builder.createVersionAndBuild(versionNumber, actorVersion, useCache, actorInfo);
277
+ // Always with the Docker cache: CI always asked for it, and a clean build can still be started on the platform
278
+ return builder.createVersionAndBuild(buildConfig.versionNumber, actorVersion, true, buildConfig.actorInfo);
279
+ });
280
+ };
281
+ /**
282
+ * Builds exactly the given Actors from the checked-out Git branch, as it is on the remote. Fails on a detached HEAD,
283
+ * where there is no branch to build. Used by `build` and the commands built on top of it.
284
+ */
285
+ export const buildActors = async ({ actorConfigs, repoUrl, ...options }) => {
286
+ if (actorConfigs.length === 0) {
287
+ logger.info('No Actors to build');
288
+ // Still the dry-run shape in a dry run, so it can't pass for a real (empty) result
289
+ return options.dryRun ? { dryRun: true, builds: [] } : [];
290
+ }
291
+ return runBuilds({
292
+ ...options,
293
+ ...(await resolveRepoUrl(repoUrl)),
294
+ actorConfigs,
295
+ branch: await getCurrentBranch(),
274
296
  });
275
297
  };
276
298
  export const deleteOldBuilds = async (actorConfigs, { dryRun }) => {