Continuous Integration Setup with Jenkins for a Node.js Project – Part 2

In my previous post, we went over how to install Jenkins on your own server.  Now, we’ll set up all the basic configurations necessary in Jenkins and integrating it with GitHub.

Basic configurations in Jenkins

At this point, anybody who’s anybody can do things in our Jenkins server.  So let’s set up security in Jenkins.  We’re going to use a project-based matrix security which will allow us to see users and their permissions in a matrix format.

From the Jenkins dashboard:

  1. Click “Manage Jenkins”
  2. Click “Setup security” button on the top right (or alternatively, click on “Configure Global Security”).

In Configure Global Security page:

  1. Check “Enable security”
  2. Scroll to “Security Realm,” select “Jenkins’ own user database” and check “Allow users to sign up.”
  3. Click “Save” button

Next, we’ll set up an administrative account.

  1. Click “Sign up” in the top-right corner of the screen.
  2. Fill out the form (username, password, confirm password, full name, e-mail address)
  3. Click “Submit” button

Go back to the “Configure Global Security” page:

  1. Scroll to “Jenkins’ own user database,” un-check “Allow users to sign up.”
  2. Click “Save” button.  That means the “Sign up” link in the top-right corner of the screen will no longer show.
  3. Still on the same page, scroll to “Authorization” select “Project-based Matrix Authorization Strategy.”  A matrix diagram will appear.
  4. Fill out your username in “User/group to add” input box and click “Add”
  5. Your username will appear in the matrix.  Next to your username, check “Administer.”
  6. Click “Save” button.  You are now the admin!

Installing GitHub Plugin

In order to integrate with GitHub, we need to install the plugin.

  1. Click “Manage Jenkins” on the menu on the left.
  2. In the “Manage Jenkins” page, click “Manage Plugins.”
  3. In “Manage Plugins” page, click on the “Available” tab.
  4. Search for the “GitHub plugin” and checkmark it as it appears in the search results.  Click “Install without restart” and checkmark “Restart Jenkins when installation is complete and no jobs are running” if it requires a Jenkins restart.

Integrating with GitHub

  1. Click “Manage Jenkins”
  2. Click “Configure System”
  3. Scroll to “Jenkins location,” ensure that it has a public facing URL so that GitHub can push events to it.
  4. Click “Save” button.

Next, go to your account in GitHub.  You will need to generate a token to use with the GitHub API.

  1. Go to “Settings”
  2. Go to “Personal access tokens”
  3. Click “Generate new token”
  4. Token description can be something like “Jenkins”
  5. Ensure that repo, public_repo, gist, and user are all checked.  The rest are un-checked.
  6. Copy the generated token.

Go back to your Jenkins dashboard.

  1. Click “Configure System”
  2. Scroll to “GitHub Web Hook”
  3. Select “Let Jenkins auto-manage hook URLs
  4. Under “GitHub credentials,” fill out Username and OAuth token (the token you just copied from GitHub) and click “Test credential.”
  5. Click “Save” button

GitHub web hooks should work now.  More setup is needed for pulling from private repositories.

  1. Click “Credentials” in side menu
  2. Click “Global Credentials”
  3. Click “Add Credentials”
  4. Fill out the form for Username, Password, Description
    1. Kind: username with password
    2. Scope – Global
    3. Username – GitHub username
    4. Password – use your token
    5. Description – You can call it “<GitHub username> (GitHub)” and replace <GitHub username> with your GitHub username
  5. Click OK button

Congratulations, GitHub has been integrated into Jenkins!  In my next post, we’ll learn how to set up our first Node.js project in Jenkins.

Continuous Integration Setup with Jenkins for a Node.js Project – Part 1

For continuous integration for Node.js projects, there’s Travis and there’s Wercker.  But sometimes, you need to have your continuous integration tool hosted on your own server, and that is where Jenkins comes at an advantage.  It’s been around way before Travis and Wercker, and some of you may remember it as Hudson.  Also, Jenkins is free for both public and private repos.  Furthermore, it has tons of plugins such as unit testing, code coverage, Javascript linting/hinting, etc etc.  On the downside, Jenkins is the hardest to set up among the three, and that is why I wrote this post.  We’ll learn how to set up continuous integration with Jenkins for a Node.js project.  In the first part of this series, we will install Jenkins on our own server, whether it be on Heroku or your own web host or what have you.

