@atolis-hq/wake 0.3.13 → 0.3.15
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.
|
@@ -8,20 +8,13 @@ export function createSourceUpdatePort(input) {
|
|
|
8
8
|
return (await execute('git', ['status', '--porcelain'], input.repoRoot)).trim().length === 0;
|
|
9
9
|
},
|
|
10
10
|
async latestTag() {
|
|
11
|
-
const tag = (await execute
|
|
12
|
-
.split(/\r?\n/u)
|
|
13
|
-
.find((value) => value.trim().length > 0)
|
|
14
|
-
?.trim();
|
|
11
|
+
const tag = (await candidateTags(execute, input.repoRoot)).at(0);
|
|
15
12
|
if (tag === undefined)
|
|
16
13
|
throw new Error('No source version tag is available');
|
|
17
14
|
return tag;
|
|
18
15
|
},
|
|
19
16
|
async candidateTags() {
|
|
20
|
-
|
|
21
|
-
return output
|
|
22
|
-
.split(/\r?\n/u)
|
|
23
|
-
.map((line) => line.trim())
|
|
24
|
-
.filter((line) => line.length > 0);
|
|
17
|
+
return candidateTags(execute, input.repoRoot);
|
|
25
18
|
},
|
|
26
19
|
async checkout(tag) {
|
|
27
20
|
await execute('git', ['checkout', tag], input.repoRoot);
|
|
@@ -41,6 +34,14 @@ export function createSourceUpdatePort(input) {
|
|
|
41
34
|
},
|
|
42
35
|
};
|
|
43
36
|
}
|
|
37
|
+
async function candidateTags(execute, repoRoot) {
|
|
38
|
+
await execute('git', ['fetch', '--tags'], repoRoot);
|
|
39
|
+
const output = await execute('git', ['tag', '--list', 'v*', '--sort=-v:refname'], repoRoot);
|
|
40
|
+
return output
|
|
41
|
+
.split(/\r?\n/u)
|
|
42
|
+
.map((line) => line.trim())
|
|
43
|
+
.filter((line) => line.length > 0);
|
|
44
|
+
}
|
|
44
45
|
async function runProcess(command, args, cwd) {
|
|
45
46
|
const result = await execFile(command, args, { cwd, encoding: 'utf8' });
|
|
46
47
|
return result.stdout;
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { selectRunExecutionEvent } from '../../execution/index.js';
|
|
2
2
|
import { correlationId, EventActorKind, } from '../../kernel/index.js';
|
|
3
3
|
import { selectOrchestrationEvent } from '../contracts/event-decoder.js';
|
|
4
|
+
import { OrchestrationEventType, } from '../contracts/events.js';
|
|
4
5
|
import { workflowInstanceId, workflowName, } from '../contracts/identifiers.js';
|
|
6
|
+
import { isWorkflowInstanceStream } from '../contracts/streams.js';
|
|
5
7
|
const checkpoint = 'reactor:orchestration.watch';
|
|
6
8
|
export function createWatchReactor(orchestration, journal, checkpoints, runs) {
|
|
7
9
|
return {
|
|
8
10
|
async react(event, context) {
|
|
9
11
|
const causalCycle = orchestrationCausalCycleId(selectOrchestrationEvent(event));
|
|
10
|
-
const sourceWorkflowInstanceId = await
|
|
12
|
+
const sourceWorkflowInstanceId = await resolveTriggerWorkflowInstanceId(event, runs);
|
|
11
13
|
for (const match of await orchestration.listWatchMatches(event, context)) {
|
|
12
14
|
if (sourceWorkflowInstanceId !== undefined &&
|
|
13
15
|
match.parent.workflowInstanceId !== sourceWorkflowInstanceId)
|
|
@@ -58,11 +60,24 @@ function commandContext(event) {
|
|
|
58
60
|
/**
|
|
59
61
|
* A run-lifecycle event (e.g. `execution.run-succeeded`) fires for every run
|
|
60
62
|
* in the system, including a watch's own spawned child re-running its own
|
|
61
|
-
* activity on retry. Without
|
|
63
|
+
* activity on retry. Without scoping, `listWatchMatches` would treat any
|
|
62
64
|
* currently-eligible parent's declared event type as a match regardless of
|
|
63
65
|
* which run actually produced it, causing a child's own retry (or an
|
|
64
66
|
* unrelated workflow's run) to spuriously re-trigger the same watch.
|
|
67
|
+
*
|
|
68
|
+
* For orchestration events, only `SignalWaitStarted` is scoped to its
|
|
69
|
+
* stream's instance; this is currently the only orchestration event type
|
|
70
|
+
* known to benefit from stream-based filtering. Other orchestration events
|
|
71
|
+
* like `ChildCompleted` are cross-instance coordination facts by design and
|
|
72
|
+
* must fall through unchanged to the async resolver to preserve their
|
|
73
|
+
* existing multi-instance coordination paths.
|
|
65
74
|
*/
|
|
75
|
+
async function resolveTriggerWorkflowInstanceId(event, runs) {
|
|
76
|
+
if (event.eventType === OrchestrationEventType.SignalWaitStarted &&
|
|
77
|
+
isWorkflowInstanceStream(event.stream))
|
|
78
|
+
return event.stream.id;
|
|
79
|
+
return resolveRunWorkflowInstanceId(event, runs);
|
|
80
|
+
}
|
|
66
81
|
async function resolveRunWorkflowInstanceId(event, runs) {
|
|
67
82
|
if (runs === undefined)
|
|
68
83
|
return undefined;
|
|
@@ -3,7 +3,14 @@ export async function runSelfUpdate(input) {
|
|
|
3
3
|
if (!input.force && (await input.readLedger()) === input.tag)
|
|
4
4
|
return false;
|
|
5
5
|
const priorTag = await input.readLedger();
|
|
6
|
-
|
|
6
|
+
try {
|
|
7
|
+
await input.update(input.tag);
|
|
8
|
+
}
|
|
9
|
+
catch (error) {
|
|
10
|
+
if (priorTag !== null && input.rollback !== undefined)
|
|
11
|
+
await input.rollback(priorTag);
|
|
12
|
+
throw error;
|
|
13
|
+
}
|
|
7
14
|
if (input.health !== undefined && !(await input.health())) {
|
|
8
15
|
if (priorTag !== null && input.rollback !== undefined)
|
|
9
16
|
await input.rollback(priorTag);
|