aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2019-09-05 03:30:41 +0000
committerGitHub <noreply@github.com>2019-09-05 03:30:41 +0000
commit428805e66f993884643136dc2d8267c53bd81588 (patch)
tree630deab9c7db1ffd00ea205fa7f1f420da0de7cb
parent763b24fe2114e10e8d040b4fe5b9fce22781de32 (diff)
parentb4bda1447abdddf35e498d5d792e30ec23034354 (diff)
Merge pull request #640 from ueokande/auto-deploy
Deploy an addon automatically
-rw-r--r--.circleci/config.yml38
-rw-r--r--package-lock.json172
-rw-r--r--package.json2
-rwxr-xr-xscript/deploy91
4 files changed, 278 insertions, 25 deletions
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 46cf0a6..1294557 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -47,7 +47,7 @@ commands:
- restore_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
- run:
- name: Install npm wee
+ name: Install dependencies
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package-lock.json" }}
@@ -77,6 +77,19 @@ jobs:
- run: npm run build
- run: npm run test:e2e
+ deploy:
+ executor:
+ name: default
+ steps:
+ - checkout
+ - setup_npm
+ - run: npm run package
+ - run:
+ name: Deploy to AMO
+ command: |
+ version=$(jq -r '.version' manifest.json)
+ ./script/deploy vim-vixen@i-beam.org "$version" "vim-vixen-${version}.zip"
+
workflows:
version: 2
build_and_test:
@@ -86,3 +99,26 @@ workflows:
filters:
branches:
ignore: /^greenkeeper\/.*/
+ deploy:
+ jobs:
+ - build:
+ filters:
+ tags:
+ only: /^.*/
+ branches:
+ ignore: /.*/
+ - e2e:
+ filters:
+ tags:
+ only: /^.*/
+ branches:
+ ignore: /.*/
+ - deploy:
+ requires:
+ - build
+ - e2e
+ filters:
+ tags:
+ only: /^.*/
+ branches:
+ ignore: /.*/
diff --git a/package-lock.json b/package-lock.json
index 6eabf8c..07869a7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1104,6 +1104,12 @@
"integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
"dev": true
},
+ "buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=",
+ "dev": true
+ },
"buffer-fill": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
@@ -2090,6 +2096,15 @@
"safer-buffer": "^2.1.0"
}
},
+ "ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
"ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -3166,7 +3181,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"aproba": {
"version": "1.2.0",
@@ -3187,12 +3203,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -3207,17 +3225,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"core-util-is": {
"version": "1.0.2",
@@ -3334,7 +3355,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"ini": {
"version": "1.3.5",
@@ -3346,6 +3368,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -3360,6 +3383,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -3367,12 +3391,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -3391,6 +3417,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -3478,7 +3505,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"object-assign": {
"version": "4.1.1",
@@ -3490,6 +3518,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"wrappy": "1"
}
@@ -3575,7 +3604,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -3611,6 +3641,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -3630,6 +3661,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
+ "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -3673,12 +3705,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
- "dev": true
+ "dev": true,
+ "optional": true
}
}
},
@@ -4756,6 +4790,32 @@
"graceful-fs": "^4.1.6"
}
},
+ "jsonwebtoken": {
+ "version": "8.5.1",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz",
+ "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==",
+ "dev": true,
+ "requires": {
+ "jws": "^3.2.2",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^5.6.0"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ }
+ }
+ },
"jsprim": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
@@ -4796,6 +4856,27 @@
"integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==",
"dev": true
},
+ "jwa": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
+ "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==",
+ "dev": true,
+ "requires": {
+ "buffer-equal-constant-time": "1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "jws": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz",
+ "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==",
+ "dev": true,
+ "requires": {
+ "jwa": "^1.4.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
"karma": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/karma/-/karma-4.2.0.tgz",
@@ -5088,7 +5169,7 @@
}
},
"lanthan": {
- "version": "git+https://github.com/ueokande/lanthan.git#fb7f641846369de5bac7762f19186d23248f0d53",
+ "version": "git+https://github.com/ueokande/lanthan.git#d7f92eb4c1c6eee3f747b4a76bdf39062b4cb58f",
"from": "git+https://github.com/ueokande/lanthan.git#master",
"dev": true,
"requires": {
@@ -5300,6 +5381,48 @@
"integrity": "sha512-DHb1ub+rMjjrxqlB3H56/6MXtm1lSksDp2rA2cNWjG8mlDUYFhUj3Di2Zn5IwSU87xLv8tNIQ7sSwE/YOX/D/Q==",
"dev": true
},
+ "lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=",
+ "dev": true
+ },
+ "lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=",
+ "dev": true
+ },
+ "lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=",
+ "dev": true
+ },
+ "lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=",
+ "dev": true
+ },
+ "lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=",
+ "dev": true
+ },
+ "lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=",
+ "dev": true
+ },
+ "lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=",
+ "dev": true
+ },
"lodash.unescape": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz",
@@ -7662,14 +7785,6 @@
"dev": true,
"requires": {
"lodash": "^4.17.11"
- },
- "dependencies": {
- "lodash": {
- "version": "4.17.15",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
- "dev": true
- }
}
},
"request-promise-native": {
@@ -8988,12 +9103,21 @@
"dev": true
},
"tough-cookie": {
- "version": "2.3.4",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
- "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"dev": true,
"requires": {
- "punycode": "^1.4.1"
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ }
}
},
"trim-newlines": {
diff --git a/package.json b/package.json
index c99a84c..2306396 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
"eslint": "^6.2.2",
"eslint-plugin-react": "^7.14.3",
"html-webpack-plugin": "^3.2.0",
+ "jsonwebtoken": "^8.5.1",
"jszip": "^3.2.2",
"karma": "^4.2.0",
"karma-firefox-launcher": "^1.2.0",
@@ -55,6 +56,7 @@
"redux": "^4.0.4",
"redux-promise": "^0.6.0",
"reflect-metadata": "^0.1.13",
+ "request-promise-native": "^1.0.7",
"sass-loader": "^7.3.1",
"sinon": "^7.4.1",
"sinon-chrome": "^3.0.1",
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);
+});