diff --git a/script/deploy b/script/deploy new file mode 100755 index 0000000..3cc27b8 --- /dev/null +++ b/script/deploy @@ -0,0 +1,91 @@ +#!/usr/bin/env node + +const uuid = require('uuid'); +const fs = require('fs'); +const jwt = require('jsonwebtoken'); +const request = require('request-promise-native'); + +class AMOClient { + constructor(issuer, secret) { + this.issuer = issuer; + this.secret = secret; + } + + async getProfile() { + let token = this._getJwtToken(); + let response = await request({ + url: 'https://addons.mozilla.org/api/v4/accounts/profile/', + method: 'GET', + headers: { + Authorization: 'JWT ' + token, + } + }); + return response; + }; + + async uploadVersion(guid, version, xpiPath) { + let token = this._getJwtToken(); + const formData = { + upload: fs.createReadStream(xpiPath), + }; + let url = `https://addons.mozilla.org/api/v4/addons/${encodeURIComponent(guid)}/versions/${encodeURIComponent(version)}/` + let response = await request({ + url, + formData, + method: 'PUT', + headers: { + Authorization: 'JWT ' + token, + } + }); + return response; + } + + _getJwtToken() { + // See https://addons-server.readthedocs.io/en/latest/topics/api/auth.html + const issuedAt = Math.floor(Date.now() / 1000); + const payload = { + iss: this.issuer, + jti: uuid.v4(), + iat: issuedAt, + exp: issuedAt + 60, + }; + return jwt.sign(payload, this.secret, { algorithm: 'HS256' }); + } +} + +const run = async() => { + let args = process.argv; + if (args.length != 5) { + console.error(`USAGE: ${args[1]} GUID VERSION XPI_PATH`) + console.error('') + console.error('Environment variables') + console.error(' JWT_ISSUER: JWT issuer generated by AMO') + console.error(' JWT_SECRET: JWT secret token generated by AMO') + process.exit(2); + } + + let guid = args[2]; + let version = args[3]; + let xpiPath = args[4] + let jwtIssuer = process.env['JWT_ISSUER']; + let jwtSecret = process.env['JWT_SECRET']; + + if (typeof jwtIssuer === 'undefined' || jwtIssuer.length === 0) { + console.error('JWT_ISSUER not set'); + process.exit(2); + } + if (typeof jwtSecret === 'undefined' || jwtSecret.length === 0) { + console.error('JWT_SECRET not set'); + process.exit(2); + } + + let amo = new AMOClient(jwtIssuer, jwtSecret); + console.log(`Uploading ${xpiPath} to ${guid}/${version}`); + let response = await amo.uploadVersion(guid, version, xpiPath); + console.log(response); +}; + +run().catch((err) => { + console.error(err.error || err.message); + process.exit(1); +});