comment 0

Introducing Repoman

Q: How do you clone 30 repositories from your personal GitHub accounts and 150 repositories from your organisation GitHub accounts in just one line?

A: repoman --github-user myuser1,myuser2 --github-org myorg1,myorg2 config && repoman init

Q: How do you execute a set of commands against all repositories in just one line?

A: repoman exec 'git stash && git pull --rebase && git stash apply'

I wrote Repoman back in 2011 and I’ve been using it ever since. It was my solution to resolve the annoyances involved with working on multiple machines, multiple OSes, multiple SCMs, and multiple repositories that depend on each other.

Repoman works against a list of repositories listed in .repoman.json file. You can use repoman config to generate a sample file, or add --github-user / --github-org flags to generate a list of GitHub repositories. This .repoman.json file can be placed in either the user home directory or the current directory (your workspace). The rest of Repoman commands like init, get, exec, etc, can then be run from that workspace directory.

Problem: switching between multiple laptop and desktop machines.

After working with multiple machines for a while, I ended up with some repositories existing on only some of the machines, never on all of them. And when I had to use a different machine, then I had to manually clone the repositories that don’t yet exist on that machine. One by one.

With Repoman, I only needed to maintain a .repoman.json file containing all repositories that I worked on, and stored it on a remote repository, then clone it over to all machines. From then on, I could simply repoman init to clone all repositories and repoman get to make sure I have the latest code of all repositories on each machine.

Problem: identifying unfinished changes.

Sometimes I code on the train, on the way to and from work. The thing about coding on the train is that often I had to stop not when I finished a piece of change, but when I arrived at my destination. This resulted in unfinished changes across several repositories on the machine that I used at the time, and I often forgot about those changes until the next time I worked on those repositories again.

With Repoman, I built a habit of running repoman changes to identify unfinished changes before working on anything else.

Problem: working with Git and Subversion repositories.

I had some repositories hosted on GitHub, Gitorious, Bitbucket, and Google Code. This of course meant that I had to switch between Git and Subversion commands.

With Repoman, I only needed to run its simple commands repoman init | get | changes | save | undo, which covers the majority of my coding activities (note: Repoman does not aim to cover all Git and Subversion commands). Those commands are mapped to its Git or Subversion equivalent accordingly.

Problem: executing a custom command on all repositories.

This used to annoy me so much. I had a number of repositories and from time to time I had to add the same file to all of them, let’s say a .travis.yml file or a .gitignore file.

With Repoman, I just needed create the file once at /tmp/file, then run repoman exec ‘cp /tmp/file . && git commit -am “Add file” && git pull –rebase && git push’. Voila, all repositories had the new file.

Problem: grouping repositories by project.

I often had to switch between projects, where each project consisted of several repositories. When I worked on a particular project, I would like to update its repositories to the latest. Ditto when I moved to the next project.

With Repoman, I created a config file for each project, e.g. .project1.json and .project2.json . Then I symlink-ed .repoman.json to the project I work on. Or if I often needed to switch between the projects, then I would use Repoman with custom config file: repoman -c .project1.json get .

Check out the README on GitHub for more usage examples, and npm install -g repoman away!

comment 0

How To Incorrectly Track The Progress Of A Project

The next time a manager asks you the percentage progress of a task, make sure you reply with a float rounded to 2 decimal places, and say it with full confidence.

Sometime in mid 2000s, the manager of a project I was working on had to take an emergency leave, so another manager filled in for him. It was an agile project, but somehow this other manager managed to come up with a magical Gantt chart for the rest of the project. The project was waterfalled!

The task in question was titled “Create HTML”, a bucket task to dump all UI related tasks from the look of it. Unfortunately I didn’t have the guts to answer with 83.62% back then, and I replied with a magical whole number divisible by 10 instead.

I know that there are still people believing in waterfall methodology to this day (yes, in 2013, believe it or not), and if it works for them, good on them. But whatever the methodology is, asking for a percentage is not going to give you the right idea of how the project is actually progressing.

It makes a good practice for generating magic numbers in your head though :).

comment 0

Voice-Controlled Lamp Using Ninja Blocks + MacBook

Here’s a video of my latest quick weekend hack, using voice to switch a lamp on and off:

Ok, so it’s actually a combination of Watts Clever + Ninja Blocks + Node.js + Automator + Speakable Items. Speakable Items takes the voice commands via MacBook’s internal microphone, then calls the Automator applications, which then runs a Node.js script (which output gets spoken by Automator applications), which then tells Ninja Blocks to actuate Watts Clever power socket.

