@tailor-platform/sdk 2.0.0-next.3 → 2.0.0-next.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (327) hide show
  1. package/CHANGELOG.md +142 -0
  2. package/dist/aigateway-DR4Kwuik.mjs +9 -0
  3. package/dist/{aigateway-B3oZZE6v.mjs.map → aigateway-DR4Kwuik.mjs.map} +1 -1
  4. package/dist/{application-eHp9jXld.mjs → application-Bf8wxOi6.mjs} +701 -597
  5. package/dist/application-Bf8wxOi6.mjs.map +1 -0
  6. package/dist/application-CUkjzfij.mjs +3 -0
  7. package/dist/authconnection-CZvi9ANm.mjs +9 -0
  8. package/dist/authconnection-CZvi9ANm.mjs.map +1 -0
  9. package/dist/brand-Eo4pLXPJ.mjs.map +1 -1
  10. package/dist/cli/cache/bundle-cache.d.mts +2 -1
  11. package/dist/cli/cache/store.d.mts +1 -1
  12. package/dist/cli/commands/api/index.d.mts +1 -0
  13. package/dist/cli/commands/deploy/aigateway.d.mts +5 -1
  14. package/dist/cli/commands/deploy/application.d.mts +7 -1
  15. package/dist/cli/commands/deploy/apply-phases.d.mts +14 -1
  16. package/dist/cli/commands/deploy/auth.d.mts +5 -1
  17. package/dist/cli/commands/deploy/deploy.d.mts +5 -0
  18. package/dist/cli/commands/deploy/executor.d.mts +7 -1
  19. package/dist/cli/commands/deploy/function-registry.d.mts +5 -0
  20. package/dist/cli/commands/deploy/idp.d.mts +5 -1
  21. package/dist/cli/commands/deploy/resolver.d.mts +5 -1
  22. package/dist/cli/commands/deploy/secret-manager.d.mts +5 -1
  23. package/dist/cli/commands/deploy/staticwebsite.d.mts +5 -1
  24. package/dist/cli/commands/deploy/tailordb/index.d.mts +8 -1
  25. package/dist/cli/commands/deploy/types.d.mts +3 -1
  26. package/dist/cli/commands/deploy/workflow-execution-policy.d.mts +3 -0
  27. package/dist/cli/commands/deploy/workflow.d.mts +4 -1
  28. package/dist/cli/commands/executor/get.d.mts +0 -1
  29. package/dist/cli/commands/executor/jobs.d.mts +0 -1
  30. package/dist/cli/commands/executor/list.d.mts +0 -1
  31. package/dist/cli/commands/executor/transform.d.mts +1 -0
  32. package/dist/cli/commands/executor/trigger.d.mts +0 -1
  33. package/dist/cli/commands/executor/webhook.d.mts +0 -1
  34. package/dist/cli/commands/function/get.d.mts +0 -1
  35. package/dist/cli/commands/function/list.d.mts +0 -1
  36. package/dist/cli/commands/function/transform.d.mts +1 -0
  37. package/dist/cli/commands/generate/service.d.mts +5 -1
  38. package/dist/cli/commands/machineuser/list.d.mts +0 -1
  39. package/dist/cli/commands/machineuser/token.d.mts +0 -1
  40. package/dist/cli/commands/oauth2client/get.d.mts +0 -1
  41. package/dist/cli/commands/oauth2client/list.d.mts +0 -1
  42. package/dist/cli/commands/oauth2client/transform.d.mts +1 -0
  43. package/dist/cli/commands/organization/folder/create.d.mts +0 -1
  44. package/dist/cli/commands/organization/folder/delete.d.mts +0 -1
  45. package/dist/cli/commands/organization/folder/get.d.mts +0 -1
  46. package/dist/cli/commands/organization/folder/list.d.mts +0 -1
  47. package/dist/cli/commands/organization/folder/update.d.mts +0 -1
  48. package/dist/cli/commands/organization/get.d.mts +0 -1
  49. package/dist/cli/commands/organization/list.d.mts +0 -1
  50. package/dist/cli/commands/organization/transform.d.mts +2 -0
  51. package/dist/cli/commands/organization/tree.d.mts +0 -1
  52. package/dist/cli/commands/organization/update.d.mts +0 -1
  53. package/dist/cli/commands/remove.d.mts +0 -1
  54. package/dist/cli/commands/show.d.mts +9 -4
  55. package/dist/cli/commands/tailordb/migrate/config.d.mts +0 -1
  56. package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +16 -3
  57. package/dist/cli/commands/tailordb/migrate/generate.d.mts +0 -1
  58. package/dist/cli/commands/tailordb/migrate/snapshot-types.d.mts +6 -0
  59. package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +1 -1
  60. package/dist/cli/commands/tailordb/truncate.d.mts +0 -1
  61. package/dist/cli/commands/workflow/executions.d.mts +0 -1
  62. package/dist/cli/commands/workflow/get.d.mts +2 -1
  63. package/dist/cli/commands/workflow/list.d.mts +0 -1
  64. package/dist/cli/commands/workflow/resume.d.mts +0 -1
  65. package/dist/cli/commands/workflow/start.d.mts +0 -1
  66. package/dist/cli/commands/workflow/status.d.mts +1 -0
  67. package/dist/cli/commands/workflow/transform.d.mts +1 -0
  68. package/dist/cli/commands/workflow/wait.d.mts +0 -1
  69. package/dist/cli/commands/workflow/waiter.d.mts +1 -1
  70. package/dist/cli/commands/workspace/app/health.d.mts +0 -1
  71. package/dist/cli/commands/workspace/app/list.d.mts +0 -1
  72. package/dist/cli/commands/workspace/app/transform.d.mts +2 -0
  73. package/dist/cli/commands/workspace/create.d.mts +0 -1
  74. package/dist/cli/commands/workspace/delete.d.mts +0 -1
  75. package/dist/cli/commands/workspace/get.d.mts +0 -1
  76. package/dist/cli/commands/workspace/list.d.mts +0 -1
  77. package/dist/cli/commands/workspace/restore.d.mts +0 -1
  78. package/dist/cli/commands/workspace/transform.d.mts +2 -0
  79. package/dist/cli/commands/workspace/user/invite.d.mts +0 -1
  80. package/dist/cli/commands/workspace/user/list.d.mts +0 -1
  81. package/dist/cli/commands/workspace/user/remove.d.mts +0 -1
  82. package/dist/cli/commands/workspace/user/transform.d.mts +1 -0
  83. package/dist/cli/commands/workspace/user/update.d.mts +0 -1
  84. package/dist/cli/index.d.mts +6 -3
  85. package/dist/cli/index.mjs +273 -104
  86. package/dist/cli/index.mjs.map +1 -1
  87. package/dist/cli/lib.d.mts +4 -2
  88. package/dist/cli/lib.mjs +4 -4
  89. package/dist/cli/lib.mjs.map +1 -1
  90. package/dist/cli/query/index.d.mts +4 -1
  91. package/dist/cli/services/application.d.mts +12 -1
  92. package/dist/cli/services/auth/service.d.mts +2 -0
  93. package/dist/cli/services/executor/service.d.mts +1 -1
  94. package/dist/cli/services/http-adapter/bundler.d.mts +3 -1
  95. package/dist/cli/services/http-adapter/service.d.mts +2 -1
  96. package/dist/cli/services/resolver/service.d.mts +1 -1
  97. package/dist/cli/services/tailordb/service.d.mts +3 -1
  98. package/dist/cli/services/workflow/bundler.d.mts +2 -1
  99. package/dist/cli/services/workflow/service.d.mts +1 -1
  100. package/dist/cli/shared/args.d.mts +1 -1
  101. package/dist/cli/shared/client.d.mts +1 -1
  102. package/dist/cli/shared/config-loader.d.mts +0 -1
  103. package/dist/cli/shared/context.d.mts +2 -1
  104. package/dist/cli/shared/script-executor.d.mts +0 -1
  105. package/dist/cli/shared/seed-chunker.d.mts +7 -3
  106. package/dist/cli/shared/type-generator.d.mts +0 -1
  107. package/dist/cli/ts-hook.mjs +43 -13
  108. package/dist/completion/zsh-worker.zsh +10 -10
  109. package/dist/configure/config/index.d.mts +0 -1
  110. package/dist/configure/config/types.d.mts +3 -1
  111. package/dist/configure/index.d.mts +17 -5
  112. package/dist/configure/index.mjs +309 -5
  113. package/dist/configure/index.mjs.map +1 -1
  114. package/dist/configure/services/aigateway/index.d.mts +0 -1
  115. package/dist/configure/services/aigateway/types.d.mts +0 -1
  116. package/dist/configure/services/auth/index.d.mts +0 -1
  117. package/dist/configure/services/auth/types.d.mts +15 -14
  118. package/dist/configure/services/executor/executor.d.mts +1 -1
  119. package/dist/configure/services/executor/index.d.mts +1 -0
  120. package/dist/configure/services/executor/operation.d.mts +2 -2
  121. package/dist/configure/services/executor/trigger/event.d.mts +0 -1
  122. package/dist/configure/services/executor/trigger/index.d.mts +0 -1
  123. package/dist/configure/services/executor/trigger/schedule.d.mts +0 -1
  124. package/dist/configure/services/executor/trigger/webhook.d.mts +0 -1
  125. package/dist/configure/services/http-adapter/http-adapter.d.mts +1 -2
  126. package/dist/configure/services/idp/index.d.mts +1 -5
  127. package/dist/configure/services/idp/permission.d.mts +4 -5
  128. package/dist/configure/services/idp/types.d.mts +0 -1
  129. package/dist/configure/services/index.d.mts +8 -1
  130. package/dist/configure/services/resolver/resolver.d.mts +1 -0
  131. package/dist/configure/services/resolver/types.d.mts +0 -1
  132. package/dist/configure/services/secrets/index.d.mts +0 -1
  133. package/dist/configure/services/secrets/types.d.mts +0 -1
  134. package/dist/configure/services/staticwebsite/index.d.mts +0 -1
  135. package/dist/configure/services/staticwebsite/types.d.mts +0 -1
  136. package/dist/configure/services/tailordb/permission.d.mts +4 -5
  137. package/dist/configure/services/tailordb/schema.d.mts +104 -68
  138. package/dist/configure/services/tailordb/types.d.mts +66 -17
  139. package/dist/configure/services/workflow/execution-policy.d.mts +70 -0
  140. package/dist/configure/services/workflow/execution-policy.types.d.mts +103 -0
  141. package/dist/configure/services/workflow/index.d.mts +4 -1
  142. package/dist/configure/services/workflow/job.d.mts +7 -3
  143. package/dist/configure/services/workflow/wait-point.d.mts +0 -1
  144. package/dist/configure/services/workflow/workflow.d.mts +1 -1
  145. package/dist/configure/types/field-runtime.d.mts +0 -1
  146. package/dist/configure/types/field.d.mts +1 -2
  147. package/dist/configure/types/field.types.d.mts +6 -45
  148. package/dist/configure/types/index.d.mts +1 -0
  149. package/dist/configure/types/type.d.mts +1 -2
  150. package/dist/{context-Bd266-ru.mjs → context-DYQVYWqZ.mjs} +4 -5
  151. package/dist/{context-Bd266-ru.mjs.map → context-DYQVYWqZ.mjs.map} +1 -1
  152. package/dist/{file-BbdFGdMV.mjs → file-BUcmVIH2.mjs} +12 -14
  153. package/dist/file-BUcmVIH2.mjs.map +1 -0
  154. package/dist/{file-utils-CYZnO1pX.mjs → file-utils-yEiIS4nJ.mjs} +2 -2
  155. package/dist/file-utils-yEiIS4nJ.mjs.map +1 -0
  156. package/dist/{globals-DhwZj0RB.mjs → globals-BjhJJ2dN.mjs} +2 -2
  157. package/dist/globals-BjhJJ2dN.mjs.map +1 -0
  158. package/dist/iconv-QWaZh0TT.mjs +38 -0
  159. package/dist/iconv-QWaZh0TT.mjs.map +1 -0
  160. package/dist/{idp-Bx25ZBdN.mjs → idp-RA_swu-h.mjs} +4 -5
  161. package/dist/idp-RA_swu-h.mjs.map +1 -0
  162. package/dist/kysely/index.d.mts +3 -4
  163. package/dist/{kysely-type-5eAChaHO.mjs → kysely-type-DqIRgDYR.mjs} +4 -5
  164. package/dist/kysely-type-DqIRgDYR.mjs.map +1 -0
  165. package/dist/parser/service/auth/index.d.mts +1 -1
  166. package/dist/parser/service/auth/schema.d.mts +2 -0
  167. package/dist/parser/service/http-adapter/index.d.mts +1 -1
  168. package/dist/parser/service/idp/types.d.mts +1 -0
  169. package/dist/parser/service/tailordb/types.d.mts +6 -1
  170. package/dist/plugin/builtin/enum-constants/index.d.mts +0 -1
  171. package/dist/plugin/builtin/file-utils/index.d.mts +0 -1
  172. package/dist/plugin/builtin/file-utils/index.mjs +1 -1
  173. package/dist/plugin/builtin/kysely-type/index.d.mts +0 -1
  174. package/dist/plugin/builtin/kysely-type/index.mjs +1 -1
  175. package/dist/plugin/builtin/seed/index.d.mts +0 -1
  176. package/dist/plugin/get-generated-type.d.mts +0 -1
  177. package/dist/plugin/manager.d.mts +2 -1
  178. package/dist/plugin/types.d.mts +0 -1
  179. package/dist/plugin/with-context.d.mts +0 -1
  180. package/dist/{register-ts-hook-ZpBacA07.mjs → register-ts-hook-BhzVkej0.mjs} +799 -446
  181. package/dist/register-ts-hook-BhzVkej0.mjs.map +1 -0
  182. package/dist/{registry-DH4m7eYo.mjs → registry-BSbq6SPo.mjs} +4 -3
  183. package/dist/registry-BSbq6SPo.mjs.map +1 -0
  184. package/dist/resource_pb-BRv7AMXK.mjs +49 -0
  185. package/dist/resource_pb-BRv7AMXK.mjs.map +1 -0
  186. package/dist/runtime/aigateway.d.mts +5 -15
  187. package/dist/runtime/aigateway.mjs +2 -2
  188. package/dist/runtime/authconnection.d.mts +5 -15
  189. package/dist/runtime/authconnection.mjs +2 -2
  190. package/dist/runtime/context.d.mts +14 -6
  191. package/dist/runtime/context.mjs +2 -2
  192. package/dist/runtime/file.d.mts +14 -54
  193. package/dist/runtime/file.mjs +2 -2
  194. package/dist/runtime/globals.d.mts +1 -2
  195. package/dist/runtime/iconv.d.mts +5 -53
  196. package/dist/runtime/iconv.mjs +2 -2
  197. package/dist/runtime/idp.d.mts +13 -70
  198. package/dist/runtime/idp.mjs +2 -2
  199. package/dist/runtime/index.d.mts +11 -12
  200. package/dist/runtime/index.mjs +9 -9
  201. package/dist/runtime/secretmanager.d.mts +7 -20
  202. package/dist/runtime/secretmanager.mjs +2 -2
  203. package/dist/runtime/types.d.mts +9 -4
  204. package/dist/runtime/workflow.d.mts +42 -41
  205. package/dist/runtime/workflow.mjs +2 -2
  206. package/dist/{schema-89dYxNC2.mjs → schema-iCd1ugGp.mjs} +257 -54
  207. package/dist/schema-iCd1ugGp.mjs.map +1 -0
  208. package/dist/secretmanager-CYlpffsz.mjs +13 -0
  209. package/dist/secretmanager-CYlpffsz.mjs.map +1 -0
  210. package/dist/seed/index.d.mts +3 -2
  211. package/dist/service-BT0GPd01.mjs +3 -0
  212. package/dist/{service-ufH7sS8o.mjs → service-CzZEVrp9.mjs} +14 -9
  213. package/dist/service-CzZEVrp9.mjs.map +1 -0
  214. package/dist/{service_pb-CIrhGwHk.mjs → service_pb-Bk7dL-yT.mjs} +27 -50
  215. package/dist/service_pb-Bk7dL-yT.mjs.map +1 -0
  216. package/dist/{service_pb-DjwIn4jO.mjs → service_pb-DZkfjB_6.mjs} +1 -1
  217. package/dist/tailor-proto/src/tailor/v1/aigateway_pb.d.mts +0 -1
  218. package/dist/tailor-proto/src/tailor/v1/aigateway_resource_pb.d.mts +0 -1
  219. package/dist/tailor-proto/src/tailor/v1/application_pb.d.mts +0 -1
  220. package/dist/tailor-proto/src/tailor/v1/application_resource_pb.d.mts +0 -1
  221. package/dist/tailor-proto/src/tailor/v1/auth_pb.d.mts +0 -1
  222. package/dist/tailor-proto/src/tailor/v1/auth_resource_pb.d.mts +0 -1
  223. package/dist/tailor-proto/src/tailor/v1/events_pb.d.mts +0 -1
  224. package/dist/tailor-proto/src/tailor/v1/events_resource_pb.d.mts +0 -1
  225. package/dist/tailor-proto/src/tailor/v1/executor_pb.d.mts +0 -1
  226. package/dist/tailor-proto/src/tailor/v1/executor_resource_pb.d.mts +0 -1
  227. package/dist/tailor-proto/src/tailor/v1/function_pb.d.mts +0 -1
  228. package/dist/tailor-proto/src/tailor/v1/function_registry_pb.d.mts +0 -1
  229. package/dist/tailor-proto/src/tailor/v1/function_resource_pb.d.mts +0 -1
  230. package/dist/tailor-proto/src/tailor/v1/http_adapter_resource_pb.d.mts +0 -1
  231. package/dist/tailor-proto/src/tailor/v1/idp_pb.d.mts +0 -1
  232. package/dist/tailor-proto/src/tailor/v1/idp_resource_pb.d.mts +0 -1
  233. package/dist/tailor-proto/src/tailor/v1/metadata_pb.d.mts +0 -1
  234. package/dist/tailor-proto/src/tailor/v1/metadata_resource_pb.d.mts +0 -1
  235. package/dist/tailor-proto/src/tailor/v1/meter_pb.d.mts +0 -1
  236. package/dist/tailor-proto/src/tailor/v1/pipeline_pb.d.mts +0 -1
  237. package/dist/tailor-proto/src/tailor/v1/pipeline_resource_pb.d.mts +0 -1
  238. package/dist/tailor-proto/src/tailor/v1/resource_pb.d.mts +0 -1
  239. package/dist/tailor-proto/src/tailor/v1/secret_manager_pb.d.mts +0 -1
  240. package/dist/tailor-proto/src/tailor/v1/secret_manager_resource_pb.d.mts +0 -1
  241. package/dist/tailor-proto/src/tailor/v1/service_pb.d.mts +1 -2
  242. package/dist/tailor-proto/src/tailor/v1/stateflow_pb.d.mts +0 -1
  243. package/dist/tailor-proto/src/tailor/v1/stateflow_resource_pb.d.mts +0 -1
  244. package/dist/tailor-proto/src/tailor/v1/staticwebsite_pb.d.mts +0 -1
  245. package/dist/tailor-proto/src/tailor/v1/staticwebsite_resource_pb.d.mts +0 -1
  246. package/dist/tailor-proto/src/tailor/v1/tailordb_pb.d.mts +0 -1
  247. package/dist/tailor-proto/src/tailor/v1/tailordb_resource_pb.d.mts +0 -1
  248. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_pb.d.mts +0 -1
  249. package/dist/tailor-proto/src/tailor/v1/telemetryrouter_resource_pb.d.mts +0 -1
  250. package/dist/tailor-proto/src/tailor/v1/workflow_pb.d.mts +29 -10
  251. package/dist/tailor-proto/src/tailor/v1/workflow_resource_pb.d.mts +35 -2
  252. package/dist/tailor-proto/src/tailor/v1/workspace_pb.d.mts +0 -1
  253. package/dist/tailor-proto/src/tailor/v1/workspace_resource_pb.d.mts +0 -1
  254. package/dist/types/aigateway.generated.d.mts +5 -2
  255. package/dist/types/auth-connection.generated.d.mts +24 -11
  256. package/dist/types/auth.generated.d.mts +115 -84
  257. package/dist/types/executor.generated.d.mts +76 -84
  258. package/dist/types/helpers.d.mts +7 -6
  259. package/dist/types/http-adapter.generated.d.mts +11 -5
  260. package/dist/types/idp.generated.d.mts +536 -524
  261. package/dist/types/resolver.generated.d.mts +26 -11
  262. package/dist/types/staticwebsite.generated.d.mts +7 -3
  263. package/dist/types/tailordb.generated.d.mts +57 -29
  264. package/dist/types/workflow.generated.d.mts +9 -4
  265. package/dist/utils/test/index.d.mts +1 -2
  266. package/dist/utils/test/index.mjs +36 -10
  267. package/dist/utils/test/index.mjs.map +1 -1
  268. package/dist/utils/test/mock.d.mts +0 -1
  269. package/dist/vitest/environment.mjs +1 -1
  270. package/dist/vitest/index.d.mts +1 -1
  271. package/dist/vitest/index.mjs +11 -11
  272. package/dist/vitest/index.mjs.map +1 -1
  273. package/dist/vitest/mock-kysely.d.mts +0 -1
  274. package/dist/vitest/mocks/aigateway.d.mts +2 -2
  275. package/dist/vitest/mocks/authconnection.d.mts +2 -2
  276. package/dist/vitest/mocks/idp.d.mts +2 -2
  277. package/dist/vitest/mocks/secretmanager.d.mts +3 -1
  278. package/dist/vitest/mocks/tailordb.d.mts +6 -3
  279. package/dist/vitest/mocks/workflow.d.mts +15 -8
  280. package/dist/vitest/setup.mjs +1 -1
  281. package/dist/vitest/workflow-local.d.mts +1 -0
  282. package/dist/workflow-GNuSnsTx.mjs +22 -0
  283. package/dist/workflow-GNuSnsTx.mjs.map +1 -0
  284. package/docs/cli/auth.md +3 -3
  285. package/docs/cli/setup.md +9 -9
  286. package/docs/cli-reference.md +7 -6
  287. package/docs/configuration.md +24 -0
  288. package/docs/migration/v2.md +317 -0
  289. package/docs/plugin/custom.md +4 -4
  290. package/docs/plugin/index.md +2 -2
  291. package/docs/runtime.md +4 -2
  292. package/docs/services/aigateway.md +2 -0
  293. package/docs/services/auth.md +2 -2
  294. package/docs/services/resolver.md +1 -1
  295. package/docs/services/tailordb-migration.md +1 -1
  296. package/docs/services/tailordb.md +125 -93
  297. package/docs/services/workflow.md +78 -0
  298. package/package.json +22 -22
  299. package/dist/aigateway-B3oZZE6v.mjs +0 -15
  300. package/dist/application-D2hSK1ZL.mjs +0 -3
  301. package/dist/application-eHp9jXld.mjs.map +0 -1
  302. package/dist/authconnection-BGQM8FZI.mjs +0 -15
  303. package/dist/authconnection-BGQM8FZI.mjs.map +0 -1
  304. package/dist/cli/shared/trigger-context.d.mts +0 -1
  305. package/dist/field-runtime-CAnh_oow.mjs +0 -183
  306. package/dist/field-runtime-CAnh_oow.mjs.map +0 -1
  307. package/dist/file-BbdFGdMV.mjs.map +0 -1
  308. package/dist/file-utils-CYZnO1pX.mjs.map +0 -1
  309. package/dist/globals-DhwZj0RB.mjs.map +0 -1
  310. package/dist/iconv-D2vi8G36.mjs +0 -63
  311. package/dist/iconv-D2vi8G36.mjs.map +0 -1
  312. package/dist/idp-Bx25ZBdN.mjs.map +0 -1
  313. package/dist/kysely-type-5eAChaHO.mjs.map +0 -1
  314. package/dist/register-ts-hook-ZpBacA07.mjs.map +0 -1
  315. package/dist/registry-DH4m7eYo.mjs.map +0 -1
  316. package/dist/rolldown-runtime-DXywRVcq.mjs +0 -20
  317. package/dist/schema-89dYxNC2.mjs.map +0 -1
  318. package/dist/secretmanager-BVxw3ih_.mjs +0 -24
  319. package/dist/secretmanager-BVxw3ih_.mjs.map +0 -1
  320. package/dist/service-CkIwEctX.mjs +0 -3
  321. package/dist/service-ufH7sS8o.mjs.map +0 -1
  322. package/dist/service_pb-CIrhGwHk.mjs.map +0 -1
  323. package/dist/types-C-lQ4se3.mjs +0 -4
  324. package/dist/types-CXF2OYdR.mjs +0 -199
  325. package/dist/types-CXF2OYdR.mjs.map +0 -1
  326. package/dist/workflow-Bo59B75H.mjs +0 -50
  327. package/dist/workflow-Bo59B75H.mjs.map +0 -1
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import { C as CustomDomainStatus, R as FunctionExecution_Type, mt as AuthInvokerSchema, xt as PATScope } from "../service_pb-CIrhGwHk.mjs";
3
2
  import { t as assertDefined } from "../assert-DBxo8jPo.mjs";
