@kody-ade/kody-engine 0.3.24 → 0.3.26

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.24",
6
+ version: "0.3.26",
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",
@@ -227,6 +227,7 @@ function parseReleaseConfig(raw) {
227
227
  if (typeof r.e2eCommand === "string") out.e2eCommand = r.e2eCommand;
228
228
  if (typeof r.draftRelease === "boolean") out.draftRelease = r.draftRelease;
229
229
  if (typeof r.releaseBranch === "string") out.releaseBranch = r.releaseBranch;
230
+ if (typeof r.devBranch === "string" && r.devBranch.length > 0) out.devBranch = r.devBranch;
230
231
  if (typeof r.timeoutMs === "number" && r.timeoutMs > 0) out.timeoutMs = Math.floor(r.timeoutMs);
231
232
  return Object.keys(out).length > 0 ? out : void 0;
232
233
  }
@@ -1,73 +1,94 @@
1
1
  #!/usr/bin/env bash
2
2
  #
3
- # release-deploy: run the configured deployCommand and/or notifyCommand
4
- # after release-publish has tagged and published the artifact. No agent.
3
+ # release-deploy: open a PR from the integration branch (dev) into the
4
+ # default branch (main) the human gate for production deploy. The
5
+ # orchestrator's chain ENDS with this PR opened; merging it is a manual
6
+ # step. No agent.
5
7
  #
6
- # Both commands are optional. With neither set, deploy is a no-op success
7
- # (the orchestrator still advances to "done").
8
+ # Behavior:
9
+ # - If release.devBranch is unset OR equals git.defaultBranch:
10
+ # no-op success (single-branch repos have nothing to deploy).
11
+ # - Else: idempotently open PR `devBranch` → `defaultBranch`. If an
12
+ # open PR already exists for that pair, reuse its URL.
13
+ #
14
+ # After the PR is opened, runs `release.notifyCommand` (if set) as a
15
+ # best-effort post-deploy hook.
8
16
  #
9
17
  # Inputs (env):
10
18
  # KODY_ARG_DRY_RUN true|false
11
19
  # KODY_ARG_ISSUE triggering issue/PR number (optional)
12
20
  #
13
21
  # Config (env):
14
- # KODY_CFG_RELEASE_DEPLOYCOMMAND optional; $VERSION substituted
22
+ # KODY_CFG_GIT_DEFAULTBRANCH e.g. main
23
+ # KODY_CFG_RELEASE_DEVBRANCH e.g. dev (unset → no-op)
15
24
  # KODY_CFG_RELEASE_NOTIFYCOMMAND optional; $VERSION substituted
16
25
  # KODY_CFG_RELEASE_TIMEOUTMS per-command timeout in ms (default 600000)
17
26
  #
18
27
  # Stdout signals:
28
+ # KODY_PR_URL=<deploy PR url>
19
29
  # KODY_REASON=<text>
20
30
  # KODY_SKIP_AGENT=true
21
31
 
22
32
  set -euo pipefail
23
33
 
24
34
  dry_run="${KODY_ARG_DRY_RUN:-false}"
25
- deploy_cmd="${KODY_CFG_RELEASE_DEPLOYCOMMAND:-}"
35
+ default_branch="${KODY_CFG_GIT_DEFAULTBRANCH:-main}"
36
+ dev_branch="${KODY_CFG_RELEASE_DEVBRANCH:-}"
26
37
  notify_cmd="${KODY_CFG_RELEASE_NOTIFYCOMMAND:-}"
27
38
  timeout_ms="${KODY_CFG_RELEASE_TIMEOUTMS:-600000}"
28
39
  timeout_s=$((timeout_ms / 1000))
29
40
 
30
41
  read_pkg_version() {
31
- python3 -c "import json; print(json.load(open('package.json'))['version'])"
42
+ python3 -c "import json; print(json.load(open('package.json'))['version'])" 2>/dev/null || echo "unknown"
32
43
  }
