Where is my code running?

This is the second in a series of blog posts looking at topics raised by our resin.io users drawn from our discussion platform, Resin Talk.

Today's topic is the customisation of builds depending on where code is being built. The inspiration – Disabling resin-specific scripts in your package.json – discusses how to adapt a node.js project to detect whether a script is being run locally, on our build server, or on the device itself.

The Device?

The easiest condition to test for is whether code is running on the device itself - we define an environment variable 'RESIN', if this variable is present, you're running on a resin device (assuming of course you haven't arbitrarily defined it in your local environment!)

A simple means of doing this using a bash script would be:

#!/bin/bash

if [ ! -z "$RESIN" ]; then  
    echo Running on resin device!
else  
    echo Running elsewhere!
fi  

The Build Server?

The query raised in the Resin Talk thread was how to determine whether the code was running on our build server or not.

Firstly, a quick aside as to how native node.js projects are built in resin – our infrastructure revolves around building a Docker Image on our build server and pushing this to your devices.

When you push code, we detect whether or not it has a Dockerfile at the root. If it does, we use this to build your image (the image has to be based on a resin image, though it's possible to build your own.) If the image doesn't contain a Dockerfile but does contain a package.json file our server detects this, and selects an appropriate image containing node tools for your architecture, generating a Dockerfile as it runs.

The project discussed in the Resin Talk thread uses node and a preinstall script - this is a typical scenario where it matters whether the install script is running on the builder server or not, as a local development environment will likely be x86_64 without GPIO whereas a remote target will most probably be ARM with GPIO, and attempting to install tools for the latter on the former will definitely slow things down and more than likely fail.

Sadly this is less easily resolved than it might seem - it is tricky to insert environment variables into the build itself so we aren't able to provide a 'RESIN_BUILD_SERVER' variable here, however there are a couple of methods which can be used to determine whether your code is running there:

Architecture

If you are targeting a foreign architecture, for example ARM (whether v6hf or v7), the following will determine which architecture you are running under:

if [[ ! "$(uname -m)" =~ ^arm ]]; then  
    echo "Not arm." >&2
    exit 1
fi  

(This script assumes you want the script to abort if it is not run on the builder.) Obviously this is not ideal if the build architecture is the same as the machine you'd like to differentiate between, however the use case is often that you need to do architecture-specific things so this is obviously very useful for that.

Debian Non-Interactive

Our Debian images are built with 'DEBIAN_FRONTEND=noninteractive' set; this option allows for unattended installations (obviously this is what we require on our build server.)

Given this is the case an alternative to checking architecture is to check this variable. Assuming you want your script to exit in case of running outside of the build server environment, the following will suffice:

if [ "$DEBIAN_FRONTEND" != "noninteractive" ]; then  
    echo "Attended installation, probably not build servers." >&2
    exit 1
fi  

Have questions, or just want to say hi? Find us on our community chat.

comments powered by Disqus
Terms of Service | Privacy Statement | Master agreement | Copyright 2019 Balena | All Rights Reserved