There are 3 files to place on your server – jenkins.war, pom.xml, and Procfile, each of them being on the same directory level on your server.  The jenkins.war can be downloaded from the Jenkins site at https://jenkins-ci.org/.  The pom.xml is very basic and has what the server needs to run the war.  The Procfile contains the necessary commands to run the jenkins.war.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.example</groupId>
 <version>1.0-SNAPSHOT</version>
 <artifactId>example-ci</artifactId>
</project>

Procfile

# Only listen on http; disable ajp and https
web: java -jar jenkins.war --httpPort=$PORT --ajp13Port=-1 --httpsPort=-1

The files can be found at – https://github.com/melkybee/jenkins-ci.

Of course, this is just one way to install Jenkins on your server.  Alternate ways to install it on your server (i.e., Ubuntu/Debian) can be found at the Jenkins website, https://jenkins-ci.org/.

At this point, Jenkins should be installed and running on your server.  You’ll see the default Jenkins dashboard with the mustache guy at the top left.  In part 2, we’ll set up all the basic configurations necessary in Jenkins and installing and integrating with GitHub.

Nightwatch.js: Open new window and continue testing in new window

Using Nightwatch.js, let’s say you have a button that opens a new window, and you want to do some testing in that new window, such as checking the new window’s url.

  // open new window button
 .verify.visible('.open-new-window')
 .getAttribute('.open-new-window', 'href', function (link) {
 newWindowUrl = link.value;
 })
 .click('.open-new-window')
 .windowHandles(function(result) {
    var newWindow;
    this.verify.equal(result.value.length, 2, 'There should be 2 windows   open');
    newWindow = result.value[1];
    this.switchWindow(newWindow);
    this.verify.urlContains(newWindowUrl);
})

Notice the windowHandles() function that returns all the windows open in the session, and the switchWindow() function allows you to switch windows and target newWindow.  The context of “this” becomes the new window that you switched to.

Nightwatch.js: Check if a checkbox is checked

This test involves waiting for a checkbox to be visible, clicking on the checkbox, and then verifying that the checkbox has been checked.

The checkbox has the following HTML DOM:

<input type="checkbox" name="vote">

Here is the Nightwatch.js test:

.verify.visible('input[name="vote"]', 'The checkbox named vote is visible')
 .click('input[name="vote"]')
 .waitForElementVisible('body', 1000)
 .element('name', 'vote', function(response) {
 client.elementIdSelected(response.value.ELEMENT, function(result) {
 client.verify.ok(result.value, 'Checkbox is selected');
 });
 })

Scuba Chibi Postmortem #2: Data and Analytics

About two weeks ago on Thursday, June 18th, I released my game Scuba Chibi to the iOS App Store.  You may be wondering, how has it been doing since then?  I’m going to grab data from iTunes Connect App Analytics, Google Analytics, my blog, my Facebook page, and my Twitter.  Let’s see how this game held up day by day, week by week!


iTunes Connect App Analytics

This shows the number of app downloads

IOS Daily Downloads 6/19 - 6/28
IOS Daily Downloads 6/18 – 6/28
IOS Country Downloads 6/19 - 6/28
IOS Country Downloads 6/18 – 6/28

TOTAL APP DOWNLOADS (6/18 – 6/28): ~99-102 (?)


Google Analytics

New Users:

  • THU 6/18: 17
  • FRI 6/19: 37
  • SAT 6/20: 13
  • SUN 6/21: 3
  • MON 6/22: 2
  • TUES 6/23: 1
  • WED 6/24: 4
  • THURS 6/25: 0
  • FRI 6/26: 0
  • SAT 6/27: 3
  • SUN 6/28: 1
  • MON 6/29: 2
  • TUES 6/30: 15
  • WED 7/1: 4
  • THURS 7/2: ?

Active Users:

  • THU 6/18: 19
  • FRI 6/19: 39
  • SAT 6/20: 20
  • SUN 6/21: 11
  • MON 6/22: 7
  • TUES 6/23: 5
  • WED 6/24: 7
  • THURS 6/25: 2
  • FRI 6/26: 5
  • SAT 6/27: 5
  • SUN 6/28: 6
  • MON 6/29: 4
  • TUES 6/30: 19
  • WED 7/1: 6
  • THURS 7/2: ?