4
3
  import { n as logger, r as styles } from "../logger-BEiZZ3qT.mjs";
5
- import { $t as compareSnapshotWithRemote, A as listCommand$13, An as apiCommand, Bn as pagedLogArgs, C as listCommand$14, Cn as hasChanges, Dn as PluginManager, Dt as listCommand$7, E as waitCommand, En as sdkNameLabelKey, F as generateCommand$1, Fn as configArg, G as removeCommand$1, Gt as deploy, H as extractOwnedNamespaces, Hn as toPageDirection, Ht as formatKeyValueTable, I as generateMigrationScript, In as confirmationArgs, It as getCommand$6, K as updateCommand$3, Kt as ensureConfigId, L as writeDbTypesFile, Ln as deploymentArgs, Mn as assertWritable, N as truncateCommand, Nn as defineAppCommand, O as resumeCommand, On as generateUserTypes, Pn as commonArgs, Pt as startCommand, Q as getCommand$5, Qt as parseMigrationLabelNumber, R as getConfiguredEditorCommand, Rn as isVerbose, Rt as executionsCommand, Sn as formatMigrationDiff, T as healthCommand, Tn as resourceTrn, Tt as triggerCommand, U as logBetaWarning, Un as workspaceArgs, Ut as getCommand$1, V as showCommand, Vn as paginationArgs, Vt as functionExecutionStatusToString, X as listCommand$12, Xt as MIGRATION_LABEL_KEY, Y as treeCommand, Zt as handleOptionalToRequiredError, _n as loadDiff, b as createCommand$4, bn as parseMigrationNumberArg, c as listCommand$15, cn as compareLocalTypesWithSnapshot, ct as createCommand$3, dn as getLatestMigrationNumber, en as generateAllTypeManifestsFromSnapshot, et as updateCommand$2, f as restoreCommand, ft as getCommand$3, g as getCommand$7, gn as isValidMigrationNumber, gt as listCommand$9, ht as tokenCommand$1, i as updateCommand$4, in as INITIAL_SCHEMA_NUMBER, it as getCommand$4, jt as jobsCommand, kn as prompt, m as listCommand$16, mn as getMigrationFiles, nt as listCommand$11, o as removeCommand, ot as deleteCommand$4, pn as getMigrationFilePath, qt as executeScript, r as queryCommand, sn as assertValidMigrationFiles, t as registerTsHook, tn as protoGqlPermission, u as inviteCommand, un as createSnapshotFromLocalTypes, ut as listCommand$10, v as deleteCommand$5, vn as reconstructSnapshotFromMigrations, vt as generate, wn as getNamespacesWithMigrations, wt as webhookCommand, xt as getCommand$2, yn as formatMigrationNumber, yt as listCommand$8, z as openInConfiguredEditor, zn as multiConfigArg } from "../register-ts-hook-ZpBacA07.mjs";
6
- import { A as hasUserTokenEntry, B as removeLegacyUserAlias, C as getDistDir, D as deleteUserTokens, E as loadConfig, F as loadPlatformClientConfig, G as closeConnectionPool, H as resolveUserTokenKey, I as loadStoredUserTokens, J as fetchAllTolerant, K as defaultPlatformBaseUrl, L as loadWorkspaceId, M as loadConfigPath, N as loadConsoleBaseUrl, O as fetchLatestToken, P as loadMachineUserName, Q as fetchUserInfo, R as platformConfigFromProfile, U as saveUserTokens, V as resolveConfigUser, W as writePlatformConfig, X as fetchPaged, Z as fetchPlatformMachineUserToken, _ as composeFunctionTreeshakeOptions, a as resolveInlineSourcemap, at as isDefaultPlatform, c as ResolverSchema, et as getOAuth2ClientId, g as platformBundleDefinePlugin, it as initOperatorClient, j as loadAccessToken, k as hasAnyUserTokenEntry, nt as getPlatformBaseUrl, q as fetchAll, rt as initOAuth2Client, s as WorkflowJobSchema, t as defineApplication, tt as getOrNull, u as INVOKER_EXPR, v as createLogLevelTreeshakeOptions, w as hashContent$1, y as resolveBundleLogLevel, z as readPlatformConfig } from "../application-eHp9jXld.mjs";
7
- import { i as ExecutorSchema, r as stripExecutorTriggerArgs } from "../service-ufH7sS8o.mjs";
4
+ import { $ as fetchUserInfo, A as hasAnyUserTokenEntry, B as readPlatformConfig, D as loadConfig, Et as workspaceArgs, F as loadMachineUserName, G as writePlatformConfig, H as resolveConfigUser, I as loadPlatformClientConfig, J as fetchAll, K as closeConnectionPool, L as loadStoredUserTokens, M as loadAccessToken, N as loadConfigPath, O as deleteUserTokens, P as loadConsoleBaseUrl, Q as fetchPlatformMachineUserToken, R as loadWorkspaceId, T as hashContent$1, Tt as toPageDirection, U as resolveUserTokenKey, V as removeLegacyUserAlias, W as saveUserTokens, Y as fetchAllTolerant, Z as fetchPaged, _ as platformBundleDefinePlugin, a as resolveInlineSourcemap, at as initOperatorClient, b as resolveBundleLogLevel, bt as pagedLogArgs, c as WorkflowJobSchema, d as INVOKER_EXPR, dt as confirmationArgs, ft as deploymentArgs, gt as multiConfigArg, ht as isVerbose, it as initOAuth2Client, j as hasUserTokenEntry, k as fetchLatestToken, l as ResolverSchema, lt as commonArgs, nt as getOrNull, ot as isDefaultPlatform, q as defaultPlatformBaseUrl, rt as getPlatformBaseUrl, t as defineApplication, tt as getOAuth2ClientId, ut as configArg, v as composeFunctionTreeshakeOptions, w as getDistDir, wt as resolveMachineUserInputSource, xt as paginationArgs, y as createLogLevelTreeshakeOptions, z as platformConfigFromProfile } from "../application-Bf8wxOi6.mjs";
5
+ import { $t as compareSnapshotWithRemote, A as listCommand$13, An as apiCommand, C as listCommand$14, Cn as hasChanges, Dn as PluginManager, Dt as listCommand$7, E as waitCommand, En as sdkNameLabelKey, F as generateCommand$1, G as removeCommand$1, Gt as deploy, H as extractOwnedNamespaces, Ht as formatKeyValueTable, I as generateMigrationScript, It as getCommand$6, K as updateCommand$3, Kt as ensureConfigId, L as writeDbTypesFile, Mn as assertWritable, N as truncateCommand, Nn as defineAppCommand, O as resumeCommand, On as generateUserTypes, Pt as startCommand, Q as getCommand$5, Qt as parseMigrationLabelNumber, R as getConfiguredEditorCommand, Rt as executionsCommand, Sn as formatMigrationDiff, T as healthCommand, Tn as resourceTrn, Tt as triggerCommand, U as logBetaWarning, Ut as getCommand$1, V as showCommand, Vt as functionExecutionStatusToString, X as listCommand$12, Xt as MIGRATION_LABEL_KEY, Y as treeCommand, Zt as handleOptionalToRequiredError, _n as loadDiff, b as createCommand$4, bn as parseMigrationNumberArg, c as listCommand$15, cn as compareLocalTypesWithSnapshot, ct as createCommand$3, dn as getLatestMigrationNumber, en as generateAllTypeManifestsFromSnapshot, et as updateCommand$2, f as restoreCommand, ft as getCommand$3, g as getCommand$7, gn as isValidMigrationNumber, gt as listCommand$9, ht as tokenCommand$1, i as updateCommand$4, in as INITIAL_SCHEMA_NUMBER, it as getCommand$4, jt as jobsCommand, kn as prompt, m as listCommand$16, mn as getMigrationFiles, nt as listCommand$11, o as removeCommand, ot as deleteCommand$4, pn as getMigrationFilePath, qt as executeScript, r as queryCommand, sn as assertValidMigrationFiles, t as registerTsHook, tn as protoGqlPermission, u as inviteCommand, un as createSnapshotFromLocalTypes, ut as listCommand$10, v as deleteCommand$5, vn as reconstructSnapshotFromMigrations, vt as generate, wn as getNamespacesWithMigrations, wt as webhookCommand, xt as getCommand$2, yn as formatMigrationNumber, yt as listCommand$8, z as openInConfiguredEditor } from "../register-ts-hook-BhzVkej0.mjs";
6
+ import { i as ExecutorSchema, r as stripExecutorTriggerArgs } from "../service-CzZEVrp9.mjs";
8
7
  import { t as multiline } from "../multiline-sfHpTZZK.mjs";
9
8
  import { t as readPackageJson } from "../package-json-8b0O9TlX.mjs";
10
9
  import { i as userAgent } from "../secret-file-aoNXJmKa.mjs";
11
10
  import { n as isCLIError } from "../errors-118wUDRr.mjs";
11
+ import { B as FunctionExecution_Type, Ct as PATScope, T as CustomDomainStatus, gt as AuthInvokerSchema } from "../service_pb-Bk7dL-yT.mjs";
12
12
  import { a as JSON_FOOTER_MARKER, i as CRASH_LOG_EXTENSION, o as parseCrashReportConfig, r as sendCrashReport, t as initCrashReporting } from "../crashreport-Cg-pqRJV.mjs";
