release-artifacts.test.mjs 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. import { test } from 'node:test'
  2. import assert from 'node:assert/strict'
  3. import { mkdtemp, writeFile, rm } from 'node:fs/promises'
  4. import { tmpdir } from 'node:os'
  5. import { join } from 'node:path'
  6. import { createHash } from 'node:crypto'
  7. import { dump } from 'js-yaml'
  8. import { releaseSigningOptions, verifyUpdateArtifacts } from '../scripts/desktop-release.mjs'
  9. test('formal desktop releases require a distribution identity and notarization credentials', () => {
  10. assert.throws(() => releaseSigningOptions({}), /Developer ID/)
  11. assert.throws(() => releaseSigningOptions({ CSC_NAME: 'Apple Development: Test' }), /Developer ID/)
  12. assert.throws(() => releaseSigningOptions({ CSC_NAME: 'Developer ID Application: Test' }), /公证/)
  13. const options = releaseSigningOptions({ CSC_NAME: 'Developer ID Application: Test', APPLE_API_KEY: '/fixture/key.p8', APPLE_API_KEY_ID: 'key', APPLE_API_ISSUER: 'issuer' })
  14. assert.equal(options.forceCodeSigning, true); assert.equal(options.mac.notarize, true)
  15. assert.equal(options.mac.identity, 'Test'); assert.equal(options.mac.type, 'distribution')
  16. assert.deepEqual(releaseSigningOptions({ CSC_NAME: 'Developer ID Application: Test', APPLE_KEYCHAIN_PROFILE: 'yaoyao-notary' }), options)
  17. assert.throws(() => releaseSigningOptions({ CSC_NAME: 'Developer ID Application: Test', APPLE_KEYCHAIN: '/fixture/login.keychain-db' }), /公证/)
  18. assert.throws(() => releaseSigningOptions({ CSC_NAME: 'Developer ID Application: Test', APPLE_KEYCHAIN_PROFILE: ' ' }), /公证/)
  19. })
  20. test('release verification rejects incomplete, mixed-version and corrupt updater artifacts', async () => {
  21. const directory = await mkdtemp(join(tmpdir(), 'yaoyao-update-artifacts-'))
  22. const bytes = Buffer.from('signed fixture'), version = '0.4.63'
  23. const files = ['zip', 'dmg'].map(ext => ({ url: `Yaoyao-${version}-arm64.${ext}`, size: bytes.length, sha512: createHash('sha512').update(bytes).digest('base64') }))
  24. try {
  25. for (const file of files) { await writeFile(join(directory, file.url), bytes); await writeFile(join(directory, file.url + '.blockmap'), 'map') }
  26. await writeFile(join(directory, 'latest-mac.yml'), dump({ version, files }))
  27. assert.equal((await verifyUpdateArtifacts(directory, version)).length, 5)
  28. await assert.rejects(verifyUpdateArtifacts(directory, '0.4.64'), /版本/)
  29. await writeFile(join(directory, files[0].url), 'tampered')
  30. await assert.rejects(verifyUpdateArtifacts(directory, version), /大小/)
  31. await writeFile(join(directory, files[0].url), Buffer.alloc(bytes.length))
  32. await assert.rejects(verifyUpdateArtifacts(directory, version), /SHA-512/)
  33. await writeFile(join(directory, 'latest-mac.yml'), dump({ version, files: [files[1]] }))
  34. await assert.rejects(verifyUpdateArtifacts(directory, version), /缺少唯一/)
  35. } finally { await rm(directory, { recursive: true, force: true }) }
  36. })