New Users / Active Users 6/18 - 7/2
New Users and Active Users 6/18 – 7/2

Countries:

  1. United States: 156 sessions (69.03%)
  2. China: 36 sessions (15.93%)
  3. Germany: 6 sessions (2.65%)
  4. Vietnam: 4 sessions (1.44%)
  5. Switzerland: 3 sessions (1.33%)
  6. United Arab Emirates: 2 sessions (0.88%)
  7. France: 2 sessions (0.88%)
  8. United Kingdom: 2 sessions (0.88%)
  9. Netherlands: 2 sessions (0.88%)
  10. Russia: 2 sessions (0.88%)
  11. Argentina: 1 session (0.44%)
  12. Canada: 1 session (0.44%)
  13. Spain: 1 session (0.44%)
  14. Indonesia: 1 session (0.44%)
  15. India: 1 session (0.44%)
  16. Philippines: 1 session (0.44%)
  17. Poland: 1 session (0.44%)
  18. Venezuela: 1 session (0.44%)
Countries 6/18 - 7/2
Countries 6/18 – 7/2

Top Device Models:

  • iPhone: 142 sessions (77.6%)
  • iPad: 41 sessions (22.4%)

User Engagement:

  • Screen Views: 285
  • Average Time On Screen: 00:02:33
  • Crashes: 0  😀
  • Events:
    • Ad Views: 500
    • Button Clicks:
      • Game Over Menu – Play Again: 367
      • Main Menu – Play Game: 240 
      • Main Menu – View Instructions: 98
      • Instructions Menu – Back to Main Menu: 94
      • Game Over Menu – Back to Main Menu: 52
      • Game Over Menu – Share Facebook: 4
      • Game Over Menu – Share Twitter: 2
    • Score View: Game Over Menu – LocalStorage Score: 147 (this is the number of times the high score was saved in the device’s local storage)
User Engagement 6/18 - 7/2
User Engagement 6/18 – 7/2

WordPress Blog – http://www.melkybee.com/blog

Best Views Ever: 197 on Friday, June 26

Blog Stats - June/July
Blog Stats – June/July

I couldn’t pull data that includes info from 6/18, but here is data from 6/25 – 7/5:

Blog Stats 6/29 - 7/5
Blog Stats 6/29 – 7/5

These are my all-time most popular blog posts:

Top 10 Most Popular Blog Posts
Top 10 Most Popular Blog Posts

Facebook Page – https://facebook.com/scubachibi

Page Likes

  • THU 6/18: 14
  • FRI 6/19: +30
  • SUN 6/21: +11
  • MON 6/22: +3
  • TUES 6/30: +2
    • TOTAL: 60 likes
Facebook Likes 6/18 - 7/2
Facebook Likes 6/18 – 7/2

Twitter – http://twitter.com/scubachibi

THU 6/18 – THU 7/2:

  • Tweets: 4
  • Tweet Impressions: 727
  • Profile Visits: 67
  • Mentions: 1
  • Followers: 43
  • Engagement Rate: 4.3%
  • Link Clicks: 12
  • Retweets: 8
  • Favorites: 12
Tweet Impressions 6/18 - 7/2
Tweet Impressions 6/18 – 7/2

 

Conclusion

What can we draw from this data?  Hrmmm…

  1. Well, I admit that I am no expert in marketing, and I spent $0 on marketing, so the numbers are not high and are also decreasing.  :'(  Lol.
  2. Also, although we saw some low numbers in New Users in Google Analytics, we still saw that there were Active Users each day, even on the days when New Users were at 0.
  3. Interestingly, if the data holds correct, there were more app downloads in China (according to iTunes Connect App Analytics), but more sessions in the U.S. (according to Google Analytics).
  4. Furthermore, the day after the release (Friday, 6/19) had the highest number of downloads, New Users, Active Users, and the highest increase in Facebook likes.  I think it had to do with people seeing the news about the app up to a day late, because the other Fridays don’t necessarily have any high numbers.
  5. There was a bit of an increase in New Users and Active Users on Tuesday, 6/30.  I am not sure how or why that happened.  I didn’t do any blog posts, Facebook posts, or tweets on that day.  Hrmmm!
  6. However, on Friday, 6/26, the Scuba Chibi blog was mentioned on the Phaser website, so that day I received 197 views, my best views ever for my blog!

