act-test-runner 2.0.0

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 (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +56 -0
  3. package/dist/ActExecStatus.d.ts +28 -0
  4. package/dist/ActExecStatus.js +29 -0
  5. package/dist/ActJobExecResult.d.ts +39 -0
  6. package/dist/ActJobExecResult.js +42 -0
  7. package/dist/ActOutputListener.d.ts +58 -0
  8. package/dist/ActOutputListener.js +45 -0
  9. package/dist/ActResourceSpec.d.ts +6 -0
  10. package/dist/ActRunner.d.ts +168 -0
  11. package/dist/ActRunner.js +304 -0
  12. package/dist/ActRunnerError.d.ts +25 -0
  13. package/dist/ActRunnerError.js +25 -0
  14. package/dist/ActRunnerOptions.d.ts +57 -0
  15. package/dist/ActRunnerOptions.js +22 -0
  16. package/dist/ActRunnerResult.d.ts +68 -0
  17. package/dist/ActRunnerResult.js +33 -0
  18. package/dist/ActWorkflowExecResult.d.ts +45 -0
  19. package/dist/ActWorkflowExecResult.js +49 -0
  20. package/dist/index.d.ts +27 -0
  21. package/dist/index.js +24 -0
  22. package/dist/internal/ActCliParams.d.ts +57 -0
  23. package/dist/internal/ActCliParams.js +119 -0
  24. package/dist/internal/ActExecListener.d.ts +37 -0
  25. package/dist/internal/ActExecListener.js +98 -0
  26. package/dist/internal/ActJobExecResultBuilder.d.ts +33 -0
  27. package/dist/internal/ActJobExecResultBuilder.js +52 -0
  28. package/dist/internal/ActJobOutputProcessor.d.ts +40 -0
  29. package/dist/internal/ActJobOutputProcessor.js +101 -0
  30. package/dist/internal/ActJsonOutput.d.ts +39 -0
  31. package/dist/internal/ActJsonOutput.js +53 -0
  32. package/dist/internal/ActResourceSpec.d.ts +26 -0
  33. package/dist/internal/ActResourceSpec.js +30 -0
  34. package/dist/internal/ActStepOutputProcessor.d.ts +32 -0
  35. package/dist/internal/ActStepOutputProcessor.js +51 -0
  36. package/dist/internal/JobIterationTracker.d.ts +27 -0
  37. package/dist/internal/JobIterationTracker.js +41 -0
  38. package/dist/internal/JobTrackingActExecListener.d.ts +34 -0
  39. package/dist/internal/JobTrackingActExecListener.js +74 -0
  40. package/dist/internal/OutputForwardingActExecListener.d.ts +30 -0
  41. package/dist/internal/OutputForwardingActExecListener.js +40 -0
  42. package/dist/utils/checks.d.ts +23 -0
  43. package/dist/utils/checks.js +38 -0
  44. package/dist/utils/fsutils.d.ts +27 -0
  45. package/dist/utils/fsutils.js +43 -0
  46. package/dist/utils/objects.d.ts +22 -0
  47. package/dist/utils/objects.js +25 -0
  48. package/dist/utils/types.d.ts +24 -0
  49. package/dist/utils/types.js +22 -0
  50. package/package.json +72 -0
package/dist/index.js ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Copyright (c) 2026 original authors
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ export { ActRunner } from './ActRunner.js';
23
+ export { ActOutputLevel, StdStreamOutputListener, } from './ActOutputListener.js';
24
+ export { ActExecStatus, ActRunnerError } from './ActRunnerResult.js';
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Copyright (c) 2026 original authors
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import { WebhookEventName } from '@octokit/webhooks-types';
23
+ import type { ActResourceServerSpec, ActValueSource } from '../ActRunnerOptions.js';
24
+ import type { ActMatrixValues } from '../ActRunnerResult.js';
25
+ export declare const MANAGED_ACT_PARAMS: Set<string>;
26
+ export declare const INTERNAL_ACT_PARAMS: Set<string>;
27
+ export type ActCliParamsInput<EventType extends WebhookEventName | undefined = undefined> = {
28
+ workflowsPath: string;
29
+ eventPayloadFilePath: string | undefined;
30
+ eventType: EventType | undefined;
31
+ envSource: ActValueSource | undefined;
32
+ inputsSource: ActValueSource | undefined;
33
+ secretsSource: ActValueSource | undefined;
34
+ variablesSource: ActValueSource | undefined;
35
+ matrixValues: ActMatrixValues | undefined;
36
+ cacheServer: ActResourceServerSpec | undefined;
37
+ artifactServer: ActResourceServerSpec | undefined;
38
+ additionalArgs: string[];
39
+ };
40
+ export declare class ActCliParams<EventType extends WebhookEventName | undefined = undefined> {
41
+ private readonly workflowsPath;
42
+ private readonly eventPayloadFilePath;
43
+ private readonly eventType;
44
+ private readonly envSource;
45
+ private readonly inputsSource;
46
+ private readonly secretsSource;
47
+ private readonly variablesSource;
48
+ private readonly matrixValues;
49
+ private readonly cacheServer;
50
+ private readonly artifactServer;
51
+ private readonly additionalArgs;
52
+ constructor(params: ActCliParamsInput<EventType>);
53
+ asCliArgs(): string[];
54
+ private addEvent;
55
+ private addInputs;
56
+ private addResource;
57
+ }
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Copyright (c) 2026 original authors
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import { checkExists } from '../utils/checks.js';
23
+ import { firstDefined } from '../utils/objects.js';
24
+ export const MANAGED_ACT_PARAMS = new Set([
25
+ '--workflows',
26
+ '-W',
27
+ '--env-file',
28
+ '--env',
29
+ '--input-file',
30
+ '--input',
31
+ '--secret-file',
32
+ '--secret',
33
+ '-s',
34
+ '--var-file',
35
+ '--var',
36
+ '--matrix',
37
+ '--cache-server-path',
38
+ '--cache-server-addr',
39
+ '--cache-server-port',
40
+ '--artifact-server-path',
41
+ '--artifact-server-addr',
42
+ '--artifact-server-port',
43
+ '--detect-event',
44
+ '--eventpath',
45
+ '-e',
46
+ ]);
47
+ export const INTERNAL_ACT_PARAMS = new Set(['--rm', '--json']);
48
+ export class ActCliParams {
49
+ workflowsPath;
50
+ eventPayloadFilePath;
51
+ eventType;
52
+ envSource;
53
+ inputsSource;
54
+ secretsSource;
55
+ variablesSource;
56
+ matrixValues;
57
+ cacheServer;
58
+ artifactServer;
59
+ additionalArgs;
60
+ constructor(params) {
61
+ this.workflowsPath = params.workflowsPath;
62
+ this.eventType = params.eventType;
63
+ this.eventPayloadFilePath = params.eventPayloadFilePath;
64
+ this.envSource = params.envSource;
65
+ this.inputsSource = params.inputsSource;
66
+ this.secretsSource = params.secretsSource;
67
+ this.variablesSource = params.variablesSource;
68
+ this.matrixValues = params.matrixValues;
69
+ this.cacheServer = params.cacheServer;
70
+ this.artifactServer = params.artifactServer;
71
+ this.additionalArgs = params.additionalArgs;
72
+ }
73
+ asCliArgs() {
74
+ const args = ['--workflows', this.workflowsPath];
75
+ this.addEvent(args, this.eventType, this.eventPayloadFilePath);
76
+ this.addInputs(args, '--env-file', 'env values file', '--env', this.envSource);
77
+ this.addInputs(args, '--input-file', 'input values file', '--input', this.inputsSource);
78
+ this.addInputs(args, '--secret-file', 'secrets values file', '--secret', this.secretsSource);
79
+ this.addInputs(args, '--var-file', 'variables values file', '--var', this.variablesSource);
80
+ Object.entries(this.matrixValues ?? {}).forEach(([key, value]) => {
81
+ args.push('--matrix');
82
+ args.push(`${key}:${value}`);
83
+ });
84
+ this.addResource(args, this.cacheServer, '--cache-server-path', '--cache-server-addr', '--cache-server-port');
85
+ this.addResource(args, this.artifactServer, '--artifact-server-path', '--artifact-server-addr', '--artifact-server-port');
86
+ this.additionalArgs.forEach((arg) => args.push(arg));
87
+ return args;
88
+ }
89
+ addEvent(args, eventType, eventPayloadFilePath) {
90
+ args.push(firstDefined(() => eventType, () => '--detect-event'));
91
+ if (eventPayloadFilePath !== undefined) {
92
+ checkExists('event payload file', eventPayloadFilePath);
93
+ args.push('--eventpath', eventPayloadFilePath);
94
+ }
95
+ }
96
+ addInputs(args, fileArg, fileLabel, valuesArg, source) {
97
+ if (source?.file !== undefined) {
98
+ checkExists(fileLabel, source.file);
99
+ args.push(fileArg, source.file);
100
+ }
101
+ Object.entries(source?.values ?? {}).forEach(([key, value]) => {
102
+ args.push(valuesArg, `${key}=${value}`);
103
+ });
104
+ }
105
+ addResource(args, resource, storageParam, addressParam, portParam) {
106
+ if (resource !== undefined) {
107
+ args.push(storageParam);
108
+ args.push(resource.path);
109
+ if (resource.host !== undefined) {
110
+ args.push(addressParam);
111
+ args.push(resource.host);
112
+ }
113
+ if (resource.port !== undefined) {
114
+ args.push(portParam);
115
+ args.push(resource.port.toString());
116
+ }
117
+ }
118
+ }
119
+ }
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Copyright (c) 2026 original authors
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import type { ActJobExecResult } from '../ActRunnerResult.js';
23
+ import { ActOutputListener } from '../ActOutputListener.js';
24
+ export declare class ActExecListener {
25
+ private readonly execOutput;
26
+ private readonly jobsByName;
27
+ private readonly jobIterationTrackers;
28
+ private readonly outputListener;
29
+ constructor(outputListener?: ActOutputListener);
30
+ onRawOutput(output: string): void;
31
+ getOutput(): string;
32
+ getJobs(): Record<string, ActJobExecResult>;
33
+ private toActOutput;
34
+ private processOutput;
35
+ private getJobOutputProcessor;
36
+ private getJobIterationIdx;
37
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Copyright (c) 2026 original authors
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import { ActJobOutputProcessor } from './ActJobOutputProcessor.js';
23
+ import { jobDescriptor, formattedMessage, stepDescriptor, } from './ActJsonOutput.js';
24
+ import { JobIterationTracker } from './JobIterationTracker.js';
25
+ export class ActExecListener {
26
+ execOutput = [];
27
+ jobsByName = new Map();
28
+ jobIterationTrackers = new Map();
29
+ outputListener;
30
+ constructor(outputListener) {
31
+ this.outputListener = outputListener;
32
+ }
33
+ onRawOutput(output) {
34
+ const lines = output.toString().split('\n');
35
+ lines.forEach((line) => {
36
+ try {
37
+ const jsonOutput = JSON.parse(line);
38
+ const actOutput = this.toActOutput(jsonOutput);
39
+ this.outputListener?.onOutput(actOutput);
40
+ this.processOutput(jsonOutput);
41
+ }
42
+ catch (err) {
43
+ if (err instanceof SyntaxError) {
44
+ // persist unparseable output as-is
45
+ this.execOutput.push(line);
46
+ }
47
+ else {
48
+ throw err;
49
+ }
50
+ }
51
+ });
52
+ }
53
+ getOutput() {
54
+ return this.execOutput.join('\n');
55
+ }
56
+ getJobs() {
57
+ return Object.fromEntries(Array.from(this.jobsByName).map(([name, jobProcessor]) => [
58
+ name,
59
+ jobProcessor.buildResult(),
60
+ ]));
61
+ }
62
+ toActOutput(jsonOutput) {
63
+ return {
64
+ time: jsonOutput.time,
65
+ level: jsonOutput.level,
66
+ message: jsonOutput.msg,
67
+ job: jobDescriptor(jsonOutput),
68
+ step: stepDescriptor(jsonOutput),
69
+ };
70
+ }
71
+ processOutput(output) {
72
+ const msg = formattedMessage(output.msg, output.job);
73
+ this.execOutput.push(msg);
74
+ const job = jobDescriptor(output);
75
+ if (job !== undefined) {
76
+ const jobProcessor = this.getJobOutputProcessor(job, output.matrix);
77
+ jobProcessor.processOutput(output);
78
+ }
79
+ }
80
+ getJobOutputProcessor(job, matrix) {
81
+ const iterationNumber = this.getJobIterationIdx(job.id, matrix);
82
+ const jobName = iterationNumber === undefined ? job.id : `${job.id}_${iterationNumber}`;
83
+ if (!this.jobsByName.has(jobName)) {
84
+ this.jobsByName.set(jobName, new ActJobOutputProcessor(jobName, matrix));
85
+ }
86
+ return this.jobsByName.get(jobName);
87
+ }
88
+ getJobIterationIdx(jobName, matrix) {
89
+ if (Object.keys(matrix).length == 0) {
90
+ return undefined;
91
+ }
92
+ if (!this.jobIterationTrackers.has(jobName)) {
93
+ this.jobIterationTrackers.set(jobName, new JobIterationTracker());
94
+ }
95
+ const iterationTracker = this.jobIterationTrackers.get(jobName);
96
+ return iterationTracker.iterationIndex(matrix);
97
+ }
98
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Copyright (c) 2025 original authors
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ * this software and associated documentation files (the "Software"), to deal in
6
+ * the Software without restriction, including without limitation the rights to
7
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ * the Software, and to permit persons to whom the Software is furnished to do so,
9
+ * subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ */
21
+ import { ActJobExecResult } from '../ActJobExecResult.js';
22
+ export declare class ActJobExecResultBuilder {
23
+ private readonly name;
24
+ private hasExecutedSteps;
25
+ private status;
26
+ private readonly outputLines;
27
+ constructor(name: string);
28
+ output(line: string): ActJobExecResultBuilder;
29
+ stepCompleted(): ActJobExecResultBuilder;
30
+ completed(): ActJobExecResultBuilder;
31
+ failed(): ActJobExecResultBuilder;
32
+ build(): ActJobExecResult;
33
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Copyright (c) 2025 original authors
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ * this software and associated documentation files (the "Software"), to deal in
6
+ * the Software without restriction, including without limitation the rights to
7
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ * the Software, and to permit persons to whom the Software is furnished to do so,
9
+ * subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in all
12
+ * copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ */
21
+ import { ActJobExecResult } from '../ActJobExecResult.js';
22
+ import { ActExecStatus } from '../ActExecStatus.js';
23
+ export class ActJobExecResultBuilder {
24
+ name;
25
+ hasExecutedSteps = false;
26
+ status;
27
+ outputLines = [];
28
+ constructor(name) {
29
+ this.name = name;
30
+ }
31
+ output(line) {
32
+ this.outputLines.push(line);
33
+ return this;
34
+ }
35
+ stepCompleted() {
36
+ this.hasExecutedSteps = true;
37
+ return this;
38
+ }
39
+ completed() {
40
+ this.status = this.hasExecutedSteps
41
+ ? ActExecStatus.SUCCESS
42
+ : ActExecStatus.SKIPPED;
43
+ return this;
44
+ }
45
+ failed() {
46
+ this.status = ActExecStatus.FAILED;
47
+ return this;
48
+ }
49
+ build() {
50
+ return new ActJobExecResult(this.name, this.status, this.outputLines.join('\n'));
51
+ }
52
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Copyright (c) 2026 original authors
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import type { ActJobExecResult, ActMatrixValues } from '../ActRunnerResult.js';
23
+ import { JsonOutput } from './ActJsonOutput.js';
24
+ export declare class ActJobOutputProcessor {
25
+ private readonly name;
26
+ private readonly matrix;
27
+ private hasExecutedSteps;
28
+ private status;
29
+ private readonly outputLines;
30
+ private readonly steps;
31
+ private currentStepProcessor;
32
+ constructor(name: string, matrix: ActMatrixValues);
33
+ processOutput(output: JsonOutput): void;
34
+ private isNonLifecycleStep;
35
+ private isExecutedStep;
36
+ private getOrInitializeStepProcessor;
37
+ private isNewStep;
38
+ private completed;
39
+ buildResult(): ActJobExecResult;
40
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Copyright (c) 2026 original authors
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import { ActExecStatus } from '../ActRunnerResult.js';
23
+ import { formattedMessage, stepDescriptor, } from './ActJsonOutput.js';
24
+ import { ActStepExecResultBuilder as ActStepOutputProcessor } from './ActStepOutputProcessor.js';
25
+ const JOB_LIFECYCLE_STEPS = new Set(['Set up job', 'Complete job']);
26
+ export class ActJobOutputProcessor {
27
+ name;
28
+ matrix;
29
+ hasExecutedSteps = false;
30
+ status;
31
+ outputLines = [];
32
+ steps = [];
33
+ currentStepProcessor;
34
+ constructor(name, matrix) {
35
+ this.name = name;
36
+ this.matrix = matrix;
37
+ }
38
+ processOutput(output) {
39
+ const msg = formattedMessage(output.msg, output.job);
40
+ this.outputLines.push(msg);
41
+ const step = stepDescriptor(output);
42
+ if (step !== undefined) {
43
+ // mark job as run only if it executed meaningful steps
44
+ if (this.isExecutedStep(output)) {
45
+ this.hasExecutedSteps = true;
46
+ }
47
+ const stepProcessor = this.getOrInitializeStepProcessor(step);
48
+ stepProcessor.processOutput(output);
49
+ }
50
+ if (output.jobResult !== undefined) {
51
+ this.completed(output.jobResult);
52
+ }
53
+ }
54
+ isNonLifecycleStep(output) {
55
+ return output.step !== undefined && !JOB_LIFECYCLE_STEPS.has(output.step);
56
+ }
57
+ isExecutedStep(output) {
58
+ return (this.isNonLifecycleStep(output) &&
59
+ output.stepResult !== undefined &&
60
+ output.stepResult !== 'skipped');
61
+ }
62
+ getOrInitializeStepProcessor(descriptor) {
63
+ if (this.currentStepProcessor === undefined) {
64
+ // first step
65
+ this.currentStepProcessor = new ActStepOutputProcessor(descriptor);
66
+ }
67
+ else if (this.isNewStep(this.currentStepProcessor.descriptor, descriptor)) {
68
+ // new step started
69
+ this.steps.push(this.currentStepProcessor.buildResult());
70
+ this.currentStepProcessor = new ActStepOutputProcessor(descriptor);
71
+ }
72
+ return this.currentStepProcessor;
73
+ }
74
+ isNewStep(currentDescriptor, newDescriptor) {
75
+ return (currentDescriptor.id != newDescriptor.id ||
76
+ currentDescriptor.name != newDescriptor.name);
77
+ }
78
+ completed(result) {
79
+ if (this.currentStepProcessor !== undefined) {
80
+ this.steps.push(this.currentStepProcessor.buildResult());
81
+ this.currentStepProcessor = undefined;
82
+ }
83
+ if (result === 'failure') {
84
+ this.status = ActExecStatus.FAILED;
85
+ }
86
+ else {
87
+ this.status = this.hasExecutedSteps
88
+ ? ActExecStatus.SUCCESS
89
+ : ActExecStatus.SKIPPED;
90
+ }
91
+ }
92
+ buildResult() {
93
+ return {
94
+ name: this.name,
95
+ status: this.status,
96
+ output: this.outputLines.join('\n'),
97
+ matrix: this.matrix,
98
+ steps: this.steps,
99
+ };
100
+ }
101
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Copyright (c) 2026 original authors
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ import { ActOutputLevel, ActJobOrStepDescriptor } from '../ActOutputListener.js';
23
+ import { ActMatrixValues } from '../ActRunnerResult.js';
24
+ export type JobOrStepResult = 'success' | 'failure' | 'skipped';
25
+ export type JsonOutput = {
26
+ time: Date;
27
+ level: ActOutputLevel;
28
+ msg: string;
29
+ job?: string;
30
+ jobID?: string;
31
+ jobResult?: JobOrStepResult;
32
+ step?: string;
33
+ stepID?: string[];
34
+ stepResult?: JobOrStepResult;
35
+ matrix: ActMatrixValues;
36
+ };
37
+ export declare function formattedMessage(message: string, jobName: string | undefined): string;
38
+ export declare function jobDescriptor(output: JsonOutput): ActJobOrStepDescriptor | undefined;
39
+ export declare function stepDescriptor(output: JsonOutput): ActJobOrStepDescriptor | undefined;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Copyright (c) 2026 original authors
3
+ *
4
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ * of this software and associated documentation files (the "Software"), to deal
6
+ * in the Software without restriction, including without limitation the rights
7
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ * copies of the Software, and to permit persons to whom the Software is
9
+ * furnished to do so, subject to the following conditions:
10
+ *
11
+ * The above copyright notice and this permission notice shall be included in
12
+ * all copies or substantial portions of the Software.
13
+ *
14
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ * SOFTWARE.
21
+ */
22
+ export function formattedMessage(message, jobName) {
23
+ if (jobName !== undefined) {
24
+ return `[${jobName}] ${message}`.trim();
25
+ }
26
+ else {
27
+ return message.trim();
28
+ }
29
+ }
30
+ export function jobDescriptor(output) {
31
+ if (output.job !== undefined && output.jobID !== undefined) {
32
+ return {
33
+ id: output.jobID,
34
+ name: output.job,
35
+ };
36
+ }
37
+ return undefined;
38
+ }
39
+ export function stepDescriptor(output) {
40
+ // act reports step ids as a path (outermost to innermost, e.g. for
41
+ // composite action steps); the innermost entry identifies the step
42
+ // currently reporting output.
43
+ if (output.step !== undefined &&
44
+ output.stepID !== undefined &&
45
+ output.stepID.length > 0) {
46
+ const lastStepIdSegment = output.stepID[output.stepID.length - 1];
47
+ return {
48
+ id: lastStepIdSegment,
49
+ name: output.step,
50
+ };
51
+ }
52
+ return undefined;
53
+ }