apify-test-tools 0.5.7-beta.2 → 0.5.7-beta.3

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 (41) hide show
  1. package/bin/diff-changes.ts +127 -0
  2. package/bin/diff-json-schema.ts +43 -0
  3. package/bin/git.ts +13 -4
  4. package/bin/main.ts +9 -5
  5. package/bin/utils.ts +2 -119
  6. package/dist/bin/diff-changes.d.ts +16 -0
  7. package/dist/bin/diff-changes.d.ts.map +1 -0
  8. package/dist/bin/diff-changes.js +91 -0
  9. package/dist/bin/diff-changes.js.map +1 -0
  10. package/dist/bin/diff-json-schema.d.ts +7 -0
  11. package/dist/bin/diff-json-schema.d.ts.map +1 -0
  12. package/dist/bin/diff-json-schema.js +40 -0
  13. package/dist/bin/diff-json-schema.js.map +1 -0
  14. package/dist/bin/git.d.ts +1 -1
  15. package/dist/bin/git.d.ts.map +1 -1
  16. package/dist/bin/git.js +12 -4
  17. package/dist/bin/git.js.map +1 -1
  18. package/dist/bin/main.js +8 -5
  19. package/dist/bin/main.js.map +1 -1
  20. package/dist/bin/utils.d.ts +0 -14
  21. package/dist/bin/utils.d.ts.map +1 -1
  22. package/dist/bin/utils.js +1 -88
  23. package/dist/bin/utils.js.map +1 -1
  24. package/dist/test/unit/bin/diff-changes.test.d.ts +2 -0
  25. package/dist/test/unit/bin/diff-changes.test.d.ts.map +1 -0
  26. package/dist/test/unit/bin/diff-changes.test.js +152 -0
  27. package/dist/test/unit/bin/diff-changes.test.js.map +1 -0
  28. package/dist/test/unit/bin/diff.test.d.ts +2 -0
  29. package/dist/test/unit/bin/diff.test.d.ts.map +1 -0
  30. package/dist/test/unit/bin/diff.test.js +133 -0
  31. package/dist/test/unit/bin/diff.test.js.map +1 -0
  32. package/dist/test/unit/parse-commit.test.js +1 -1
  33. package/dist/test/unit/parse-commit.test.js.map +1 -1
  34. package/dist/test/unit/should-built-and-test.test.js +93 -30
  35. package/dist/test/unit/should-built-and-test.test.js.map +1 -1
  36. package/dist/tsconfig.tsbuildinfo +1 -1
  37. package/package.json +1 -1
  38. package/test/unit/bin/diff-changes.test.ts +175 -0
  39. package/test/unit/bin/diff.test.ts +214 -0
  40. package/test/unit/parse-commit.test.ts +2 -1
  41. package/test/unit/should-built-and-test.test.ts +115 -31
