@kitsi/action 0.0.16 → 0.0.18

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.
Files changed (2) hide show
  1. package/dist/index.js +153 -24
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -99672,7 +99672,7 @@ var require_fxp2 = __commonJS((exports, module) => {
99672
99672
  });
99673
99673
 
99674
99674
  // ../../node_modules/.bun/picomatch@4.0.3/node_modules/picomatch/lib/constants.js
99675
- var require_constants14 = __commonJS((exports, module2) => {
99675
+ var require_constants14 = __commonJS((exports, module) => {
99676
99676
  var WIN_SLASH = "\\\\/";
99677
99677
  var WIN_NO_SLASH = `[^${WIN_SLASH}]`;
99678
99678
  var DOT_LITERAL = "\\.";
@@ -99740,7 +99740,7 @@ var require_constants14 = __commonJS((exports, module2) => {
99740
99740
  word: "A-Za-z0-9_",
99741
99741
  xdigit: "A-Fa-f0-9"
99742
99742
  };
99743
- module2.exports = {
99743
+ module.exports = {
99744
99744
  MAX_LENGTH: 1024 * 64,
99745
99745
  POSIX_REGEX_SOURCE,
99746
99746
  REGEX_BACKSLASH: /\\(?![*+?^${}(|)[\]])/g,
@@ -99877,7 +99877,7 @@ var require_utils9 = __commonJS((exports) => {
99877
99877
  });
99878
99878
 
99879
99879
  // ../../node_modules/.bun/picomatch@4.0.3/node_modules/picomatch/lib/scan.js
99880
- var require_scan = __commonJS((exports, module2) => {
99880
+ var require_scan = __commonJS((exports, module) => {
99881
99881
  var utils = require_utils9();
99882
99882
  var {
99883
99883
  CHAR_ASTERISK,
@@ -100188,11 +100188,11 @@ var require_scan = __commonJS((exports, module2) => {
100188
100188
  }
100189
100189
  return state;
100190
100190
  };
100191
- module2.exports = scan;
100191
+ module.exports = scan;
100192
100192
  });
100193
100193
 
100194
100194
  // ../../node_modules/.bun/picomatch@4.0.3/node_modules/picomatch/lib/parse.js
100195
- var require_parse2 = __commonJS((exports, module2) => {
100195
+ var require_parse2 = __commonJS((exports, module) => {
100196
100196
  var constants = require_constants14();
100197
100197
  var utils = require_utils9();
100198
100198
  var {
@@ -100604,11 +100604,11 @@ var require_parse2 = __commonJS((exports, module2) => {
100604
100604
  state.backtrack = true;
100605
100605
  }
100606
100606
  if (brace.comma !== true && brace.dots !== true) {
100607
- const out3 = state.output.slice(0, brace.outputIndex);
100607
+ const out = state.output.slice(0, brace.outputIndex);
100608
100608
  const toks = state.tokens.slice(brace.tokensIndex);
100609
100609
  brace.value = brace.output = "\\{";
100610
100610
  value = output = "\\}";
100611
- state.output = out3;
100611
+ state.output = out;
100612
100612
  for (const t of toks) {
100613
100613
  state.output += t.output || t.value;
100614
100614
  }
@@ -100961,11 +100961,11 @@ var require_parse2 = __commonJS((exports, module2) => {
100961
100961
  }
100962
100962
  return source;
100963
100963
  };
100964
- module2.exports = parse;
100964
+ module.exports = parse;
100965
100965
  });
100966
100966
 
100967
100967
  // ../../node_modules/.bun/picomatch@4.0.3/node_modules/picomatch/lib/picomatch.js
100968
- var require_picomatch = __commonJS((exports, module2) => {
100968
+ var require_picomatch = __commonJS((exports, module) => {
100969
100969
  var scan = require_scan();
100970
100970
  var parse = require_parse2();
100971
100971
  var utils = require_utils9();
@@ -101101,11 +101101,11 @@ var require_picomatch = __commonJS((exports, module2) => {
101101
101101
  }
101102
101102
  };
101103
101103
  picomatch.constants = constants;
101104
- module2.exports = picomatch;
101104
+ module.exports = picomatch;
101105
101105
  });
101106
101106
 
101107
101107
  // ../../node_modules/.bun/picomatch@4.0.3/node_modules/picomatch/index.js
101108
- var require_picomatch2 = __commonJS((exports, module2) => {
101108
+ var require_picomatch2 = __commonJS((exports, module) => {
101109
101109
  var pico = require_picomatch();
101110
101110
  var utils = require_utils9();
101111
101111
  function picomatch(glob3, options, returnState = false) {
@@ -101115,7 +101115,7 @@ var require_picomatch2 = __commonJS((exports, module2) => {
101115
101115
  return pico(glob3, options, returnState);
101116
101116
  }
101117
101117
  Object.assign(picomatch, pico);
101118
- module2.exports = picomatch;
101118
+ module.exports = picomatch;
101119
101119
  });
101120
101120
 
101121
101121
  // src/index.ts
@@ -101569,7 +101569,7 @@ import { pathToFileURL } from "node:url";
101569
101569
  // ../core/dist/version.js
101570
101570
  var VERSION = "0.0.1";
101571
101571
  // ../core/dist/dsl/plan.js
101572
- var clonePlan = (plan, patch) => new PlanBuilder((() => {
101572
+ var clonePlan = (plan, patch) => {
101573
101573
  const next = {
101574
101574
  name: patch.name ?? plan.config.name,
101575
101575
  concurrency: patch.concurrency ?? plan.config.concurrency,
@@ -101578,6 +101578,9 @@ var clonePlan = (plan, patch) => new PlanBuilder((() => {
101578
101578
  const when = patch.when ?? plan.config.when;
101579
101579
  if (when)
101580
101580
  next.when = when;
101581
+ const maxConcurrency = patch.maxConcurrency ?? plan.config.maxConcurrency;
101582
+ if (maxConcurrency !== undefined)
101583
+ next.maxConcurrency = maxConcurrency;
101581
101584
  const matrix = patch.matrix ?? plan.config.matrix;
101582
101585
  if (matrix)
101583
101586
  next.matrix = matrix;
@@ -101587,8 +101590,8 @@ var clonePlan = (plan, patch) => new PlanBuilder((() => {
101587
101590
  const taskFactory = patch.taskFactory ?? plan.config.taskFactory;
101588
101591
  if (taskFactory)
101589
101592
  next.taskFactory = taskFactory;
101590
- return next;
101591
- })());
101593
+ return new PlanBuilder(next);
101594
+ };
101592
101595
 
101593
101596
  class PlanBuilder {
101594
101597
  config;
@@ -101600,6 +101603,8 @@ class PlanBuilder {
101600
101603
  };
101601
101604
  if (config.when)
101602
101605
  next.when = config.when;
101606
+ if (config.maxConcurrency !== undefined)
101607
+ next.maxConcurrency = config.maxConcurrency;
101603
101608
  if (config.matrix)
101604
101609
  next.matrix = config.matrix;
101605
101610
  if (config.params)
@@ -101611,6 +101616,9 @@ class PlanBuilder {
101611
101616
  when(predicate) {
101612
101617
  return clonePlan(this, { when: predicate });
101613
101618
  }
101619
+ maxConcurrency(value) {
101620
+ return clonePlan(this, { maxConcurrency: value });
101621
+ }
101614
101622
  concurrency = {
101615
101623
  group: (fn) => clonePlan(this, { concurrency: { ...this.config.concurrency, group: fn } }),
101616
101624
  cancelInProgress: (value) => clonePlan(this, { concurrency: { ...this.config.concurrency, cancelInProgress: value } })
@@ -101715,7 +101723,11 @@ class TaskBuilder {
101715
101723
  needs(...tasks) {
101716
101724
  const ids = new Set(this.config.needs);
101717
101725
  for (const task of tasks) {
101718
- ids.add(task.config.name);
101726
+ if (typeof task === "string") {
101727
+ ids.add(task);
101728
+ } else {
101729
+ ids.add(task.config.name);
101730
+ }
101719
101731
  }
101720
101732
  return cloneTask(this, { needs: Array.from(ids) });
101721
101733
  }
@@ -104216,6 +104228,58 @@ class UseHandler {
104216
104228
  }
104217
104229
  }
104218
104230
 
104231
+ // ../core/dist/engine/executor/buffering-reporter.js
104232
+ class BufferingReporter {
104233
+ target;
104234
+ taskBuffers = new Map;
104235
+ enableBuffering;
104236
+ constructor(target, enableBuffering) {
104237
+ this.target = target ?? { emit: () => {} };
104238
+ this.enableBuffering = enableBuffering;
104239
+ }
104240
+ setBuffering(enabled) {
104241
+ this.enableBuffering = enabled;
104242
+ }
104243
+ emit(event, data) {
104244
+ if (!this.enableBuffering) {
104245
+ this.target.emit(event, data);
104246
+ return;
104247
+ }
104248
+ const taskName = this.extractTaskName(event, data);
104249
+ if (!taskName || event === "plan_start" || event === "plan_end") {
104250
+ this.target.emit(event, data);
104251
+ return;
104252
+ }
104253
+ if (event === "task_start") {
104254
+ this.taskBuffers.set(taskName, []);
104255
+ }
104256
+ const buffer = this.taskBuffers.get(taskName);
104257
+ if (buffer) {
104258
+ buffer.push({ event, data });
104259
+ } else {
104260
+ this.target.emit(event, data);
104261
+ }
104262
+ if (event === "task_end") {
104263
+ this.flush(taskName);
104264
+ }
104265
+ }
104266
+ extractTaskName(_event, data) {
104267
+ if (typeof data.task === "string") {
104268
+ return data.task;
104269
+ }
104270
+ return null;
104271
+ }
104272
+ flush(taskName) {
104273
+ const buffer = this.taskBuffers.get(taskName);
104274
+ if (!buffer)
104275
+ return;
104276
+ for (const bufferedEvent of buffer) {
104277
+ this.target.emit(bufferedEvent.event, bufferedEvent.data);
104278
+ }
104279
+ this.taskBuffers.delete(taskName);
104280
+ }
104281
+ }
104282
+
104219
104283
  // ../core/dist/engine/executor/command-runner.js
104220
104284
  import { spawn } from "node:child_process";
104221
104285
  class CommandRunner {
@@ -104434,6 +104498,7 @@ class PlanRunner {
104434
104498
  params;
104435
104499
  logger;
104436
104500
  failFast;
104501
+ maxConcurrencyOverride;
104437
104502
  reporter;
104438
104503
  signal;
104439
104504
  states = new Map;
@@ -104444,6 +104509,7 @@ class PlanRunner {
104444
104509
  opHandlers;
104445
104510
  cache;
104446
104511
  expandedTasks = null;
104512
+ taskPromises = new Map;
104447
104513
  constructor(plan2, opts) {
104448
104514
  this.plan = plan2;
104449
104515
  this.workspace = opts.workspace;
@@ -104452,7 +104518,8 @@ class PlanRunner {
104452
104518
  this.params = opts.params ?? {};
104453
104519
  this.logger = opts.logger;
104454
104520
  this.failFast = opts.failFast;
104455
- this.reporter = opts.reporter;
104521
+ this.maxConcurrencyOverride = opts.maxConcurrency;
104522
+ this.reporter = new BufferingReporter(opts.reporter, false);
104456
104523
  this.signal = opts.signal;
104457
104524
  this.resolver = new ValueResolver(this.states, this.params, this.secrets);
104458
104525
  this.commandRunner = new CommandRunner({
@@ -104508,15 +104575,22 @@ class PlanRunner {
104508
104575
  }
104509
104576
  const tasks = this.plan.expand();
104510
104577
  this.expandedTasks = tasks;
104578
+ const maxConcurrency = this.maxConcurrencyOverride ?? this.plan.config.maxConcurrency ?? 1;
104511
104579
  const results = {};
104512
- for (const task2 of tasks) {
104513
- this.checkSignal("plan");
104514
- const result = await this.executeTask(task2);
104515
- results[task2.config.name] = result;
104516
- if (result.status === "failed") {
104517
- if (this.failFast)
104518
- break;
104580
+ if (maxConcurrency === 1) {
104581
+ this.reporter.setBuffering(false);
104582
+ for (const task2 of tasks) {
104583
+ this.checkSignal("plan");
104584
+ const result = await this.executeTask(task2);
104585
+ results[task2.config.name] = result;
104586
+ if (result.status === "failed") {
104587
+ if (this.failFast)
104588
+ break;
104589
+ }
104519
104590
  }
104591
+ } else {
104592
+ this.reporter.setBuffering(true);
104593
+ await this.executeTasksParallel(tasks, maxConcurrency, results);
104520
104594
  }
104521
104595
  const status = Object.values(results).some((task2) => task2.status === "failed") ? "failed" : "success";
104522
104596
  this.reporter?.emit("plan_end", {
@@ -104531,6 +104605,46 @@ class PlanRunner {
104531
104605
  tasks: results
104532
104606
  };
104533
104607
  }
104608
+ async executeTasksParallel(tasks, maxConcurrency, results) {
104609
+ const limit = maxConcurrency === 0 ? Number.POSITIVE_INFINITY : maxConcurrency;
104610
+ const queue = [...tasks];
104611
+ const executing = [];
104612
+ let shouldStop = false;
104613
+ while (queue.length > 0 || executing.length > 0) {
104614
+ while (!shouldStop && executing.length < limit && queue.length > 0) {
104615
+ const task2 = queue.shift();
104616
+ if (!task2)
104617
+ break;
104618
+ const promise = (async () => {
104619
+ try {
104620
+ this.checkSignal("plan");
104621
+ const result = await this.executeTask(task2);
104622
+ results[task2.config.name] = result;
104623
+ if (result.status === "failed" && this.failFast) {
104624
+ shouldStop = true;
104625
+ }
104626
+ } catch (error2) {
104627
+ shouldStop = true;
104628
+ throw error2;
104629
+ }
104630
+ })();
104631
+ executing.push(promise);
104632
+ promise.finally(() => {
104633
+ const index = executing.indexOf(promise);
104634
+ if (index >= 0) {
104635
+ executing.splice(index, 1);
104636
+ }
104637
+ });
104638
+ }
104639
+ if (executing.length > 0) {
104640
+ await Promise.race(executing);
104641
+ }
104642
+ if (shouldStop) {
104643
+ break;
104644
+ }
104645
+ }
104646
+ await Promise.all(executing);
104647
+ }
104534
104648
  findTask(name) {
104535
104649
  const tasks = this.expandedTasks ?? this.plan.expand();
104536
104650
  return tasks.find((task2) => task2.config.name === name);
@@ -104541,12 +104655,26 @@ class PlanRunner {
104541
104655
  if (existing?.status === "success" || existing?.status === "failed") {
104542
104656
  return this.toResult(existing, undefined, this.cache.wasTaskCached(name));
104543
104657
  }
104658
+ const existingPromise = this.taskPromises.get(name);
104659
+ if (existingPromise) {
104660
+ if (this.inProgress.has(name)) {
104661
+ throw new Error(`Cycle detected while executing task "${name}"`);
104662
+ }
104663
+ return existingPromise;
104664
+ }
104544
104665
  if (this.inProgress.has(name)) {
104545
104666
  throw new Error(`Cycle detected while executing task "${name}"`);
104546
104667
  }
104668
+ const promise = this.executeTaskInternal(task2);
104669
+ this.taskPromises.set(name, promise);
104670
+ return promise;
104671
+ }
104672
+ async executeTaskInternal(task2) {
104673
+ const name = task2.config.name;
104547
104674
  this.inProgress.add(name);
104548
104675
  this.reporter?.emit("task_start", { task: name });
104549
104676
  const taskStart = Date.now();
104677
+ const existing = this.states.get(name);
104550
104678
  const state = existing ?? (() => {
104551
104679
  const next = {
104552
104680
  status: "pending",
@@ -104830,6 +104958,7 @@ var runPlan = async (registryOrPlan, planName, options = {}) => {
104830
104958
  params: options.params ?? {},
104831
104959
  logger,
104832
104960
  failFast: options.failFast ?? true,
104961
+ maxConcurrency: options.maxConcurrency,
104833
104962
  reporter: options.reporter,
104834
104963
  signal: options.signal,
104835
104964
  ...options.cache ? { cache: options.cache } : {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitsi/action",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
4
4
  "description": "GitHub Action for running Kitsi pipelines",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",