Here’s how I set it up:

Configure Watts Clever remote RF signals on Ninja Blocks dashboard (/hattip: @james and @Jeremy over at the forum).

Create this simple Node.js script file. I saved it as rf433.js .

var ninjaBlocks = require('ninja-blocks'),
  app = ninjaBlocks.app({
    user_access_token: 'your-ninjablocks-token'
  });

app.devices({ device_type: 'rf433' }, function (err, devices) {
  var subDevices = app.utils.findSubDevice({ shortName: process.argv[2] }, devices);
  console.log('Switching ' + name);
  Object.keys(subDevices).forEach(function (key) {
    var subDevice = subDevices[key];
    app.device(subDevice.guid).actuate(subDevice.data)
  });
});

Create two Automator applications, one called ‘Lamp on’, the other ‘Lamp off’, each containing:

  • Run Shell Script, which is used to run rf433.js .
  • Speak Text, which is used to notify when device#actuate is about to be called (that’s the console.log('Switching ' + name); line from the above Node.js script).

These applications must be available from ~/Library/Speech/Speakable Items/ .

Configure the Mac’s System Preferences -> Accessibility -> Speakable Items on Lion and Mountain Lion, or System Preferences -> Speech on Snow Leopard.

Done.

Overall, this is just an experiment to prove that it can be done. Speakable Items is obviously _not_ Siri, so you can’t expect the same quality of speech recognition. And having to open a MacBook every time I want to use this is obviously too troublesome.

It would be awesome for Ninja Blocks to have / work with something like Ubi. Every home automation solution needs at least a voice or gesture based input mechanism :).

Note to self: I’m totally looking forward to the future where every single thing in the house is powered by renewable energy-based wireless electricity, each running a tiny low-powered Node.js server which talks to one another via HTTP. Life would be much more efficient!

Update (14/12/2014): Ninja Blocks’ Dan Friedman showed a demo video of Ubi integration with Ninja Sphere. W00t w00t!

comments 2

Jenkins Build Status On Ninja Blocks RGB LED

Nestor v0.1.2 is out and one of its new features is nestor ninja for monitoring Jenkins and displaying the latest build status on Ninja Blocks RGB LED device (if you have a block, it’s the ninja’s eyes).

Here’s a usage example:
export JENKINS_URL=<url>
export NINJABLOCKS_TOKEN=<token_from_https://a.ninja.is/hacking>
nestor ninja

Red for build failure, green for build success, yellow for build warning, and white for unknown status. The yellow light looks quite similar to green, and the white one does look blue-ish.

And the best place to run nestor ninja? On the block itself of course!

ssh ubuntu@ninjablock.local
apt-get install upstart
npm install -g nestor
cat /usr/lib/node_modules/nestor/conf/ninja_upstart.conf > /etc/init/nestor_ninja.conf
vi /etc/init/nestor_ninja.conf # and change JENKINS_URL and NINJABLOCKS_TOKEN values
shutdown -r now

Log messages will then be written to /var/log/nestor_ninja.log

comment 1

Akio Morita On Management

For the past few weeks, I’ve been reading Made In Japan, a story about Akio Morita‘s life and the first three decades since the founding of Sony Corporation.

I haven’t finished this book, but the last chapter titled ‘On Management’ was very interesting and it struck a chord with me. I’ve seen enough management decisions that were short sighted and proven to be wrong in the long run, throughout the 12 years I’ve been in the industry, and some of them could’ve been avoided or at least improved had the people behind them had better insights. I think everyone can learn a thing or two from these quotes…

I

pg 144
The most important mission for a Japanese manager is to develop a healthy relationship within the corporation, a feeling that employees and managers share the same fate.
pg 153
What we in industry learned in dealing with people is that people do not work just for money and that if you’re trying to motivate, money is not the most effective tool. To motivate people, you must bring them into the family and treat them like respected members of it.
pg 158
In the Japanese case, the business does not start out with the entrepreneur organizing his company using the worker as a tool. He starts a company and he hires personnel to realize his idea, but once he hires employees he must regard them as colleagues or helpers, not as tools for making profits.
pg 158
The investor and the employee are in the same position, but sometimes the employee is more important, because he will be there a long time whereas an investor will often get in and out on a whim in order to make a profit.
pg 162
At our company we are challenged to bring our ideas out into the open. If they clash with others, so much the better, because out of it may come something good at a higher level.
pg 163
If you and I had exactly the same ideas on all subjects, it would not be necessary for both of us to be in this company and receive a salary. Either you or I should resign in that case. It is precisely because you and I have different ideas that this company will run a smaller risk of making mistakes.