@@ -0,0 +1,127 @@
1
+ import { isCosmeticOnlyJsonSchemaChange } from './diff-json-schema.js';
2
+ import type { ActorConfig, Commit } from './types.js';
3
+
4
+ interface ShouldBuildAndTestOptions {
5
+ filepathsChanged: string[];
6
+ actorConfigs: ActorConfig[];
7
+ isLatest?: boolean;
8
+ commits: Commit[];
9
+ }
10
+
11
+ export const maybeParseActorFolder = (lowercaseFilePath: string): { isActorFolder: true, actorName: string } | { isActorFolder: false } => {
12
+ const match = lowercaseFilePath.match(/^(?:standalone-)?actors\/([^/]+)\/.+/);
13
+ if (match) {
14
+ // Some usernames weirdly use underscores, e.g. google_maps_email_extractor_standby-contact-details-scraper so we only need replace the last one
15
+ return { isActorFolder: true, actorName: match[1].replace(/_(?=[^_]*$)/, '/') };
16
+ }
17
+ return { isActorFolder: false };
18
+ }
19
+
20
+ /**
21
+ * Also works for folders
22
+ */
23
+ const isIgnoredTopLevelFile = (lowercaseFilePath: string) => {
24
+ // On top level, we should only have dev-only readme and .actor/ is just for apify push CLI (real Actor configs are in /actors)
25
+ const IGNORED_TOP_LEVEL_FILES = ['.vscode/', '.gitignore', 'readme.md', '.husky/', '.eslintrc', 'eslint.config.mjs', '.prettierrc', '.editorconfig', '.actor/'];
26
+ // Strip out deprecated /code and /shared folders, treat them as top-level code
27
+ const sanitizedLowercaseFilePath = lowercaseFilePath.replace(/^code\//, '').replace(/^shared\//, '');
28
+
29
+ return IGNORED_TOP_LEVEL_FILES.some((ignoredFile) => sanitizedLowercaseFilePath.startsWith(ignoredFile));
30
+ };
31
+
32
+ type FileChange =
33
+ { impact: 'ignored' } |
34
+ // Only things that influence how the Actor looks - e.g. README and CHANGELOG files, schema titles, descriptions, reordering, etc. We only need to rebuild on release
35
+ { impact: 'cosmetic', includes: 'all-actors' | ActorConfig } |
36
+ // Influences how the Actor works - we need to run tests
37
+ {
38
+ impact: 'functional', includes: 'all-actors' | ActorConfig
39
+ };
40
+
41
+ const classifyFileChange = (lowercaseFilePath: string, actorConfigs: ActorConfig[], commits: Commit[]): FileChange => {
42
+ if (isIgnoredTopLevelFile(lowercaseFilePath)) {
43
+ return { impact: 'ignored' };
44
+ }
45
+
46
+ if (lowercaseFilePath.endsWith('changelog.md')) {
47
+ return { impact: 'cosmetic', includes: 'all-actors' };
48
+ }
49
+
50
+ const actorFolderInfo = maybeParseActorFolder(lowercaseFilePath);
51
+ if (actorFolderInfo.isActorFolder) {
52
+ const actorConfigChanged = actorConfigs.find(({ actorName }) => actorName.toLowerCase() === actorFolderInfo.actorName);
53
+ // This is some super weird case that happened once in the past but I don't remember the context anymore
54
+ if (actorConfigChanged === undefined) {
55
+ console.error('SHOULD NEVER HAPPEN: changes was found in an actor folder which no longer exists in the current commit, skipping this file', {
56
+ actorName: actorFolderInfo.actorName,
57
+ lowercaseFilePath,
58
+ });
59
+ return { impact: 'ignored' };
60
+ }
61
+ if (lowercaseFilePath.endsWith('readme.md')) {
62
+ return { impact: 'cosmetic', includes: actorConfigChanged };
63
+ }
64
+ if (lowercaseFilePath.endsWith('.json') && isCosmeticOnlyJsonSchemaChange(commits, lowercaseFilePath)) {
65
+ return { impact: 'cosmetic', includes: actorConfigChanged };
66
+ }
67
+
68
+ return { impact: 'functional', includes: actorConfigChanged };
69
+ }
70
+
71
+ // For any other files, we assume they can interact with the code
72
+ return { impact: 'functional', includes: 'all-actors' };
73
+ }
74
+
75
+ export const getChangedActors = (
76
+ { filepathsChanged, actorConfigs, isLatest = false, commits }: ShouldBuildAndTestOptions,
77
+ ): ActorConfig[] => {
78
+ // folder -> ActorConfig
79
+ const actorsChangedMap = new Map<string, ActorConfig>();
80
+
81
+ const actorConfigsWithoutStandalone = actorConfigs.filter(({ isStandalone }) => !isStandalone);
82
+
83
+ const lowercaseFiles = filepathsChanged.map((file) => file.toLowerCase());
84
+
85
+ for (const lowercaseFilePath of lowercaseFiles) {
86
+ const fileChange = classifyFileChange(lowercaseFilePath, actorConfigs, commits);
87
+ if (fileChange.impact === 'ignored') {
88
+ continue;
89
+ }
90
+
91
+ if (fileChange.impact === 'cosmetic' && !isLatest) {
92
+ continue;
93
+ }
94
+
95
+ if (fileChange.includes !== 'all-actors') {
96
+ actorsChangedMap.set(fileChange.includes.folder, fileChange.includes);
97
+ } else if (fileChange.includes === 'all-actors') {
98
+ // Standalone Actors are handled always via specific actors change, not all-actors
99
+ for (const actorConfig of actorConfigsWithoutStandalone) {
100
+ actorsChangedMap.set(actorConfig.folder, actorConfig);
101
+ }
102
+ }
103
+ }
104
+
105
+ const actorsChanged = Array.from(actorsChangedMap.values());
106
+
107
+ // All below here is just for logging
108
+ const ignoredFilesChanged = lowercaseFiles.filter((file) => classifyFileChange(file, actorConfigs, commits).impact === 'ignored');
109
+ console.error(`[DIFF]: Ignored files (don't trigger test or build): ${ignoredFilesChanged.join(', ')}`);
110
+
111
+ const cosmeticFilesChanged = lowercaseFiles.filter((file) => classifyFileChange(file, actorConfigs, commits).impact === 'cosmetic');
112
+ console.error(`[DIFF]: Cosmetic files (should only trigger release build): ${cosmeticFilesChanged.join(', ')}`);
113
+
114
+ const functionalFilesChanged = lowercaseFiles.filter((file) => classifyFileChange(file, actorConfigs, commits).impact === 'functional');
115
+ console.error(`[DIFF]: Functional files (trigger test & release build): ${functionalFilesChanged.join(', ')}`);
116
+
117
+ if (actorsChanged.length > 0) {
118
+ const miniactors = actorsChanged.filter((config) => !config.isStandalone).map((config) => config.actorName);
119
+ const standaloneActors = actorsChanged.filter((config) => config.isStandalone).map((config) => config.actorName);
120
+ console.error(`[DIFF]: MiniActors to be built and tested: ${miniactors.join(', ')}`);
121
+ console.error(`[DIFF]: Standalone Actors to be built and tested: ${standaloneActors.join(', ')}`);
122
+ } else {
123
+ console.error(`[DIFF]: No relevant files changed, skipping builds and tests`);
124
+ }
125
+
126
+ return actorsChanged;
127
+ };
@@ -0,0 +1,43 @@
1
+ import type { Commit } from './types.js';
2
+ import { spawnCommandInGhWorkspace } from './utils.js';
3
+
4
+ const COSMETIC_JSON_FIELD_NAMES = new Set([
5
+ 'title', 'description', 'example', 'enumTitles', 'sectionCaption', 'sectionDescription',
6
+ ]);
7
+
8
+ const isPlainObject = (val: unknown): val is Record<string, unknown> =>
9
+ typeof val === 'object' && val !== null && !Array.isArray(val);
10
+
11
+ const isCosmeticObjectChange = (oldVal: unknown, newVal: unknown, currentKey?: string): boolean => {
12
+ // If the key itself is cosmetic, any change under it is fine
13
+ if (currentKey && COSMETIC_JSON_FIELD_NAMES.has(currentKey)) return true;
14
+ if (JSON.stringify(oldVal) === JSON.stringify(newVal)) return true;
15
+ if (isPlainObject(oldVal) && isPlainObject(newVal)) {
16
+ const allKeys = new Set([...Object.keys(oldVal), ...Object.keys(newVal)]);
17
+ return [...allKeys].every((key) => isCosmeticObjectChange(oldVal[key], newVal[key], key));
18
+ }
19
+ return false;
20
+ };
21
+
22
+ /**
23
+ * Returns true if the two JSON strings differ only in cosmetic fields
24
+ * (title, description, example, enumTitles, sectionCaption, sectionDescription).
25
+ */
26
+ export const isCosmeticOnlyJsonSchemaChange = (commits: Commit[], changedFilepath: string): boolean => {
27
+ // TODO: validate this is the right commit range
28
+ const oldRef = `${commits[0].sha}~`;
29
+ const newRef = commits[commits.length - 1].sha;
30
+ let oldJson: unknown;
31
+ let newJson: unknown;
32
+ try {
33
+ const oldContent = spawnCommandInGhWorkspace(`git show ${oldRef}:${changedFilepath}`);
34
+ const newContent = spawnCommandInGhWorkspace(`git show ${newRef}:${changedFilepath}`);
35
+
36
+ oldJson = JSON.parse(oldContent);
37
+ newJson = JSON.parse(newContent);
38
+ } catch {
39
+ console.error(`Failed to get or parse JSON content for ${changedFilepath} at refs ${oldRef} and ${newRef}, maybe it is new file or deleted? Treating it as a non-cosmetic change.`);
40
+ return false;
41
+ }
42
+ return isCosmeticObjectChange(oldJson, newJson);
43
+ };
package/bin/git.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Commit, Config } from './types.js';
1
+ import type { Commit, Config } from './types.js';
2
2
  import { spawnCommandInGhWorkspace } from './utils.js';
