gowalk-cicd 1.0.126 → 1.0.127
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/action/.daemux-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.127
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.127
|
|
@@ -12,18 +12,39 @@ function evidence(status) {
|
|
|
12
12
|
return 'release_write_status=error';
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
// Does the record name THIS run? That one question settles both halves of the
|
|
16
|
+
// protocol -- a claim is won when the answer is yes, released when it is no --
|
|
17
|
+
// and the answer does not depend on which write produced it.
|
|
18
|
+
//
|
|
19
|
+
// Both halves used to demand their OWN revision back from the read that
|
|
20
|
+
// follows their write. GitHub's contents API is read-after-write eventual on a
|
|
21
|
+
// branch ref, so that read can serve the previous blob for a moment, and a
|
|
22
|
+
// write that had already landed then looked like a failure. Foundy run
|
|
23
|
+
// 34345638488 (2026-09-09) released ownership twice -- both commits are on
|
|
24
|
+
// app-robot-play-coordination, both wrote `owner: null` -- and still failed
|
|
25
|
+
// `play_owner_release_unverified`, taking the app's first Play release with it.
|
|
26
|
+
const held = (row, selected) => record.same(row.value.owner, selected.owner);
|
|
27
|
+
|
|
28
|
+
// Seal owes two things, not one: the record must not name this run, AND no
|
|
29
|
+
// claim write of ours may still be able to land. A record another holder has
|
|
30
|
+
// taken settles both -- their write moved the blob, so a late CAS of ours can
|
|
31
|
+
// only conflict. An UNOWNED record settles only the first, so seal still writes
|
|
32
|
+
// once to move the revision itself, and then accepts any readback that no
|
|
33
|
+
// longer names this run. (That fence used to be a side effect of releasing a
|
|
34
|
+
// record we never held; a lost claim response relies on it.)
|
|
35
|
+
const fenced = (row, selected) => row.value.owner !== null && !held(row, selected);
|
|
36
|
+
|
|
15
37
|
async function seal(client, selected) {
|
|
16
38
|
let detail = 'release_write_status=none';
|
|
17
39
|
for (let attempt = 0; attempt < 3; attempt++) {
|
|
18
40
|
const row = record.validate(await client.read(selected.path), selected);
|
|
19
|
-
if (
|
|
41
|
+
if (fenced(row, selected)) return;
|
|
20
42
|
const idle = record.replacement(row, null);
|
|
21
43
|
// Reconcile a possibly applied write; keep only its status as evidence.
|
|
22
44
|
try { detail = evidence(await client.write(selected.path, row, idle)); }
|
|
23
45
|
catch { detail = evidence(undefined); }
|
|
24
46
|
const after = record.validate(await client.read(selected.path), selected);
|
|
25
|
-
if (after
|
|
26
|
-
if (after.value.owner !== null && !record.same(after.value.owner, selected.owner)) return;
|
|
47
|
+
if (!held(after, selected)) return;
|
|
27
48
|
}
|
|
28
49
|
const failure = new Error('play_owner_release_unverified');
|
|
29
50
|
failure.detail = detail;
|
|
@@ -40,6 +61,12 @@ async function acquire(client, selected, attempted = () => {}, waiting = {}) {
|
|
|
40
61
|
for (let attempt = 0; attempt < 3;) {
|
|
41
62
|
if (waiting.signal?.aborted) throw new Error('play_owner_cancelled');
|
|
42
63
|
const row = record.validate(await client.read(selected.path), selected);
|
|
64
|
+
// A record already naming THIS run is this run's own claim: the owner id is
|
|
65
|
+
// a UUID minted once per process, so no other writer can have put it there.
|
|
66
|
+
// Without this, a claim whose write landed but whose readback lagged came
|
|
67
|
+
// back on the next pass as a foreign live holder and the run waited out its
|
|
68
|
+
// own deadline against itself.
|
|
69
|
+
if (held(row, selected)) return;
|
|
43
70
|
if (row.value.owner !== null) {
|
|
44
71
|
const owner = row.value.owner;
|
|
45
72
|
if (owner.kind !== 'ci' || !record.terminal(await client.run(owner), owner)) {
|
|
@@ -55,7 +82,7 @@ async function acquire(client, selected, attempted = () => {}, waiting = {}) {
|
|
|
55
82
|
attempted();
|
|
56
83
|
try { await client.write(selected.path, row, desired); } catch { /* Only exact readback may adopt it. */ }
|
|
57
84
|
const after = record.validate(await client.read(selected.path), selected);
|
|
58
|
-
if (
|
|
85
|
+
if (held(after, selected)) return;
|
|
59
86
|
}
|
|
60
87
|
throw new Error('play_owner_busy');
|
|
61
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.127
|