13
13
  import { t as isPluginGeneratedType } from "../type-source-DH_LH20p.mjs";
14
14
  import * as path from "pathe";
@@ -489,6 +489,35 @@ const crashReportCommand = defineCommand({
489
489
  }
490
490
  });
491
491
 
492
+ //#endregion
493
+ //#region src/parser/service/resolver/local-input-parser.ts
494
+ /**
495
+ * Build a local, in-process validator for a resolver's declared input fields.
496
+ * Each field already carries its own bound `_parseInternal` (attached when the
497
+ * user's resolver module was loaded via dynamic import), so this only needs to
498
+ * orchestrate calling every field and collecting issues.
499
+ * @param fields - Resolver's raw input field definitions (already-built TailorField instances)
500
+ * @returns An object exposing a `.parse()` method for local format detection
501
+ */
502
+ function buildLocalInputParser(fields) {
503
+ return { parse(args) {
504
+ const { value, data, invoker } = args;
505
+ if (typeof value !== "object" || value === null || Array.isArray(value) || value instanceof Date) return { issues: [{ message: `Expected an object: received ${String(value)}` }] };
506
+ const record = value;
507
+ const issues = [];
508
+ for (const [name, field] of Object.entries(fields)) {
509
+ const result = field._parseInternal({
510
+ value: record[name],
511
+ data,
512
+ invoker,
513
+ pathArray: [name]
514
+ });
515
+ if (result.issues) issues.push(...result.issues);
516
+ }
517
+ return issues.length > 0 ? { issues } : {};
518
+ } };
519
+ }
520
+
492
521
  //#endregion
493
522
  //#region src/cli/commands/deploy/index.ts
494
523
  const deployCommand$1 = defineAppCommand({
@@ -1272,10 +1301,7 @@ async function detectFunctionType(options) {
1272
1301
  if (resolverResult.success) {
1273
1302
  const rawInput = module.default.input;
1274
1303
  let inputSchema;
1275
- if (rawInput) {
1276
- const { t } = await import("../types-C-lQ4se3.mjs");
1277
- inputSchema = t.object(rawInput);
1278
- }
1304
+ if (rawInput) inputSchema = buildLocalInputParser(rawInput);
1279
1305
  return {
1280
1306
  type: "resolver",
1281
1307
  name: resolverResult.data.name,
@@ -1425,6 +1451,7 @@ When a \`.js\` file is provided, detection and bundling are skipped and the file
1425
1451
  const authNamespace = resolveAuthNamespace(config.auth);
1426
1452
  const machineUserName = await resolveMachineUserName({
1427
1453
  cliMachineUser: args["machine-user"],
1454
+ cliMachineUserSource: resolveMachineUserInputSource(args["machine-user"]),
1428
1455
  profile: args.profile,
1429
1456
  authConfig: config.auth
1430
1457
  });
@@ -1545,9 +1572,10 @@ function resolveAuthNamespace(authConfig) {
1545
1572
  * @returns Resolved machine user name
1546
1573
  */
1547
1574
  async function resolveMachineUserName(options) {
1548
- const { cliMachineUser, profile, authConfig } = options;
1575
+ const { cliMachineUser, cliMachineUserSource, profile, authConfig } = options;
1549
1576
  const resolved = await loadMachineUserName({
1550
1577
  machineUser: cliMachineUser,
1578
+ machineUserSource: cliMachineUserSource,
1551
1579
  profile
1552
1580
  });
1553
1581
  if (resolved) return resolved;
@@ -1690,8 +1718,47 @@ const redirectUri = `http://localhost:${redirectPort}/callback`;
1690
1718
  function randomState() {
1691
1719
  return crypto.randomBytes(32).toString("base64url");
1692
1720
  }
1693
- function assertProfileLoginUser(args, authenticatedUser, authenticatedSubject) {
1694
- if (args.profile && args.profileUser && authenticatedUser !== args.profileUser && authenticatedSubject !== args.profileUser) throw new Error(`Profile "${args.profile}" is configured for "${args.profileUser}", but login authenticated "${authenticatedUser}".`);
1721
+ function getProfileUserMismatch(args, authenticatedUser, authenticatedSubject) {
1722
+ if (!args.profile || !args.profileUser || authenticatedUser === args.profileUser || authenticatedSubject === args.profileUser) return;
1723
+ return {
1724
+ profile: args.profile,
1725
+ oldUser: args.profileUser,
1726
+ authenticatedUser,
1727
+ loginMode: args.loginMode ?? "user"
1728
+ };
1729
+ }
1730
+ function quoteCommandArg(value, platform = process.platform) {
1731
+ if (platform === "win32") {
1732
+ if (/^[A-Za-z0-9_./:@+=,-]+$/.test(value)) return value;
1733
+ return;
1734
+ }
1735
+ return `'${value.replaceAll("'", "'\\''")}'`;
1736
+ }
1737
+ function profileUpdateCommand(mismatch) {
1738
+ const profileArg = quoteCommandArg(mismatch.profile);
1739
+ const userArg = quoteCommandArg(mismatch.authenticatedUser);
1740
+ if (profileArg && userArg) return `tailor-sdk profile update --user ${userArg} -- ${profileArg}`;
1741
+ return [
1742
+ "tailor-sdk profile update --user <authenticated-user> -- <profile>",
1743
+ `profile = ${JSON.stringify(mismatch.profile)}`,
1744
+ `authenticated user = ${JSON.stringify(mismatch.authenticatedUser)}`
1745
+ ].join("\n");
1746
+ }
1747
+ function retryInstruction(mismatch) {
1748
+ if (mismatch.loginMode === "machine-user") return "Then retry the original machine-user login command.";
1749
+ const profileArg = quoteCommandArg(mismatch.profile);
1750
+ if (!profileArg) return "Then retry the browser login with the same profile value.";
1751
+ return `Then run:\n tailor-sdk login --profile ${profileArg}`;
1752
+ }
1753
+ function profileUserMismatchError(mismatch) {
1754
+ const updateCommand = profileUpdateCommand(mismatch);
1755
+ const nextStep = retryInstruction(mismatch);
1756
+ return new Error(multiline`
1757
+ Profile "${mismatch.profile}" is configured for "${mismatch.oldUser}", but login authenticated "${mismatch.authenticatedUser}".
1758
+ The authenticated user has been saved. To use it with this profile, run:
1759
+ ${updateCommand}
1760
+ ${nextStep}
1761
+ `);
1695
1762
  }
1696
1763
  function shouldUpdateCurrentUser(profile, platformConfig) {
1697
1764
  if (!profile) return true;
@@ -1711,7 +1778,6 @@ const startAuthServer = async (args = {}) => {
1711
1778
  codeVerifier
1712
1779
  });
1713
1780
  const userInfo = await fetchUserInfo(tokens.accessToken, args.platformConfig);
1714
- assertProfileLoginUser(args, userInfo.email, userInfo.sub);
1715
1781
  const pfConfig = await readPlatformConfig();
1716
1782
  await saveUserTokens(pfConfig, userInfo.sub, {
1717
1783
  accessToken: tokens.accessToken,
@@ -1720,6 +1786,11 @@ const startAuthServer = async (args = {}) => {
1720
1786
  platformConfig: args.platformConfig,
1721
1787
  email: userInfo.email
1722
1788
  });
1789
+ const mismatch = getProfileUserMismatch(args, userInfo.email, userInfo.sub);
1790
+ if (mismatch) {
1791
+ writePlatformConfig(pfConfig);
1792
+ throw profileUserMismatchError(mismatch);
1793
+ }
1723
1794
  if (args.updateCurrentUser ?? true) pfConfig.current_user = userInfo.sub;
1724
1795
  await removeLegacyUserAlias(pfConfig, userInfo.email, userInfo.sub, args.platformConfig);
1725
1796
  writePlatformConfig(pfConfig);
@@ -1763,11 +1834,15 @@ const startAuthServer = async (args = {}) => {
1763
1834
  });
1764
1835
  };
1765
1836
  async function loginAsMachineUser(args) {
1766
- assertProfileLoginUser(args, args.clientId);
1767
1837
  const clientSecret = args.clientSecret ?? await prompt.password({ message: "Client secret" });
1768
1838
  const tokens = await fetchPlatformMachineUserToken(args.clientId, clientSecret, args.platformConfig);
1769
1839
  const pfConfig = await readPlatformConfig();
1770
1840
  await saveUserTokens(pfConfig, args.clientId, { accessToken: tokens.accessToken }, new Date(assertDefined(tokens.expiresAt, "token response missing expiresAt")).toISOString(), { platformConfig: args.platformConfig });
1841
+ const mismatch = getProfileUserMismatch(args, args.clientId);
1842
+ if (mismatch) {
1843
+ writePlatformConfig(pfConfig);
1844
+ throw profileUserMismatchError(mismatch);
1845
+ }
1771
1846
  if (args.updateCurrentUser ?? true) pfConfig.current_user = args.clientId;
1772
1847
  writePlatformConfig(pfConfig);
1773
1848
  }
@@ -1799,31 +1874,36 @@ const loginCommand = defineAppCommand({
1799
1874
  })
1800
1875
  }).describe("Machine User Login")]),
1801
1876
  run: async (args) => {
1802
- let platformConfig;
1803
- let profileUser;
1804
- if ("profile" in args && args.profile) {
1805
- const profileEntry = (await readPlatformConfig()).profiles[args.profile];
1806
- if (!profileEntry) throw new Error(`Profile "${args.profile}" not found`);
1807
- platformConfig = platformConfigFromProfile(profileEntry);
1808
- profileUser = profileEntry.user;
1877
+ try {
1878
+ let platformConfig;
1879
+ let profileUser;
1880
+ if ("profile" in args && args.profile) {
1881
+ const profileEntry = (await readPlatformConfig()).profiles[args.profile];
1882
+ if (!profileEntry) throw new Error(`Profile "${args.profile}" not found`);
1883
+ platformConfig = platformConfigFromProfile(profileEntry);
1884
+ profileUser = profileEntry.user;
1885
+ }
1886
+ const updateCurrentUser = shouldUpdateCurrentUser(args.profile, platformConfig);
1887
+ if ("machine-user" in args) await loginAsMachineUser({
1888
+ clientId: args.clientId,
1889
+ clientSecret: args.clientSecret,
1890
+ profile: args.profile,
1891
+ profileUser,
1892
+ platformConfig,
1893
+ updateCurrentUser,
1894
+ loginMode: "machine-user"
1895
+ });
1896
+ else await startAuthServer({
1897
+ profile: args.profile,
1898
+ profileUser,
1899
+ platformConfig,
1900
+ updateCurrentUser,
1901
+ loginMode: "user"
1902
+ });
1903
+ logger.success("Successfully logged in to Tailor Platform.");
1904
+ } finally {
1905
+ await closeConnectionPool();
1809
1906
  }
1810
- const updateCurrentUser = shouldUpdateCurrentUser(args.profile, platformConfig);
1811
- if ("machine-user" in args) await loginAsMachineUser({
1812
- clientId: args.clientId,
1813
- clientSecret: args.clientSecret,
1814
- profile: args.profile,
1815
- profileUser,
1816
- platformConfig,
1817
- updateCurrentUser
1818
- });
1819
- else await startAuthServer({
1820
- profile: args.profile,
1821
- profileUser,
1822
- platformConfig,
1823
- updateCurrentUser
1824
- });
1825
- logger.success("Successfully logged in to Tailor Platform.");
1826
- await closeConnectionPool();
1827
1907
  }
1828
1908
  });
1829
1909
 