II

pg 165
Who could tell us better how to structure the work more than the people who are doing it?
pg 167
Go ahead and do what you think is right. If you make a mistake, you will learn from it. Just don’t make the same mistake twice.
pg 168
In Western countries, management lays off workers when a recession sets in. In Japan we just do not do that unless we have been brought to the direst point.
pg 170
And when a company is in trouble, it is the top management who take salary cuts before the lower-level employees.
pg 171
Despite the work of the Harvard Business School and others, and the increasing number of holders of advanced degrees in business administration, management is an elusive thing that cannot always be judged by next quarter’s bottom line. Management can look good on the bottom line but at the same time may be destroying the company by failing to invest in the future.
pg 171
To my mind, the performance of a manager is measured by how well that manager can organize a large number of people and how effectively he or she can get the highest performance from each of the individuals and blend them into a coordinated performance.
pg 173
In my view, profit doesn’t have to be so high, because in Japanese companies our shareholders do not clamor for immediate returns; rather they prefer long-term growth and appreciation. Of course we have to make a profit, but we have to make a profit over the long haul, not just the short term, and that means we must keep investing in research and development.
pg 174
I learned that an enemy of this innovation could be your own sales organization, if it has too much power, because very often these organizations discourage innovation.
pg 174
If you are nothing but profit-conscious, you cannot see the opportunities ahead. And where compensation is tied to profits, very often management will say, “Why should I sacrifice my own profits today for the guy who is going to follow me a few years from now?” Too often management will abandon work on a promising product because development costs seem to high. That can be short-sighted and can lead to the inability of a company to compete.

III

pg 186
People who are running a business ought to know their business very well. If the accountant had been in charge of our little company in 1946, our company would be a small operation making parts for the giants. Likewise, someone who is only a scientist is not always the best person to have at the helm.
pg 187
Whether the design, the technology, the merchandising, or the promotion was bad, the failure was a failure of management.
pg 187
Managers who do not have the capability to judge from a technical standpoint whether a product is feasible or not are at a tremendous disadvantage. I have always felt that the idea that professional managers can move from one industry to another is dangerous. Even being in the business and being knowledgeable about it is no guarantee that all the possible opportunities will be exploited and that mistakes will not be made.
pg 188
It is possible to have a good idea, a fine invention, but still miss the boat, so product planning, which means deciding how to use technology in a given product, demands creativity. Only with these three kinds of creativity — technology, product planning, and marketing — can the public receive the benefit of a new technology. And without an organization that can work together, sometimes over a very long period, it is difficult to see new projects to fruition.

The above came only from one chapter of the book, the rest of it was even more fascinating, the story of his childhood, the second World War, the people behind Sony, the technical and business sides of their product development, and the comparison between Japanese and Western philosophies.

I picked up this book after learning from Steve Jobs biography that both Akio Morita and Sony were inspirations to Steve and many people at Apple, I was curious, and now I understand why the legend is such an inspiration.

Note: If you’re a geek interested in reading the book, please also note that it contains lots of chapters on business and management.

Filed under: Etc
comment 0

Private NPM Registry Replicator Document

For my future reference and to help others trying to set up a private NPM registry which sits behind a [corporate] proxy and requires authenticated CouchDB admin access, here’s the replicator document that I ended up using:

{
   "_id": "registry",
   "source": "http://isaacs.iriscouch.com/registry/",
   "target": "registry",
   "user_ctx": {
       "name": "myadmin_username",
       "roles": ["_admin"]
   },
   "continuous": true,
   "owner": "myadmin_username",
   "proxy": "http://proxy:8080"
}

For those who are not familiar with CouchDB, the above is a document that needs to be created in _replicator database, so that the replication rule from public NPM registry to your private NPM registry can be persisted and runs continuously.

The key here is the user_ctx, owner, continuous, and proxy settings, which after several trials and errors, I managed to get them right with several clean full replication runs (always monitor CouchDB log during replication!).

Have a look at CouchDB Replication wiki page and this gist on the new replicator database (introduced in CouchDB v1.2.0) for explanation on those fields and how CouchDB replication works.

