1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
kukuri build & deploy guide
===========================
Artifacts (all land in modules/orgflow-domain/build/distributions/):
kukuri-desktop-<v>.zip desktop fat jar + launcher (bundleDesktop)
kukuri-wasm-node-<v>.zip Kotlin/Wasm node build (bundleWasmNode)
kukuri-wasm-web-<v>.zip web app: index.html + orgflow-ui.js + webfont.js (bundleWeb)
kukuri-native-linuxx64-<v>.zip linux native executable (bundleNative)
kukuri-android-<v>.apk debug-signed android APK (bundleApk)
1. Local build
--------------
Requirements: JDK 21, Android SDK (ANDROID_HOME or local.properties), node.js (wasm tests).
Build everything:
./gradlew bundleDesktop bundleWasm bundleNative bundleWeb bundleApk
Single artifacts:
./gradlew :modules:orgflow-domain:bundleWeb
./gradlew :modules:orgflow-domain:bundleApk
Run the desktop shell:
./gradlew :apps:desktop:run
Test set (same steps CI runs):
./gradlew :modules:orgflow-domain:detekt assemble jvmTest \
testDebugUnitTest testReleaseUnitTest wasmJsNodeTest linuxX64Test
2. git add -> buildbot (automatic build + deploy)
-------------------------------------------------
The buildbot master (http://192.168.3.110:8010) polls
http://192.168.3.110/git/kukuri.git (branch main) every 30 seconds.
git add -A
git commit -m "..."
git push origin main # origin pushes to both gitea and github
Within ~30s a build starts on the worker:
setup-git-auth -> git checkout -> detekt-gate -> assemble
-> jvm/android/wasm/native tests -> bundles
-> wait-github-ios (blocks until the Actions "ios" run for the same commit
finishes; fails the build if it fails)
-> fetch-github-ios (downloads the "kukuri-ios" artifact, stages
distributions/kukuri-ios-<v>.zip)
-> deploy-to-lighttpd (FTP upload of all zips + the apk)
Watch progress: http://192.168.3.110:8010 (waterfall / console view)
CLI watcher (waits for a build newer than the given number; exit 0 = success):
ops/watch-buildbot.sh 32 900 # e.g. wait for build # > 32, up to 15 min
Manual trigger for a specific revision:
curl -s -X POST http://192.168.3.110:8010/api/v2/forceschedulers/force \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"force","id":1,"params":{"revision":"<sha>"}}'
(omit "revision" to build HEAD)
Deployed result: http://192.168.3.110/artifact/kukuri/latest/
web app: http://192.168.3.110/artifact/kukuri/latest/web/index.html
android: http://192.168.3.110/artifact/kukuri/latest/kukuri-android-<v>.apk
zips: http://192.168.3.110/artifact/kukuri/latest/kukuri-*.zip
3. Changing the buildbot pipeline (deploy/buildbot/master/master.cfg)
---------------------------------------------------------------------
The repo copy deploy/buildbot/master/master.cfg is the source of truth. The
live master on 192.168.3.110 runs from /var/lib/buildbot/masters/default
(user "buildbot", system-wide /usr/bin/buildbot - the /opt/kukuri-buildbot dir
only keeps a spare copy of the cfg).
Apply (SSH password = ketsuban's git password, i.e. the worker's
/run/secrets/git_pass; sshpass keeps it one-shot):
PW=$(docker exec kukuri-worker cat /run/secrets/git_pass)
sshpass -p "$PW" scp deploy/buildbot/master/master.cfg \
root@192.168.3.110:/var/lib/buildbot/masters/default/master.cfg
sshpass -p "$PW" ssh root@192.168.3.110 \
"chown buildbot:buildbot /var/lib/buildbot/masters/default/master.cfg && \
buildbot reconfig /var/lib/buildbot/masters/default"
"Reconfiguration appears to have completed successfully" = ok, no restart
needed. Trigger a build to exercise the new pipeline (section 2).
4. Docker build test (CI parity before pushing)
-----------------------------------------------
The buildbot worker runs in a container ("kukuri-worker", built from
deploy/buildbot/worker/Dockerfile.worker) that already has JDK, Android SDK,
node and the shared gradle cache (GRADLE_USER_HOME=/var/jenkins_home/.gradle).
To verify exactly what CI will run before pushing, replay the committed tree
inside it:
# 1. archive the committed tree (use /root: /tmp of the dev shell is not
# visible to docker cp)
git archive main | gzip > /root/k.tgz
docker cp /root/k.tgz kukuri-worker:/tmp/k.tgz
# 2. replace the container's tree and run the full CI task list
docker exec kukuri-worker bash -c '
rm -rf /worker/kukuri-build/build &&
mkdir -p /worker/kukuri-build/build &&
tar xzf /tmp/k.tgz -C /worker/kukuri-build/build &&
cd /worker/kukuri-build/build &&
JAVA_HOME=/opt/java/openjdk GRADLE_USER_HOME=/var/jenkins_home/.gradle \
./gradlew :modules:orgflow-domain:detekt assemble jvmTest \
testDebugUnitTest testReleaseUnitTest wasmJsNodeTest linuxX64Test \
bundleDesktop bundleWasm bundleNative bundleWeb bundleApk'
Notes:
- Extracting a fresh archive (rm -rf + tar) guarantees no stale files from
deleted sources linger - same as CI's clean checkout.
- The gradle caches persist in the container volume, so repeat runs are fast.
- For a fresh worker container on any host: deploy/buildbot/worker/run-worker.sh.
5. Error logs & diagnostics
---------------------------
buildbot (web UI):
http://192.168.3.110:8010 -> builders -> kukuri-build -> click a build
Each step shows "stdio"; failed steps show the tail inline (red).
buildbot (API, same data as the UI):
steps of a build: curl -s http://192.168.3.110:8010/api/v2/builds/<BUILD>/steps
logs of a step: curl -s http://192.168.3.110:8010/api/v2/steps/<STEPID>/logs
full step log (raw): curl -s http://192.168.3.110:8010/api/v2/logs/<LOGID>/raw
(use the step's stepid and the log's logid from the JSON responses)
worker-side gradle reports (inside the kukuri-worker container):
detekt: modules/orgflow-domain/build/reports/detekt/detekt.txt
jvm tests: <module>/build/reports/tests/jvmTest/index.html
android tests: <module>/build/reports/tests/testDebugUnitTest/...
config cache: build/reports/configuration-cache/<...>/configuration-cache-report.html
problems: build/build/reports/problems/problems-report.html
e.g.:
docker exec kukuri-worker cat \
/worker/kukuri-build/build/modules/orgflow-domain/build/reports/detekt/detekt.txt
local docker build test (section 4): when ./gradlew fails there, rerun with the
failing task alone and grep around the failure:
docker exec kukuri-worker bash -c 'cd /worker/kukuri-build/build && \
JAVA_HOME=/opt/java/openjdk GRADLE_USER_HOME=/var/jenkins_home/.gradle \
./gradlew --console=plain <task> 2>&1 | grep -B2 -A8 "What went wrong"'
github actions (ios):
https://github.com/ketsuban152/kukuri/actions -> workflow run -> job step log
6. iOS
------
Two places:
- buildbot ships "kukuri-ios-<v>.zip" (frameworks + klibs from the Actions
run) to http://192.168.3.110/artifact/kukuri/latest/ together with the
other artifacts.
- the raw "kukuri-ios" Actions artifact stays on
https://github.com/ketsuban152/kukuri/actions
ios.yml uses actions/cache for ~/.gradle/caches, ~/.gradle/wrapper and ~/.konan
(key: ios-<os>-<hash of build scripts>) - the first run after a cache-key
change is cold, later runs reuse the Konan toolchain and task outputs.
The worker reads /run/secrets/github_token (a repo-scoped PAT) for the
artifact download; run-worker.sh mounts it from
/root/buildbot/secrets/github_token.
|