33
44
 
34
- if [[ ! -f package.json ]]; then
35
- echo "KODY_REASON=release deploy: package.json not found"
36
- echo "KODY_SKIP_AGENT=true"
37
- exit 99
38
- fi
39
-
40
45
  version=$(read_pkg_version)
41
46
  echo "→ release deploy: v${version}"
42
47
 
43
- if [[ -z "$deploy_cmd" && -z "$notify_cmd" ]]; then
44
- echo "KODY_REASON=no deployCommand or notifyCommand configured nothing to run"
48
+ # Single-branch repos: nothing to deploy.
49
+ if [[ -z "$dev_branch" || "$dev_branch" == "$default_branch" ]]; then
50
+ echo "KODY_REASON=no devBranch configured (or equals defaultBranch) — nothing to deploy"
45
51
  echo "KODY_SKIP_AGENT=true"
46
52
  exit 0
47
53
  fi
48
54
 
49
55
  if [[ "$dry_run" == "true" ]]; then
50
- echo "KODY_REASON=dry-run — would run deploy/notify commands"
56
+ echo "KODY_REASON=dry-run — would open PR ${dev_branch} → ${default_branch}"
51
57
  echo "KODY_SKIP_AGENT=true"
52
58
  exit 0
53
59
  fi
54
60
 
55
61
  export HUSKY=0 SKIP_HOOKS=1 CI="${CI:-1}"
56
62
 
