biucingcli 0.9.1__py3-none-any.whl

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 (269) hide show
  1. biucingcli/__init__.py +5 -0
  2. biucingcli/cli.py +849 -0
  3. biucingcli/template_data/android/template/.editorconfig +9 -0
  4. biucingcli/template_data/android/template/.gitignore +26 -0
  5. biucingcli/template_data/android/template/.mise.toml +3 -0
  6. biucingcli/template_data/android/template/Brewfile +6 -0
  7. biucingcli/template_data/android/template/Makefile +103 -0
  8. biucingcli/template_data/android/template/README.md +163 -0
  9. biucingcli/template_data/android/template/app/build.gradle.kts +178 -0
  10. biucingcli/template_data/android/template/app/proguard-rules.pro +1 -0
  11. biucingcli/template_data/android/template/app/src/androidTest/java/app/HomeRouteUiTest.kt +21 -0
  12. biucingcli/template_data/android/template/app/src/main/AndroidManifest.xml +18 -0
  13. biucingcli/template_data/android/template/app/src/main/java/app/MainActivity.kt +36 -0
  14. biucingcli/template_data/android/template/app/src/main/res/values/strings.xml +4 -0
  15. biucingcli/template_data/android/template/app/src/main/res/values/themes.xml +8 -0
  16. biucingcli/template_data/android/template/app/src/test/java/app/AppSmokeTest.kt +19 -0
  17. biucingcli/template_data/android/template/build.gradle.kts +27 -0
  18. biucingcli/template_data/android/template/core/designsystem/build.gradle.kts +33 -0
  19. biucingcli/template_data/android/template/core/designsystem/src/main/java/designsystem/Components.kt +75 -0
  20. biucingcli/template_data/android/template/core/designsystem/src/main/java/designsystem/DesignTokens.kt +23 -0
  21. biucingcli/template_data/android/template/core/designsystem/src/main/java/designsystem/Theme.kt +110 -0
  22. biucingcli/template_data/android/template/core/model/build.gradle.kts +26 -0
  23. biucingcli/template_data/android/template/core/model/src/main/java/model/Greeting.kt +6 -0
  24. biucingcli/template_data/android/template/core/model/src/test/java/model/GreetingTest.kt +16 -0
  25. biucingcli/template_data/android/template/core/network/build.gradle.kts +26 -0
  26. biucingcli/template_data/android/template/core/network/src/main/java/network/AppEnvironment.kt +17 -0
  27. biucingcli/template_data/android/template/core/testing/build.gradle.kts +27 -0
  28. biucingcli/template_data/android/template/core/testing/src/main/java/testing/FakeAppEnvironmentProvider.kt +13 -0
  29. biucingcli/template_data/android/template/docs/release-delivery.md +68 -0
  30. biucingcli/template_data/android/template/docs/release-signing.properties.example +20 -0
  31. biucingcli/template_data/android/template/fastlane/.env.example +22 -0
  32. biucingcli/template_data/android/template/fastlane/Appfile +1 -0
  33. biucingcli/template_data/android/template/fastlane/Fastfile +121 -0
  34. biucingcli/template_data/android/template/feature/home/build.gradle.kts +35 -0
  35. biucingcli/template_data/android/template/feature/home/src/main/java/home/HomeRoute.kt +38 -0
  36. biucingcli/template_data/android/template/feature/settings/build.gradle.kts +34 -0
  37. biucingcli/template_data/android/template/feature/settings/src/main/java/settings/SettingsRoute.kt +35 -0
  38. biucingcli/template_data/android/template/gradle/libs.versions.toml +35 -0
  39. biucingcli/template_data/android/template/gradle/verification-metadata.xml +3462 -0
  40. biucingcli/template_data/android/template/gradle/wrapper/gradle-wrapper.jar +0 -0
  41. biucingcli/template_data/android/template/gradle/wrapper/gradle-wrapper.jar.sha256 +1 -0
  42. biucingcli/template_data/android/template/gradle/wrapper/gradle-wrapper.properties +10 -0
  43. biucingcli/template_data/android/template/gradle.properties +4 -0
  44. biucingcli/template_data/android/template/gradlew +252 -0
  45. biucingcli/template_data/android/template/gradlew.bat +94 -0
  46. biucingcli/template_data/android/template/scripts/artifact-info +11 -0
  47. biucingcli/template_data/android/template/scripts/bootstrap +17 -0
  48. biucingcli/template_data/android/template/scripts/doctor +133 -0
  49. biucingcli/template_data/android/template/scripts/setup-android-sdk +23 -0
  50. biucingcli/template_data/android/template/scripts/sync-gradle-wrapper +19 -0
  51. biucingcli/template_data/android/template/scripts/verify-gradle-supply-chain +61 -0
  52. biucingcli/template_data/android/template/scripts/verify-release-artifact +104 -0
  53. biucingcli/template_data/android/template/settings.gradle.kts +25 -0
  54. biucingcli/template_data/android/template.json +146 -0
  55. biucingcli/template_data/apple/template/.gitignore +28 -0
  56. biucingcli/template_data/apple/template/.mise.toml +4 -0
  57. biucingcli/template_data/apple/template/.swiftformat +10 -0
  58. biucingcli/template_data/apple/template/.swiftlint.yml +33 -0
  59. biucingcli/template_data/apple/template/App/Config/ProjectDescriptionHelpers/Module.swift +6 -0
  60. biucingcli/template_data/apple/template/App/Config/XCConfig/Base.xcconfig +4 -0
  61. biucingcli/template_data/apple/template/App/Project.swift +66 -0
  62. biucingcli/template_data/apple/template/App/Targets/App/Resources/.gitkeep +1 -0
  63. biucingcli/template_data/apple/template/App/Targets/App/Sources/AppEntry.swift +9 -0
  64. biucingcli/template_data/apple/template/App/Targets/App/Sources/HomeView.swift +18 -0
  65. biucingcli/template_data/apple/template/App/Targets/App/Sources/HomeViewModel.swift +38 -0
  66. biucingcli/template_data/apple/template/App/Targets/AppTests/Sources/AppTests.swift +59 -0
  67. biucingcli/template_data/apple/template/Brewfile +8 -0
  68. biucingcli/template_data/apple/template/Makefile +128 -0
  69. biucingcli/template_data/apple/template/Packages/AppServices/Package.swift +20 -0
  70. biucingcli/template_data/apple/template/Packages/AppServices/Sources/AppServices/StarterMetadata.swift +52 -0
  71. biucingcli/template_data/apple/template/Packages/DesignSystem/Package.swift +20 -0
  72. biucingcli/template_data/apple/template/Packages/DesignSystem/Sources/DesignSystem/Theme.swift +8 -0
  73. biucingcli/template_data/apple/template/README.md +133 -0
  74. biucingcli/template_data/apple/template/Tuist.swift +8 -0
  75. biucingcli/template_data/apple/template/Workspace.swift +11 -0
  76. biucingcli/template_data/apple/template/docs/release-delivery.md +55 -0
  77. biucingcli/template_data/apple/template/fastlane/.env.example +20 -0
  78. biucingcli/template_data/apple/template/fastlane/Appfile +3 -0
  79. biucingcli/template_data/apple/template/fastlane/Fastfile +126 -0
  80. biucingcli/template_data/apple/template/fastlane/Matchfile +7 -0
  81. biucingcli/template_data/apple/template/scripts/bootstrap +9 -0
  82. biucingcli/template_data/apple/template/scripts/doctor +163 -0
  83. biucingcli/template_data/apple/template/scripts/setup-xcode +6 -0
  84. biucingcli/template_data/apple/template/scripts/test-destination +42 -0
  85. biucingcli/template_data/apple/template/scripts/verify-release-identity +88 -0
  86. biucingcli/template_data/apple/template.json +110 -0
  87. biucingcli/template_data/frontend/template/.dockerignore +8 -0
  88. biucingcli/template_data/frontend/template/.env.example +1 -0
  89. biucingcli/template_data/frontend/template/.gitignore +7 -0
  90. biucingcli/template_data/frontend/template/.npmrc +1 -0
  91. biucingcli/template_data/frontend/template/.prettierignore +2 -0
  92. biucingcli/template_data/frontend/template/.prettierrc.json +4 -0
  93. biucingcli/template_data/frontend/template/Dockerfile +25 -0
  94. biucingcli/template_data/frontend/template/Dockerfile.dev +35 -0
  95. biucingcli/template_data/frontend/template/Dockerfile.dev.full +40 -0
  96. biucingcli/template_data/frontend/template/Makefile +137 -0
  97. biucingcli/template_data/frontend/template/README.md +146 -0
  98. biucingcli/template_data/frontend/template/compose.dev.yaml +29 -0
  99. biucingcli/template_data/frontend/template/eslint.config.js +27 -0
  100. biucingcli/template_data/frontend/template/index.html +12 -0
  101. biucingcli/template_data/frontend/template/nginx.conf +11 -0
  102. biucingcli/template_data/frontend/template/package.json +50 -0
  103. biucingcli/template_data/frontend/template/playwright.production.config.ts +21 -0
  104. biucingcli/template_data/frontend/template/playwright.smoke.config.ts +19 -0
  105. biucingcli/template_data/frontend/template/pnpm-lock.yaml +4054 -0
  106. biucingcli/template_data/frontend/template/public/.gitkeep +1 -0
  107. biucingcli/template_data/frontend/template/scripts/browser-smoke-production +55 -0
  108. biucingcli/template_data/frontend/template/scripts/doctor +46 -0
  109. biucingcli/template_data/frontend/template/src/App.test.tsx +18 -0
  110. biucingcli/template_data/frontend/template/src/App.tsx +5 -0
  111. biucingcli/template_data/frontend/template/src/components/MetricCard.tsx +14 -0
  112. biucingcli/template_data/frontend/template/src/components/TaskPanel.tsx +32 -0
  113. biucingcli/template_data/frontend/template/src/config/env.ts +3 -0
  114. biucingcli/template_data/frontend/template/src/hooks/useProjectOverview.ts +24 -0
  115. biucingcli/template_data/frontend/template/src/index.css +208 -0
  116. biucingcli/template_data/frontend/template/src/main.tsx +11 -0
  117. biucingcli/template_data/frontend/template/src/pages/HomePage.tsx +60 -0
  118. biucingcli/template_data/frontend/template/src/router/AppRouter.tsx +14 -0
  119. biucingcli/template_data/frontend/template/src/services/api/client.ts +33 -0
  120. biucingcli/template_data/frontend/template/src/services/projectOverview.ts +39 -0
  121. biucingcli/template_data/frontend/template/src/test/setup.ts +1 -0
  122. biucingcli/template_data/frontend/template/src/types/projectOverview.ts +22 -0
  123. biucingcli/template_data/frontend/template/src/vite-env.d.ts +9 -0
  124. biucingcli/template_data/frontend/template/tests/browser-smoke.spec.ts +16 -0
  125. biucingcli/template_data/frontend/template/tests/production-browser-smoke.spec.ts +22 -0
  126. biucingcli/template_data/frontend/template/tsconfig.json +21 -0
  127. biucingcli/template_data/frontend/template/vite.config.ts +12 -0
  128. biucingcli/template_data/frontend/template.json +81 -0
  129. biucingcli/template_data/harmonyos/template/.gitignore +21 -0
  130. biucingcli/template_data/harmonyos/template/.mise.toml +2 -0
  131. biucingcli/template_data/harmonyos/template/AppScope/app.json5 +10 -0
  132. biucingcli/template_data/harmonyos/template/AppScope/resources/base/element/string.json +8 -0
  133. biucingcli/template_data/harmonyos/template/AppScope/resources/base/media/background.svg +3 -0
  134. biucingcli/template_data/harmonyos/template/AppScope/resources/base/media/foreground.svg +4 -0
  135. biucingcli/template_data/harmonyos/template/AppScope/resources/base/media/layered_image.json +6 -0
  136. biucingcli/template_data/harmonyos/template/Makefile +106 -0
  137. biucingcli/template_data/harmonyos/template/README.md +152 -0
  138. biucingcli/template_data/harmonyos/template/build-profile.json5 +36 -0
  139. biucingcli/template_data/harmonyos/template/code-linter.json5 +12 -0
  140. biucingcli/template_data/harmonyos/template/docs/release-signing.local.properties.example +14 -0
  141. biucingcli/template_data/harmonyos/template/entry/build-profile.json5 +9 -0
  142. biucingcli/template_data/harmonyos/template/entry/hvigorfile.ts +6 -0
  143. biucingcli/template_data/harmonyos/template/entry/oh-package.json5 +9 -0
  144. biucingcli/template_data/harmonyos/template/entry/src/main/ets/core/config/AppConfig.ets +10 -0
  145. biucingcli/template_data/harmonyos/template/entry/src/main/ets/core/designsystem/Tokens.ets +28 -0
  146. biucingcli/template_data/harmonyos/template/entry/src/main/ets/entryability/EntryAbility.ets +29 -0
  147. biucingcli/template_data/harmonyos/template/entry/src/main/ets/pages/Index.ets +47 -0
  148. biucingcli/template_data/harmonyos/template/entry/src/main/ets/pages/Settings.ets +96 -0
  149. biucingcli/template_data/harmonyos/template/entry/src/main/module.json5 +34 -0
  150. biucingcli/template_data/harmonyos/template/entry/src/main/resources/base/element/color.json +24 -0
  151. biucingcli/template_data/harmonyos/template/entry/src/main/resources/base/element/string.json +12 -0
  152. biucingcli/template_data/harmonyos/template/entry/src/main/resources/base/media/app_icon.svg +5 -0
  153. biucingcli/template_data/harmonyos/template/entry/src/main/resources/base/profile/main_pages.json +6 -0
  154. biucingcli/template_data/harmonyos/template/entry/src/test/List.test.ets +11 -0
  155. biucingcli/template_data/harmonyos/template/hvigor/hvigor-config.json5 +8 -0
  156. biucingcli/template_data/harmonyos/template/hvigorfile.ts +6 -0
  157. biucingcli/template_data/harmonyos/template/oh-package-lock.json5 +19 -0
  158. biucingcli/template_data/harmonyos/template/oh-package.json5 +13 -0
  159. biucingcli/template_data/harmonyos/template/scripts/artifact-info +31 -0
  160. biucingcli/template_data/harmonyos/template/scripts/bootstrap +38 -0
  161. biucingcli/template_data/harmonyos/template/scripts/doctor +147 -0
  162. biucingcli/template_data/harmonyos/template/scripts/lint +105 -0
  163. biucingcli/template_data/harmonyos/template/scripts/release-build +199 -0
  164. biucingcli/template_data/harmonyos/template/scripts/release-preflight +109 -0
  165. biucingcli/template_data/harmonyos/template/scripts/test +28 -0
  166. biucingcli/template_data/harmonyos/template/scripts/verify-release-artifact +173 -0
  167. biucingcli/template_data/harmonyos/template/scripts/verify-supply-chain +70 -0
  168. biucingcli/template_data/harmonyos/template.json +134 -0
  169. biucingcli/template_data/microservice/template/.air.toml +11 -0
  170. biucingcli/template_data/microservice/template/.dockerignore +5 -0
  171. biucingcli/template_data/microservice/template/.gitignore +4 -0
  172. biucingcli/template_data/microservice/template/.mise.toml +3 -0
  173. biucingcli/template_data/microservice/template/Brewfile +7 -0
  174. biucingcli/template_data/microservice/template/Dockerfile +44 -0
  175. biucingcli/template_data/microservice/template/Dockerfile.dev +50 -0
  176. biucingcli/template_data/microservice/template/Makefile +145 -0
  177. biucingcli/template_data/microservice/template/README.md +191 -0
  178. biucingcli/template_data/microservice/template/api/buf.gen.yaml +11 -0
  179. biucingcli/template_data/microservice/template/api/buf.yaml +11 -0
  180. biucingcli/template_data/microservice/template/api/proto/service/v1/service.proto +18 -0
  181. biucingcli/template_data/microservice/template/cmd/server/main.go +81 -0
  182. biucingcli/template_data/microservice/template/compose.dev.yaml +49 -0
  183. biucingcli/template_data/microservice/template/configs/config.yaml +18 -0
  184. biucingcli/template_data/microservice/template/deploy/compose.yaml +35 -0
  185. biucingcli/template_data/microservice/template/deploy/otel-collector.yaml +15 -0
  186. biucingcli/template_data/microservice/template/go.mod +53 -0
  187. biucingcli/template_data/microservice/template/go.sum +138 -0
  188. biucingcli/template_data/microservice/template/internal/config/config.go +112 -0
  189. biucingcli/template_data/microservice/template/internal/config/config_test.go +92 -0
  190. biucingcli/template_data/microservice/template/internal/handler/health.go +25 -0
  191. biucingcli/template_data/microservice/template/internal/handler/ping.go +25 -0
  192. biucingcli/template_data/microservice/template/internal/model/health.go +8 -0
  193. biucingcli/template_data/microservice/template/internal/model/ping.go +7 -0
  194. biucingcli/template_data/microservice/template/internal/repository/.gitkeep +1 -0
  195. biucingcli/template_data/microservice/template/internal/router/router.go +26 -0
  196. biucingcli/template_data/microservice/template/internal/runtime/server.go +116 -0
  197. biucingcli/template_data/microservice/template/internal/runtime/server_test.go +161 -0
  198. biucingcli/template_data/microservice/template/internal/service/health.go +26 -0
  199. biucingcli/template_data/microservice/template/internal/service/ping.go +23 -0
  200. biucingcli/template_data/microservice/template/internal/telemetry/telemetry.go +56 -0
  201. biucingcli/template_data/microservice/template/internal/transport/grpc.go +51 -0
  202. biucingcli/template_data/microservice/template/internal/transport/ping.go +28 -0
  203. biucingcli/template_data/microservice/template/scripts/bootstrap +29 -0
  204. biucingcli/template_data/microservice/template/scripts/doctor +115 -0
  205. biucingcli/template_data/microservice/template/tests/server_test.go +153 -0
  206. biucingcli/template_data/microservice/template.json +114 -0
  207. biucingcli/template_data/web-service/template/.air.toml +11 -0
  208. biucingcli/template_data/web-service/template/.dockerignore +5 -0
  209. biucingcli/template_data/web-service/template/.gitignore +5 -0
  210. biucingcli/template_data/web-service/template/.mise.toml +2 -0
  211. biucingcli/template_data/web-service/template/Brewfile +5 -0
  212. biucingcli/template_data/web-service/template/Dockerfile +41 -0
  213. biucingcli/template_data/web-service/template/Dockerfile.dev +45 -0
  214. biucingcli/template_data/web-service/template/Makefile +113 -0
  215. biucingcli/template_data/web-service/template/README.md +164 -0
  216. biucingcli/template_data/web-service/template/cmd/server/main.go +50 -0
  217. biucingcli/template_data/web-service/template/compose.dev.yaml +28 -0
  218. biucingcli/template_data/web-service/template/compose.yaml +14 -0
  219. biucingcli/template_data/web-service/template/configs/config.yaml +10 -0
  220. biucingcli/template_data/web-service/template/go.mod +36 -0
  221. biucingcli/template_data/web-service/template/go.sum +89 -0
  222. biucingcli/template_data/web-service/template/internal/config/config.go +84 -0
  223. biucingcli/template_data/web-service/template/internal/config/config_test.go +88 -0
  224. biucingcli/template_data/web-service/template/internal/handler/health.go +25 -0
  225. biucingcli/template_data/web-service/template/internal/handler/ping.go +25 -0
  226. biucingcli/template_data/web-service/template/internal/handler/user.go +40 -0
  227. biucingcli/template_data/web-service/template/internal/model/health.go +6 -0
  228. biucingcli/template_data/web-service/template/internal/model/ping.go +7 -0
  229. biucingcli/template_data/web-service/template/internal/model/user.go +7 -0
  230. biucingcli/template_data/web-service/template/internal/repository/.gitkeep +1 -0
  231. biucingcli/template_data/web-service/template/internal/repository/user.go +37 -0
  232. biucingcli/template_data/web-service/template/internal/router/router.go +28 -0
  233. biucingcli/template_data/web-service/template/internal/runtime/server.go +76 -0
  234. biucingcli/template_data/web-service/template/internal/runtime/server_test.go +139 -0
  235. biucingcli/template_data/web-service/template/internal/service/health.go +22 -0
  236. biucingcli/template_data/web-service/template/internal/service/ping.go +23 -0
  237. biucingcli/template_data/web-service/template/internal/service/user.go +27 -0
  238. biucingcli/template_data/web-service/template/scripts/bootstrap +23 -0
  239. biucingcli/template_data/web-service/template/scripts/doctor +83 -0
  240. biucingcli/template_data/web-service/template/tests/server_test.go +160 -0
  241. biucingcli/template_data/web-service/template.json +88 -0
  242. biucingcli/template_data/worker/template/.dockerignore +3 -0
  243. biucingcli/template_data/worker/template/.gitignore +2 -0
  244. biucingcli/template_data/worker/template/.mise.toml +2 -0
  245. biucingcli/template_data/worker/template/Brewfile +1 -0
  246. biucingcli/template_data/worker/template/Dockerfile +19 -0
  247. biucingcli/template_data/worker/template/Dockerfile.dev +9 -0
  248. biucingcli/template_data/worker/template/Makefile +105 -0
  249. biucingcli/template_data/worker/template/README.md +164 -0
  250. biucingcli/template_data/worker/template/cmd/worker/main.go +41 -0
  251. biucingcli/template_data/worker/template/compose.dev.yaml +29 -0
  252. biucingcli/template_data/worker/template/configs/config.json +11 -0
  253. biucingcli/template_data/worker/template/go.mod +3 -0
  254. biucingcli/template_data/worker/template/go.sum +1 -0
  255. biucingcli/template_data/worker/template/internal/config/config.go +108 -0
  256. biucingcli/template_data/worker/template/internal/config/config_test.go +86 -0
  257. biucingcli/template_data/worker/template/internal/runtime/runner.go +199 -0
  258. biucingcli/template_data/worker/template/internal/runtime/runner_test.go +215 -0
  259. biucingcli/template_data/worker/template/internal/task/heartbeat.go +19 -0
  260. biucingcli/template_data/worker/template/scripts/bootstrap +6 -0
  261. biucingcli/template_data/worker/template/scripts/doctor +41 -0
  262. biucingcli/template_data/worker/template/tests/worker_test.go +44 -0
  263. biucingcli/template_data/worker/template.json +100 -0
  264. biucingcli/templates.py +902 -0
  265. biucingcli-0.9.1.dist-info/METADATA +204 -0
  266. biucingcli-0.9.1.dist-info/RECORD +269 -0
  267. biucingcli-0.9.1.dist-info/WHEEL +5 -0
  268. biucingcli-0.9.1.dist-info/entry_points.txt +2 -0
  269. biucingcli-0.9.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,139 @@