In my next postmortem, I am going to write about the backstory of Scuba Chibi and how the game evolved into what it became.  It should be interesting from a game design perspective.  Stay tuned!

Android Icon and Splash Screen Sizes in Phonegap Build Config

In the config.xml:

<!-- Define app icon -->
<icon src="assets/icons/android/icon-36-ldpi.png" gap:platform="android" gap:qualifier="ldpi" />
<icon src="assets/icons/android/icon-48-mdpi.png" gap:platform="android" gap:qualifier="mdpi" />
<icon src="assets/icons/android/icon-72-hdpi.png" gap:platform="android" gap:qualifier="hdpi" />
<icon src="assets/icons/android/icon-96-xhdpi.png" gap:platform="android" gap:qualifier="xhdpi" />
<!-- Define app splash screen -->
<gap:splash src="ldpi.png" gap:platform="android" gap:qualifier="ldpi" />
<gap:splash src="mdpi.png" gap:platform="android" gap:qualifier="mdpi" />
<gap:splash src="hdpi.png" gap:platform="android" gap:qualifier="hdpi" />
<gap:splash src="xhdpi.png" gap:platform="android" gap:qualifier="xhdpi" />
<gap:splash src="fr-xhdpi.png" gap:platform="android" gap:qualifier="fr-xhdpi" />
<gap:splash src="portrait-xxhdpi.png" gap:platform="android" gap:qualifier="port-xxhdpi" />
<gap:splash src="landscape-xxhdpi.png" gap:platform="android" gap:qualifier="land-xxhdpi" />

 

But how do these translate to pixels?

Icons:

  • LDPI:
    • 36x36px
  • MDPI:
    • 48x48px
  • HDPI:
    • 72x72px
  • XHDPI:
    • 96x96px
  • XXHDPI:
    • 144x144px
  • XXHDPI:
    • 192x192px
  • 512 x 512 pixel – only used in Android Market; resized to various sizes

Splash Screens:

  • LDPI:
    • Portrait: 200x320px
    • Landscape: 320x200px
  • MDPI:
    • Portrait: 320x480px
    • Landscape: 480x320px
  • HDPI:
    • Portrait: 480x800px
    • Landscape: 800x480px
  • XHDPI:
    • Portrait: 720px1280px
    • Landscape: 1280x720px

References:

Scuba Chibi: What’s Next?

In as much as I would like to move on to my next project, there are still a few things I need to finish with Scuba Chibi:

1. Android Support

Android friends, I haven’t forgotten about you.  I’ve tried out the game on Android, but it appears that Ad Mob and Phaser.js are not working well together.  If I remove Ad Mob, then the game loads fine.  I might have to look into using another Ad Mob plugin that works in Phonegap, or maybe I’ll do some Javascript magic without a library.  We’ll see.  There are also some resizing issues that I would need to take care of.  The game does not resize to the screen for my Android tablet.  This will be fun…

2. Suggestions?

I’ve had some suggestions as far as leaderboards, more enemies, and more backgrounds.  All are possibilites!  🙂  Any other suggestions?  🙂

Stay tuned for my upcoming blog post when I do my Postmortem #2 – Data and Analytics!

Scuba Chibi Released to the iOS App Store!

Scuba Chibi is now available on the iOS App Store!  Check it out!

https://itunes.apple.com/us/app/scuba-chibi/id970197009?ls=1&mt=8

appstore

Other links:

Scuba Chibi website:  http://melkybee.com/scubachibi/

Facebook page:  https://www.facebook.com/scubachibi

Twitter:  https://twitter.com/scubachibi

SlideDB:  http://www.slidedb.com/games/scuba-chibi

Scuba Chibi Postmortem #1: The Technical Learnings

I can finally say that Scuba Chibi is done and will soon be released to the iOS App Store!

As simple as this game is, it actually took me a whole lot longer to finish than I had expected.  Most of it was due to finding the free time to actually work on it.  But it was a lingering item on my To-Do list and I wanted it done and over with so that I can move on to my next project.  🙂

