Automate your chrome extension deployment in minutes!

April 02, 2018 0 Comments

Automate your chrome extension deployment in minutes!

 

 

Building a chrome extension is fun! But deployment is a bit tedious as it requires few manual processes. In this post, I’ll Show you how to automate the build, upload and publish process of your chrome extension in a matter of few minutes 🔥🔥

First thing first, thanks for the authors of the following NPM packages which I will be using to automate things.

Let’s get started. One of the perfect places for automating the deployment process is the CI/CD pipelines. I will be demoing using the GitLab’s built-in CI environment with the help of gitlab-ci.yml file. The same can be applied to any CI services for Github like Travis, Circle-CI etc.,

As a chrome extension authors, you may be aware of the following release steps.


  • zipping the extension folder (make sure you bump the manifest version)

  • uploading to chrome web store.

  • publish the uploaded version of the extension.

I'm going to code the automating script using node. So, let's create a node file (deploy.js) in the root directory to invoke it from the CI environment using gitlab-ci.yml file.

zipping the extension folder:

Using the zip-folder package, zipping will be only a command away!

const zipFolder = require('zip-folder'); 
let folderName = 'path/to/folder'; // I too hate placeholders! will be attaching a sample file at the end of this writeup
let zipName = '/path/to/archive.zip'; zipFolder(folderName, zipName, function(err) { if(err) { console.log('oh no! ', err); } else { console.log(Successfully zipped the </span><span class="p">${</span><span class="nx">folderName</span><span class="p">}</span><span class="s2"> directory and store as </span><span class="p">${</span><span class="nx">zipName</span><span class="p">}</span><span class="s2">); // will be invoking upload process }
});

Woohoo! You Done zipping your extension 🤟🏻Add this to your deploy.js file.

uploading to chrome web store:

Here comes the another package, chrome-webstore-upload-cli. With the help of this package, we can upload the zipped extension to the chrome web store.

Install the package on your extension project using the command:

npm install --save-dev chrome-webstore-upload-cli

To upload the file to webstore, this package needs client ID, client secret and refresh token of your extension project. If you are not familiar with those terminologies, don't worry. To use the webstore APIs, Google needs some identifiers and credentials to authorize you and identify your extension.

To get all the three credentials, follow the instruction mentioned here. The package author, Andrew did a great job of adding this guide.

[Take few moments and generate all the three ids and credentials...]

Once you have done with getting all those ids and credentials, store those credentials in your CI environment variable (GitLab) or other CI services' environment variable, like Travis' env variable or circleci env variable or anything of your choice. ⚠️ Please don't check-in these variables into your codebase as these are your API credentials (like your password!)

Now, we can now start to upload the zip file to webstore using the command:

webstore upload --source extension.zip --extension-id $EXTENSIONID --client-id $CLIENTID --client-secret $CLIENTSECRET --refresh-token $REFRESHTOKEN

In the node file, you can execute this commands using childprocess. This command has to be invoked on the success of the zipping process.

// getting all the credentials and IDs from gitlab-ci.yml file 
let REFRESH
TOKEN = process.env.REFRESHTOKEN; let EXTENSIONID = process.env.EXTENSIONID;
let CLIENT
SECRET = process.env.CLIENTSECRET;
let CLIENT
ID = process.env.CLIENTID; let uploadCmd = webstore upload --source </span><span class="p">${</span><span class="nx">zipName</span><span class="p">}</span><span class="s2"> --extension-id </span><span class="p">${</span><span class="nx">EXTENSION_ID</span><span class="p">}</span><span class="s2"> --client-id </span><span class="p">${</span><span class="nx">CLIENT_ID</span><span class="p">}</span><span class="s2"> --client-secret </span><span class="p">${</span><span class="nx">CLIENT_SECRET</span><span class="p">}</span><span class="s2"> --refresh-token </span><span class="p">${</span><span class="nx">REFRESH_TOKEN</span><span class="p">}</span><span class="s2">; exec(uploadCmd, (error, stdout, stderr) => { console.log(stdout: </span><span class="p">${</span><span class="nx">stdout</span><span class="p">}</span><span class="s2">); console.log(stderr: </span><span class="p">${</span><span class="nx">stderr</span><span class="p">}</span><span class="s2">); if (error ! null) { console.log(error while executing the command: </span><span class="p">${</span><span class="nx">error</span><span class="p">}</span><span class="s2">); } else { console.log('Successfully Uploaded the zip to chrome web store'); // will be invoking publish process }
});

The process.env thing is a way to pass the variable from gitlab-ci.yml file to the node process. Will be showing how it works later in this post.

The above command will upload the mentioned zip to the web store as draft. You can check out the draft at your developer console. Again, make sure you bump the manifest version. Otherwise, the command will fail to upload the zip!

Once we successfully uploaded the zip to webstore, we can publish it using the webstore package's publish command:

webstore publish --extension-id $EXTENSIONID --client-id $CLIENTID --client-secret $CLIENTSECRET --refresh-token $REFRESHTOKEN

Like the upload command, we can invoke the publish command the same way. Make sure you call the publish command on the success of upload command.

 let publishCmd = webstore publish --extension-id </span><span class="p">${</span><span class="nx">EXTENSION_ID</span><span class="p">}</span><span class="s2"> --client-id </span><span class="p">${</span><span class="nx">CLIENT_ID</span><span class="p">}</span><span class="s2"> --client-secret </span><span class="p">${</span><span class="nx">CLIENT_SECRET</span><span class="p">}</span><span class="s2"> --refresh-token </span><span class="p">${</span><span class="nx">REFRESH_TOKEN</span><span class="p">}</span><span class="s2">; exec(publishCmd, (error, stdout, stderr) => { console.log(stdout: </span><span class="p">${</span><span class="nx">stdout</span><span class="p">}</span><span class="s2">); console.log(stderr: </span><span class="p">${</span><span class="nx">stderr</span><span class="p">}</span><span class="s2">); if (error ! null) { console.log(exec error: </span><span class="p">${</span><span class="nx">error</span><span class="p">}</span><span class="s2">); } else { console.log('Successfully published the newer version'); } }); 

You know something? you have done automating the extension deployment process 😍Let's put together all the snippets to give birth to the node process file - deploy.js

As I promised, sample deploy.js file is as follow! Keep it as a reference. Get your hands dirty with code 💻

hi-fi 🙏

Now it’s time to invoke those script from the gitlab-ci.yml file. This is a sample ci file I'm using (to be invoked in GitLab CI environment)

image: node:6.10.3 beforescript: - yarn stages: - deployExtension deployExtension: stage: deployExtension only: - master #to be invoked only on master merge script: - npm run build - CLIENTID=${CLIENTID} CLIENTSECRET=${CLIENTSECRET} EXTENSIONID=${EXTENSIONID} REFRESHTOKEN=${REFRESHTOKEN} node ./deploy.js 

the credentials (${CLIENTID}, ${CLIENTSECRET}, ${EXTENSIONID}, ${REFRESHTOKEN}) will be pulled from the environemnt variable (in case of GitLab) and passed to the deploy.js file (present in the root directory) as environment variable. Those varables can be accessed using process.env (say, to retrieve CLIENTID in node process, use process.env.CLIENTID)

PS: you can completely automate this without using a separate node file (deploy.js) with the help of gitlab-ci.yml file alone. But for our convenience and for better error handling, we can go with a separate node file 😉

I personally love building extensions. But definitely not a PRO! Reach me out if you have any queries with getting started. The package, baby-chrome of mine should help you scaffolding a chrome extension and help get up and running in minutes.


Tag cloud