Tip:

If you tried to be smart by copying the design documents from the public NPM registry to your private NPM registry before replicating the documents, you would see some errors in CouchDB log file due to some rules in the latest design document that would fail the older documents. For example: module name must be in lower case, but there are old modules with name containing upper case letter(s).

My suggestion is to start from empty registry and public_users databases, then kick off the replication, and refresh the indices nearing the end of the replication, followed by compacting the databases and views to save some disk space.

Tip 2:

Public NPM registry sets require_valid_user = false in its CouchDB configuration file, which allows database read access without CouchDB admin authentication. If you set require_valid_user = true instead, then CouchDB will require authentication when you fetch any module (a document from CouchDB’s point of view). Unfortunately, as of NPM v1.2.15, there’s no authentication info on its fetch request, so you might find this monkey patch and this issue handy.

Tip 3:

And if you want to make the private NPM registry available over SSL:

  1. Generate self-signed SSL certificate
  2. Enable SSL on CouchDB via local.ini configurations
  3. Configure registry URL in .npmrc file to use https://
  4. npm install

If you get DEPTH_ZERO_SELF_SIGNED_CERT error, you might want to check this issue for workarounds.
If you’re connecting via a proxy, you might get ‘tunneling socket could not be established, cause=Parse Error’ error.

Tip 4:

If you are working behind an older proxy server, there’s a chance that your replication might fail because the proxy rejects lengthy GET request URL. To get around this problem, you need to patch MAX_URL_LEN with a larger value. /hattip: Adam Kocoloski

Tip 5:

If you are seeing this error:

[error] [<0.18564.6>] Uncaught server error: {insecure_rewrite_rule, <<”too many ../.. segments”>>}

You need to set this in CouchDB configuration .ini file:

[httpd]
secure_rewrites=false

comments 2

Roomba Twist Fix Attempt

A few months ago my awesome Roomba vacuum cleaner started dancing instead of cleaning the carpet like it’s supposed to. It reversed, then rotated to the right, left, right, left, all the time. I call it ‘doing the Twist’ (Chubby Checker’s).

The closest explanation I could find on the Internet regarding this problem was something that’s commonly known as Roomba Circle Dance. The problem is that there are a number of solutions which various people claimed to have fixed the problem and I didn’t know which one was applicable to my case.

I’ve tried cleaning the Roomba to no avail, so the next thing I tried was a solution with the most fun, i.e. replacing a couple of sensor emitters. This involved disassembling the Roomba and soldering those emitters, but that’s ok, I had some experience with making printed circuit board and soldering… like 17 years ago back in junior high school, surely it’s like riding a bike, right? (as I found out later, this statement is NOT true)

Here’s a video of my Roomba doing the Twist, plus some photos I took while disassembling and reassembling the Roomba followed by the result after the fix (bonus badass Streets of Rage soundtrack as the background music):

Some pictures of the Roomba 560 internals:

Glad that these wires didn’t get entangled at all.

On the other hand, these plastic snap locks totally tested my patience, not wanting to accidentally break any of them.

The white thingy on the right was the part I had to replace.

iRobot. Woot woot.

These simple red white and black wires made me unscrew and re-screw the bumper plate three times, just to get them positioned correctly.

Spoiler: It turned out that the sensor emitter wasn’t the cause of the problem, so I’m back to square one, but hey, at least I didn’t break the Roomba and managed to reassemble it. For now, I’m using Brian Pratt’s Roomote to control my Roomba from an iPhone and vacuum the carpet. I still need to figure out a way to return the Roomba to its original autonomous state.

comment 0

100 Kiva Loans Later

Today I made my 100th micro loan on Kiva.org . I joined Kiva in July 2007 and today I have $275 across 15 active loans, so I’m one of those people with a minimal fund who re-loan as soon as there’s enough repayment.

Here are some stats from my portfolio:

The interesting numbers here are the 1.62% delinquency rate and 0.68% default rate. Yep, default happens in microfinance world.

Portfolio distribution:

  • Gender: 65% female, 35% male.
  • 54 countries. Top 5: Tajikistan, Peru, Kyrgyzstan, Cambodia, Paraguay.
  • 13 sectors. Top 5: food, agriculture, retail, clothing, construction.
  • 73 field partners.

Map view of portfolio distribution, darker green = more loans.

Hey I just met you, this is crazy, but let’s make the world a better place, so join Kiva, maybe?

Filed under: Etc