diff --git a/README.md b/README.md index 869fbd1b..17c2ca5d 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,9 @@ The service account json in plain text, provided via a secret, etc. **Required:** The package name, or Application Id, of the app you are uploading -### `releaseFile` +### `releaseFiles` -**Required:** The Android release file to upload (.apk or .aab) +**Required:** The Android release file(s) to upload (.apk or .aab). Multiple files are separated by ','. ### `track` diff --git a/lib/edits.js b/lib/edits.js index 1b9c72c3..eb907305 100644 --- a/lib/edits.js +++ b/lib/edits.js @@ -37,65 +37,64 @@ const whatsnew_1 = require("./whatsnew"); const androidPublisher = googleapis_1.google.androidpublisher('v3'); function uploadToPlayStore(options, releaseFiles) { return __awaiter(this, void 0, void 0, function* () { - const appEdit = yield androidPublisher.edits.insert({ - auth: options.auth, - packageName: options.applicationId - }); - releaseFiles.forEach((releaseFile) => __awaiter(this, void 0, void 0, function* () { - core.debug(`Uploading ${releaseFile}`); - yield uploadRelease(appEdit.data, options, releaseFile).catch(reason => { - return Promise.reject(reason); - }); - })); - const res = yield androidPublisher.edits.commit({ - auth: options.auth, - editId: appEdit.data.id, - packageName: options.applicationId - }); - if (res.data.id != null) { - core.debug(`Successfully committed ${res.data.id}`); - return Promise.resolve(res.data.id); + if (options.track === 'internalappsharing') { + core.debug("Track is Internal app sharing, switch to special upload api"); + releaseFiles.forEach((releaseFile) => __awaiter(this, void 0, void 0, function* () { + core.debug(`Uploading ${releaseFile}`); + yield uploadInternalSharingRelease(options, releaseFile).catch(reason => { + core.setFailed(reason); + return Promise.reject(reason); + }); + })); } else { - core.setFailed(`Error ${res.status}: ${res.statusText}`); - return Promise.reject(res.status); + const appEdit = yield androidPublisher.edits.insert({ + auth: options.auth, + packageName: options.applicationId + }); + yield validateSelectedTrack(appEdit.data, options).catch(reason => { + core.setFailed(reason); + return Promise.reject(reason); + }); + // Check the 'track' for 'internalsharing', if so switch to a non-track api + var versionCodes = new Array(); + releaseFiles.forEach((releaseFile) => __awaiter(this, void 0, void 0, function* () { + core.debug(`Uploading ${releaseFile}`); + const versionCode = yield uploadRelease(appEdit.data, options, releaseFile).catch(reason => { + core.setFailed(reason); + return Promise.reject(reason); + }); + versionCodes.push(versionCode); + })); + const track = addReleasesToTrack(appEdit.data, options, versionCodes); + const res = yield androidPublisher.edits.commit({ + auth: options.auth, + editId: appEdit.data.id, + packageName: options.applicationId + }); + if (res.data.id != null) { + core.debug(`Successfully committed ${res.data.id}`); + return Promise.resolve(res.data.id); + } + else { + core.setFailed(`Error ${res.status}: ${res.statusText}`); + return Promise.reject(res.status); + } } }); } exports.uploadToPlayStore = uploadToPlayStore; -function uploadRelease(appEdit, options, releaseFile) { +function uploadInternalSharingRelease(options, releaseFile) { return __awaiter(this, void 0, void 0, function* () { - // Check the 'track' for 'internalsharing', if so switch to a non-track api - if (options.track === 'internalsharing') { - core.debug("Track is Internal app sharing, switch to special upload api"); - if (releaseFile.endsWith('.apk')) { - const res = yield internalSharingUploadApk(options, releaseFile); - return Promise.resolve(res.downloadUrl); - } - else if (releaseFile.endsWith('.aab')) { - const res = yield internalSharingUploadBundle(options, releaseFile); - return Promise.resolve(res.downloadUrl); - } - else { - core.setFailed(`${releaseFile} is invalid`); - return Promise.reject(`${releaseFile} is invalid`); - } - } - const allTracks = yield getAllTracks(appEdit, options); - if (allTracks == undefined || allTracks.find(value => value.track == options.track) == undefined) { - core.setFailed(`Track "${options.track}" could not be found `); - return Promise.reject(`No track found for "${options.track}"`); - } - let track = undefined; if (releaseFile.endsWith('.apk')) { - const apk = yield uploadApk(appEdit, options, releaseFile); - yield uploadMappingFile(appEdit, apk.versionCode, options); - track = yield trackVersionCode(appEdit, options, apk.versionCode); + const res = yield internalSharingUploadApk(options, releaseFile); + console.log(`${releaseFile} uploaded to Internal Sharing, download it with ${res.downloadUrl}`); + return Promise.resolve(res.downloadUrl); } else if (releaseFile.endsWith('.aab')) { - const bundle = yield uploadBundle(appEdit, options, releaseFile); - yield uploadMappingFile(appEdit, bundle.versionCode, options); - track = yield trackVersionCode(appEdit, options, bundle.versionCode); + const res = yield internalSharingUploadBundle(options, releaseFile); + console.log(`${releaseFile} uploaded to Internal Sharing, download it with ${res.downloadUrl}`); + return Promise.resolve(res.downloadUrl); } else { core.setFailed(`${releaseFile} is invalid`); @@ -103,17 +102,39 @@ function uploadRelease(appEdit, options, releaseFile) { } }); } -function getAllTracks(appEdit, options) { +function uploadRelease(appEdit, options, releaseFile) { + return __awaiter(this, void 0, void 0, function* () { + if (releaseFile.endsWith('.apk')) { + const apk = yield uploadApk(appEdit, options, releaseFile); + yield uploadMappingFile(appEdit, apk.versionCode, options); + return Promise.resolve(apk.versionCode); + } + else if (releaseFile.endsWith('.aab')) { + const bundle = yield uploadBundle(appEdit, options, releaseFile); + yield uploadMappingFile(appEdit, bundle.versionCode, options); + return Promise.resolve(bundle.versionCode); + } + else { + core.setFailed(`${releaseFile} is invalid`); + return Promise.reject(`${releaseFile} is invalid`); + } + }); +} +function validateSelectedTrack(appEdit, options) { return __awaiter(this, void 0, void 0, function* () { const res = yield androidPublisher.edits.tracks.list({ auth: options.auth, editId: appEdit.id, packageName: options.applicationId }); - return res.data.tracks; + const allTracks = res.data.tracks; + if (allTracks == undefined || allTracks.find(value => value.track == options.track) == undefined) { + core.setFailed(`Track "${options.track}" could not be found `); + return Promise.reject(`No track found for "${options.track}"`); + } }); } -function trackVersionCode(appEdit, options, versionCode) { +function addReleasesToTrack(appEdit, options, versionCodes) { return __awaiter(this, void 0, void 0, function* () { let status; if (options.userFraction != undefined) { @@ -122,7 +143,7 @@ function trackVersionCode(appEdit, options, versionCode) { else { status = 'completed'; } - core.debug(`Creating Track Release for Edit(${appEdit.id}) for Track(${options.track}) with a UserFraction(${options.userFraction}) and VersionCode(${versionCode})`); + core.debug(`Creating Track Release for Edit(${appEdit.id}) for Track(${options.track}) with a UserFraction(${options.userFraction}) and VersionCodes(${versionCodes})`); const res = yield androidPublisher.edits.tracks .update({ auth: options.auth, @@ -136,9 +157,7 @@ function trackVersionCode(appEdit, options, versionCode) { userFraction: options.userFraction, status: status, releaseNotes: yield whatsnew_1.readLocalizedReleaseNotes(options.whatsNewDir), - versionCodes: [ - versionCode.toString() - ] + versionCodes: versionCodes.map(x => x.toString()) } ] } diff --git a/src/edits.ts b/src/edits.ts index 643e94ca..d517c92c 100644 --- a/src/edits.ts +++ b/src/edits.ts @@ -28,89 +28,106 @@ export interface EditOptions { } export async function uploadToPlayStore(options: EditOptions, releaseFiles: string[]): Promise { - const appEdit = await androidPublisher.edits.insert({ - auth: options.auth, - packageName: options.applicationId - }); - - releaseFiles.forEach(async releaseFile => { - core.debug(`Uploading ${releaseFile}`) - await uploadRelease(appEdit.data, options, releaseFile).catch(reason => { - return Promise.reject(reason) - }) - }) - - const res = await androidPublisher.edits.commit({ - auth: options.auth, - editId: appEdit.data.id!, - packageName: options.applicationId - }); - - if (res.data.id != null) { - core.debug(`Successfully committed ${res.data.id}`) - return Promise.resolve(res.data.id!) + if (options.track === 'internalappsharing') { + core.debug("Track is Internal app sharing, switch to special upload api") + releaseFiles.forEach(async releaseFile => { + core.debug(`Uploading ${releaseFile}`); + await uploadInternalSharingRelease(options, releaseFile).catch(reason => { + core.setFailed(reason); + return Promise.reject(reason); + }); + }); } else { - core.setFailed(`Error ${res.status}: ${res.statusText}`) - return Promise.reject(res.status) + const appEdit = await androidPublisher.edits.insert({ + auth: options.auth, + packageName: options.applicationId + }); + + await validateSelectedTrack(appEdit.data, options).catch(reason => { + core.setFailed(reason); + return Promise.reject(reason); + }); + + // Check the 'track' for 'internalsharing', if so switch to a non-track api + var versionCodes = new Array(); + releaseFiles.forEach(async releaseFile => { + core.debug(`Uploading ${releaseFile}`); + const versionCode = await uploadRelease(appEdit.data, options, releaseFile).catch(reason => { + core.setFailed(reason); + return Promise.reject(reason); + }); + versionCodes.push(versionCode!); + }); + + const track = addReleasesToTrack(appEdit.data, options, versionCodes); + const res = await androidPublisher.edits.commit({ + auth: options.auth, + editId: appEdit.data.id!, + packageName: options.applicationId + }); + + if (res.data.id != null) { + core.debug(`Successfully committed ${res.data.id}`); + return Promise.resolve(res.data.id!); + } else { + core.setFailed(`Error ${res.status}: ${res.statusText}`); + return Promise.reject(res.status); + } } } -async function uploadRelease(appEdit: AppEdit, options: EditOptions, releaseFile: string): Promise { - // Check the 'track' for 'internalsharing', if so switch to a non-track api - if (options.track === 'internalsharing'){ - core.debug("Track is Internal app sharing, switch to special upload api") - if (releaseFile.endsWith('.apk')) { - const res = await internalSharingUploadApk(options, releaseFile) - return Promise.resolve(res.downloadUrl) - } else if (releaseFile.endsWith('.aab')) { - const res = await internalSharingUploadBundle(options, releaseFile) - return Promise.resolve(res.downloadUrl) - } else { - core.setFailed(`${releaseFile} is invalid`) - return Promise.reject(`${releaseFile} is invalid`) - } - } - - const allTracks = await getAllTracks(appEdit!, options); - if (allTracks == undefined || allTracks.find(value => value.track == options.track) == undefined) { - core.setFailed(`Track "${options.track}" could not be found `) - return Promise.reject(`No track found for "${options.track}"`) - } - - let track: Track | undefined = undefined; +async function uploadInternalSharingRelease(options: EditOptions, releaseFile: string): Promise { if (releaseFile.endsWith('.apk')) { - const apk = await uploadApk(appEdit, options, releaseFile); - await uploadMappingFile(appEdit, apk.versionCode!, options); - track = await trackVersionCode(appEdit, options, apk.versionCode!) + const res = await internalSharingUploadApk(options, releaseFile) + console.log(`${releaseFile} uploaded to Internal Sharing, download it with ${res.downloadUrl}`) + return Promise.resolve(res.downloadUrl) } else if (releaseFile.endsWith('.aab')) { - const bundle = await uploadBundle(appEdit, options, releaseFile); - await uploadMappingFile(appEdit, bundle.versionCode!, options); - track = await trackVersionCode(appEdit, options, bundle.versionCode!) + const res = await internalSharingUploadBundle(options, releaseFile) + console.log(`${releaseFile} uploaded to Internal Sharing, download it with ${res.downloadUrl}`) + return Promise.resolve(res.downloadUrl) } else { core.setFailed(`${releaseFile} is invalid`) return Promise.reject(`${releaseFile} is invalid`) } } -async function getAllTracks(appEdit: AppEdit, options: EditOptions): Promise { +async function uploadRelease(appEdit: AppEdit, options: EditOptions, releaseFile: string): Promise { + if (releaseFile.endsWith('.apk')) { + const apk = await uploadApk(appEdit, options, releaseFile); + await uploadMappingFile(appEdit, apk.versionCode!, options); + return Promise.resolve(apk.versionCode); + } else if (releaseFile.endsWith('.aab')) { + const bundle = await uploadBundle(appEdit, options, releaseFile); + await uploadMappingFile(appEdit, bundle.versionCode!, options); + return Promise.resolve(bundle.versionCode); + } else { + core.setFailed(`${releaseFile} is invalid`); + return Promise.reject(`${releaseFile} is invalid`); + } +} + +async function validateSelectedTrack(appEdit: AppEdit, options: EditOptions): Promise { const res = await androidPublisher.edits.tracks.list({ auth: options.auth, editId: appEdit.id!, packageName: options.applicationId }); - - return res.data.tracks + const allTracks = res.data.tracks; + if (allTracks == undefined || allTracks.find(value => value.track == options.track) == undefined) { + core.setFailed(`Track "${options.track}" could not be found `); + return Promise.reject(`No track found for "${options.track}"`); + } } -async function trackVersionCode(appEdit: AppEdit, options: EditOptions, versionCode: number): Promise { +async function addReleasesToTrack(appEdit: AppEdit, options: EditOptions, versionCodes: number[]): Promise { let status: string; if (options.userFraction != undefined) { - status = 'inProgress' + status = 'inProgress'; } else { - status = 'completed' + status = 'completed'; } - core.debug(`Creating Track Release for Edit(${appEdit.id}) for Track(${options.track}) with a UserFraction(${options.userFraction}) and VersionCode(${versionCode})`); + core.debug(`Creating Track Release for Edit(${appEdit.id}) for Track(${options.track}) with a UserFraction(${options.userFraction}) and VersionCodes(${versionCodes})`); const res = await androidPublisher.edits.tracks .update({ auth: options.auth, @@ -124,15 +141,13 @@ async function trackVersionCode(appEdit: AppEdit, options: EditOptions, versionC userFraction: options.userFraction, status: status, releaseNotes: await readLocalizedReleaseNotes(options.whatsNewDir), - versionCodes: [ - versionCode.toString() - ] + versionCodes: versionCodes.map(x => x.toString()) } ] } }); - return res.data + return res.data; } async function uploadMappingFile(appEdit: AppEdit, versionCode: number, options: EditOptions) {