Last active
January 19, 2022 10:27
-
-
Save BransonGitomeh/4f9f04c23e0f413e9c2f38d38697ed20 to your computer and use it in GitHub Desktop.
Script to upload apk to playstore, can be added to CI step to automate publications
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env NODE_NO_WARNINGS=1 node | |
const { google } = require('googleapis'); | |
const Promise = require('bluebird'); | |
const fs = require('fs'); | |
const settings = require('./config/settings.json'); | |
const { version } = require('./package.json'); | |
// Enable API access into the Developer Console: https://play.google.com/apps/publish/?account=7639196906174529268#ApiAccessPlace | |
// Create a service account | |
// Download the JSON and save it here | |
// Make sure the email of the JSON is added to the apps for release manager role: | |
// https://play.google.com/apps/publish/?account=7639196906174529268#AdminPlace | |
const key = require('./secrets.json'); | |
// editing "scope" allowed for OAuth2 | |
const scopes = ['https://www.googleapis.com/auth/androidpublisher']; | |
process.exitCode = 1; | |
const { OAuth2 } = google.auth; | |
const oauth2Client = new OAuth2(); | |
const jwtClient = new google.auth.JWT( | |
key.client_email, | |
null, | |
key.private_key, | |
scopes, | |
null, | |
); | |
const play = google.androidpublisher({ | |
version: 'v3', | |
auth: oauth2Client, | |
params: { | |
// default options | |
// this is the package name for your initial app you've already set up on the Play Store | |
packageName: settings.app.id, | |
}, | |
}); | |
google.options({ auth: oauth2Client }); | |
/** | |
* Sets our authorization token and begins an edit transaction. | |
*/ | |
function startEdit() { | |
return new Promise(((resolve, reject) => { | |
jwtClient.authorize((err, tokens) => { | |
if (err) { | |
console.log('authorize error', err); | |
process.exit(1); | |
return; | |
} | |
// Set the credentials before we doing anything. | |
oauth2Client.setCredentials(tokens); | |
play.edits.insert( | |
{ | |
packageName: settings.app.id, | |
}, | |
(insertError, edit) => { | |
if (insertError || !edit) { | |
console.log('Insert errors', insertError); | |
reject(err); | |
} | |
resolve({ | |
edit: edit.data, | |
}); | |
}, | |
); | |
}); | |
})); | |
} | |
const start = async () => { | |
const { packageName = 'io.braiven.databank' } = process.env; | |
console.log(`Upload started for ${packageName} for version ${version}`); | |
const { | |
edit: { id: editId }, | |
} = await startEdit(); | |
const builds = ['app-armeabi-v7a-release.apk', 'app-x86-release.apk']; | |
const availableOutputFiles = fs.readdirSync('./android/app/build/outputs/apk/release'); | |
console.log('Available builds are', availableOutputFiles.join(', ')); | |
const uploadRes = await Promise.all( | |
builds.map(async (build) => { | |
try { | |
// dont try read a build thats not on the FS | |
if (!availableOutputFiles.includes(build)) { return; } | |
const apk = fs.readFileSync(`./android/app/build/outputs/apk/release/${build}`); | |
console.log(`Attempting Upload for cpu build ${build}`); | |
const { | |
data: { | |
versionCode: uploadedVersionCode, | |
binary: { sha256 }, | |
}, | |
} = await play.edits.apks.upload({ | |
editId, | |
packageName, | |
media: { | |
mimeType: 'application/vnd.android.package-archive', | |
body: apk, | |
}, | |
}); | |
console.log(`Successfully uploaded version:${uploadedVersionCode}, build:${build}, sha256:${sha256}`); | |
return { versionCode: uploadedVersionCode, sha256 }; | |
} catch (err) { | |
console.log(`Upload for ${build} failed`, err.message); | |
throw err; | |
} | |
}), | |
); | |
console.log(JSON.stringify({ uploadRes }, null, '\t')); | |
// Assign apk to beta track. | |
const { data: trackRes } = await play.edits.tracks.update({ | |
editId, | |
track: 'beta', | |
packageName, | |
releases: [ | |
{ | |
versionCodes: [uploadRes[0].versionCode], | |
status: 'completed', | |
}, | |
], | |
}); | |
console.log('Placing edit on beta track', trackRes); | |
const { data: lists } = await play.edits.apks.list({ editId }); | |
console.log('Edits apk list', lists.apks.map(apk => apk.versionCode)); | |
// const { data: lists } = await play.edits.apks.u; | |
const { data: commit } = await play.edits.commit({ | |
editId, | |
packageName, | |
}); | |
console.log({ commit }); | |
}; | |
start().catch((err) => { | |
const errString = 'Upload failed with the following errors'; | |
if (err.errors) { | |
console.error(`${errString} ${JSON.stringify(err.errors, null, '\t')}`); | |
} else { | |
console.error(`${errString} ${err}`); | |
} | |
process.exit(1); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is this up to date? I'm getting invalid request errors. Also how is this different / better than the
apkup
package?