apify-test-tools 0.10.2-beta.1 → 0.10.2-beta.11
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.
- package/.gitattributes +2 -0
- package/.github/actionlint.yaml +11 -0
- package/.github/actions/checkout-restore-dependencies/action.yaml +64 -28
- package/.github/cli/apify-test-tools.mjs +360 -0
- package/.github/scripts/mask-config-secrets.sh +17 -0
- package/.github/scripts/run-with-apify-tokens.mjs +37 -12
- package/.github/workflows/_check_code.yaml +25 -16
- package/.github/workflows/_move_major_tag.yaml +5 -83
- package/.github/workflows/_tests.yaml +34 -0
- package/.github/workflows/_update_release_metadata.yaml +0 -12
- package/.github/workflows/manual_move_major_tag.yaml +3 -3
- package/.github/workflows/manual_release_stable.yaml +3 -13
- package/.github/workflows/on_master.yaml +9 -5
- package/.github/workflows/on_pull_request.yaml +3 -48
- package/.github/workflows/public_platform-tests-claude-investigate-and-fix.yaml +16 -3
- package/.github/workflows/public_platform-tests.yaml +27 -3
- package/.github/workflows/public_pr-build-test.yaml +67 -29
- package/.github/workflows/public_push-build-latest.yaml +44 -10
- package/.github/workflows/public_review.yaml +5 -4
- package/.husky/pre-commit +5 -0
- package/.prettierignore +3 -0
- package/CHANGELOG.md +17 -0
- package/CONTRIBUTING.md +112 -24
- package/README.md +218 -600
- package/bin/affected-actors.ts +198 -0
- package/bin/build-from-local.ts +65 -13
- package/bin/build.ts +123 -41
- package/bin/diff-changes.ts +32 -23
- package/bin/diff-json-schema.ts +5 -6
- package/bin/git.ts +69 -99
- package/bin/main.ts +96 -135
- package/bin/slack.ts +43 -10
- package/bin/stdin-input.ts +65 -0
- package/bin/test-report.ts +6 -9
- package/bin/types.ts +15 -0
- package/dist/bin/affected-actors.d.ts +46 -0
- package/dist/bin/affected-actors.d.ts.map +1 -0
- package/dist/bin/affected-actors.js +135 -0
- package/dist/bin/affected-actors.js.map +1 -0
- package/dist/bin/build-from-local.d.ts +12 -3
- package/dist/bin/build-from-local.d.ts.map +1 -1
- package/dist/bin/build-from-local.js +34 -12
- package/dist/bin/build-from-local.js.map +1 -1
- package/dist/bin/build.d.ts +30 -7
- package/dist/bin/build.d.ts.map +1 -1
- package/dist/bin/build.js +85 -26
- package/dist/bin/build.js.map +1 -1
- package/dist/bin/diff-changes.d.ts +11 -4
- package/dist/bin/diff-changes.d.ts.map +1 -1
- package/dist/bin/diff-changes.js +19 -19
- package/dist/bin/diff-changes.js.map +1 -1
- package/dist/bin/diff-json-schema.d.ts +2 -2
- package/dist/bin/diff-json-schema.d.ts.map +1 -1
- package/dist/bin/diff-json-schema.js +1 -4
- package/dist/bin/diff-json-schema.js.map +1 -1
- package/dist/bin/git.d.ts +23 -21
- package/dist/bin/git.d.ts.map +1 -1
- package/dist/bin/git.js +60 -83
- package/dist/bin/git.js.map +1 -1
- package/dist/bin/main.js +82 -105
- package/dist/bin/main.js.map +1 -1
- package/dist/bin/slack.d.ts +14 -4
- package/dist/bin/slack.d.ts.map +1 -1
- package/dist/bin/slack.js +39 -6
- package/dist/bin/slack.js.map +1 -1
- package/dist/bin/stdin-input.d.ts +17 -0
- package/dist/bin/stdin-input.d.ts.map +1 -0
- package/dist/bin/stdin-input.js +54 -0
- package/dist/bin/stdin-input.js.map +1 -0
- package/dist/bin/test-report.d.ts.map +1 -1
- package/dist/bin/test-report.js +6 -8
- package/dist/bin/test-report.js.map +1 -1
- package/dist/bin/types.d.ts +13 -0
- package/dist/bin/types.d.ts.map +1 -1
- package/dist/lib/extend-expect.d.ts.map +1 -1
- package/dist/lib/extend-expect.js +37 -218
- package/dist/lib/extend-expect.js.map +1 -1
- package/dist/lib/lib.d.ts +1 -2
- package/dist/lib/lib.d.ts.map +1 -1
- package/dist/lib/lib.js +15 -22
- package/dist/lib/lib.js.map +1 -1
- package/dist/lib/run-checks.d.ts +14 -0
- package/dist/lib/run-checks.d.ts.map +1 -0
- package/dist/lib/run-checks.js +82 -0
- package/dist/lib/run-checks.js.map +1 -0
- package/dist/lib/run-test-result.d.ts +3 -6
- package/dist/lib/run-test-result.d.ts.map +1 -1
- package/dist/lib/run-test-result.js +41 -54
- package/dist/lib/run-test-result.js.map +1 -1
- package/dist/test/bundle/cli-bundle.test.d.ts +2 -0
- package/dist/test/bundle/cli-bundle.test.d.ts.map +1 -0
- package/dist/test/bundle/cli-bundle.test.js +190 -0
- package/dist/test/bundle/cli-bundle.test.js.map +1 -0
- package/dist/test/e2e/cli-bundle.e2e.test.d.ts +2 -0
- package/dist/test/e2e/cli-bundle.e2e.test.d.ts.map +1 -0
- package/dist/test/e2e/cli-bundle.e2e.test.js +138 -0
- package/dist/test/e2e/cli-bundle.e2e.test.js.map +1 -0
- package/dist/test/e2e/git-build-release.e2e.test.d.ts +2 -0
- package/dist/test/e2e/git-build-release.e2e.test.d.ts.map +1 -0
- package/dist/test/e2e/git-build-release.e2e.test.js +87 -0
- package/dist/test/e2e/git-build-release.e2e.test.js.map +1 -0
- package/dist/test/e2e/helpers.d.ts +37 -0
- package/dist/test/e2e/helpers.d.ts.map +1 -0
- package/dist/test/e2e/helpers.js +57 -0
- package/dist/test/e2e/helpers.js.map +1 -0
- package/dist/test/unit/bin/affected-actors-cli.test.d.ts +2 -0
- package/dist/test/unit/bin/affected-actors-cli.test.d.ts.map +1 -0
- package/dist/test/unit/bin/affected-actors-cli.test.js +167 -0
- package/dist/test/unit/bin/affected-actors-cli.test.js.map +1 -0
- package/dist/test/unit/bin/affected-actors.test.d.ts +2 -0
- package/dist/test/unit/bin/affected-actors.test.d.ts.map +1 -0
- package/dist/test/unit/bin/affected-actors.test.js +141 -0
- package/dist/test/unit/bin/affected-actors.test.js.map +1 -0
- package/dist/test/unit/bin/build-cli.test.d.ts +2 -0
- package/dist/test/unit/bin/build-cli.test.d.ts.map +1 -0
- package/dist/test/unit/bin/build-cli.test.js +44 -0
- package/dist/test/unit/bin/build-cli.test.js.map +1 -0
- package/dist/test/unit/bin/build-from-local.test.js +65 -1
- package/dist/test/unit/bin/build-from-local.test.js.map +1 -1
- package/dist/test/unit/bin/build.test.js +223 -3
- package/dist/test/unit/bin/build.test.js.map +1 -1
- package/dist/test/unit/bin/compiled-cli.d.ts +6 -0
- package/dist/test/unit/bin/compiled-cli.d.ts.map +1 -0
- package/dist/test/unit/bin/compiled-cli.js +16 -0
- package/dist/test/unit/bin/compiled-cli.js.map +1 -0
- package/dist/test/unit/bin/diff-changes.test.js +130 -101
- package/dist/test/unit/bin/diff-changes.test.js.map +1 -1
- package/dist/test/unit/bin/diff.test.js +25 -28
- package/dist/test/unit/bin/diff.test.js.map +1 -1
- package/dist/test/unit/bin/git.test.js +69 -152
- package/dist/test/unit/bin/git.test.js.map +1 -1
- package/dist/test/unit/bin/slack.test.d.ts +2 -0
- package/dist/test/unit/bin/slack.test.d.ts.map +1 -0
- package/dist/test/unit/bin/slack.test.js +71 -0
- package/dist/test/unit/bin/slack.test.js.map +1 -0
- package/dist/test/unit/bin/stdin-input.test.d.ts +2 -0
- package/dist/test/unit/bin/stdin-input.test.d.ts.map +1 -0
- package/dist/test/unit/bin/stdin-input.test.js +50 -0
- package/dist/test/unit/bin/stdin-input.test.js.map +1 -0
- package/dist/test/unit/github-scripts/mask-config-secrets.test.d.ts +2 -0
- package/dist/test/unit/github-scripts/mask-config-secrets.test.d.ts.map +1 -0
- package/dist/test/unit/github-scripts/mask-config-secrets.test.js +50 -0
- package/dist/test/unit/github-scripts/mask-config-secrets.test.js.map +1 -0
- package/dist/test/unit/github-scripts/run-with-apify-tokens.test.d.ts +2 -0
- package/dist/test/unit/github-scripts/run-with-apify-tokens.test.d.ts.map +1 -0
- package/dist/test/unit/github-scripts/run-with-apify-tokens.test.js +102 -0
- package/dist/test/unit/github-scripts/run-with-apify-tokens.test.js.map +1 -0
- package/dist/test/unit/run-checks.test.d.ts +2 -0
- package/dist/test/unit/run-checks.test.d.ts.map +1 -0
- package/dist/test/unit/run-checks.test.js +62 -0
- package/dist/test/unit/run-checks.test.js.map +1 -0
- package/dist/test/unit/run-test-result.test.d.ts +2 -0
- package/dist/test/unit/run-test-result.test.d.ts.map +1 -0
- package/dist/test/unit/run-test-result.test.js +34 -0
- package/dist/test/unit/run-test-result.test.js.map +1 -0
- package/dist/test/unit/should-built-and-test.test.js +41 -38
- package/dist/test/unit/should-built-and-test.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/docs/cli.md +373 -0
- package/docs/lib.md +271 -0
- package/docs/workflows.md +370 -0
- package/lib/extend-expect.ts +48 -258
- package/lib/lib.ts +24 -28
- package/lib/run-checks.ts +101 -0
- package/lib/run-test-result.ts +45 -55
- package/package.json +13 -3
- package/test/bundle/cli-bundle.test.ts +235 -0
- package/test/e2e/cli-bundle.e2e.test.ts +207 -0
- package/test/e2e/git-build-release.e2e.test.ts +113 -0
- package/test/e2e/helpers.ts +82 -0
- package/test/unit/bin/affected-actors-cli.test.ts +201 -0
- package/test/unit/bin/affected-actors.test.ts +182 -0
- package/test/unit/bin/build-cli.test.ts +55 -0
- package/test/unit/bin/build-from-local.test.ts +71 -0
- package/test/unit/bin/build.test.ts +279 -3
- package/test/unit/bin/compiled-cli.ts +17 -0
- package/test/unit/bin/diff-changes.test.ts +139 -101
- package/test/unit/bin/diff.test.ts +25 -28
- package/test/unit/bin/git.test.ts +85 -176
- package/test/unit/bin/slack.test.ts +84 -0
- package/test/unit/bin/stdin-input.test.ts +61 -0
- package/test/unit/github-scripts/mask-config-secrets.test.ts +61 -0
- package/test/unit/github-scripts/run-with-apify-tokens.test.ts +115 -0
- package/test/unit/run-checks.test.ts +76 -0
- package/test/unit/run-test-result.test.ts +44 -0
- package/test/unit/should-built-and-test.test.ts +46 -39
- package/.github/scripts/check-major-tag-refs.mjs +0 -72
- package/.github/scripts/check-package-version-bump.mjs +0 -74
- package/.github/workflows-package-version +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "apify-test-tools",
|
|
3
|
-
"version": "0.10.2-beta.
|
|
3
|
+
"version": "0.10.2-beta.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "TBD",
|
|
6
6
|
"repository": {
|
|
@@ -8,7 +8,14 @@
|
|
|
8
8
|
"url": "https://github.com/apify/apify-test-tools.git"
|
|
9
9
|
},
|
|
10
10
|
"engines": {
|
|
11
|
-
"node": ">=
|
|
11
|
+
"node": ">=22.0.0"
|
|
12
|
+
},
|
|
13
|
+
"devEngines": {
|
|
14
|
+
"packageManager": {
|
|
15
|
+
"name": "npm",
|
|
16
|
+
"version": ">=11.10.0",
|
|
17
|
+
"onFail": "warn"
|
|
18
|
+
}
|
|
12
19
|
},
|
|
13
20
|
"bin": {
|
|
14
21
|
"apify-test-tools": "dist/bin/main.js"
|
|
@@ -32,6 +39,7 @@
|
|
|
32
39
|
"@types/node": "^24.0.0",
|
|
33
40
|
"@types/picomatch": "^4.0.3",
|
|
34
41
|
"@types/yargs": "^17.0.33",
|
|
42
|
+
"esbuild": "0.25.12",
|
|
35
43
|
"eslint": "^9.29.0",
|
|
36
44
|
"eslint-config-prettier": "^10.1.5",
|
|
37
45
|
"globals": "^17.0.0",
|
|
@@ -51,12 +59,14 @@
|
|
|
51
59
|
"start": "npm run dist/bin/main.js",
|
|
52
60
|
"start:dev": "cd local-clone && tsx ../bin/main.ts",
|
|
53
61
|
"build": "tsc && chmod +x ./dist/bin/main.js",
|
|
62
|
+
"bundle": "esbuild bin/main.ts --bundle --minify --platform=node --format=esm --target=node24 --log-level=warning --banner:js=\"import{createRequire as __createRequire}from'node:module';const require=__createRequire(import.meta.url);\" --outfile=.github/cli/apify-test-tools.mjs",
|
|
54
63
|
"lint": "eslint",
|
|
55
64
|
"lint:fix": "eslint --fix",
|
|
56
65
|
"format": "prettier --write .",
|
|
57
66
|
"format:check": "prettier --check .",
|
|
58
67
|
"type-check": "tsc --noEmit",
|
|
59
|
-
"test": "vitest run",
|
|
68
|
+
"test": "vitest run --exclude 'test/e2e/**'",
|
|
69
|
+
"test:e2e": "vitest run test/e2e",
|
|
60
70
|
"check-unused": "npx knip",
|
|
61
71
|
"prepare": "husky .husky || true"
|
|
62
72
|
},
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { execFileSync, spawnSync } from 'node:child_process';
|
|
2
|
+
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
9
|
+
|
|
10
|
+
// Runs the committed bundle the composite action ships, not the sources, so these catch anything
|
|
11
|
+
// that only breaks once bundled (a dependency loading code at runtime, a missing shim). Everything
|
|
12
|
+
// here works without tokens or network: read-only commands, dry runs that end up with nothing to
|
|
13
|
+
// build, and the missing-token error. The `CLI bundle` check keeps the bundle in sync with bin/.
|
|
14
|
+
const bundlePath = fileURLToPath(new URL('../../.github/cli/apify-test-tools.mjs', import.meta.url));
|
|
15
|
+
|
|
16
|
+
// Only what node and git need, so no Apify or Slack token from the developer's shell leaks in.
|
|
17
|
+
const cliEnv = { PATH: process.env.PATH ?? '', HOME: os.tmpdir() };
|
|
18
|
+
const gitEnv = {
|
|
19
|
+
...cliEnv,
|
|
20
|
+
GIT_AUTHOR_NAME: 'Tester',
|
|
21
|
+
GIT_AUTHOR_EMAIL: 'tester@example.com',
|
|
22
|
+
GIT_COMMITTER_NAME: 'Tester',
|
|
23
|
+
GIT_COMMITTER_EMAIL: 'tester@example.com',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
let repoDir: string;
|
|
27
|
+
let baseSha: string;
|
|
28
|
+
let headSha: string;
|
|
29
|
+
|
|
30
|
+
const git = (...args: string[]) => execFileSync('git', args, { cwd: repoDir, env: gitEnv, encoding: 'utf8' }).trim();
|
|
31
|
+
|
|
32
|
+
const writeRepoFile = async (file: string, content: string) => {
|
|
33
|
+
await mkdir(path.dirname(path.join(repoDir, file)), { recursive: true });
|
|
34
|
+
await writeFile(path.join(repoDir, file), content);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const runCliWithInput = (input: string, ...args: string[]) => {
|
|
38
|
+
const result = spawnSync(process.execPath, [bundlePath, ...args], {
|
|
39
|
+
cwd: repoDir,
|
|
40
|
+
env: cliEnv,
|
|
41
|
+
encoding: 'utf8',
|
|
42
|
+
input,
|
|
43
|
+
});
|
|
44
|
+
return { status: result.status, stdout: result.stdout, stderr: result.stderr };
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const runCli = (...args: string[]) => runCliWithInput('', ...args);
|
|
48
|
+
|
|
49
|
+
const gitRange = ['--source-branch', 'feature', '--target-branch', 'main'];
|
|
50
|
+
|
|
51
|
+
describe('CLI bundle', () => {
|
|
52
|
+
// Two Actors on `main`; `feature` changes only tester/foo and the root README.
|
|
53
|
+
beforeAll(async () => {
|
|
54
|
+
repoDir = await mkdtemp(path.join(os.tmpdir(), 'apify-cli-bundle-'));
|
|
55
|
+
git('init', '-q', '-b', 'main');
|
|
56
|
+
git('remote', 'add', 'origin', 'https://github.com/apify/fixture-repo.git');
|
|
57
|
+
for (const name of ['foo', 'bar']) {
|
|
58
|
+
await writeRepoFile(
|
|
59
|
+
`actors/${name}/.actor/actor.json`,
|
|
60
|
+
JSON.stringify({ actorSpecification: 1, name, version: '0.1' }),
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
await writeRepoFile(
|
|
64
|
+
'apify-test-tools.config.json',
|
|
65
|
+
JSON.stringify({
|
|
66
|
+
actors: [
|
|
67
|
+
{ folder: 'actors/foo', actorFullName: 'tester/foo', tokenEnvVar: 'FOO_TOKEN' },
|
|
68
|
+
{ folder: 'actors/bar', actorFullName: 'tester/bar', tokenEnvVar: 'BAR_TOKEN' },
|
|
69
|
+
],
|
|
70
|
+
}),
|
|
71
|
+
);
|
|
72
|
+
git('add', '-A');
|
|
73
|
+
git('commit', '-q', '-m', 'chore: init');
|
|
74
|
+
baseSha = git('rev-parse', 'HEAD');
|
|
75
|
+
|
|
76
|
+
git('checkout', '-q', '-b', 'feature');
|
|
77
|
+
await writeRepoFile('actors/foo/main.js', 'console.log("changed");\n');
|
|
78
|
+
git('add', '-A');
|
|
79
|
+
git('commit', '-q', '-m', 'fix(foo): change foo');
|
|
80
|
+
await writeRepoFile('README.md', 'readme\n');
|
|
81
|
+
git('add', '-A');
|
|
82
|
+
git('commit', '-q', '-m', 'docs: readme');
|
|
83
|
+
headSha = git('rev-parse', 'HEAD');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
afterAll(async () => {
|
|
87
|
+
if (repoDir) await rm(repoDir, { recursive: true, force: true });
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('lists every command in --help', () => {
|
|
91
|
+
const { status, stdout } = runCli('--help');
|
|
92
|
+
expect(status).toBe(0);
|
|
93
|
+
for (const command of [
|
|
94
|
+
'get-commits',
|
|
95
|
+
'get-latest-commit',
|
|
96
|
+
'get-changed-files',
|
|
97
|
+
'get-actor-configs',
|
|
98
|
+
'get-affected-actors',
|
|
99
|
+
'report-tests',
|
|
100
|
+
'build',
|
|
101
|
+
'notify-release',
|
|
102
|
+
'build-from-local',
|
|
103
|
+
'delete-old-builds',
|
|
104
|
+
]) {
|
|
105
|
+
expect(stdout).toContain(command);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('get-commits returns the commits on the source branch', () => {
|
|
110
|
+
const { status, stdout, stderr } = runCli('get-commits', ...gitRange);
|
|
111
|
+
expect(status, stderr).toBe(0);
|
|
112
|
+
expect(JSON.parse(stdout).map((commit: { message: string }) => commit.message)).toEqual([
|
|
113
|
+
'fix(foo): change foo',
|
|
114
|
+
'docs: readme',
|
|
115
|
+
]);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('get-latest-commit returns the head of the source branch', () => {
|
|
119
|
+
const { status, stdout, stderr } = runCli('get-latest-commit', ...gitRange);
|
|
120
|
+
expect(status, stderr).toBe(0);
|
|
121
|
+
expect(JSON.parse(stdout)).toMatchObject({ sha: headSha, message: 'docs: readme' });
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('get-changed-files returns the files changed on the source branch', () => {
|
|
125
|
+
const { status, stdout, stderr } = runCli('get-changed-files', ...gitRange);
|
|
126
|
+
expect(status, stderr).toBe(0);
|
|
127
|
+
expect(JSON.parse(stdout)).toEqual(['README.md', 'actors/foo/main.js']);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('get-actor-configs reads both Actors from the config file', () => {
|
|
131
|
+
const { status, stdout, stderr } = runCli('get-actor-configs');
|
|
132
|
+
expect(status, stderr).toBe(0);
|
|
133
|
+
expect(JSON.parse(stdout).map((actor: { actorFullName: string }) => actor.actorFullName)).toEqual([
|
|
134
|
+
'tester/foo',
|
|
135
|
+
'tester/bar',
|
|
136
|
+
]);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('get-affected-actors returns only the Actor whose files changed', () => {
|
|
140
|
+
// `feature` is checked out, and the range always ends at HEAD
|
|
141
|
+
const { status, stdout, stderr } = runCli('get-affected-actors', '--base', 'main');
|
|
142
|
+
expect(status, stderr).toBe(0);
|
|
143
|
+
expect(JSON.parse(stdout)).toMatchObject({
|
|
144
|
+
version: 1,
|
|
145
|
+
head: headSha,
|
|
146
|
+
functionallyChangedActors: [{ actorFullName: 'tester/foo' }],
|
|
147
|
+
// The root README isn't in tester/bar's folder, so it doesn't count for it
|
|
148
|
+
cosmeticallyChangedActors: [],
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('build --dry-run with nothing to build needs no token', () => {
|
|
153
|
+
const { status, stdout, stderr } = runCliWithInput(
|
|
154
|
+
JSON.stringify({ actors: [] }),
|
|
155
|
+
'build',
|
|
156
|
+
'--version-number',
|
|
157
|
+
'0.99',
|
|
158
|
+
'--dry-run',
|
|
159
|
+
);
|
|
160
|
+
expect(status, stderr).toBe(0);
|
|
161
|
+
expect(JSON.parse(stdout)).toEqual({ dryRun: true, builds: [] });
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('build --dry-run fails cleanly when the Actor token is missing', () => {
|
|
165
|
+
const { status, stderr } = runCliWithInput(
|
|
166
|
+
JSON.stringify({ actors: [{ actorFullName: 'tester/foo' }] }),
|
|
167
|
+
'build',
|
|
168
|
+
'--version-number',
|
|
169
|
+
'0.99',
|
|
170
|
+
'--dry-run',
|
|
171
|
+
);
|
|
172
|
+
expect(status).toBe(1);
|
|
173
|
+
expect(stderr).toContain('Env var FOO_TOKEN is not set (needed for actor "tester/foo")');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('build fails on empty input instead of building nothing', () => {
|
|
177
|
+
const { status, stderr } = runCli('build', '--version-number', '0.99', '--dry-run');
|
|
178
|
+
expect(status).toBe(1);
|
|
179
|
+
expect(stderr).toContain('got nothing');
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
it('get-affected-actors --since HEAD reports nothing', () => {
|
|
183
|
+
const { status, stdout, stderr } = runCli('get-affected-actors', '--since', headSha);
|
|
184
|
+
expect(status, stderr).toBe(0);
|
|
185
|
+
expect(JSON.parse(stdout)).toMatchObject({
|
|
186
|
+
commits: [],
|
|
187
|
+
functionallyChangedActors: [],
|
|
188
|
+
cosmeticallyChangedActors: [],
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('notify-release announces nothing, and needs no token, when there are no new commits', () => {
|
|
193
|
+
const affected = runCli('get-affected-actors', '--since', headSha).stdout;
|
|
194
|
+
const { status, stderr } = runCliWithInput(affected, 'notify-release', '--release-slack-channel', '#releases');
|
|
195
|
+
expect(status, stderr).toBe(0);
|
|
196
|
+
expect(stderr).toContain('No new commits, so there is no release to announce');
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('notify-release skips Slack without a channel', () => {
|
|
200
|
+
const affected = runCli('get-affected-actors', '--since', baseSha).stdout;
|
|
201
|
+
const { status, stderr } = runCliWithInput(affected, 'notify-release', '--dry-run');
|
|
202
|
+
expect(status, stderr).toBe(0);
|
|
203
|
+
expect(stderr).toContain('Skipping slack notification');
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('report-tests summarizes a vitest JSON report', async () => {
|
|
207
|
+
const assertion = (title: string, status: 'passed' | 'failed', runId: string) => ({
|
|
208
|
+
ancestorTitles: [],
|
|
209
|
+
fullName: `foo ${title}`,
|
|
210
|
+
title,
|
|
211
|
+
status,
|
|
212
|
+
failureMessages: status === 'failed' ? ['AssertionError: expected 1 to be 2\n at foo.test.ts:1:1'] : [],
|
|
213
|
+
meta: { runId, runLink: `https://console.apify.com/view/runs/${runId}`, actorId: 'tester/foo' },
|
|
214
|
+
});
|
|
215
|
+
await writeRepoFile(
|
|
216
|
+
'test-output.json',
|
|
217
|
+
JSON.stringify({
|
|
218
|
+
success: false,
|
|
219
|
+
testResults: [
|
|
220
|
+
{
|
|
221
|
+
name: 'test/platform/foo.test.ts',
|
|
222
|
+
status: 'failed',
|
|
223
|
+
assertionResults: [assertion('works', 'passed', 'run1'), assertion('fails', 'failed', 'run2')],
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
}),
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
const { status, stderr } = runCli('report-tests', '--report-file', 'test-output.json', '--dry-run');
|
|
230
|
+
expect(status, stderr).toBe(0);
|
|
231
|
+
expect(stderr).toContain('PASSED: 1, FAILED: 1');
|
|
232
|
+
expect(stderr).toContain('1) foo fails ... https://console.apify.com/view/runs/run2');
|
|
233
|
+
expect(stderr).toContain('Skipping slack notification');
|
|
234
|
+
});
|
|
235
|
+
});
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { mkdir, mkdtemp, readFile, rm, symlink, writeFile } from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import process from 'node:process';
|
|
6
|
+
|
|
7
|
+
import { ApifyClient } from 'apify-client';
|
|
8
|
+
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
9
|
+
|
|
10
|
+
import type { ActorBuild } from './helpers.js';
|
|
11
|
+
import {
|
|
12
|
+
cliEnv,
|
|
13
|
+
gitEnv,
|
|
14
|
+
projectRoot,
|
|
15
|
+
runCli as runCliIn,
|
|
16
|
+
runCliWithInput as runCliWithInputIn,
|
|
17
|
+
runProcess,
|
|
18
|
+
token,
|
|
19
|
+
TOKEN_ENV_VAR,
|
|
20
|
+
} from './helpers.js';
|
|
21
|
+
|
|
22
|
+
// End-to-end run of the shipped CLI bundle against two dummy Actors in an isolated sandbox account:
|
|
23
|
+
// dry-run plans read the real Actors, `build-from-local` really builds them, the lib runs them
|
|
24
|
+
// through `testActor` on exactly those builds (the ACTOR_BUILDS handoff), `report-tests` reads the
|
|
25
|
+
// result, and `delete-old-builds` cleans up. Git builds of a real repository are in
|
|
26
|
+
// git-build-release.e2e.test.ts.
|
|
27
|
+
//
|
|
28
|
+
// Runs with `npm run test:e2e`, kept out of `npm test`. Skipped without the token, e.g. on fork PRs.
|
|
29
|
+
const ACTORS = ['test-tools-testing-sandbox/dummy-for-testing-1', 'test-tools-testing-sandbox/dummy-for-testing-2'];
|
|
30
|
+
// Only used as the source URL in dry-run plans; nothing is cloned from it.
|
|
31
|
+
const REPO_URL = 'https://github.com/apify/apify-test-tools-e2e-fixture';
|
|
32
|
+
|
|
33
|
+
const vitestPath = path.join(projectRoot, 'node_modules/vitest/vitest.mjs');
|
|
34
|
+
|
|
35
|
+
let repoDir: string;
|
|
36
|
+
let baseSha: string;
|
|
37
|
+
|
|
38
|
+
const git = (...args: string[]) => execFileSync('git', args, { cwd: repoDir, env: gitEnv, encoding: 'utf8' }).trim();
|
|
39
|
+
|
|
40
|
+
const writeRepoFile = async (file: string, content: string) => {
|
|
41
|
+
await mkdir(path.dirname(path.join(repoDir, file)), { recursive: true });
|
|
42
|
+
await writeFile(path.join(repoDir, file), content);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const runCli = async (...args: string[]) => runCliIn(repoDir, ...args);
|
|
46
|
+
const runCliWithInput = async (input: string, ...args: string[]) => runCliWithInputIn(repoDir, input, ...args);
|
|
47
|
+
|
|
48
|
+
describe.runIf(token)('CLI bundle against real Actors', { timeout: 2 * 60_000 }, () => {
|
|
49
|
+
let builds: ActorBuild[];
|
|
50
|
+
|
|
51
|
+
// Both Actors on `main`; `feature` changes only dummy-for-testing-1.
|
|
52
|
+
beforeAll(async () => {
|
|
53
|
+
repoDir = await mkdtemp(path.join(os.tmpdir(), 'apify-cli-e2e-'));
|
|
54
|
+
git('init', '-q', '-b', 'main');
|
|
55
|
+
git('remote', 'add', 'origin', `${REPO_URL}.git`);
|
|
56
|
+
const actors = [];
|
|
57
|
+
for (const [i, actorFullName] of ACTORS.entries()) {
|
|
58
|
+
const folder = `actors/dummy-${i + 1}`;
|
|
59
|
+
await writeRepoFile(
|
|
60
|
+
`${folder}/.actor/actor.json`,
|
|
61
|
+
JSON.stringify({
|
|
62
|
+
actorSpecification: 1,
|
|
63
|
+
name: actorFullName.split('/')[1],
|
|
64
|
+
version: '0.0',
|
|
65
|
+
dockerfile: '../Dockerfile',
|
|
66
|
+
}),
|
|
67
|
+
);
|
|
68
|
+
await writeRepoFile(
|
|
69
|
+
`${folder}/Dockerfile`,
|
|
70
|
+
'FROM apify/actor-node:22\nCOPY . ./\nCMD ["node", "main.js"]\n',
|
|
71
|
+
);
|
|
72
|
+
await writeRepoFile(`${folder}/main.js`, `console.log('dummy ${i + 1}');\n`);
|
|
73
|
+
actors.push({ folder, actorFullName, tokenEnvVar: TOKEN_ENV_VAR });
|
|
74
|
+
}
|
|
75
|
+
await writeRepoFile('apify-test-tools.config.json', JSON.stringify({ actors }));
|
|
76
|
+
git('add', '-A');
|
|
77
|
+
git('commit', '-q', '-m', 'chore: init');
|
|
78
|
+
baseSha = git('rev-parse', 'HEAD');
|
|
79
|
+
|
|
80
|
+
git('checkout', '-q', '-b', 'feature');
|
|
81
|
+
await writeRepoFile('actors/dummy-1/main.js', "console.log('dummy 1 changed');\n");
|
|
82
|
+
git('add', '-A');
|
|
83
|
+
git('commit', '-q', '-m', 'fix(dummy-1): change');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
afterAll(async () => {
|
|
87
|
+
if (repoDir) await rm(repoDir, { recursive: true, force: true });
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
it('build --dry-run plans a test build of the Actors it is given', async () => {
|
|
91
|
+
const { status, stdout, stderr } = await runCliWithInput(
|
|
92
|
+
JSON.stringify({ actors: [{ actorFullName: ACTORS[0] }] }),
|
|
93
|
+
'build',
|
|
94
|
+
'--version-number',
|
|
95
|
+
'0.99',
|
|
96
|
+
'--repo-url',
|
|
97
|
+
REPO_URL,
|
|
98
|
+
'--dry-run',
|
|
99
|
+
);
|
|
100
|
+
expect(status, stderr).toBe(0);
|
|
101
|
+
expect(JSON.parse(stdout)).toEqual({
|
|
102
|
+
dryRun: true,
|
|
103
|
+
builds: [
|
|
104
|
+
{ actorFullName: ACTORS[0], versionNumber: '0.99', gitRepoUrl: `${REPO_URL}#feature:actors/dummy-1` },
|
|
105
|
+
],
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('a release pipeline plans a build of the default version of every changed Actor', async () => {
|
|
110
|
+
const affected = await runCli('get-affected-actors', '--since', baseSha);
|
|
111
|
+
expect(affected.status, affected.stderr).toBe(0);
|
|
112
|
+
const { functionallyChangedActors, cosmeticallyChangedActors } = JSON.parse(affected.stdout);
|
|
113
|
+
|
|
114
|
+
const { status, stderr } = await runCliWithInput(
|
|
115
|
+
JSON.stringify({ actors: [...functionallyChangedActors, ...cosmeticallyChangedActors] }),
|
|
116
|
+
'build',
|
|
117
|
+
'--version-number',
|
|
118
|
+
'default',
|
|
119
|
+
'--repo-url',
|
|
120
|
+
REPO_URL,
|
|
121
|
+
'--dry-run',
|
|
122
|
+
);
|
|
123
|
+
expect(status, stderr).toBe(0);
|
|
124
|
+
expect(stderr).toContain(
|
|
125
|
+
`[DRY RUN] Would build:\n ${ACTORS[0]} (0.0) from ${REPO_URL}#feature:actors/dummy-1`,
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('build-from-local --dry-run plans both Actors from the working tree', async () => {
|
|
130
|
+
const { status, stdout, stderr } = await runCli('build-from-local', '--dry-run');
|
|
131
|
+
expect(status, stderr).toBe(0);
|
|
132
|
+
expect(JSON.parse(stdout)).toMatchObject({
|
|
133
|
+
dryRun: true,
|
|
134
|
+
builds: ACTORS.map((actorFullName) => ({ actorFullName, versionNumber: '0.98', fileCount: 3 })),
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('build-from-local builds both Actors', { timeout: 10 * 60_000 }, async () => {
|
|
139
|
+
const { status, stdout, stderr } = await runCli('build-from-local');
|
|
140
|
+
expect(status, stderr).toBe(0);
|
|
141
|
+
builds = JSON.parse(stdout);
|
|
142
|
+
expect(builds.map((build) => build.actorFullName)).toEqual(ACTORS);
|
|
143
|
+
for (const build of builds) expect(build.buildNumber).toMatch(/^0\.98\.\d+$/);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('runs the builds through testActor and reports the results', { timeout: 10 * 60_000 }, async () => {
|
|
147
|
+
expect(builds, 'needs the builds from the previous test').toBeDefined();
|
|
148
|
+
|
|
149
|
+
// A consumer's platform test, importing the lib from this checkout. The symlink lets it
|
|
150
|
+
// resolve vitest and the lib's dependencies the way an installed package would.
|
|
151
|
+
await symlink(path.join(projectRoot, 'node_modules'), path.join(repoDir, 'node_modules'), 'dir');
|
|
152
|
+
const libPath = path.join(projectRoot, 'index.ts');
|
|
153
|
+
const actorTests = ACTORS.map(
|
|
154
|
+
(actorId) => `
|
|
155
|
+
testActor(${JSON.stringify(actorId)}, 'finishes', async ({ expect, run }) => {
|
|
156
|
+
const result = await run({ input: {} });
|
|
157
|
+
expect(result.status).toBe('SUCCEEDED');
|
|
158
|
+
});`,
|
|
159
|
+
).join('\n');
|
|
160
|
+
await writeRepoFile(
|
|
161
|
+
'test/platform/dummies.test.ts',
|
|
162
|
+
`import { describe, testActor } from ${JSON.stringify(libPath)};
|
|
163
|
+
|
|
164
|
+
describe('sandbox dummies', () => {${actorTests}
|
|
165
|
+
});
|
|
166
|
+
`,
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
const vitest = await runProcess(
|
|
170
|
+
process.execPath,
|
|
171
|
+
[vitestPath, 'run', 'test/platform', '--reporter=json', '--outputFile=./test-output.json'],
|
|
172
|
+
{
|
|
173
|
+
cwd: repoDir,
|
|
174
|
+
env: { ...cliEnv, TESTER_APIFY_TOKEN: token!, ACTOR_BUILDS: JSON.stringify(builds) },
|
|
175
|
+
},
|
|
176
|
+
);
|
|
177
|
+
expect(vitest.status, `${vitest.stdout}\n${vitest.stderr}`).toBe(0);
|
|
178
|
+
|
|
179
|
+
// Each run used the build from ACTOR_BUILDS, not the Actor's default build.
|
|
180
|
+
const report = JSON.parse(await readFile(path.join(repoDir, 'test-output.json'), 'utf8'));
|
|
181
|
+
const assertions = report.testResults.flatMap(
|
|
182
|
+
(file: { assertionResults: { meta: { runId: string } }[] }) => file.assertionResults,
|
|
183
|
+
);
|
|
184
|
+
expect(assertions).toHaveLength(ACTORS.length);
|
|
185
|
+
const client = new ApifyClient({ token });
|
|
186
|
+
const runBuildIds = await Promise.all(
|
|
187
|
+
assertions.map(
|
|
188
|
+
async ({ meta }: { meta: { runId: string } }) => (await client.run(meta.runId).get())?.buildId,
|
|
189
|
+
),
|
|
190
|
+
);
|
|
191
|
+
expect(runBuildIds.sort()).toEqual(builds.map((build) => build.buildId).sort());
|
|
192
|
+
|
|
193
|
+
const { status, stderr } = await runCli('report-tests', '--report-file', 'test-output.json', '--dry-run');
|
|
194
|
+
expect(status, stderr).toBe(0);
|
|
195
|
+
expect(stderr).toContain(`PASSED: ${ACTORS.length}, FAILED: 0`);
|
|
196
|
+
expect(stderr).toContain('https://console.apify.com/view/runs/');
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// Last, so builds from earlier runs of this suite don't pile up in the sandbox.
|
|
200
|
+
it('delete-old-builds keeps the default builds', async () => {
|
|
201
|
+
const { status, stderr } = await runCli('delete-old-builds');
|
|
202
|
+
expect(status, stderr).toBe(0);
|
|
203
|
+
for (const actorFullName of ACTORS) {
|
|
204
|
+
expect(stderr).toContain(`[DELETE OLD BUILDS][${actorFullName}]: Skipping default build`);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { mkdtemp, rm } from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
import { ApifyClient } from 'apify-client';
|
|
7
|
+
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
8
|
+
|
|
9
|
+
import type { ActorBuild } from './helpers.js';
|
|
10
|
+
import { gitEnv, runCli as runCliIn, runCliWithInput as runCliWithInputIn, token } from './helpers.js';
|
|
11
|
+
|
|
12
|
+
// Real git builds of a real repository: the shipped CLI bundle builds an Actor from a clone of
|
|
13
|
+
// apify-store/testing-repo-for-github-actions, and the Apify builder clones the same repository
|
|
14
|
+
// (over SSH, with the sandbox org's deploy key installed on it).
|
|
15
|
+
//
|
|
16
|
+
// The repo's `e2e/base` and `e2e/feature` branches are fixtures and never change: `e2e/feature`
|
|
17
|
+
// adds one commit touching only dummy-for-testing-1. Like the reusable workflows, the commands run
|
|
18
|
+
// with `e2e/feature` checked out and compare it with `origin/e2e/base`. The release pipeline rebuilds
|
|
19
|
+
// dummy-for-testing-1 under `latest` on every run, which is fine for a sandbox Actor nobody else uses.
|
|
20
|
+
//
|
|
21
|
+
// Runs with `npm run test:e2e`, kept out of `npm test`. Skipped without the token, e.g. on fork PRs.
|
|
22
|
+
const FIXTURE_REPO = 'https://github.com/apify-store/testing-repo-for-github-actions';
|
|
23
|
+
const BASE_BRANCH = 'e2e/base';
|
|
24
|
+
const FEATURE_BRANCH = 'e2e/feature';
|
|
25
|
+
const CHANGED_ACTOR = 'test-tools-testing-sandbox/dummy-for-testing-1';
|
|
26
|
+
const CHANGED_ACTOR_FOLDER = 'actors/dummy-for-testing-1';
|
|
27
|
+
// The CLI builds from the SSH form of the origin URL, which is what lets a deploy key work.
|
|
28
|
+
const BUILD_SOURCE = `git@github.com:apify-store/testing-repo-for-github-actions#${FEATURE_BRANCH}:${CHANGED_ACTOR_FOLDER}`;
|
|
29
|
+
|
|
30
|
+
let repoDir: string;
|
|
31
|
+
|
|
32
|
+
const git = (...args: string[]) => execFileSync('git', args, { cwd: repoDir, env: gitEnv, encoding: 'utf8' }).trim();
|
|
33
|
+
const runCli = async (...args: string[]) => runCliIn(repoDir, ...args);
|
|
34
|
+
const runCliWithInput = async (input: string, ...args: string[]) => runCliWithInputIn(repoDir, input, ...args);
|
|
35
|
+
|
|
36
|
+
const getAffectedActors = async () => {
|
|
37
|
+
const { status, stdout, stderr } = await runCli('get-affected-actors', '--base', `origin/${BASE_BRANCH}`);
|
|
38
|
+
expect(status, stderr).toBe(0);
|
|
39
|
+
return JSON.parse(stdout);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
describe.runIf(token)('CLI bundle building a real repository', { timeout: 2 * 60_000 }, () => {
|
|
43
|
+
const client = new ApifyClient({ token });
|
|
44
|
+
|
|
45
|
+
const versionSource = async (versionNumber: string) => {
|
|
46
|
+
const actor = await client.actor(CHANGED_ACTOR).get();
|
|
47
|
+
const version = actor?.versions.find(({ versionNumber: number }) => number === versionNumber);
|
|
48
|
+
return version && 'gitRepoUrl' in version ? version.gitRepoUrl : undefined;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// A full clone checked out on the feature branch, like actions/checkout with fetch-depth: 0.
|
|
52
|
+
beforeAll(async () => {
|
|
53
|
+
repoDir = await mkdtemp(path.join(os.tmpdir(), 'apify-cli-e2e-git-'));
|
|
54
|
+
execFileSync('git', ['clone', '-q', FIXTURE_REPO, repoDir], { env: gitEnv });
|
|
55
|
+
git('checkout', '-q', '-b', FEATURE_BRANCH, `origin/${FEATURE_BRANCH}`);
|
|
56
|
+
}, 5 * 60_000);
|
|
57
|
+
|
|
58
|
+
afterAll(async () => {
|
|
59
|
+
if (repoDir) await rm(repoDir, { recursive: true, force: true });
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('get-affected-actors finds only the Actor the feature branch changed', async () => {
|
|
63
|
+
expect(await getAffectedActors()).toMatchObject({
|
|
64
|
+
functionallyChangedActors: [{ actorFullName: CHANGED_ACTOR }],
|
|
65
|
+
cosmeticallyChangedActors: [],
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('build builds the changed Actor from the feature branch', { timeout: 10 * 60_000 }, async () => {
|
|
70
|
+
// What the PR workflow does: the functionally changed Actors, piped into a test build
|
|
71
|
+
const { functionallyChangedActors } = await getAffectedActors();
|
|
72
|
+
const { status, stdout, stderr } = await runCliWithInput(
|
|
73
|
+
JSON.stringify({ actors: functionallyChangedActors }),
|
|
74
|
+
'build',
|
|
75
|
+
'--version-number',
|
|
76
|
+
'0.99',
|
|
77
|
+
);
|
|
78
|
+
expect(status, stderr).toBe(0);
|
|
79
|
+
const builds: ActorBuild[] = JSON.parse(stdout);
|
|
80
|
+
expect(builds).toMatchObject([
|
|
81
|
+
{ actorFullName: CHANGED_ACTOR, buildNumber: expect.stringMatching(/^0\.99\.\d+$/) },
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
// The version builds the checked-out branch, as it is on the remote.
|
|
85
|
+
expect(await versionSource('0.99')).toBe(BUILD_SOURCE);
|
|
86
|
+
expect((await client.build(builds[0].buildId).get())?.status).toBe('SUCCEEDED');
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('the release pipeline rebuilds the default version of the changed Actor', { timeout: 10 * 60_000 }, async () => {
|
|
90
|
+
// What the release workflow does: every Actor changed since the last release, built into its default version
|
|
91
|
+
const baseSha = git('rev-parse', `origin/${BASE_BRANCH}`);
|
|
92
|
+
const affected = await runCli('get-affected-actors', '--since', baseSha);
|
|
93
|
+
expect(affected.status, affected.stderr).toBe(0);
|
|
94
|
+
const { functionallyChangedActors, cosmeticallyChangedActors } = JSON.parse(affected.stdout);
|
|
95
|
+
|
|
96
|
+
const { status, stderr } = await runCliWithInput(
|
|
97
|
+
JSON.stringify({ actors: [...functionallyChangedActors, ...cosmeticallyChangedActors] }),
|
|
98
|
+
'build',
|
|
99
|
+
'--version-number',
|
|
100
|
+
'default',
|
|
101
|
+
);
|
|
102
|
+
expect(status, stderr).toBe(0);
|
|
103
|
+
expect(stderr).toMatch(new RegExp(`\\[${CHANGED_ACTOR}\\]: 0\\.0\\.\\d+`));
|
|
104
|
+
|
|
105
|
+
// Releasing builds the default version from the branch being released.
|
|
106
|
+
expect(await versionSource('0.0')).toBe(BUILD_SOURCE);
|
|
107
|
+
|
|
108
|
+
// Without a channel the announcement is skipped, so it needs no Slack token
|
|
109
|
+
const notify = await runCliWithInput(affected.stdout, 'notify-release');
|
|
110
|
+
expect(notify.status, notify.stderr).toBe(0);
|
|
111
|
+
expect(notify.stderr).toContain('Skipping slack notification');
|
|
112
|
+
});
|
|
113
|
+
});
|