Creating a Hello World Resource Type for Concourse

Written on February 20, 2021

What is Concourse?

Concourse is an open-source continuous thing-doer.

Concourse is a CI/CD tool that is configurable with a simple YAML file.

screenshot3

The Walkthrough

Pre-Requisities

Follow the steps on https://concourse-ci.org/ to install Fly & Concourse. If this is your first time checking out Concourse, I would highly recommend reviewing the tutorials & docs they have posted.

Exploring a basic Resource Type

You can follow along using or (fork my repo)[https://github.com/thehandsomezebra/concourse-resourcetype-helloworld].

A concourse resource_type works well using a minimum of 4 files:

+-- resource
|   +-- check
|   +-- in
|   +-- out
+-- Dockerfile

Each of the scripts are required to have the output of its execution in json appropriate format.

Let’s walk thru each file at a high level and get everything set up!


check

The check file is going to check for new versions.

The check script we will report back a message of Hello World.

#!/bin/bash
set -eu
set -o pipefail
echo '[{ "revision": "N/A",  "message": "The check script says Hello World!" }]'

in

This fetches the given resource.

For the In script, let’s add some metadata. This metadata will be viewable in a few places in the pipeline.

#!/bin/bash
set -eu
set -o pipefail
echo '{ "version": { "revision": "N/A", "message": "The in script version message says Hello World" }, "metadata": [{ "name": "message", "value": "The in script metadata message says Hello World." }] }'


out

For the Out script, let’s get a little more complex. We’ll be getting a variable greeting from the pipeline, and let’s echo it out. We’ll be using jq to grab it from the params that get passed via the pipeline.

#!/bin/bash
echo '{ "version": { "revision": "N/A", "message": "The out script version message says Hello World" }, "metadata": [{ "name": "message", "value": "The out script metadata message says Hello World." }] }'

set -e -u

exec 3>&1 # make stdout available as fd 3 for the result
exec 1>&2 # redirect all output to stderr for logging

echo "Echo says hi from the out script!" >&2

source=$1

if [[ -z "$source" ]]; then
  echo "usage: $0 <path/to/source>"
  exit 1
fi

# for jq
PATH=/usr/local/bin:$PATH

export TMPDIR=${TMPDIR:-/tmp/rclone}
mkdir -p "${TMPDIR}"

payload=$(mktemp "$TMPDIR/resource-request.XXXXXX")
cat > "$payload" <&0

greeting=$(jq -r '.params.greeting // ""' < "$payload")
echo "Param greeting says: $greeting" >&2

Dockerfile

This Dockerfile will be short and sweet.

  • Spins up a tiny Alpine Linux instance
  • Loads in bash & jq
  • Adds in our script files to the /opt/resource folder
  • Makes those files executable
  • Specifies that we will be running bash in root
FROM alpine:3.13

RUN apk add --update --upgrade --no-cache bash

RUN apk update \
    && apk upgrade \
    && apk add --update bash curl unzip jq

ADD resource/ /opt/resource/
RUN chmod +x /opt/resource/*

WORKDIR /
ENTRYPOINT ["/bin/bash"]

One last file to get it running: the pipeline yaml file

This file does not need to be in the docker - but it’s inluded in my repo, so you can follow along.

Create a file called hello-pipeline.yml

resource_types:
- name: helloworld
  type: docker-image
  source:
    # set repo of your helloworld resource
    #repository: Your-Docker-Acct/Your-Docker-Repository
    ## or use my helloworld resource
    repository: thehandsomezebra/concourse-test

resources:
- name: helloworld
  type: helloworld

jobs:
- name: hello-job
  plan:
  - get: helloworld
  - put: put-helloworld
    resource: helloworld
    inputs:
         - helloworld
    params:
      greeting: "Hey y'all!"

This is going to create a new pipeline called hello-job that will get the in and put the out.

Get it running

Following the steps above, create a github repo (or fork mine) & create a docker hub repo. It’s fast to connect your github repo to docker and even set it up to autobuild (learn more about that here)).

Once your repo is ready in Docker Hub, let’s start the concourse pipeline by using this line

Let’s start the hello-world pipeline! Run the following in your terminal.

fly -t ci set-pipeline -c hello-pipeline.yml -p hello-world

ci will be the name of your target (if you followed a the tutorial, it might be named tutorial or example)

If we look at the pipeline diagram, we can also see the result of the check step in the box with the dashed lines (dependency - trigger).

screenshot2

Checking our job, we can see our messages in each of the stages.

screenshot1

There’s a lot you can do creating your own resource types for concourse - be sure to check out the Resource Types catalog, contribute to the community and get assistance (or lurk thru questions that have been already answered) in Discord in the #resource-types channel.

Note: I’m not affiliated with Concourse - I am just a nerd that is fascinated by the continuous thing-doer continuously doing things.


Sources:

  • https://concourse-ci.org/implementing-resource-types.html
  • https://github.com/concourse/resource-types/blob/master/README.md
  • https://github.com/concourse/concourse/wiki/Tutorials