Skip to content

Commit

Permalink
feat: Added channel to specify a release channel
Browse files Browse the repository at this point in the history
  • Loading branch information
welwood08 committed Feb 12, 2018
1 parent f3769db commit 652a77c
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 1 deletion.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ signAddon(
// WebExtensions do not require an ID.
// See the notes below about dealing with IDs.
id: 'your-addon-id@somewhere',
// The release channel (listed or unlisted).
// Ignored for new add-ons, which are always unlisted.
// Default: most recently used channel.
channel: undefined,
// Save downloaded files to this directory.
// Default: current working directory.
downloadDir: undefined,
Expand Down
12 changes: 11 additions & 1 deletion src/amo-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,13 @@ export class Client {
* - `xpiPath` Path to xpi file.
* - `guid` Optional add-on GUID, aka the ID in install.rdf.
* - `version` add-on version string.
* - `channel` release channel (listed, unlisted).
* @return {Promise} signingResult with keys:
* - success: boolean
* - downloadedFiles: Array of file objects
* - id: string identifier for the signed add-on
*/
sign({guid, version, xpiPath}) {
sign({guid, version, channel, xpiPath}) {

const formData = {
upload: this._fs.createReadStream(xpiPath),
Expand All @@ -93,11 +94,20 @@ export class Client {
// PUT to a specific URL for this add-on + version.
addonUrl += encodeURIComponent(guid) +
"/versions/" + encodeURIComponent(version) + "/";
if (channel) {
formData.channel = channel;
}
} else {
// POST to a generic URL to create a new add-on.
this.debug("Signing add-on without an ID");
method = "post";
formData.version = version;
if (channel) {
this.logger.warn(
"Specifying a channel for a new add-on is unsupported. " +
"New add-ons are always in the unlisted channel."
);
}
}

const doRequest = this[method].bind(this);
Expand Down
5 changes: 5 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ export default function signAddon(
// This must match the expiration time that the API server accepts.
apiJwtExpiresIn,
verbose=false,
// The release channel (listed or unlisted).
// Ignored for new add-ons, which are always unlisted.
// Defaults to most recently used channel.
channel,
// Number of milleseconds to wait before giving up on a
// response from Mozilla's web service.
timeout,
Expand Down Expand Up @@ -87,6 +91,7 @@ export default function signAddon(
xpiPath: xpiPath,
guid: id,
version: version,
channel: channel,
});

});
Expand Down
23 changes: 23 additions & 0 deletions tests/test.amo-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ describe("amoClient.Client", function() {
expect(putCall.conf.formData.upload).to.be.equal("fake-read-stream");
// When doing a PUT, the version is in the URL not the form data.
expect(putCall.conf.formData.version).to.be.undefined;
// When no channel is supplied, the API is expected to use the most recent channel.
expect(putCall.conf.formData.channel).to.be.undefined;

expect(waitForSignedAddon.called).to.be.equal(true);
expect(waitForSignedAddon.firstCall.args[0])
Expand Down Expand Up @@ -171,13 +173,34 @@ describe("amoClient.Client", function() {
expect(call.conf.url).to.match(/\/addons\/$/);
expect(call.conf.formData.upload).to.be.equal("fake-read-stream");
expect(call.conf.formData.version).to.be.equal(conf.version);
// Channel is not a valid parameter for new add-ons.
expect(call.conf.formData.channel).to.be.undefined;

expect(waitForSignedAddon.called).to.be.equal(true);
expect(waitForSignedAddon.firstCall.args[0])
.to.be.equal(apiStatusUrl);
});
});

it("lets you sign an add-on on a specific channel", function() {
var conf = {
guid: "a-guid",
version: "a-version",
channel: "listed",
};
var waitForSignedAddon = sinon.spy(() => {});
this.client.waitForSignedAddon = waitForSignedAddon;

this.client._request = new MockRequest({
httpResponse: {statusCode: 202},
});

return this.sign(conf).then(() => {
expect(this.client._request.calls[0].conf.formData.channel)
.to.be.equal("listed");
});
});

it("handles already validated add-ons", function() {
var waitForSignedAddon = sinon.spy(() => {});
this.client.waitForSignedAddon = waitForSignedAddon;
Expand Down
10 changes: 10 additions & 0 deletions tests/test.sign.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ describe("sign", function() {
});
});

it("passes release channel to the signer", () => {
const channel = "listed";
return runSignCmd({
cmdOptions: {channel},
}).then(function() {
expect(signingCall.called).to.be.equal(true);
expect(signingCall.firstCall.args[0].channel).to.be.equal(channel);
});
});

it("passes JWT expiration to the signing client", () => {
const expiresIn = 60 * 15; // 15 minutes
return runSignCmd({
Expand Down

0 comments on commit 652a77c

Please sign in to comment.