$ import { createJobId, createWorkflowId, defineWorkflow } from "@ghawb/sdk";
import { nodeCi } from "@ghawb/job-helpers"; const workflow = defineWorkflow({ id: createWorkflowId("ci"), name: "CI",
}) .onPush({ branches: ["main"] }) .onPullRequest({ branches: ["main"] }) .addJob(createJobId("test"), (job) => { job.runsOn("ubuntu-latest").apply(nodeCi({ nodeVersion: "24" })); }) .build();
import { createJobId, createWorkflowId, defineWorkflow } from "@ghawb/sdk";
import { nodeCi } from "@ghawb/job-helpers"; const workflow = defineWorkflow({ id: createWorkflowId("ci"), name: "CI",
}) .onPush({ branches: ["main"] }) .onPullRequest({ branches: ["main"] }) .addJob(createJobId("test"), (job) => { job.runsOn("ubuntu-latest").apply(nodeCi({ nodeVersion: "24" })); }) .build();
import { createJobId, createWorkflowId, defineWorkflow } from "@ghawb/sdk";
import { nodeCi } from "@ghawb/job-helpers"; const workflow = defineWorkflow({ id: createWorkflowId("ci"), name: "CI",
}) .onPush({ branches: ["main"] }) .onPullRequest({ branches: ["main"] }) .addJob(createJobId("test"), (job) => { job.runsOn("ubuntu-latest").apply(nodeCi({ nodeVersion: "24" })); }) .build();
bun x @ghawb/cli render --input workflows/ci.ts --output .github/workflows/ci.yml
bun x @ghawb/cli render --input workflows/ci.ts --output .github/workflows/ci.yml
bun x @ghawb/cli render --input workflows/ci.ts --output .github/workflows/ci.yml
import { createJobId, createWorkflowId, defineWorkflow } from "@ghawb/sdk";
import { nodeCi } from "@ghawb/job-helpers"; export default defineWorkflow({ id: createWorkflowId("ci"), name: "CI",
}) .onPush({ branches: ["main"] }) .onPullRequest({ branches: ["main"] }) .concurrency({ group: "ci-${{ github.ref }}", cancelInProgress: true, }) .addJob(createJobId("check"), (job) => { job .runsOn("ubuntu-latest") .permissions({ contents: "read" }) .apply(nodeCi({ nodeVersion: "24" })); }) .build();
import { createJobId, createWorkflowId, defineWorkflow } from "@ghawb/sdk";
import { nodeCi } from "@ghawb/job-helpers"; export default defineWorkflow({ id: createWorkflowId("ci"), name: "CI",
}) .onPush({ branches: ["main"] }) .onPullRequest({ branches: ["main"] }) .concurrency({ group: "ci-${{ github.ref }}", cancelInProgress: true, }) .addJob(createJobId("check"), (job) => { job .runsOn("ubuntu-latest") .permissions({ contents: "read" }) .apply(nodeCi({ nodeVersion: "24" })); }) .build();
import { createJobId, createWorkflowId, defineWorkflow } from "@ghawb/sdk";
import { nodeCi } from "@ghawb/job-helpers"; export default defineWorkflow({ id: createWorkflowId("ci"), name: "CI",
}) .onPush({ branches: ["main"] }) .onPullRequest({ branches: ["main"] }) .concurrency({ group: "ci-${{ github.ref }}", cancelInProgress: true, }) .addJob(createJobId("check"), (job) => { job .runsOn("ubuntu-latest") .permissions({ contents: "read" }) .apply(nodeCi({ nodeVersion: "24" })); }) .build();
bunx jsr add @ghawb/sdk
bunx jsr add @ghawb/sdk
bunx jsr add @ghawb/sdk
bunx jsr add @ghawb/cli
bunx jsr add @ghawb/cli
bunx jsr add @ghawb/cli
bun x @ghawb/cli render --input workflows/ci.ts
bun x @ghawb/cli render --input workflows/ci.ts
bun x @ghawb/cli render --input workflows/ci.ts
deno add jsr:@ghawb/sdk
deno add jsr:@ghawb/sdk
deno add jsr:@ghawb/sdk - type-safe builders
- validation at construction time
- deterministic YAML rendering
- source-first distribution through JSR - invalid combinations of trigger fields
- blank or malformed IDs
- step output references that point to nothing
- reusable workflow jobs using fields GitHub does not allow there
- matrix definitions that look plausible but are structurally wrong - keep the GitHub Actions model explicit
- catch structural mistakes earlier
- make large workflows easier to compose and review
- preserve committed YAML as a normal repository artifact - triggers are still triggers
- jobs are still jobs
- reusable workflows are still reusable workflows
- rendered output is still plain GitHub Actions YAML - identifier format for workflow IDs and job IDs
- invalid trigger/filter combinations
- duplicate or malformed step IDs
- references to undeclared step outputs in job outputs
- unsupported fields on reusable workflow jobs
- invalid matrix declarations
- invalid environment/config shapes - factor repeated workflow logic into named helpers
- test workflow construction
- inject render-time config
- use editor completion and refactoring
- keep reusable CI paths small and explicit
- review generated YAML without manually maintaining all of it - TypeScript is the source
- GitHub Actions YAML is the committed artifact
- GitHub Actions remains the runtime
- the rendered output stays reviewable - workflow builders
- expressions
- rendering payloads - @ghawb/job-helpers for higher-level helpers like Node CI setup
- @ghawb/typed-actions for typed wrappers around common actions
- @ghawb/composite-actions for authoring action.yml
- @ghawb/cli for rendering source modules into YAML
- @ghawb/reusable-workflow-import for bringing existing reusable workflow YAML into the typed world without pushing YAML parsing into the SDK core - source-first TypeScript packages
- Bun as the default development runtime
- continued Deno support - workflow authoring
- CLI rendering
- typed action wrappers
- composite action authoring
- reusable workflow import