@@ -3169,23 +3249,23 @@ function findTarget(lock, kind, workspaceName) {
3169
3249
 
3170
3250
  //#endregion
3171
3251
  //#region src/cli/commands/setup/action.yml
3172
- var action_default = "# __HEADER__\nname: __WORKSPACE_NAME__\ndescription: >-\n Deploy __WORKSPACE_NAME__ to Tailor Platform.\n Checkout and dependency installation are expected to be handled by the caller.\n\ninputs:\n workspace-id:\n description: Tailor Platform workspace id\n required: true\n name:\n description: Workspace name (used in Slack notifications)\n required: true\n working-directory:\n description: App directory relative to the repository root\n required: false\n default: \".\"\n platform-client-id:\n description: Machine-user client id\n required: true\n platform-client-secret:\n description: Machine-user client secret\n required: true\n slack-token:\n description: Slack bot token\n required: false\n slack-channel-id:\n description: Slack channel id\n required: false\n user-mapping:\n description: JSON string mapping GitHub usernames to Slack user IDs\n required: false\n package-manager:\n description: Package manager used for dependency installation (pnpm, npm, yarn, bun)\n required: false\n default: pnpm\n\noutputs:\n app-url:\n description: Deployed application URL\n value: ${{ steps.tailor-apply.outputs.app-url }}\n\nruns:\n using: composite\n steps:\n # __STATIC_WEBSITE_BUILD_START__\n - id: build-site\n shell: bash\n run: |\n # Replace with your static website build command.\n # Example: pnpm --filter <package-name> run build:static\n # Note: this run: command is user-editable. Custom build commands are preserved across\n # reruns and are not treated as drift by setup check. Other edits to this file are flagged\n # as drift and will be overwritten if you re-run setup action with --force.\n true\n # __STATIC_WEBSITE_BUILD_END__\n - id: tailor-apply\n uses: tailor-platform/actions/deploy@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-id: ${{ inputs.workspace-id }}\n working-directory: ${{ inputs.working-directory }}\n package-manager: ${{ inputs.package-manager }}\n platform-client-id: ${{ inputs.platform-client-id }}\n platform-client-secret: ${{ inputs.platform-client-secret }}\n - id: tailor-notify\n if: failure() && inputs.slack-token != '' && inputs.slack-channel-id != ''\n uses: tailor-platform/actions/notify@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n provider: slack\n status: failure\n workspace-name: ${{ inputs.name }}\n slack-token: ${{ inputs.slack-token }}\n slack-channel-id: ${{ inputs.slack-channel-id }}\n user-mapping: ${{ inputs.user-mapping }}\n";
3252
+ var action_default = "# __HEADER__\nname: __WORKSPACE_NAME__\ndescription: >-\n Deploy __WORKSPACE_NAME__ to Tailor Platform.\n Checkout and dependency installation are expected to be handled by the caller.\n\ninputs:\n workspace-id:\n description: Tailor Platform workspace id\n required: true\n name:\n description: Workspace name (used in Slack notifications)\n required: true\n working-directory:\n description: App directory relative to the repository root\n required: false\n default: \".\"\n config:\n description: SDK config path, or comma-separated config paths for multi-config deploys\n required: false\n default: \"tailor.config.ts\"\n deploy:\n description: Whether to run the Tailor deploy step after build steps\n required: false\n default: \"true\"\n build-site:\n description: Whether to run the static website build slot when present\n required: false\n default: \"true\"\n platform-client-id:\n description: Machine-user client id\n required: true\n platform-client-secret:\n description: Machine-user client secret\n required: true\n slack-token:\n description: Slack bot token\n required: false\n slack-channel-id:\n description: Slack channel id\n required: false\n user-mapping:\n description: JSON string mapping GitHub usernames to Slack user IDs\n required: false\n package-manager:\n description: Package manager used for dependency installation (pnpm, npm, yarn, bun)\n required: false\n default: pnpm\n\noutputs:\n app-url:\n description: Deployed application URL\n value: ${{ steps.tailor-apply.outputs.app-url }}\n\nruns:\n using: composite\n steps:\n # __STATIC_WEBSITE_BUILD_START__\n - id: build-site\n if: inputs.build-site == 'true'\n shell: bash\n run: |\n # Replace with your static website build command.\n # Example: pnpm --filter <package-name> run build:static\n # Note: this run: command is user-editable. Custom build commands are preserved across\n # reruns and are not treated as drift by setup check. Other edits to this file are flagged\n # as drift and will be overwritten if you re-run setup action with --force.\n true\n # __STATIC_WEBSITE_BUILD_END__\n - id: tailor-apply\n if: inputs.deploy == 'true'\n uses: tailor-platform/actions/deploy@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n env:\n TAILOR_PLATFORM_SDK_CONFIG_PATH: ${{ inputs.config }}\n with:\n workspace-id: ${{ inputs.workspace-id }}\n working-directory: ${{ inputs.working-directory }}\n package-manager: ${{ inputs.package-manager }}\n platform-client-id: ${{ inputs.platform-client-id }}\n platform-client-secret: ${{ inputs.platform-client-secret }}\n - id: tailor-notify\n if: failure() && inputs.slack-token != '' && inputs.slack-channel-id != ''\n uses: tailor-platform/actions/notify@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n provider: slack\n status: failure\n workspace-name: ${{ inputs.name }}\n slack-token: ${{ inputs.slack-token }}\n slack-channel-id: ${{ inputs.slack-channel-id }}\n user-mapping: ${{ inputs.user-mapping }}\n";
3173
3253
 
3174
3254
  //#endregion
3175
3255
  //#region src/cli/commands/setup/branch.workflow.yml
3176
- var branch_workflow_default = "# __HEADER__\nname: Tailor (__WORKSPACE_NAME__)\n\non:\n # __PULL_REQUEST_START__\n pull_request:\n branches: [\"__BRANCH__\"]\n # __PATHS__\n # __PULL_REQUEST_END__\n push:\n branches: [\"__BRANCH__\"]\n # __PATHS__\n workflow_dispatch:\n # __DISPATCH_INPUTS_START__\n inputs:\n dry-run:\n description: Preview changes without deploying\n type: boolean\n default: false\n # __DISPATCH_INPUTS_END__\n\npermissions:\n contents: read\n\njobs:\n # __PLAN_JOB_START__\n tailor-plan:\n if: >-\n github.event_name == 'pull_request' ||\n (github.event_name == 'workflow_dispatch' && inputs['dry-run'])\n runs-on: ubuntu-latest\n timeout-minutes: 30\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n concurrency:\n group: tailor-plan-__WORKSPACE_NAME__-${{ github.event.pull_request.number || github.run_id }}\n cancel-in-progress: true\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-generate-check\n uses: tailor-platform/actions/generate-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_START__\n - id: tailor-seed-validate\n uses: tailor-platform/actions/seed-validate@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_END__\n - id: tailor-drift-check\n uses: tailor-platform/actions/drift-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __MIGRATION_DRIFT_CHECK_START__\n - id: tailor-migration-drift-check\n uses: tailor-platform/actions/migration-drift-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __MIGRATION_DRIFT_CHECK_END__\n - id: tailor-plan\n # Fork PRs cannot read secrets; the checks above still run for them.\n if: github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork\n uses: tailor-platform/actions/plan@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n label: __WORKSPACE_NAME__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n # __PLAN_JOB_END__\n # __ERD_PREVIEW_JOB_START__\n tailor-erd-preview-matrix:\n if: github.event_name == 'pull_request'\n runs-on: ubuntu-latest\n timeout-minutes: 5\n permissions:\n contents: read\n outputs:\n namespaces: ${{ steps.tailor-erd-preview-matrix.outputs.namespaces }}\n base-app-dir: ${{ steps.tailor-erd-preview-matrix.outputs['base-app-dir'] }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n persist-credentials: false\n - id: tailor-checkout-base\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n repository: ${{ github.event.pull_request.base.repo.full_name }}\n ref: ${{ github.event.pull_request.base.sha }}\n path: .tailor-erd-base\n persist-credentials: false\n - id: tailor-erd-preview-matrix\n shell: bash\n env:\n APP_DIR: \"__APP_DIR__\"\n WORKSPACE_NAME: \"__WORKSPACE_NAME__\"\n run: |\n set -euo pipefail\n node <<'NODE'\n const fs = require(\"node:fs\");\n\n const appDir = process.env.APP_DIR || \".\";\n const workspaceName = process.env.WORKSPACE_NAME;\n const output = process.env.GITHUB_OUTPUT;\n const dirPattern = /^[A-Za-z0-9._/-]+$/;\n const namespacePattern = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\n\n function lockTarget(file) {\n try {\n const lock = JSON.parse(fs.readFileSync(file, \"utf8\"));\n return lock.targets?.find(\n (candidate) =>\n candidate.kind === \"branch\" &&\n candidate.workspaceName === workspaceName,\n );\n } catch (error) {\n if (error && error.code === \"ENOENT\") return undefined;\n throw error;\n }\n }\n\n function namespacesFromTarget(target, label) {\n const namespaces =\n target?.inputs?.erdPreview === true && Array.isArray(target.inputs?.erdNamespaces)\n ? target.inputs.erdNamespaces\n : [];\n for (const namespace of namespaces) {\n if (typeof namespace !== \"string\" || !namespacePattern.test(namespace)) {\n throw new Error(`Invalid ERD namespace in ${label}: ${String(namespace)}`);\n }\n }\n return namespaces;\n }\n\n function normalizeDir(value, label) {\n const raw = typeof value === \"string\" && value.length > 0 ? value : appDir;\n const normalized =\n raw.replaceAll(\"\\\\\", \"/\").replace(/\\/{2,}/g, \"/\").replace(/^\\.\\//, \"\").replace(/\\/$/, \"\") ||\n \".\";\n if (\n !dirPattern.test(normalized) ||\n normalized.startsWith(\"/\") ||\n normalized.split(\"/\").includes(\"..\")\n ) {\n throw new Error(`Invalid ERD app dir in ${label}: ${raw}`);\n }\n return normalized;\n }\n\n const headTarget = lockTarget(\".github/tailor.lock\");\n const baseTarget = lockTarget(\".tailor-erd-base/.github/tailor.lock\");\n const baseAppDir = normalizeDir(baseTarget?.inputs?.dir, \"base setup lock\");\n const namespaces = [\n ...new Set([\n ...namespacesFromTarget(headTarget, \"head setup lock\"),\n ...namespacesFromTarget(baseTarget, \"base setup lock\"),\n ]),\n ].sort((a, b) => a.localeCompare(b));\n\n if (namespaces.length === 0) {\n console.error(\"No ERD preview namespaces found in the head or base setup lock.\");\n process.exit(1);\n }\n\n fs.appendFileSync(output, `namespaces=${JSON.stringify(namespaces)}\\n`);\n fs.appendFileSync(output, `base-app-dir=${baseAppDir}\\n`);\n NODE\n\n tailor-erd-preview:\n needs: tailor-erd-preview-matrix\n if: github.event_name == 'pull_request'\n runs-on: ubuntu-latest\n timeout-minutes: 15\n permissions:\n contents: read\n strategy:\n fail-fast: false\n matrix:\n namespace: ${{ fromJSON(needs.tailor-erd-preview-matrix.outputs.namespaces) }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n persist-credentials: false\n - id: tailor-setup\n uses: tailor-platform/actions/setup@7817f37adf2891fbb2ebbe0a3b222a5fa2ed0c1f # v1.3.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-checkout-base\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n repository: ${{ github.event.pull_request.base.repo.full_name }}\n ref: ${{ github.event.pull_request.base.sha }}\n path: .tailor-erd-base\n persist-credentials: false\n - id: tailor-detect-base-package-manager\n shell: bash\n run: |\n set -euo pipefail\n cd .tailor-erd-base\n base_package_manager=\"$(\n if [ -f pnpm-lock.yaml ]; then\n echo pnpm\n elif [ -f yarn.lock ]; then\n echo yarn\n elif [ -f bun.lockb ] || [ -f bun.lock ]; then\n echo bun\n elif [ -f package-lock.json ]; then\n echo npm\n else\n echo \"__PACKAGE_MANAGER__\"\n fi\n )\"\n echo \"package-manager=$base_package_manager\" >> \"$GITHUB_OUTPUT\"\n if [ \"$base_package_manager\" = \"pnpm\" ]; then\n base_pnpm_version=\"$(node <<'NODE'\n const fs = require(\"node:fs\");\n\n const fallback = \"10\";\n\n function readManifest(file) {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch {\n return {};\n }\n }\n\n function pnpmVersion(manifest) {\n const packageManager = manifest.packageManager;\n if (typeof packageManager === \"string\" && packageManager.startsWith(\"pnpm@\")) {\n return packageManager.slice(\"pnpm@\".length).split(\"+\")[0];\n }\n\n const devPackageManager = manifest.devEngines?.packageManager;\n if (devPackageManager?.name === \"pnpm\" && devPackageManager.version) {\n return devPackageManager.version;\n }\n\n return undefined;\n }\n\n process.stdout.write(\n pnpmVersion(readManifest(\"package.json\")) ?? fallback,\n );\n NODE\n )\"\n echo \"pnpm-version=$base_pnpm_version\" >> \"$GITHUB_OUTPUT\"\n fi\n - id: tailor-setup-base-pnpm\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] == 'pnpm'\n uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9\n with:\n version: ${{ steps.tailor-detect-base-package-manager.outputs['pnpm-version'] }}\n package_json_file: .tailor-erd-base/package.json\n run_install: false\n - id: tailor-setup-base-node\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] != 'bun'\n uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0\n with:\n node-version-file: .tailor-erd-base/package.json\n - id: tailor-setup-base-yarn\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] == 'yarn'\n shell: bash\n working-directory: .tailor-erd-base\n run: |\n set -euo pipefail\n corepack enable\n - id: tailor-setup-base-bun\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] == 'bun'\n uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0\n - id: tailor-install-base\n shell: bash\n working-directory: .tailor-erd-base\n env:\n BASE_PACKAGE_MANAGER: ${{ steps.tailor-detect-base-package-manager.outputs['package-manager'] }}\n run: |\n set -euo pipefail\n case \"$BASE_PACKAGE_MANAGER\" in\n pnpm) pnpm install --frozen-lockfile ;;\n npm) npm ci ;;\n yarn)\n if grep -q '^__metadata:' yarn.lock; then\n yarn install --immutable\n else\n yarn install --frozen-lockfile\n fi\n ;;\n bun) bun install --frozen-lockfile ;;\n *)\n echo \"::error::Unsupported base package-manager '$BASE_PACKAGE_MANAGER' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n - id: tailor-restore-head-setup\n uses: tailor-platform/actions/setup@7817f37adf2891fbb2ebbe0a3b222a5fa2ed0c1f # v1.3.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-build-erd-preview\n shell: bash\n env:\n APP_DIR: \"__APP_DIR__\"\n BASE_APP_DIR: ${{ needs.tailor-erd-preview-matrix.outputs['base-app-dir'] }}\n BASE_PACKAGE_MANAGER: ${{ steps.tailor-detect-base-package-manager.outputs['package-manager'] }}\n NAMESPACE: ${{ matrix.namespace }}\n run: |\n set -euo pipefail\n\n run_tailor_cli() {\n case \"__PACKAGE_MANAGER__\" in\n pnpm) pnpm exec tailor \"$@\" ;;\n npm) npx tailor \"$@\" ;;\n yarn) yarn tailor \"$@\" ;;\n bun) bunx tailor \"$@\" ;;\n *)\n echo \"::error::Unsupported package-manager '__PACKAGE_MANAGER__' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n }\n\n run_head_node() {\n case \"__PACKAGE_MANAGER__\" in\n pnpm) pnpm exec node \"$@\" ;;\n npm) node \"$@\" ;;\n yarn) yarn node \"$@\" ;;\n bun) node \"$@\" ;;\n *)\n echo \"::error::Unsupported package-manager '__PACKAGE_MANAGER__' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n }\n\n tailor_cli_bin=\"$(\n run_head_node - <<'NODE'\n const path = require(\"node:path\");\n const { createRequire } = require(\"node:module\");\n const appDir = process.env.APP_DIR || \".\";\n const githubWorkspace = process.env.GITHUB_WORKSPACE;\n if (!githubWorkspace) {\n throw new Error(\"GITHUB_WORKSPACE is required.\");\n }\n\n let lastError;\n for (const manifestPath of [\n path.join(githubWorkspace, appDir, \"package.json\"),\n path.join(githubWorkspace, \"package.json\"),\n ]) {\n try {\n const requireFromManifest = createRequire(manifestPath);\n process.stdout.write(\n path.join(\n path.dirname(requireFromManifest.resolve(\"@tailor-platform/sdk/cli\")),\n \"index.mjs\",\n ),\n );\n process.exit(0);\n } catch (error) {\n lastError = error;\n }\n }\n throw lastError || new Error(\"Failed to resolve @tailor-platform/sdk/cli.\");\n NODE\n )\"\n\n run_head_tailor_cli_bin() {\n local command_cwd=\"$1\"\n shift\n\n run_head_cli_env() {\n env TAILOR_CLI_BIN=\"$tailor_cli_bin\" TAILOR_CLI_CWD=\"$command_cwd\" \"$@\"\n }\n\n (\n cd \"$GITHUB_WORKSPACE\" || exit 1\n case \"__PACKAGE_MANAGER__\" in\n pnpm) run_head_cli_env pnpm exec node \"$head_cli_runner\" \"$@\" ;;\n npm) run_head_cli_env node \"$head_cli_runner\" \"$@\" ;;\n yarn) run_head_cli_env yarn node \"$head_cli_runner\" \"$@\" ;;\n bun) run_head_cli_env bun \"$head_cli_runner\" \"$@\" ;;\n *)\n echo \"::error::Unsupported package-manager '__PACKAGE_MANAGER__' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n )\n }\n\n run_base_tailor_cli_bin() {\n local command_cwd=\"$1\"\n shift\n\n run_head_cli_env() {\n env TAILOR_CLI_BIN=\"$tailor_cli_bin\" TAILOR_CLI_CWD=\"$command_cwd\" \"$@\"\n }\n\n (\n cd \"$command_cwd\" || exit 1\n case \"$BASE_PACKAGE_MANAGER\" in\n pnpm) run_head_cli_env pnpm exec node \"$head_cli_runner\" \"$@\" ;;\n npm) run_head_cli_env node \"$head_cli_runner\" \"$@\" ;;\n yarn) run_head_cli_env yarn node \"$head_cli_runner\" \"$@\" ;;\n bun) run_head_cli_env bun \"$head_cli_runner\" \"$@\" ;;\n *)\n echo \"::error::Unsupported base package-manager '$BASE_PACKAGE_MANAGER' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n )\n }\n\n head_output=\"$RUNNER_TEMP/tailor-erd/head\"\n base_output=\"$RUNNER_TEMP/tailor-erd/base\"\n preview_output=\"$RUNNER_TEMP/tailor-erd/preview\"\n dts_output=\"$RUNNER_TEMP/tailor-erd/dts\"\n head_cli_runner=\"$RUNNER_TEMP/tailor-erd/run-head-cli.mjs\"\n head_log=\"$RUNNER_TEMP/tailor-erd/head-$NAMESPACE.log\"\n base_log=\"$RUNNER_TEMP/tailor-erd/base-$NAMESPACE.log\"\n rm -rf \"$head_output\" \"$base_output\" \"$preview_output\" \"$dts_output\"\n mkdir -p \"$head_output\" \"$base_output\" \"$preview_output\" \"$dts_output\"\n cat > \"$head_cli_runner\" <<'NODE'\n import { pathToFileURL } from \"node:url\";\n\n const cliBin = process.env.TAILOR_CLI_BIN;\n const commandCwd = process.env.TAILOR_CLI_CWD;\n if (!cliBin || !commandCwd) {\n throw new Error(\"TAILOR_CLI_BIN and TAILOR_CLI_CWD are required.\");\n }\n\n process.chdir(commandCwd);\n process.argv = [process.argv[0], cliBin, ...process.argv.slice(2)];\n await import(pathToFileURL(cliBin).href);\n NODE\n\n head_config=\"$GITHUB_WORKSPACE/$APP_DIR/tailor.config.ts\"\n base_config=\"$GITHUB_WORKSPACE/.tailor-erd-base/$BASE_APP_DIR/tailor.config.ts\"\n head_html=\"$head_output/$NAMESPACE/dist/index.html\"\n base_html=\"$base_output/$NAMESPACE/dist/index.html\"\n preview_html=\"$preview_output/$NAMESPACE-viewer.html\"\n\n head_missing=\"false\"\n if [ ! -f \"$head_config\" ]; then\n echo \"Head ERD config not found; rendering base objects as removed.\"\n head_missing=\"true\"\n elif ! (\n cd \"$GITHUB_WORKSPACE/$APP_DIR\" || exit 1\n TAILOR_PLATFORM_SDK_DTS_PATH=\"$dts_output/head-$NAMESPACE.d.ts\" \\\n run_tailor_cli tailordb erd export --config \"$head_config\" --namespace \"$NAMESPACE\" --output \"$head_output\"\n ) >\"$head_log\" 2>&1; then\n if grep -q 'not found in local config.db' \"$head_log\"; then\n cat \"$head_log\"\n echo \"Head ERD namespace '$NAMESPACE' not found; rendering base objects as removed.\"\n head_missing=\"true\"\n else\n cat \"$head_log\"\n exit 1\n fi\n elif [ -s \"$head_log\" ]; then\n cat \"$head_log\"\n fi\n\n base_missing=\"false\"\n if [ ! -f \"$base_config\" ]; then\n echo \"Base ERD config not found; rendering current objects as added.\"\n base_missing=\"true\"\n elif ! (\n TAILOR_PLATFORM_SDK_DTS_PATH=\"$dts_output/base-$NAMESPACE.d.ts\" \\\n run_base_tailor_cli_bin \"$GITHUB_WORKSPACE/.tailor-erd-base/$BASE_APP_DIR\" tailordb erd export --config \"$base_config\" --namespace \"$NAMESPACE\" --output \"$base_output\"\n ) >\"$base_log\" 2>&1; then\n if grep -q 'not found in local config.db' \"$base_log\"; then\n cat \"$base_log\"\n echo \"Base ERD namespace '$NAMESPACE' not found; rendering current objects as added.\"\n base_missing=\"true\"\n else\n cat \"$base_log\"\n exit 1\n fi\n elif [ -s \"$base_log\" ]; then\n cat \"$base_log\"\n fi\n\n if [ \"$head_missing\" = \"true\" ] && [ \"$base_missing\" = \"true\" ]; then\n echo \"::error::ERD namespace '$NAMESPACE' was not found in head or base.\"\n exit 1\n fi\n if [ \"$head_missing\" = \"false\" ] && [ ! -f \"$head_html\" ]; then\n echo \"::error::Head ERD viewer was not generated at $head_html\"\n exit 1\n fi\n if [ \"$base_missing\" = \"false\" ] && [ ! -f \"$base_html\" ]; then\n echo \"::error::Base ERD viewer was not generated at $base_html\"\n exit 1\n fi\n\n diff_args=(--namespace \"$NAMESPACE\" --output \"$preview_html\")\n if [ \"$head_missing\" = \"false\" ]; then\n diff_args+=(--head-html \"$head_html\")\n fi\n if [ \"$base_missing\" = \"false\" ]; then\n diff_args+=(--base-html \"$base_html\")\n fi\n run_head_tailor_cli_bin \"$GITHUB_WORKSPACE\" tailordb erd diff \"${diff_args[@]}\"\n - id: tailor-upload-erd-viewer\n uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1\n with:\n name: ${{ matrix.namespace }}-viewer.html\n path: ${{ runner.temp }}/tailor-erd/preview/${{ matrix.namespace }}-viewer.html\n if-no-files-found: error\n archive: false\n retention-days: 7\n\n # __ERD_PREVIEW_JOB_END__\n # __ERD_PREVIEW_COMMENT_JOB_START__\n tailor-erd-preview-comment:\n needs: tailor-erd-preview\n if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository\n runs-on: ubuntu-latest\n timeout-minutes: 5\n permissions:\n actions: read\n pull-requests: write\n steps:\n - id: tailor-comment-erd-preview\n env:\n GH_TOKEN: ${{ github.token }}\n REPO: ${{ github.repository }}\n RUN_ID: ${{ github.run_id }}\n SERVER: ${{ github.server_url }}\n PR_NUMBER: ${{ github.event.pull_request.number }}\n BASE_REF: ${{ github.event.pull_request.base.ref }}\n HEAD_SHA: ${{ github.event.pull_request.head.sha }}\n MARKER: \"<!-- tailor-erd-preview: __WORKSPACE_NAME__ -->\"\n run: |\n set -euo pipefail\n\n current_head=$(gh api \"repos/$REPO/pulls/$PR_NUMBER\" --jq '.head.sha')\n if [ \"$current_head\" != \"$HEAD_SHA\" ]; then\n echo \"Skipping stale ERD preview comment for $HEAD_SHA; current head is $current_head.\"\n exit 0\n fi\n\n body=\"$MARKER\"$'\\n'\"### TailorDB ERD preview (__WORKSPACE_NAME__)\"$'\\n\\n'\n body+=\"Self-contained ERD viewer HTML artifacts for this pull request. Each viewer can switch between the current schema and a diff against base branch \\`$BASE_REF\\`.\"$'\\n'\n\n while IFS=$'\\t' read -r name id; do\n [ -z \"$name\" ] && continue\n if [[ \"$name\" != *-viewer.html ]]; then\n continue\n fi\n ns=${name%-viewer.html}\n label=\"$ns viewer\"\n body+=$'\\n'\"- **$label**: [$name]($SERVER/$REPO/actions/runs/$RUN_ID/artifacts/$id)\"\n done < <(gh api \"repos/$REPO/actions/runs/$RUN_ID/artifacts\" --paginate \\\n --jq '.artifacts[] | select(.name | endswith(\"-viewer.html\")) | [.name, (.id|tostring)] | @tsv' | sort)\n\n existing=$(gh api \"repos/$REPO/issues/$PR_NUMBER/comments\" --paginate \\\n --jq 'map(select(.body | contains(env.MARKER))) | .[0].id // empty')\n if [ -n \"$existing\" ]; then\n gh api --method PATCH \"repos/$REPO/issues/comments/$existing\" -f body=\"$body\" >/dev/null\n else\n gh api --method POST \"repos/$REPO/issues/$PR_NUMBER/comments\" -f body=\"$body\" >/dev/null\n fi\n\n # __ERD_PREVIEW_COMMENT_JOB_END__\n tailor-deploy:\n # __DEPLOY_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n permissions:\n contents: read\n environment: __ENVIRONMENT__\n concurrency:\n group: tailor-deploy-__WORKSPACE_NAME__\n cancel-in-progress: false\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-apply\n uses: tailor-platform/actions/deploy@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n # __SEED_DATA_START__\n - id: seed-data\n if: false\n shell: bash\n # __WORKING_DIRECTORY__\n run: |\n # Uncomment and implement to seed data on deploy.\n # Run after apply so the schema is ready.\n # Example: node scripts/seed.mjs\n true\n # __SEED_DATA_END__\n - id: slack-prereq\n if: always()\n shell: bash\n env:\n SLACK_TOKEN: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n SLACK_CHANNEL_ID: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n run: |\n if [[ -n \"$SLACK_TOKEN\" && -n \"$SLACK_CHANNEL_ID\" ]]; then\n echo \"ready=true\" >> \"$GITHUB_OUTPUT\"\n fi\n - id: tailor-notify\n if: always() && steps.slack-prereq.outputs.ready == 'true'\n uses: tailor-platform/actions/notify@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n provider: slack\n status: ${{ job.status }}\n workspace-name: __WORKSPACE_NAME__\n slack-token: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n slack-channel-id: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n # user-mapping: ${{ vars.TAILOR_SLACK_USER_MAPPING }}\n";
3256
+ var branch_workflow_default = "# __HEADER__\nname: Tailor (__WORKSPACE_NAME__)\n\non:\n # __PULL_REQUEST_START__\n pull_request:\n branches: [\"__BRANCH__\"]\n # __PATHS__\n # __PULL_REQUEST_END__\n push:\n branches: [\"__BRANCH__\"]\n # __PATHS__\n workflow_dispatch:\n # __DISPATCH_INPUTS_START__\n inputs:\n dry-run:\n description: Preview changes without deploying\n type: boolean\n default: false\n # __DISPATCH_INPUTS_END__\n\npermissions:\n contents: read\n\njobs:\n # __PLAN_JOB_START__\n tailor-plan:\n if: >-\n github.event_name == 'pull_request' ||\n (github.event_name == 'workflow_dispatch' && inputs['dry-run'])\n runs-on: ubuntu-latest\n timeout-minutes: 30\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n concurrency:\n group: tailor-plan-__WORKSPACE_NAME__-${{ github.event.pull_request.number || github.run_id }}\n cancel-in-progress: true\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-generate-check\n uses: tailor-platform/actions/generate-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_START__\n - id: tailor-seed-validate\n uses: tailor-platform/actions/seed-validate@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_END__\n - id: tailor-drift-check\n uses: tailor-platform/actions/drift-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __MIGRATION_DRIFT_CHECK_START__\n - id: tailor-migration-drift-check\n uses: tailor-platform/actions/migration-drift-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __MIGRATION_DRIFT_CHECK_END__\n - id: tailor-plan\n # Fork PRs cannot read secrets; the checks above still run for them.\n if: github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork\n uses: tailor-platform/actions/plan@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n label: __WORKSPACE_NAME__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n # __PLAN_JOB_END__\n # __ERD_PREVIEW_JOB_START__\n tailor-erd-preview-matrix:\n if: github.event_name == 'pull_request'\n runs-on: ubuntu-latest\n timeout-minutes: 5\n permissions:\n contents: read\n outputs:\n namespaces: ${{ steps.tailor-erd-preview-matrix.outputs.namespaces }}\n base-app-dir: ${{ steps.tailor-erd-preview-matrix.outputs['base-app-dir'] }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n persist-credentials: false\n - id: tailor-checkout-base\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n repository: ${{ github.event.pull_request.base.repo.full_name }}\n ref: ${{ github.event.pull_request.base.sha }}\n path: .tailor-erd-base\n persist-credentials: false\n - id: tailor-erd-preview-matrix\n shell: bash\n env:\n APP_DIR: \"__APP_DIR__\"\n WORKSPACE_NAME: \"__WORKSPACE_NAME__\"\n run: |\n set -euo pipefail\n node <<'NODE'\n const fs = require(\"node:fs\");\n\n const appDir = process.env.APP_DIR || \".\";\n const workspaceName = process.env.WORKSPACE_NAME;\n const output = process.env.GITHUB_OUTPUT;\n const dirPattern = /^[A-Za-z0-9._/-]+$/;\n const namespacePattern = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\n\n function lockTarget(file) {\n try {\n const lock = JSON.parse(fs.readFileSync(file, \"utf8\"));\n return lock.targets?.find(\n (candidate) =>\n candidate.kind === \"branch\" &&\n candidate.workspaceName === workspaceName,\n );\n } catch (error) {\n if (error && error.code === \"ENOENT\") return undefined;\n throw error;\n }\n }\n\n function namespacesFromTarget(target, label) {\n const namespaces =\n target?.inputs?.erdPreview === true && Array.isArray(target.inputs?.erdNamespaces)\n ? target.inputs.erdNamespaces\n : [];\n for (const namespace of namespaces) {\n if (typeof namespace !== \"string\" || !namespacePattern.test(namespace)) {\n throw new Error(`Invalid ERD namespace in ${label}: ${String(namespace)}`);\n }\n }\n return namespaces;\n }\n\n function normalizeDir(value, label) {\n const raw = typeof value === \"string\" && value.length > 0 ? value : appDir;\n const normalized =\n raw.replaceAll(\"\\\\\", \"/\").replace(/\\/{2,}/g, \"/\").replace(/^\\.\\//, \"\").replace(/\\/$/, \"\") ||\n \".\";\n if (\n !dirPattern.test(normalized) ||\n normalized.startsWith(\"/\") ||\n normalized.split(\"/\").includes(\"..\")\n ) {\n throw new Error(`Invalid ERD app dir in ${label}: ${raw}`);\n }\n return normalized;\n }\n\n const headTarget = lockTarget(\".github/tailor.lock\");\n const baseTarget = lockTarget(\".tailor-erd-base/.github/tailor.lock\");\n const baseAppDir = normalizeDir(baseTarget?.inputs?.dir, \"base setup lock\");\n const namespaces = [\n ...new Set([\n ...namespacesFromTarget(headTarget, \"head setup lock\"),\n ...namespacesFromTarget(baseTarget, \"base setup lock\"),\n ]),\n ].sort((a, b) => a.localeCompare(b));\n\n if (namespaces.length === 0) {\n console.error(\"No ERD preview namespaces found in the head or base setup lock.\");\n process.exit(1);\n }\n\n fs.appendFileSync(output, `namespaces=${JSON.stringify(namespaces)}\\n`);\n fs.appendFileSync(output, `base-app-dir=${baseAppDir}\\n`);\n NODE\n\n tailor-erd-preview:\n needs: tailor-erd-preview-matrix\n if: github.event_name == 'pull_request'\n runs-on: ubuntu-latest\n timeout-minutes: 15\n permissions:\n contents: read\n strategy:\n fail-fast: false\n matrix:\n namespace: ${{ fromJSON(needs.tailor-erd-preview-matrix.outputs.namespaces) }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n persist-credentials: false\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-checkout-base\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n repository: ${{ github.event.pull_request.base.repo.full_name }}\n ref: ${{ github.event.pull_request.base.sha }}\n path: .tailor-erd-base\n persist-credentials: false\n - id: tailor-detect-base-package-manager\n shell: bash\n run: |\n set -euo pipefail\n cd .tailor-erd-base\n base_package_manager=\"$(\n if [ -f pnpm-lock.yaml ]; then\n echo pnpm\n elif [ -f yarn.lock ]; then\n echo yarn\n elif [ -f bun.lockb ] || [ -f bun.lock ]; then\n echo bun\n elif [ -f package-lock.json ]; then\n echo npm\n else\n echo \"__PACKAGE_MANAGER__\"\n fi\n )\"\n echo \"package-manager=$base_package_manager\" >> \"$GITHUB_OUTPUT\"\n if [ \"$base_package_manager\" = \"pnpm\" ]; then\n base_pnpm_version=\"$(node <<'NODE'\n const fs = require(\"node:fs\");\n\n const fallback = \"10\";\n\n function readManifest(file) {\n try {\n return JSON.parse(fs.readFileSync(file, \"utf8\"));\n } catch {\n return {};\n }\n }\n\n function pnpmVersion(manifest) {\n const packageManager = manifest.packageManager;\n if (typeof packageManager === \"string\" && packageManager.startsWith(\"pnpm@\")) {\n return packageManager.slice(\"pnpm@\".length).split(\"+\")[0];\n }\n\n const devPackageManager = manifest.devEngines?.packageManager;\n if (devPackageManager?.name === \"pnpm\" && devPackageManager.version) {\n return devPackageManager.version;\n }\n\n return undefined;\n }\n\n process.stdout.write(\n pnpmVersion(readManifest(\"package.json\")) ?? fallback,\n );\n NODE\n )\"\n echo \"pnpm-version=$base_pnpm_version\" >> \"$GITHUB_OUTPUT\"\n fi\n - id: tailor-setup-base-pnpm\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] == 'pnpm'\n uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9\n with:\n version: ${{ steps.tailor-detect-base-package-manager.outputs['pnpm-version'] }}\n package_json_file: .tailor-erd-base/package.json\n run_install: false\n - id: tailor-setup-base-node\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] != 'bun'\n uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7\n with:\n node-version-file: .tailor-erd-base/package.json\n - id: tailor-setup-base-yarn\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] == 'yarn'\n shell: bash\n working-directory: .tailor-erd-base\n run: |\n set -euo pipefail\n corepack enable\n - id: tailor-setup-base-bun\n if: steps.tailor-detect-base-package-manager.outputs['package-manager'] == 'bun'\n uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0\n - id: tailor-install-base\n shell: bash\n working-directory: .tailor-erd-base\n env:\n BASE_PACKAGE_MANAGER: ${{ steps.tailor-detect-base-package-manager.outputs['package-manager'] }}\n run: |\n set -euo pipefail\n case \"$BASE_PACKAGE_MANAGER\" in\n pnpm) pnpm install --frozen-lockfile ;;\n npm) npm ci ;;\n yarn)\n if grep -q '^__metadata:' yarn.lock; then\n yarn install --immutable\n else\n yarn install --frozen-lockfile\n fi\n ;;\n bun) bun install --frozen-lockfile ;;\n *)\n echo \"::error::Unsupported base package-manager '$BASE_PACKAGE_MANAGER' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n - id: tailor-restore-head-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-build-erd-preview\n shell: bash\n env:\n APP_DIR: \"__APP_DIR__\"\n BASE_APP_DIR: ${{ needs.tailor-erd-preview-matrix.outputs['base-app-dir'] }}\n BASE_PACKAGE_MANAGER: ${{ steps.tailor-detect-base-package-manager.outputs['package-manager'] }}\n NAMESPACE: ${{ matrix.namespace }}\n run: |\n set -euo pipefail\n\n run_tailor_cli() {\n case \"__PACKAGE_MANAGER__\" in\n pnpm) pnpm exec tailor \"$@\" ;;\n npm) npx tailor \"$@\" ;;\n yarn) yarn tailor \"$@\" ;;\n bun) bunx tailor \"$@\" ;;\n *)\n echo \"::error::Unsupported package-manager '__PACKAGE_MANAGER__' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n }\n\n run_head_node() {\n case \"__PACKAGE_MANAGER__\" in\n pnpm) pnpm exec node \"$@\" ;;\n npm) node \"$@\" ;;\n yarn) yarn node \"$@\" ;;\n bun) node \"$@\" ;;\n *)\n echo \"::error::Unsupported package-manager '__PACKAGE_MANAGER__' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n }\n\n tailor_cli_bin=\"$(\n run_head_node - <<'NODE'\n const path = require(\"node:path\");\n const { createRequire } = require(\"node:module\");\n const appDir = process.env.APP_DIR || \".\";\n const githubWorkspace = process.env.GITHUB_WORKSPACE;\n if (!githubWorkspace) {\n throw new Error(\"GITHUB_WORKSPACE is required.\");\n }\n\n let lastError;\n for (const manifestPath of [\n path.join(githubWorkspace, appDir, \"package.json\"),\n path.join(githubWorkspace, \"package.json\"),\n ]) {\n try {\n const requireFromManifest = createRequire(manifestPath);\n process.stdout.write(\n path.join(\n path.dirname(requireFromManifest.resolve(\"@tailor-platform/sdk/cli\")),\n \"index.mjs\",\n ),\n );\n process.exit(0);\n } catch (error) {\n lastError = error;\n }\n }\n throw lastError || new Error(\"Failed to resolve @tailor-platform/sdk/cli.\");\n NODE\n )\"\n\n run_head_tailor_cli_bin() {\n local command_cwd=\"$1\"\n shift\n\n run_head_cli_env() {\n env TAILOR_CLI_BIN=\"$tailor_cli_bin\" TAILOR_CLI_CWD=\"$command_cwd\" \"$@\"\n }\n\n (\n cd \"$GITHUB_WORKSPACE\" || exit 1\n case \"__PACKAGE_MANAGER__\" in\n pnpm) run_head_cli_env pnpm exec node \"$head_cli_runner\" \"$@\" ;;\n npm) run_head_cli_env node \"$head_cli_runner\" \"$@\" ;;\n yarn) run_head_cli_env yarn node \"$head_cli_runner\" \"$@\" ;;\n bun) run_head_cli_env bun \"$head_cli_runner\" \"$@\" ;;\n *)\n echo \"::error::Unsupported package-manager '__PACKAGE_MANAGER__' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n )\n }\n\n run_base_tailor_cli_bin() {\n local command_cwd=\"$1\"\n shift\n\n run_head_cli_env() {\n env TAILOR_CLI_BIN=\"$tailor_cli_bin\" TAILOR_CLI_CWD=\"$command_cwd\" \"$@\"\n }\n\n (\n cd \"$command_cwd\" || exit 1\n case \"$BASE_PACKAGE_MANAGER\" in\n pnpm) run_head_cli_env pnpm exec node \"$head_cli_runner\" \"$@\" ;;\n npm) run_head_cli_env node \"$head_cli_runner\" \"$@\" ;;\n yarn) run_head_cli_env yarn node \"$head_cli_runner\" \"$@\" ;;\n bun) run_head_cli_env bun \"$head_cli_runner\" \"$@\" ;;\n *)\n echo \"::error::Unsupported base package-manager '$BASE_PACKAGE_MANAGER' (expected pnpm, npm, yarn, or bun)\"\n exit 1\n ;;\n esac\n )\n }\n\n head_output=\"$RUNNER_TEMP/tailor-erd/head\"\n base_output=\"$RUNNER_TEMP/tailor-erd/base\"\n preview_output=\"$RUNNER_TEMP/tailor-erd/preview\"\n dts_output=\"$RUNNER_TEMP/tailor-erd/dts\"\n head_cli_runner=\"$RUNNER_TEMP/tailor-erd/run-head-cli.mjs\"\n head_log=\"$RUNNER_TEMP/tailor-erd/head-$NAMESPACE.log\"\n base_log=\"$RUNNER_TEMP/tailor-erd/base-$NAMESPACE.log\"\n rm -rf \"$head_output\" \"$base_output\" \"$preview_output\" \"$dts_output\"\n mkdir -p \"$head_output\" \"$base_output\" \"$preview_output\" \"$dts_output\"\n cat > \"$head_cli_runner\" <<'NODE'\n import { pathToFileURL } from \"node:url\";\n\n const cliBin = process.env.TAILOR_CLI_BIN;\n const commandCwd = process.env.TAILOR_CLI_CWD;\n if (!cliBin || !commandCwd) {\n throw new Error(\"TAILOR_CLI_BIN and TAILOR_CLI_CWD are required.\");\n }\n\n process.chdir(commandCwd);\n process.argv = [process.argv[0], cliBin, ...process.argv.slice(2)];\n await import(pathToFileURL(cliBin).href);\n NODE\n\n head_config=\"$GITHUB_WORKSPACE/$APP_DIR/tailor.config.ts\"\n base_config=\"$GITHUB_WORKSPACE/.tailor-erd-base/$BASE_APP_DIR/tailor.config.ts\"\n head_html=\"$head_output/$NAMESPACE/dist/index.html\"\n base_html=\"$base_output/$NAMESPACE/dist/index.html\"\n preview_html=\"$preview_output/$NAMESPACE-viewer.html\"\n\n head_missing=\"false\"\n if [ ! -f \"$head_config\" ]; then\n echo \"Head ERD config not found; rendering base objects as removed.\"\n head_missing=\"true\"\n elif ! (\n cd \"$GITHUB_WORKSPACE/$APP_DIR\" || exit 1\n TAILOR_PLATFORM_SDK_DTS_PATH=\"$dts_output/head-$NAMESPACE.d.ts\" \\\n run_tailor_cli tailordb erd export --config \"$head_config\" --namespace \"$NAMESPACE\" --output \"$head_output\"\n ) >\"$head_log\" 2>&1; then\n if grep -q 'not found in local config.db' \"$head_log\"; then\n cat \"$head_log\"\n echo \"Head ERD namespace '$NAMESPACE' not found; rendering base objects as removed.\"\n head_missing=\"true\"\n else\n cat \"$head_log\"\n exit 1\n fi\n elif [ -s \"$head_log\" ]; then\n cat \"$head_log\"\n fi\n\n base_missing=\"false\"\n if [ ! -f \"$base_config\" ]; then\n echo \"Base ERD config not found; rendering current objects as added.\"\n base_missing=\"true\"\n elif ! (\n TAILOR_PLATFORM_SDK_DTS_PATH=\"$dts_output/base-$NAMESPACE.d.ts\" \\\n run_base_tailor_cli_bin \"$GITHUB_WORKSPACE/.tailor-erd-base/$BASE_APP_DIR\" tailordb erd export --config \"$base_config\" --namespace \"$NAMESPACE\" --output \"$base_output\"\n ) >\"$base_log\" 2>&1; then\n if grep -q 'not found in local config.db' \"$base_log\"; then\n cat \"$base_log\"\n echo \"Base ERD namespace '$NAMESPACE' not found; rendering current objects as added.\"\n base_missing=\"true\"\n else\n cat \"$base_log\"\n exit 1\n fi\n elif [ -s \"$base_log\" ]; then\n cat \"$base_log\"\n fi\n\n if [ \"$head_missing\" = \"true\" ] && [ \"$base_missing\" = \"true\" ]; then\n echo \"::error::ERD namespace '$NAMESPACE' was not found in head or base.\"\n exit 1\n fi\n if [ \"$head_missing\" = \"false\" ] && [ ! -f \"$head_html\" ]; then\n echo \"::error::Head ERD viewer was not generated at $head_html\"\n exit 1\n fi\n if [ \"$base_missing\" = \"false\" ] && [ ! -f \"$base_html\" ]; then\n echo \"::error::Base ERD viewer was not generated at $base_html\"\n exit 1\n fi\n\n diff_args=(--namespace \"$NAMESPACE\" --output \"$preview_html\")\n if [ \"$head_missing\" = \"false\" ]; then\n diff_args+=(--head-html \"$head_html\")\n fi\n if [ \"$base_missing\" = \"false\" ]; then\n diff_args+=(--base-html \"$base_html\")\n fi\n run_head_tailor_cli_bin \"$GITHUB_WORKSPACE\" tailordb erd diff \"${diff_args[@]}\"\n - id: tailor-upload-erd-viewer\n uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1\n with:\n name: ${{ matrix.namespace }}-viewer.html\n path: ${{ runner.temp }}/tailor-erd/preview/${{ matrix.namespace }}-viewer.html\n if-no-files-found: error\n archive: false\n retention-days: 7\n\n # __ERD_PREVIEW_JOB_END__\n # __ERD_PREVIEW_COMMENT_JOB_START__\n tailor-erd-preview-comment:\n needs: tailor-erd-preview\n if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository\n runs-on: ubuntu-latest\n timeout-minutes: 5\n permissions:\n actions: read\n pull-requests: write\n steps:\n - id: tailor-comment-erd-preview\n env:\n GH_TOKEN: ${{ github.token }}\n REPO: ${{ github.repository }}\n RUN_ID: ${{ github.run_id }}\n SERVER: ${{ github.server_url }}\n PR_NUMBER: ${{ github.event.pull_request.number }}\n BASE_REF: ${{ github.event.pull_request.base.ref }}\n HEAD_SHA: ${{ github.event.pull_request.head.sha }}\n MARKER: \"<!-- tailor-erd-preview: __WORKSPACE_NAME__ -->\"\n run: |\n set -euo pipefail\n\n current_head=$(gh api \"repos/$REPO/pulls/$PR_NUMBER\" --jq '.head.sha')\n if [ \"$current_head\" != \"$HEAD_SHA\" ]; then\n echo \"Skipping stale ERD preview comment for $HEAD_SHA; current head is $current_head.\"\n exit 0\n fi\n\n body=\"$MARKER\"$'\\n'\"### TailorDB ERD preview (__WORKSPACE_NAME__)\"$'\\n\\n'\n body+=\"Self-contained ERD viewer HTML artifacts for this pull request. Each viewer can switch between the current schema and a diff against base branch \\`$BASE_REF\\`.\"$'\\n'\n\n while IFS=$'\\t' read -r name id; do\n [ -z \"$name\" ] && continue\n if [[ \"$name\" != *-viewer.html ]]; then\n continue\n fi\n ns=${name%-viewer.html}\n label=\"$ns viewer\"\n body+=$'\\n'\"- **$label**: [$name]($SERVER/$REPO/actions/runs/$RUN_ID/artifacts/$id)\"\n done < <(gh api \"repos/$REPO/actions/runs/$RUN_ID/artifacts\" --paginate \\\n --jq '.artifacts[] | select(.name | endswith(\"-viewer.html\")) | [.name, (.id|tostring)] | @tsv' | sort)\n\n existing=$(gh api \"repos/$REPO/issues/$PR_NUMBER/comments\" --paginate \\\n --jq 'map(select(.body | contains(env.MARKER))) | .[0].id // empty')\n if [ -n \"$existing\" ]; then\n gh api --method PATCH \"repos/$REPO/issues/comments/$existing\" -f body=\"$body\" >/dev/null\n else\n gh api --method POST \"repos/$REPO/issues/$PR_NUMBER/comments\" -f body=\"$body\" >/dev/null\n fi\n\n # __ERD_PREVIEW_COMMENT_JOB_END__\n tailor-deploy:\n # __DEPLOY_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n permissions:\n contents: read\n environment: __ENVIRONMENT__\n concurrency:\n group: tailor-deploy-__WORKSPACE_NAME__\n cancel-in-progress: false\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-apply\n uses: tailor-platform/actions/deploy@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n # __SEED_DATA_START__\n - id: seed-data\n if: false\n shell: bash\n # __WORKING_DIRECTORY__\n run: |\n # Uncomment and implement to seed data on deploy.\n # Run after apply so the schema is ready.\n # Example: node scripts/seed.mjs\n true\n # __SEED_DATA_END__\n - id: slack-prereq\n if: always()\n shell: bash\n env:\n SLACK_TOKEN: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n SLACK_CHANNEL_ID: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n run: |\n if [[ -n \"$SLACK_TOKEN\" && -n \"$SLACK_CHANNEL_ID\" ]]; then\n echo \"ready=true\" >> \"$GITHUB_OUTPUT\"\n fi\n - id: tailor-notify\n if: always() && steps.slack-prereq.outputs.ready == 'true'\n uses: tailor-platform/actions/notify@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n provider: slack\n status: ${{ job.status }}\n workspace-name: __WORKSPACE_NAME__\n slack-token: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n slack-channel-id: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n # user-mapping: ${{ vars.TAILOR_SLACK_USER_MAPPING }}\n";
3177
3257
 
3178
3258
  //#endregion
3179
3259
  //#region src/cli/commands/setup/coordinate.workflow.yml
3180
- var coordinate_workflow_default = "# __HEADER__\nname: Tailor Coordinator (__WORKSPACE_NAME__)\n\non:\n # __PULL_REQUEST_START__\n pull_request:\n branches: [\"__BRANCH__\"]\n # __PULL_REQUEST_END__\n push:\n # __PUSH_BRANCHES_START__\n branches: [\"__BRANCH__\"]\n # __PUSH_BRANCHES_END__\n # __PUSH_TAGS_START__\n tags: [__TAG_PATTERN__]\n # __PUSH_TAGS_END__\n workflow_dispatch:\n inputs:\n dry-run:\n description: Preview changes without deploying\n type: boolean\n default: false\n\npermissions:\n contents: read\n\njobs:\n # __TAG_GUARD_JOB_START__\n tailor-tag-guard:\n runs-on: ubuntu-latest\n timeout-minutes: 5\n permissions:\n contents: read\n outputs:\n on-branch: ${{ steps.tailor-tag-guard.outputs.on-branch }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n fetch-depth: 0\n - id: tailor-tag-guard\n uses: tailor-platform/actions/tag-guard@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n target-branch: __BRANCH__\n # __TAG_GUARD_JOB_END__\n\n tailor-plan:\n # __PLAN_NEEDS__\n # __PLAN_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 60\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n concurrency:\n group: tailor-plan-__WORKSPACE_NAME__-${{ github.event.pull_request.number || github.run_id }}\n cancel-in-progress: true\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: ./.github/actions/tailor-setup\n # __PER_APP_PLAN_STEPS__\n\n tailor-deploy:\n # __DEPLOY_NEEDS__\n # __DEPLOY_IF__\n # __DEPLOY_ENVIRONMENT__\n runs-on: ubuntu-latest\n timeout-minutes: 60\n permissions:\n contents: read\n concurrency:\n group: tailor-deploy-__WORKSPACE_NAME__\n cancel-in-progress: false\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: ./.github/actions/tailor-setup\n # __PER_APP_DEPLOY_STEPS__\n";
3260
+ var coordinate_workflow_default = "# __HEADER__\nname: Tailor Coordinator (__WORKSPACE_NAME__)\n\non:\n # __PULL_REQUEST_START__\n pull_request:\n branches: [\"__BRANCH__\"]\n # __PULL_REQUEST_END__\n push:\n # __PUSH_BRANCHES_START__\n branches: [\"__BRANCH__\"]\n # __PUSH_BRANCHES_END__\n # __PUSH_TAGS_START__\n tags: [__TAG_PATTERN__]\n # __PUSH_TAGS_END__\n workflow_dispatch:\n inputs:\n dry-run:\n description: Preview changes without deploying\n type: boolean\n default: false\n\npermissions:\n contents: read\n\njobs:\n # __TAG_GUARD_JOB_START__\n tailor-tag-guard:\n runs-on: ubuntu-latest\n timeout-minutes: 5\n permissions:\n contents: read\n outputs:\n on-branch: ${{ steps.tailor-tag-guard.outputs.on-branch }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n fetch-depth: 0\n - id: tailor-tag-guard\n uses: tailor-platform/actions/tag-guard@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n target-branch: __BRANCH__\n # __TAG_GUARD_JOB_END__\n\n tailor-plan:\n # __PLAN_NEEDS__\n # __PLAN_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 60\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n concurrency:\n group: tailor-plan-__WORKSPACE_NAME__-${{ github.event.pull_request.number || github.run_id }}\n cancel-in-progress: true\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: ./.github/actions/tailor-setup\n # __PER_APP_PLAN_STEPS__\n\n tailor-deploy:\n # __DEPLOY_NEEDS__\n # __DEPLOY_IF__\n # __DEPLOY_ENVIRONMENT__\n runs-on: ubuntu-latest\n timeout-minutes: 60\n permissions:\n contents: read\n concurrency:\n group: tailor-deploy-__WORKSPACE_NAME__\n cancel-in-progress: false\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: ./.github/actions/tailor-setup\n # __PER_APP_DEPLOY_STEPS__\n";
3181
3261
 
3182
3262
  //#endregion
3183
3263
  //#region src/cli/commands/setup/preview.workflow.yml
3184
- var preview_workflow_default = "# __HEADER__\nname: Tailor Preview (__WORKSPACE_NAME__)\n\non:\n pull_request:\n branches: [\"__BRANCH__\"]\n # __PR_TYPES__\n # To deploy only for PRs that carry the `tailor:preview` label instead of all PRs,\n # re-run: tailor setup preview --require-preview-label\n # __PATHS__\n\npermissions:\n contents: read\n pull-requests: write\n\njobs:\n tailor-preview-deploy:\n # __DEPLOY_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n concurrency:\n group: tailor-preview-__WORKSPACE_NAME__-${{ github.event.pull_request.number }}\n cancel-in-progress: true\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-generate-check\n uses: tailor-platform/actions/generate-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n - id: tailor-preview-deploy\n uses: tailor-platform/actions/preview-deploy@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-name-prefix: __WORKSPACE_NAME__\n region: \"__REGION__\"\n organization-id: ${{ vars.TAILOR_PLATFORM_ORGANIZATION_ID }}\n folder-id: ${{ vars.TAILOR_PLATFORM_FOLDER_ID }}\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n - id: tailor-preview-comment\n if: always()\n uses: tailor-platform/actions/preview-comment@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-id: ${{ steps.tailor-preview-deploy.outputs.workspace-id }}\n workspace-name: ${{ steps.tailor-preview-deploy.outputs.workspace-name }}\n status: ${{ job.status == 'success' && 'success' || 'failure' }}\n app-url: ${{ steps.tailor-preview-deploy.outputs.app-url }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n\n tailor-preview-cleanup:\n # __CLEANUP_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 15\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-preview-cleanup\n uses: tailor-platform/actions/preview-cleanup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-name-prefix: __WORKSPACE_NAME__\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n";
3264
+ var preview_workflow_default = "# __HEADER__\nname: Tailor Preview (__WORKSPACE_NAME__)\n\non:\n pull_request:\n branches: [\"__BRANCH__\"]\n # __PR_TYPES__\n # To deploy only for PRs that carry the `tailor:preview` label instead of all PRs,\n # re-run: tailor setup preview --require-preview-label\n # __PATHS__\n\npermissions:\n contents: read\n pull-requests: write\n\njobs:\n tailor-preview-deploy:\n # __DEPLOY_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n concurrency:\n group: tailor-preview-__WORKSPACE_NAME__-${{ github.event.pull_request.number }}\n cancel-in-progress: true\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-generate-check\n uses: tailor-platform/actions/generate-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n - id: tailor-preview-deploy\n uses: tailor-platform/actions/preview-deploy@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-name-prefix: __WORKSPACE_NAME__\n region: \"__REGION__\"\n organization-id: ${{ vars.TAILOR_PLATFORM_ORGANIZATION_ID }}\n folder-id: ${{ vars.TAILOR_PLATFORM_FOLDER_ID }}\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n - id: tailor-preview-comment\n if: always()\n uses: tailor-platform/actions/preview-comment@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-id: ${{ steps.tailor-preview-deploy.outputs.workspace-id }}\n workspace-name: ${{ steps.tailor-preview-deploy.outputs.workspace-name }}\n status: ${{ job.status == 'success' && 'success' || 'failure' }}\n app-url: ${{ steps.tailor-preview-deploy.outputs.app-url }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n\n tailor-preview-cleanup:\n # __CLEANUP_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 15\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n pull-requests: write\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-preview-cleanup\n uses: tailor-platform/actions/preview-cleanup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-name-prefix: __WORKSPACE_NAME__\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n github-token: ${{ secrets.GITHUB_TOKEN }}\n";
3185
3265
 
3186
3266
  //#endregion
3187
3267
  //#region src/cli/commands/setup/tag.workflow.yml
3188
- var tag_workflow_default = "# __HEADER__\nname: Tailor (__WORKSPACE_NAME__)\n\non:\n push:\n tags: [\"__TAG_PATTERN__\"]\n workflow_dispatch:\n inputs:\n dry-run:\n description: Preview changes without deploying\n type: boolean\n default: false\n\npermissions:\n contents: read\n\njobs:\n # __TAG_GUARD_JOB_START__\n tailor-tag-guard:\n runs-on: ubuntu-latest\n timeout-minutes: 10\n permissions:\n contents: read\n outputs:\n on-branch: ${{ steps.tailor-tag-guard.outputs.on-branch }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n fetch-depth: 0\n - id: tailor-tag-guard\n uses: tailor-platform/actions/tag-guard@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n target-branch: \"__BRANCH__\"\n # __TAG_GUARD_JOB_END__\n tailor-plan:\n # __PLAN_NEEDS__\n # __PLAN_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-generate-check\n uses: tailor-platform/actions/generate-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_START__\n - id: tailor-seed-validate\n uses: tailor-platform/actions/seed-validate@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_END__\n - id: tailor-drift-check\n uses: tailor-platform/actions/drift-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __MIGRATION_DRIFT_CHECK_START__\n - id: tailor-migration-drift-check\n uses: tailor-platform/actions/migration-drift-check@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __MIGRATION_DRIFT_CHECK_END__\n - id: tailor-plan\n uses: tailor-platform/actions/plan@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n label: __WORKSPACE_NAME__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n\n tailor-deploy:\n needs: tailor-plan\n if: ${{ !(github.event_name == 'workflow_dispatch' && inputs['dry-run']) }}\n environment: __ENVIRONMENT__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n permissions:\n contents: read\n concurrency:\n group: tailor-deploy-__WORKSPACE_NAME__\n cancel-in-progress: false\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-apply\n uses: tailor-platform/actions/deploy@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n # __SEED_DATA_START__\n - id: seed-data\n if: false\n shell: bash\n # __WORKING_DIRECTORY__\n run: |\n # Uncomment and implement to seed data on deploy.\n # Run after apply so the schema is ready.\n # Example: node scripts/seed.mjs\n true\n # __SEED_DATA_END__\n - id: slack-prereq\n if: always()\n shell: bash\n env:\n SLACK_TOKEN: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n SLACK_CHANNEL_ID: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n run: |\n if [[ -n \"$SLACK_TOKEN\" && -n \"$SLACK_CHANNEL_ID\" ]]; then\n echo \"ready=true\" >> \"$GITHUB_OUTPUT\"\n fi\n - id: tailor-notify\n if: always() && steps.slack-prereq.outputs.ready == 'true'\n uses: tailor-platform/actions/notify@e74173d4bdd931d036ad359cf5f7729fc6aa7067 # v1.5.1\n with:\n provider: slack\n status: ${{ job.status }}\n workspace-name: __WORKSPACE_NAME__\n slack-token: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n slack-channel-id: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n # user-mapping: ${{ vars.TAILOR_SLACK_USER_MAPPING }}\n";
3268
+ var tag_workflow_default = "# __HEADER__\nname: Tailor (__WORKSPACE_NAME__)\n\non:\n push:\n tags: [\"__TAG_PATTERN__\"]\n workflow_dispatch:\n inputs:\n dry-run:\n description: Preview changes without deploying\n type: boolean\n default: false\n\npermissions:\n contents: read\n\njobs:\n # __TAG_GUARD_JOB_START__\n tailor-tag-guard:\n runs-on: ubuntu-latest\n timeout-minutes: 10\n permissions:\n contents: read\n outputs:\n on-branch: ${{ steps.tailor-tag-guard.outputs.on-branch }}\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n with:\n fetch-depth: 0\n - id: tailor-tag-guard\n uses: tailor-platform/actions/tag-guard@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n target-branch: \"__BRANCH__\"\n # __TAG_GUARD_JOB_END__\n tailor-plan:\n # __PLAN_NEEDS__\n # __PLAN_IF__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n environment: __ENVIRONMENT__\n permissions:\n contents: read\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-generate-check\n uses: tailor-platform/actions/generate-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_START__\n - id: tailor-seed-validate\n uses: tailor-platform/actions/seed-validate@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __SEED_VALIDATE_END__\n - id: tailor-drift-check\n uses: tailor-platform/actions/drift-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __MIGRATION_DRIFT_CHECK_START__\n - id: tailor-migration-drift-check\n uses: tailor-platform/actions/migration-drift-check@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n # __MIGRATION_DRIFT_CHECK_END__\n - id: tailor-plan\n uses: tailor-platform/actions/plan@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n label: __WORKSPACE_NAME__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n\n tailor-deploy:\n needs: tailor-plan\n if: ${{ !(github.event_name == 'workflow_dispatch' && inputs['dry-run']) }}\n environment: __ENVIRONMENT__\n runs-on: ubuntu-latest\n timeout-minutes: 30\n permissions:\n contents: read\n concurrency:\n group: tailor-deploy-__WORKSPACE_NAME__\n cancel-in-progress: false\n steps:\n - id: tailor-checkout\n uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0\n - id: tailor-setup\n uses: tailor-platform/actions/setup@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-install\n uses: tailor-platform/actions/install@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n package-manager: __PACKAGE_MANAGER__\n - id: tailor-apply\n uses: tailor-platform/actions/deploy@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n workspace-id: ${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}\n package-manager: __PACKAGE_MANAGER__\n # __WORKING_DIRECTORY__\n platform-client-id: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}\n platform-client-secret: ${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}\n # __SEED_DATA_START__\n - id: seed-data\n if: false\n shell: bash\n # __WORKING_DIRECTORY__\n run: |\n # Uncomment and implement to seed data on deploy.\n # Run after apply so the schema is ready.\n # Example: node scripts/seed.mjs\n true\n # __SEED_DATA_END__\n - id: slack-prereq\n if: always()\n shell: bash\n env:\n SLACK_TOKEN: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n SLACK_CHANNEL_ID: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n run: |\n if [[ -n \"$SLACK_TOKEN\" && -n \"$SLACK_CHANNEL_ID\" ]]; then\n echo \"ready=true\" >> \"$GITHUB_OUTPUT\"\n fi\n - id: tailor-notify\n if: always() && steps.slack-prereq.outputs.ready == 'true'\n uses: tailor-platform/actions/notify@a3c3032e14277e81039eb26ae1a425adb22eb532 # v1.7.0\n with:\n provider: slack\n status: ${{ job.status }}\n workspace-name: __WORKSPACE_NAME__\n slack-token: ${{ secrets.TAILOR_SLACK_BOT_TOKEN }}\n slack-channel-id: ${{ vars.TAILOR_SLACK_CHANNEL_ID }}\n # user-mapping: ${{ vars.TAILOR_SLACK_USER_MAPPING }}\n";
3189
3269
 
3190
3270
  //#endregion
3191
3271
  //#region src/cli/commands/setup/templates.ts
@@ -3355,7 +3435,8 @@ function renderActionWorkflow(params) {
3355
3435
  generatedIds: ["tailor-apply", "tailor-notify"]
3356
3436
  };
3357
3437
  }
