check-workspace-constraints.spec.ts 4.6 KB

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