@factorialco/gat 0.0.1
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/README.md +3 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +31 -0
- package/dist/event.d.ts +15 -0
- package/dist/event.js +2 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +5 -0
- package/dist/job.d.ts +108 -0
- package/dist/job.js +2 -0
- package/dist/workflow.d.ts +24 -0
- package/dist/workflow.js +111 -0
- package/dist/workflow.spec.d.ts +1 -0
- package/dist/workflow.spec.js +155 -0
- package/package.json +40 -0
package/README.md
ADDED
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
|
+
};
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const child_process_1 = require("child_process");
|
|
10
|
+
const commander_1 = require("commander");
|
|
11
|
+
const util_1 = require("util");
|
|
12
|
+
const execPromise = (0, util_1.promisify)(child_process_1.exec);
|
|
13
|
+
const cli = new commander_1.Command();
|
|
14
|
+
cli.version("0.0.1").description("TODO");
|
|
15
|
+
cli
|
|
16
|
+
.command("build")
|
|
17
|
+
.description("TODO")
|
|
18
|
+
.action(async () => {
|
|
19
|
+
const folder = path_1.default.join(process.cwd(), ".github", "templates");
|
|
20
|
+
if (!fs_1.default.existsSync(path_1.default.join(folder, "..", "workflows"))) {
|
|
21
|
+
fs_1.default.mkdirSync(path_1.default.join(folder, "..", "workflows"));
|
|
22
|
+
}
|
|
23
|
+
for await (const templateFile of fs_1.default.readdirSync(folder)) {
|
|
24
|
+
if (!templateFile.match(/^shared$/)) {
|
|
25
|
+
const { stdout } = await execPromise(`npx ts-node ${path_1.default.join(folder, templateFile)}`);
|
|
26
|
+
fs_1.default.writeFileSync(path_1.default.join(folder, "..", "workflows", templateFile.replace(".ts", ".yml")), stdout);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
process.exit(0);
|
|
30
|
+
});
|
|
31
|
+
cli.parse(process.argv);
|
package/dist/event.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare type EventName = "push" | "pull_request";
|
|
2
|
+
export declare type EventOptions<T extends EventName> = T extends "push" ? PushEventOptions : T extends "pull_request" ? PullRequestEventOptions : never;
|
|
3
|
+
interface PushEventOptions {
|
|
4
|
+
branches?: string[];
|
|
5
|
+
paths?: string[];
|
|
6
|
+
}
|
|
7
|
+
interface PullRequestEventOptions {
|
|
8
|
+
types?: Array<"opened" | "reopened" | "synchronize">;
|
|
9
|
+
paths?: string[];
|
|
10
|
+
}
|
|
11
|
+
export interface Event {
|
|
12
|
+
name: EventName;
|
|
13
|
+
options?: EventOptions<EventName>;
|
|
14
|
+
}
|
|
15
|
+
export {};
|
package/dist/event.js
ADDED
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
package/dist/job.d.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
declare type Step = RunStep | {
|
|
2
|
+
[Name in ActionName]: UseStep<Name>;
|
|
3
|
+
}[ActionName];
|
|
4
|
+
interface BaseStep {
|
|
5
|
+
id?: string;
|
|
6
|
+
name?: string;
|
|
7
|
+
env?: Record<string, string>;
|
|
8
|
+
ifExpression?: string;
|
|
9
|
+
workingDirectory?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface RunStep extends BaseStep {
|
|
12
|
+
run: string;
|
|
13
|
+
}
|
|
14
|
+
declare type ActionName = "actions/checkout@v3" | "actions/setup-node@v3" | "actions/upload-artifact@v3" | "actions/download-artifact@v3" | "ruby/setup-ruby@v1" | "dorny/paths-filter@v2" | "tespkg/actions-cache@v1" | "prewk/s3-cp-action@v2" | "chromaui/action@v1" | "rtCamp/action-slack-notify@v2" | "factorialco/delta-action@v3.0.0" | "factorialco/test-summary-action@v1.2.0";
|
|
15
|
+
export interface UseStep<T extends ActionName> extends BaseStep {
|
|
16
|
+
uses: T;
|
|
17
|
+
with?: StepOptions<T>;
|
|
18
|
+
}
|
|
19
|
+
declare type StepOptions<T extends ActionName> = T extends "actions/checkout@v3" ? {
|
|
20
|
+
ref?: string;
|
|
21
|
+
"fetch-depth"?: number;
|
|
22
|
+
} : T extends "actions/setup-node@v3" ? {
|
|
23
|
+
"node-version": string;
|
|
24
|
+
} : T extends "actions/upload-artifact@v3" ? {
|
|
25
|
+
name: string;
|
|
26
|
+
path: string;
|
|
27
|
+
} : T extends "ruby/setup-ruby@v1" ? {
|
|
28
|
+
"ruby-version": string;
|
|
29
|
+
"cache-version"?: number;
|
|
30
|
+
"bundler-cache"?: boolean;
|
|
31
|
+
"working-directory"?: string;
|
|
32
|
+
} : T extends "dorny/paths-filter@v2" ? {
|
|
33
|
+
filters: string;
|
|
34
|
+
} : T extends "tespkg/actions-cache@v1" ? {
|
|
35
|
+
endpoint: string;
|
|
36
|
+
region: string;
|
|
37
|
+
bucket: string;
|
|
38
|
+
accessKey: string;
|
|
39
|
+
secretKey: string;
|
|
40
|
+
insecure: string;
|
|
41
|
+
"use-fallback": boolean;
|
|
42
|
+
path: string;
|
|
43
|
+
key: string;
|
|
44
|
+
"restore-keys": string;
|
|
45
|
+
} : T extends "prewk/s3-cp-action@v2" ? {
|
|
46
|
+
source: string;
|
|
47
|
+
dest: string;
|
|
48
|
+
aws_s3_endpoint: string;
|
|
49
|
+
aws_region: string;
|
|
50
|
+
aws_access_key_id: string;
|
|
51
|
+
aws_secret_access_key: string;
|
|
52
|
+
} : T extends "chromaui/action@v1" ? {
|
|
53
|
+
workingDir: string;
|
|
54
|
+
token: string;
|
|
55
|
+
projectToken: string;
|
|
56
|
+
exitZeroOnChanges?: boolean;
|
|
57
|
+
autoAcceptChanges?: boolean;
|
|
58
|
+
} : T extends "factorialco/delta-action@v3.0.0" ? {
|
|
59
|
+
engine: "eslint" | "semgrep" | "rubocop";
|
|
60
|
+
main: string;
|
|
61
|
+
branch: string;
|
|
62
|
+
head_ref: string;
|
|
63
|
+
forkpoint: string;
|
|
64
|
+
monorepo_prefix: "frontend" | "backend";
|
|
65
|
+
} : T extends "factorialco/test-summary-action@v1.2.0" ? {
|
|
66
|
+
engine: "jest" | "rspec";
|
|
67
|
+
reportFile: string;
|
|
68
|
+
sha: string;
|
|
69
|
+
} : never;
|
|
70
|
+
declare type Runner = "standard" | "beefy" | "large" | "release" | "standard-aws" | "beefy-aws" | "large-aws" | "release-aws";
|
|
71
|
+
export interface ConcurrencyGroup {
|
|
72
|
+
groupSuffix: string;
|
|
73
|
+
cancelPrevious: boolean;
|
|
74
|
+
}
|
|
75
|
+
export interface Matrix {
|
|
76
|
+
elements: Array<{
|
|
77
|
+
id: string;
|
|
78
|
+
options: any[];
|
|
79
|
+
}>;
|
|
80
|
+
extra?: Array<Record<string, any>>;
|
|
81
|
+
}
|
|
82
|
+
export interface Service {
|
|
83
|
+
image: string;
|
|
84
|
+
credentials?: {
|
|
85
|
+
username: string;
|
|
86
|
+
password: string;
|
|
87
|
+
};
|
|
88
|
+
env?: Record<string, string>;
|
|
89
|
+
ports: string[];
|
|
90
|
+
options?: string;
|
|
91
|
+
}
|
|
92
|
+
export interface JobOptions<JobNames = never> {
|
|
93
|
+
ifExpression?: string;
|
|
94
|
+
runsOn?: Runner;
|
|
95
|
+
timeout?: number;
|
|
96
|
+
dependsOn?: Array<JobNames>;
|
|
97
|
+
services?: Record<string, Service>;
|
|
98
|
+
env?: Record<string, string>;
|
|
99
|
+
concurrency?: ConcurrencyGroup;
|
|
100
|
+
matrix?: Matrix;
|
|
101
|
+
steps: Step[];
|
|
102
|
+
outputs?: Record<string, string>;
|
|
103
|
+
}
|
|
104
|
+
export interface Job<JobNames> {
|
|
105
|
+
name: string;
|
|
106
|
+
options: JobOptions<JobNames>;
|
|
107
|
+
}
|
|
108
|
+
export {};
|
package/dist/job.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Job, JobOptions } from "./job";
|
|
2
|
+
import type { Event, EventName, EventOptions } from "./event";
|
|
3
|
+
interface DefaultOptions {
|
|
4
|
+
workingDirectory: string;
|
|
5
|
+
}
|
|
6
|
+
interface EnvVar {
|
|
7
|
+
name: string;
|
|
8
|
+
value: string;
|
|
9
|
+
}
|
|
10
|
+
export declare class Workflow<JobNames = never> {
|
|
11
|
+
name: string;
|
|
12
|
+
events: Event[];
|
|
13
|
+
jobs: Array<Job<JobNames>>;
|
|
14
|
+
defaultOptions: DefaultOptions | null;
|
|
15
|
+
env: EnvVar[];
|
|
16
|
+
constructor(name: string);
|
|
17
|
+
on<T extends EventName>(name: T, options?: EventOptions<T>): this;
|
|
18
|
+
addDefaults(options: DefaultOptions): this;
|
|
19
|
+
addJob<JobName extends string>(name: JobName, options: JobOptions<JobNames>): Workflow<JobNames | JobName>;
|
|
20
|
+
addMergeGatekeeperJob(dependsOn: Array<JobNames>): this;
|
|
21
|
+
setEnv(name: string, value: any): this;
|
|
22
|
+
compile(): string;
|
|
23
|
+
}
|
|
24
|
+
export {};
|
package/dist/workflow.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.Workflow = void 0;
|
|
7
|
+
const yaml_1 = require("yaml");
|
|
8
|
+
const kebabCase_1 = __importDefault(require("lodash/kebabCase"));
|
|
9
|
+
class Workflow {
|
|
10
|
+
constructor(name) {
|
|
11
|
+
this.name = name;
|
|
12
|
+
this.events = [];
|
|
13
|
+
this.jobs = [];
|
|
14
|
+
this.defaultOptions = null;
|
|
15
|
+
this.env = [];
|
|
16
|
+
}
|
|
17
|
+
on(name, options) {
|
|
18
|
+
this.events = [...this.events, { name, options }];
|
|
19
|
+
return this;
|
|
20
|
+
}
|
|
21
|
+
addDefaults(options) {
|
|
22
|
+
this.defaultOptions = options;
|
|
23
|
+
return this;
|
|
24
|
+
}
|
|
25
|
+
addJob(name, options) {
|
|
26
|
+
this.jobs = [...this.jobs, { name, options }];
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
addMergeGatekeeperJob(dependsOn) {
|
|
30
|
+
this.jobs = [
|
|
31
|
+
...this.jobs,
|
|
32
|
+
{
|
|
33
|
+
name: "merge_gatekeeper",
|
|
34
|
+
options: {
|
|
35
|
+
ifExpression: "${{ always() }}",
|
|
36
|
+
dependsOn,
|
|
37
|
+
steps: [
|
|
38
|
+
{
|
|
39
|
+
workingDirectory: "${{ github.workspace }}",
|
|
40
|
+
run: dependsOn
|
|
41
|
+
.map((jobName) => `\${{ needs.${jobName}.result == 'success' || needs.${jobName}.result == 'skipped' }}`)
|
|
42
|
+
.join(" && "),
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
setEnv(name, value) {
|
|
51
|
+
this.env = [...this.env, { name, value }];
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
compile() {
|
|
55
|
+
const result = {
|
|
56
|
+
name: this.name,
|
|
57
|
+
on: Object.fromEntries(this.events.map(({ name, options }) => [name, options ? options : null])),
|
|
58
|
+
defaults: this.defaultOptions
|
|
59
|
+
? {
|
|
60
|
+
run: {
|
|
61
|
+
"working-directory": this.defaultOptions.workingDirectory,
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
: undefined,
|
|
65
|
+
env: this.env.length > 0
|
|
66
|
+
? Object.fromEntries(this.env.map(({ name, value }) => [name, value]))
|
|
67
|
+
: undefined,
|
|
68
|
+
jobs: Object.fromEntries(this.jobs.map(({ name, options: { ifExpression, runsOn, matrix, steps, dependsOn, services, timeout, concurrency, outputs, }, }) => [
|
|
69
|
+
name,
|
|
70
|
+
{
|
|
71
|
+
if: ifExpression,
|
|
72
|
+
"runs-on": ["self-hosted", `${runsOn ?? "standard-aws"}-runner`],
|
|
73
|
+
"timeout-minutes": timeout ?? 15,
|
|
74
|
+
needs: dependsOn,
|
|
75
|
+
services,
|
|
76
|
+
concurrency: concurrency
|
|
77
|
+
? {
|
|
78
|
+
group: `${(0, kebabCase_1.default)(this.name)}-${name}-${concurrency.groupSuffix}`,
|
|
79
|
+
"cancel-in-progress": concurrency.cancelPrevious,
|
|
80
|
+
}
|
|
81
|
+
: undefined,
|
|
82
|
+
strategy: matrix
|
|
83
|
+
? {
|
|
84
|
+
"fail-fast": false,
|
|
85
|
+
matrix: {
|
|
86
|
+
...Object.fromEntries(matrix.elements.map(({ id, options }) => [id, options])),
|
|
87
|
+
include: matrix.extra,
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
: undefined,
|
|
91
|
+
steps: steps.map(({ id, name, ifExpression, workingDirectory, ...options }) => ({
|
|
92
|
+
id,
|
|
93
|
+
name,
|
|
94
|
+
if: ifExpression,
|
|
95
|
+
"working-directory": workingDirectory,
|
|
96
|
+
...options,
|
|
97
|
+
})),
|
|
98
|
+
outputs,
|
|
99
|
+
},
|
|
100
|
+
])),
|
|
101
|
+
};
|
|
102
|
+
const compiled = `# Template automatically generated by gat\n# DO NOT CHANGE THIS FILE MANUALLY\n\n${(0, yaml_1.stringify)(result, {
|
|
103
|
+
singleQuote: true,
|
|
104
|
+
aliasDuplicateObjects: false,
|
|
105
|
+
lineWidth: 150,
|
|
106
|
+
})}`;
|
|
107
|
+
console.log(compiled);
|
|
108
|
+
return compiled;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.Workflow = Workflow;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const workflow_1 = require("./workflow");
|
|
5
|
+
(0, vitest_1.describe)("Workflow", () => {
|
|
6
|
+
(0, vitest_1.it)("generates a simple workflow", () => {
|
|
7
|
+
const workflow = new workflow_1.Workflow("Simple");
|
|
8
|
+
workflow
|
|
9
|
+
.on("pull_request", { types: ["opened"] })
|
|
10
|
+
.addJob("job1", {
|
|
11
|
+
runsOn: "standard",
|
|
12
|
+
steps: [{ name: "Do something", run: "exit 0" }],
|
|
13
|
+
})
|
|
14
|
+
.addJob("job2", {
|
|
15
|
+
runsOn: "standard",
|
|
16
|
+
steps: [{ name: "Do something else", run: "exit 0" }],
|
|
17
|
+
dependsOn: ["job1"],
|
|
18
|
+
});
|
|
19
|
+
(0, vitest_1.expect)(workflow.compile()).toMatchSnapshot();
|
|
20
|
+
});
|
|
21
|
+
(0, vitest_1.it)("allows multiple events", () => {
|
|
22
|
+
const workflow = new workflow_1.Workflow("Multiple events");
|
|
23
|
+
workflow
|
|
24
|
+
.on("push", { branches: ["main"] })
|
|
25
|
+
.on("pull_request", { types: ["opened"] })
|
|
26
|
+
.addJob("job1", {
|
|
27
|
+
runsOn: "standard",
|
|
28
|
+
steps: [{ name: "Do something", run: "exit 0" }],
|
|
29
|
+
});
|
|
30
|
+
(0, vitest_1.expect)(workflow.compile()).toMatchSnapshot();
|
|
31
|
+
});
|
|
32
|
+
(0, vitest_1.it)("allows declaring default options", () => {
|
|
33
|
+
const workflow = new workflow_1.Workflow("Default options");
|
|
34
|
+
workflow
|
|
35
|
+
.on("push", { branches: ["main"] })
|
|
36
|
+
.addDefaults({
|
|
37
|
+
workingDirectory: "frontend",
|
|
38
|
+
})
|
|
39
|
+
.addJob("job1", {
|
|
40
|
+
runsOn: "standard",
|
|
41
|
+
steps: [{ name: "Do something", run: "exit 0" }],
|
|
42
|
+
});
|
|
43
|
+
(0, vitest_1.expect)(workflow.compile()).toMatchSnapshot();
|
|
44
|
+
});
|
|
45
|
+
(0, vitest_1.it)("allows declaring environment variables", () => {
|
|
46
|
+
const workflow = new workflow_1.Workflow("With Environment variables");
|
|
47
|
+
workflow
|
|
48
|
+
.on("push")
|
|
49
|
+
.setEnv("NODE_VERSION", "16")
|
|
50
|
+
.setEnv("ENABLED", true)
|
|
51
|
+
.addJob("job1", {
|
|
52
|
+
runsOn: "standard",
|
|
53
|
+
steps: [
|
|
54
|
+
{
|
|
55
|
+
name: "Do something",
|
|
56
|
+
run: "echo ${{ env.NODE_VERSION }} && echo ${{ env.ENABLED }}",
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
});
|
|
60
|
+
(0, vitest_1.expect)(workflow.compile()).toMatchSnapshot();
|
|
61
|
+
});
|
|
62
|
+
(0, vitest_1.it)("allows uses steps", () => {
|
|
63
|
+
const workflow = new workflow_1.Workflow("Uses steps");
|
|
64
|
+
workflow
|
|
65
|
+
.on("push")
|
|
66
|
+
.setEnv("NODE_VERSION", "16")
|
|
67
|
+
.setEnv("ENABLED", true)
|
|
68
|
+
.addJob("job1", {
|
|
69
|
+
runsOn: "standard",
|
|
70
|
+
steps: [
|
|
71
|
+
{
|
|
72
|
+
uses: "actions/checkout@v3",
|
|
73
|
+
with: {
|
|
74
|
+
ref: "main",
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
});
|
|
79
|
+
(0, vitest_1.expect)(workflow.compile()).toMatchSnapshot();
|
|
80
|
+
});
|
|
81
|
+
(0, vitest_1.it)("allows using a concurrency group", () => {
|
|
82
|
+
const workflow = new workflow_1.Workflow("Concurrency group");
|
|
83
|
+
workflow.on("push").addJob("job1", {
|
|
84
|
+
runsOn: "standard",
|
|
85
|
+
concurrency: {
|
|
86
|
+
groupSuffix: "foo",
|
|
87
|
+
cancelPrevious: true,
|
|
88
|
+
},
|
|
89
|
+
steps: [
|
|
90
|
+
{
|
|
91
|
+
run: "echo 0",
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
});
|
|
95
|
+
(0, vitest_1.expect)(workflow.compile()).toMatchSnapshot();
|
|
96
|
+
});
|
|
97
|
+
(0, vitest_1.it)("allows using outputs", () => {
|
|
98
|
+
const workflow = new workflow_1.Workflow("Using outputs");
|
|
99
|
+
workflow.on("push").addJob("job1", {
|
|
100
|
+
runsOn: "standard",
|
|
101
|
+
steps: [
|
|
102
|
+
{
|
|
103
|
+
id: "random-number",
|
|
104
|
+
run: 'echo "::set-output name=random-number::$RANDOM"',
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
outputs: {
|
|
108
|
+
"random-number": "${{ steps.random-number.outputs.random-number }}",
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
(0, vitest_1.expect)(workflow.compile()).toMatchSnapshot();
|
|
112
|
+
});
|
|
113
|
+
(0, vitest_1.it)("allows conditional jobs", () => {
|
|
114
|
+
const workflow = new workflow_1.Workflow("Conditional job");
|
|
115
|
+
workflow.on("push").addJob("job1", {
|
|
116
|
+
ifExpression: "${{ github.ref != 'refs/heads/main' }}",
|
|
117
|
+
steps: [
|
|
118
|
+
{
|
|
119
|
+
run: "exit 0",
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
});
|
|
123
|
+
(0, vitest_1.expect)(workflow.compile()).toMatchSnapshot();
|
|
124
|
+
});
|
|
125
|
+
(0, vitest_1.it)("allows a job matrix", () => {
|
|
126
|
+
const workflow = new workflow_1.Workflow("Conditional job");
|
|
127
|
+
workflow.on("push").addJob("job1", {
|
|
128
|
+
matrix: {
|
|
129
|
+
elements: [
|
|
130
|
+
{
|
|
131
|
+
id: "food",
|
|
132
|
+
options: ["🍕", "🍔"],
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: "topping",
|
|
136
|
+
options: ["🍍"],
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
extra: [
|
|
140
|
+
{
|
|
141
|
+
food: "🍕",
|
|
142
|
+
topping: "🍍",
|
|
143
|
+
tasty: true,
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
steps: [
|
|
148
|
+
{
|
|
149
|
+
run: "echo ${{ matrix.food }} with ${{ matrix.topping }}",
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
});
|
|
153
|
+
(0, vitest_1.expect)(workflow.compile()).toMatchSnapshot();
|
|
154
|
+
});
|
|
155
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@factorialco/gat",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "TODO",
|
|
5
|
+
"bin": {
|
|
6
|
+
"gat": "dist/cli.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist/**/*"
|
|
10
|
+
],
|
|
11
|
+
"types": "dist/index.d.ts",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"prepare": "npm run build",
|
|
15
|
+
"prepublishOnly": "vitest run",
|
|
16
|
+
"test": "vitest",
|
|
17
|
+
"coverage": "vitest run --coverage"
|
|
18
|
+
},
|
|
19
|
+
"author": "David Morcillo <david.morcillo@factorial.co>",
|
|
20
|
+
"license": "ISC",
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/lodash": "^4.14.184",
|
|
23
|
+
"commander": "^9.4.0",
|
|
24
|
+
"typescript": "^4.7.4",
|
|
25
|
+
"vitest": "^0.18.1"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"lodash": "^4.17.21",
|
|
29
|
+
"yaml": "^2.1.1"
|
|
30
|
+
},
|
|
31
|
+
"main": "index.js",
|
|
32
|
+
"repository": {
|
|
33
|
+
"type": "git",
|
|
34
|
+
"url": "git+https://github.com/factorialco/gat.git"
|
|
35
|
+
},
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/factorialco/gat/issues"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/factorialco/gat#readme"
|
|
40
|
+
}
|