@ipul-labs/forge 1.16.4 → 1.16.5
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/package.json +3 -2
- package/scripts/inject-readme.cjs +13 -0
- package/scripts/local-rollout.sh +134 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ipul-labs/forge",
|
|
3
|
-
"version": "1.16.
|
|
3
|
+
"version": "1.16.5",
|
|
4
4
|
"description": "AI-powered code change & deploy control panel — connects Claude, GitLab, and Kubernetes",
|
|
5
5
|
"readmeFilename": "README.md",
|
|
6
6
|
"type": "module",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"files": [
|
|
17
17
|
"README.md",
|
|
18
18
|
"bin",
|
|
19
|
+
"scripts",
|
|
19
20
|
"server/forge",
|
|
20
21
|
"dist"
|
|
21
22
|
],
|
|
@@ -26,7 +27,7 @@
|
|
|
26
27
|
"typecheck": "tsc --noEmit",
|
|
27
28
|
"test": "vitest run",
|
|
28
29
|
"test:watch": "vitest",
|
|
29
|
-
"prepack": "node -
|
|
30
|
+
"prepack": "node scripts/inject-readme.cjs"
|
|
30
31
|
},
|
|
31
32
|
"dependencies": {
|
|
32
33
|
"@kubernetes/client-node": "^1.0.0",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const path = require("path");
|
|
4
|
+
|
|
5
|
+
const root = path.resolve(__dirname, "..");
|
|
6
|
+
const pkgPath = path.join(root, "package.json");
|
|
7
|
+
const readmePath = path.join(root, "README.md");
|
|
8
|
+
|
|
9
|
+
if (!fs.existsSync(readmePath)) process.exit(0);
|
|
10
|
+
|
|
11
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
12
|
+
pkg.readme = fs.readFileSync(readmePath, "utf8");
|
|
13
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
3
|
+
# Local dry-run of the same manifests + commands the *-rollout CI jobs execute.
|
|
4
|
+
# Catches manifest bugs, missing env vars, image-pull problems, and rollout
|
|
5
|
+
# logic errors BEFORE burning another CI cycle. Uses your local kubeconfig
|
|
6
|
+
# (admin creds against k3s), so it does NOT test the agent SA's RBAC — for
|
|
7
|
+
# that, the actual CI run is still the source of truth.
|
|
8
|
+
#
|
|
9
|
+
# ./scripts/local-rollout.sh [test|prep|prod] [image-tag]
|
|
10
|
+
#
|
|
11
|
+
# Defaults: env=test, image-tag=<current deployment's tag OR "latest">
|
|
12
|
+
#
|
|
13
|
+
# Exits non-zero on the first failure with a clear message.
|
|
14
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
set -euo pipefail
|
|
17
|
+
|
|
18
|
+
ENV=${1:-test}
|
|
19
|
+
IMAGE_TAG=${2:-}
|
|
20
|
+
|
|
21
|
+
case "$ENV" in
|
|
22
|
+
test) NS=test; DEPLOY=forge-test; MANIFEST_DIR=manifests/test/forge-test ;;
|
|
23
|
+
prep) NS=prep; DEPLOY=forge-prep; MANIFEST_DIR=manifests/prep/forge-prep ;;
|
|
24
|
+
prod) NS=prod; DEPLOY=forge; MANIFEST_DIR=manifests/prod/forge ;;
|
|
25
|
+
*) echo "Usage: $0 [test|prep|prod] [image-tag]"; exit 2 ;;
|
|
26
|
+
esac
|
|
27
|
+
|
|
28
|
+
# All envs pull from the same consolidated image repo. Per-env differences
|
|
29
|
+
# live in the manifests, not in the image.
|
|
30
|
+
IMAGE_REPO=iplayulisten/forge
|
|
31
|
+
|
|
32
|
+
# ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
c_step() { printf '\n\033[1;34m── %s ──\033[0m\n' "$*"; }
|
|
35
|
+
c_ok() { printf '\033[1;32m✓\033[0m %s\n' "$*"; }
|
|
36
|
+
c_warn() { printf '\033[1;33m⚠\033[0m %s\n' "$*"; }
|
|
37
|
+
c_fail() { printf '\033[1;31m✗\033[0m %s\n' "$*"; exit 1; }
|
|
38
|
+
|
|
39
|
+
require() { command -v "$1" >/dev/null 2>&1 || c_fail "missing required binary: $1"; }
|
|
40
|
+
|
|
41
|
+
# ─── Preflight ────────────────────────────────────────────────────────────────
|
|
42
|
+
|
|
43
|
+
c_step "Preflight"
|
|
44
|
+
require kubectl
|
|
45
|
+
require openssl
|
|
46
|
+
|
|
47
|
+
CTX=$(kubectl config current-context 2>/dev/null || true)
|
|
48
|
+
[ -n "$CTX" ] || c_fail "no current kubectl context — set one with 'kubectl config use-context <name>'"
|
|
49
|
+
c_ok "kubectl context: $CTX"
|
|
50
|
+
|
|
51
|
+
if ! kubectl get ns "$NS" >/dev/null 2>&1; then
|
|
52
|
+
c_warn "namespace '$NS' doesn't exist — creating it"
|
|
53
|
+
kubectl create namespace "$NS"
|
|
54
|
+
c_ok "namespace '$NS' created"
|
|
55
|
+
else
|
|
56
|
+
c_ok "namespace '$NS' exists"
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
[ -d "$MANIFEST_DIR" ] || c_fail "manifest dir not found: $MANIFEST_DIR"
|
|
60
|
+
c_ok "manifest dir: $MANIFEST_DIR"
|
|
61
|
+
|
|
62
|
+
# ─── Secret creation (mirrors CI) ─────────────────────────────────────────────
|
|
63
|
+
|
|
64
|
+
c_step "Secret: forge-secret"
|
|
65
|
+
: "${FORGE_TOKEN:=}"
|
|
66
|
+
: "${ANTHROPIC_API_KEY:=}"
|
|
67
|
+
: "${GITLAB_TOKEN:=}"
|
|
68
|
+
|
|
69
|
+
if [ -z "$FORGE_TOKEN" ]; then
|
|
70
|
+
c_warn "FORGE_TOKEN unset — generating a throwaway for this run"
|
|
71
|
+
FORGE_TOKEN=$(openssl rand -hex 32)
|
|
72
|
+
fi
|
|
73
|
+
[ -n "$GITLAB_TOKEN" ] || c_warn "GITLAB_TOKEN unset (forge backend needs this at runtime — ok for manifest test)"
|
|
74
|
+
[ -n "$ANTHROPIC_API_KEY" ] || c_warn "ANTHROPIC_API_KEY unset (optional, only needed for quota probe)"
|
|
75
|
+
|
|
76
|
+
kubectl create secret generic forge-secret \
|
|
77
|
+
--from-literal=FORGE_TOKEN="$FORGE_TOKEN" \
|
|
78
|
+
--from-literal=ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
|
|
79
|
+
--from-literal=GITLAB_TOKEN="$GITLAB_TOKEN" \
|
|
80
|
+
-n "$NS" --dry-run=client -o yaml | kubectl apply -f -
|
|
81
|
+
c_ok "forge-secret applied"
|
|
82
|
+
|
|
83
|
+
# ─── Apply manifests in CI order ──────────────────────────────────────────────
|
|
84
|
+
|
|
85
|
+
for f in config-map.yaml service.yaml deployment.yaml; do
|
|
86
|
+
path="$MANIFEST_DIR/$f"
|
|
87
|
+
[ -f "$path" ] || c_fail "missing manifest: $path"
|
|
88
|
+
c_step "Applying $f"
|
|
89
|
+
kubectl apply -f "$path"
|
|
90
|
+
c_ok "$f applied"
|
|
91
|
+
done
|
|
92
|
+
|
|
93
|
+
# ─── Image tag ────────────────────────────────────────────────────────────────
|
|
94
|
+
|
|
95
|
+
if [ -z "$IMAGE_TAG" ]; then
|
|
96
|
+
CURRENT_IMAGE=$(kubectl get deploy/"$DEPLOY" -n "$NS" -o jsonpath='{.spec.template.spec.containers[0].image}' 2>/dev/null || true)
|
|
97
|
+
if [ -n "$CURRENT_IMAGE" ] && [ "$CURRENT_IMAGE" != "*__VERSION__*" ] && [[ "$CURRENT_IMAGE" != *__VERSION__* ]]; then
|
|
98
|
+
IMAGE_TAG=${CURRENT_IMAGE##*:}
|
|
99
|
+
c_ok "reusing current deployment image tag: $IMAGE_TAG"
|
|
100
|
+
else
|
|
101
|
+
IMAGE_TAG=latest
|
|
102
|
+
c_warn "no usable tag in current deployment — falling back to '$IMAGE_TAG' (may fail to pull)"
|
|
103
|
+
fi
|
|
104
|
+
fi
|
|
105
|
+
|
|
106
|
+
c_step "kubectl set image → ${IMAGE_REPO}:${IMAGE_TAG}"
|
|
107
|
+
kubectl set image deployment/"$DEPLOY" -n "$NS" "${DEPLOY}=${IMAGE_REPO}:${IMAGE_TAG}"
|
|
108
|
+
c_ok "image set"
|
|
109
|
+
|
|
110
|
+
# ─── Rollout ──────────────────────────────────────────────────────────────────
|
|
111
|
+
|
|
112
|
+
c_step "Rollout status (120s timeout)"
|
|
113
|
+
if kubectl rollout status deployment/"$DEPLOY" -n "$NS" --timeout=120s; then
|
|
114
|
+
c_ok "rollout succeeded"
|
|
115
|
+
else
|
|
116
|
+
c_warn "rollout did not finish in 120s — dumping pod state to help diagnose"
|
|
117
|
+
kubectl get pods -n "$NS" -l app="$DEPLOY" -o wide || true
|
|
118
|
+
kubectl describe deployment/"$DEPLOY" -n "$NS" | sed -n '/Events:/,$p' || true
|
|
119
|
+
kubectl get events -n "$NS" --sort-by=.lastTimestamp | tail -20 || true
|
|
120
|
+
exit 1
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# ─── Summary ──────────────────────────────────────────────────────────────────
|
|
124
|
+
|
|
125
|
+
c_step "Summary"
|
|
126
|
+
kubectl get pods,svc,deploy -n "$NS" -l app="$DEPLOY"
|
|
127
|
+
c_ok "local rollout for '$ENV' passed"
|
|
128
|
+
echo
|
|
129
|
+
echo "Next: push CI. If CI fails where this didn't, it's agent SA RBAC."
|
|
130
|
+
echo "To tear down what this script created:"
|
|
131
|
+
echo " kubectl delete -f $MANIFEST_DIR/deployment.yaml -n $NS"
|
|
132
|
+
echo " kubectl delete -f $MANIFEST_DIR/service.yaml -n $NS"
|
|
133
|
+
echo " kubectl delete -f $MANIFEST_DIR/config-map.yaml -n $NS"
|
|
134
|
+
echo " kubectl delete secret forge-secret -n $NS"
|