Twelve-Factors in practice - Part II - Dependencies

Explicitly declare and isolate dependencies

Triangle

Twelve-Factors in practice - Part II - Dependencies

Explicitly declare and isolate dependencies

The second of a 12 part series on how to use Twelve-Factor App in practice. This entry is written in collaboration with my good friend and (twice/double) former coworker Mycha de Vrees.

We will be implementing https://12factor.net/dependencies based on my/our combined experience on how to deal with dependencies.

The takeaway of this post is defined your dependencies as specify as strict as possible. Yes, in most cases pinning major and minor version should be enough but pinning the patch version should make sure of this.

LanguagePackage manager
Godep
NodeJSnpm / yarn
PHPComposer
PythonPIP
RubyBundler

Python

Python uses a requirements.txt file which is managed by PIP

Installing PIP

curl --silent --show-error https://bootstrap.pypa.io/get-pip.py | sudo python

# Specific version of python
curl --silent --show-error https://bootstrap.pypa.io/get-pip.py | sudo python2

curl --silent --show-error https://bootstrap.pypa.io/get-pip.py | sudo python3

curl --silent --show-error https://bootstrap.pypa.io/get-pip.py | sudo python3.6

More on install options can be found at https://pip.pypa.io/en/stable/installing/

Listing installed

Listing all installed versions is done with pip freeze

Please note that this is not advised outside of a virtual environment. For example; you’ll have docker-compose installed (via pip) globally, handy tool, but not specific to a project and not a dependency of your working project. Running pip globally, i.e. outside of a specific environment will include such tools in your requirements.

pip freeze > requirements.txt

Requirements.txt

Below is a short example external links are based on Git, a full list can be found at https://pip.readthedocs.io/en/1.1/requirements.html#requirements-file-format

# default
MyPackage

# pinned version options
MyPackage==3.0
MyPackage>=3.0
MyPackage<=4.0
MyPackage>=3.0<=4.0

# 
MyPackage==3.0 [PDF]

# GIT
-e git://git.myproject.org/MyProject.git#egg=MyProject
-e git+http://git.myproject.org/MyProject/#egg=MyProject
-e git+ssh://git@myproject.org/MyProject/#egg=MyProject

# GIT - Specific branch/tag/commit
-e git://git.myproject.org/MyProject.git@master#egg=MyProject
-e git://git.myproject.org/MyProject.git@v1.0#egg=MyProject
-e git://git.myproject.org/MyProject.git@da39a3ee5e6b4b0d3255bfef95601890afd80709#egg=MyProject

NodeJS

NodeJS uses NPM (or Yarn) to manage dependencies, this is done via package.json to define it and package-lock.json to pin it.

package.json vs package-lock.json

The major difference, in short, is that package.json allows version ranges, ^, >=, <=, and package-lock.json pins it to a specific version.

Lets say I have a requirement with version ^5.1.0 and next week 5.1.1 is released package.json allows us to both multiple version while package-lock.json will make sure person A this week will install the same version as person B next week.

The lock file will be generated by npm install if it is not present.

npm

npm is a package manager for the JavaScript programming language. It is the default package manager for the JavaScript runtime environment Node.js.

yarn

Yarn is an alternative to the default npm manager. Yarn is created by Facebook due to issues with consistency, security and speed.

package.json example

Within the file, amongst a lot of other things, you’ll find the following; dependencies and devDependencies the difference should be fairly simple.

Dependencies for stuff you need in the final product / in production, devDependencies for the rest of the stuff you need while developing (and/or testing).

{
    "dependencies": {
      "vue": "^2.5.2"
    },
    "devDependencies": {
      "autoprefixer": "^7.1.2",
      "babel-core": "^6.22.1"
    }
}

See also