Publishing Node.js Module To Ivy Repository

Let me guess what you’re going to say in 3… 2… 1…

WTF??? Why would anyone want to do that?

Right?

Some of us don’t have the luxury of a local NPM repository, while some others have their delivery pipeline tightly integrated to an Ivy repository.

So, for those few who are stuck with the unholy union of Node.js and Apache Ivy, you can publish your Node.js module to an Ivy repository using Bob. Here’s how:

Update (23/08/2012): The instruction below is for Bob v0.4.x or older. If you’re using Bob v0.5.0, please scroll further down for the updated instruction.

1. Create an ivy.xml file template in your Node.js module project directory

<?xml version="1.0" encoding="ISO-8859-1"?>
<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
    <info organisation="com.company" module="modulename" status="integration" revision="${version}" publication="${now('yyyymmddHHMMss')}"/>
    <configurations>
        <conf name="default" visibility="public" description="..." extends="runtime,master"/>
    </configurations>
    <publications>
        <artifact name="modulename" type="tar.gz" conf="default"/>
    </publications>
</ivy-module>

2. Create a .bob.json file in your project directory, specifying ivy.xml location and details of the Ivy repository server

{
  "packagemeta": {
    "dir": "path/to",
    "file": "ivy.xml"
  },
  "template": [
    "path/to/ivy.xml"
  ],
  "deploy": {
    "user": "username",
    "key": "path/to/keyfile",
    "host": "hostname",
    "port": portnumber,
    "dir": "/path/to/ivy/repo/${name}/${version}"
  }
}

3. Run Bob

bob template package package-meta ssh-mkdir deploy (yup, this could’ve been simpler, on my TODO list)

This will create /path/to/ivy/repo/modulename/version/ directory with the following files:

  • modulename.tar.gz
  • modulename.tar.gz.md5
  • modulename.tar.gz.sha1
  • ivy.xml
  • ivy.xml.md5
  • ivy.xml.sha1

This module can then be referenced as com.company.modulename, and used just like any other artifact using Ivy.

If the repository is accessible via HTTP, then you can also specify the Ivy artifact as a dependency of another Node.js module in its package.json file:

{
  "dependencies": {
    "modulename": "http://ivyserver/com/company/modulename/version/modulename-version.tar.gz",
  }
}

Update (23/08/2012): The instruction below is for Bob v0.5.x or newer.

1. Create an ivy.xml file template in your Node.js module project’s root directory
If you’re upgrading from Bob v0.4.x, all you need to do is remove the $ from the parameter syntax.

<?xml version="1.0" encoding="ISO-8859-1"?>
<ivy-module version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">
    <info organisation="com.company" module="modulename" status="integration" revision="{version}" publication="{now('yyyymmddHHMMss')}"/>
    <configurations>
        <conf name="default" visibility="public" description="..." extends="runtime,master"/>
    </configurations>
    <publications>
        <artifact name="modulename" type="tar.gz" conf="default"/>
    </publications>
</ivy-module>

2. Create a .bob.json file in your project directory, specifying ivy.xml location and details of the Ivy repository server
If you’re upgrading from Bob v0.4.x, you need to move ivy.xml to the project’s root directory, and modify .bob.json by removing packagemeta, change template structure, renaming deploy to publish, adding publish.type: ivy .

{
  "template": [".bob/artifact/ivy.xml"],
  "publish": {
    "type": "ivy",
    "user": "username",
    "key": "path/to/keyfile",
    "host": "hostname",
    "port": portnumber,
    "dir": "/path/to/ivy/repo/${name}/${version}"
  }
}

3. Run Bob
If you’re upgrading from Bob v0.4.x, simply replace template package package-meta ssh-mkdir deploy targets, with package publish

bob package publish

This will create /path/to/ivy/repo/modulename/version/ directory with the following files:

  • modulename.tar.gz
  • modulename.tar.gz.md5
  • modulename.tar.gz.sha1
  • ivy.xml
  • ivy.xml.md5
  • ivy.xml.sha1

This module can then be referenced as com.company.modulename, and used just like any other artifact using Ivy.

If the repository is accessible via HTTP, then you can also specify the Ivy artifact as a dependency of another Node.js module in its package.json file:

{
  "dependencies": {
    "modulename": "http://ivyserver/com/company/modulename/version/modulename-version.tar.gz",
  }
}

Despite my dislike towards XML configuration files, Ivy has worked just fine all these years and I’ve been using it to store various types of artifacts. Even though its main popularity is within the Java community, you can store pretty much anything there (YMMV).

Bob itself is still at an early stage, there are lots of things I want to improve. I just need that mythical spare time :).