3
3
 
4
4
  export const GIT_FORMAT_SEPARATOR = '»¦«';
@@ -8,11 +8,13 @@ const GIT_LOG_FORMAT = ['%H', '%aN<%aE>', '%aD', '%s'].join(GIT_FORMAT_SEPARATOR
8
8
  * Gets the list of changed files between the given commits (inclusive).
9
9
  */
10
10
  export const getChangedFiles = (commits: Commit[]) => {
11
- const changedFiles = spawnCommandInGhWorkspace(
11
+ const changedFilesString = spawnCommandInGhWorkspace(
12
12
  `git diff --name-only ${commits[0].sha}~..${commits[commits.length - 1].sha}`,
13
13
  );
14
14
 
15
- return changedFiles.split('\n');
15
+ const changedFiles = changedFilesString.split('\n');
16
+ console.error(`Changed files (up to 50): ${changedFiles.slice(0, 50).join(', ')}`);
17
+ return changedFiles;
16
18
  };
17
19
 
18
20
  /**
@@ -29,8 +31,15 @@ export const getCommits = ({ sourceBranch, targetBranch, baseCommit: baseCommitS
29
31
  const baseCommitIndex = commits.findIndex((commit) => commit.sha === baseCommitSha);
30
32
 
31
33
  const hasBaseCommit = baseCommitIndex !== -1;
32
- if (hasBaseCommit) return commits.slice(baseCommitIndex + 1);
34
+ if (hasBaseCommit) {
35
+ const commitsUpToBaseCommit = commits.slice(baseCommitIndex + 1);
36
+ console.error(`Found base commit ${baseCommitSha} at index ${baseCommitIndex}, returning ${commitsUpToBaseCommit.length} commits after it`);
37
+ console.error(`Commits being returned: ${commitsUpToBaseCommit.map((c) => c.sha).join(', ')}`);
38
+ return commitsUpToBaseCommit;
39
+ }
33
40
 
41
+ console.error(`Base commit ${baseCommitSha} not found in the commit range, returning all ${commits.length} commits`);
42
+ console.error(`Commits being returned: ${commits.map((c) => c.sha).join(', ')}`);
34
43
  return commits;
35
44
  };
36
45
 
package/bin/main.ts CHANGED
@@ -1,15 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import process from 'process';
3
+ import process from 'node:process';
4
+
4
5
  import yargs, { type Argv } from 'yargs';
5
6
  import { hideBin } from 'yargs/helpers';
6
7
 
7
- import { getRepoActors, getChangedActors, spawnCommandInGhWorkspace, setCwd } from './utils.js';
8
8
  import { runBuilds } from './build.js';
9
+ import { getChangedActors } from './diff-changes.js';
9
10
  import { getChangedFiles, getCommits } from './git.js';
10
11
  import { getPushData } from './github.js';
11
12
  import { notifyToSlack } from './slack.js';
12
13
  import { reportTestResults } from './test-report.js';
14
+ import { getRepoActors, setCwd,spawnCommandInGhWorkspace } from './utils.js';
13
15
 
14
16
  /**
15
17
  * Middlewares to be run before every command execution
@@ -69,7 +71,7 @@ await yargs()
69
71
  const commits = getCommits(args);
70
72
  const changedFiles = getChangedFiles(commits);
71
73
  const actorConfigs = await getRepoActors();
72
- const { actorsChanged } = getChangedActors({ filepathsChanged: changedFiles, actorConfigs, isLatest: false });
74
+ const actorsChanged = getChangedActors({ filepathsChanged: changedFiles, actorConfigs, isLatest: false, commits });
73
75
  console.log(JSON.stringify(actorsChanged));
74
76
  })
75
77
  .command(
@@ -93,9 +95,10 @@ await yargs()
93
95
  const commits = getCommits(args);
94
96
  const changedFiles = getChangedFiles(commits);
95
97
  const actorConfigs = await getRepoActors();
96
- const { actorsChanged } = getChangedActors({
98
+ const actorsChanged = getChangedActors({
97
99
  filepathsChanged: changedFiles,
98
100
  actorConfigs,
101
+ commits,
99
102
  });
100
103
  // https://github.com/apify-store/google-maps#:actors/lukaskrivka_google-maps-with-contact-details
101
104
  // git@github.com:apify-store/google-maps#:actors/lukaskrivka_google-maps-with-contact-details
@@ -128,10 +131,11 @@ await yargs()
128
131
  );
129
132
  const isLatest = true;
130
133
  const actorConfigs = await getRepoActors();
131
- const { actorsChanged } = getChangedActors({
134
+ const actorsChanged = getChangedActors({
132
135
  filepathsChanged: changedFiles,
133
136
  actorConfigs,
134
137
  isLatest,
138
+ commits,
135
139
  });
136
140
  const { dryRun, reportSlackChannel, releaseSlackChannel } = args;
137
141
  const builds = await runBuilds({
package/bin/utils.ts CHANGED
@@ -1,8 +1,8 @@
1
- import fs from 'node:fs/promises';
2
1
  import { spawnSync } from 'node:child_process';
2
+ import fs from 'node:fs/promises';
3
+
3
4
  import type {
4
5
  ActorConfig,
5
- Commit,
6
6
  GitHubEvent,
7
7
  } from './types.js';
8
8
 
@@ -92,120 +92,3 @@ export const getHeadCommitSha = (githubEvent: GitHubEvent) => {
92
92
  ? githubEvent.pull_request.head.sha
93
93
  : githubEvent.head_commit.id;
94
94
  };
95
-
96
- export interface GetChangedActorsResult {
97
- actorsChanged: ActorConfig[];
98
- codeChanged: boolean;
99
- }
100
-
101
- interface ShouldBuildAndTestOptions {
102
- filepathsChanged: string[];
103
- actorConfigs: ActorConfig[];
104
- // Just for logging
105
- isLatest?: boolean;
106
- }
107
-
108
- /**
109
- * Also works for folders
110
- */
111
- const isIgnoredTopLevelFile = (lowercaseFilePath: string) => {
112
- // On top level, we should only have dev-only readme and .actor/ is just for apify push CLI (real Actor configs are in /actors)
113
- const IGNORED_TOP_LEVEL_FILES = ['.vscode/', '.gitignore', 'readme.md', '.husky/', '.eslintrc', '.editorconfig', '.actor/'];
114
- // Strip out deprecated /code and /shared folders, treat them as top-level code
115
- const sanitizedLowercaseFilePath = lowercaseFilePath.replace(/^code\//, '').replace(/^shared\//, '');
116
-
117
- return IGNORED_TOP_LEVEL_FILES.some((ignoredFile) => sanitizedLowercaseFilePath.startsWith(ignoredFile));
118
- };
119
-
120
- const isLatestBuildOnlyFile = (lowercaseFilePath: string) => {
121
- if (lowercaseFilePath.endsWith('changelog.md')) {
122
- return true;
123
- }
124
-
125
- // Either in /actors or /standalone-actors, we need to rebuild readme but we don't rebuild top-level dev-only readme
126
- if ((lowercaseFilePath.startsWith('actors/') || lowercaseFilePath.startsWith('standalone-actors/')) && lowercaseFilePath.endsWith('readme.md')) {
127
- return true;
128
- }
129
-
130
- return false;
131
- };
132
-
133
- /**
134
- * Latest and devel are the same except that for latest we also rebuild with README and CHANGELOG files
135
- */
136
- export const getChangedActors = (
137
- { filepathsChanged, actorConfigs, isLatest = false }: ShouldBuildAndTestOptions,
138
- ): GetChangedActorsResult => {
139
- let codeChanged = false;
140
- // folder -> ActorConfig
141
- const actorsChangedMap = new Map<string, ActorConfig>();
142
-
143
- const actorConfigsWithoutStandalone = actorConfigs.filter(({ isStandalone }) => !isStandalone);
144
-
145
- const lowercaseFiles = filepathsChanged.map((file) => file.toLowerCase());
146
-
147
- for (const lowercaseFilePath of lowercaseFiles) {
148
- if (isIgnoredTopLevelFile(lowercaseFilePath)) {
149
- continue;
150
- }
151
- // First we check for specific actors that have configs in /actors or standalone actors in /standalone-actors
152
- // This matches both actors/username_actorName and standalone-actors/username_actorName
153
- const changedActorConfigMatch = lowercaseFilePath.match(/^(?:standalone-)?actors\/([^/]+)\/.+/);
154
- if (changedActorConfigMatch) {
155
- const sanitizedActorName = changedActorConfigMatch[1].replace('_', '/');
156
- const actorConfigChanged = actorConfigs.find(({ actorName }) => actorName.toLowerCase() === sanitizedActorName);
157
- if (actorConfigChanged === undefined) {
158
- console.warn('changes was found in an actor folder which no longer exists in the current commit', {
159
- actorName: sanitizedActorName,
160
- actorFolderName: changedActorConfigMatch[1],
161
- });
162
- continue;
163
- }
164
-
165
- console.error(`actorConfigChanged ${actorConfigChanged.actorName}: sanitizedActorName ${sanitizedActorName} ${lowercaseFilePath} `);
166
- // These can be nested at various folders inside the actor folder
167
- if (isLatest || !isLatestBuildOnlyFile(lowercaseFilePath)) {
168
- // We assume other files will are either actor.json or input_schema.json and those needs to be tested
169
- // TODO: Check what changed in schema, we don't need to test description changes
170
- actorsChangedMap.set(actorConfigChanged.folder, actorConfigChanged);
171
- }
172
- continue;
173
- }
174
-
175
- // We check top level files (formerly in /code and /shared folders) that are shared among all non-standalone Actors
176
- // Standalone actors are always handled separately by name via changedActorConfigMatch
177
- if (isLatest || !isLatestBuildOnlyFile(lowercaseFilePath)) {
178
- codeChanged = !isLatest; // NOTE: code is changed only in PR
179
- for (const actorConfig of actorConfigsWithoutStandalone) {
180
- actorsChangedMap.set(actorConfig.folder, actorConfig);
181
- }
182
- }
183
- }
184
-
185
- const actorsChanged = Array.from(actorsChangedMap.values());
186
-
187
- // All below here is just for logging
188
- const ignoredFilesChanged = lowercaseFiles.filter((file) => isIgnoredTopLevelFile(file));
189
- console.error(`[DIFF]: Top level files changed that we ignore (don't trigger test or build): ${ignoredFilesChanged.join(', ')}`);
190
-
191
- const onlyLatestFilesChanged = lowercaseFiles.filter((file) => isLatestBuildOnlyFile(file));
192
- console.error(`[DIFF]: Files changed that only trigger latest build: ${onlyLatestFilesChanged.join(', ')}`);
193
-
194
- if (!isLatest && codeChanged) {
195
- console.error(`[DIFF]: All non-standalone Actors need to be built and tested (changes in top-level code)`);
196
- }
197
-
198
- if (actorsChanged.length > 0) {
199
- const miniactors = actorsChanged.filter((config) => !config.isStandalone).map((config) => config.actorName);
200
- const standaloneActors = actorsChanged.filter((config) => config.isStandalone).map((config) => config.actorName);
201
- console.error(`[DIFF]: MiniActors to be built and tested: ${miniactors.join(', ')}`);
202
- console.error(`[DIFF]: Standalone Actors to be built and tested: ${standaloneActors.join(', ')}`);
203
- } else {
204
- console.error(`[DIFF]: No relevant files changed, skipping builds and tests`);
205
- }
206
-
207
- return {
208
- actorsChanged,
209
- codeChanged,
210
- };
211
- };
@@ -0,0 +1,16 @@
1
+ import type { ActorConfig, Commit } from './types.js';
2
+ interface ShouldBuildAndTestOptions {
3
+ filepathsChanged: string[];
4
+ actorConfigs: ActorConfig[];
5
+ isLatest?: boolean;
6
+ commits: Commit[];
7
+ }
8
+ export declare const maybeParseActorFolder: (lowercaseFilePath: string) => {
9
+ isActorFolder: true;
10
+ actorName: string;
11
+ } | {
12
+ isActorFolder: false;
13
+ };
14
+ export declare const getChangedActors: ({ filepathsChanged, actorConfigs, isLatest, commits }: ShouldBuildAndTestOptions) => ActorConfig[];
15
+ export {};
16
+ //# sourceMappingURL=diff-changes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-changes.d.ts","sourceRoot":"","sources":["../../bin/diff-changes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEtD,UAAU,yBAAyB;IAC/B,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,eAAO,MAAM,qBAAqB,GAAI,mBAAmB,MAAM,KAAG;IAAE,aAAa,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,aAAa,EAAE,KAAK,CAAA;CAOpI,CAAA;AAyDD,eAAO,MAAM,gBAAgB,GACzB,uDAA+D,yBAAyB,KACzF,WAAW,EAkDb,CAAC"}
@@ -0,0 +1,91 @@
1
+ import { isCosmeticOnlyJsonSchemaChange } from './diff-json-schema.js';
2
+ export const maybeParseActorFolder = (lowercaseFilePath) => {
3
+ const match = lowercaseFilePath.match(/^(?:standalone-)?actors\/([^/]+)\/.+/);
4
+ if (match) {
5
+ // Some usernames weirdly use underscores, e.g. google_maps_email_extractor_standby-contact-details-scraper so we only need replace the last one
6
+ return { isActorFolder: true, actorName: match[1].replace(/_(?=[^_]*$)/, '/') };
7
+ }
8
+ return { isActorFolder: false };
9
+ };
10
+ /**
11
+ * Also works for folders
12
+ */
13
+ const isIgnoredTopLevelFile = (lowercaseFilePath) => {
14
+ // On top level, we should only have dev-only readme and .actor/ is just for apify push CLI (real Actor configs are in /actors)
15
+ const IGNORED_TOP_LEVEL_FILES = ['.vscode/', '.gitignore', 'readme.md', '.husky/', '.eslintrc', 'eslint.config.mjs', '.prettierrc', '.editorconfig', '.actor/'];
16
+ // Strip out deprecated /code and /shared folders, treat them as top-level code
17
+ const sanitizedLowercaseFilePath = lowercaseFilePath.replace(/^code\//, '').replace(/^shared\//, '');
18
+ return IGNORED_TOP_LEVEL_FILES.some((ignoredFile) => sanitizedLowercaseFilePath.startsWith(ignoredFile));
19
+ };
20
+ const classifyFileChange = (lowercaseFilePath, actorConfigs, commits) => {
21
+ if (isIgnoredTopLevelFile(lowercaseFilePath)) {
22
+ return { impact: 'ignored' };
23
+ }
24
+ if (lowercaseFilePath.endsWith('changelog.md')) {
25
+ return { impact: 'cosmetic', includes: 'all-actors' };
26
+ }
27
+ const actorFolderInfo = maybeParseActorFolder(lowercaseFilePath);
28
+ if (actorFolderInfo.isActorFolder) {
29
+ const actorConfigChanged = actorConfigs.find(({ actorName }) => actorName.toLowerCase() === actorFolderInfo.actorName);
30
+ // This is some super weird case that happened once in the past but I don't remember the context anymore
31
+ if (actorConfigChanged === undefined) {
32
+ console.error('SHOULD NEVER HAPPEN: changes was found in an actor folder which no longer exists in the current commit, skipping this file', {
33
+ actorName: actorFolderInfo.actorName,
34
+ lowercaseFilePath,
35
+ });
36
+ return { impact: 'ignored' };
37
+ }
38
+ if (lowercaseFilePath.endsWith('readme.md')) {
39
+ return { impact: 'cosmetic', includes: actorConfigChanged };
40
+ }
41
+ if (lowercaseFilePath.endsWith('.json') && isCosmeticOnlyJsonSchemaChange(commits, lowercaseFilePath)) {
42
+ return { impact: 'cosmetic', includes: actorConfigChanged };
43
+ }
44
+ return { impact: 'functional', includes: actorConfigChanged };
45
+ }
46
+ // For any other files, we assume they can interact with the code
47
+ return { impact: 'functional', includes: 'all-actors' };
48
+ };
49
+ export const getChangedActors = ({ filepathsChanged, actorConfigs, isLatest = false, commits }) => {
50
+ // folder -> ActorConfig
51
+ const actorsChangedMap = new Map();
52
+ const actorConfigsWithoutStandalone = actorConfigs.filter(({ isStandalone }) => !isStandalone);
53
+ const lowercaseFiles = filepathsChanged.map((file) => file.toLowerCase());
54
+ for (const lowercaseFilePath of lowercaseFiles) {
55
+ const fileChange = classifyFileChange(lowercaseFilePath, actorConfigs, commits);
56
+ if (fileChange.impact === 'ignored') {
57
+ continue;
58
+ }
59
+ if (fileChange.impact === 'cosmetic' && !isLatest) {
60
+ continue;
61
+ }
62
+ if (fileChange.includes !== 'all-actors') {
63
+ actorsChangedMap.set(fileChange.includes.folder, fileChange.includes);
64
+ }
65
+ else if (fileChange.includes === 'all-actors') {
66
+ // Standalone Actors are handled always via specific actors change, not all-actors
67
+ for (const actorConfig of actorConfigsWithoutStandalone) {
68
+ actorsChangedMap.set(actorConfig.folder, actorConfig);
69
+ }
70
+ }
71
+ }
72
+ const actorsChanged = Array.from(actorsChangedMap.values());
73
+ // All below here is just for logging
74
+ const ignoredFilesChanged = lowercaseFiles.filter((file) => classifyFileChange(file, actorConfigs, commits).impact === 'ignored');
75
+ console.error(`[DIFF]: Ignored files (don't trigger test or build): ${ignoredFilesChanged.join(', ')}`);
76
+ const cosmeticFilesChanged = lowercaseFiles.filter((file) => classifyFileChange(file, actorConfigs, commits).impact === 'cosmetic');
77
+ console.error(`[DIFF]: Cosmetic files (should only trigger release build): ${cosmeticFilesChanged.join(', ')}`);
78
+ const functionalFilesChanged = lowercaseFiles.filter((file) => classifyFileChange(file, actorConfigs, commits).impact === 'functional');
79
+ console.error(`[DIFF]: Functional files (trigger test & release build): ${functionalFilesChanged.join(', ')}`);
80
+ if (actorsChanged.length > 0) {
81
+ const miniactors = actorsChanged.filter((config) => !config.isStandalone).map((config) => config.actorName);
82
+ const standaloneActors = actorsChanged.filter((config) => config.isStandalone).map((config) => config.actorName);
83
+ console.error(`[DIFF]: MiniActors to be built and tested: ${miniactors.join(', ')}`);
84
+ console.error(`[DIFF]: Standalone Actors to be built and tested: ${standaloneActors.join(', ')}`);
85
+ }
86
+ else {
87
+ console.error(`[DIFF]: No relevant files changed, skipping builds and tests`);
88
+ }
89
+ return actorsChanged;
90
+ };
91
+ //# sourceMappingURL=diff-changes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-changes.js","sourceRoot":"","sources":["../../bin/diff-changes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { Commit } from './types.js';
2
+ /**
3
+ * Returns true if the two JSON strings differ only in cosmetic fields
4
+ * (title, description, example, enumTitles, sectionCaption, sectionDescription).
5
+ */
6
+ export declare const isCosmeticOnlyJsonSchemaChange: (commits: Commit[], changedFilepath: string) => boolean;
7
+ //# sourceMappingURL=diff-json-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-json-schema.d.ts","sourceRoot":"","sources":["../../bin/diff-json-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAqBzC;;;GAGG;AACH,eAAO,MAAM,8BAA8B,GAAI,SAAS,MAAM,EAAE,EAAE,iBAAiB,MAAM,KAAG,OAiB3F,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { spawnCommandInGhWorkspace } from './utils.js';
2
+ const COSMETIC_JSON_FIELD_NAMES = new Set([
3
+ 'title', 'description', 'example', 'enumTitles', 'sectionCaption', 'sectionDescription',
4
+ ]);
5
+ const isPlainObject = (val) => typeof val === 'object' && val !== null && !Array.isArray(val);
6
+ const isCosmeticObjectChange = (oldVal, newVal, currentKey) => {
7
+ // If the key itself is cosmetic, any change under it is fine
8
+ if (currentKey && COSMETIC_JSON_FIELD_NAMES.has(currentKey))
9
+ return true;
10
+ if (JSON.stringify(oldVal) === JSON.stringify(newVal))
11
+ return true;
12
+ if (isPlainObject(oldVal) && isPlainObject(newVal)) {
13
+ const allKeys = new Set([...Object.keys(oldVal), ...Object.keys(newVal)]);
14
+ return [...allKeys].every((key) => isCosmeticObjectChange(oldVal[key], newVal[key], key));
15
+ }
16
+ return false;
17
+ };
18
+ /**
19
+ * Returns true if the two JSON strings differ only in cosmetic fields
20
+ * (title, description, example, enumTitles, sectionCaption, sectionDescription).
21
+ */
22
+ export const isCosmeticOnlyJsonSchemaChange = (commits, changedFilepath) => {
23
+ // TODO: validate this is the right commit range
24
+ const oldRef = `${commits[0].sha}~`;
25
+ const newRef = commits[commits.length - 1].sha;
26
+ let oldJson;
27
+ let newJson;
28
+ try {
29
+ const oldContent = spawnCommandInGhWorkspace(`git show ${oldRef}:${changedFilepath}`);
30
+ const newContent = spawnCommandInGhWorkspace(`git show ${newRef}:${changedFilepath}`);
31
+ oldJson = JSON.parse(oldContent);
32
+ newJson = JSON.parse(newContent);
33
+ }
34
+ catch {
35
+ console.error(`Failed to get or parse JSON content for ${changedFilepath} at refs ${oldRef} and ${newRef}, maybe it is new file or deleted? Treating it as a non-cosmetic change.`);
36
+ return false;
37
+ }
38
+ return isCosmeticObjectChange(oldJson, newJson);
39
+ };
40
+ //# sourceMappingURL=diff-json-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-json-schema.js","sourceRoot":"","sources":["../../bin/diff-json-schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,yBAAyB,GAAG,IAAI,GAAG,CAAC;IACtC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,gBAAgB,EAAE,oBAAoB;CAC1F,CAAC,CAAC;AAEH,MAAM,aAAa,GAAG,CAAC,GAAY,EAAkC,EAAE,CACnE,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;AAEnE,MAAM,sBAAsB,GAAG,CAAC,MAAe,EAAE,MAAe,EAAE,UAAmB,EAAW,EAAE;IAC9F,6DAA6D;IAC7D,IAAI,UAAU,IAAI,yBAAyB,CAAC,GAAG,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IACzE,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACnE,IAAI,aAAa,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;QACjD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,sBAAsB,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC9F,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,OAAiB,EAAE,eAAuB,EAAW,EAAE;IAClG,gDAAgD;IAChD,MAAM,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC;IACpC,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IAC/C,IAAI,OAAgB,CAAC;IACrB,IAAI,OAAgB,CAAC;IACrB,IAAI,CAAC;QACD,MAAM,UAAU,GAAG,yBAAyB,CAAC,YAAY,MAAM,IAAI,eAAe,EAAE,CAAC,CAAC;QACtF,MAAM,UAAU,GAAG,yBAAyB,CAAC,YAAY,MAAM,IAAI,eAAe,EAAE,CAAC,CAAC;QAEtF,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACjC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,CAAC,KAAK,CAAC,2CAA2C,eAAe,YAAY,MAAM,QAAQ,MAAM,0EAA0E,CAAC,CAAC;QACpL,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,sBAAsB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;AACpD,CAAC,CAAC"}
package/dist/bin/git.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Commit, Config } from './types.js';
1
+ import type { Commit, Config } from './types.js';
2
2
  export declare const GIT_FORMAT_SEPARATOR = "\u00BB\u00A6\u00AB";
3
3
  /**
4
4
  * Gets the list of changed files between the given commits (inclusive).
@@ -1 +1 @@
1
- {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../bin/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAG5C,eAAO,MAAM,oBAAoB,uBAAQ,CAAC;AAG1C;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,EAAE,aAMhD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,2DAA2D,MAAM,KAAG,MAAM,EAapG,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,WAAW,MAAM,KAAG,MAIjD,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,cAAc,MAAM,KAAG,MAYlD,CAAC"}
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../bin/git.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAGjD,eAAO,MAAM,oBAAoB,uBAAQ,CAAC;AAG1C;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,SAAS,MAAM,EAAE,aAQhD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,UAAU,GAAI,2DAA2D,MAAM,KAAG,MAAM,EAoBpG,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,WAAW,MAAM,KAAG,MAIjD,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,cAAc,MAAM,KAAG,MAYlD,CAAC"}
package/dist/bin/git.js CHANGED
@@ -5,8 +5,10 @@ const GIT_LOG_FORMAT = ['%H', '%aN<%aE>', '%aD', '%s'].join(GIT_FORMAT_SEPARATOR
5
5
  * Gets the list of changed files between the given commits (inclusive).
6
6
  */
7
7
  export const getChangedFiles = (commits) => {
8
- const changedFiles = spawnCommandInGhWorkspace(`git diff --name-only ${commits[0].sha}~..${commits[commits.length - 1].sha}`);
9
- return changedFiles.split('\n');
8
+ const changedFilesString = spawnCommandInGhWorkspace(`git diff --name-only ${commits[0].sha}~..${commits[commits.length - 1].sha}`);
9
+ const changedFiles = changedFilesString.split('\n');
10
+ console.error(`Changed files (up to 50): ${changedFiles.slice(0, 50).join(', ')}`);
11
+ return changedFiles;
10
12
  };
11
13
  /**
12
14
  * Gets the commits between sourceBranch and targetBranch (exclusive).
@@ -18,8 +20,14 @@ export const getCommits = ({ sourceBranch, targetBranch, baseCommit: baseCommitS
18
20
  commits.reverse();
19
21
  const baseCommitIndex = commits.findIndex((commit) => commit.sha === baseCommitSha);
20
22
  const hasBaseCommit = baseCommitIndex !== -1;
21
- if (hasBaseCommit)
22
- return commits.slice(baseCommitIndex + 1);
23
+ if (hasBaseCommit) {
24
+ const commitsUpToBaseCommit = commits.slice(baseCommitIndex + 1);
25
+ console.error(`Found base commit ${baseCommitSha} at index ${baseCommitIndex}, returning ${commitsUpToBaseCommit.length} commits after it`);
26
+ console.error(`Commits being returned: ${commitsUpToBaseCommit.map((c) => c.sha).join(', ')}`);
27
+ return commitsUpToBaseCommit;
28
+ }
29
+ console.error(`Base commit ${baseCommitSha} not found in the commit range, returning all ${commits.length} commits`);
30
+ console.error(`Commits being returned: ${commits.map((c) => c.sha).join(', ')}`);
23
31
  return commits;
24
32
  };
25
33
  export const getCommitInfo = (commitSha) => {
@@ -1 +1 @@
1
- {"version":3,"file":"git.js","sourceRoot":"","sources":["../../bin/git.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAEvD,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAC1C,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAElF;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAiB,EAAE,EAAE;IACjD,MAAM,YAAY,GAAG,yBAAyB,CAC1C,wBAAwB,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAChF,CAAC;IAEF,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAU,EAAY,EAAE;IACtG,MAAM,cAAc,GAAG,yBAAyB,CAC5C,4BAA4B,cAAc,KAAK,YAAY,KAAK,YAAY,EAAE,CACjF,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACd,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC;IAChF,OAAO,CAAC,OAAO,EAAE,CAAC;IAElB,MAAM,eAAe,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,KAAK,aAAa,CAAC,CAAC;IAEpF,MAAM,aAAa,GAAG,eAAe,KAAK,CAAC,CAAC,CAAC;IAC7C,IAAI,aAAa;QAAE,OAAO,OAAO,CAAC,KAAK,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC;IAE7D,OAAO,OAAO,CAAC;AACnB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,SAAiB,EAAU,EAAE;IACvD,MAAM,YAAY,GAAG,yBAAyB,CAAC,+BAA+B,cAAc,KAAK,SAAS,EAAE,CAAC,CAAC;IAC9G,MAAM,MAAM,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,YAAoB,EAAU,EAAE;IACxD,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACxD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,kCAAkC,YAAY,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC;IAC5C,OAAO;QACH,GAAG;QACH,MAAM;QACN,IAAI;QACJ,OAAO;KACV,CAAC;AACN,CAAC,CAAC"}
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../bin/git.ts"],"names":[],"mappings":"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"}