aboutsummaryrefslogtreecommitdiff
path: root/script/deploy
blob: 3cc27b84496f8209332c6dcfb9271d2c8c66e642 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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);
});