static-shards.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. /** Static-gate shard definitions for GitHub Actions. */
  2. /** A static CI lane identified by the gate IDs it owns. */
  3. export interface StaticShard {
  4. /** Stable lane identifier passed through `DSH_STATIC_SHARD`. */
  5. name: string
  6. /** Gate IDs selected from the static gate inventory. */
  7. gateIds: readonly string[]
  8. }
  9. /** Exhaustive, non-overlapping ownership of static CI gates. */
  10. export const staticShards = [
  11. {
  12. name: 'foundation',
  13. gateIds: [
  14. 'runtime-closure',
  15. 'constraints',
  16. 'package-invariants',
  17. 'cordis-config',
  18. 'module-graph',
  19. 'knip',
  20. ],
  21. },
  22. {
  23. name: 'api-contracts',
  24. gateIds: ['build', 'doc-typecheck', 'cordis-api', 'export-jsdoc', 'scoped-events', 'type-equivalence'],
  25. },
  26. {
  27. name: 'catalogs',
  28. gateIds: ['cordis-catalog', 'tool-catalog', 'config-catalog', 'persistence-catalog', 'doc-graphs'],
  29. },
  30. {
  31. name: 'prose',
  32. gateIds: [
  33. 'markdown-wrap',
  34. 'markdown-links',
  35. 'doc-refs',
  36. 'package-paths',
  37. 'package-readme-model-experience',
  38. 'mermaid',
  39. 'agent-note-classification',
  40. 'agent-note-format',
  41. 'translation-prompt',
  42. 'translation-pairing',
  43. 'doc-budgets',
  44. 'package-readme-limitations',
  45. ],
  46. },
  47. { name: 'site-projection', gateIds: ['docs-site-projection'] },
  48. { name: 'site-build', gateIds: ['docs-site-build'] },
  49. ] as const satisfies readonly StaticShard[]
  50. /**
  51. * Validate the complete gate partition and optionally select one lane.
  52. *
  53. * @param gates Complete static gate inventory.
  54. * @param name Optional stable shard name.
  55. * @returns All gates when no shard is requested, otherwise the selected lane.
  56. */
  57. export function selectStaticGates<T extends { id: string }>(gates: readonly T[], name?: string): T[] {
  58. const gateIds = gates.map(gate => gate.id)
  59. const assignedIds = staticShards.flatMap(shard => shard.gateIds)
  60. const uniqueGateIds = new Set<string>(gateIds)
  61. const uniqueAssignedIds = new Set<string>(assignedIds)
  62. if (uniqueGateIds.size !== gateIds.length) throw new Error('run-gates: static gate IDs must be unique.')
  63. if (uniqueAssignedIds.size !== assignedIds.length) throw new Error('run-gates: static shard gate IDs must be unique.')
  64. if (gateIds.length !== assignedIds.length
  65. || gateIds.some(id => !uniqueAssignedIds.has(id))
  66. || assignedIds.some(id => !uniqueGateIds.has(id))) {
  67. throw new Error('run-gates: static shards must assign every static gate exactly once.')
  68. }
  69. if (name === undefined || name === '') return [...gates]
  70. const shard = staticShards.find(candidate => candidate.name === name)
  71. if (shard === undefined) throw new Error(`run-gates: unknown DSH_STATIC_SHARD ${JSON.stringify(name)}.`)
  72. const selectedIds = new Set<string>(shard.gateIds)
  73. return gates.filter(gate => selectedIds.has(gate.id))
  74. }