check-workspace-constraints.spec.ts 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. /** Experimental-package publication and dependency constraints. */
  2. import { describe, expect, it } from 'vitest'
  3. import {
  4. checkDshFamilyVersion,
  5. checkExperimentalDependencyIsolation,
  6. checkExperimentalManifest,
  7. expectedDshPackageFiles,
  8. type WorkspaceManifest,
  9. } from './check-workspace-constraints.ts'
  10. const experimental: WorkspaceManifest = {
  11. dir: 'packages/experimental/prototype',
  12. manifest: { name: '@deepseek-ai/dsh-experimental-prototype', private: true },
  13. }
  14. const publicExperimental: WorkspaceManifest = {
  15. dir: 'packages/experimental/agent-team',
  16. manifest: {
  17. name: '@deepseek-ai/dsh-experimental-agent-team',
  18. publishConfig: { access: 'public' },
  19. },
  20. }
  21. describe('experimental workspace constraints', () => {
  22. it('requires the experimental package-name prefix', () => {
  23. expect(checkExperimentalManifest({
  24. ...experimental,
  25. manifest: { ...experimental.manifest, name: '@deepseek-ai/dsh-prototype' },
  26. })).toEqual([
  27. '@deepseek-ai/dsh-prototype: experimental package name must start with "@deepseek-ai/dsh-experimental-"',
  28. ])
  29. })
  30. it('requires private manifests without publication metadata', () => {
  31. expect(checkExperimentalManifest(experimental)).toEqual([])
  32. expect(checkExperimentalManifest({
  33. ...experimental,
  34. manifest: { ...experimental.manifest, private: false, publishConfig: { access: 'public' } },
  35. })).toEqual([
  36. '@deepseek-ai/dsh-experimental-prototype: experimental package must set "private": true',
  37. '@deepseek-ai/dsh-experimental-prototype: experimental package must omit publishConfig',
  38. ])
  39. })
  40. it('requires public metadata only for the Agent Teams exceptions', () => {
  41. expect(checkExperimentalManifest(publicExperimental)).toEqual([])
  42. expect(checkExperimentalManifest({
  43. ...publicExperimental,
  44. manifest: {
  45. name: '@deepseek-ai/dsh-experimental-agent-team',
  46. private: true,
  47. },
  48. })).toEqual([
  49. '@deepseek-ai/dsh-experimental-agent-team: public experimental package must not set "private": true',
  50. '@deepseek-ai/dsh-experimental-agent-team: public experimental package must set publishConfig.access to "public"',
  51. ])
  52. })
  53. it.each(['dependencies', 'optionalDependencies', 'peerDependencies'] as const)(
  54. 'rejects release %s on an experimental package',
  55. (section) => {
  56. expect(checkExperimentalDependencyIsolation([experimental, {
  57. dir: 'packages/core/consumer',
  58. manifest: {
  59. name: '@deepseek-ai/dsh-consumer',
  60. [section]: { '@deepseek-ai/dsh-experimental-prototype': 'workspace:^' },
  61. },
  62. }])).toEqual([
  63. `@deepseek-ai/dsh-consumer: ${section}.@deepseek-ai/dsh-experimental-prototype must not reference an experimental package`,
  64. ])
  65. },
  66. )
  67. it('allows development and experimental consumers but rejects the Python release runtime', () => {
  68. const manifests: WorkspaceManifest[] = [experimental, {
  69. dir: 'packages/core/test-only',
  70. manifest: {
  71. name: '@deepseek-ai/dsh-test-only',
  72. devDependencies: { '@deepseek-ai/dsh-experimental-prototype': 'workspace:^' },
  73. },
  74. }, {
  75. dir: 'packages/experimental/consumer',
  76. manifest: {
  77. name: '@deepseek-ai/dsh-experimental-consumer',
  78. dependencies: { '@deepseek-ai/dsh-experimental-prototype': 'workspace:^' },
  79. },
  80. }, {
  81. dir: 'python/sdk-runtime',
  82. manifest: {
  83. name: '@deepseek-ai/dsh-python-runtime',
  84. dependencies: { '@deepseek-ai/dsh-experimental-prototype': 'workspace:^' },
  85. },
  86. }]
  87. expect(checkExperimentalDependencyIsolation(manifests)).toEqual([
  88. '@deepseek-ai/dsh-python-runtime: dependencies.@deepseek-ai/dsh-experimental-prototype must not reference an experimental package',
  89. ])
  90. })
  91. })
  92. describe('dsh family version coherence', () => {
  93. it('rejects a package carrying a stale shared version', () => {
  94. expect(checkDshFamilyVersion(
  95. { name: '@deepseek-ai/dsh-http-proxy', version: '0.1.2-alpha.5' },
  96. '0.1.2-rc.1',
  97. )).toBe('@deepseek-ai/dsh-http-proxy: package.json version must match root version 0.1.2-rc.1')
  98. })
  99. it('rejects the root-named CLI app on a stale shared version', () => {
  100. expect(checkDshFamilyVersion(
  101. { name: '@deepseek-ai/dsh', version: '0.1.2-alpha.5' },
  102. '0.1.2-rc.1',
  103. )).toBe('@deepseek-ai/dsh: package.json version must match root version 0.1.2-rc.1')
  104. })
  105. it('accepts a manifest carrying the shared version', () => {
  106. expect(checkDshFamilyVersion(
  107. { name: '@deepseek-ai/dsh-http-proxy', version: '0.1.2-rc.1' },
  108. '0.1.2-rc.1',
  109. )).toBeUndefined()
  110. })
  111. it('leaves other sequences to their own version lines', () => {
  112. expect(checkDshFamilyVersion({ name: '@deepseek-ai/cordis', version: '4.0.1' }, '0.1.2-rc.1')).toBeUndefined()
  113. expect(checkDshFamilyVersion(
  114. { name: '@deepseek-ai/node-addon-system', version: '0.1.1' },
  115. '0.1.2-rc.1',
  116. )).toBeUndefined()
  117. expect(checkDshFamilyVersion({ version: '0.1.2-alpha.5' }, '0.1.2-rc.1')).toBeUndefined()
  118. })
  119. })
  120. describe('package payload constraints', () => {
  121. it('includes a declared profile patch without a package-name allowlist', () => {
  122. expect(expectedDshPackageFiles({
  123. name: '@deepseek-ai/dsh-private-profile',
  124. dsh: { bundle: { patch: './cordis.patch.yml' } },
  125. })).toEqual([
  126. 'lib/index.js',
  127. 'cordis.patch.yml',
  128. 'lib/types/**/*.d.ts',
  129. ])
  130. })
  131. })