@whyour/qinglong 2.20.2-3 → 2.21.0-10

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.
Files changed (238) hide show
  1. package/.env.example +5 -0
  2. package/AGENTS.md +43 -0
  3. package/README-en.md +11 -0
  4. package/README.md +11 -0
  5. package/back/protos/api.proto +3 -0
  6. package/deploy/kubernetes/README.md +81 -0
  7. package/deploy/kubernetes/base/kustomization.yaml +5 -0
  8. package/deploy/kubernetes/base/qinglong.yaml +95 -0
  9. package/deploy/kubernetes/overlays/example/kustomization.yaml +10 -0
  10. package/docker/Dockerfile +51 -69
  11. package/docker/Dockerfile.310 +94 -0
  12. package/docker/Dockerfile.debian +120 -0
  13. package/docker/{310.Dockerfile → Dockerfile.debian310} +13 -5
  14. package/docker/docker-entrypoint.sh +95 -3
  15. package/docs/PROJECT_ARCHITECTURE.md +550 -0
  16. package/package.json +29 -28
  17. package/sample/config.sample.sh +19 -3
  18. package/sample/notify.js +145 -9
  19. package/sample/notify.py +110 -11
  20. package/shell/api.sh +51 -21
  21. package/shell/bot.sh +30 -16
  22. package/shell/check.sh +21 -19
  23. package/shell/lang/en.sh +105 -0
  24. package/shell/lang/zh.sh +105 -0
  25. package/shell/otask.sh +117 -28
  26. package/shell/preload/client.js +20 -2
  27. package/shell/preload/esm-loader.mjs +41 -0
  28. package/shell/preload/sitecustomize.js +36 -0
  29. package/shell/pub.sh +8 -8
  30. package/shell/rmlog.sh +5 -5
  31. package/shell/share.sh +50 -31
  32. package/shell/start.sh +40 -27
  33. package/shell/task.sh +10 -2
  34. package/shell/update.sh +22 -22
  35. package/static/build/api/config.js +17 -7
  36. package/static/build/api/cron.js +40 -3
  37. package/static/build/api/dashboard.js +344 -0
  38. package/static/build/api/env.js +40 -2
  39. package/static/build/api/index.js +2 -0
  40. package/static/build/api/log.js +15 -5
  41. package/static/build/api/script.js +34 -9
  42. package/static/build/api/system.js +22 -8
  43. package/static/build/api/user.js +6 -5
  44. package/static/build/app.js +22 -19
  45. package/static/build/config/const.js +8 -6
  46. package/static/build/config/container.js +12 -0
  47. package/static/build/config/grpcCerts.js +150 -0
  48. package/static/build/config/index.js +6 -4
  49. package/static/build/config/util.js +69 -18
  50. package/static/build/data/cron.js +3 -1
  51. package/static/build/data/cronStats.js +59 -0
  52. package/static/build/data/env.js +2 -0
  53. package/static/build/data/notify.js +18 -1
  54. package/static/build/data/runningInstance.js +57 -0
  55. package/static/build/data/sock.js +1 -0
  56. package/static/build/loaders/app.js +7 -7
  57. package/static/build/loaders/db.js +8 -2
  58. package/static/build/loaders/deps.js +1 -22
  59. package/static/build/loaders/express.js +19 -15
  60. package/static/build/loaders/initData.js +20 -2
  61. package/static/build/loaders/initFile.js +3 -1
  62. package/static/build/loaders/initTask.js +3 -2
  63. package/static/build/loaders/server.js +1 -1
  64. package/static/build/protos/api.js +23 -1
  65. package/static/build/schedule/addCron.js +67 -10
  66. package/static/build/schedule/api.js +1 -1
  67. package/static/build/schedule/client.js +9 -1
  68. package/static/build/schedule/delCron.js +11 -1
  69. package/static/build/schedule/health.js +1 -1
  70. package/static/build/services/config.js +19 -5
  71. package/static/build/services/cron.js +198 -38
  72. package/static/build/services/dependence.js +19 -18
  73. package/static/build/services/env.js +31 -3
  74. package/static/build/services/grpc.js +32 -6
  75. package/static/build/services/http.js +33 -18
  76. package/static/build/services/notify.js +87 -8
  77. package/static/build/services/open.js +2 -1
  78. package/static/build/services/sshKey.js +6 -3
  79. package/static/build/services/subscription.js +8 -5
  80. package/static/build/services/system.js +34 -9
  81. package/static/build/services/user.js +39 -13
  82. package/static/build/shared/auth.js +7 -1
  83. package/static/build/shared/i18n.js +160 -0
  84. package/static/build/shared/pLimit.js +15 -3
  85. package/static/build/shared/runCron.js +5 -0
  86. package/static/build/shared/store.js +7 -0
  87. package/static/build/validation/schedule.js +10 -0
  88. package/static/dist/1089.0ecc5383.async.js +1 -0
  89. package/static/dist/1147.62793604.async.js +1 -0
  90. package/static/dist/1192.4e5740f2.async.js +1 -0
  91. package/static/dist/1214.c6469b53.async.js +1 -0
  92. package/static/dist/134.54df9e38.async.js +1 -0
  93. package/static/dist/1352.96a77e1d.async.js +1 -0
  94. package/static/dist/{1765.d8e002d7.async.js → 1765.5ac01a93.async.js} +1 -1
  95. package/static/dist/1836.f0b74cf1.async.js +1 -0
  96. package/static/dist/{1885.e0d00d2d.async.js → 1885.e1ea09f6.async.js} +1 -1
  97. package/static/dist/1967.3f3945d0.async.js +1 -0
  98. package/static/dist/{2096.383c1047.async.js → 2096.6d98fd12.async.js} +1 -1
  99. package/static/dist/2208.85285476.async.js +1 -0
  100. package/static/dist/2286.f371c743.async.js +1 -0
  101. package/static/dist/2476.4e9b0992.async.js +1 -0
  102. package/static/dist/2537.2b262ee0.async.js +1 -0
  103. package/static/dist/{255.12f03ab2.async.js → 255.8a80b983.async.js} +1 -1
  104. package/static/dist/2635.d4c59d23.async.js +1 -0
  105. package/static/dist/2808.cdc0995c.async.js +1 -0
  106. package/static/dist/{2821.be3dc88e.async.js → 2821.651f31e5.async.js} +1 -1
  107. package/static/dist/2986.4c49eef7.async.js +1 -0
  108. package/static/dist/300.08ac9875.async.js +1 -0
  109. package/static/dist/3191.545ab873.async.js +1 -0
  110. package/static/dist/3714.8d6dba9e.async.js +1 -0
  111. package/static/dist/3906.a5eee612.async.js +1 -0
  112. package/static/dist/{6541.a6d499de.async.js → 3948.4fe809fd.async.js} +1 -1
  113. package/static/dist/{5171.7fc6d0a2.async.js → 4573.16f19278.async.js} +1 -1
  114. package/static/dist/{4859.93e63ea6.async.js → 4859.6592cebb.async.js} +1 -1
  115. package/static/dist/4887.8e3ae573.async.js +1 -0
  116. package/static/dist/{4902.54ecbdb5.async.js → 4902.555f92ab.async.js} +1 -1
  117. package/static/dist/{4934.1ca6b6b0.async.js → 4934.f3539d08.async.js} +1 -1
  118. package/static/dist/5077.cbd111cd.async.js +1 -0
  119. package/static/dist/{6247.b550d996.async.js → 5157.7c5af144.async.js} +1 -1
  120. package/static/dist/{540.481d4708.async.js → 540.19ddf020.async.js} +1 -1
  121. package/static/dist/{5970.10ac4f16.async.js → 5970.d3a6e7bd.async.js} +1 -1
  122. package/static/dist/{6013.2d7bb12a.async.js → 6013.4e38de36.async.js} +1 -1
  123. package/static/dist/{6016.9c379049.async.js → 6016.1e6574b6.async.js} +1 -1
  124. package/static/dist/{6035.5889ddc7.async.js → 6035.32ebfad9.async.js} +1 -1
  125. package/static/dist/6339.ab305e96.async.js +1 -0
  126. package/static/dist/6569.55177f6a.async.js +1 -0
  127. package/static/dist/6610.c111af7e.async.js +1 -0
  128. package/static/dist/{3034.6413c38e.async.js → 6638.87a163d2.async.js} +1 -1
  129. package/static/dist/{6646.5fc37228.async.js → 6646.95e92533.async.js} +1 -1
  130. package/static/dist/6665.1d099ad1.async.js +1 -0
  131. package/static/dist/{7355.b7c0562f.async.js → 7355.f9f263d8.async.js} +1 -1
  132. package/static/dist/{7384.065ccae2.async.js → 7384.1bb449d5.async.js} +1 -1
  133. package/static/dist/7441.ee1bf2bb.async.js +1 -0
  134. package/static/dist/{7508.a31662a3.async.js → 7508.7dcee91c.async.js} +1 -1
  135. package/static/dist/{7802.6b73f16a.async.js → 7802.34255805.async.js} +1 -1
  136. package/static/dist/{7984.e6bb9378.async.js → 7984.594296a5.async.js} +1 -1
  137. package/static/dist/{5653.4fce7ce8.async.js → 8033.5cb31493.async.js} +1 -1
  138. package/static/dist/8147.2fb55202.async.js +1 -0
  139. package/static/dist/8187.48c130d6.async.js +1 -0
  140. package/static/dist/8495.d53e15ca.async.js +1 -0
  141. package/static/dist/8587.315b06c0.async.js +1 -0
  142. package/static/dist/8826.db34ad8d.async.js +1 -0
  143. package/static/dist/{2742.4852aac8.async.js → 8865.ed665d31.async.js} +1 -1
  144. package/static/dist/901.7ee5c6d3.async.js +1 -0
  145. package/static/dist/9271.231db2ce.async.js +1 -0
  146. package/static/dist/9323.a33f47da.async.js +1 -0
  147. package/static/dist/{9730.30083c91.async.js → 9730.801665a3.async.js} +1 -1
  148. package/static/dist/{9761.627ca3b5.async.js → 9761.360a19d8.async.js} +1 -1
  149. package/static/dist/index.html +2 -2
  150. package/static/dist/layouts__index.a7a2bfe0.async.js +1 -0
  151. package/static/dist/layouts__index.adf0692f.chunk.css +1 -0
  152. package/static/dist/preload_helper.3048fe5b.js +1 -0
  153. package/static/dist/{src__pages__config__index.622b6ee8.async.js → src__pages__config__index.a22ff7dc.async.js} +1 -1
  154. package/static/dist/{src__pages__crontab__const.323d5124.async.js → src__pages__crontab__const.aba07deb.async.js} +1 -1
  155. package/static/dist/src__pages__crontab__detail.b98f0084.async.js +1 -0
  156. package/static/dist/src__pages__crontab__index.68e78a33.async.js +1 -0
  157. package/static/dist/{src__pages__crontab__logModal.5e6a4bf2.async.js → src__pages__crontab__logModal.831d5e4b.async.js} +1 -1
  158. package/static/dist/src__pages__crontab__modal.f7041c7c.async.js +1 -0
  159. package/static/dist/src__pages__crontab__type.d7af36e5.async.js +1 -0
  160. package/static/dist/{src__pages__crontab__viewCreateModal.ffcf7a24.async.js → src__pages__crontab__viewCreateModal.4d589f66.async.js} +1 -1
  161. package/static/dist/{src__pages__crontab__viewManageModal.c2724575.async.js → src__pages__crontab__viewManageModal.0e317746.async.js} +1 -1
  162. package/static/dist/src__pages__dashboard__index.58177357.async.js +1 -0
  163. package/static/dist/src__pages__dependence__index.b7bbc795.async.js +1 -0
  164. package/static/dist/{src__pages__dependence__logModal.f123e2ac.async.js → src__pages__dependence__logModal.0681830b.async.js} +1 -1
  165. package/static/dist/src__pages__dependence__modal.f7bb47ba.async.js +1 -0
  166. package/static/dist/src__pages__env__editNameModal.48715576.async.js +1 -0
  167. package/static/dist/src__pages__env__index.452cdc47.async.js +1 -0
  168. package/static/dist/src__pages__env__modal.e1234834.async.js +1 -0
  169. package/static/dist/src__pages__error__index.dedb2b90.async.js +1 -0
  170. package/static/dist/src__pages__initialization__index.22620a77.async.js +1 -0
  171. package/static/dist/src__pages__log__index.9c66639f.async.js +1 -0
  172. package/static/dist/{src__pages__login__index.cd6e3152.async.js → src__pages__login__index.8c813eb1.async.js} +1 -1
  173. package/static/dist/{src__pages__script__components__UnsupportedFilePreview__index.39074c68.async.js → src__pages__script__components__UnsupportedFilePreview__index.c347a13a.async.js} +1 -1
  174. package/static/dist/src__pages__script__editNameModal.532a3044.async.js +1 -0
  175. package/static/dist/src__pages__script__index.1fc20f22.async.js +1 -0
  176. package/static/dist/src__pages__script__renameModal.5cdde919.async.js +1 -0
  177. package/static/dist/src__pages__script__saveModal.5ffed35f.async.js +1 -0
  178. package/static/dist/src__pages__script__setting.1a82c6d7.async.js +1 -0
  179. package/static/dist/src__pages__setting__appModal.43b7758a.async.js +1 -0
  180. package/static/dist/src__pages__setting__checkUpdate.34d773f2.async.js +1 -0
  181. package/static/dist/src__pages__setting__dependence.9c04c79a.async.js +1 -0
  182. package/static/dist/src__pages__setting__index.7e070838.async.js +1 -0
  183. package/static/dist/src__pages__setting__notification.bac481c2.async.js +1 -0
  184. package/static/dist/src__pages__setting__other.707cfafe.async.js +1 -0
  185. package/static/dist/src__pages__setting__security.b7235753.async.js +1 -0
  186. package/static/dist/src__pages__setting__systemLog.b81a8c1d.async.js +1 -0
  187. package/static/dist/{src__pages__subscription__logModal.0caa7283.async.js → src__pages__subscription__logModal.3864b37f.async.js} +1 -1
  188. package/static/dist/src__pages__subscription__modal.562448e2.async.js +1 -0
  189. package/static/dist/{umi.ef8199a4.js → umi.a54a59f6.js} +1 -1
  190. package/version.yaml +33 -4
  191. package/sample/notify.py.save +0 -1010
  192. package/static/dist/105.85a5c47a.async.js +0 -1
  193. package/static/dist/1083.f86ce804.async.js +0 -1
  194. package/static/dist/1147.32f41a88.async.js +0 -1
  195. package/static/dist/1352.ab6da08e.async.js +0 -1
  196. package/static/dist/1690.f0290540.async.js +0 -1
  197. package/static/dist/1742.6cbe5aca.async.js +0 -1
  198. package/static/dist/2208.8e3a7325.async.js +0 -1
  199. package/static/dist/3191.70bc19db.async.js +0 -1
  200. package/static/dist/5312.74b95311.async.js +0 -1
  201. package/static/dist/5691.931f59c5.async.js +0 -1
  202. package/static/dist/6159.55cb068a.async.js +0 -1
  203. package/static/dist/7025.f4080d63.async.js +0 -1
  204. package/static/dist/739.6be5552a.async.js +0 -1
  205. package/static/dist/7571.4f6240b1.async.js +0 -1
  206. package/static/dist/786.59fc381c.async.js +0 -1
  207. package/static/dist/8317.c44c1ebd.async.js +0 -1
  208. package/static/dist/8826.0291edfd.async.js +0 -1
  209. package/static/dist/955.3c9481f7.async.js +0 -1
  210. package/static/dist/layouts__index.1fce90e0.chunk.css +0 -1
  211. package/static/dist/layouts__index.8dcf1576.async.js +0 -1
  212. package/static/dist/preload_helper.116a62f6.js +0 -1
  213. package/static/dist/src__pages__crontab__detail.b07f0c0a.async.js +0 -1
  214. package/static/dist/src__pages__crontab__index.2e2e1096.async.js +0 -1
  215. package/static/dist/src__pages__crontab__modal.4d8c2a22.async.js +0 -1
  216. package/static/dist/src__pages__crontab__type.db7c1858.async.js +0 -1
  217. package/static/dist/src__pages__dependence__index.3d87ceac.async.js +0 -1
  218. package/static/dist/src__pages__dependence__modal.631ffb5b.async.js +0 -1
  219. package/static/dist/src__pages__env__editNameModal.ff85ef8c.async.js +0 -1
  220. package/static/dist/src__pages__env__index.a0a2fece.async.js +0 -1
  221. package/static/dist/src__pages__env__modal.d1004662.async.js +0 -1
  222. package/static/dist/src__pages__error__index.1bc3c90b.async.js +0 -1
  223. package/static/dist/src__pages__initialization__index.8b1cbaf9.async.js +0 -1
  224. package/static/dist/src__pages__log__index.cf00c9af.async.js +0 -1
  225. package/static/dist/src__pages__script__editNameModal.53424d49.async.js +0 -1
  226. package/static/dist/src__pages__script__index.e65df827.async.js +0 -1
  227. package/static/dist/src__pages__script__renameModal.4bbe7fb1.async.js +0 -1
  228. package/static/dist/src__pages__script__saveModal.cf449f3c.async.js +0 -1
  229. package/static/dist/src__pages__script__setting.b345d59a.async.js +0 -1
  230. package/static/dist/src__pages__setting__appModal.03faec89.async.js +0 -1
  231. package/static/dist/src__pages__setting__checkUpdate.46efe057.async.js +0 -1
  232. package/static/dist/src__pages__setting__dependence.4495c7b6.async.js +0 -1
  233. package/static/dist/src__pages__setting__index.6919c399.async.js +0 -1
  234. package/static/dist/src__pages__setting__notification.d6a3884f.async.js +0 -1
  235. package/static/dist/src__pages__setting__other.0d931d6f.async.js +0 -1
  236. package/static/dist/src__pages__setting__security.91cb545f.async.js +0 -1
  237. package/static/dist/src__pages__setting__systemLog.1d433a48.async.js +0 -1
  238. package/static/dist/src__pages__subscription__modal.0b84f6cf.async.js +0 -1
