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,153 @@
1
+ package tests
2
+
3
+ import (
4
+ "context"
5
+ "encoding/json"
6
+ "net"
7
+ "net/http"
8
+ "net/http/httptest"
9
+ "testing"
10
+ "time"
11
+
12
+ servicev1 "{{MODULE_NAME}}/api/gen/go/service/v1"
13
+ "{{MODULE_NAME}}/internal/config"
14
+ "{{MODULE_NAME}}/internal/model"
15
+ "{{MODULE_NAME}}/internal/router"
16
+ "{{MODULE_NAME}}/internal/service"
17
+ "{{MODULE_NAME}}/internal/transport"
18
+
19
+ "google.golang.org/grpc"
20
+ "google.golang.org/grpc/credentials/insecure"
21
+ healthpb "google.golang.org/grpc/health/grpc_health_v1"
22
+ "google.golang.org/grpc/test/bufconn"
23
+ )
24
+
25
+ func TestHealthz(t *testing.T) {
26
+ engine := router.New(config.Config{
27
+ Service: config.ServiceConfig{
28
+ Name: "{{SERVICE_NAME}}",
29
+ HTTPPort: "{{HTTP_PORT}}",
30
+ GRPCPort: "{{GRPC_PORT}}",
31
+ },
32
+ Store: config.StoreConfig{
33
+ Driver: "{{DEPENDENCY_STORE}}",
34
+ },
35
+ })
36
+
37
+ request := httptest.NewRequest(http.MethodGet, "/healthz", nil)
38
+ recorder := httptest.NewRecorder()
39
+
40
+ engine.ServeHTTP(recorder, request)
41
+
42
+ if recorder.Code != http.StatusOK {
43
+ t.Fatalf("expected status %d, got %d", http.StatusOK, recorder.Code)
44
+ }
45
+
46
+ var response model.HealthResponse
47
+ if err := json.Unmarshal(recorder.Body.Bytes(), &response); err != nil {
48
+ t.Fatal(err)
49
+ }
50
+
51
+ if response.Service != "{{SERVICE_NAME}}" {
52
+ t.Fatalf("expected service %q, got %q", "{{SERVICE_NAME}}", response.Service)
53
+ }
54
+
55
+ if response.Store != "{{DEPENDENCY_STORE}}" {
56
+ t.Fatalf("expected store %q, got %q", "{{DEPENDENCY_STORE}}", response.Store)
57
+ }
58
+ }
59
+
60
+ func TestPing(t *testing.T) {
61
+ engine := router.New(config.Config{
62
+ Service: config.ServiceConfig{
63
+ Name: "{{SERVICE_NAME}}",
64
+ HTTPPort: "{{HTTP_PORT}}",
65
+ GRPCPort: "{{GRPC_PORT}}",
66
+ },
67
+ Store: config.StoreConfig{
68
+ Driver: "{{DEPENDENCY_STORE}}",
69
+ },
70
+ })
71
+
72
+ request := httptest.NewRequest(http.MethodGet, "/api/v1/ping", nil)
73
+ recorder := httptest.NewRecorder()
74
+
75
+ engine.ServeHTTP(recorder, request)
76
+
77
+ if recorder.Code != http.StatusOK {
78
+ t.Fatalf("expected status %d, got %d", http.StatusOK, recorder.Code)
79
+ }
80
+
81
+ var response model.PingResponse
82
+ if err := json.Unmarshal(recorder.Body.Bytes(), &response); err != nil {
83
+ t.Fatal(err)
84
+ }
85
+
86
+ if response.Message != "pong" {
87
+ t.Fatalf("expected message %q, got %q", "pong", response.Message)
88
+ }
89
+
90
+ if response.ProtoPackage != "{{PROTO_PACKAGE}}" {
91
+ t.Fatalf("expected proto package %q, got %q", "{{PROTO_PACKAGE}}", response.ProtoPackage)
92
+ }
93
+ }
94
+
95
+ func TestGRPCPingContract(t *testing.T) {
96
+ listener := bufconn.Listen(1024 * 1024)
97
+ pingService := service.NewPingService("{{SERVICE_NAME}}", "{{PROTO_PACKAGE}}")
98
+ server := transport.NewGRPCServer("{{SERVICE_NAME}}", pingService)
99
+
100
+ go func() {
101
+ _ = server.Serve(listener)
102
+ }()
103
+ t.Cleanup(func() {
104
+ server.Stop()
105
+ _ = listener.Close()
106
+ })
107
+
108
+ connection, err := grpc.NewClient(
109
+ "passthrough:///bufnet",
110
+ grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) {
111
+ return listener.Dial()
112
+ }),
113
+ grpc.WithTransportCredentials(insecure.NewCredentials()),
114
+ )
115
+ if err != nil {
116
+ t.Fatalf("create gRPC client: %v", err)
117
+ }
118
+ t.Cleanup(func() { _ = connection.Close() })
119
+
120
+ ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
121
+ defer cancel()
122
+
123
+ client := servicev1.New{{SERVICE_TYPE_NAME}}ServiceClient(connection)
124
+ healthClient := healthpb.NewHealthClient(connection)
125
+ healthResponse, err := healthClient.Check(ctx, &healthpb.HealthCheckRequest{Service: "{{SERVICE_NAME}}"})
126
+ if err != nil {
127
+ t.Fatalf("check gRPC health: %v", err)
128
+ }
129
+ if healthResponse.GetStatus() != healthpb.HealthCheckResponse_SERVING {
130
+ t.Fatalf("expected gRPC health status SERVING, got %s", healthResponse.GetStatus())
131
+ }
132
+
133
+ response, err := client.Ping(ctx, &servicev1.PingRequest{RequestId: "contract-test"})
134
+ if err != nil {
135
+ t.Fatalf("call Ping: %v", err)
136
+ }
137
+
138
+ if response.GetMessage() != "pong" {
139
+ t.Fatalf("expected message %q, got %q", "pong", response.GetMessage())
140
+ }
141
+ if response.GetService() != "{{SERVICE_NAME}}" {
142
+ t.Fatalf("expected service %q, got %q", "{{SERVICE_NAME}}", response.GetService())
143
+ }
144
+
145
+ expectedMethod := "/{{PROTO_PACKAGE}}.{{SERVICE_TYPE_NAME}}Service/Ping"
146
+ if servicev1.{{SERVICE_TYPE_NAME}}Service_Ping_FullMethodName != expectedMethod {
147
+ t.Fatalf(
148
+ "expected full method %q, got %q",
149
+ expectedMethod,
150
+ servicev1.{{SERVICE_TYPE_NAME}}Service_Ping_FullMethodName,
151
+ )
152
+ }
153
+ }
@@ -0,0 +1,114 @@
1
+ {
2
+ "name": "microservice",
3
+ "description": "Go microservice starter with Protobuf, Buf, Compose, and OpenTelemetry",
4
+ "category": "backend",
5
+ "stack": ["Go", "Gin", "Protobuf", "Buf", "Docker Compose", "OpenTelemetry"],
6
+ "tags": ["grpc", "otel", "protobuf", "docker", "service"],
7
+ "platforms": ["linux", "container"],
8
+ "maturity": {
9
+ "level": "validated",
10
+ "summary": "Containerized microservice starter with coordinated HTTP/gRPC shutdown, bounded timeouts, health checks, protobuf, and observability."
11
+ },
12
+ "validation": {
13
+ "status": "real-build-verified",
14
+ "verification_tier": "real-build",
15
+ "evidence": [
16
+ "python unittest template rendering coverage",
17
+ "generated-project HTTP and gRPC shutdown tests",
18
+ "HTTP and gRPC health checks",
19
+ "real docker runtime image builds",
20
+ "real docker development image builds"
21
+ ]
22
+ },
23
+ "operating_assumptions": [
24
+ "The starter assumes a contract-first backend workflow with Buf and local dependency orchestration.",
25
+ "Generated projects are expected to validate protobuf, service runtime, and container packaging together."
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
+ "dependency-stores",
44
+ "caches",
45
+ "generated-output",
46
+ "cleanup",
47
+ "diagnostics"
48
+ ],
49
+ "diagnostics": [
50
+ "make worktree-info",
51
+ "make worktree-doctor"
52
+ ],
53
+ "cleanup": [
54
+ "make clean-worktree"
55
+ ]
56
+ },
57
+ "variables": [
58
+ {
59
+ "name": "project_name",
60
+ "required": true,
61
+ "validator": "project-name"
62
+ },
63
+ {
64
+ "name": "module_name",
65
+ "required": true,
66
+ "prompt": "Go module name: ",
67
+ "validator": "go-module"
68
+ },
69
+ {
70
+ "name": "service_name",
71
+ "required": false,
72
+ "default_from": "project_name",
73
+ "validator": "slug"
74
+ },
75
+ {
76
+ "name": "proto_package",
77
+ "required": true,
78
+ "prompt": "Proto package: ",
79
+ "validator": "protobuf-package"
80
+ },
81
+ {
82
+ "name": "http_port",
83
+ "required": false,
84
+ "default": "8080",
85
+ "validator": "port"
86
+ },
87
+ {
88
+ "name": "grpc_port",
89
+ "required": false,
90
+ "default": "9090",
91
+ "validator": "port"
92
+ },
93
+ {
94
+ "name": "dependency_store",
95
+ "required": false,
96
+ "default": "postgres",
97
+ "validator": "choice",
98
+ "choices": ["postgres", "redis"]
99
+ },
100
+ {
101
+ "name": "otel_exporter_endpoint",
102
+ "required": false,
103
+ "default": "http://localhost:4318",
104
+ "validator": "url"
105
+ }
106
+ ],
107
+ "next_steps": [
108
+ "make bootstrap",
109
+ "make dev",
110
+ "make verify",
111
+ "make up",
112
+ "make docker-build"
113
+ ]
114
+ }
@@ -0,0 +1,11 @@
1
+ root = "."
2
+ tmp_dir = "tmp"
3
+
4
+ [build]
5
+ cmd = "go build -o ./tmp/server ./cmd/server"
6
+ bin = "./tmp/server"
7
+ exclude_dir = [".git", ".cache", "bin", "tmp"]
8
+ include_ext = ["go", "yaml"]
9
+
10
+ [log]
11
+ time = true
@@ -0,0 +1,5 @@
1
+ .git/
2
+ .cache/
3
+ bin/
4
+ tmp/
5
+ .DS_Store
@@ -0,0 +1,5 @@
1
+ bin/
2
+ dist/
3
+ .cache/
4
+ .DS_Store
5
+ coverage.out
@@ -0,0 +1,2 @@
1
+ [tools]
2
+ go = "1.26.0"
@@ -0,0 +1,5 @@
1
+ brew "mise"
2
+ brew "go"
3
+ brew "golangci-lint"
4
+ brew "gh"
5
+ brew "jq"
@@ -0,0 +1,41 @@
1
+ ARG BUILDER_IMAGE=golang:1.26-alpine
2
+ ARG RUNTIME_IMAGE=alpine:3.20
3
+
4
+ FROM ${BUILDER_IMAGE} AS builder
5
+
6
+ WORKDIR /app
7
+
8
+ ARG GOPROXY=https://proxy.golang.org,direct
9
+ ARG GOSUMDB=sum.golang.org
10
+ ENV GOPROXY=${GOPROXY}
11
+ ENV GOSUMDB=${GOSUMDB}
12
+
13
+ COPY go.mod ./
14
+ RUN set -eux; \
15
+ attempt=1; \
16
+ until go mod download; do \
17
+ if [ "$attempt" -ge 3 ]; then \
18
+ exit 1; \
19
+ fi; \
20
+ attempt=$((attempt + 1)); \
21
+ sleep 5; \
22
+ done
23
+
24
+ COPY . .
25
+ RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH:-amd64} go build -o /out/server ./cmd/server
26
+
27
+ FROM ${RUNTIME_IMAGE}
28
+
29
+ WORKDIR /app
30
+
31
+ COPY --from=builder /out/server /app/server
32
+ COPY configs/config.yaml /app/configs/config.yaml
33
+
34
+ EXPOSE {{HTTP_PORT}}
35
+
36
+ ENV CONFIG_FILE=/app/configs/config.yaml
37
+
38
+ HEALTHCHECK --interval=10s --timeout=3s --start-period=5s --retries=3 \
39
+ CMD ["/app/server", "healthcheck", "http://127.0.0.1:{{HTTP_PORT}}/healthz"]
40
+
41
+ CMD ["/app/server"]
@@ -0,0 +1,45 @@
1
+ FROM golang:1.26-bookworm
2
+
3
+ WORKDIR /workspace
4
+
5
+ ARG AIR_VERSION=1.65.3
6
+ ARG GOLANGCI_LINT_VERSION=2.12.2
7
+ ARG GOPROXY=https://proxy.golang.org,direct
8
+ ARG GOSUMDB=sum.golang.org
9
+ ARG TARGETARCH
10
+
11
+ RUN apt-get update \
12
+ && apt-get install -y --no-install-recommends bash ca-certificates curl git make tar \
13
+ && rm -rf /var/lib/apt/lists/*
14
+
15
+ RUN set -eux; \
16
+ case "${TARGETARCH}" in \
17
+ arm64) air_arch="arm64"; golangci_arch="arm64" ;; \
18
+ amd64) air_arch="amd64"; golangci_arch="amd64" ;; \
19
+ *) echo "Unsupported TARGETARCH: ${TARGETARCH}"; exit 1 ;; \
20
+ esac; \
21
+ curl -fsSL "https://github.com/air-verse/air/releases/download/v${AIR_VERSION}/air_${AIR_VERSION}_linux_${air_arch}.tar.gz" \
22
+ | tar -xz -C /usr/local/bin air; \
23
+ curl -fsSL "https://github.com/golangci/golangci-lint/releases/download/v${GOLANGCI_LINT_VERSION}/golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${golangci_arch}.tar.gz" \
24
+ | tar -xz -C /tmp; \
25
+ mv "/tmp/golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${golangci_arch}/golangci-lint" /usr/local/bin/golangci-lint; \
26
+ rm -rf /tmp/golangci-lint-${GOLANGCI_LINT_VERSION}-linux-${golangci_arch}
27
+
28
+ COPY go.mod go.sum ./
29
+ ENV GOPROXY=${GOPROXY}
30
+ ENV GOSUMDB=${GOSUMDB}
31
+ RUN set -eux; \
32
+ attempt=1; \
33
+ until go mod download; do \
34
+ if [ "$attempt" -ge 3 ]; then \
35
+ exit 1; \
36
+ fi; \
37
+ attempt=$((attempt + 1)); \
38
+ sleep 5; \
39
+ done
40
+
41
+ ENV PATH="/go/bin:${PATH}"
42
+ ENV GOCACHE=/workspace/.cache/go-build
43
+ ENV GOLANGCI_LINT_CACHE=/workspace/.cache/golangci-lint
44
+
45
+ CMD ["air", "-c", ".air.toml"]
@@ -0,0 +1,113 @@
1
+ APP_NAME={{SERVICE_NAME}}
2
+ WORKTREE_ROOT ?=$(shell git rev-parse --show-toplevel 2>/dev/null || pwd)
3
+ WORKTREE_LABEL ?=$(shell basename "$(WORKTREE_ROOT)" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9' '-' | sed 's/^-//; s/-$$//')
4
+ WORKTREE_ID ?=$(shell printf '%s' "$(WORKTREE_ROOT)" | shasum | cut -c1-8)
5
+ WORKTREE_SLUG ?=$(APP_NAME)-$(WORKTREE_ID)
6
+ COMPOSE_PROJECT_NAME ?=$(WORKTREE_SLUG)
7
+ IMAGE ?=$(WORKTREE_SLUG)
8
+ TAG ?=dev
9
+ IMAGE_REF := $(IMAGE):$(TAG)
10
+ COMPOSE ?=COMPOSE_PROJECT_NAME=$(COMPOSE_PROJECT_NAME) docker compose
11
+ CONTAINER_PORT ?={{HTTP_PORT}}
12
+ HOST_PORT ?={{HTTP_PORT}}
13
+ DEV_COMPOSE_FILE ?=compose.dev.yaml
14
+ DEV_SERVICE ?=app-dev
15
+ DOCKER_VARIANT ?=alpine
16
+ DOCKER_PLATFORM ?=linux/arm64
17
+ GOPROXY ?=https://proxy.golang.org,direct
18
+ GOSUMDB ?=sum.golang.org
19
+ GOCACHE ?= $(CURDIR)/.cache/go-build
20
+ GOMODCACHE ?= $(CURDIR)/.cache/go-mod
21
+ GOLANGCI_LINT_CACHE ?= $(CURDIR)/.cache/golangci-lint
22
+ export COMPOSE_PROJECT_NAME
23
+ export IMAGE
24
+ export TAG
25
+ export HOST_PORT
26
+ export CONTAINER_PORT
27
+ export GOCACHE
28
+ export GOMODCACHE
29
+ export GOLANGCI_LINT_CACHE
30
+
31
+ ifeq ($(DOCKER_VARIANT),ubuntu)
32
+ BUILDER_IMAGE ?= public.ecr.aws/docker/library/golang:1.26
33
+ RUNTIME_IMAGE ?= public.ecr.aws/docker/library/ubuntu:26.04
34
+ else
35
+ BUILDER_IMAGE ?= golang:1.26-alpine
36
+ RUNTIME_IMAGE ?= alpine:3.20
37
+ endif
38
+
39
+ .PHONY: worktree-info worktree-doctor worktree-compose-config clean-worktree bootstrap doctor dev dev-shell tidy lint test verify run build clean help docker-build docker-run docker-push
40
+
41
+ worktree-info:
42
+ @printf '%s\n' "Worktree root: $(WORKTREE_ROOT)"
43
+ @printf '%s\n' "Worktree label: $(WORKTREE_LABEL)"
44
+ @printf '%s\n' "Worktree ID: $(WORKTREE_ID)"
45
+ @printf '%s\n' "Worktree slug: $(WORKTREE_SLUG)"
46
+ @printf '%s\n' "Compose project: $(COMPOSE_PROJECT_NAME)"
47
+ @printf '%s\n' "HTTP URL: http://127.0.0.1:$(HOST_PORT)"
48
+ @printf '%s\n' "Image ref: $(IMAGE_REF)"
49
+ @printf '%s\n' "Go cache: $(GOCACHE)"
50
+ @printf '%s\n' "Go module cache: $(GOMODCACHE)"
51
+ @printf '%s\n' "golangci-lint cache: $(GOLANGCI_LINT_CACHE)"
52
+
53
+ worktree-doctor:
54
+ @$(MAKE) --no-print-directory worktree-info
55
+ @case "$(GOCACHE)" in "$(WORKTREE_ROOT)"/*) ;; *) printf '%s\n' "GOCACHE should stay inside this worktree: $(GOCACHE)"; exit 1;; esac
56
+ @case "$(GOMODCACHE)" in "$(WORKTREE_ROOT)"/*) ;; *) printf '%s\n' "GOMODCACHE should stay inside this worktree: $(GOMODCACHE)"; exit 1;; esac
57
+ @case "$(GOLANGCI_LINT_CACHE)" in "$(WORKTREE_ROOT)"/*) ;; *) printf '%s\n' "GOLANGCI_LINT_CACHE should stay inside this worktree: $(GOLANGCI_LINT_CACHE)"; exit 1;; esac
58
+ @if [ "$(HOST_PORT)" = "{{HTTP_PORT}}" ]; then printf '%s\n' "Warning: HOST_PORT uses the generated default {{HTTP_PORT}}; override it when another worktree is running."; fi
59
+ @if ! command -v lsof >/dev/null 2>&1; then printf '%s\n' "Port occupancy checks skipped: lsof is not available."; else \
60
+ if lsof -nP -iTCP:$(HOST_PORT) -sTCP:LISTEN >/dev/null 2>&1; then printf '%s\n%s\n' "Warning: HOST_PORT $(HOST_PORT) is already in use." "Suggested override: HOST_PORT=$$(( $(HOST_PORT) + 10000 )) make dev"; fi; \
61
+ fi
62
+ @printf '%s\n' "Compose config check: make worktree-compose-config"
63
+
64
+ worktree-compose-config:
65
+ @if ! command -v docker >/dev/null 2>&1; then printf '%s\n' "Docker is not available; cannot render Compose config."; exit 1; fi
66
+ $(COMPOSE) -f $(DEV_COMPOSE_FILE) config
67
+
68
+ clean-worktree:
69
+ $(COMPOSE) -f $(DEV_COMPOSE_FILE) down --remove-orphans --volumes
70
+
71
+ bootstrap:
72
+ GOPROXY=$(GOPROXY) GOSUMDB=$(GOSUMDB) $(COMPOSE) -f $(DEV_COMPOSE_FILE) build $(DEV_SERVICE)
73
+
74
+ doctor:
75
+ $(COMPOSE) -f $(DEV_COMPOSE_FILE) run --rm $(DEV_SERVICE) ./scripts/doctor
76
+
77
+ dev:
78
+ GOPROXY=$(GOPROXY) GOSUMDB=$(GOSUMDB) $(COMPOSE) -f $(DEV_COMPOSE_FILE) up $(DEV_SERVICE)
79
+
80
+ dev-shell:
81
+ $(COMPOSE) -f $(DEV_COMPOSE_FILE) run --rm $(DEV_SERVICE) bash
82
+
83
+ tidy:
84
+ $(COMPOSE) -f $(DEV_COMPOSE_FILE) run --rm $(DEV_SERVICE) go mod tidy
85
+
86
+ lint:
87
+ $(COMPOSE) -f $(DEV_COMPOSE_FILE) run --rm $(DEV_SERVICE) golangci-lint run --disable-all --enable=errcheck --enable=govet --enable=ineffassign --enable=staticcheck --enable=unused ./...
88
+
89
+ test:
90
+ $(COMPOSE) -f $(DEV_COMPOSE_FILE) run --rm $(DEV_SERVICE) go test ./...
91
+
92
+ verify: doctor lint test build
93
+
94
+ run:
95
+ $(COMPOSE) -f $(DEV_COMPOSE_FILE) run --rm --service-ports $(DEV_SERVICE)
96
+
97
+ build:
98
+ $(COMPOSE) -f $(DEV_COMPOSE_FILE) run --rm $(DEV_SERVICE) go build -o bin/$(APP_NAME) ./cmd/server
99
+
100
+ clean:
101
+ $(COMPOSE) -f $(DEV_COMPOSE_FILE) down --remove-orphans
102
+
103
+ help:
104
+ @printf '%s\n' "Common commands:" " make bootstrap Prepare the development environment" " make doctor Check required tools and project configuration" " make lint Run static analysis" " make test Run tests" " make verify Run the complete local verification contract" " make build Build the application" " make clean Remove generated runtime state" " make help Show this command summary"
105
+
106
+ docker-build:
107
+ docker build --platform $(DOCKER_PLATFORM) --build-arg BUILDER_IMAGE=$(BUILDER_IMAGE) --build-arg RUNTIME_IMAGE=$(RUNTIME_IMAGE) --build-arg GOPROXY=$(GOPROXY) --build-arg GOSUMDB=$(GOSUMDB) -t $(IMAGE_REF) .
108
+
109
+ docker-run:
110
+ docker run --rm -p $(HOST_PORT):$(CONTAINER_PORT) $(IMAGE_REF)
111
+
112
+ docker-push:
113
+ docker push $(IMAGE_REF)
@@ -0,0 +1,164 @@
1
+ # {{SERVICE_NAME}}
2
+
3
+ This project was generated by BiucingCLI.
4
+
5
+ ## Stack
6
+
7
+ - Go
8
+ - Gin
9
+ - Docker
10
+
11
+ ## Project Layout
12
+
13
+ - `cmd/server`: application entrypoint
14
+ - `internal/config`: config loading
15
+ - `internal/handler`: HTTP handlers
16
+ - `internal/service`: business logic
17
+ - `internal/model`: response models
18
+ - `internal/router`: route wiring
19
+ - `internal/runtime`: bounded HTTP serving and graceful shutdown
20
+ - `configs`: local config files
21
+ - `tests`: integration-style HTTP tests
22
+
23
+ ## Docker Workflow
24
+
25
+ ```bash
26
+ make bootstrap
27
+ make dev
28
+ ```
29
+
30
+ The starter is designed to run development, checks, and runtime packaging inside Docker by default.
31
+
32
+ ## Available Commands
33
+
34
+ ```bash
35
+ make bootstrap
36
+ make dev
37
+ make dev-shell
38
+ make doctor
39
+ make lint
40
+ make test
41
+ make verify
42
+ make build
43
+ make docker-build
44
+ make docker-run
45
+ make clean
46
+ make help
47
+ ```
48
+
49
+ The service reads configuration from `configs/config.yaml` by default.
50
+
51
+ ## Runtime Safety
52
+
53
+ - `SIGINT` and `SIGTERM` stop accepting new connections and drain in-flight HTTP requests.
54
+ - HTTP read, read-header, write, and idle timeouts are configured under `server` in `configs/config.yaml`.
55
+ - Graceful shutdown is bounded by `server.shutdown_timeout_seconds`; after the deadline, open connections are force-closed and the process exits non-zero.
56
+ - The runtime image checks `GET /healthz` every 10 seconds. Compose allows 15 seconds for the default 10-second shutdown window.
57
+
58
+ ## Environment
59
+
60
+ - `Brewfile`: optional host workstation tool installation
61
+ - `.mise.toml`: pinned Go version for host workflows
62
+ - `Dockerfile.dev`: Go development image with `air` and `golangci-lint`
63
+ - `compose.dev.yaml`: local Docker development workflow
64
+ - `.air.toml`: hot reload config for the development container
65
+ - `scripts/bootstrap`: host-oriented setup helper when you do not use Docker
66
+ - `scripts/doctor`: local environment checks
67
+ - `make lint`: baseline static analysis with `golangci-lint`
68
+ - `make verify`: run doctor, lint, and tests together inside Docker
69
+ - the development image prewarms `go mod download` so the first Docker-based dev shell and verification flow spend less time resolving modules
70
+ - `GOPROXY` and `GOSUMDB` can be overridden on `make bootstrap`, `make dev`, and `make docker-build` when your network needs a different module proxy or checksum policy
71
+
72
+ ## Example Endpoints
73
+
74
+ - `GET /healthz`: lightweight health check
75
+ - `GET /api/v1/ping`: sample versioned API endpoint
76
+ - `GET /api/v1/users`: list sample users from an in-memory repository
77
+ - `GET /api/v1/users/:id`: fetch a sample user by ID
78
+
79
+ ## Docker
80
+
81
+ Start the hot-reload development container:
82
+
83
+ ```bash
84
+ make dev
85
+ ```
86
+
87
+ Open a shell in the development container:
88
+
89
+ ```bash
90
+ make dev-shell
91
+ ```
92
+
93
+ Build the runtime image:
94
+
95
+ ```bash
96
+ make docker-build
97
+ ```
98
+
99
+ Build with the Ubuntu runtime path:
100
+
101
+ ```bash
102
+ make docker-build DOCKER_VARIANT=ubuntu
103
+ ```
104
+
105
+ Build and run the Ubuntu variant end to end:
106
+
107
+ ```bash
108
+ make docker-build DOCKER_VARIANT=ubuntu IMAGE={{SERVICE_NAME}}-ubuntu TAG=dev
109
+ make docker-run IMAGE={{SERVICE_NAME}}-ubuntu TAG=dev HOST_PORT={{HTTP_PORT}}
110
+ ```
111
+
112
+ Run the container:
113
+
114
+ ```bash
115
+ make docker-run
116
+ ```
117
+
118
+ `make docker-run` starts whatever image tag you last built or specify explicitly through `IMAGE` and `TAG`.
119
+
120
+ ## Worktree Workflow
121
+
122
+ This starter is safe to run from parallel Git worktrees when each worktree keeps its own identity and host port.
123
+
124
+ ```bash
125
+ make worktree-info
126
+ make worktree-doctor
127
+ make worktree-compose-config
128
+ HOST_PORT=8081 make dev
129
+ HOST_PORT=8081 make docker-run
130
+ make clean-worktree
131
+ ```
132
+
133
+ - `WORKTREE_LABEL` is derived from the worktree directory name for display.
134
+ - `WORKTREE_ID` is derived from the current worktree path by default and can be overridden.
135
+ - `COMPOSE_PROJECT_NAME` defaults to `{{SERVICE_NAME}}-$(WORKTREE_ID)`, so Compose containers, networks, and volumes stay scoped to the worktree.
136
+ - `IMAGE` defaults to the worktree slug and `TAG` defaults to `dev`, so runtime image tags do not overwrite another worktree by default.
137
+ - `GOCACHE`, `GOMODCACHE`, and `GOLANGCI_LINT_CACHE` stay under the current worktree's `.cache/` directory.
138
+ - The Docker dev workflow mounts Go build, module, and lint caches as Compose-scoped volumes, so dependency versions and downloads do not bleed across worktrees.
139
+ - `make worktree-doctor` checks whether `HOST_PORT` is already in use and prints a suggested override.
140
+ - `make worktree-compose-config` renders the current worktree's Compose config without starting containers.
141
+ - `make clean-worktree` removes only the current worktree's Compose containers, networks, and volumes.
142
+
143
+ Push a tagged image:
144
+
145
+ ```bash
146
+ make docker-push IMAGE=registry.example.com/{{SERVICE_NAME}} TAG=0.1.0
147
+ ```
148
+
149
+ Run with Docker Compose:
150
+
151
+ ```bash
152
+ docker compose up --build
153
+ ```
154
+
155
+ The Docker defaults are:
156
+
157
+ - `DOCKER_VARIANT=alpine`: `golang:1.26-alpine` + `alpine:3.20`
158
+ - `DOCKER_VARIANT=ubuntu`: `public.ecr.aws/docker/library/golang:1.26` + `public.ecr.aws/docker/library/ubuntu:26.04`
159
+
160
+ You can also override the exact images directly:
161
+
162
+ ```bash
163
+ make docker-build BUILDER_IMAGE=public.ecr.aws/docker/library/golang:1.26 RUNTIME_IMAGE=public.ecr.aws/docker/library/ubuntu:26.04
164
+ ```