@@ -38,13 +38,13 @@ const cfg = new Config()
3838 .include (" ./common.yml" )
3939
4040// Template job (hidden)
41- cfg .template (" base" , { image: " node:18" })
42- // same as
43- // cfg .job("base", { image: "node:18" }, true)
44- // or
45- // cfg .job(".base", { image: "node:18" })
41+ config .template (" base" , { image: " node:18" })
42+ // Or using job() with options:
43+ // config .job("base", { image: "node:18" }, { hidden: true } )
44+ // Or with dot prefix:
45+ // config .job(".base", { image: "node:18" })
4646
47- cfg .extends (" .base" , " unittest" , {
47+ config .extends (" .base" , " unittest" , {
4848 stage: " test" ,
4949 script: [" npm run test" ],
5050})
@@ -355,6 +355,67 @@ export default function (config: Config) {
355355
356356** Note:** If both default and named exports are present, the default export takes precedence.
357357
358+ ## Job Options & Global Settings
359+
360+ ### Job Options
361+
362+ The ` job() ` , ` template() ` , and ` extends() ` methods accept an optional ` JobOptions ` parameter for fine-grained control:
363+
364+ ``` ts
365+ interface JobOptions {
366+ hidden? : boolean // Mark as template (prefix with dot)
367+ mergeExisting? : boolean // Merge with existing job/template (default: true)
368+ resolveExtends? : boolean // Resolve parent extends (default: true)
369+ }
370+ ```
371+
372+ ** Example:**
373+
374+ ``` ts
375+ const config = new Config ()
376+
377+ // Create a hidden template
378+ config .job (" base" , { image: " node:22" }, { hidden: true })
379+ // Same as: config.template(".base", { image: "node:22" })
380+
381+ // Replace instead of merge
382+ config .job (" build" , { stage: " build" , script: [" npm run build" ] })
383+ config .job (" build" , { script: [" npm run build:prod" ] }, { mergeExisting: false })
384+ // Result: { script: ["npm run build:prod"] } (stage removed)
385+
386+ // Keep extends reference (don't resolve parent)
387+ config .template (" .base" , { script: [" base command" ] })
388+ config .job (" child" , { extends: " .base" }, { resolveExtends: false })
389+ // Output keeps: extends: ".base"
390+ ```
391+
392+ ### Global Options
393+
394+ Set default behavior for all jobs using ` globalOptions() ` . Job-level options override global settings:
395+
396+ ``` ts
397+ const config = new Config ()
398+
399+ // Disable extends resolution globally
400+ config .globalOptions ({ resolveExtends: false })
401+
402+ config .template (" .base" , { script: [" base" ] })
403+
404+ // This job keeps extends (global setting)
405+ config .job (" job1" , { extends: " .base" })
406+ // Output: { extends: ".base" }
407+
408+ // This job resolves extends (local override)
409+ config .job (" job2" , { extends: " .base" }, { resolveExtends: true })
410+ // Output: { script: ["base"] }
411+ ```
412+
413+ ** Use Cases:**
414+
415+ - ** Preserve extends in output** : Set ` resolveExtends: false ` to keep GitLab CI's native extends instead of inlining parent properties
416+ - ** Strict replacement** : Set ` mergeExisting: false ` globally to prevent accidental job merging
417+ - ** Conditional resolution** : Disable extends resolution globally, then selectively enable it for specific jobs
418+
358419## API Reference
359420
360421This reference summarizes the primary ` Config ` API surface. Method signatures reflect
@@ -369,6 +430,11 @@ the runtime builder and are derived from the JSDoc on the source `Config` class.
369430- ` addStage(stage: string): Config `
370431 - Convenience wrapper for adding a single stage.
371432
433+ - ` globalOptions(options: GlobalOptions): Config `
434+ - Set global options that apply to all jobs and templates.
435+ - Options: ` { resolveExtends?: boolean, mergeExisting?: boolean } `
436+ - Job-level options override global settings.
437+
372438- ` workflow(workflow: GitLabCi["workflow"]): Config `
373439 - Set or deep-merge the top-level ` workflow ` configuration (typically ` rules ` ).
374440
@@ -387,25 +453,28 @@ the runtime builder and are derived from the JSDoc on the source `Config` class.
387453- ` getJob(name: string): JobDefinition | undefined `
388454 - Look up a job or template definition by name (templates start with ` . ` ).
389455
390- - ` template(name: string, definition: JobDefinition, options?: { mergeExisting?: boolean } ): Config `
456+ - ` template(name: string, definition: JobDefinition, options?: JobOptions ): Config `
391457 - Define or deep-merge a hidden template job. The stored template name will have a leading ` . ` .
458+ - Options: ` { mergeExisting?: boolean, resolveExtends?: boolean, hidden?: boolean } `
392459
393460- ` include(item: IncludeDefinition | IncludeDefinition[]): Config `
394461 - Add include entries. Accepts strings, objects or arrays and normalizes strings to
395462 ` { local: "..." } ` or ` { remote: "https://..." } ` depending on the value.
396463
397- - ` job(name: string, definition: JobDefinition, hidden?: boolean, options?: { mergeExisting?: boolean } ): Config `
398- - Create or merge a job. If ` name ` starts with ` . ` or ` hidden ` is true, the call delegates
464+ - ` job(name: string, definition: JobDefinition, options?: JobOptions ): Config `
465+ - Create or merge a job. If ` name ` starts with ` . ` or ` options. hidden` is true, the call delegates
399466 to ` template() ` and ensures a single leading ` . ` on the stored template name.
467+ - Options: ` { hidden?: boolean, mergeExisting?: boolean, resolveExtends?: boolean } `
400468
401469- ` macro<T extends MacroArgs>(key: string, callback: (config: Config, args: T) => void): void `
402470 - Register a macro function for programmatic job generation.
403471
404472- ` from<T extends MacroArgs>(key: string, args: T): void `
405473 - Invoke a previously registered macro.
406474
407- - ` extends(fromName: string | string[], name: string, job?: JobDefinition, hidden ?: boolean ): void `
475+ - ` extends(fromName: string | string[], name: string, job?: JobDefinition, options ?: JobOptions ): void `
408476 - Create a job that will extend one or more templates/jobs (injects an ` extends ` property).
477+ - Options: ` { hidden?: boolean, mergeExisting?: boolean, resolveExtends?: boolean } `
409478
410479- ` dynamicInclude(cwd: string, globs: string[]): Promise<void> `
411480 - Import TypeScript modules matched by the provided globs and call their exported ` extendConfig ` .
0 commit comments