@factorialco/gat 3.5.0 → 3.10.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/LICENSE +21 -0
- package/README.md +45 -5
- package/dist/job.d.ts +1 -0
- package/dist/workflow.d.ts +2 -0
- package/dist/workflow.js +8 -0
- package/dist/workflow.spec.js +33 -0
- package/package.json +2 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Factorial
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="gat.png" width="200" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
# gat  [](https://badge.fury.io/js/@factorialco%2Fgat)
|
|
2
6
|
|
|
3
7
|
The `gat` project is a tool to **write your GitHub Actions workflows using TypeScript**.
|
|
@@ -24,7 +28,7 @@ The `gat` CLI assumes that you have a `index.ts` file inside `.github/templates`
|
|
|
24
28
|
// .github/templates/index.ts
|
|
25
29
|
import { Workflow } from "@factorialco/gat";
|
|
26
30
|
|
|
27
|
-
new Workflow("My first workflow")
|
|
31
|
+
await new Workflow("My first workflow")
|
|
28
32
|
.on("push")
|
|
29
33
|
.addJob("test", {
|
|
30
34
|
steps: [
|
|
@@ -39,10 +43,10 @@ new Workflow("My first workflow")
|
|
|
39
43
|
},
|
|
40
44
|
],
|
|
41
45
|
})
|
|
42
|
-
.compile("my-first-workflow.yml");
|
|
46
|
+
.compile({ filePath: "my-first-workflow.yml" });
|
|
43
47
|
```
|
|
44
48
|
|
|
45
|
-
Notice that you need to call the `compile()` method at the end, passing the
|
|
49
|
+
Notice that you need to call the `compile()` method at the end, passing an options object with the `filePath` of the generated GitHub Actions workflow.
|
|
46
50
|
|
|
47
51
|
### Compiling your templates
|
|
48
52
|
|
|
@@ -75,11 +79,47 @@ Notice that the job includes a few assumptions like the `runs-on` and `timeout-m
|
|
|
75
79
|
|
|
76
80
|
### Create your own workflow class
|
|
77
81
|
|
|
78
|
-
|
|
82
|
+
You can create factory functions that return pre-configured `Workflow` instances with shared settings. This avoids duplication across your templates:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
// .github/templates/helpers.ts
|
|
86
|
+
import { Workflow } from "@factorialco/gat";
|
|
87
|
+
|
|
88
|
+
export function createWorkflow(name: string) {
|
|
89
|
+
return new Workflow(name)
|
|
90
|
+
.setEnv("NODE_ENV", "production")
|
|
91
|
+
.on("push", { branches: ["main"] });
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Then use it in your templates:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
// .github/templates/index.ts
|
|
99
|
+
import { createWorkflow } from "./helpers";
|
|
100
|
+
|
|
101
|
+
await createWorkflow("Test")
|
|
102
|
+
.addJob("test", {
|
|
103
|
+
steps: [{ run: "npm test" }],
|
|
104
|
+
})
|
|
105
|
+
.compile({ filePath: "test.yml" });
|
|
106
|
+
|
|
107
|
+
await createWorkflow("Lint")
|
|
108
|
+
.addJob("lint", {
|
|
109
|
+
steps: [{ run: "npm run lint" }],
|
|
110
|
+
})
|
|
111
|
+
.compile({ filePath: "lint.yml" });
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
This way all your workflows share the same environment variables, triggers, and any other defaults you configure in the factory function.
|
|
79
115
|
|
|
80
116
|
## Contributing
|
|
81
117
|
|
|
82
|
-
|
|
118
|
+
1. Fork the repository and clone it locally
|
|
119
|
+
2. Install dependencies: `npm install`
|
|
120
|
+
3. Run the tests: `npm test`
|
|
121
|
+
4. Make your changes and ensure tests pass
|
|
122
|
+
5. Submit a pull request
|
|
83
123
|
|
|
84
124
|
## License
|
|
85
125
|
|
package/dist/job.d.ts
CHANGED
package/dist/workflow.d.ts
CHANGED
|
@@ -23,11 +23,13 @@ export declare class Workflow<JobStep extends Step = Step, Runner extends Runner
|
|
|
23
23
|
defaultOptions: DefaultOptions | null;
|
|
24
24
|
env: EnvVar[];
|
|
25
25
|
concurrencyGroup?: ConcurrencyGroup | null;
|
|
26
|
+
runName?: string;
|
|
26
27
|
constructor(name: string);
|
|
27
28
|
on<T extends EventName>(name: T, options?: EventOptions<T>): this;
|
|
28
29
|
addDefaults(options: DefaultOptions): this;
|
|
29
30
|
addJob<T extends string>(name: StringWithNoSpaces<T>, options: StepsJobOptions<JobStep, Runner, JobName> | UsesJobOptions<JobName>): Workflow<JobStep, Runner, JobName | T>;
|
|
30
31
|
setEnv(name: string, value: string): this;
|
|
32
|
+
setRunName(runName: string): this;
|
|
31
33
|
setConcurrencyGroup(concurrencyGroup: ConcurrencyGroup | null): this;
|
|
32
34
|
defaultRunner(): string;
|
|
33
35
|
compile(compileOptions?: WorkflowCompileOptions): Promise<string | void>;
|
package/dist/workflow.js
CHANGED
|
@@ -41,6 +41,10 @@ class Workflow {
|
|
|
41
41
|
this.env = [...this.env, { name, value }];
|
|
42
42
|
return this;
|
|
43
43
|
}
|
|
44
|
+
setRunName(runName) {
|
|
45
|
+
this.runName = runName;
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
44
48
|
setConcurrencyGroup(concurrencyGroup) {
|
|
45
49
|
this.concurrencyGroup = concurrencyGroup;
|
|
46
50
|
return this;
|
|
@@ -51,6 +55,7 @@ class Workflow {
|
|
|
51
55
|
async compile(compileOptions = {}) {
|
|
52
56
|
const result = {
|
|
53
57
|
name: this.name,
|
|
58
|
+
"run-name": this.runName,
|
|
54
59
|
on: Object.fromEntries(this.events.map(({ name, options }) => [
|
|
55
60
|
name,
|
|
56
61
|
options ? options : null,
|
|
@@ -107,6 +112,9 @@ class Workflow {
|
|
|
107
112
|
strategy: matrix
|
|
108
113
|
? {
|
|
109
114
|
"fail-fast": false,
|
|
115
|
+
"max-parallel": typeof matrix !== "string" && matrix.maxParallel != null
|
|
116
|
+
? matrix.maxParallel
|
|
117
|
+
: undefined,
|
|
110
118
|
matrix: typeof matrix === "string"
|
|
111
119
|
? matrix
|
|
112
120
|
: {
|
package/dist/workflow.spec.js
CHANGED
|
@@ -126,6 +126,26 @@ const workflow_1 = require("./workflow");
|
|
|
126
126
|
});
|
|
127
127
|
(0, vitest_1.expect)(await workflow.compile()).toMatchSnapshot();
|
|
128
128
|
});
|
|
129
|
+
(0, vitest_1.it)("allows a job matrix with max-parallel", async () => {
|
|
130
|
+
const workflow = new workflow_1.Workflow("Matrix with max parallel");
|
|
131
|
+
workflow.on("push").addJob("job1", {
|
|
132
|
+
matrix: {
|
|
133
|
+
elements: [
|
|
134
|
+
{
|
|
135
|
+
id: "food",
|
|
136
|
+
options: ["🍕", "🍔", "🌮"],
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
maxParallel: 2,
|
|
140
|
+
},
|
|
141
|
+
steps: [
|
|
142
|
+
{
|
|
143
|
+
run: "echo ${{ matrix.food }}",
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
});
|
|
147
|
+
(0, vitest_1.expect)(await workflow.compile()).toMatchSnapshot();
|
|
148
|
+
});
|
|
129
149
|
(0, vitest_1.it)("allows uses steps", async () => {
|
|
130
150
|
const workflow = new workflow_1.Workflow("Uses steps");
|
|
131
151
|
workflow
|
|
@@ -291,6 +311,19 @@ exit 0`,
|
|
|
291
311
|
},
|
|
292
312
|
})).toMatchSnapshot();
|
|
293
313
|
});
|
|
314
|
+
(0, vitest_1.it)("supports a workflow-level run name", async () => {
|
|
315
|
+
const workflow = new workflow_1.Workflow("With run name")
|
|
316
|
+
.setRunName("Preview ${{ inputs.domain }} #${{ inputs.environmentIndex }}")
|
|
317
|
+
.on("workflow_dispatch", {
|
|
318
|
+
inputs: {
|
|
319
|
+
domain: { description: "A domain", required: true },
|
|
320
|
+
},
|
|
321
|
+
})
|
|
322
|
+
.addJob("job1", {
|
|
323
|
+
steps: [{ name: "Do something", run: "exit 0" }],
|
|
324
|
+
});
|
|
325
|
+
(0, vitest_1.expect)(await workflow.compile()).toMatchSnapshot();
|
|
326
|
+
});
|
|
294
327
|
(0, vitest_1.it)("allows setting environment on a job", async () => {
|
|
295
328
|
const workflow = new workflow_1.Workflow("Job Environment");
|
|
296
329
|
workflow.on("push").addJob("job1", {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@factorialco/gat",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.10.1",
|
|
4
4
|
"description": "Write your GitHub Actions workflows using TypeScript",
|
|
5
5
|
"bin": {
|
|
6
6
|
"gat": "dist/cli.js"
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"format:check": "prettier --check ."
|
|
23
23
|
},
|
|
24
24
|
"author": "David Morcillo <david.morcillo@factorial.co>",
|
|
25
|
-
"license": "
|
|
25
|
+
"license": "MIT",
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@swc/core": "^1.3.14",
|
|
28
28
|
"@types/js-yaml": "^4.0.5",
|