gagen 0.2.1 → 0.2.3

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
@@ -18,7 +18,6 @@ import {
18
18
  conditions,
19
19
  createWorkflow,
20
20
  step,
21
- steps,
22
21
  } from "gagen";
23
22
 
24
23
  const checkout = step({
@@ -34,7 +33,7 @@ const installDeno = step({
34
33
  uses: "denoland/setup-deno@v2",
35
34
  });
36
35
 
37
- const lint = steps(
36
+ const lint = step(
38
37
  {
39
38
  name: "Clippy",
40
39
  run: "cargo clippy",
@@ -1 +1 @@
1
- {"version":3,"file":"artifact.d.ts","sourceRoot":"","sources":["../src/artifact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,QAAQ;;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAIV,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe;IAKnD,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAgBlC,QAAQ,CAAC,MAAM,GAAE,cAAmB,GAAG,IAAI;CAgB5C;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,eAAe,GACxB,QAAQ,CAEV"}
1
+ {"version":3,"file":"artifact.d.ts","sourceRoot":"","sources":["../src/artifact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,QAAQ;;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;gBAIV,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe;IAKnD,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAgBlC,QAAQ,CAAC,MAAM,GAAE,cAAmB,GAAG,IAAI;CAe5C;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,eAAe,GACxB,QAAQ,CAEV"}
package/esm/artifact.js CHANGED
@@ -46,14 +46,10 @@ export class Artifact {
46
46
  if (config.path != null) {
47
47
  withObj.path = config.path;
48
48
  }
49
- const s = new Step({
49
+ return new Step({
50
50
  uses: `actions/download-artifact@${__classPrivateFieldGet(this, _Artifact_version, "f")}`,
51
51
  with: withObj,
52
- });
53
- if (__classPrivateFieldGet(this, _Artifact_uploadStep, "f")) {
54
- s._crossJobDeps.push(__classPrivateFieldGet(this, _Artifact_uploadStep, "f"));
55
- }
56
- return s;
52
+ }, __classPrivateFieldGet(this, _Artifact_uploadStep, "f") ? [__classPrivateFieldGet(this, _Artifact_uploadStep, "f")] : []);
57
53
  }
58
54
  }
59
55
  _Artifact_version = new WeakMap(), _Artifact_uploadStep = new WeakMap();
@@ -19,6 +19,7 @@ export declare class ExpressionValue {
19
19
  notEquals(value: string | number | boolean): Condition;
20
20
  startsWith(prefix: string): Condition;
21
21
  contains(substring: string): Condition;
22
+ not(): Condition;
22
23
  /** wrap in `${{ }}` for use in YAML */
23
24
  toString(): string;
24
25
  }
@@ -1 +1 @@
1
- {"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../src/expression.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,gBAAgB,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAIvD,wEAAwE;AACxE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,eAAe,CAAC;AAEvE;;;GAGG;AACH,qBAAa,eAAe;;IAE1B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAC;gBAI5C,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,gBAAgB,GAAG,WAAW,CAAC,gBAAgB,CAAC;IAa3D,sDAAsD;IACtD,IAAI,UAAU,IAAI,WAAW,CAAC,gBAAgB,CAAC,CAE9C;IAED,oDAAoD;IACpD,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS;IASnD,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS;IAStD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS;IAQrC,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;IAQtC,uCAAuC;IACvC,QAAQ,IAAI,MAAM;CAGnB;AAED;;;;GAIG;AACH,8BAAsB,SAAS;IAC7B,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,gBAAgB,CAAC,CAAC;gBAEpC,OAAO,EAAE,WAAW,CAAC,gBAAgB,CAAC;IAIlD,GAAG,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS;IAIhC,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS;IAI/B,GAAG,IAAI,SAAS;IAIhB;;;;;;;OAOG;IACH,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,WAAW;IAItC;;;OAGG;IACH,WAAW,IAAI,MAAM,EAAE;IAIvB,2EAA2E;IAC3E,UAAU,IAAI,SAAS,EAAE;IAIzB,0EAA0E;IAC1E,SAAS,IAAI,SAAS,EAAE;IAIxB,uCAAuC;IACvC,QAAQ,CAAC,YAAY,IAAI,MAAM;IAE/B,sDAAsD;IACtD,QAAQ,IAAI,MAAM;CAGnB;AAID,yCAAyC;AACzC,qBAAa,mBAAoB,SAAQ,SAAS;;gBAM9C,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,IAAI,GAAG,IAAI,EACf,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAChC,OAAO,EAAE,WAAW,CAAC,gBAAgB,CAAC;IAQxC,YAAY,IAAI,MAAM;CAGvB;AAED,4BAA4B;AAC5B,qBAAa,qBAAsB,SAAQ,SAAS;;gBAKhD,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,WAAW,CAAC,gBAAgB,CAAC;IAOxC,YAAY,IAAI,MAAM;CAGvB;AAoFD,mDAAmD;AACnD,qBAAa,YAAa,SAAQ,SAAS;;gBAG7B,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,CAAC,gBAAgB,CAAC;IAKtE,YAAY,IAAI,MAAM;CAGvB;AAED,+DAA+D;AAC/D,wBAAgB,IAAI,CAAC,UAAU,EAAE,MAAM,GAAG,eAAe,CAExD;AAED,6DAA6D;AAC7D,eAAO,MAAM,UAAU;IACrB,8DAA8D;;QAE5D,+CAA+C;+BACnC,SAAS;QAErB,qEAAqE;gCACxD,SAAS;QAEtB,gDAAgD;gCACnC,SAAS;QAEtB,gDAAgD;kCACjC,SAAS;;IAG1B;;;;;;;;OAQG;2BACW,MAAM,KAAG,SAAS;IAahC;;;;;;OAMG;gCACgB,MAAM,KAAG,SAAS;IAOrC;;;;;;OAMG;8BACc,MAAM,KAAG,SAAS;CAO3B,CAAC;AAIX,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAGtE;AAED,wBAAgB,WAAW,CACzB,GAAG,WAAW,EAAE,CAAC;IAAE,MAAM,CAAC,EAAE,gBAAgB,CAAA;CAAE,GAAG,SAAS,CAAC,EAAE,GAC5D,WAAW,CAAC,gBAAgB,CAAC,CAY/B;AAcD,UAAU,aAAa;IACrB,SAAS,EAAE,SAAS,CAAC;IACrB,KAAK,EAAE,YAAY,CAAC;CACrB;AA+BD;;;GAGG;AACH,qBAAa,WAAW;;gBAKpB,QAAQ,EAAE,aAAa,EAAE,EACzB,OAAO,EAAE,WAAW,CAAC,gBAAgB,CAAC;IAOxC,sCAAsC;IACtC,MAAM,CAAC,SAAS,EAAE,SAAS,GAAG,aAAa;IAI3C;;;;;;;OAOG;IACH,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,eAAe;CAiB3C;AAED;;;GAGG;AACH,qBAAa,aAAa;;gBAMtB,QAAQ,EAAE,aAAa,EAAE,EACzB,OAAO,EAAE,GAAG,CAAC,gBAAgB,CAAC,EAC9B,SAAS,EAAE,SAAS;IAQtB,yCAAyC;IACzC,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,WAAW;CAMvC"}
1
+ {"version":3,"file":"expression.d.ts","sourceRoot":"","sources":["../src/expression.ts"],"names":[],"mappings":"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"}
package/esm/expression.js CHANGED
@@ -56,6 +56,9 @@ export class ExpressionValue {
56
56
  contains(substring) {
57
57
  return new FunctionCallCondition("contains", [__classPrivateFieldGet(this, _ExpressionValue_expression, "f"), formatLiteral(substring)], sourcesFrom(this));
58
58
  }
59
+ not() {
60
+ return new RawCondition(`!(${__classPrivateFieldGet(this, _ExpressionValue_expression, "f")})`, sourcesFrom(this));
61
+ }
59
62
  /** wrap in `${{ }}` for use in YAML */
60
63
  toString() {
61
64
  return `\${{ ${__classPrivateFieldGet(this, _ExpressionValue_expression, "f")} }}`;
package/esm/job.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type ExpressionSource, ExpressionValue } from "./expression.js";
2
2
  import type { Permissions } from "./permissions.js";
3
- import { type ConditionLike, type ConfigValue, Step, StepGroup, type StepLike } from "./step.js";
3
+ import { type ConditionLike, type ConfigValue, Step, type StepLike } from "./step.js";
4
4
  interface CommonJobFields {
5
5
  name?: string | ExpressionValue;
6
6
  needs?: Job[];
@@ -51,7 +51,7 @@ export interface ReusableJobConfig extends CommonJobFields {
51
51
  export type JobConfig = StepsJobConfig | ReusableJobConfig;
52
52
  export interface StepsJobDef extends StepsJobConfig {
53
53
  id?: string;
54
- steps: StepLike[] | StepGroup;
54
+ steps: StepLike | StepLike[];
55
55
  outputs?: Record<string, ExpressionValue>;
56
56
  }
57
57
  export interface ReusableJobDef extends ReusableJobConfig {
@@ -60,15 +60,15 @@ export interface ReusableJobDef extends ReusableJobConfig {
60
60
  export type JobDef = StepsJobDef | ReusableJobDef;
61
61
  export declare class Job implements ExpressionSource {
62
62
  #private;
63
- readonly outputs: Record<string, ExpressionValue>;
63
+ readonly outputs: Readonly<Record<string, ExpressionValue>>;
64
64
  constructor(id: string, config: JobConfig, init?: {
65
65
  steps?: StepLike[];
66
66
  outputs?: Record<string, ExpressionValue>;
67
67
  });
68
68
  get id(): string;
69
69
  resolveSteps(): Step<string>[];
70
- inferNeeds(): Job[];
71
- toYaml(): Record<string, unknown>;
70
+ inferNeeds(stepOwners?: Map<Step<string>, Job[]>): Job[];
71
+ toYaml(stepOwners?: Map<Step<string>, Job[]>): Record<string, unknown>;
72
72
  }
73
73
  export declare function toKebabCase(input: string): string;
74
74
  export declare function resolveJobId(def: JobDef): string;
package/esm/job.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../src/job.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../src/job.ts"],"names":[],"mappings":"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"}
package/esm/job.js CHANGED
@@ -9,15 +9,211 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _Job_id, _Job_config, _Job_leafSteps, _Job_outputDefs;
12
+ var _Job_instances, _Job_id, _Job_config, _Job_leafItems, _Job_outputDefs, _Job_cachedGraph, _Job_cachedLeafSteps, _Job_buildGraph;
13
13
  import { Condition, ExpressionValue, } from "./expression.js";
14
14
  import { Matrix } from "./matrix.js";
15
- import { serializeConditionLike, serializeConfigValues, Step, StepGroup, toCondition, } from "./step.js";
15
+ import { serializeConditionLike, serializeConfigValues, Step, StepRef, toCondition, unwrapSteps, } from "./step.js";
16
+ function ensureEntry(graph, step) {
17
+ let entry = graph.get(step);
18
+ if (!entry) {
19
+ entry = { deps: new Set(), afterDeps: new Set(), contexts: [] };
20
+ graph.set(step, entry);
21
+ }
22
+ return entry;
23
+ }
24
+ /**
25
+ * Records a context condition for a graph entry. Contexts from multiple
26
+ * encounters are collected and combined later (via combineContexts) to
27
+ * properly factor out shared terms. An undefined context means
28
+ * unconditional and dominates any condition.
29
+ */
30
+ function applyContextCondition(entry, context) {
31
+ if (entry.hasUnconditionalContext)
32
+ return;
33
+ if (context == null) {
34
+ entry.contexts = [];
35
+ entry.hasUnconditionalContext = true;
36
+ return;
37
+ }
38
+ entry.contexts.push(context);
39
+ }
40
+ /**
41
+ * Combines the collected context conditions for a graph entry into a single
42
+ * condition. Factors out common AND-terms so that shared conditions (like
43
+ * `!(matrix.skip)`) appear once rather than being duplicated in each OR branch.
44
+ */
45
+ function combineContexts(entry) {
46
+ if (entry.hasUnconditionalContext || entry.contexts.length === 0) {
47
+ return undefined;
48
+ }
49
+ if (entry.contexts.length === 1) {
50
+ return toCondition(entry.contexts[0]);
51
+ }
52
+ const conditions = entry.contexts.map((c) => toCondition(c));
53
+ return simplifyOrConditions(conditions) ?? undefined;
54
+ }
55
+ /** ANDs two optional conditions together (for nesting StepRef conditions). */
56
+ function combineAndConditions(a, b) {
57
+ if (a != null && b != null)
58
+ return toCondition(a).and(toCondition(b));
59
+ return a ?? b;
60
+ }
61
+ /**
62
+ * Returns a step's config.if as a ConditionLike suitable for passing down
63
+ * to dependencies, or undefined if it references step outputs (which would
64
+ * create circular condition dependencies).
65
+ */
66
+ function propagatableConfigIf(step) {
67
+ const configIf = step.config.if;
68
+ if (configIf == null)
69
+ return undefined;
70
+ if (configIf instanceof Condition) {
71
+ for (const source of configIf.sources) {
72
+ if (source instanceof Step)
73
+ return undefined;
74
+ }
75
+ }
76
+ if (configIf instanceof ExpressionValue) {
77
+ for (const source of configIf.allSources) {
78
+ if (source instanceof Step)
79
+ return undefined;
80
+ }
81
+ }
82
+ return configIf;
83
+ }
84
+ /**
85
+ * Recursively flattens a StepLike tree into a flat graph of Steps with
86
+ * per-job dependencies and conditions. Returns the leaf-level Steps that
87
+ * were contributed, so parent composite steps can apply their modifiers.
88
+ *
89
+ * Context conditions are accumulated top-down via AND (nesting) and applied
90
+ * at leaf steps via OR (multiple encounters from different paths).
91
+ *
92
+ * afterDependencies (comesAfter) are NOT flattened into the graph — they are
93
+ * collected in `deferredAfterDeps` and resolved later, so that comesAfter
94
+ * only adds ordering edges for steps already present in the graph.
95
+ */
96
+ function flattenStepLike(item, graph, isLeaf, leafSteps, deferredAfterDeps, contextCondition) {
97
+ if (item instanceof StepRef) {
98
+ const step = item.step;
99
+ // AND this StepRef's condition with the parent context
100
+ const newContext = combineAndConditions(contextCondition, item.condition);
101
+ if (step.children.length > 0) {
102
+ // StepRef wrapping composite step: recurse with combined context
103
+ const contributed = [];
104
+ for (const child of step.children) {
105
+ contributed.push(...flattenStepLike(child, graph, isLeaf, leafSteps, deferredAfterDeps, newContext));
106
+ }
107
+ // compute aggregate dep context: newContext AND (OR of children's
108
+ // config.ifs). If any child is unconditional, or the OR is a tautology,
109
+ // just use newContext.
110
+ let compositeDepsCtx = newContext;
111
+ if (item.dependencies.length > 0) {
112
+ const childIfs = [];
113
+ let allConditional = true;
114
+ for (const s of contributed) {
115
+ const cif = propagatableConfigIf(s);
116
+ if (cif == null) {
117
+ allConditional = false;
118
+ break;
119
+ }
120
+ childIfs.push(cif);
121
+ }
122
+ if (allConditional && childIfs.length > 0) {
123
+ const orCond = simplifyOrConditions(childIfs.map((c) => toCondition(c)));
124
+ if (orCond != null) {
125
+ compositeDepsCtx = combineAndConditions(newContext, orCond);
126
+ }
127
+ }
128
+ }
129
+ // apply deps once with aggregate context, add to all children's dep sets
130
+ for (const dep of item.dependencies) {
131
+ const depSteps = flattenStepLike(dep, graph, false, [], deferredAfterDeps, compositeDepsCtx);
132
+ for (const s of contributed) {
133
+ const entry = graph.get(s);
134
+ for (const ds of depSteps)
135
+ entry.deps.add(ds);
136
+ }
137
+ }
138
+ for (const s of contributed) {
139
+ for (const dep of item.afterDependencies) {
140
+ deferredAfterDeps.push({ step: s, target: dep });
141
+ }
142
+ }
143
+ return contributed;
144
+ }
145
+ // StepRef wrapping leaf step
146
+ const entry = ensureEntry(graph, step);
147
+ if (isLeaf)
148
+ leafSteps.push(step);
149
+ applyContextCondition(entry, newContext);
150
+ // include step's config.if in the dep context
151
+ const depContext = combineAndConditions(newContext, propagatableConfigIf(step));
152
+ for (const dep of item.dependencies) {
153
+ flattenDep(dep, entry.deps, graph, deferredAfterDeps, depContext);
154
+ }
155
+ for (const dep of item.afterDependencies) {
156
+ deferredAfterDeps.push({ step, target: dep });
157
+ }
158
+ return [step];
159
+ }
160
+ // Step (leaf or composite)
161
+ if (item.children.length > 0) {
162
+ // composite step: recurse into children with same context
163
+ const contributed = [];
164
+ for (const child of item.children) {
165
+ contributed.push(...flattenStepLike(child, graph, isLeaf, leafSteps, deferredAfterDeps, contextCondition));
166
+ }
167
+ return contributed;
168
+ }
169
+ // leaf step
170
+ const entry = ensureEntry(graph, item);
171
+ if (isLeaf)
172
+ leafSteps.push(item);
173
+ applyContextCondition(entry, contextCondition);
174
+ return [item];
175
+ }
176
+ /** Flattens a dependency target into the graph and adds it to a dep set. */
177
+ function flattenDep(dep, targetSet, graph, deferredAfterDeps, contextCondition) {
178
+ const steps = flattenStepLike(dep, graph, false, [], deferredAfterDeps, contextCondition);
179
+ for (const s of steps) {
180
+ targetSet.add(s);
181
+ }
182
+ }
183
+ /**
184
+ * Adds condition-source steps as deps in the graph. Iterates until stable
185
+ * because condition sources may bring in new steps whose own conditions
186
+ * reference additional steps.
187
+ */
188
+ function addConditionSourceDeps(graph) {
189
+ let changed = true;
190
+ while (changed) {
191
+ changed = false;
192
+ for (const [step, entry] of [...graph]) {
193
+ for (const cond of [step.config.if, ...entry.contexts]) {
194
+ if (!(cond instanceof Condition))
195
+ continue;
196
+ for (const source of cond.sources) {
197
+ if (!(source instanceof Step))
198
+ continue;
199
+ const srcStep = source;
200
+ if (!graph.has(srcStep)) {
201
+ ensureEntry(graph, srcStep);
202
+ changed = true;
203
+ }
204
+ entry.deps.add(srcStep);
205
+ }
206
+ }
207
+ }
208
+ }
209
+ }
210
+ // --- Job class ---
16
211
  export class Job {
17
212
  constructor(id, config, init) {
213
+ _Job_instances.add(this);
18
214
  _Job_id.set(this, void 0);
19
215
  _Job_config.set(this, void 0);
20
- _Job_leafSteps.set(this, []);
216
+ _Job_leafItems.set(this, []);
21
217
  _Job_outputDefs.set(this, {});
22
218
  Object.defineProperty(this, "outputs", {
23
219
  enumerable: true,
@@ -25,22 +221,21 @@ export class Job {
25
221
  writable: true,
26
222
  value: {}
27
223
  });
224
+ // cached graph — built lazily
225
+ _Job_cachedGraph.set(this, void 0);
226
+ _Job_cachedLeafSteps.set(this, void 0);
28
227
  __classPrivateFieldSet(this, _Job_id, id, "f");
29
228
  __classPrivateFieldSet(this, _Job_config, config, "f");
30
229
  if (init?.steps) {
31
230
  for (const s of init.steps) {
32
- if (s instanceof StepGroup) {
33
- __classPrivateFieldGet(this, _Job_leafSteps, "f").push(...s.all);
34
- }
35
- else {
36
- __classPrivateFieldGet(this, _Job_leafSteps, "f").push(s);
37
- }
231
+ __classPrivateFieldGet(this, _Job_leafItems, "f").push(s);
38
232
  }
39
233
  }
40
234
  if (init?.outputs) {
235
+ const outputs = this.outputs;
41
236
  for (const [name, stepOutput] of Object.entries(init.outputs)) {
42
237
  __classPrivateFieldGet(this, _Job_outputDefs, "f")[name] = stepOutput;
43
- this.outputs[name] = new ExpressionValue(`needs.${__classPrivateFieldGet(this, _Job_id, "f")}.outputs.${name}`, this);
238
+ outputs[name] = new ExpressionValue(`needs.${__classPrivateFieldGet(this, _Job_id, "f")}.outputs.${name}`, this);
44
239
  }
45
240
  }
46
241
  }
@@ -48,27 +243,8 @@ export class Job {
48
243
  return __classPrivateFieldGet(this, _Job_id, "f");
49
244
  }
50
245
  resolveSteps() {
51
- // collect all reachable steps from leaves
52
- const allSteps = new Set();
53
- const collect = (s) => {
54
- if (allSteps.has(s))
55
- return;
56
- allSteps.add(s);
57
- for (const dep of s.dependencies) {
58
- collect(dep);
59
- }
60
- // also collect steps referenced in if-conditions
61
- if (s.config.if instanceof Condition) {
62
- for (const source of s.config.if.sources) {
63
- if (source instanceof Step) {
64
- collect(source);
65
- }
66
- }
67
- }
68
- };
69
- for (const leaf of __classPrivateFieldGet(this, _Job_leafSteps, "f")) {
70
- collect(leaf);
71
- }
246
+ const { graph, leafSteps } = __classPrivateFieldGet(this, _Job_instances, "m", _Job_buildGraph).call(this);
247
+ const allSteps = new Set(graph.keys());
72
248
  // compute priority: each step gets the minimum leaf index of any
73
249
  // leaf step that transitively depends on it (directly or via
74
250
  // condition sources). This makes the topo sort respect steps order.
@@ -78,30 +254,21 @@ export class Job {
78
254
  if (current !== undefined && current <= p)
79
255
  return;
80
256
  priority.set(s, p);
81
- for (const dep of s.dependencies) {
257
+ const entry = graph.get(s);
258
+ if (!entry)
259
+ return;
260
+ for (const dep of entry.deps) {
82
261
  if (allSteps.has(dep)) {
83
262
  assignPriority(dep, p);
84
263
  }
85
264
  }
86
- if (s.config.if instanceof Condition) {
87
- for (const source of s.config.if.sources) {
88
- if (source instanceof Step && allSteps.has(source)) {
89
- assignPriority(source, p);
90
- }
91
- }
92
- }
93
265
  };
94
- for (let i = 0; i < __classPrivateFieldGet(this, _Job_leafSteps, "f").length; i++) {
95
- assignPriority(__classPrivateFieldGet(this, _Job_leafSteps, "f")[i], i);
266
+ for (let i = 0; i < leafSteps.length; i++) {
267
+ assignPriority(leafSteps[i], i);
96
268
  }
97
- const sorted = topoSort(allSteps, priority);
98
- // set job reference on each resolved step for cross-job needs inference
99
- for (const s of sorted) {
100
- s._job = this;
101
- }
102
- return sorted;
269
+ return topoSort(allSteps, priority, graph);
103
270
  }
104
- inferNeeds() {
271
+ inferNeeds(stepOwners) {
105
272
  const config = __classPrivateFieldGet(this, _Job_config, "f");
106
273
  const jobSources = new Set();
107
274
  // explicit needs
@@ -136,15 +303,14 @@ export class Job {
136
303
  if (config.strategy?.failFast != null) {
137
304
  collectJobSources(config.strategy.failFast, jobSources);
138
305
  }
139
- // collect from all step configs
140
- for (const s of __classPrivateFieldGet(this, _Job_leafSteps, "f")) {
141
- collectJobSourcesFromStep(s, jobSources);
142
- }
306
+ // collect from all steps in the graph
307
+ const { graph } = __classPrivateFieldGet(this, _Job_instances, "m", _Job_buildGraph).call(this);
308
+ collectJobSourcesFromGraph(graph, jobSources, stepOwners);
143
309
  }
144
310
  // filter out self-references (can happen with cross-job deps in the same job)
145
311
  return [...jobSources].filter((j) => j !== this);
146
312
  }
147
- toYaml() {
313
+ toYaml(stepOwners) {
148
314
  const config = __classPrivateFieldGet(this, _Job_config, "f");
149
315
  const result = {};
150
316
  if (config.name != null) {
@@ -152,7 +318,7 @@ export class Job {
152
318
  ? config.name.toString()
153
319
  : config.name;
154
320
  }
155
- const needs = this.inferNeeds();
321
+ const needs = this.inferNeeds(stepOwners);
156
322
  if (needs.length > 0) {
157
323
  result.needs = needs.map((j) => j.id);
158
324
  }
@@ -261,110 +427,64 @@ export class Job {
261
427
  result.outputs = outputs;
262
428
  }
263
429
  // steps
430
+ const { graph } = __classPrivateFieldGet(this, _Job_instances, "m", _Job_buildGraph).call(this);
264
431
  const resolvedSteps = this.resolveSteps();
265
- const effectiveConditions = computeEffectiveConditions(resolvedSteps, __classPrivateFieldGet(this, _Job_leafSteps, "f"));
432
+ const effectiveConditions = computeEffectiveConditions(resolvedSteps, graph);
266
433
  result.steps = resolvedSteps.map((s) => {
267
434
  return s.toYaml(effectiveConditions.get(s));
268
435
  });
269
436
  return result;
270
437
  }
271
438
  }
272
- _Job_id = new WeakMap(), _Job_config = new WeakMap(), _Job_leafSteps = new WeakMap(), _Job_outputDefs = new WeakMap();
273
- // --- condition propagation ---
274
- function computeEffectiveConditions(sortedSteps, leafSteps) {
275
- const posMap = new Map();
276
- for (let i = 0; i < sortedSteps.length; i++) {
277
- posMap.set(sortedSteps[i], i);
278
- }
279
- // build dependents map: for each step, which steps depend on it
280
- const dependents = new Map();
281
- const addDependent = (dep, s) => {
282
- let set = dependents.get(dep);
283
- if (!set) {
284
- set = new Set();
285
- dependents.set(dep, set);
286
- }
287
- set.add(s);
288
- };
289
- for (const s of sortedSteps) {
290
- for (const dep of s.dependencies) {
291
- if (posMap.has(dep)) {
292
- addDependent(dep, s);
293
- }
294
- }
295
- // condition-inferred dependencies (matches topo sort edges)
296
- if (s.config.if instanceof Condition) {
297
- for (const source of s.config.if.sources) {
298
- if (source instanceof Step && posMap.has(source)) {
299
- addDependent(source, s);
300
- }
301
- }
302
- }
303
- }
304
- // steps explicitly passed to steps should not receive propagated
305
- // conditions — the user declared them directly, so they keep their own if
306
- const leafSet = new Set(leafSteps);
307
- // compute effective conditions in reverse topo order
439
+ _Job_id = new WeakMap(), _Job_config = new WeakMap(), _Job_leafItems = new WeakMap(), _Job_outputDefs = new WeakMap(), _Job_cachedGraph = new WeakMap(), _Job_cachedLeafSteps = new WeakMap(), _Job_instances = new WeakSet(), _Job_buildGraph = function _Job_buildGraph() {
440
+ if (__classPrivateFieldGet(this, _Job_cachedGraph, "f") && __classPrivateFieldGet(this, _Job_cachedLeafSteps, "f")) {
441
+ return { graph: __classPrivateFieldGet(this, _Job_cachedGraph, "f"), leafSteps: __classPrivateFieldGet(this, _Job_cachedLeafSteps, "f") };
442
+ }
443
+ const graph = new Map();
444
+ const leafSteps = [];
445
+ const deferredAfterDeps = [];
446
+ for (const item of __classPrivateFieldGet(this, _Job_leafItems, "f")) {
447
+ flattenStepLike(item, graph, true, leafSteps, deferredAfterDeps);
448
+ }
449
+ addConditionSourceDeps(graph);
450
+ // resolve deferred after-deps: only add ordering edges for steps
451
+ // already present in the graph (comesAfter does not pull in steps)
452
+ for (const { step, target } of deferredAfterDeps) {
453
+ const entry = graph.get(step);
454
+ for (const t of unwrapSteps(target)) {
455
+ if (graph.has(t))
456
+ entry.afterDeps.add(t);
457
+ }
458
+ }
459
+ __classPrivateFieldSet(this, _Job_cachedGraph, graph, "f");
460
+ __classPrivateFieldSet(this, _Job_cachedLeafSteps, leafSteps, "f");
461
+ return { graph, leafSteps };
462
+ };
463
+ // --- effective conditions ---
464
+ /**
465
+ * Computes effective conditions for all steps. Each step's effective condition
466
+ * is the combination of its collected context conditions (OR'd together,
467
+ * simplified) AND'd with its intrinsic config.if.
468
+ *
469
+ * Context conditions are collected during the tree walk — they flow DOWN
470
+ * from parent groups and StepRef conditions through dependencies, so shared
471
+ * top-level conditions like `!(matrix.skip)` naturally stay factored out.
472
+ */
473
+ function computeEffectiveConditions(steps, graph) {
308
474
  const effective = new Map();
309
- for (let i = sortedSteps.length - 1; i >= 0; i--) {
310
- const s = sortedSteps[i];
311
- const ownIf = s.config.if != null ? toCondition(s.config.if) : undefined;
312
- if (leafSet.has(s)) {
313
- // explicitly added by user no propagation
314
- effective.set(s, ownIf);
315
- continue;
316
- }
317
- const deps = dependents.get(s);
318
- if (!deps || deps.size === 0) {
319
- effective.set(s, ownIf);
320
- continue;
321
- }
322
- // collect propagatable conditions from dependents
323
- const depConditions = [];
324
- let mustAlwaysRun = false;
325
- for (const d of deps) {
326
- const dEffective = effective.get(d);
327
- if (dEffective == null) {
328
- // dependent has no effective condition — step must always run
329
- mustAlwaysRun = true;
330
- break;
331
- }
332
- // check if the condition can propagate to this position
333
- if (!canPropagateTo(dEffective, i, posMap)) {
334
- // condition references steps at or after this position
335
- mustAlwaysRun = true;
336
- break;
337
- }
338
- depConditions.push(dEffective);
339
- }
340
- const propagated = mustAlwaysRun
341
- ? undefined
342
- : simplifyOrConditions(depConditions);
343
- if (mustAlwaysRun) {
344
- effective.set(s, ownIf);
345
- }
346
- else if (propagated != null && ownIf != null) {
347
- effective.set(s, deduplicateAndTerms(propagated.and(ownIf)));
475
+ for (const s of steps) {
476
+ const entry = graph.get(s);
477
+ const ctx = combineContexts(entry);
478
+ const configIf = s.config.if != null ? toCondition(s.config.if) : undefined;
479
+ if (ctx != null && configIf != null) {
480
+ effective.set(s, deduplicateAndTerms(ctx.and(configIf)));
348
481
  }
349
482
  else {
350
- effective.set(s, propagated ?? ownIf);
483
+ effective.set(s, ctx ?? configIf);
351
484
  }
352
485
  }
353
486
  return effective;
354
487
  }
355
- // a condition can propagate backward to a step at targetPos only if none of
356
- // the condition's Step sources are at or after that position
357
- function canPropagateTo(condition, targetPos, posMap) {
358
- for (const source of condition.sources) {
359
- if (source instanceof Step) {
360
- const pos = posMap.get(source);
361
- if (pos !== undefined && pos >= targetPos) {
362
- return false;
363
- }
364
- }
365
- }
366
- return true;
367
- }
368
488
  // --- condition simplification ---
369
489
  /**
370
490
  * Simplifies an array of conditions that will be OR'd together:
@@ -606,26 +726,18 @@ function extractCommonFactors(terms) {
606
726
  return result;
607
727
  }
608
728
  // --- topological sort ---
609
- function topoSort(steps, priority) {
729
+ function topoSort(steps, priority, graph) {
610
730
  // build in-degree map (only counting unique predecessors within our set)
611
731
  const inDegree = new Map();
612
732
  for (const s of steps) {
733
+ const entry = graph.get(s);
613
734
  const predecessors = new Set();
614
- for (const dep of s.dependencies) {
735
+ for (const dep of entry.deps) {
615
736
  if (steps.has(dep)) {
616
737
  predecessors.add(dep);
617
738
  }
618
739
  }
619
- // also count condition-inferred deps (deduplicated via Set)
620
- if (s.config.if instanceof Condition) {
621
- for (const source of s.config.if.sources) {
622
- if (source instanceof Step && steps.has(source)) {
623
- predecessors.add(source);
624
- }
625
- }
626
- }
627
- // also count comesAfter ordering deps
628
- for (const dep of s.comesAfterDeps) {
740
+ for (const dep of entry.afterDeps) {
629
741
  if (steps.has(dep)) {
630
742
  predecessors.add(dep);
631
743
  }
@@ -663,31 +775,9 @@ function topoSort(steps, priority) {
663
775
  for (const s of allSteps) {
664
776
  if (s === current)
665
777
  continue;
666
- let isSuccessor = false;
667
- for (const dep of s.dependencies) {
668
- if (dep === current) {
669
- isSuccessor = true;
670
- break;
671
- }
672
- }
673
- // check condition sources too
674
- if (!isSuccessor && s.config.if instanceof Condition) {
675
- for (const source of s.config.if.sources) {
676
- if (source === current) {
677
- isSuccessor = true;
678
- break;
679
- }
680
- }
681
- }
682
- // check comesAfter deps (s.comesAfter(current) means s comes after current)
683
- if (!isSuccessor) {
684
- for (const dep of s.comesAfterDeps) {
685
- if (dep === current) {
686
- isSuccessor = true;
687
- break;
688
- }
689
- }
690
- }
778
+ const entry = graph.get(s);
779
+ const isSuccessor = entry.deps.has(current) ||
780
+ entry.afterDeps.has(current);
691
781
  if (isSuccessor) {
692
782
  const newDeg = (inDegree.get(s) ?? 0) - 1;
693
783
  inDegree.set(s, newDeg);
@@ -716,7 +806,7 @@ function topoSort(steps, priority) {
716
806
  if (!resultSet.has(s))
717
807
  remaining.add(s);
718
808
  }
719
- const cyclePath = findCyclePath(remaining);
809
+ const cyclePath = findCyclePath(remaining, graph);
720
810
  throw new Error(`Cycle detected in step ordering: ${cyclePath.map(stepLabel).join(" → ")}`);
721
811
  }
722
812
  return result;
@@ -725,29 +815,22 @@ function stepLabel(s) {
725
815
  return s.config.name ?? s.config.uses ?? s.id;
726
816
  }
727
817
  /** DFS on the remaining (unsorted) steps to find and return one cycle. */
728
- function findCyclePath(remaining) {
818
+ function findCyclePath(remaining, graph) {
729
819
  // build successor map within remaining steps
730
820
  const successors = new Map();
731
821
  for (const s of remaining) {
732
822
  successors.set(s, []);
733
823
  }
734
824
  for (const s of remaining) {
735
- // dependsOn edges: s depends on dep → dep is predecessor of s
736
- for (const dep of s.dependencies) {
825
+ const entry = graph.get(s);
826
+ // deps: s depends on dep → dep is predecessor of s
827
+ for (const dep of entry.deps) {
737
828
  if (remaining.has(dep)) {
738
829
  successors.get(dep).push(s);
739
830
  }
740
831
  }
741
- // condition-source edges
742
- if (s.config.if instanceof Condition) {
743
- for (const source of s.config.if.sources) {
744
- if (source instanceof Step && remaining.has(source)) {
745
- successors.get(source).push(s);
746
- }
747
- }
748
- }
749
- // comesAfter edges: s.comesAfter(dep) → dep is predecessor of s
750
- for (const dep of s.comesAfterDeps) {
832
+ // afterDeps: s comesAfter dep → dep is predecessor of s
833
+ for (const dep of entry.afterDeps) {
751
834
  if (remaining.has(dep)) {
752
835
  successors.get(dep).push(s);
753
836
  }
@@ -821,24 +904,25 @@ function collectJobSources(value, out) {
821
904
  }
822
905
  }
823
906
  }
824
- function collectJobSourcesFromStep(s, out, visited = new Set()) {
825
- if (visited.has(s))
826
- return;
827
- visited.add(s);
828
- collectJobSources(s.config.if, out);
829
- if (s.config.with)
830
- collectJobSources(s.config.with, out);
831
- if (s.config.env)
832
- collectJobSources(s.config.env, out);
833
- // check cross-job step dependencies (e.g., artifact download → upload)
834
- for (const dep of s._crossJobDeps) {
835
- if (dep._job instanceof Job) {
836
- out.add(dep._job);
837
- }
838
- }
839
- // walk dependencies recursively
840
- for (const dep of s.dependencies) {
841
- collectJobSourcesFromStep(dep, out, visited);
907
+ function collectJobSourcesFromGraph(graph, out, stepOwners) {
908
+ for (const [step, entry] of graph) {
909
+ collectJobSources(step.config.if, out);
910
+ for (const ctx of entry.contexts) {
911
+ collectJobSources(ctx, out);
912
+ }
913
+ if (step.config.with)
914
+ collectJobSources(step.config.with, out);
915
+ if (step.config.env)
916
+ collectJobSources(step.config.env, out);
917
+ if (stepOwners) {
918
+ for (const dep of step._crossJobDeps) {
919
+ const owners = stepOwners.get(dep);
920
+ if (owners) {
921
+ for (const j of owners)
922
+ out.add(j);
923
+ }
924
+ }
925
+ }
842
926
  }
843
927
  }
844
928
  function serializeService(svc) {
@@ -900,7 +984,7 @@ export function job(id, config) {
900
984
  }
901
985
  const { id: _id, steps, outputs, ...jobConfig } = config;
902
986
  return new Job(id, jobConfig, {
903
- steps: steps instanceof StepGroup ? [steps] : steps,
987
+ steps: Array.isArray(steps) ? steps : [steps],
904
988
  outputs,
905
989
  });
906
990
  }
package/esm/mod.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./_dnt.polyfills.js";
2
- export { Step, step, StepGroup, steps } from "./step.js";
2
+ export { Step, step, StepRef } from "./step.js";
3
3
  export type { ConditionLike, ConfigValue, StepConfig, StepLike, } from "./step.js";
4
4
  export { Job, job } from "./job.js";
5
5
  export type { JobConfig, JobDef, ReusableJobConfig, ReusableJobDef, ServiceContainer, StepsJobConfig, StepsJobDef, } from "./job.js";
package/esm/mod.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AACzD,YAAY,EACV,aAAa,EACb,WAAW,EACX,UAAU,EACV,QAAQ,GACT,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,YAAY,EACV,SAAS,EACT,MAAM,EACN,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,WAAW,GACZ,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACpE,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,SAAS,EACT,UAAU,EACV,aAAa,EACb,IAAI,EACJ,eAAe,EACf,WAAW,GACZ,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACnD,YAAY,EACV,eAAe,EACf,WAAW,EACX,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACzD,YAAY,EACV,eAAe,EACf,cAAc,EACd,YAAY,GACb,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAChD,YAAY,EACV,aAAa,EACb,WAAW,EACX,UAAU,EACV,QAAQ,GACT,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AACpC,YAAY,EACV,SAAS,EACT,MAAM,EACN,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,WAAW,GACZ,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACpE,YAAY,EACV,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,cAAc,EACd,gBAAgB,GACjB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,SAAS,EACT,UAAU,EACV,aAAa,EACb,IAAI,EACJ,eAAe,EACf,WAAW,GACZ,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACnD,YAAY,EACV,eAAe,EACf,WAAW,EACX,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACzD,YAAY,EACV,eAAe,EACf,cAAc,EACd,YAAY,GACb,MAAM,eAAe,CAAC"}
package/esm/mod.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./_dnt.polyfills.js";
2
- export { Step, step, StepGroup, steps } from "./step.js";
2
+ export { Step, step, StepRef } from "./step.js";
3
3
  export { Job, job } from "./job.js";
4
4
  export { createWorkflow, isLinting, Workflow } from "./workflow.js";
5
5
  export { Condition, conditions, ElseIfBuilder, expr, ExpressionValue, ThenBuilder, } from "./expression.js";
package/esm/step.d.ts CHANGED
@@ -2,48 +2,63 @@ import { Condition, type ExpressionSource, ExpressionValue } from "./expression.
2
2
  export type ConditionLike = Condition | ExpressionValue | string;
3
3
  export type ConfigValue = string | number | boolean | ExpressionValue;
4
4
  export interface StepConfig<O extends string = never> {
5
- name?: string;
6
- id?: string;
7
- uses?: string;
8
- run?: string | string[];
9
- with?: Record<string, ConfigValue>;
10
- env?: Record<string, ConfigValue>;
11
- if?: ConditionLike;
12
- shell?: string;
13
- workingDirectory?: string;
14
- continueOnError?: boolean | string;
15
- timeoutMinutes?: number;
16
- outputs?: readonly O[];
5
+ readonly name?: string;
6
+ readonly id?: string;
7
+ readonly uses?: string;
8
+ readonly run?: string | string[];
9
+ readonly with?: Readonly<Record<string, ConfigValue>>;
10
+ readonly env?: Readonly<Record<string, ConfigValue>>;
11
+ readonly if?: ConditionLike;
12
+ readonly shell?: string;
13
+ readonly workingDirectory?: string;
14
+ readonly continueOnError?: boolean | string;
15
+ readonly timeoutMinutes?: number;
16
+ readonly outputs?: readonly O[];
17
17
  }
18
18
  export declare function resetStepCounter(): void;
19
- export type StepLike = Step<string> | StepGroup;
19
+ export type StepLike = Step<string> | StepRef<string>;
20
20
  export declare class Step<O extends string = never> implements ExpressionSource {
21
21
  #private;
22
22
  readonly config: StepConfig<O>;
23
- readonly dependencies: Step<string>[];
24
- readonly comesAfterDeps: Step<string>[];
25
23
  readonly outputs: {
26
24
  [K in O]: ExpressionValue;
27
25
  };
28
- readonly _crossJobDeps: Step<string>[];
29
- _job?: ExpressionSource;
30
- constructor(config: StepConfig<O>);
26
+ readonly _crossJobDeps: readonly Step<string>[];
27
+ readonly children: readonly StepLike[];
28
+ constructor(config: StepConfig<O>, crossJobDeps?: Step<string>[]);
29
+ constructor(children: readonly StepLike[]);
31
30
  get id(): string;
32
- dependsOn(...deps: StepLike[]): this;
33
- comesAfter(...deps: StepLike[]): this;
34
- if(condition: ConditionLike): this;
31
+ dependsOn(...deps: StepLike[]): StepRef<O>;
32
+ comesAfter(...deps: StepLike[]): StepRef<O>;
33
+ if(condition: ConditionLike): StepRef<O>;
35
34
  toYaml(effectiveIf?: Condition): Record<string, unknown>;
36
35
  }
37
36
  export declare function step<const O extends string = never>(config: StepConfig<O>): Step<O>;
37
+ export declare function step(first: Step<string> | StepRef<string> | StepConfig, second: Step<string> | StepRef<string> | StepConfig, ...rest: (Step<string> | StepRef<string> | StepConfig)[]): Step<never>;
38
+ export declare class StepRef<O extends string = never> {
39
+ readonly step: Step<O>;
40
+ readonly condition?: ConditionLike;
41
+ readonly dependencies: readonly StepLike[];
42
+ readonly afterDependencies: readonly StepLike[];
43
+ constructor(step: Step<O>, init?: {
44
+ condition?: ConditionLike;
45
+ dependencies?: readonly StepLike[];
46
+ afterDependencies?: readonly StepLike[];
47
+ });
48
+ get id(): string;
49
+ get config(): StepConfig<O>;
50
+ get outputs(): {
51
+ [K in O]: ExpressionValue;
52
+ };
53
+ dependsOn(...deps: StepLike[]): StepRef<O>;
54
+ comesAfter(...deps: StepLike[]): StepRef<O>;
55
+ if(condition: ConditionLike): StepRef<O>;
56
+ }
38
57
  export declare function serializeConditionLike(c: ConditionLike): string;
39
58
  export declare function toCondition(c: ConditionLike): Condition;
40
59
  export declare function serializeConfigValues(record: Record<string, ConfigValue>): Record<string, string | number | boolean>;
41
- export declare class StepGroup {
42
- readonly all: Step<string>[];
43
- constructor(steps: Step<string>[]);
44
- if(condition: ConditionLike): this;
45
- dependsOn(...deps: StepLike[]): this;
46
- comesAfter(...deps: StepLike[]): this;
47
- }
48
- export declare function steps(...items: (Step<string> | StepGroup | StepConfig)[]): StepGroup;
60
+ /** Extracts the underlying Step from a StepLike (Step or StepRef). */
61
+ export declare function unwrapStep(item: Step<string> | StepRef<string>): Step<string>;
62
+ /** Extracts all underlying leaf Steps from a StepLike (recursively for composites). */
63
+ export declare function unwrapSteps(item: StepLike): Step<string>[];
49
64
  //# sourceMappingURL=step.d.ts.map
package/esm/step.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../src/step.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../src/step.ts"],"names":[],"mappings":"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"}
package/esm/step.js CHANGED
@@ -17,7 +17,7 @@ export function resetStepCounter() {
17
17
  stepCounter = 0;
18
18
  }
19
19
  export class Step {
20
- constructor(config) {
20
+ constructor(configOrChildren, crossJobDeps) {
21
21
  _Step_id.set(this, void 0);
22
22
  Object.defineProperty(this, "config", {
23
23
  enumerable: true,
@@ -25,18 +25,6 @@ export class Step {
25
25
  writable: true,
26
26
  value: void 0
27
27
  });
28
- Object.defineProperty(this, "dependencies", {
29
- enumerable: true,
30
- configurable: true,
31
- writable: true,
32
- value: []
33
- });
34
- Object.defineProperty(this, "comesAfterDeps", {
35
- enumerable: true,
36
- configurable: true,
37
- writable: true,
38
- value: []
39
- });
40
28
  Object.defineProperty(this, "outputs", {
41
29
  enumerable: true,
42
30
  configurable: true,
@@ -48,20 +36,33 @@ export class Step {
48
36
  enumerable: true,
49
37
  configurable: true,
50
38
  writable: true,
51
- value: []
39
+ value: void 0
52
40
  });
53
- // set by Job.resolveSteps() the job that owns this step
54
- Object.defineProperty(this, "_job", {
41
+ Object.defineProperty(this, "children", {
55
42
  enumerable: true,
56
43
  configurable: true,
57
44
  writable: true,
58
45
  value: void 0
59
46
  });
47
+ if (Array.isArray(configOrChildren)) {
48
+ // composite step (group of children)
49
+ if (configOrChildren.length === 0) {
50
+ throw new Error("step() requires at least one step");
51
+ }
52
+ __classPrivateFieldSet(this, _Step_id, `_step_${stepCounter++}`, "f");
53
+ this.config = {};
54
+ this._crossJobDeps = Object.freeze([]);
55
+ this.outputs = {};
56
+ this.children = Object.freeze([...configOrChildren]);
57
+ return;
58
+ }
59
+ const config = configOrChildren;
60
60
  if (config.outputs?.length && !config.id) {
61
61
  throw new Error("Step with outputs must have an explicit id");
62
62
  }
63
63
  __classPrivateFieldSet(this, _Step_id, config.id ?? `_step_${stepCounter++}`, "f");
64
64
  this.config = config;
65
+ this._crossJobDeps = Object.freeze(crossJobDeps ?? []);
65
66
  // build typed outputs
66
67
  const outputs = {};
67
68
  if (config.outputs) {
@@ -71,41 +72,19 @@ export class Step {
71
72
  }
72
73
  }
73
74
  this.outputs = outputs;
75
+ this.children = Object.freeze([]);
74
76
  }
75
77
  get id() {
76
78
  return __classPrivateFieldGet(this, _Step_id, "f");
77
79
  }
78
80
  dependsOn(...deps) {
79
- for (const d of deps) {
80
- if (d instanceof StepGroup) {
81
- this.dependencies.push(...d.all);
82
- }
83
- else {
84
- this.dependencies.push(d);
85
- }
86
- }
87
- return this;
81
+ return new StepRef(this, { dependencies: deps });
88
82
  }
89
83
  comesAfter(...deps) {
90
- for (const d of deps) {
91
- if (d instanceof StepGroup) {
92
- this.comesAfterDeps.push(...d.all);
93
- }
94
- else {
95
- this.comesAfterDeps.push(d);
96
- }
97
- }
98
- return this;
84
+ return new StepRef(this, { afterDependencies: deps });
99
85
  }
100
86
  if(condition) {
101
- const cond = toCondition(condition);
102
- if (this.config.if != null) {
103
- this.config.if = cond.and(toCondition(this.config.if));
104
- }
105
- else {
106
- this.config.if = cond;
107
- }
108
- return this;
87
+ return new StepRef(this, { condition });
109
88
  }
110
89
  toYaml(effectiveIf) {
111
90
  const result = {};
@@ -150,8 +129,86 @@ export class Step {
150
129
  }
151
130
  }
152
131
  _Step_id = new WeakMap();
153
- export function step(config) {
154
- return new Step(config);
132
+ export function step(...args) {
133
+ if (args.length === 1) {
134
+ return new Step(args[0]);
135
+ }
136
+ const children = [];
137
+ for (const item of args) {
138
+ if (item instanceof Step || item instanceof StepRef) {
139
+ children.push(item);
140
+ }
141
+ else {
142
+ children.push(new Step(item));
143
+ }
144
+ }
145
+ return new Step(children);
146
+ }
147
+ // --- StepRef: immutable wrapper for per-usage deps/conditions ---
148
+ export class StepRef {
149
+ constructor(step, init) {
150
+ Object.defineProperty(this, "step", {
151
+ enumerable: true,
152
+ configurable: true,
153
+ writable: true,
154
+ value: void 0
155
+ });
156
+ Object.defineProperty(this, "condition", {
157
+ enumerable: true,
158
+ configurable: true,
159
+ writable: true,
160
+ value: void 0
161
+ });
162
+ Object.defineProperty(this, "dependencies", {
163
+ enumerable: true,
164
+ configurable: true,
165
+ writable: true,
166
+ value: void 0
167
+ });
168
+ Object.defineProperty(this, "afterDependencies", {
169
+ enumerable: true,
170
+ configurable: true,
171
+ writable: true,
172
+ value: void 0
173
+ });
174
+ this.step = step;
175
+ this.condition = init?.condition;
176
+ this.dependencies = init?.dependencies ?? [];
177
+ this.afterDependencies = init?.afterDependencies ?? [];
178
+ }
179
+ get id() {
180
+ return this.step.id;
181
+ }
182
+ get config() {
183
+ return this.step.config;
184
+ }
185
+ get outputs() {
186
+ return this.step.outputs;
187
+ }
188
+ dependsOn(...deps) {
189
+ return new StepRef(this.step, {
190
+ condition: this.condition,
191
+ dependencies: [...this.dependencies, ...deps],
192
+ afterDependencies: this.afterDependencies,
193
+ });
194
+ }
195
+ comesAfter(...deps) {
196
+ return new StepRef(this.step, {
197
+ condition: this.condition,
198
+ dependencies: this.dependencies,
199
+ afterDependencies: [...this.afterDependencies, ...deps],
200
+ });
201
+ }
202
+ if(condition) {
203
+ const newCond = this.condition != null
204
+ ? toCondition(condition).and(toCondition(this.condition))
205
+ : condition;
206
+ return new StepRef(this.step, {
207
+ condition: newCond,
208
+ dependencies: this.dependencies,
209
+ afterDependencies: this.afterDependencies,
210
+ });
211
+ }
155
212
  }
156
213
  // --- serialization helpers ---
157
214
  export function serializeConditionLike(c) {
@@ -180,51 +237,16 @@ export function serializeConfigValues(record) {
180
237
  }
181
238
  return result;
182
239
  }
183
- // --- step group ---
184
- export class StepGroup {
185
- constructor(steps) {
186
- Object.defineProperty(this, "all", {
187
- enumerable: true,
188
- configurable: true,
189
- writable: true,
190
- value: void 0
191
- });
192
- this.all = steps;
193
- }
194
- if(condition) {
195
- for (const s of this.all) {
196
- s.if(condition);
197
- }
198
- return this;
199
- }
200
- dependsOn(...deps) {
201
- for (const s of this.all) {
202
- s.dependsOn(...deps);
203
- }
204
- return this;
205
- }
206
- comesAfter(...deps) {
207
- for (const s of this.all) {
208
- s.comesAfter(...deps);
209
- }
210
- return this;
211
- }
240
+ // --- helpers ---
241
+ /** Extracts the underlying Step from a StepLike (Step or StepRef). */
242
+ export function unwrapStep(item) {
243
+ return item instanceof StepRef ? item.step : item;
212
244
  }
213
- export function steps(...items) {
214
- if (items.length === 0) {
215
- throw new Error("steps() requires at least one step");
216
- }
217
- const created = [];
218
- for (const item of items) {
219
- if (item instanceof StepGroup) {
220
- created.push(...item.all);
221
- }
222
- else if (item instanceof Step) {
223
- created.push(item);
224
- }
225
- else {
226
- created.push(new Step(item));
227
- }
245
+ /** Extracts all underlying leaf Steps from a StepLike (recursively for composites). */
246
+ export function unwrapSteps(item) {
247
+ const s = unwrapStep(item);
248
+ if (s.children.length > 0) {
249
+ return s.children.flatMap(unwrapSteps);
228
250
  }
229
- return new StepGroup(created);
251
+ return [s];
230
252
  }
@@ -1 +1 @@
1
- {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../src/workflow.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../src/workflow.ts"],"names":[],"mappings":"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"}
package/esm/workflow.js CHANGED
@@ -63,14 +63,22 @@ export class Workflow {
63
63
  }
64
64
  obj.env = env;
65
65
  }
66
- // pre-resolve all jobs to establish step→job mappings for cross-job deps
66
+ // pre-resolve all jobs and build step→job mapping for cross-job deps
67
+ const stepOwners = new Map();
67
68
  for (const job of __classPrivateFieldGet(this, _Workflow_jobs, "f").values()) {
68
- job.resolveSteps();
69
+ for (const s of job.resolveSteps()) {
70
+ let owners = stepOwners.get(s);
71
+ if (!owners) {
72
+ owners = [];
73
+ stepOwners.set(s, owners);
74
+ }
75
+ owners.push(job);
76
+ }
69
77
  }
70
78
  // jobs
71
79
  const jobs = {};
72
80
  for (const [id, job] of __classPrivateFieldGet(this, _Workflow_jobs, "f")) {
73
- jobs[id] = job.toYaml();
81
+ jobs[id] = job.toYaml(stepOwners);
74
82
  }
75
83
  obj.jobs = jobs;
76
84
  const yaml = stringify(obj, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gagen",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Generate complex GitHub Actions YAML files using a declarative API.",
5
5
  "repository": {
6
6
  "type": "git",