From 7b1cf307031f1c10be030f29d362b8d4bf5f7724 Mon Sep 17 00:00:00 2001 From: Randy Fay Date: Thu, 30 Apr 2026 20:51:23 +0200 Subject: [PATCH] ci: add HCL validate/fmt workflow and Makefile targets for #71 (Phase 1) Adds .github/workflows/validate.yml running terraform validate and terraform fmt -check on all three templates for every push/PR. Adds make validate and make fmt-check as local equivalents. Also applies terraform fmt fixes to all three templates so CI passes from the first run. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/validate.yml | 37 ++++++++++++++++++++++++++++++++++ Makefile | 12 +++++++++++ drupal-core/template.tf | 20 +++++++++--------- freeform/template.tf | 36 ++++++++++++++++----------------- user-defined-web/template.tf | 16 +++++++-------- 5 files changed, 85 insertions(+), 36 deletions(-) create mode 100644 .github/workflows/validate.yml diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..dcacfac --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,37 @@ +name: Validate Templates + +on: + push: + branches: [main] + pull_request: + +jobs: + validate: + name: Validate (${{ matrix.template }}) + runs-on: ubuntu-latest + strategy: + matrix: + template: [user-defined-web, drupal-core, freeform] + fail-fast: false + steps: + - uses: actions/checkout@v4 + - uses: hashicorp/setup-terraform@v4 + with: + terraform_version: "~1.9" + - name: Init + run: terraform init -backend=false -input=false + working-directory: ${{ matrix.template }} + - name: Validate + run: terraform validate + working-directory: ${{ matrix.template }} + + fmt: + name: Format Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: hashicorp/setup-terraform@v4 + with: + terraform_version: "~1.9" + - name: Check formatting + run: terraform fmt -check -recursive diff --git a/Makefile b/Makefile index 3adbd1b..5095e7a 100644 --- a/Makefile +++ b/Makefile @@ -102,6 +102,18 @@ test: ## Test the built image by running it docker run --rm $(IMAGE_TAG) node --version @echo "Test complete" +.PHONY: validate +validate: ## Validate all Terraform templates (requires terraform in PATH) + @for t in $(TEMPLATES); do \ + echo "--- Validating $$t ---"; \ + (cd $$t && terraform init -backend=false -input=false -no-color && terraform validate -no-color) || exit 1; \ + done + @echo "All templates valid." + +.PHONY: fmt-check +fmt-check: ## Check Terraform formatting across all templates + terraform fmt -check -recursive + .PHONY: clean clean: ## Remove local image @echo "Removing local images..." diff --git a/drupal-core/template.tf b/drupal-core/template.tf index eaf3eec..8b1c56a 100644 --- a/drupal-core/template.tf +++ b/drupal-core/template.tf @@ -8,7 +8,7 @@ terraform { source = "kreuzwerker/docker" version = "~> 3.0" } -} + } } provider "docker" { @@ -171,10 +171,10 @@ data "coder_workspace_owner" "me" {} locals { # Determine workspace home path # Sysbox Strategy: Use standard /home/coder - workspace_home = "/home/coder" + workspace_home = "/home/coder" selected_extensions = jsondecode(data.coder_parameter.vscode_extensions.value) - issue_fork_clean = trimprefix(data.coder_parameter.issue_fork.value, "drupal-") - issue_url = local.issue_fork_clean != "" ? "https://www.drupal.org/project/drupal/issues/${local.issue_fork_clean}" : "" + issue_fork_clean = trimprefix(data.coder_parameter.issue_fork.value, "drupal-") + issue_url = local.issue_fork_clean != "" ? "https://www.drupal.org/project/drupal/issues/${local.issue_fork_clean}" : "" } locals { @@ -1471,8 +1471,8 @@ BASHCOMP CODER_AGENT_FORCE_UPDATE = "35" # DOCKER_HOST not needed as we use local socket # DOCKER_HOST = var.docker_host - CODER_WORKSPACE_ID = data.coder_workspace.me.id - CODER_WORKSPACE_NAME = data.coder_workspace.me.name + CODER_WORKSPACE_ID = data.coder_workspace.me.id + CODER_WORKSPACE_NAME = data.coder_workspace.me.name CODER_WORKSPACE_OWNER_NAME = data.coder_workspace_owner.me.name CODER_WORKSPACE_OWNER_EMAIL = data.coder_workspace_owner.me.email # Force HOME to /home/coder (Standard Home Strategy) @@ -1598,8 +1598,8 @@ resource "coder_script" "ddev_shutdown" { resource "docker_container" "workspace" { - count = data.coder_workspace.me.start_count - image = docker_image.workspace_image.image_id + count = data.coder_workspace.me.start_count + image = docker_image.workspace_image.image_id name = "coder-${data.coder_workspace.me.id}" hostname = "${data.coder_workspace.me.name}-${data.coder_workspace_owner.me.name}" user = "coder" @@ -1609,8 +1609,8 @@ resource "docker_container" "workspace" { # Increase stop_timeout to allow shutdown_script and ddev stop to run # Default is usually 10s, which is not enough for ddev shutdown - stop_timeout = 180 - stop_signal = "SIGINT" + stop_timeout = 180 + stop_signal = "SIGINT" destroy_grace_seconds = 180 # Direct Mount Strategy: Set Working Directory to path matching Host diff --git a/freeform/template.tf b/freeform/template.tf index 32553a6..b1b325b 100644 --- a/freeform/template.tf +++ b/freeform/template.tf @@ -8,7 +8,7 @@ terraform { source = "kreuzwerker/docker" version = "~> 3.0" } -} + } } provider "docker" { @@ -86,9 +86,9 @@ data "coder_parameter" "vscode_extensions" { } locals { - workspace_home = "/home/coder" + workspace_home = "/home/coder" selected_extensions = jsondecode(data.coder_parameter.vscode_extensions.value) - image_version = try(trimspace(file("${path.module}/VERSION")), var.image_version) + image_version = try(trimspace(file("${path.module}/VERSION")), var.image_version) registry_without_version = replace(var.workspace_image_registry, ":${local.image_version}", "") workspace_image_registry_base = replace(local.registry_without_version, ":latest", "") @@ -395,9 +395,9 @@ BASHCOMP EOT env = { - CODER_AGENT_FORCE_UPDATE = "1" - CODER_WORKSPACE_ID = data.coder_workspace.me.id - CODER_WORKSPACE_NAME = data.coder_workspace.me.name + CODER_AGENT_FORCE_UPDATE = "1" + CODER_WORKSPACE_ID = data.coder_workspace.me.id + CODER_WORKSPACE_NAME = data.coder_workspace.me.name CODER_WORKSPACE_OWNER_NAME = data.coder_workspace_owner.me.name CODER_WORKSPACE_OWNER_EMAIL = data.coder_workspace_owner.me.email HOME = "/home/coder" @@ -510,19 +510,19 @@ resource "coder_script" "ddev_shutdown" { } resource "docker_container" "workspace" { - count = data.coder_workspace.me.start_count - image = docker_image.workspace_image.image_id - name = "coder-${data.coder_workspace.me.id}" - hostname = "${data.coder_workspace.me.name}-${data.coder_workspace_owner.me.name}" - user = "coder" - group_add = [tostring(var.docker_gid)] - stop_timeout = 180 - stop_signal = "SIGINT" + count = data.coder_workspace.me.start_count + image = docker_image.workspace_image.image_id + name = "coder-${data.coder_workspace.me.id}" + hostname = "${data.coder_workspace.me.name}-${data.coder_workspace_owner.me.name}" + user = "coder" + group_add = [tostring(var.docker_gid)] + stop_timeout = 180 + stop_signal = "SIGINT" destroy_grace_seconds = 60 - working_dir = local.workspace_home - cpu_shares = var.cpu * 1024 - memory = var.memory * 1024 * 1024 * 1024 - runtime = "sysbox-runc" + working_dir = local.workspace_home + cpu_shares = var.cpu * 1024 + memory = var.memory * 1024 * 1024 * 1024 + runtime = "sysbox-runc" volumes { container_path = local.workspace_home diff --git a/user-defined-web/template.tf b/user-defined-web/template.tf index 304c87c..d073edd 100644 --- a/user-defined-web/template.tf +++ b/user-defined-web/template.tf @@ -8,7 +8,7 @@ terraform { source = "kreuzwerker/docker" version = "~> 3.0" } -} + } } provider "docker" { @@ -103,7 +103,7 @@ data "coder_parameter" "vscode_extensions" { locals { # Determine workspace home path # Sysbox Strategy: Use standard /home/coder - workspace_home = "/home/coder" + workspace_home = "/home/coder" selected_extensions = jsondecode(data.coder_parameter.vscode_extensions.value) } @@ -571,8 +571,8 @@ BASHCOMP CODER_AGENT_FORCE_UPDATE = "35" # DOCKER_HOST not needed as we use local socket # DOCKER_HOST = var.docker_host - CODER_WORKSPACE_ID = data.coder_workspace.me.id - CODER_WORKSPACE_NAME = data.coder_workspace.me.name + CODER_WORKSPACE_ID = data.coder_workspace.me.id + CODER_WORKSPACE_NAME = data.coder_workspace.me.name CODER_WORKSPACE_OWNER_NAME = data.coder_workspace_owner.me.name CODER_WORKSPACE_OWNER_EMAIL = data.coder_workspace_owner.me.email # Force HOME to /home/coder (Standard Home Strategy) @@ -658,8 +658,8 @@ resource "coder_script" "ddev_shutdown" { resource "docker_container" "workspace" { - count = data.coder_workspace.me.start_count - image = docker_image.workspace_image.image_id + count = data.coder_workspace.me.start_count + image = docker_image.workspace_image.image_id name = "coder-${data.coder_workspace.me.id}" hostname = "${data.coder_workspace.me.name}-${data.coder_workspace_owner.me.name}" user = "coder" @@ -669,8 +669,8 @@ resource "docker_container" "workspace" { # Increase stop_timeout to allow shutdown_script and ddev stop to run # Default is usually 10s, which is not enough for ddev shutdown - stop_timeout = 180 - stop_signal = "SIGINT" + stop_timeout = 180 + stop_signal = "SIGINT" destroy_grace_seconds = 60