package/.env.example CHANGED
@@ -1,6 +1,11 @@
1
1
  GRPC_PORT=5500
2
2
  BACK_PORT=5700
3
3
 
4
+ # 服务绑定地址,默认 ::(IPv6 通配,双栈系统同时支持 IPv4/IPv6)
5
+ # 纯 IPv4 环境自动 fallback 到 0.0.0.0,也可手动指定
6
+ # BIND_HOST=0.0.0.0
7
+ # BIND_HOST_GRPC=0.0.0.0
8
+
4
9
  LOG_LEVEL='info'
5
10
 
6
11
  JWT_SECRET=
package/AGENTS.md ADDED
@@ -0,0 +1,43 @@
1
+ <!-- gitnexus:start -->
2
+ # GitNexus — Code Intelligence
3
+
4
+ This project is indexed by GitNexus as **qinglong** (2778 symbols, 6698 relationships, 233 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
5
+
6
+ > Index stale? Run `node .gitnexus/run.cjs analyze` from the project root — it auto-selects an available runner. No `.gitnexus/run.cjs` yet? `npx gitnexus analyze` (npm 11 crash → `npm i -g gitnexus`; #1939).
7
+
8
+ ## Always Do
9
+
10
+ - **MUST run impact analysis before editing any symbol.** Before modifying a function, class, or method, run `impact({target: "symbolName", direction: "upstream"})` and report the blast radius (direct callers, affected processes, risk level) to the user.
11
+ - **MUST run `detect_changes()` before committing** to verify your changes only affect expected symbols and execution flows. For regression review, compare against the default branch: `detect_changes({scope: "compare", base_ref: "develop"})`.
12
+ - **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits.
13
+ - When exploring unfamiliar code, use `query({query: "concept"})` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance.
14
+ - When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use `context({name: "symbolName"})`.
15
+
16
+ ## Never Do
17
+
18
+ - NEVER edit a function, class, or method without first running `impact` on it.
19
+ - NEVER ignore HIGH or CRITICAL risk warnings from impact analysis.
20
+ - NEVER rename symbols with find-and-replace — use `rename` which understands the call graph.
21
+ - NEVER commit changes without running `detect_changes()` to check affected scope.
22
+
23
+ ## Resources
24
+
25
+ | Resource | Use for |
26
+ |----------|---------|
27
+ | `gitnexus://repo/qinglong/context` | Codebase overview, check index freshness |
28
+ | `gitnexus://repo/qinglong/clusters` | All functional areas |
29
+ | `gitnexus://repo/qinglong/processes` | All execution flows |
30
+ | `gitnexus://repo/qinglong/process/{name}` | Step-by-step execution trace |
31
+
32
+ ## CLI
33
+
34
+ | Task | Read this skill file |
35
+ |------|---------------------|
36
+ | Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` |
37
+ | Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` |
38
+ | Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` |
39
+ | Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` |
40
+ | Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` |
41
+ | Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` |
42
+
43
+ <!-- gitnexus:end -->
package/README-en.md CHANGED
@@ -48,6 +48,17 @@ docker pull whyour/qinglong:latest
48
48
  docker pull whyour/qinglong:debian
49
49
  ```
50
50
 
51
+ When running the `debian` image as a non-root user, specify `--user qinglong`:
52
+
53
+ ```bash
54
+ docker run -d \
55
+ -v /path/to/ql/data:/ql/data \
56
+ -p 5700:5700 \
57
+ --user qinglong \
58
+ --name qinglong \
59
+ whyour/qinglong:debian
60
+ ```
61
+
51
62
  ### npm
52
63
 
53
64
  The npm version supports `debian/ubuntu/alpine` systems and requires `node/npm/python3/pip3/pnpm` to be installed.
package/README.md CHANGED
@@ -50,6 +50,17 @@ docker pull whyour/qinglong:latest
50
50
  docker pull whyour/qinglong:debian
51
51
  ```
52
52
 
53
+ 使用 `debian` 镜像以非 root 用户运行时,需指定 `--user qinglong`:
54
+
55
+ ```bash
56
+ docker run -d \
57
+ -v /path/to/ql/data:/ql/data \
58
+ -p 5700:5700 \
59
+ --user qinglong \
60
+ --name qinglong \
61
+ whyour/qinglong:debian
62
+ ```
63
+
53
64
  ### npm
54
65
 
55
66
  npm 版本支持 `debian/ubuntu/alpine` 系统,需要自行安装 `node/npm/python3/pip3/pnpm`
@@ -151,6 +151,7 @@ enum NotificationMode {
151
151
  chronocat = 18;
152
152
  ntfy = 19;
153
153
  wxPusherBot = 20;
154
+ wxPusherSpt = 21;
154
155
  }
155
156
 
156
157
  message NotificationInfo {
@@ -244,6 +245,8 @@ message NotificationInfo {
244
245
  optional string wxPusherBotAppToken = 66;
245
246
  optional string wxPusherBotTopicIds = 67;
246
247
  optional string wxPusherBotUids = 68;
248
+
249
+ optional string wxPusherSptList = 70;
247
250
  }
248
251
 
249
252
  message SystemNotifyRequest {
@@ -0,0 +1,81 @@
1
+ # Kubernetes deployment
2
+
3
+ This deploys Qinglong as a single-replica `StatefulSet` with persistent data at `/ql/data`.
4
+
5
+ ```bash
6
+ kubectl apply -k deploy/kubernetes/overlays/local
7
+ kubectl -n qinglong rollout status statefulset/qinglong
8
+ ```
9
+
10
+ Open the panel locally:
11
+
12
+ ```bash
13
+ kubectl -n qinglong port-forward svc/qinglong 5700:5700
14
+ ```
15
+
16
+ Then visit <http://127.0.0.1:5700>.
17
+
18
+ ## Image registry overlays
19
+
20
+ Use `overlays/example` as the committed template for registry customization:
21
+
22
+ ```yaml
23
+ whyour/qinglong:debian -> registry.example.com/whyour/qinglong:debian
24
+ ```
25
+
26
+ Create `overlays/local/kustomization.yaml` for the actual cluster image. The `local` overlay is ignored by git so private registry names, digests, and credentials-related references stay local.
27
+
28
+ ## Storage
29
+
30
+ The manifest creates a 5 GiB `ReadWriteOnce` PVC from the cluster's default `StorageClass`.
31
+ If your cluster has no default storage class, add `storageClassName` under:
32
+
33
+ ```yaml
34
+ volumeClaimTemplates:
35
+ - metadata:
36
+ name: data
37
+ spec:
38
+ storageClassName: your-storage-class
39
+ ```
40
+
41
+ Keep `replicas: 1`. Qinglong stores state in the persistent data directory, including SQLite files, so multiple replicas should not share the same data volume.
42
+
43
+ ## Ingress example
44
+
45
+ If you expose Qinglong through an Ingress path other than `/`, set `QlBaseUrl` to the same path with leading and trailing slashes.
46
+
47
+ ```yaml
48
+ env:
49
+ - name: QlBaseUrl
50
+ value: "/qinglong/"
51
+ ```
52
+
53
+ Example Ingress:
54
+
55
+ ```yaml
56
+ apiVersion: networking.k8s.io/v1
57
+ kind: Ingress
58
+ metadata:
59
+ name: qinglong
60
+ namespace: qinglong
61
+ spec:
62
+ rules:
63
+ - host: qinglong.example.com
64
+ http:
65
+ paths:
66
+ - path: /
67
+ pathType: Prefix
68
+ backend:
69
+ service:
70
+ name: qinglong
71
+ port:
72
+ number: 5700
73
+ ```
74
+
75
+ ## Maintenance commands
76
+
77
+ ```bash
78
+ kubectl -n qinglong logs -f statefulset/qinglong
79
+ kubectl -n qinglong exec -it statefulset/qinglong -- ql check
80
+ kubectl -n qinglong exec -it statefulset/qinglong -- ql update
81
+ ```
@@ -0,0 +1,5 @@
1
+ apiVersion: kustomize.config.k8s.io/v1beta1
2
+ kind: Kustomization
3
+
4
+ resources:
5
+ - qinglong.yaml
@@ -0,0 +1,95 @@
1
+ apiVersion: v1
2
+ kind: Namespace
3
+ metadata:
4
+ name: qinglong
5
+ ---
6
+ apiVersion: v1
7
+ kind: Service
8
+ metadata:
9
+ name: qinglong
10
+ namespace: qinglong
11
+ labels:
12
+ app.kubernetes.io/name: qinglong
13
+ spec:
14
+ type: ClusterIP
15
+ selector:
16
+ app.kubernetes.io/name: qinglong
17
+ ports:
18
+ - name: http
19
+ port: 5700
20
+ targetPort: http
21
+ ---
22
+ apiVersion: apps/v1
23
+ kind: StatefulSet
24
+ metadata:
25
+ name: qinglong
26
+ namespace: qinglong
27
+ labels:
28
+ app.kubernetes.io/name: qinglong
29
+ spec:
30
+ serviceName: qinglong
31
+ replicas: 1
32
+ selector:
33
+ matchLabels:
34
+ app.kubernetes.io/name: qinglong
35
+ template:
36
+ metadata:
37
+ labels:
38
+ app.kubernetes.io/name: qinglong
39
+ spec:
40
+ securityContext:
41
+ fsGroup: 5432
42
+ fsGroupChangePolicy: OnRootMismatch
43
+ containers:
44
+ - name: qinglong
45
+ image: whyour/qinglong:debian
46
+ imagePullPolicy: IfNotPresent
47
+ env:
48
+ - name: QlBaseUrl
49
+ value: "/"
50
+ - name: TZ
51
+ value: Asia/Shanghai
52
+ ports:
53
+ - name: http
54
+ containerPort: 5700
55
+ readinessProbe:
56
+ httpGet:
57
+ path: /api/health
58
+ port: http
59
+ initialDelaySeconds: 20
60
+ periodSeconds: 10
61
+ timeoutSeconds: 3
62
+ failureThreshold: 6
63
+ livenessProbe:
64
+ httpGet:
65
+ path: /api/health
66
+ port: http
67
+ initialDelaySeconds: 60
68
+ periodSeconds: 20
69
+ timeoutSeconds: 3
70
+ failureThreshold: 6
71
+ startupProbe:
72
+ httpGet:
73
+ path: /api/health
74
+ port: http
75
+ periodSeconds: 5
76
+ timeoutSeconds: 3
77
+ failureThreshold: 60
78
+ resources:
79
+ requests:
80
+ cpu: 100m
81
+ memory: 256Mi
82
+ limits:
83
+ memory: 1Gi
84
+ volumeMounts:
85
+ - name: data
86
+ mountPath: /ql/data
87
+ volumeClaimTemplates:
88
+ - metadata:
89
+ name: data
90
+ spec:
91
+ accessModes:
92
+ - ReadWriteOnce
93
+ resources:
94
+ requests:
95
+ storage: 5Gi
@@ -0,0 +1,10 @@
1
+ apiVersion: kustomize.config.k8s.io/v1beta1
2
+ kind: Kustomization
3
+
4
+ resources:
5
+ - ../../base
6
+
7
+ images:
8
+ - name: whyour/qinglong
9
+ newName: registry.example.com/whyour/qinglong
10
+ newTag: debian
package/docker/Dockerfile CHANGED
@@ -1,18 +1,13 @@
1
- FROM node:22-slim AS nodebuilder
2
-
3
- FROM python:3.11-slim-bookworm AS builder
1
+ FROM python:3.11-alpine3.18 AS builder
4
2
  COPY package.json .npmrc pnpm-lock.yaml /tmp/build/
5
- COPY --from=nodebuilder /usr/local/bin/node /usr/local/bin/
6
- COPY --from=nodebuilder /usr/local/lib/node_modules/. /usr/local/lib/node_modules/
7
- RUN set -x && \
8
- ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
9
- apt-get update && \
10
- apt-get install --no-install-recommends -y libatomic1 && \
11
- npm i -g pnpm@8.3.1 && \
12
- cd /tmp/build && \
13
- pnpm install --prod
14
-
15
- FROM python:3.11-slim-bookworm
3
+ RUN set -x \
4
+ && apk update \
5
+ && apk add nodejs npm git \
6
+ && npm i -g pnpm@8.3.1 pm2 ts-node \
7
+ && cd /tmp/build \
8
+ && pnpm install --prod
9
+
10
+ FROM python:3.11-alpine
16
11
 
17
12
  ARG QL_MAINTAINER="whyour"
18
13
  LABEL maintainer="${QL_MAINTAINER}"
@@ -22,67 +17,56 @@ ARG PYTHON_SHORT_VERSION=3.11
22
17
 
23
18
  ENV QL_DIR=/ql \
24
19
  QL_BRANCH=${QL_BRANCH} \
20
+ QL_CONTAINER=true \
25
21
  LANG=C.UTF-8 \
26
22
  SHELL=/bin/bash \
27
23
  PS1="\u@\h:\w \$ "
28
24
 
29
- ARG QL_UID=5432
30
- ARG QL_GID=5432
31
- RUN groupadd -g ${QL_GID} qinglong && \
32
- useradd -m -u ${QL_UID} -g ${QL_GID} -s /bin/bash qinglong && \
33
- mkdir -p /home/qinglong/bin /home/qinglong/.ssh && \
34
- chmod 700 /home/qinglong/.ssh && \
35
- chown -R ${QL_UID}:${QL_GID} /home/qinglong
36
-
37
- ENV QL_USER=qinglong
38
- ENV QL_HOME=/home/$QL_USER
39
-
40
- COPY --from=nodebuilder /usr/local/bin/node /usr/local/bin/
41
- COPY --from=nodebuilder /usr/local/lib/node_modules/. /usr/local/lib/node_modules/
42
-
43
- RUN set -x && \
44
- ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm && \
45
- ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx && \
46
- apt-get update && \
47
- apt-get upgrade -y && \
48
- apt-get install --no-install-recommends -y git \
25
+ VOLUME /ql/data
26
+
27
+ EXPOSE 5700
28
+
29
+ COPY --from=builder /usr/local/lib/node_modules/. /usr/local/lib/node_modules/
30
+ COPY --from=builder /usr/local/bin/. /usr/local/bin/
31
+
32
+ RUN set -x \
33
+ && apk update -f \
34
+ && apk upgrade \
35
+ && apk --no-cache add -f bash \
36
+ coreutils \
37
+ git \
49
38
  curl \
50
39
  wget \
51
40
  tzdata \
52
41
  perl \
53
42
  openssl \
54
- openssh-client \
43
+ nodejs \
55
44
  jq \
45
+ openssh \
56
46
  procps \
57
47
  netcat-openbsd \
58
48
  unzip \
59
- libatomic1 && \
60
- apt-get clean && \
61
- ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
62
- echo "Asia/Shanghai" >/etc/timezone && \
63
- git config --global user.email "qinglong@users.noreply.github.com" && \
64
- git config --global user.name "qinglong" && \
65
- git config --global http.postBuffer 524288000 && \
66
- npm install -g pnpm@8.3.1 pm2 ts-node && \
67
- rm -rf /root/.cache && \
68
- rm -rf /root/.npm && \
69
- rm -rf /etc/apt/apt.conf.d/docker-clean && \
70
- ulimit -c 0
71
-
72
- RUN mkdir -p ${QL_DIR} && \
73
- chown -R ${QL_UID}:${QL_GID} ${QL_DIR}
74
-
75
- USER qinglong
49
+ npm \
50
+ && rm -rf /var/cache/apk/* \
51
+ && apk update \
52
+ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
53
+ && echo "Asia/Shanghai" > /etc/timezone \
54
+ && git config --global user.email "qinglong@users.noreply.github.com" \
55
+ && git config --global user.name "qinglong" \
56
+ && git config --global http.postBuffer 524288000 \
57
+ && rm -rf /root/.cache \
58
+ && ulimit -c 0
59
+
76
60
  ARG SOURCE_COMMIT
77
- RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} && \
78
- cd ${QL_DIR} && \
79
- cp -f .env.example .env && \
80
- chmod 777 ${QL_DIR}/shell/*.sh && \
81
- chmod 777 ${QL_DIR}/docker/*.sh && \
82
- git clone --depth=1 -b ${QL_BRANCH} https://github.com/${QL_MAINTAINER}/qinglong-static.git /tmp/static && \
83
- mkdir -p ${QL_DIR}/static && \
84
- cp -rf /tmp/static/* ${QL_DIR}/static && \
85
- rm -rf /tmp/static
61
+ RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
62
+ && cd ${QL_DIR} \
63
+ && cp -f .env.example .env \
64
+ && chmod 777 ${QL_DIR}/shell/*.sh \
65
+ && chmod 777 ${QL_DIR}/docker/*.sh \
66
+ && git clone --depth=1 -b ${QL_BRANCH} https://github.com/${QL_MAINTAINER}/qinglong-static.git /static \
67
+ && mkdir -p ${QL_DIR}/static \
68
+ && cp -rf /static/* ${QL_DIR}/static \
69
+ && rm -rf /static
86
70
 
87
71
  ENV PNPM_HOME=${QL_DIR}/data/dep_cache/node \
88
72
  PYTHON_HOME=${QL_DIR}/data/dep_cache/python3 \
@@ -90,23 +74,21 @@ ENV PNPM_HOME=${QL_DIR}/data/dep_cache/node \
90
74
  HOME=/root
91
75
 
92
76
  ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${PNPM_HOME}:${PYTHON_HOME}/bin:${HOME}/bin \
93
- NODE_PATH=/usr/local/bin:/usr/local/lib/node_modules:${PNPM_HOME}/global/5/node_modules \
77
+ NODE_PATH=/usr/local/bin:/usr/local/lib/node_modules \
94
78
  PIP_CACHE_DIR=${PYTHON_HOME}/pip \
95
79
  PYTHONPATH=${PYTHON_HOME}:${PYTHON_HOME}/lib/python${PYTHON_SHORT_VERSION}:${PYTHON_HOME}/lib/python${PYTHON_SHORT_VERSION}/site-packages
96
80
 
97
81
  RUN pip3 install --prefix ${PYTHON_HOME} requests
98
82
 
99
- COPY --chown=qinglong:qinglong --from=builder /tmp/build/node_modules/. /ql/node_modules/
83
+ COPY --from=builder /tmp/build/node_modules/. /ql/node_modules/
100
84
 
101
- USER root
85
+ RUN ln -sf ${QL_DIR}/shell/task.sh /usr/local/bin/task \
86
+ && ln -sf ${QL_DIR}/shell/update.sh /usr/local/bin/ql \
87
+ && chmod +x /usr/local/bin/task /usr/local/bin/ql
102
88
 
103
89
  WORKDIR ${QL_DIR}
104
90
 
105
91
  HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
106
- CMD curl -sf --noproxy '*' http://127.0.0.1:5700/api/health || exit 1
92
+ CMD curl -sf --noproxy '*' http://localhost:${QlPort:-5700}/api/health || exit 1
107
93
 
108
94
  ENTRYPOINT ["./docker/docker-entrypoint.sh"]
109
-
110
- VOLUME /ql/data
111
-
112
- EXPOSE 5700
@@ -0,0 +1,94 @@
1
+ FROM python:3.10-alpine3.18 AS builder
2
+ COPY package.json .npmrc pnpm-lock.yaml /tmp/build/
3
+ RUN set -x \
4
+ && apk update \
5
+ && apk add nodejs npm git \
6
+ && npm i -g pnpm@8.3.1 pm2 ts-node \
7
+ && cd /tmp/build \
8
+ && pnpm install --prod
9
+
10
+ FROM python:3.10-alpine
11
+
12
+ ARG QL_MAINTAINER="whyour"
13
+ LABEL maintainer="${QL_MAINTAINER}"
14
+ ARG QL_URL=https://github.com/${QL_MAINTAINER}/qinglong.git
15
+ ARG QL_BRANCH=develop
16
+ ARG PYTHON_SHORT_VERSION=3.10
17
+
18
+ ENV QL_DIR=/ql \
19
+ QL_BRANCH=${QL_BRANCH} \
20
+ QL_CONTAINER=true \
21
+ LANG=C.UTF-8 \
22
+ SHELL=/bin/bash \
23
+ PS1="\u@\h:\w \$ "
24
+
25
+ VOLUME /ql/data
26
+
27
+ EXPOSE 5700
28
+
29
+ COPY --from=builder /usr/local/lib/node_modules/. /usr/local/lib/node_modules/
30
+ COPY --from=builder /usr/local/bin/. /usr/local/bin/
31
+
32
+ RUN set -x \
33
+ && apk update -f \
34
+ && apk upgrade \
35
+ && apk --no-cache add -f bash \
36
+ coreutils \
37
+ git \
38
+ curl \
39
+ wget \
40
+ tzdata \
41
+ perl \
42
+ openssl \
43
+ nodejs \
44
+ jq \
45
+ openssh \
46
+ procps \
47
+ netcat-openbsd \
48
+ unzip \
49
+ npm \
50
+ && rm -rf /var/cache/apk/* \
51
+ && apk update \
52
+ && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
53
+ && echo "Asia/Shanghai" > /etc/timezone \
54
+ && git config --global user.email "qinglong@users.noreply.github.com" \
55
+ && git config --global user.name "qinglong" \
56
+ && git config --global http.postBuffer 524288000 \
57
+ && rm -rf /root/.cache \
58
+ && ulimit -c 0
59
+
60
+ ARG SOURCE_COMMIT
61
+ RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
62
+ && cd ${QL_DIR} \
63
+ && cp -f .env.example .env \
64
+ && chmod 777 ${QL_DIR}/shell/*.sh \
65
+ && chmod 777 ${QL_DIR}/docker/*.sh \
66
+ && git clone --depth=1 -b ${QL_BRANCH} https://github.com/${QL_MAINTAINER}/qinglong-static.git /static \
67
+ && mkdir -p ${QL_DIR}/static \
68
+ && cp -rf /static/* ${QL_DIR}/static \
69
+ && rm -rf /static
70
+
71
+ ENV PNPM_HOME=${QL_DIR}/data/dep_cache/node \
72
+ PYTHON_HOME=${QL_DIR}/data/dep_cache/python3 \
73
+ PYTHONUSERBASE=${QL_DIR}/data/dep_cache/python3 \
74
+ HOME=/root
75
+
76
+ ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${PNPM_HOME}:${PYTHON_HOME}/bin:${HOME}/bin \
77
+ NODE_PATH=/usr/local/bin:/usr/local/lib/node_modules \
78
+ PIP_CACHE_DIR=${PYTHON_HOME}/pip \
79
+ PYTHONPATH=${PYTHON_HOME}:${PYTHON_HOME}/lib/python${PYTHON_SHORT_VERSION}:${PYTHON_HOME}/lib/python${PYTHON_SHORT_VERSION}/site-packages
80
+
81
+ RUN pip3 install --prefix ${PYTHON_HOME} requests
82
+
83
+ COPY --from=builder /tmp/build/node_modules/. /ql/node_modules/
84
+
85
+ RUN ln -sf ${QL_DIR}/shell/task.sh /usr/local/bin/task \
86
+ && ln -sf ${QL_DIR}/shell/update.sh /usr/local/bin/ql \
87
+ && chmod +x /usr/local/bin/task /usr/local/bin/ql
88
+
89
+ WORKDIR ${QL_DIR}
90
+
91
+ HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
92
+ CMD curl -sf --noproxy '*' http://localhost:${QlPort:-5700}/api/health || exit 1
93
+
94
+ ENTRYPOINT ["./docker/docker-entrypoint.sh"]