Using Grunt to kick Phonegap
Tagged with: phonegap, development, windgazer, bitbucket2phonegap
Continuing to build on our previous article that dealt with versioning of our source and release code, this article will reveal how to give Phonegap a kick in the but and get it into action, without having to logon to the website manually.
Revised on 2015-04-12, discovered blogged http-task was incomplete
The Phonegap API
Maybe not the first thing people would think of checking but PhoneGap Build does have an
API. Essentially, it allows you to do anything you would usually do on their website,
using some sweet REST
calls and sharing information using JSON
. They've kept it
simple, so simple in fact that it uses basic authentication. Perhaps not the most secure
way of dealing with authentication, but it makes what I'm about to show you a heck of a
lot easier.
First of, have read on the API documentation about updating an existing app. Even as it states it is for 'updating' an app, it will also cause a rebuild. Which is nice, as it is nice and easy. Let's go ahead and test it, shall we?
Basic testing in the browser
You'll need to get your app id from the https://build.phonegap.com/apps overview.
It's right there, top-left of your project information :) I've blacked it out in my screenie, not quite ready to share all of my secrets with you. Anyways, armed with that id we can now complete our url! So just open it up in your browser:
https://build.phonegap.com/api/v1/apps/[your app id goes here ;)]
The phonegap api will now ask for username and password, just use those that you use for the normal web interface. If you did it all correct, you should be presented with a screen full of JSON, outlining all info Phonegap has on your project.
Taking a leap back to Grunt
Armed with your app id
, username
and password
we should start looking back at grunt
now. For starters, I'd like to introduce you to grunt-http, a plugin that keeps
things streight-forward.
npm install grunt-http --save-dev
We're going to use grunt-http
to do our earlier request again, only this time we'll use
a put
request and we'll also inline the username and password. There's one tricky bit
here, Phonegap Build uses emails as a username and that messes a bit with the url syntax
for this case. Make sure that you escape the @
in your username with %40
.
http: {
kickPhonegap: {
options: {
url: "https://[name]%40[domain]:[password]@build.phonegap.com/api/v1/apps/[id]",
method: "PUT"
},
dest: "target/release/phonegap.response.json"
}
}
Now, if you run this task on grunt
grunt http:kickPhonegap
And update your apps overview page, you'll notice that the last build is set to 1 minute ago! At this point I was quite excited. Although I really don't like putting my password into a url, or even worse, into a repository...
Creating a basic auth 'hash'
We're going to do a little prep-work again. Using the javascript console of your browser, run the following script:
btoa("[username]:[password]");
For instance btoa( "dodo@extinct.com:d0d0XL" )
would end up looking like
ZG9kb0BleHRpbmN0LmNvbTpkMGQwWEw=
. You should copy that hash unto your clipboard. It's
only BASE64 encoded, so that's in no way safe for the repository. Instead we're going to
save the hash in a file in our user directory! Use any method you have at your disposal
to create a file in your user directory and put the hash into it. An example command for a
*
nix flavoured OS is:
printf [hash]>~/.phonegap.auth
I'm also working towards having a common Gruntfile.js
for all of my projects, so I've
moved my app id to the package.json
file in the info.id
custom property.
Using headers to hide our Auth request
So, now we've prepped a few things we can get away with a slightly more advanced http request. Instead of putting our basic auth information on the url, we can hide it away in a pair of headers.
http: {
kickPhonegap: {
options: {
url: "https://build.phonegap.com/api/v1/apps/<%= pkg.info.id %>",
method: "PUT",
headers: {
"Authorization": "Basic " +
"<%= grunt.file.read( process.env[\"HOME\"] + \"/.phonegap.auth\") %>",
"Accept": "*/*"
},
form: {
data: {
pull: true
}
}
},
dest: "target/release/phonegap.response.json"
}
}
To be fair, I've never tested this on a windows machine, so let me know if it works, or not! And if not, what you might have done to make it work anyways :)
grunt http:kickPhonegap
The nice thing is by reading the file only when we actually run the kickPhonegap task, we
also make sure that anybody that just wants to work on the project without interacting
with Phonegap, doesn't have to worry about not having that auth
file.
You can verify you've done your changes correctly on the relevant commit of my reference repository.
Kicking Phonegap TL;DR
Create a username/password hash using btoa("[username]:[password]");
in your browser
console. Paste the result into a file named ~/.phonegap.auth
.
Find your app-id on the Phonegap Build apps overview and put it into your
package.json
under the info.id
custom property.
Install grunt-http and copy past the following config:
http: {
kickPhonegap: {
options: {
url: "https://build.phonegap.com/api/v1/apps/<%= pkg.info.id %>",
method: "PUT",
headers: {
"Authorization": "Basic " +
"<%= grunt.file.read( process.env[\"HOME\"] + \"/.phonegap.auth\") %>",
"Accept": "*/*"
}
},
dest: "target/release/phonegap.response.json"
}
}
Now just run:
grunt http:kickPhonegap
Next
In the next chapter I'll be throwing in a bit of bonus content. Phonegap doesn't use
the version in your git-tags, or your package.json :( So, we'll set up our config.xml
to
be a template, with it's relevant parts being filled in using a filtered copy. While at it
let's also try and add some json to our kickPhonegap process so that we can trigger live
and development
builds properly.