@factorialco/gat 0.0.18 → 0.0.20
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 +90 -1
- package/dist/workflow.d.ts +3 -1
- package/dist/workflow.js +10 -10
- package/dist/workflow.spec.js +19 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,3 +1,92 @@
|
|
|
1
|
-
#
|
|
1
|
+
# gat  [](https://badge.fury.io/js/@factorialco%2Fgat)
|
|
2
|
+
|
|
3
|
+
The `gat` project is a tool to **write your GitHub Actions workflows using TypeScript**.
|
|
4
|
+
|
|
5
|
+
Maintaining YAML files is hard and if your project is big enough you will find yourself duplicating a lot of code between your workflows. With `gat` you can create reusable jobs and steps just using TypeScript objects and importing them in your workflow templates.
|
|
6
|
+
|
|
7
|
+
_Why `gat`?_ The name is an acronym of "GitHub Actions Template Generator" without the last part because `gat` means "cat" in Catalan.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
Install the main package and its dependencies using the following command:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm i -D @factorialco/gat typescript ts-node commander
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Writing a template
|
|
20
|
+
|
|
21
|
+
The `gat` CLI assumes that your templates are inside `.github/templates`. Let's create our first template:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// .github/templates/my-first-workflow.ts
|
|
25
|
+
import { Workflow } from "@factorialco/gat";
|
|
26
|
+
|
|
27
|
+
new Workflow("My first workflow")
|
|
28
|
+
.on("push")
|
|
29
|
+
.addJob("test", {
|
|
30
|
+
steps: [
|
|
31
|
+
{
|
|
32
|
+
uses: "actions/checkout@v3",
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
uses: "actions/setup-node@v3",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
run: "npm test",
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
})
|
|
42
|
+
.compile();
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Notice that you need to call the `compile()` method at the end.
|
|
46
|
+
|
|
47
|
+
### Compiling your templates
|
|
48
|
+
|
|
49
|
+
You can build your templates running this command in your root folder:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npx gat build
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Alternatively you can also compile a single template:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npx gat build .github/templates/some-workflow.ts
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Following the previous example, you should see now a file `.github/workflows/my-first-workflow.yml` like this:
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
# Workflow automatically generated by gat
|
|
65
|
+
# DO NOT CHANGE THIS FILE MANUALLY
|
|
66
|
+
|
|
67
|
+
name: My first workflow
|
|
68
|
+
on:
|
|
69
|
+
push: null
|
|
70
|
+
jobs:
|
|
71
|
+
test:
|
|
72
|
+
runs-on: ubuntu-22.04
|
|
73
|
+
timeout-minutes: 15
|
|
74
|
+
steps:
|
|
75
|
+
- uses: actions/checkout@v3
|
|
76
|
+
- uses: actions/setup-node@v3
|
|
77
|
+
- run: npm test
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Notice that the job includes a few assumptions like the `runs-on` and `timeout-minutes` fields. You can change those when adding a new job.
|
|
81
|
+
|
|
82
|
+
### Create your own workflow class
|
|
83
|
+
|
|
84
|
+
TODO
|
|
85
|
+
|
|
86
|
+
## Contributing
|
|
87
|
+
|
|
88
|
+
TODO
|
|
89
|
+
|
|
90
|
+
## License
|
|
2
91
|
|
|
3
92
|
TODO
|
package/dist/workflow.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Job, JobOptions } from "./job";
|
|
1
|
+
import { ConcurrencyGroup, Job, JobOptions } from "./job";
|
|
2
2
|
import type { Event, EventName, EventOptions } from "./event";
|
|
3
3
|
import { BaseStep, Step } from "./step";
|
|
4
4
|
declare const DEFAULT_RUNNERS: string[];
|
|
@@ -15,11 +15,13 @@ export declare class Workflow<JobStep extends BaseStep = Step, Runner = typeof D
|
|
|
15
15
|
jobs: Array<Job<JobStep, Runner, JobName>>;
|
|
16
16
|
defaultOptions: DefaultOptions | null;
|
|
17
17
|
env: EnvVar[];
|
|
18
|
+
concurrencyGroup?: ConcurrencyGroup;
|
|
18
19
|
constructor(name: string);
|
|
19
20
|
on<T extends EventName>(name: T, options?: EventOptions<T>): this;
|
|
20
21
|
addDefaults(options: DefaultOptions): this;
|
|
21
22
|
addJob<T extends string>(name: T, options: JobOptions<JobStep, Runner, JobName>): Workflow<JobStep, Runner, JobName | T>;
|
|
22
23
|
setEnv(name: string, value: string): this;
|
|
24
|
+
setConcurrencyGroup(concurrencyGroup: ConcurrencyGroup): this;
|
|
23
25
|
defaultRunner(): string;
|
|
24
26
|
private assignRunner;
|
|
25
27
|
compile(): string;
|
package/dist/workflow.js
CHANGED
|
@@ -6,7 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.Workflow = void 0;
|
|
7
7
|
const js_yaml_1 = require("js-yaml");
|
|
8
8
|
const kebabCase_1 = __importDefault(require("lodash/kebabCase"));
|
|
9
|
-
const lodash_1 = require("lodash");
|
|
10
9
|
const DEFAULT_RUNNERS = ["ubuntu-22.04"];
|
|
11
10
|
class Workflow {
|
|
12
11
|
constructor(name) {
|
|
@@ -32,6 +31,10 @@ class Workflow {
|
|
|
32
31
|
this.env = [...this.env, { name, value }];
|
|
33
32
|
return this;
|
|
34
33
|
}
|
|
34
|
+
setConcurrencyGroup(concurrencyGroup) {
|
|
35
|
+
this.concurrencyGroup = concurrencyGroup;
|
|
36
|
+
return this;
|
|
37
|
+
}
|
|
35
38
|
defaultRunner() {
|
|
36
39
|
return "ubuntu-22.04";
|
|
37
40
|
}
|
|
@@ -44,6 +47,12 @@ class Workflow {
|
|
|
44
47
|
const result = {
|
|
45
48
|
name: this.name,
|
|
46
49
|
on: Object.fromEntries(this.events.map(({ name, options }) => [name, options ? options : null])),
|
|
50
|
+
concurrency: this.concurrencyGroup
|
|
51
|
+
? {
|
|
52
|
+
group: this.concurrencyGroup.groupSuffix,
|
|
53
|
+
"cancel-in-progress": this.concurrencyGroup.cancelPrevious,
|
|
54
|
+
}
|
|
55
|
+
: undefined,
|
|
47
56
|
defaults: this.defaultOptions
|
|
48
57
|
? {
|
|
49
58
|
run: {
|
|
@@ -96,15 +105,6 @@ class Workflow {
|
|
|
96
105
|
noRefs: true,
|
|
97
106
|
lineWidth: 200,
|
|
98
107
|
noCompatMode: true,
|
|
99
|
-
replacer: (_, value) => {
|
|
100
|
-
if (typeof value === "string") {
|
|
101
|
-
if (value.startsWith("\n")) {
|
|
102
|
-
return (0, lodash_1.compact)(value.split("\n").map((str) => (0, lodash_1.trim)(str))).join("\n");
|
|
103
|
-
}
|
|
104
|
-
return value;
|
|
105
|
-
}
|
|
106
|
-
return value;
|
|
107
|
-
},
|
|
108
108
|
})}`;
|
|
109
109
|
console.log(compiled);
|
|
110
110
|
return compiled;
|
package/dist/workflow.spec.js
CHANGED
|
@@ -219,10 +219,25 @@ const workflow_1 = require("./workflow");
|
|
|
219
219
|
steps: [
|
|
220
220
|
{
|
|
221
221
|
name: "Do something",
|
|
222
|
-
run: `
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
222
|
+
run: `echo foo
|
|
223
|
+
exit 0`,
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
});
|
|
227
|
+
(0, vitest_1.expect)(workflow.compile()).toMatchSnapshot();
|
|
228
|
+
});
|
|
229
|
+
(0, vitest_1.it)("allows concurrency groups at workflow level", () => {
|
|
230
|
+
const workflow = new workflow_1.Workflow("Concurrency at workflow level")
|
|
231
|
+
.on("push")
|
|
232
|
+
.setConcurrencyGroup({
|
|
233
|
+
groupSuffix: "${{ github.workflow }}-${{ github.ref }}",
|
|
234
|
+
cancelPrevious: true,
|
|
235
|
+
})
|
|
236
|
+
.addJob("job1", {
|
|
237
|
+
steps: [
|
|
238
|
+
{
|
|
239
|
+
name: "Do something",
|
|
240
|
+
run: "exit 0",
|
|
226
241
|
},
|
|
227
242
|
],
|
|
228
243
|
});
|