Engineering Elixir Applications: End of Chapter 2, github_issues_labels

@elliefairholm and @Gilacost

All of Chapter 2 works fine until this last bit.
variable “issues” {
type = list(object({
title = string
body = string
labels = list(string)
milestone = string
}))
}

resource “github_issue” “tasks” {
count = length(var.issues)
repository = github_repository.kanban.name
title = var.issues[count.index].title
body = var.issues[count.index].body
milestone_number = github_repository_milestone.epics[var.issues[count.index].milestone].number
labels = [for l in var.issues[count.index].labels :
github_issue_label.issues_labels[l].name]

Error: Invalid index

│ on main.tf line 77, in resource “github_issue” “tasks”:
│ 77: github_issue_label.issues_labels[l].name]
│ ├────────────────
│ │ github_issue_label.issues_labels is object with 15 attributes

│ The given key does not identify an element in this collection value.

Hi @SoldierCoder could you share your whole main.tf and .auto.tfvars files? It looks like your having an issue when trying to access a specific “github_issue_label.issues_labels” resource. Rather than having many “issue_labels” in your state it seems that you only have one.

.auto.tfvars
milestones = {
“infrastructure” = {
title = “Infrastructure”
due_date = “2024-07-12”
description = <<EOT
This milestone includes all the deliverables related to building the application(e.g. Dockerfile), provisioning AWS, the local environment and the base AMI (Amazon Machine Image) with Packer.
EOT
},
“ci-cd” = {
title = “Continuous Deployment / Continuous Integration”
due_date = “2024-07-12”
description = <<EOT
This milestone will include all deliverables that have to do with GitHub workflows that will perform the basic checks for an Elixir application. It will also build the Docker
image and pull the latest images in production.
EOT
},
“instrumentation” = {
title = “Instrumentation”
due_date = “2024-07-01”
description = <<EOT
This milestone will include all deliverables that have to do with the addition of basic instrumentation and BEAM specific metrics for your application. Any task(s) related
to instrumentation (independently of which part of the stack they relate to) will be included in this milestone.
EOT
},
“documentation” = {
title = “Documentation”
due_date = “”
description = <<EOT
This milestone includes documentation for Terraform, Elixir, Packer and others and will converge with CI when needed.
EOT
},
“uncategorized” = {
title = “Uncategorized”
due_date = “”
description = <<EOT
A milestone to add all issues that do not fit in any of the other milestones. This is a way to track those uncategorized tasks in an easy way.
EOT
}
}

labels = {
“kind-infrastructure” = {
name = “Kind:Infrastructure”
color = “B60205”
},
“kind-ci-cd” = {
name = “Kind:CI-CD”
color = “FBCA04”
},
“kind-instrumentation” = {
name = “Kind:Instrumentation”
color = “0E8A16”
},
“kind-documentation” = {
name = “Kind:Documentation”
color = “5319E7”
},
“kind-uncategorized” = {
name = “Kind:Uncategorized”
color = “D93F0B”
},
“tech-docker” = {
name = “Tech:Docker”
color = “1D76DB”
},
“dockerfile” = {
name = “Kind:Dockerfile”
color = “3895Ad”
},
“tech-elixir” = {
name = “Tech:Elixir”
color = “D981FC”
},
“tech-gha” = {
name = “Tech:GHA”
color = “66FE68”
},
“tech-docker-compose” = {
name = “Tech:Docker-Compose”
color = “006B75”
},
“tech-packer” = {
name = “Tech:Packer”
color = “1D76DB”
},
“tech-terraform” = {
name = “Tech:Terraform”
color = “5319A1”
},
“tech-sops” = {
name = “Tech:SOPS”
color = “F9D0C4”
},
“env-aws” = {
name = “Env:AWS”
color = “D3A968”
},
“env-local” = {
name = “Env:Local”
color = “0075CA”
}
}

issues = [
{
title = “Implement the Dockerfile’s builder stage”
body = <<EOT
The builder stage packages all the tools and compile-time dependencies for your
application. It has to build the mix release that will be copied in the running
stage.
EOT
labels = [“kind-infrastrcture”, “dockerfile”]
milestone = “infrastructure”
},
{
title = “Implement the Dockerfile’s runner stage”
body = <<EOT
This stage copies the release built in the builder stage and uses it as the
entrypoint of your Docker image with the minimum system requirement to run it.
EOT
labels = [“kind-infrastructure”, “dockerfile”]
milestone = “infrastructure”
},
{
title = “Elixir integration pipelines”
body = <<EOT
Implement a CI pipeline that includes all of the necessary steps when delivering an
Elixir application: code compilation, dependency caching, testing, code
formatting, and an used dependency check.
EOT
labels = [“kind-ci-cd”, “tech-elixir”]
milestone = “ci-cd”
}
]

main.tf

terraform {
required_providers {
github = {
source = “integrations/github”
version = “~> 6.0”
}
}
}

locals {
repository_name = “kanban”
github_owner = “SoldierCoder”
}

resource “github_repository” “kanban” {

name = local.repository_name
description = “Taking the BEAM to production pragmatically.”
visibility = “private”
has_issues = true
auto_init = true
gitignore_template = “Terraform”
delete_branch_on_merge = true
vulnerability_alerts = true
has_discussions = true
has_projects = true
}

variable “milestones” {
type = map(object({
title = string
due_date = string
description = string
}))
description = “Milestones, consider them the biggest deliverable unit.”
}

resource “github_repository_milestone” “epics” {
depends_on = [github_repository.kanban]
for_each = var.milestones
owner = local.github_owner
repository = local.repository_name
title = each.value.title
description = replace(each.value.description, “\n”, " ")
due_date = each.value.due_date
}

variable “labels” {
type = map(object({
name = string
color = string
}))
description = “The labels to tag the issues.”
}

resource “github_issue_label” “issues_labels” {
depends_on = [github_repository.kanban]
for_each = var.labels
repository = local.repository_name
name = each.value.name
color = each.value.color
}

variable “issues” {
type = list(object({
title = string
body = string
labels = list(string)
milestone = string
}))
}

resource “github_issue” “tasks” {
count = length(var.issues)
repository = github_repository.kanban.name
title = var.issues[count.index].title
body = var.issues[count.index].body
milestone_number = github_repository_milestone.epics[var.issues[count.index].milestone].number
labels = [for l in var.issues[count.index].labels : github_issue_label.issues_labels[l].name]
}

provider “github” {
owner = local.github_owner
}