3358
- const ACTIONS_SHA = "e74173d4bdd931d036ad359cf5f7729fc6aa7067";
3438
+ const ACTIONS_SHA = "a3c3032e14277e81039eb26ae1a425adb22eb532";
3439
+ const ACTIONS_VERSION = "v1.7.0";
3359
3440
  /**
3360
3441
  * Render the coordinator workflow that orchestrates per-app composite actions.
3361
3442
  *
@@ -3366,7 +3447,7 @@ const ACTIONS_SHA = "e74173d4bdd931d036ad359cf5f7729fc6aa7067";
3366
3447
  * @returns Rendered YAML and the list of managed job/step ids
3367
3448
  */
3368
3449
  function renderCoordinateWorkflow(params) {
3369
- const { coordinatorName, kind, apps, environment, packageManager } = params;
3450
+ const { coordinatorName, kind, actionGroups, environment, packageManager } = params;
3370
3451
  const isTag = kind === "tag";
3371
3452
  const branch = params.branch;
3372
3453
  const tagPattern = params.tagPattern ?? "v*";
@@ -3397,45 +3478,108 @@ function renderCoordinateWorkflow(params) {
3397
3478
  }
3398
3479
  const driftCheckStep = [
3399
3480
  `- id: tailor-drift-check`,
3400
- ` uses: tailor-platform/actions/drift-check@${ACTIONS_SHA} # v1.5.1`,
3481
+ ` uses: tailor-platform/actions/drift-check@${ACTIONS_SHA} # ${ACTIONS_VERSION}`,
3401
3482
  ` with:`,
3402
3483
  ` package-manager: ${packageManager}`
3403
3484
  ].join("\n");
3404
- const perAppPlanSteps = apps.flatMap((app) => {
3485
+ const configPath = (app) => app.dir === "." ? "tailor.config.ts" : `${app.dir}/tailor.config.ts`;
3486
+ const groupConfigPath = (group) => group.apps.map(configPath).join(",");
3487
+ const firstApp = (group) => {
3488
+ const [app] = group.apps;
3489
+ if (!app) throw new Error("Coordinate action groups must contain at least one app.");
3490
+ return app;
3491
+ };
3492
+ const singleAppPlanStep = (group, app) => {
3405
3493
  const wd = app.dir !== "." ? app.dir : void 0;
3406
3494
  const wdLine = wd ? `\n working-directory: ${wd}` : "";
3407
3495
  return [
3408
- `- id: tailor-generate-check-${app.name}`,
3409
- ` uses: tailor-platform/actions/generate-check@${ACTIONS_SHA} # v1.5.1`,
3410
- ` with:`,
3411
- ` package-manager: ${packageManager}${wdLine}`,
3412
- `- id: tailor-plan-${app.name}`,
3496
+ `- id: tailor-plan-${group.id}`,
3413
3497
  ` if: github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork`,
3414
- ` uses: tailor-platform/actions/plan@${ACTIONS_SHA} # v1.5.1`,
3498
+ ` uses: tailor-platform/actions/plan@${ACTIONS_SHA} # ${ACTIONS_VERSION}`,
3415
3499
  ` with:`,
3416
3500
  ` workspace-id: \${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}`,
3417
3501
  ` package-manager: ${packageManager}${wdLine}`,
3418
- ` label: ${coordinatorName}/${app.name}`,
3502
+ ` label: ${coordinatorName}/${group.id}`,
3419
3503
  ` platform-client-id: \${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}`,
3420
3504
  ` platform-client-secret: \${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}`,
3421
3505
  ` github-token: \${{ secrets.GITHUB_TOKEN }}`
3422
3506
  ];
3507
+ };
3508
+ const multiConfigPlanStep = (group) => [
3509
+ `- id: tailor-plan-${group.id}`,
3510
+ ` if: github.event_name != 'pull_request' || !github.event.pull_request.head.repo.fork`,
3511
+ ` uses: tailor-platform/actions/plan@${ACTIONS_SHA} # ${ACTIONS_VERSION}`,
3512
+ ` env:`,
3513
+ ` TAILOR_PLATFORM_SDK_CONFIG_PATH: ${groupConfigPath(group)}`,
3514
+ ` with:`,
3515
+ ` workspace-id: \${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}`,
3516
+ ` package-manager: ${packageManager}`,
3517
+ ` label: ${coordinatorName}/${group.id}`,
3518
+ ` platform-client-id: \${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}`,
3519
+ ` platform-client-secret: \${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}`,
3520
+ ` github-token: \${{ secrets.GITHUB_TOKEN }}`
3521
+ ];
3522
+ const perAppPlanSteps = actionGroups.flatMap((group) => {
3523
+ const generateCheckSteps = group.apps.flatMap((app) => {
3524
+ const wd = app.dir !== "." ? app.dir : void 0;
3525
+ const wdLine = wd ? `\n working-directory: ${wd}` : "";
3526
+ return [
3527
+ `- id: tailor-generate-check-${app.name}`,
3528
+ ` uses: tailor-platform/actions/generate-check@${ACTIONS_SHA} # ${ACTIONS_VERSION}`,
3529
+ ` with:`,
3530
+ ` package-manager: ${packageManager}${wdLine}`
3531
+ ];
3532
+ });
3533
+ const planStep = group.apps.length === 1 ? singleAppPlanStep(group, firstApp(group)) : multiConfigPlanStep(group);
3534
+ return [...generateCheckSteps, ...planStep];
3423
3535
  }).join("\n");
3424
3536
  out = line(out, "PER_APP_PLAN_STEPS", `${driftCheckStep}\n${perAppPlanSteps}`);
3425
- const deploySteps = apps.flatMap((app) => [
3426
- `- id: tailor-deploy-${app.name}`,
3537
+ const singleAppDeployStep = (group, app) => [
3538
+ `- id: tailor-deploy-${group.id}`,
3539
+ ` uses: ./.github/actions/tailor-${app.name}`,
3540
+ ` with:`,
3541
+ ` workspace-id: \${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}`,
3542
+ ` name: ${app.name}`,
3543
+ ` working-directory: ${app.dir}`,
3544
+ ` package-manager: ${packageManager}`,
3545
+ ` platform-client-id: \${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}`,
3546
+ ` platform-client-secret: \${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}`,
3547
+ ` slack-token: \${{ secrets.TAILOR_SLACK_BOT_TOKEN }}`,
3548
+ ` slack-channel-id: \${{ vars.TAILOR_SLACK_CHANNEL_ID }}`,
3549
+ ` # editable: api-url:`
3550
+ ];
3551
+ const buildSiteStep = (app) => [
3552
+ `- id: tailor-build-site-${app.name}`,
3427
3553
  ` uses: ./.github/actions/tailor-${app.name}`,
3428
3554
  ` with:`,
3429
3555
  ` workspace-id: \${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}`,
3430
3556
  ` name: ${app.name}`,
3431
3557
  ` working-directory: ${app.dir}`,
3558
+ ` deploy: "false"`,
3559
+ ` package-manager: ${packageManager}`,
3560
+ ` platform-client-id: \${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}`,
3561
+ ` platform-client-secret: \${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}`,
3562
+ ` slack-token: \${{ secrets.TAILOR_SLACK_BOT_TOKEN }}`,
3563
+ ` slack-channel-id: \${{ vars.TAILOR_SLACK_CHANNEL_ID }}`
3564
+ ];
3565
+ const multiConfigDeployStep = (group) => [
3566
+ ...group.apps.filter((app) => app.hasStaticWebsites).flatMap(buildSiteStep),
3567
+ `- id: tailor-deploy-${group.id}`,
3568
+ ` uses: ./.github/actions/tailor-${firstApp(group).name}`,
3569
+ ` with:`,
3570
+ ` workspace-id: \${{ vars.TAILOR_PLATFORM_WORKSPACE_ID }}`,
3571
+ ` name: ${coordinatorName}/${group.id}`,
3572
+ ` working-directory: .`,
3573
+ ` config: ${groupConfigPath(group)}`,
3574
+ ` build-site: "false"`,
3432
3575
  ` package-manager: ${packageManager}`,
3433
3576
  ` platform-client-id: \${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID }}`,
3434
3577
  ` platform-client-secret: \${{ secrets.TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET }}`,
3435
3578
  ` slack-token: \${{ secrets.TAILOR_SLACK_BOT_TOKEN }}`,
3436
3579
  ` slack-channel-id: \${{ vars.TAILOR_SLACK_CHANNEL_ID }}`,
3437
3580
  ` # editable: api-url:`
3438
- ]).join("\n");
3581
+ ];
3582
+ const deploySteps = actionGroups.flatMap((group) => group.apps.length === 1 ? singleAppDeployStep(group, firstApp(group)) : multiConfigDeployStep(group)).join("\n");
3439
3583
  out = line(out, "PER_APP_DEPLOY_STEPS", deploySteps);
3440
3584
  out = out.replaceAll("__WORKSPACE_NAME__", () => coordinatorName);
3441
3585
  out = out.replaceAll("__ENVIRONMENT__", () => environment);
@@ -3444,9 +3588,15 @@ function renderCoordinateWorkflow(params) {
3444
3588
  const generatedIds = [];
3445
3589
  if (isTag && branch !== void 0) generatedIds.push("tailor-tag-guard", "tailor-tag-guard/tailor-checkout", "tailor-tag-guard/tailor-tag-guard");
3446
3590
  generatedIds.push("tailor-plan", "tailor-plan/tailor-checkout", "tailor-plan/tailor-setup", "tailor-plan/tailor-drift-check");
3447
- for (const app of apps) generatedIds.push(`tailor-plan/tailor-generate-check-${app.name}`, `tailor-plan/tailor-plan-${app.name}`);
3591
+ for (const group of actionGroups) {
3592
+ for (const app of group.apps) generatedIds.push(`tailor-plan/tailor-generate-check-${app.name}`);
3593
+ generatedIds.push(`tailor-plan/tailor-plan-${group.id}`);
3594
+ }
3448
3595
  generatedIds.push("tailor-deploy", "tailor-deploy/tailor-checkout", "tailor-deploy/tailor-setup");
3449
- for (const app of apps) generatedIds.push(`tailor-deploy/tailor-deploy-${app.name}`);
3596
+ for (const group of actionGroups) {
3597
+ for (const app of group.apps) if (group.apps.length > 1 && app.hasStaticWebsites) generatedIds.push(`tailor-deploy/tailor-build-site-${app.name}`);
3598
+ generatedIds.push(`tailor-deploy/tailor-deploy-${group.id}`);
3599
+ }
3450
3600
  return {
3451
3601
  content: out,
3452
3602
  generatedIds
@@ -3470,11 +3620,11 @@ function renderTailorSetupAction(params) {
3470
3620
  `runs:`,
3471
3621
  ` using: composite`,
3472
3622
  ` steps:`,
3473
- ` - uses: tailor-platform/actions/setup@${ACTIONS_SHA} # v1.5.1`,
3623
+ ` - uses: tailor-platform/actions/setup@${ACTIONS_SHA} # ${ACTIONS_VERSION}`,
3474
3624
  ` with:`,
3475
3625
  ` package-manager: ${packageManager}`,
3476
3626
  ` # Add custom steps here (e.g. private registry authentication)`,
3477
- ` - uses: tailor-platform/actions/install@${ACTIONS_SHA} # v1.5.1`,
3627
+ ` - uses: tailor-platform/actions/install@${ACTIONS_SHA} # ${ACTIONS_VERSION}`,
3478
3628
  ` with:`,
3479
3629
  ` package-manager: ${packageManager}`,
3480
3630
  ` # editable: install-command:`,
@@ -3484,6 +3634,25 @@ function renderTailorSetupAction(params) {
3484
3634
 
3485
3635
  //#endregion
3486
3636
  //#region src/cli/commands/setup/generate.ts
3637
+ function actionName(input) {
3638
+ return input.startsWith("tailor-") ? input.slice(7) : input;
3639
+ }
3640
+ function splitActionGroup(input) {
3641
+ const names = input.split(",").map((entry) => actionName(entry.trim()));
3642
+ if (names.some((name) => name.length === 0)) throw new Error("--action must contain one or more non-empty action names.");
3643
+ return names;
3644
+ }
3645
+ function uniqueGroupId(names, usedIds) {
3646
+ const base = names.join("-");
3647
+ let id = base;
3648
+ let suffix = 2;
3649
+ while (usedIds.has(id)) {
3650
+ id = `${base}-${suffix}`;
3651
+ suffix += 1;
3652
+ }
3653
+ usedIds.add(id);
3654
+ return id;
3655
+ }
3487
3656
  async function defaultLoadConfigName(configPath) {
3488
3657
  const { config } = await loadConfig(configPath);
3489
3658
  return config.name;
@@ -3674,7 +3843,7 @@ async function resolve$1(options) {
3674
3843
  configPath
3675
3844
  };
3676
3845
  }
3677
- const BUILD_SITE_RUN_RE = /([ \t]*- id: build-site\n[ \t]+shell: bash\n[ \t]+run: \|)([\s\S]*?)(\n[ \t]*- |\n*$)/;
3846
+ const BUILD_SITE_RUN_RE = /([ \t]*- id: build-site\n(?:[ \t]+if: [^\n]+\n)?[ \t]+shell: bash\n[ \t]+run: \|)([\s\S]*?)(\n[ \t]*- |\n*$)/;
3678
3847
  /**
3679
3848
  * Strip the mutable run: body of the build-site step before hashing.
3680
3849
  * When hasStaticWebsites is true the step is present; users are expected to
@@ -3816,7 +3985,7 @@ async function setupTarget(options) {
3816
3985
  kind: resolved.kind,
3817
3986
  workspaceName: resolved.workspaceName,
3818
3987
  file: resolved.file,
3819
- templateVersion: 6,
3988
+ templateVersion: 7,
3820
3989
  inputs: resolved.inputs,
3821
3990
  generatedIds: resolved.render.generatedIds,
3822
3991
  ejectedIds: existing?.ejectedIds ?? [],
@@ -3874,23 +4043,33 @@ async function setupCoordinate(options) {
3874
4043
  const packageManager = detectPackageManager(outputDir);
3875
4044
  const lock = readLock(outputDir);
3876
4045
  if (!lock) throw new Error(".github/tailor.lock not found. Run `tailor setup action --name <name>` for each app before running setup coordinate.");
4046
+ const actionTargets = new Map(lock.targets.filter((t) => t.kind === "action").map((target) => [target.workspaceName, target]));
3877
4047
  const seenNames = /* @__PURE__ */ new Set();
3878
- const apps = actions.map((actionName) => {
3879
- const name = actionName.startsWith("tailor-") ? actionName.slice(7) : actionName;
3880
- if (seenNames.has(name)) throw new Error(`Duplicate --action "${name}". Each composite action can only appear once in a coordinator.`);
3881
- seenNames.add(name);
3882
- const entry = lock.targets.find((t) => t.kind === "action" && t.workspaceName === name);
3883
- if (!entry) throw new Error(`Action target "${name}" not found in .github/tailor.lock. Run \`tailor setup action --name ${name}\` first.`);
3884
- validateDir(entry.inputs.dir);
4048
+ const usedGroupIds = /* @__PURE__ */ new Set();
4049
+ const actionGroups = actions.map((actionGroup) => {
4050
+ const names = splitActionGroup(actionGroup);
4051
+ const apps = names.map((name) => {
4052
+ if (seenNames.has(name)) throw new Error(`Duplicate --action "${name}". Each composite action can only appear once in a coordinator.`);
4053
+ seenNames.add(name);
4054
+ const entry = actionTargets.get(name);
4055
+ if (!entry) throw new Error(`Action target "${name}" not found in .github/tailor.lock. Run \`tailor setup action --name ${name}\` first.`);
4056
+ if (names.length > 1 && entry.templateVersion < 7) throw new Error(`Action target "${name}" was generated with an older setup template. Run \`tailor setup action --name ${name} --force\` before grouping it in setup coordinate.`);
4057
+ validateDir(entry.inputs.dir);
4058
+ return {
4059
+ name,
4060
+ dir: entry.inputs.dir,
4061
+ hasStaticWebsites: entry.inputs.hasStaticWebsites
4062
+ };
4063
+ });
3885
4064
  return {
3886
- name,
3887
- dir: entry.inputs.dir
4065
+ id: uniqueGroupId(names, usedGroupIds),
4066
+ apps
3888
4067
  };
3889
4068
  });
3890
4069
  const render = renderCoordinateWorkflow({
3891
4070
  coordinatorName,
3892
4071
  kind: coordinateKind,
3893
- apps,
4072
+ actionGroups,
3894
4073
  branch: branch ?? void 0,
3895
4074
  tagPattern: coordinateKind === "tag" ? tagPattern : void 0,
3896
4075
  environment,
@@ -3926,7 +4105,7 @@ async function setupCoordinate(options) {
3926
4105
  kind: "coordinate",
3927
4106
  workspaceName: coordinatorName,
3928
4107
  file,
3929
- templateVersion: 6,
4108
+ templateVersion: 7,
3930
4109
  inputs: {
3931
4110
  branch,
3932
4111
  branchAutoDetected: coordinateKind === "branch" ? branchAutoDetected : branch !== null ? false : void 0,
@@ -3934,7 +4113,7 @@ async function setupCoordinate(options) {
3934
4113
  environment,
3935
4114
  dir: ".",
3936
4115
  packageManager,
3937
- actionDirs: apps.map((a) => a.dir)
4116
+ actionDirs: actionGroups.flatMap((group) => group.apps.map((a) => a.dir))
3938
4117
  },
3939
4118
  generatedIds: render.generatedIds,
3940
4119
  ejectedIds: existing?.ejectedIds ?? [],
@@ -3958,8 +4137,8 @@ async function setupCoordinate(options) {
3958
4137
  logger.log(` gh secret set TAILOR_PLATFORM_MACHINE_USER_CLIENT_ID --env ${environment}`);
3959
4138
  logger.log(` gh secret set TAILOR_PLATFORM_MACHINE_USER_CLIENT_SECRET --env ${environment}`);
3960
4139
  logger.newline();
3961
- logger.log(`2. Provision each workspace and set TAILOR_PLATFORM_WORKSPACE_ID on the "${environment}" environment:`);
3962
- logger.log(" tailor workspace create # one per app; copy the id");
4140
+ logger.log(`2. Provision the target workspace and set TAILOR_PLATFORM_WORKSPACE_ID on the "${environment}" environment:`);
4141
+ logger.log(" tailor workspace create # if it does not exist yet; copy the id");
3963
4142
  logger.log(` gh variable set TAILOR_PLATFORM_WORKSPACE_ID --env ${environment}`);
3964
4143
  logger.newline();
3965
4144
  logger.log("3. Commit the generated files:");
@@ -4114,7 +4293,7 @@ async function checkGitHub(options) {
4114
4293
  currentHash,
4115
4294
  configExists,
4116
4295
  defaultBranch,
4117
- templateVersion: 6,
4296
+ templateVersion: 7,
4118
4297
  erdNamespaces,
4119
4298
  hasMigrations,
4120
4299
  hasSeeds,
@@ -4152,7 +4331,7 @@ function resolveMatch(outputDir, targets, input) {
4152
4331
  }
4153
4332
  function warnCoordinatorReferences(allTargets, deletedKeys, match) {
4154
4333
  if (match.target.kind !== "action") return;
4155
- for (const coordinator of allTargets) if (coordinator.kind === "coordinate" && coordinator.inputs.actionDirs?.includes(match.target.inputs.dir) && !deletedKeys.has(targetKey(coordinator))) logger.warn(`Coordinator "${coordinator.workspaceName}" still references this action's directory (${match.target.inputs.dir}). Re-run \`tailor-sdk setup coordinate\` without --action ${match.target.workspaceName} to remove it there too.`);
4334
+ for (const coordinator of allTargets) if (coordinator.kind === "coordinate" && coordinator.inputs.actionDirs?.includes(match.target.inputs.dir) && !deletedKeys.has(targetKey(coordinator))) logger.warn(`Coordinator "${coordinator.workspaceName}" still references this action's directory (${match.target.inputs.dir}). Remove \`${match.target.workspaceName}\` from the relevant \`--action\` value and re-run \`tailor-sdk setup coordinate\` to update it.`);
4156
4335
  }
4157
4336
  /**
4158
4337
  * Delete managed workflow/action files and their `.github/tailor-sdk.lock` entries.
@@ -4220,7 +4399,7 @@ const coordinateCommand = defineAppCommand({
4220
4399
  alias: "n",
4221
4400
  description: "Coordinator name (used in the generated workflow file name and job names)"
4222
4401
  }),
4223
- action: arg(z.array(z.string().min(1)).min(1), { description: "Composite action to include (can be specified multiple times). tailor- prefix optional." }),
4402
+ action: arg(z.array(z.string().min(1)).min(1), { description: "Composite action to include. Repeat for separate deploy steps, or use commas to deploy actions as one multi-config group. tailor- prefix optional." }),
4224
4403
  branch: arg(z.string().min(1).optional(), { description: "Branch target: deploy trigger branch (defaults to the detected default branch)" }),
4225
4404
  tag: arg(z.boolean().default(false), { description: "Generate a tag target coordinator" }),
4226
4405
  environment: arg(z.string().min(1).optional(), { description: "GitHub Environment for the plan/deploy jobs" }),
@@ -6327,7 +6506,7 @@ async function fetchRemoteTypes(client, workspaceId, namespace) {
6327
6506
  async function assertMigrationsReproduceLocalTypes(loaded, target) {
6328
6507
  const { config, plugins } = loaded;
6329
6508
  const pluginManager = plugins.length > 0 ? new PluginManager(plugins) : void 0;
6330
- const { defineApplication, generatePluginFilesIfNeeded } = await import("../application-D2hSK1ZL.mjs");
6509
+ const { defineApplication, generatePluginFilesIfNeeded } = await import("../application-CUkjzfij.mjs");
6331
6510
  const application = defineApplication({
6332
6511
  config,
6333
6512
  pluginManager
@@ -6339,7 +6518,7 @@ async function assertMigrationsReproduceLocalTypes(loaded, target) {
6339
6518
  await service.processNamespacePlugins();
6340
6519
  }
6341
6520
  const pluginExecutorFiles = generatePluginFilesIfNeeded(pluginManager, application.tailorDBServices, config.path);
6342
- const executorService = application.executorService ?? (pluginExecutorFiles.length > 0 ? (await import("../service-CkIwEctX.mjs")).createExecutorService({ config: { files: [] } }) : void 0);
6521
+ const executorService = application.executorService ?? (pluginExecutorFiles.length > 0 ? (await import("../service-BT0GPd01.mjs")).createExecutorService({ config: { files: [] } }) : void 0);
6343
6522
  await executorService?.loadExecutors();
6344
6523
  if (pluginExecutorFiles.length > 0) await executorService?.loadPluginExecutorFiles([...pluginExecutorFiles]);
6345
6524
  const executorUsedTypes = /* @__PURE__ */ new Set();
@@ -7024,37 +7203,22 @@ const packageJson = await readPackageJson();
7024
7203
  const cliName = Object.keys(packageJson.bin ?? {})[0] || "tailor";
7025
7204
  const packageName = packageJson.name ?? "@tailor-platform/sdk";
7026
7205
  const bundledSkillsDir = resolve(dirname(await resolvePackageJSON(import.meta.url)), "agent-skills");
7027
- function replaceCommandArgs(command, removals = []) {
7028
- const args = command.args;
7029
- if (!args?.shape) return command;
7030
- const shape = { ...args.shape };
7031
- for (const name of removals) delete shape[name];
7032
- return {
7033
- ...command,
7034
- args: z.strictObject({ ...shape })
7035
- };
7036
- }
7037
- function removeCommandAliases(command) {
7038
- const next = { ...command };
7039
- delete next.aliases;
7040
- return next;
7041
- }
7042
7206
  function alignSkillCommand(command) {
7043
7207
  const subCommands = command.subCommands ?? {};
7044
7208
  const add = {
7045
- ...removeCommandAliases(replaceCommandArgs(subCommands.add, ["verbose"])),
7209
+ ...subCommands.add,
7046
7210
  description: "Install Tailor SDK agent skills."
7047
7211
  };
7048
7212
  const list = {
7049
- ...replaceCommandArgs(subCommands.list, ["json"]),
7213
+ ...subCommands.list,
7050
7214
  description: "List Tailor SDK agent skills."
7051
7215
  };
7052
7216
  const remove = {
7053
- ...removeCommandAliases(replaceCommandArgs(subCommands.remove)),
7217
+ ...subCommands.remove,
7054
7218
  description: "Remove installed Tailor SDK agent skills."
7055
7219
  };
7056
7220
  const sync = {
7057
- ...replaceCommandArgs(subCommands.sync, ["verbose"]),
7221
+ ...subCommands.sync,
7058
7222
  description: "Remove and reinstall Tailor SDK agent skills."
7059
7223
  };
7060
7224
  return {
@@ -7112,14 +7276,19 @@ Run \`${cliName} plugin list\` to see which plugins are installed and where they
7112
7276
  sourceDir: bundledSkillsDir,
7113
7277
  package: packageName,
7114
7278
  mode: "copy",
7115
- descriptionAppend: false
7279
+ descriptionAppend: false,
7280
+ globalArgs: z.object(commonArgs),
7281
+ commandMap: {
7282
+ add: ["add"],
7283
+ remove: ["remove"]
7284
+ },
7285
+ unknownKeys: "strict"
7116
7286
  });
7117
- const commandWithSkillsSubCommands = commandWithSkills.subCommands ?? {};
7118
7287
  const mainCommand = withCompletionCommand({
7119
7288
  ...commandWithSkills,
7120
7289
  subCommands: {
7121
- ...commandWithSkillsSubCommands,
7122
- skills: alignSkillCommand(commandWithSkillsSubCommands.skills)
7290
+ ...commandWithSkills.subCommands,
7291
+ skills: alignSkillCommand(commandWithSkills.subCommands.skills)
7123
7292
  }
7124
7293
  });
7125
7294
  runMain(mainCommand, {