diff --git a/packages/publisher/electron-release-server/src/PublisherERS.ts b/packages/publisher/electron-release-server/src/PublisherERS.ts index fd46396542..891801e11d 100644 --- a/packages/publisher/electron-release-server/src/PublisherERS.ts +++ b/packages/publisher/electron-release-server/src/PublisherERS.ts @@ -11,10 +11,19 @@ import { PublisherERSConfig } from './Config'; const d = debug('electron-forge:publish:ers'); +interface ERSAsset { + name: string; + platform: string; +} + +interface ERSFlavor { + name: string; +} + interface ERSVersion { name: string; - assets: { name: string }[]; - flavor?: string; + assets: ERSAsset[]; + flavor: ERSFlavor; } const fetchAndCheckStatus = async (url: RequestInfo, init?: RequestInit): Promise => { @@ -71,16 +80,15 @@ export default class PublisherERS extends PublisherBase { const authFetch = (apiPath: string, options?: RequestInit) => fetchAndCheckStatus(api(apiPath), { ...(options || {}), headers: { ...(options || {}).headers, Authorization: `Bearer ${token}` } }); - const versions: ERSVersion[] = await (await authFetch('api/version')).json(); const flavor = config.flavor || 'default'; for (const makeResult of makeResults) { const { packageJSON } = makeResult; const artifacts = makeResult.artifacts.filter((artifactPath) => path.basename(artifactPath).toLowerCase() !== 'releases'); - const existingVersion = versions.find((version) => { - return version.name === packageJSON.version && (!version.flavor || version.flavor === flavor); - }); + const versions: ERSVersion[] = await (await authFetch('api/version')).json(); + // Find the version with the same name and flavor + const existingVersion = versions.find((version) => version.name === packageJSON.version && version.flavor.name === flavor); let channel = 'stable'; if (config.channel) { @@ -97,12 +105,11 @@ export default class PublisherERS extends PublisherBase { await authFetch('api/version', { method: 'POST', body: JSON.stringify({ - channel: { - name: channel, - }, - flavor: config.flavor, + channel: channel, + flavor: flavor, name: packageJSON.version, notes: '', + id: packageJSON.version + '_' + channel, }), headers: { 'Content-Type': 'application/json', @@ -115,10 +122,10 @@ export default class PublisherERS extends PublisherBase { updateStatusLine(); await Promise.all( - artifacts.map(async (artifactPath) => { + artifacts.map(async (artifactPath: string) => { + const platform = ersPlatform(makeResult.platform, makeResult.arch); if (existingVersion) { - const existingAsset = existingVersion.assets.find((asset) => asset.name === path.basename(artifactPath)); - + const existingAsset = existingVersion.assets.find((asset) => asset.name === path.basename(artifactPath) && asset.platform === platform); if (existingAsset) { d('asset at path:', artifactPath, 'already exists on server'); uploaded += 1; @@ -130,8 +137,7 @@ export default class PublisherERS extends PublisherBase { const artifactForm = new FormData(); artifactForm.append('token', token); artifactForm.append('version', `${packageJSON.version}_${flavor}`); - artifactForm.append('platform', ersPlatform(makeResult.platform, makeResult.arch)); - + artifactForm.append('platform', platform); // see https://github.com/form-data/form-data/issues/426 const fileOptions = { knownLength: fs.statSync(artifactPath).size, diff --git a/packages/publisher/electron-release-server/test/PublisherERS_spec.ts b/packages/publisher/electron-release-server/test/PublisherERS_spec.ts index ccc36d3f5e..52a79d4c2c 100644 --- a/packages/publisher/electron-release-server/test/PublisherERS_spec.ts +++ b/packages/publisher/electron-release-server/test/PublisherERS_spec.ts @@ -35,7 +35,7 @@ describe('PublisherERS', () => { // mock login fetch.postOnce('path:/api/auth/login', { body: { token }, status: 200 }); // mock fetch all existing versions - fetch.getOnce('path:/api/version', { body: [{ name: '2.0.0', assets: [], flavor: 'default' }], status: 200 }); + fetch.getOnce('path:/api/version', { body: [{ name: '2.0.0', assets: [], flavor: { name: 'default' } }], status: 200 }); // mock creating a new version fetch.postOnce('path:/api/version', { status: 200 }); // mock asset upload @@ -65,7 +65,7 @@ describe('PublisherERS', () => { // creates a new version with the correct flavor, name, and channel expect(calls[2][0]).to.equal(`${baseUrl}/api/version`); - expect(calls[2][1]?.body).to.equal(`{"channel":{"name":"stable"},"flavor":"${flavor}","name":"${version}","notes":""}`); + expect(calls[2][1]?.body).to.equal(`{"channel":"stable","flavor":"${flavor}","name":"${version}","notes":"","id":"${version}_stable"}`); // uploads asset successfully expect(calls[3][0]).to.equal(`${baseUrl}/api/asset`); @@ -83,7 +83,7 @@ describe('PublisherERS', () => { // mock login fetch.postOnce('path:/api/auth/login', { body: { token }, status: 200 }); // mock fetch all existing versions - fetch.getOnce('path:/api/version', { body: [{ name: '2.0.0', assets: [], flavor: 'lite' }], status: 200 }); + fetch.getOnce('path:/api/version', { body: [{ name: '2.0.0', assets: [], flavor: { name: 'lite' } }], status: 200 }); // mock asset upload fetch.post('path:/api/asset', { status: 200 }); @@ -123,7 +123,10 @@ describe('PublisherERS', () => { // mock login fetch.postOnce('path:/api/auth/login', { body: { token }, status: 200 }); // mock fetch all existing versions - fetch.getOnce('path:/api/version', { body: [{ name: '2.0.0', assets: [{ name: 'existing-artifact' }], flavor: 'default' }], status: 200 }); + fetch.getOnce('path:/api/version', { + body: [{ name: '2.0.0', assets: [{ name: 'existing-artifact', platform: 'linux_64' }], flavor: { name: 'default' } }], + status: 200, + }); const publisher = new PublisherERS({ baseUrl, @@ -158,7 +161,7 @@ describe('PublisherERS', () => { // mock login fetch.postOnce('path:/api/auth/login', { body: { token }, status: 200 }); // mock fetch all existing versions - fetch.getOnce('path:/api/version', { body: [{ name: '2.0.0', assets: [{ name: 'existing-artifact' }], flavor: 'default' }], status: 200 }); + fetch.getOnce('path:/api/version', { body: [{ name: '2.0.0', assets: [{ name: 'existing-artifact' }], flavor: { name: 'default' } }], status: 200 }); // mock creating a new version fetch.postOnce('path:/api/version', { status: 200 }); // mock asset upload @@ -188,7 +191,7 @@ describe('PublisherERS', () => { // creates a new version with the correct flavor, name, and channel expect(calls[2][0]).to.equal(`${baseUrl}/api/version`); - expect(calls[2][1]?.body).to.equal(`{"channel":{"name":"stable"},"flavor":"${flavor}","name":"${version}","notes":""}`); + expect(calls[2][1]?.body).to.equal(`{"channel":"stable","flavor":"${flavor}","name":"${version}","notes":"","id":"${version}_stable"}`); // uploads asset successfully expect(calls[3][0]).to.equal(`${baseUrl}/api/asset`);