diff --git a/.github/templates/build.ts b/.github/templates/build.ts index 2a6d9e4..86f7dd1 100644 --- a/.github/templates/build.ts +++ b/.github/templates/build.ts @@ -8,7 +8,7 @@ const setupNodeStep: UseStep = { uses: "actions/setup-node@v3", }; -new Workflow("Build") +export default new Workflow("Build") .on("push", { branches: ["main"] }) .on("pull_request") .addJob("build", { @@ -30,5 +30,4 @@ new Workflow("Build") { name: "Check lint problems", run: "npm run lint" }, { name: "Check format problems", run: "npm run format:check" }, ], - }) - .compile(); + }); diff --git a/.github/templates/index.ts b/.github/templates/index.ts new file mode 100644 index 0000000..91608e0 --- /dev/null +++ b/.github/templates/index.ts @@ -0,0 +1,3 @@ +import Build from "./build"; + +Build.compile("build.yml"); diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b81fd70..996dfac 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,4 +28,3 @@ jobs: run: npm run lint - name: Check format problems run: npm run format:check - diff --git a/package-lock.json b/package-lock.json index 8dce1e9..9b47974 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@factorialco/gat", - "version": "1.5.0", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@factorialco/gat", - "version": "1.5.0", + "version": "2.0.0", "license": "ISC", "dependencies": { "js-yaml": "^4.1.0", diff --git a/package.json b/package.json index 72f435d..e73fe22 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@factorialco/gat", - "version": "1.5.0", + "version": "2.0.0", "description": "Write your GitHub Actions workflows using TypeScript", "bin": { "gat": "dist/cli.js" diff --git a/src/__snapshots__/workflow.spec.ts.snap b/src/__snapshots__/workflow.spec.ts.snap index 93bcba6..e03f412 100644 --- a/src/__snapshots__/workflow.spec.ts.snap +++ b/src/__snapshots__/workflow.spec.ts.snap @@ -1,4 +1,4 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +// Vitest Snapshot v1 exports[`Workflow > allows a job matrix 1`] = ` "# Workflow automatically generated by gat diff --git a/src/cli.ts b/src/cli.ts index 5b7c76e..b8fd7cf 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -4,83 +4,32 @@ import path from "path"; import { exec } from "child_process"; import { Command } from "commander"; import { promisify } from "util"; -import debounce from "lodash/debounce"; const execPromise = promisify(exec); -const writeFilePromise = promisify(fs.writeFile); const folder = path.join(process.cwd(), ".github", "templates"); -const parseFile = async (templateFile: string) => { - // NOTE: can we improve this using ts-node or typescript programatically? - const { stdout } = await execPromise( - `npx ts-node ${ - process.env["GAT_BUILD_FLAGS"] ?? "--swc -T" - } ${templateFile}` - ); - - await writeFilePromise( - path.join( - process.cwd(), - ".github", - "workflows", - templateFile.split("/").at(-1)!.replace(".ts", ".yml") - ), - stdout - ); -}; - const cli = new Command(); cli - .version("1.0.0") + .version("2.0.0") .description("Write your GitHub Actions workflows using TypeScript"); cli .command("build") .description("Transpile all Gat templates into GitHub Actions workflows.") - .argument("[file]", "(Optional) A Gat template file") - .action(async (file) => { + .action(async () => { if (!fs.existsSync(path.join(folder, "..", "workflows"))) { fs.mkdirSync(path.join(folder, "..", "workflows")); } - if (file !== undefined) { - await parseFile(file); - } else { - await Promise.all( - fs.readdirSync(folder).map(async (templateFile) => { - if (!templateFile.match(/^shared$/)) { - await parseFile(`${path.join(folder, templateFile)}`); - } - }) - ); - } + await execPromise( + `npx ts-node ${process.env["GAT_BUILD_FLAGS"] ?? "--swc -T"} ${path.join( + folder, + "index.ts" + )}` + ); process.exit(0); }); -cli - .command("watch") - .description( - "Watch file changes in your Gat templates folder and transpile them automatically." - ) - .action(async () => { - const parseWatchedFile = debounce(async (fileName) => { - const start = process.hrtime.bigint(); - process.stdout.write( - `😸 Detected change on file ${fileName}. Transpiling... ` - ); - await parseFile(path.join(folder, fileName.toString())); - console.log( - `Done in ${( - Number(process.hrtime.bigint() - start) / 1_000_000 - ).toFixed(2)}ms` - ); - }, 1000); - console.log(`😼 Watching file changes on ${folder}...`); - fs.watch(folder).on("change", (_eventName, fileName) => { - parseWatchedFile(fileName); - }); - }); - cli.parse(process.argv); diff --git a/src/event.ts b/src/event.ts index 33ac4b5..cb98850 100644 --- a/src/event.ts +++ b/src/event.ts @@ -6,7 +6,7 @@ export type EventName = | "workflow_dispatch" | "schedule" | "pull_request_target" - | "repository_dispatch" + | "repository_dispatch"; export type EventOptions = T extends "push" ? PushEventOptions @@ -60,7 +60,7 @@ interface WorkflowDispatchEventOptions { type ScheduleEventOptions = Array<{ cron: string }>; interface RepositoryDispatchEventOptions { - types: string[] + types: string[]; } export interface Event { diff --git a/src/workflow.ts b/src/workflow.ts index 2f355fa..5b8212f 100644 --- a/src/workflow.ts +++ b/src/workflow.ts @@ -1,10 +1,15 @@ import { dump } from "js-yaml"; import kebabCase from "lodash/kebabCase"; +import fs from "fs"; +import path from "path"; +import { promisify } from "util"; import { ConcurrencyGroup, Job, JobOptions, StringWithNoSpaces } from "./job"; import type { Event, EventName, EventOptions } from "./event"; import { BaseStep, Step } from "./step"; +const writeFilePromise = promisify(fs.writeFile); + const DEFAULT_RUNNERS = ["ubuntu-22.04"]; interface DefaultOptions { @@ -73,7 +78,7 @@ export class Workflow< return isSelfHosted ? ["self-hosted", runnerName] : runnerName; } - compile() { + compile(filepath?: string) { const result = { name: this.name, on: Object.fromEntries( @@ -136,12 +141,18 @@ export class Workflow< strategy: matrix ? { "fail-fast": false, - matrix: typeof matrix === 'string' ? matrix : { - ...Object.fromEntries( - matrix.elements.map(({ id, options }) => [id, options]) - ), - include: matrix.extra, - }, + matrix: + typeof matrix === "string" + ? matrix + : { + ...Object.fromEntries( + matrix.elements.map(({ id, options }) => [ + id, + options, + ]) + ), + include: matrix.extra, + }, } : undefined, env, @@ -187,8 +198,11 @@ export class Workflow< } )}`; - console.log(compiled); + if (!filepath) return compiled; - return compiled; + return writeFilePromise( + path.join(process.cwd(), ".github", "workflows", filepath), + compiled + ); } }