57
- deploy_status="skipped"
58
- if [[ -n "$deploy_cmd" ]]; then
59
- cmd="${deploy_cmd//\$VERSION/$version}"
60
- echo " deploy: ${cmd}"
61
- if timeout "${timeout_s}" bash -c "$cmd"; then
62
- deploy_status="ok"
63
- else
64
- deploy_status="failed"
65
- echo "KODY_REASON=release deploy: deployCommand failed"
63
+ # Idempotency: reuse an open PR for this branch pair if one exists.
64
+ existing=$(gh pr list --head "$dev_branch" --base "$default_branch" --state open --json url --limit 1 2>/dev/null \
65
+ | python3 -c 'import json,sys; data=json.load(sys.stdin); print(data[0]["url"] if data else "")' 2>/dev/null \
66
+ || echo "")
67
+
68
+ if [[ -n "$existing" ]]; then
69
+ echo " reusing existing deploy PR: ${existing}"
70
+ pr_url="$existing"
71
+ else
72
+ body="Automated deploy PR opened by kody — promotes \`${dev_branch}\` to \`${default_branch}\` for release **v${version}**.
73
+
74
+ Merge this PR to deploy v${version} to \`${default_branch}\`."
75
+ if ! pr_url=$(printf '%s' "$body" | gh pr create --head "$dev_branch" --base "$default_branch" --title "deploy: ${dev_branch} → ${default_branch} (v${version})" --body-file -); then
76
+ echo "KODY_REASON=release deploy: gh pr create failed"
66
77
  echo "KODY_SKIP_AGENT=true"
67
78
  exit 1
68
79
  fi
69
80
  fi
70
81
 
82
+ if [[ -z "$pr_url" ]]; then
83
+ echo "KODY_REASON=release deploy: empty PR URL after gh pr create"
84
+ echo "KODY_SKIP_AGENT=true"
85
+ exit 1
86
+ fi
87
+
88
+ echo "RELEASE_DEPLOY_PR=${pr_url}"
89
+ echo "KODY_PR_URL=${pr_url}"
90
+
91
+ # Optional post-deploy notification (e.g. Slack ping that a deploy PR is up).
71
92
  notify_status="skipped"
72
93
  if [[ -n "$notify_cmd" ]]; then
73
94
  cmd="${notify_cmd//\$VERSION/$version}"
@@ -80,5 +101,5 @@ if [[ -n "$notify_cmd" ]]; then
80
101
  fi
81
102
  fi
82
103
 
83
- echo "KODY_REASON=deploy=${deploy_status} notify=${notify_status}"
104
+ echo "KODY_REASON=opened deploy PR ${dev_branch} → ${default_branch} (notify=${notify_status})"
84
105
  echo "KODY_SKIP_AGENT=true"
@@ -26,6 +26,10 @@ bump="${KODY_ARG_BUMP:-patch}"
26
26
  dry_run="${KODY_ARG_DRY_RUN:-false}"
27
27
  prefer="${KODY_ARG_PREFER:-}"
28
28
  default_branch="${KODY_CFG_GIT_DEFAULTBRANCH:-main}"
29
+ dev_branch="${KODY_CFG_RELEASE_DEVBRANCH:-}"
30
+ # PR target: dev branch when configured (and different from default), else default.
31
+ pr_base="${dev_branch:-$default_branch}"
32
+ [[ "$pr_base" == "$default_branch" ]] && pr_base="$default_branch"
29
33
  version_files_json="${KODY_CFG_RELEASE_VERSIONFILES:-}"
30
34
 
31
35
  fail() {
@@ -313,8 +317,8 @@ _… truncated; see CHANGELOG.md_"
313
317
  else
314
318
  body_entry="$entry"
315
319
  fi
316
- body=$'Automated release PR opened by kody.\n\n'"$body_entry"$'\n\nMerge this and then run `kody release --mode finalize`.'
317
- pr_url=$(printf '%s' "$body" | gh pr create --head "$release_branch" --base "$default_branch" --title "chore: release ${tag}" --body-file -)
320
+ body=$'Automated release PR opened by kody.\n\n'"$body_entry"$'\n\nThe release orchestrator will merge this into `'"${pr_base}"$'` and continue to publish + deploy.'
321
+ pr_url=$(printf '%s' "$body" | gh pr create --head "$release_branch" --base "$pr_base" --title "chore: release ${tag}" --body-file -)
318
322
  fi
319
323
 
320
324
  if [[ -z "$pr_url" ]]; then
@@ -24,6 +24,13 @@ set -euo pipefail
24
24
 
25
25
  dry_run="${KODY_ARG_DRY_RUN:-false}"
26
26
  default_branch="${KODY_CFG_GIT_DEFAULTBRANCH:-main}"
27
+ dev_branch="${KODY_CFG_RELEASE_DEVBRANCH:-}"
28
+ # Tag the branch where the release-prepare PR was merged: devBranch when set
29
+ # (and different from default), else defaultBranch.
30
+ target_branch="$default_branch"
31
+ if [[ -n "$dev_branch" && "$dev_branch" != "$default_branch" ]]; then
32
+ target_branch="$dev_branch"
33
+ fi
27
34
  publish_cmd="${KODY_CFG_RELEASE_PUBLISHCOMMAND:-}"
28
35
  draft="${KODY_CFG_RELEASE_DRAFTRELEASE:-false}"
29
36
  timeout_ms="${KODY_CFG_RELEASE_TIMEOUTMS:-600000}"
@@ -46,10 +53,10 @@ fi
46
53
  export HUSKY=0 SKIP_HOOKS=1 CI="${CI:-1}"
47
54
 
48
55
  # Make sure we're on the merged commit. The orchestrator merged the release
49
- # PR into default_branch; pull so the local tree has the bump commit.
50
- git fetch origin "$default_branch" --tags
51
- git checkout "$default_branch"
52
- git reset --hard "origin/$default_branch"
56
+ # PR into target_branch; pull so the local tree has the bump commit.
57
+ git fetch origin "$target_branch" --tags
58
+ git checkout "$target_branch"
59
+ git reset --hard "origin/$target_branch"
53
60
 
54
61
  version=$(read_pkg_version)
55
62
  tag="v${version}"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kody-ade/kody-engine",
3
- "version": "0.3.24",
3
+ "version": "0.3.26",
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",