@kody-ade/kody-engine 0.3.70-beta.1 → 0.3.70-beta.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/dist/bin/kody.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// package.json
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "@kody-ade/kody-engine",
|
|
6
|
-
version: "0.3.70-beta.
|
|
6
|
+
version: "0.3.70-beta.3",
|
|
7
7
|
description: "kody \u2014 autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
8
8
|
license: "MIT",
|
|
9
9
|
type: "module",
|
|
@@ -15,14 +15,32 @@ tag_and_publish() {
|
|
|
15
15
|
local timeout_s=$((timeout_ms / 1000))
|
|
16
16
|
local tag="v${new_version}"
|
|
17
17
|
|
|
18
|
-
#
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
# Idempotent tagging: if the tag already exists and points at HEAD,
|
|
19
|
+
# treat it as already-published. If it points elsewhere, fail loudly —
|
|
20
|
+
# something is inconsistent and a human should look.
|
|
21
|
+
local remote_sha local_sha head_sha
|
|
22
|
+
head_sha=$(git rev-parse HEAD)
|
|
23
|
+
if local_sha=$(git rev-parse --verify "$tag" 2>/dev/null); then
|
|
24
|
+
if [[ "$local_sha" == "$head_sha" ]]; then
|
|
25
|
+
echo " tag ${tag} already exists locally at HEAD — skipping create" >&2
|
|
26
|
+
else
|
|
27
|
+
echo "[publish] tag ${tag} exists locally at ${local_sha} but HEAD is ${head_sha}" >&2
|
|
28
|
+
return 1
|
|
29
|
+
fi
|
|
30
|
+
else
|
|
31
|
+
git tag -a "$tag" -m "Release ${tag}"
|
|
32
|
+
fi
|
|
33
|
+
# Push the tag if it isn't already on origin (or push always; gh will
|
|
34
|
+
# no-op on existing remote tag at the same sha).
|
|
35
|
+
if remote_sha=$(git ls-remote --tags origin "refs/tags/${tag}" 2>/dev/null | awk '{print $1}'); then
|
|
36
|
+
if [[ -z "$remote_sha" ]]; then
|
|
37
|
+
git push origin "$tag"
|
|
38
|
+
elif [[ "$remote_sha" != "$head_sha" ]]; then
|
|
39
|
+
echo " WARN: remote tag ${tag} points at ${remote_sha}, HEAD is ${head_sha}" >&2
|
|
40
|
+
fi
|
|
41
|
+
else
|
|
42
|
+
git push origin "$tag" || true
|
|
22
43
|
fi
|
|
23
|
-
|
|
24
|
-
git tag -a "$tag" -m "Release ${tag}"
|
|
25
|
-
git push origin "$tag"
|
|
26
44
|
|
|
27
45
|
# publishCommand (optional). Failure here is recorded but does not abort —
|
|
28
46
|
# we still want the GH release entry so the tag is discoverable.
|
|
@@ -48,6 +66,16 @@ create_gh_release() {
|
|
|
48
66
|
local draft_flag=""
|
|
49
67
|
[[ "$draft" == "true" ]] && draft_flag="--draft"
|
|
50
68
|
|
|
69
|
+
# Idempotent: if a release for this tag already exists, reuse it.
|
|
70
|
+
local existing_url
|
|
71
|
+
if existing_url=$(gh release view "$tag" --json url -q .url 2>/dev/null); then
|
|
72
|
+
if [[ -n "$existing_url" ]]; then
|
|
73
|
+
echo " GH release for ${tag} already exists: ${existing_url}" >&2
|
|
74
|
+
echo "$existing_url"
|
|
75
|
+
return 0
|
|
76
|
+
fi
|
|
77
|
+
fi
|
|
78
|
+
|
|
51
79
|
local release_url=""
|
|
52
80
|
if release_url=$(gh release create "$tag" --title "$tag" --notes "Release ${tag} — automated by kody." $draft_flag 2>&1); then
|
|
53
81
|
echo "$release_url"
|
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
# release/wait.sh — wait_for_ci function: poll a PR's check rollup
|
|
4
4
|
# until all non-skipped checks pass, or timeout.
|
|
5
5
|
#
|
|
6
|
-
# Function: wait_for_ci <pr_number> <timeout_minutes>
|
|
7
|
-
#
|
|
6
|
+
# Function: wait_for_ci <pr_number> <timeout_minutes> [poll_seconds] [initial_wait]
|
|
7
|
+
# Returns 0 on CI passed, 1 on CI failed/timeout.
|
|
8
8
|
#
|
|
9
|
-
#
|
|
9
|
+
# Special-case: if a PR has zero registered checks (no CI configured),
|
|
10
|
+
# treats that as PASSED after a short stabilization window — so a Tester
|
|
11
|
+
# repo without checks doesn't loop forever.
|
|
10
12
|
|
|
11
13
|
# shellcheck disable=SC2148
|
|
12
14
|
|
|
@@ -24,43 +26,50 @@ wait_for_ci() {
|
|
|
24
26
|
local deadline=$(( $(date +%s) + timeout_minutes * 60 ))
|
|
25
27
|
echo "→ wait_for_ci: PR #${pr_number}, timeout=${timeout_minutes}m"
|
|
26
28
|
|
|
27
|
-
# Initial wait — gives GHA time to register checks.
|
|
28
29
|
sleep "$initial_wait"
|
|
29
30
|
|
|
31
|
+
# Track consecutive "no checks" results so we don't bail prematurely
|
|
32
|
+
# on a PR that's just slow to register checks.
|
|
33
|
+
local empty_count=0
|
|
34
|
+
local empty_threshold=4 # ~2 minutes (4 * poll_seconds=30s) before treating as no-CI
|
|
35
|
+
|
|
30
36
|
while (( $(date +%s) < deadline )); do
|
|
31
|
-
# gh pr checks <N> --json prints an array of {state, name, ...}.
|
|
32
37
|
local raw
|
|
33
|
-
if ! raw=$(gh pr checks "$pr_number" --json state
|
|
34
|
-
|
|
38
|
+
if ! raw=$(gh pr checks "$pr_number" --json state 2>/dev/null); then
|
|
39
|
+
# gh exits non-zero when there are no checks — treat as no-CI.
|
|
40
|
+
empty_count=$((empty_count + 1))
|
|
41
|
+
echo " [wait_for_ci] gh pr checks returned non-zero (count=${empty_count})"
|
|
42
|
+
if (( empty_count >= empty_threshold )); then
|
|
43
|
+
echo "→ wait_for_ci: PR #${pr_number} has no CI checks configured — treating as passed"
|
|
44
|
+
return 0
|
|
45
|
+
fi
|
|
35
46
|
sleep "$poll_seconds"
|
|
36
47
|
continue
|
|
37
48
|
fi
|
|
38
49
|
|
|
39
|
-
#
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
buckets["failed"] += 1
|
|
54
|
-
buckets["failed_names"].append(name)
|
|
55
|
-
else: # SUCCESS, SKIPPED, NEUTRAL, etc.
|
|
56
|
-
buckets["passed"] += 1
|
|
57
|
-
print(f"{buckets[\"pending\"]}|{buckets[\"passed\"]}|{buckets[\"failed\"]}|{','.join(buckets[\"failed_names\"][:5])}")
|
|
58
|
-
')
|
|
50
|
+
# Empty array? Same path.
|
|
51
|
+
local total
|
|
52
|
+
total=$(printf '%s' "$raw" | jq 'length' 2>/dev/null || echo "0")
|
|
53
|
+
if [[ "$total" == "0" ]]; then
|
|
54
|
+
empty_count=$((empty_count + 1))
|
|
55
|
+
echo " [wait_for_ci] no checks registered yet (count=${empty_count})"
|
|
56
|
+
if (( empty_count >= empty_threshold )); then
|
|
57
|
+
echo "→ wait_for_ci: PR #${pr_number} has no CI checks configured — treating as passed"
|
|
58
|
+
return 0
|
|
59
|
+
fi
|
|
60
|
+
sleep "$poll_seconds"
|
|
61
|
+
continue
|
|
62
|
+
fi
|
|
63
|
+
empty_count=0
|
|
59
64
|
|
|
60
|
-
|
|
61
|
-
|
|
65
|
+
# Tally states via jq.
|
|
66
|
+
local pending failed passed failed_names
|
|
67
|
+
pending=$(printf '%s' "$raw" | jq '[.[] | select((.state // "") | IN("PENDING","IN_PROGRESS","QUEUED",""))] | length')
|
|
68
|
+
failed=$(printf '%s' "$raw" | jq '[.[] | select((.state // "") | IN("FAILURE","CANCELLED","TIMED_OUT","ACTION_REQUIRED","STARTUP_FAILURE"))] | length')
|
|
69
|
+
passed=$(printf '%s' "$raw" | jq '[.[] | select((.state // "") | IN("SUCCESS","SKIPPED","NEUTRAL"))] | length')
|
|
70
|
+
failed_names=$(printf '%s' "$raw" | jq -r '[.[] | select((.state // "") | IN("FAILURE","CANCELLED","TIMED_OUT","ACTION_REQUIRED","STARTUP_FAILURE")) | .name] | join(",")')
|
|
62
71
|
|
|
63
|
-
echo " [wait_for_ci] pending=${pending} passed=${passed} failed=${failed}"
|
|
72
|
+
echo " [wait_for_ci] pending=${pending} passed=${passed} failed=${failed} (total=${total})"
|
|
64
73
|
|
|
65
74
|
if [[ "$failed" -gt 0 ]]; then
|
|
66
75
|
echo "[wait_for_ci] CI failed on PR #${pr_number}: ${failed_names}" >&2
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kody-ade/kody-engine",
|
|
3
|
-
"version": "0.3.70-beta.
|
|
3
|
+
"version": "0.3.70-beta.3",
|
|
4
4
|
"description": "kody — autonomous development engine. Single-session Claude Code agent behind a generic executor + declarative executable profiles.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|