1
+ package runtime
2
+
3
+ import (
4
+ "context"
5
+ "errors"
6
+ "net"
7
+ "net/http"
8
+ "net/http/httptest"
9
+ "testing"
10
+ "time"
11
+
12
+ "{{MODULE_NAME}}/internal/config"
13
+ )
14
+
15
+ func TestCheckHealthRequiresSuccessfulResponse(t *testing.T) {
16
+ healthServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
17
+ if request.URL.Path != "/healthz" {
18
+ writer.WriteHeader(http.StatusNotFound)
19
+ return
20
+ }
21
+ writer.WriteHeader(http.StatusOK)
22
+ }))
23
+ defer healthServer.Close()
24
+
25
+ if err := CheckHealth(context.Background(), healthServer.URL+"/healthz"); err != nil {
26
+ t.Fatal(err)
27
+ }
28
+ if err := CheckHealth(context.Background(), healthServer.URL+"/missing"); err == nil {
29
+ t.Fatal("expected a non-success status to fail the health check")
30
+ }
31
+ }
32
+
33
+ func TestNewHTTPServerAppliesTimeouts(t *testing.T) {
34
+ server := NewHTTPServer(config.Config{
35
+ Service: config.ServiceConfig{Port: "8080"},
36
+ Server: config.ServerConfig{
37
+ ReadTimeoutSeconds: 1,
38
+ ReadHeaderTimeoutSeconds: 2,
39
+ WriteTimeoutSeconds: 3,
40
+ IdleTimeoutSeconds: 4,
41
+ },
42
+ }, http.NewServeMux())
43
+
44
+ if server.ReadTimeout != time.Second || server.ReadHeaderTimeout != 2*time.Second {
45
+ t.Fatalf("unexpected read timeouts: %s, %s", server.ReadTimeout, server.ReadHeaderTimeout)
46
+ }
47
+ if server.WriteTimeout != 3*time.Second || server.IdleTimeout != 4*time.Second {
48
+ t.Fatalf("unexpected connection timeouts: %s, %s", server.WriteTimeout, server.IdleTimeout)
49
+ }
50
+ }
51
+
52
+ func TestServeDrainsInFlightRequest(t *testing.T) {
53
+ requestStarted := make(chan struct{})
54
+ releaseRequest := make(chan struct{})
55
+ handler := http.HandlerFunc(func(writer http.ResponseWriter, _ *http.Request) {
56
+ close(requestStarted)
57
+ <-releaseRequest
58
+ writer.WriteHeader(http.StatusNoContent)
59
+ })
60
+
61
+ listener, err := net.Listen("tcp", "127.0.0.1:0")
62
+ if err != nil {
63
+ t.Fatal(err)
64
+ }
65
+
66
+ ctx, cancel := context.WithCancel(context.Background())
67
+ serveDone := make(chan error, 1)
68
+ go func() {
69
+ serveDone <- Serve(ctx, &http.Server{Handler: handler}, listener, time.Second)
70
+ }()
71
+
72
+ requestDone := make(chan error, 1)
73
+ go func() {
74
+ response, requestErr := http.Get("http://" + listener.Addr().String())
75
+ if response != nil {
76
+ _ = response.Body.Close()
77
+ }
78
+ requestDone <- requestErr
79
+ }()
80
+
81
+ select {
82
+ case <-requestStarted:
83
+ case <-time.After(time.Second):
84
+ t.Fatal("request did not reach the server")
85
+ }
86
+
87
+ cancel()
88
+ select {
89
+ case err := <-serveDone:
90
+ t.Fatalf("server returned before the request drained: %v", err)
91
+ case <-time.After(25 * time.Millisecond):
92
+ }
93
+
94
+ close(releaseRequest)
95
+ if err := <-requestDone; err != nil {
96
+ t.Fatal(err)
97
+ }
98
+ if err := <-serveDone; err != nil {
99
+ t.Fatal(err)
100
+ }
101
+ }
102
+
103
+ func TestServeEnforcesShutdownTimeout(t *testing.T) {
104
+ requestStarted := make(chan struct{})
105
+ handler := http.HandlerFunc(func(_ http.ResponseWriter, request *http.Request) {
106
+ close(requestStarted)
107
+ <-request.Context().Done()
108
+ })
109
+
110
+ listener, err := net.Listen("tcp", "127.0.0.1:0")
111
+ if err != nil {
112
+ t.Fatal(err)
113
+ }
114
+
115
+ ctx, cancel := context.WithCancel(context.Background())
116
+ serveDone := make(chan error, 1)
117
+ go func() {
118
+ serveDone <- Serve(ctx, &http.Server{Handler: handler}, listener, 25*time.Millisecond)
119
+ }()
120
+ go func() {
121
+ _, _ = http.Get("http://" + listener.Addr().String())
122
+ }()
123
+
124
+ select {
125
+ case <-requestStarted:
126
+ case <-time.After(time.Second):
127
+ t.Fatal("request did not reach the server")
128
+ }
129
+ cancel()
130
+
131
+ select {
132
+ case err := <-serveDone:
133
+ if !errors.Is(err, context.DeadlineExceeded) {
134
+ t.Fatalf("expected shutdown deadline, got %v", err)
135
+ }
136
+ case <-time.After(time.Second):
137
+ t.Fatal("shutdown timeout was not enforced")
138
+ }
139
+ }
@@ -0,0 +1,22 @@
1
+ package service
2
+
3
+ import "{{MODULE_NAME}}/internal/model"
4
+
5
+ type HealthService interface {
6
+ Status() model.HealthResponse
7
+ }
8
+
9
+ type healthService struct {
10
+ serviceName string
11
+ }
12
+
13
+ func NewHealthService(serviceName string) HealthService {
14
+ return healthService{serviceName: serviceName}
15
+ }
16
+
17
+ func (service healthService) Status() model.HealthResponse {
18
+ return model.HealthResponse{
19
+ Service: service.serviceName,
20
+ Status: "ok",
21
+ }
22
+ }
@@ -0,0 +1,23 @@
1
+ package service
2
+
3
+ import "{{MODULE_NAME}}/internal/model"
4
+
5
+ type PingService interface {
6
+ Ping() model.PingResponse
7
+ }
8
+
9
+ type pingService struct {
10
+ serviceName string
11
+ }
12
+
13
+ func NewPingService(serviceName string) PingService {
14
+ return pingService{serviceName: serviceName}
15
+ }
16
+
17
+ func (service pingService) Ping() model.PingResponse {
18
+ return model.PingResponse{
19
+ Service: service.serviceName,
20
+ Message: "pong",
21
+ Version: "v1",
22
+ }
23
+ }
@@ -0,0 +1,27 @@
1
+ package service
2
+
3
+ import (
4
+ "{{MODULE_NAME}}/internal/model"
5
+ "{{MODULE_NAME}}/internal/repository"
6
+ )
7
+
8
+ type UserService interface {
9
+ ListUsers() []model.User
10
+ GetUser(id string) (model.User, bool)
11
+ }
12
+
13
+ type userService struct {
14
+ repository repository.UserRepository
15
+ }
16
+
17
+ func NewUserService(repository repository.UserRepository) UserService {
18
+ return userService{repository: repository}
19
+ }
20
+
21
+ func (service userService) ListUsers() []model.User {
22
+ return service.repository.List()
23
+ }
24
+
25
+ func (service userService) GetUser(id string) (model.User, bool) {
26
+ return service.repository.GetByID(id)
27
+ }
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ if command -v brew >/dev/null 2>&1; then
5
+ brew bundle
6
+ else
7
+ echo "brew not found; skipping Brewfile install."
8
+ fi
9
+
10
+ if command -v mise >/dev/null 2>&1; then
11
+ mise install
12
+ else
13
+ echo "mise not found; skipping runtime install."
14
+ fi
15
+
16
+ if ! command -v go >/dev/null 2>&1; then
17
+ echo "go is not available on PATH."
18
+ echo "Install Go with Homebrew or activate it through mise, then rerun ./scripts/bootstrap."
19
+ exit 1
20
+ fi
21
+
22
+ go mod tidy
23
+ ./scripts/doctor
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ if ! command -v go >/dev/null 2>&1; then
5
+ echo "go is not installed or not on PATH."
6
+ exit 1
7
+ fi
8
+
9
+ go_version="$(go env GOVERSION)"
10
+ echo "Go toolchain: $go_version"
11
+
12
+ if [[ -z "${GOCACHE:-}" ]]; then
13
+ export GOCACHE="$(pwd)/.cache/go-build"
14
+ fi
15
+ mkdir -p "$GOCACHE"
16
+
17
+ if [[ ! -f "./go.mod" ]]; then
18
+ echo "go.mod is missing."
19
+ exit 1
20
+ fi
21
+
22
+ if [[ ! -f "./go.sum" ]]; then
23
+ echo "go.sum is missing."
24
+ echo "Run 'go mod tidy' or './scripts/bootstrap' to resolve dependencies first."
25
+ exit 1
26
+ fi
27
+
28
+ if [[ ! -f "./configs/config.yaml" ]]; then
29
+ echo "configs/config.yaml is missing."
30
+ exit 1
31
+ fi
32
+
33
+ if ! grep -q "name:" ./configs/config.yaml; then
34
+ echo "configs/config.yaml must define service.name."
35
+ exit 1
36
+ fi
37
+
38
+ if ! grep -q "port:" ./configs/config.yaml; then
39
+ echo "configs/config.yaml must define service.port."
40
+ exit 1
41
+ fi
42
+
43
+ service_name="$(sed -n 's/^ name: //p' ./configs/config.yaml | head -n 1)"
44
+ service_port="$(sed -n 's/^ port: //p' ./configs/config.yaml | head -n 1)"
45
+
46
+ if [[ -z "$service_name" ]]; then
47
+ echo "configs/config.yaml service.name must not be empty."
48
+ exit 1
49
+ fi
50
+
51
+ if [[ ! "$service_port" =~ ^[0-9]+$ ]]; then
52
+ echo "configs/config.yaml service.port must be a numeric string."
53
+ exit 1
54
+ fi
55
+
56
+ if (( service_port < 1 || service_port > 65535 )); then
57
+ echo "configs/config.yaml service.port must be between 1 and 65535."
58
+ exit 1
59
+ fi
60
+
61
+ if ! go list -m >/dev/null 2>&1; then
62
+ echo "go.mod does not define a valid module."
63
+ exit 1
64
+ fi
65
+
66
+ if ! CONFIG_FILE=./configs/config.yaml go test ./internal/config -run TestLoadDefaultConfig -count=1 >/dev/null; then
67
+ echo "config loader could not read configs/config.yaml successfully."
68
+ exit 1
69
+ fi
70
+
71
+ if command -v golangci-lint >/dev/null 2>&1; then
72
+ echo "golangci-lint: available"
73
+ else
74
+ echo "golangci-lint: not installed; make lint and make verify will be unavailable."
75
+ fi
76
+
77
+ if command -v docker >/dev/null 2>&1; then
78
+ echo "Docker: available"
79
+ else
80
+ echo "Docker: not installed; container workflows will be unavailable."
81
+ fi
82
+
83
+ echo "Environment looks ready."
@@ -0,0 +1,160 @@
1
+ package tests
2
+
3
+ import (
4
+ "encoding/json"
5
+ "net/http"
6
+ "net/http/httptest"
7
+ "testing"
8
+
9
+ "{{MODULE_NAME}}/internal/config"
10
+ "{{MODULE_NAME}}/internal/model"
11
+ "{{MODULE_NAME}}/internal/router"
12
+ )
13
+
14
+ func TestHealthz(t *testing.T) {
15
+ engine := router.New(config.Config{
16
+ Service: config.ServiceConfig{
17
+ Name: "{{SERVICE_NAME}}",
18
+ Port: "{{HTTP_PORT}}",
19
+ },
20
+ })
21
+
22
+ request := httptest.NewRequest(http.MethodGet, "/healthz", nil)
23
+ recorder := httptest.NewRecorder()
24
+
25
+ engine.ServeHTTP(recorder, request)
26
+
27
+ if recorder.Code != http.StatusOK {
28
+ t.Fatalf("expected status %d, got %d", http.StatusOK, recorder.Code)
29
+ }
30
+
31
+ var response model.HealthResponse
32
+ if err := json.Unmarshal(recorder.Body.Bytes(), &response); err != nil {
33
+ t.Fatal(err)
34
+ }
35
+
36
+ if response.Service != "{{SERVICE_NAME}}" {
37
+ t.Fatalf("expected service %q, got %q", "{{SERVICE_NAME}}", response.Service)
38
+ }
39
+
40
+ if response.Status != "ok" {
41
+ t.Fatalf("expected status %q, got %q", "ok", response.Status)
42
+ }
43
+ }
44
+
45
+ func TestListUsers(t *testing.T) {
46
+ engine := router.New(config.Config{
47
+ Service: config.ServiceConfig{
48
+ Name: "{{SERVICE_NAME}}",
49
+ Port: "{{HTTP_PORT}}",
50
+ },
51
+ })
52
+
53
+ request := httptest.NewRequest(http.MethodGet, "/api/v1/users", nil)
54
+ recorder := httptest.NewRecorder()
55
+
56
+ engine.ServeHTTP(recorder, request)
57
+
58
+ if recorder.Code != http.StatusOK {
59
+ t.Fatalf("expected status %d, got %d", http.StatusOK, recorder.Code)
60
+ }
61
+
62
+ var response struct {
63
+ Items []model.User `json:"items"`
64
+ }
65
+ if err := json.Unmarshal(recorder.Body.Bytes(), &response); err != nil {
66
+ t.Fatal(err)
67
+ }
68
+
69
+ if len(response.Items) != 2 {
70
+ t.Fatalf("expected %d users, got %d", 2, len(response.Items))
71
+ }
72
+
73
+ if response.Items[0].ID != "u_001" {
74
+ t.Fatalf("expected first user id %q, got %q", "u_001", response.Items[0].ID)
75
+ }
76
+ }
77
+
78
+ func TestGetUser(t *testing.T) {
79
+ engine := router.New(config.Config{
80
+ Service: config.ServiceConfig{
81
+ Name: "{{SERVICE_NAME}}",
82
+ Port: "{{HTTP_PORT}}",
83
+ },
84
+ })
85
+
86
+ request := httptest.NewRequest(http.MethodGet, "/api/v1/users/u_002", nil)
87
+ recorder := httptest.NewRecorder()
88
+
89
+ engine.ServeHTTP(recorder, request)
90
+
91
+ if recorder.Code != http.StatusOK {
92
+ t.Fatalf("expected status %d, got %d", http.StatusOK, recorder.Code)
93
+ }
94
+
95
+ var response model.User
96
+ if err := json.Unmarshal(recorder.Body.Bytes(), &response); err != nil {
97
+ t.Fatal(err)
98
+ }
99
+
100
+ if response.ID != "u_002" {
101
+ t.Fatalf("expected user id %q, got %q", "u_002", response.ID)
102
+ }
103
+
104
+ if response.Email != "alan@example.com" {
105
+ t.Fatalf("expected email %q, got %q", "alan@example.com", response.Email)
106
+ }
107
+ }
108
+
109
+ func TestGetUserNotFound(t *testing.T) {
110
+ engine := router.New(config.Config{
111
+ Service: config.ServiceConfig{
112
+ Name: "{{SERVICE_NAME}}",
113
+ Port: "{{HTTP_PORT}}",
114
+ },
115
+ })
116
+
117
+ request := httptest.NewRequest(http.MethodGet, "/api/v1/users/u_999", nil)
118
+ recorder := httptest.NewRecorder()
119
+
120
+ engine.ServeHTTP(recorder, request)
121
+
122
+ if recorder.Code != http.StatusNotFound {
123
+ t.Fatalf("expected status %d, got %d", http.StatusNotFound, recorder.Code)
124
+ }
125
+ }
126
+
127
+ func TestPing(t *testing.T) {
128
+ engine := router.New(config.Config{
129
+ Service: config.ServiceConfig{
130
+ Name: "{{SERVICE_NAME}}",
131
+ Port: "{{HTTP_PORT}}",
132
+ },
133
+ })
134
+
135
+ request := httptest.NewRequest(http.MethodGet, "/api/v1/ping", nil)
136
+ recorder := httptest.NewRecorder()
137
+
138
+ engine.ServeHTTP(recorder, request)
139
+
140
+ if recorder.Code != http.StatusOK {
141
+ t.Fatalf("expected status %d, got %d", http.StatusOK, recorder.Code)
142
+ }
143
+
144
+ var response model.PingResponse
145
+ if err := json.Unmarshal(recorder.Body.Bytes(), &response); err != nil {
146
+ t.Fatal(err)
147
+ }
148
+
149
+ if response.Service != "{{SERVICE_NAME}}" {
150
+ t.Fatalf("expected service %q, got %q", "{{SERVICE_NAME}}", response.Service)
151
+ }
152
+
153
+ if response.Message != "pong" {
154
+ t.Fatalf("expected message %q, got %q", "pong", response.Message)
155
+ }
156
+
157
+ if response.Version != "v1" {
158
+ t.Fatalf("expected version %q, got %q", "v1", response.Version)
159
+ }
160
+ }
@@ -0,0 +1,88 @@
1
+ {
2
+ "name": "web-service",
3
+ "description": "Go + Gin web service starter",
4
+ "category": "backend",
5
+ "stack": ["Go", "Gin"],
6
+ "tags": ["api", "docker", "go", "service"],
7
+ "platforms": ["linux", "container"],
8
+ "maturity": {
9
+ "level": "validated",
10
+ "summary": "Dockerized web service starter with bounded HTTP timeouts, graceful shutdown, runtime health checks, lint, and tests."
11
+ },
12
+ "validation": {
13
+ "status": "real-build-verified",
14
+ "verification_tier": "real-build",
15
+ "evidence": [
16
+ "python unittest template rendering coverage",
17
+ "generated-project graceful shutdown and timeout tests",
18
+ "runtime image HTTP health check",
19
+ "real docker runtime image builds",
20
+ "real docker development image builds"
21
+ ]
22
+ },
23
+ "operating_assumptions": [
24
+ "The starter is optimized for Go service development with Docker-based dev and runtime flows.",
25
+ "Generated projects are expected to keep config, build, and verification workflows repo-local."
26
+ ],
27
+ "workflow_labels": ["bootstrap", "dev", "verify", "build", "runtime"],
28
+ "commands": {
29
+ "bootstrap": "make bootstrap",
30
+ "doctor": "make doctor",
31
+ "lint": "make lint",
32
+ "test": "make test",
33
+ "verify": "make verify",
34
+ "build": "make build",
35
+ "clean": "make clean",
36
+ "help": "make help"
37
+ },
38
+ "worktree": {
39
+ "support_level": "worktree-ready",
40
+ "isolation_dimensions": [
41
+ "runtime-names",
42
+ "ports",
43
+ "caches",
44
+ "generated-output",
45
+ "cleanup",
46
+ "diagnostics"
47
+ ],
48
+ "diagnostics": [
49
+ "make worktree-info",
50
+ "make worktree-doctor"
51
+ ],
52
+ "cleanup": [
53
+ "make clean-worktree"
54
+ ]
55
+ },
56
+ "variables": [
57
+ {
58
+ "name": "project_name",
59
+ "required": true,
60
+ "validator": "project-name"
61
+ },
62
+ {
63
+ "name": "module_name",
64
+ "required": true,
65
+ "prompt": "Go module name: ",
66
+ "validator": "go-module"
67
+ },
68
+ {
69
+ "name": "service_name",
70
+ "required": false,
71
+ "default_from": "project_name",
72
+ "validator": "slug"
73
+ },
74
+ {
75
+ "name": "http_port",
76
+ "required": false,
77
+ "default": "8080",
78
+ "validator": "port"
79
+ }
80
+ ],
81
+ "next_steps": [
82
+ "make bootstrap",
83
+ "make dev",
84
+ "make verify",
85
+ "make docker-build",
86
+ "make docker-run"
87
+ ]
88
+ }
@@ -0,0 +1,3 @@
1
+ .git
2
+ .cache
3
+ bin
@@ -0,0 +1,2 @@
1
+ .cache/
2
+ bin/
@@ -0,0 +1,2 @@
1
+ [tools]
2
+ go = "1.26.0"
@@ -0,0 +1 @@
1
+ brew "go"
@@ -0,0 +1,19 @@
1
+ ARG BUILDER_IMAGE=golang:1.26-alpine
2
+ ARG RUNTIME_IMAGE=alpine:3.20
3
+
4
+ FROM ${BUILDER_IMAGE} AS builder
5
+ ARG GOPROXY=https://proxy.golang.org,direct
6
+ ARG GOSUMDB=sum.golang.org
7
+ WORKDIR /app
8
+ ENV GOPROXY=${GOPROXY}
9
+ ENV GOSUMDB=${GOSUMDB}
10
+ COPY go.mod go.sum ./
11
+ RUN go mod download || true
12
+ COPY . .
13
+ RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH:-amd64} go build -o /out/worker ./cmd/worker
14
+
15
+ FROM ${RUNTIME_IMAGE}
16
+ WORKDIR /app
17
+ COPY --from=builder /out/worker /usr/local/bin/worker
18
+ COPY configs ./configs
19
+ CMD ["/usr/local/bin/worker"]
@@ -0,0 +1,9 @@
1
+ FROM golang:1.26-alpine
2
+ ARG GOPROXY=https://proxy.golang.org,direct
3
+ ARG GOSUMDB=sum.golang.org
4
+ WORKDIR /app
5
+ ENV GOPROXY=${GOPROXY}
6
+ ENV GOSUMDB=${GOSUMDB}
7
+ COPY go.mod go.sum ./
8
+ RUN go mod download || true
9
+ CMD ["sh", "-lc", "go run ./cmd/worker"]