@savvy-web/github-action-builder 0.6.4 → 0.7.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/677.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Context, Data, Effect, Layer, ParseResult, Schema } from "effect";
2
- import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
2
+ import { copyFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, statSync, writeFileSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
3
4
  import { dirname, join, relative, resolve } from "node:path";
4
5
  import { createRsbuild } from "@rsbuild/core";
5
6
  import { fileURLToPath } from "node:url";
@@ -102,6 +103,9 @@ const BuildOptionsSchema = Schema.Struct({
102
103
  }),
103
104
  externals: Schema.optionalWith(Schema.Array(Schema.String), {
104
105
  default: ()=>[]
106
+ }),
107
+ ignore: Schema.optionalWith(Schema.Array(Schema.String), {
108
+ default: ()=>[]
105
109
  })
106
110
  });
107
111
  const ValidationOptionsSchema = Schema.Struct({
@@ -131,7 +135,8 @@ const ConfigInputSchema = Schema.Struct({
131
135
  build: Schema.optional(Schema.Struct({
132
136
  minify: Schema.optional(Schema.Boolean),
133
137
  sourceMap: Schema.optional(Schema.Boolean),
134
- externals: Schema.optional(Schema.Array(Schema.String))
138
+ externals: Schema.optional(Schema.Array(Schema.String)),
139
+ ignore: Schema.optional(Schema.Array(Schema.String))
135
140
  })),
136
141
  validation: Schema.optional(Schema.Struct({
137
142
  requireActionYml: Schema.optional(Schema.Boolean),
@@ -178,6 +183,7 @@ Schema.Struct({
178
183
  usingDefaults: Schema.Boolean
179
184
  });
180
185
  const ConfigService = Context.GenericTag("ConfigService");
186
+ const IGNORE_STUB_SOURCE = `throw new Error("A module excluded via the build 'ignore' option was loaded at runtime.");\n`;
181
187
  function formatBytes(bytes) {
182
188
  if (bytes < 1024) return `${bytes} B`;
183
189
  if (bytes < 1048576) return `${(bytes / 1024).toFixed(1)} KB`;
@@ -231,6 +237,22 @@ function bundleEntry(entry, config, cwd) {
231
237
  return Effect.gen(function*() {
232
238
  const startTime = Date.now();
233
239
  const outputDir = resolve(cwd, "dist");
240
+ const externalsSet = new Set(config.build.externals);
241
+ const ignoreSet = new Set(config.build.ignore);
242
+ const ignoreAlias = {};
243
+ let stubDir;
244
+ if (config.build.ignore.length > 0) {
245
+ stubDir = yield* Effect["try"]({
246
+ try: ()=>mkdtempSync(join(tmpdir(), "github-action-builder-")),
247
+ catch: (error)=>new WriteError({
248
+ path: tmpdir(),
249
+ cause: error
250
+ })
251
+ });
252
+ const stubPath = resolve(stubDir, "ignore-stub.mjs");
253
+ yield* writeFile(stubPath, IGNORE_STUB_SOURCE);
254
+ for (const moduleName of config.build.ignore)ignoreAlias[`${moduleName}$`] = stubPath;
255
+ }
234
256
  const rsbuild = yield* Effect.tryPromise({
235
257
  try: ()=>createRsbuild({
236
258
  rsbuildConfig: {
@@ -239,6 +261,9 @@ function bundleEntry(entry, config, cwd) {
239
261
  [entry.type]: entry.path
240
262
  }
241
263
  },
264
+ resolve: {
265
+ alias: ignoreAlias
266
+ },
242
267
  output: {
243
268
  target: "node",
244
269
  module: true,
@@ -248,10 +273,13 @@ function bundleEntry(entry, config, cwd) {
248
273
  filename: {
249
274
  js: "[name].js"
250
275
  },
251
- externals: [
252
- (data)=>data.request?.startsWith("node:") ? `node-commonjs ${data.request}` : false,
253
- ...config.build.externals
254
- ],
276
+ externals: (data)=>{
277
+ const request = data.request;
278
+ if (!request) return false;
279
+ if (request.startsWith("node:")) return `node-commonjs ${request}`;
280
+ if (externalsSet.has(request) && !ignoreSet.has(request)) return request;
281
+ return false;
282
+ },
255
283
  cleanDistPath: false,
256
284
  minify: config.build.minify,
257
285
  sourceMap: config.build.sourceMap ? {
@@ -262,6 +290,17 @@ function bundleEntry(entry, config, cwd) {
262
290
  chunkSplit: {
263
291
  strategy: "all-in-one"
264
292
  }
293
+ },
294
+ tools: {
295
+ rspack: {
296
+ node: {
297
+ __dirname: "node-module",
298
+ __filename: "node-module"
299
+ },
300
+ output: {
301
+ asyncChunks: false
302
+ }
303
+ }
265
304
  }
266
305
  }
267
306
  }),
@@ -284,6 +323,13 @@ function bundleEntry(entry, config, cwd) {
284
323
  cause: new Error(`rsbuild close() failed: ${error}`)
285
324
  })
286
325
  });
326
+ if (void 0 !== stubDir) {
327
+ const dir = stubDir;
328
+ yield* Effect.ignore(Effect["try"](()=>rmSync(dir, {
329
+ recursive: true,
330
+ force: true
331
+ })));
332
+ }
287
333
  const outputPath = resolve(outputDir, `${entry.type}.js`);
288
334
  const size = yield* Effect["try"]({
289
335
  try: ()=>statSync(outputPath).size,
package/README.md CHANGED
@@ -1,27 +1,23 @@
1
1
  # @savvy-web/github-action-builder
2
2
 
3
- A zero-config build tool for creating GitHub Actions from TypeScript source
4
- code. Bundles your action with [@rsbuild/core](https://github.com/web-infra-dev/rsbuild)
5
- (rspack-based), validates `action.yml` against GitHub's official schema, and
6
- outputs production-ready Node.js 24 actions.
3
+ [![npm](https://img.shields.io/npm/v/@savvy-web%2Fgithub-action-builder?label=npm&color=cb3837)](https://www.npmjs.com/package/@savvy-web/github-action-builder)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-4caf50.svg)](https://opensource.org/licenses/MIT)
5
+ [![Node.js 24](https://img.shields.io/badge/Node.js-24-5fa04e.svg)](https://nodejs.org/)
6
+
7
+ Build a GitHub Action from TypeScript source without writing build config. The builder bundles your code with [@rsbuild/core](https://github.com/web-infra-dev/rsbuild) (rspack under the hood) and checks `action.yml` against GitHub's published metadata schema. The output is a single Node.js 24 file you commit to your repo.
7
8
 
8
9
  ## Features
9
10
 
10
- - **Zero-config** - Auto-detects entry points from `src/main.ts`, `src/pre.ts`,
11
- `src/post.ts`
12
- - **Node.js 24** - Builds modern ESM actions for the latest GitHub Actions
13
- runtime
14
- - **Schema validation** - Validates `action.yml` against GitHub's official
15
- metadata specification
16
- - **Single-file bundles** - All npm dependencies inlined via rsbuild, `node:`
17
- builtins externalized, with tree-shaking support
18
- - **Local testing** - Auto-persists build output for testing with
19
- [nektos/act](https://github.com/nektos/act)
11
+ - **No build config required** - Picks up entry points from `src/main.ts`, `src/pre.ts`, `src/post.ts` on its own
12
+ - **Node.js 24** - Emits ESM actions that run on the `node24` GitHub Actions runtime
13
+ - **Schema validation** - Validates `action.yml` against GitHub's official metadata specification
14
+ - **Single-file bundles** - All npm dependencies inlined via rsbuild; `node:` builtins externalized; user-configured `externals` and `ignore` options for optional or native modules
15
+ - **Local testing** - Auto-persists build output for testing with [nektos/act](https://github.com/nektos/act)
20
16
  - **CI-aware** - Strict validation in CI, warnings-only locally
21
17
 
22
- ## Quick Start
18
+ ## Quick start
23
19
 
24
- Create a new GitHub Action project with a single command:
20
+ Scaffold a new GitHub Action project, then build it:
25
21
 
26
22
  ```bash
27
23
  npx @savvy-web/github-action-builder init my-action
@@ -30,8 +26,7 @@ npm install
30
26
  npm run build
31
27
  ```
32
28
 
33
- That's it! Your action is built and ready. The `init` command generates a
34
- complete project:
29
+ The `init` command lays down the project:
35
30
 
36
31
  ```text
37
32
  my-action/
@@ -45,10 +40,9 @@ my-action/
45
40
  └── tsconfig.json # TypeScript configuration
46
41
  ```
47
42
 
48
- Edit `src/main.ts` with your action logic, then rebuild with `npm run build`.
49
- Your bundled action is in `dist/main.js`, ready to commit and use.
43
+ Put your action logic in `src/main.ts` and run `npm run build` again. The bundled action lands at `dist/main.js` commit that file to your repo.
50
44
 
51
- ## Basic Usage
45
+ ## Basic usage
52
46
 
53
47
  ### Initialize
54
48
 
@@ -78,7 +72,7 @@ npm run validate
78
72
  npx @savvy-web/github-action-builder validate
79
73
  ```
80
74
 
81
- ## Project Structure
75
+ ## Project structure
82
76
 
83
77
  The builder expects this structure:
84
78
 
@@ -112,7 +106,7 @@ export default GitHubAction.create({
112
106
  });
113
107
  ```
114
108
 
115
- ## action.yml Requirements
109
+ ## action.yml requirements
116
110
 
117
111
  Your `action.yml` must use Node.js 24:
118
112
 
@@ -127,12 +121,12 @@ runs:
127
121
 
128
122
  ## Documentation
129
123
 
130
- - [Getting Started](./docs/getting-started.md) - Installation and first build
131
- - [Configuration](./docs/configuration.md) - All configuration options
132
- - [Local Testing](./docs/local-testing.md) - Testing with nektos/act
133
- - [CLI Reference](./docs/cli-reference.md) - Complete command reference
134
- - [Architecture](./docs/architecture.md) - How it works internally
135
- - [Troubleshooting](./docs/troubleshooting.md) - Common issues and solutions
124
+ - [Getting started](./docs/01-getting-started.md) - Installation and first build
125
+ - [Configuration](./docs/02-configuration.md) - All configuration options
126
+ - [Local testing](./docs/03-local-testing.md) - Testing with nektos/act
127
+ - [CLI reference](./docs/04-cli-reference.md) - Complete command reference
128
+ - [Architecture](./docs/05-architecture.md) - How it works internally
129
+ - [Troubleshooting](./docs/06-troubleshooting.md) - Common issues and solutions
136
130
 
137
131
  ## Programmatic API
138
132
 
@@ -146,10 +140,11 @@ const result = await action.build();
146
140
 
147
141
  if (result.success) {
148
142
  console.log(`Built ${result.build?.entries.length} entry points`);
143
+ // e.g. "Built 3 entry points"
149
144
  }
150
145
  ```
151
146
 
152
- ## Shared TypeScript Configuration
147
+ ## Shared TypeScript configuration
153
148
 
154
149
  The package exports a base `tsconfig.json` for GitHub Action projects:
155
150
 
@@ -159,9 +154,7 @@ The package exports a base `tsconfig.json` for GitHub Action projects:
159
154
  }
160
155
  ```
161
156
 
162
- This provides sensible defaults for Node.js 24 ESM actions including strict
163
- mode, ES2022 target, and bundler module resolution. Override or extend as
164
- needed in your project's `tsconfig.json`.
157
+ It sets up Node.js 24 ESM actions with strict mode, an ES2022 target and bundler module resolution. Override any of it in your own `tsconfig.json`.
165
158
 
166
159
  ## Requirements
167
160
 
@@ -74,7 +74,7 @@ const actionNameArg = Args.text({
74
74
  name: "action-name"
75
75
  }).pipe(Args.withDescription("Name of the GitHub Action (also the output directory)"));
76
76
  const forceOption = Options.boolean("force").pipe(Options.withAlias("f"), Options.withDescription("Overwrite existing files"), Options.withDefault(false));
77
- const getPackageVersion = ()=>"0.6.4";
77
+ const getPackageVersion = ()=>"0.7.1";
78
78
  const generatePackageJson = (name)=>{
79
79
  const version = getPackageVersion();
80
80
  const pkg = {
@@ -306,7 +306,7 @@ const rootCommand = Command.make("github-action-builder").pipe(Command.withSubco
306
306
  ]));
307
307
  const cli = Command.run(rootCommand, {
308
308
  name: "github-action-builder",
309
- version: "0.6.4"
309
+ version: "0.7.1"
310
310
  });
311
311
  const CliLayer = Layer.merge(AppLayer, NodeContext.layer);
312
312
  const main = Effect.suspend(()=>cli(process.argv)).pipe(Effect.provide(CliLayer), Effect.catchAllCause((cause)=>{
package/index.d.ts CHANGED
@@ -343,6 +343,10 @@ export declare const BuildOptionsSchema: Schema.Struct<{
343
343
  externals: Schema.optionalWith<Schema.Array$<typeof Schema.String>, {
344
344
  default: () => never[];
345
345
  }>;
346
+ /** Packages to exclude from the bundle and replace with a stub that throws if loaded at runtime. Use for optional transitive dependencies the action never exercises (e.g. native modules). Defaults to []. */
347
+ ignore: Schema.optionalWith<Schema.Array$<typeof Schema.String>, {
348
+ default: () => never[];
349
+ }>;
346
350
  }>;
347
351
 
348
352
  /**
@@ -637,6 +641,7 @@ export declare const ConfigInputSchema: Schema.Struct<{
637
641
  minify: Schema.optional<typeof Schema.Boolean>;
638
642
  sourceMap: Schema.optional<typeof Schema.Boolean>;
639
643
  externals: Schema.optional<Schema.Array$<typeof Schema.String>>;
644
+ ignore: Schema.optional<Schema.Array$<typeof Schema.String>>;
640
645
  }>>;
641
646
  validation: Schema.optional<Schema.Struct<{
642
647
  requireActionYml: Schema.optional<typeof Schema.Boolean>;
@@ -782,6 +787,10 @@ export declare const ConfigSchema: Schema.Struct<{
782
787
  externals: Schema.optionalWith<Schema.Array$<typeof Schema.String>, {
783
788
  default: () => never[];
784
789
  }>;
790
+ /** Packages to exclude from the bundle and replace with a stub that throws if loaded at runtime. Use for optional transitive dependencies the action never exercises (e.g. native modules). Defaults to []. */
791
+ ignore: Schema.optionalWith<Schema.Array$<typeof Schema.String>, {
792
+ default: () => never[];
793
+ }>;
785
794
  }>;
786
795
  validation: Schema.Struct<{
787
796
  /** Require action.yml to exist and be valid. Defaults to true. */
@@ -910,6 +919,7 @@ export declare const ConfigService: Context.Tag<ConfigService, ConfigService>;
910
919
  * minify: true,
911
920
  * sourceMap: true,
912
921
  * externals: ["@aws-sdk/client-s3"],
922
+ * ignore: ["libxmljs2"],
913
923
  * },
914
924
  * validation: {
915
925
  * requireActionYml: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvy-web/github-action-builder",
3
- "version": "0.6.4",
3
+ "version": "0.7.1",
4
4
  "private": false,
5
5
  "description": "A zero-config build tool for creating GitHub Actions from TypeScript. Bundles with rsbuild, validates action.yml against GitHub's schema, and outputs production-ready Node.js 24 actions.",
6
6
  "keywords": [