Nevertheless, from a technical and artistic standpoint, it was fun to work on.  It was a game that I had made with Phaser, Javascript, and Phonegap Build.  I do Javascript for work and I have played around with some small Phaser examples, but I am new to Phonegap Build.  So there would be times when I ran into some issues here and there and after googling for some solutions, I could not find any, so I resulted in doing a bit of trial and error.  That is where my blog comes into play.  I’ve always thought that my blog would be my way to remind my future self on how to do things.  Because let’s face it, I have a bad memory :-).

So here is a compilation of technical things that I have learned along the way while making Scuba Chibi:

Also, here are some blog entries for the art that I made for the game:

So, look out for my game Scuba Chibi, coming soon to the iOS App Store! 😀

iOS Icons and Splashes in Phonegap Config

Here’s what I put in my Phonegap build config.xml.  Note that I’ve got an icon.png and splash.png at the root level.

<!-- Icon -->
<icon src="icon.png" />
<!-- iPhone / iPod Touch -->
<icon src="assets/icons/ios/icon.png" gap:platform="ios" width="57" height="57" />
<icon src="assets/icons/ios/icon@2x.png" gap:platform="ios" width="114" height="114" />
<!-- iPhone 6 / 6+ -->
<icon src="assets/icons/ios/icon-60@3x.png" gap:platform="ios" width="180" height="180" />
<!-- iPhone / iPod Touch -->
<icon src="assets/icons/ios/icon-60.png" gap:platform="ios" width="60" height="60" />
<icon src="assets/icons/ios/icon-60@2x.png" gap:platform="ios" width="120" height="120" />
<!-- iPad -->
<icon src="assets/icons/ios/icon-76.png" gap:platform="ios" width="76" height="76" />
<icon src="assets/icons/ios/icon-76@2x.png" gap:platform="ios" width="152" height="152" />
<!-- Settings Icon -->
<icon src="assets/icons/ios/icon-small.png" gap:platform="ios" width="29" height="29" />
<icon src="assets/icons/ios/icon-small@2x.png" gap:platform="ios" width="58" height="58" />
<!-- Spotlight Icon -->
<icon src="assets/icons/ios/icon-40.png" gap:platform="ios" width="40" height="40" />
<icon src="assets/icons/ios/icon-40@2x.png" gap:platform="ios" width="80" height="80" />
<!-- iPad -->
<icon src="assets/icons/ios/icon-72.png" gap:platform="ios" width="72" height="72" />
<icon src="assets/icons/ios/icon-72@2x.png" gap:platform="ios" width="144" height="144" />
<!-- iPad Spotlight and Settings Icon -->
<icon src="assets/icons/ios/icon-50.png" gap:platform="ios" width="50" height="50" />
<icon src="assets/icons/ios/icon-50@2x.png" gap:platform="ios" width="100" height="100" />
<!-- Splash screen -->
<gap:splash src="splash.png" />
<!-- iPhone and iPod touch -->
<gap:splash src="assets/splash/ios/Default-iphone.png" gap:platform="ios" width="320" height="480" />
<gap:splash src="assets/splash/ios/Default@2x-iphone.png" gap:platform="ios" width="640" height="960" />
<!-- iPhone 5 / iPod Touch (5th Generation) -->
<gap:splash src="assets/splash/ios/Default-568h@2x-iphone.png" gap:platform="ios" width="640" height="1136" />
<!-- iPhone 6 -->
<gap:splash src="assets/splash/ios/Default-667h.png" gap:platform="ios" width="750" height="1334" />
<gap:splash src="assets/splash/ios/Default-736h.png" gap:platform="ios" width="1242" height="2208" />
<gap:splash src="assets/splash/ios/Default-Landscape-736h.png" gap:platform="ios" width="2208" height="1242" />
<!-- iPad -->
<gap:splash src="assets/splash/ios/Default-Portrait-ipad.png" gap:platform="ios" width="768" height="1024" />
<gap:splash src="assets/splash/ios/Default-Landscape-ipad.png" gap:platform="ios" width="1024" height="768" />
<!-- Retina iPad -->
<gap:splash src="assets/splash/ios/Default-Portrait@2x-ipad.png" gap:platform="ios" width="1536" height="2048" />
<gap:splash src="assets/splash/ios/Default-Landscape@2x-ipad.png" gap:platform="ios" width="2048" height="1536" />