terraform and GitHub labels


terraform is a fantastic tool to "Write, Plan, and Create infrastructure as code". I have been playing around with it for more than one year and decided to write about it because twitter’s friends said it was a good idea.

The basic idea behind terraform is brilliant and simple: you describe your infrastructure using a little language called hcl and then use terraform to apply your changes. The thing that strikes me the most is how productive you can be using terraform.

To get started, you only need to learn about how configuration is done via resources. A resource represents one component in your infrastructure, terraform provides a great number of providers to interact with different APIs (things like AWS, DNSimple, CloudFlare and so on). You describe your infrastructure by describing your resources.

In the past few weeks, something silly started bugging me: I have multiple GitHub projects that share the same labels.

As I created those labels manually over time, different projects have the same labels with different colors.

It’s a small thing, but it hurts my visual memory and I don’t want to manually sync them.

Fortunately, terraform has a GitHub provider that exposes a github_issue_label resource. A few days ago, I decided to try syncing labels using terraform. It took literally two minutes to implement a first working configuration.

I created a config.tf that looks like this:

provider "github" {
  token = "REAL TOKEN HERE"
  organization = "lucapette"
}

and a github.tf file that looked like this:

resource "github_issue_label" "fakedata-gardening-label" {
  repository = "fakedata"
  name       = "gardening"
  color      = "006b75"
}

resource "github_issue_label" "fakedata-bug-label" {
  repository = "fakedata"
  name       = "bug"
  color      = "ee0701"
}

// more resources like those...

I ran terraform apply and a few seconds later fakedata had labels properly configured. It felt like magic! Just a note: running terraform apply will either create or update a terraform.tfstate, which contains an up-to-date version of the infrastructure. I think it makes sense to commit this file. I did not look into good practices yet, so take the advice with a grain of salt. Of course, the point of this experiment was to sync labels within multiple GitHub projects. I could have replicated the github_issue_labels with a copy and paste and call it a day: it surely works that way, but it’s not the most maintainable approach. Furthermore, writing the configuration manually is a pretty boring task. While reading the documentation, I ran into meta-parameters, which are parameters available to all the resources. With the help of the count parameter and some syntax, I wrote the following:

variable repositories {
  default = {
    "0" = "fakedata"
    "1" = "another project here"
  }
}

resource "github_issue_label" "gardening-label" {
  count = "${length(var.repositories)}"
  repository = "${lookup(var.repositories, count.index)}"
  name       = "gardening"
  color      = "006b75"
}

resource "github_issue_label" "bug-label" {
  count = "${length(var.repositories)}"
  repository = "${lookup(var.repositories, count.index)}"
  name       = "bug"
  color      = "ee0701"
}

// more resources like these

I ran terraform apply once more and I had all the labels synced within multiple projects. To recap, the entire process consisted of the following steps:

  • quick read of the documentation
  • writing a first configuration
  • running terraform apply
  • writing a more general configuration
  • running terraform apply

It took around 10 minutes from the idea to a fully automated configuration of GitHub labels. Here is the entire file if you’re curious.

Of course, this was so trivial you could do it with a shell script, but I believe it shows the huge potential of this wonderful tool. I suggest you have a look at the providers and the syntax, there’s much more than this simple use case I just showed you here. One great feature is terraform import, which can help a with adoption.

Happy terraforming!

See also