@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 CHANGED
@@ -1,3 +1,92 @@
1
- # GitHub Actions Template Generator (aka GAT)
1
+ # gat ![Build](https://github.com/factorialco/gat/actions/workflows/build.yml/badge.svg?branch=main) [![npm version](https://badge.fury.io/js/@factorialco%2Fgat.svg)](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
@@ -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;
@@ -219,10 +219,25 @@ const workflow_1 = require("./workflow");
219
219
  steps: [
220
220
  {
221
221
  name: "Do something",
222
- run: `
223
- echo foo
224
- exit 0
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
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@factorialco/gat",
3
- "version": "0.0.18",
3
+ "version": "0.0.20",
4
4
  "description": "TODO",
5
5
  "bin": {
6
6
  "gat": "dist/cli.js"