-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Bump Terraform to 1.15.6 and add Terragrunt 1.0.8 #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
4876993
feat: Bump Terraform to 1.15.6 and add Terragrunt 1.0.8
Taegost ff72e50
docs: Add CLAUDE.md with repo conventions and PR smoke-test gate
Taegost 4f9c894
fix: Remove stray v prefix from STERN_VERSION in .env.example
Taegost e98dc8d
Update: CLAUDE.md with new directives
Taegost 55c9776
fix: Add empty-guard on Terragrunt checksum extraction
Taegost File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| # CLAUDE.md | ||
|
|
||
| This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. | ||
|
|
||
| ## What This Repo Is | ||
|
|
||
| A Docker image (Dev Container) that bundles pinned versions of DevOps tooling — Terraform, Packer, kubectl, Helm, Ansible, cloud CLIs, database clients, and Python/.NET SDKs. Published to Docker Hub as `taegost/devops-toolbox`. Consumers pull the image into their projects' `.devcontainer/devcontainer.json`. | ||
|
|
||
| ## Build Commands | ||
|
|
||
| ```bash | ||
| # Local build (needs .env file copied from .env.example) | ||
| cp .env.example .env | ||
| docker build \ | ||
| $(grep -v '^#' .env | grep -v '^$' | sed 's/^/--build-arg /') \ | ||
| -t devops-toolbox:local . | ||
|
|
||
| # CI build (multi-arch, no .env needed — ARGs read from Dockerfile defaults) | ||
| # Triggered by: push to main, semver tag, weekly cron, workflow_dispatch | ||
| # Defined in .github/workflows/build-and-push.yml | ||
| ``` | ||
|
|
||
| No test suite, no linter. The CI pipeline's PR build is the validation step — it builds (without pushing) to confirm the Dockerfile is valid. | ||
|
|
||
| ## Architecture | ||
|
|
||
| ### Dockerfile Design | ||
|
|
||
| **Base image:** `mcr.microsoft.com/devcontainers/base:ubuntu-24.04` — provides git, zsh, oh-my-zsh, curl, non-root `vscode` user, pipx. | ||
|
|
||
| **Version pinning pattern:** Each tool's `ARG VERSION` is declared directly above its install block, not grouped at the top. This is intentional — changing one tool's version only invalidates the Docker layer cache from that tool downward, not the entire build. | ||
|
|
||
| **Architecture handling:** `TARGETARCH` is set by Docker Buildx (`amd64` or `arm64`). Tools that use different arch naming (AWS CLI: `x86_64`/`aarch64`, gcloud: `x86_64`/`arm`) remap inline with shell conditionals. | ||
|
|
||
| **Install method priority:** | ||
| 1. Direct binary download (most tools) — for exact version pinning | ||
| 2. APT with version pin (Azure CLI only) — because it's a Python app with complex deps | ||
| 3. pipx (Ansible, Python dev tools) — isolated virtualenvs, no dependency conflicts | ||
| 4. Microsoft install script (.NET SDK) — needed for feature-band control beyond what APT offers | ||
|
|
||
| **Ansible setup:** Ansible is installed via pipx into an isolated venv. Collections (`dependencies/ansible-requirements.yml`) are baked in at build time. Supporting Python packages (`dependencies/python-ansible-requirements.txt`) are injected into Ansible's venv via `pipx runpip ansible install`. Azure collection deps are installed from the collection's own requirements file post-install. | ||
|
|
||
| **Shell completions:** Written to `/etc/bash_completion.d/` system-wide (not `~/.bashrc`) — available to all users without per-user config. Bash-completion loading is appended to `/etc/bash.bashrc`. | ||
|
|
||
| ### Dependency Files | ||
|
|
||
| | File | Purpose | Version Strategy | | ||
| |---|---|---| | ||
| | `dependencies/ansible-requirements.yml` | Ansible Galaxy collections baked into image | `>=X,<Y` (compatible range, capped at next major) | | ||
| | `dependencies/python-ansible-requirements.txt` | Python packages injected into Ansible's venv | `~=X.Y.Z` (compatible release) | | ||
| | `dependencies/python-dev-requirements.txt` | Dev tools (ipython, pytest, black) via pipx | `==X.Y.Z` (exact pin) | | ||
|
|
||
| ### CI/CD Pipeline | ||
|
|
||
| **File:** `.github/workflows/build-and-push.yml` | ||
|
|
||
| **Triggers:** push to main, semver tags (`v*.*.*`), PRs to main (build-only validation), weekly Monday 04:00 UTC cron, manual `workflow_dispatch`. | ||
|
|
||
| **Platforms:** `linux/amd64`, `linux/arm64` (via QEMU + Buildx). | ||
|
|
||
| **Tagging (via docker/metadata-action):** | ||
| - `latest` — every push to main + weekly rebuild | ||
| - `sha-<short>` — every build (traceability) | ||
| - `1.2.3`, `1.2`, `1` — when a `v1.2.3` Git tag is pushed (semver expansion) | ||
| - PR builds: no push, no tags | ||
|
|
||
| **Security:** Images are signed with Cosign against Sigstore/Fulcio public transparency log. Docker Hub README is synced automatically. | ||
|
|
||
| **Required secrets:** `DOCKERHUB_USERNAME`, `DOCKERHUB_TOKEN` (access token, not password), `DOCKERHUB_IMAGENAME`. | ||
|
|
||
| ### Tag Validation | ||
|
|
||
| Two-stage guard against bad semver tags: | ||
| 1. `Validate tag format` step — regex check that tag matches `vMAJOR.MINOR.PATCH` | ||
| 2. `Verify semver tags were generated` step — confirms docker/metadata-action produced non-SHA tags | ||
|
|
||
| ## Updating a Tool Version | ||
|
|
||
| 1. Find the tool's `ARG` in the Dockerfile (directly above its install block) | ||
| 2. Update the version value | ||
| 3. Update the matching entry in `.env.example` | ||
| 4. Commit changes and push the branch | ||
| 5. Run the smoke test (see ABSOLUTE DIRECTIVE below) — report the result | ||
| 6. Wait for explicit user approval before opening the PR. The user may require additional validation beyond the build. | ||
| 7. After user approval, create the PR — CI validates the build | ||
| 8. Merge to main, then tag a new semver release (`v1.2.3`) to publish versioned tags | ||
|
|
||
| `.env.example` is the quick-reference for current versions — it mirrors all Dockerfile ARGs with links to each tool's release page in comments. | ||
|
|
||
| ## ABSOLUTE DIRECTIVE | ||
|
|
||
| - **NEVER open a PR for Dockerfile changes without smoke testing first.** The smoke test is `docker build .` — it must complete successfully. Run it, report the result. The PR is gated by user approval; the user may require additional checks beyond the build. Do not open the PR until the user explicitly says to proceed. | ||
|
|
||
| ## Key Conventions | ||
|
|
||
| - No `weekly` tag — semantically identical to `latest`, would add noise | ||
| - `kubeseal` and `stern` version ARGs omit the `v` prefix (unlike other tools) because their GitHub release URLs use bare numbers | ||
| - `mariadb-client` comes from Ubuntu APT, not MariaDB Foundation repo — MariaDB 12.x lacks a stable version-addressable APT URL | ||
| - Azure Ansible collection Python deps are installed from the collection's own `requirements.txt` (only exists post-install), not pre-listed in `python-ansible-requirements.txt` | ||
| - `.dockerignore` excludes `.github`, `.devcontainer`, and README.md — the image doesn't need them |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
docs/plans/2026-06-14-001-feat-terraform-bump-terragrunt-add-plan.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| --- | ||
| title: feat: Bump Terraform to 1.15.6 and add Terragrunt 1.0.8 | ||
| type: feat | ||
| status: completed | ||
| date: 2026-06-14 | ||
| --- | ||
|
|
||
| ## Summary | ||
|
|
||
| Bump Terraform from 1.14.8 to 1.15.6 and add Terragrunt 1.0.8 as a new tool with checksum verification, shell completions, and matching doc updates. | ||
|
|
||
| ## Problem Frame | ||
|
|
||
| The image currently ships Terraform 1.14.8 (November 2025). Terraform 1.15.6 (June 2026) is the latest stable release. Terragrunt — a thin wrapper around Terraform/OpenTofu that provides state management, DRY configuration, and CLI ergonomics — is not currently available in the image despite being a common companion to Terraform in DevOps workflows. | ||
|
|
||
| --- | ||
|
|
||
| ## Requirements | ||
|
|
||
| - R1. Terraform version updated from 1.14.8 to 1.15.6 in Dockerfile and `.env.example` | ||
| - R2. Terragrunt 1.0.8 installed via direct binary download from GitHub releases | ||
| - R3. Terragrunt binary verified against published SHA256SUMS before installation | ||
| - R4. Terragrunt shell completions available system-wide via `/etc/bash_completion.d/` | ||
| - R5. README.md tool table updated: Terraform version reference, new Terragrunt row | ||
| - R6. New Terragrunt install block follows existing Dockerfile conventions: header comment describing the tool, in-line rationale comments, version pin as `ARG`, and a `--version` smoke test | ||
|
|
||
| --- | ||
|
|
||
| ## Key Technical Decisions | ||
|
|
||
| - **Checksum verification: yes.** Follows Packer's pattern (download SHA256SUMS, grep the expected hash, pipe to `sha256sum -c`). Most tools in this Dockerfile skip verification; Packer and now Terragrunt are the exceptions. | ||
| - **Install method: raw binary, not archive.** Terragrunt publishes a standalone binary alongside `.tar.gz` and `.zip` archives. Downloading the raw binary avoids an extraction step. This matches the kubectl install pattern. | ||
| - **Version ARG format: no `v` prefix.** `TERRAGRUNT_VERSION=1.0.8` (not `v1.0.8`). The `v` prefix is baked into the download URL pattern. This matches kubeseal and stern conventions. | ||
| - **Shell completions: `terragrunt --install-autocomplete`** per upstream docs. If this writes per-user files rather than system-wide, fall back to the `complete -C` pattern used by Packer and AWS CLI. | ||
|
|
||
| --- | ||
|
|
||
| ## Implementation Units | ||
|
|
||
| ### U1. Bump Terraform version | ||
|
|
||
| - **Goal:** Update Terraform from 1.14.8 to 1.15.6 | ||
| - **Requirements:** R1 | ||
| - **Dependencies:** none | ||
| - **Files:** `Dockerfile`, `.env.example` | ||
| - **Approach:** Change the `TERRAFORM_VERSION` ARG in the Dockerfile and the matching line in `.env.example`. No other Terraform install block changes — the URL pattern (`releases.hashicorp.com`) and zip extraction are unchanged. | ||
| - **Patterns to follow:** Single-line version ARG change per the repo's update conventions documented in README.md | ||
| - **Test scenarios:** | ||
| - Build the image locally and run `terraform version` — verifies the binary downloads, extracts, and reports 1.15.6 | ||
| - **Verification:** `docker build` succeeds and `terraform version` inside the container reports 1.15.6 | ||
|
|
||
| ### U2. Add Terragrunt install block to Dockerfile | ||
|
|
||
| - **Goal:** Install Terragrunt 1.0.8 with checksum verification | ||
| - **Requirements:** R2, R3, R6 | ||
| - **Dependencies:** none | ||
| - **Files:** `Dockerfile` | ||
| - **Approach:** Add a new install block after the Terraform block (logical grouping — both are HashiCorp-ecosystem IaC tools). Download the raw `terragrunt_linux_${TARGETARCH}` binary and the `SHA256SUMS` file. Verify the checksum, then `install -m 755` to `/usr/local/bin/terragrunt`. The block includes: header comment identifying the tool with a URL to its homepage, inline comments explaining each step, the `ARG TERRAGRUNT_VERSION` declaration, and a `terragrunt --version` smoke test. | ||
| - **Patterns to follow:** | ||
| - Packer block for checksum verification shape (`SHA256SUMS` download, `grep` + `awk` for expected hash, `sha256sum -c`) | ||
| - kubectl block for raw binary install (`install -m 755` rather than `chmod +x` after mv) | ||
| - General block structure: comment header → ARG → RUN with cleanup → version check | ||
| - **Test scenarios:** | ||
| - Build the image and run `terragrunt --version` — verifies the binary downloads, passes checksum verification, and reports 1.0.8 | ||
| - Build with a deliberately wrong checksum expectation to confirm the `sha256sum -c` gate fails the build | ||
| - **Verification:** `terragrunt --version` inside the container reports 1.0.8 | ||
|
|
||
| ### U3. Add Terragrunt shell completions | ||
|
|
||
| - **Goal:** Terragrunt tab completion available in bash sessions | ||
| - **Requirements:** R4 | ||
| - **Dependencies:** U2 (binary must be installed first) | ||
| - **Files:** `Dockerfile` | ||
| - **Approach:** Run `terragrunt --install-autocomplete` during build. If this command writes to a per-user RC file rather than `/etc/bash_completion.d/`, fall back to the `complete -C` pattern: `echo "complete -C '$(which terragrunt)' terragrunt" > /etc/bash_completion.d/terragrunt`. The install docs show `touch ~/.bashrc` before running `--install-autocomplete`, so the fallback may be necessary. | ||
| - **Patterns to follow:** Terraform's `-install-autocomplete || true` for the primary approach; Packer's `complete -C` for the fallback | ||
| - **Test scenarios:** | ||
| - After build, start a bash session in the container and type `terragrunt <TAB>` — verifies completions load without errors | ||
| - **Verification:** `complete -p terragrunt` returns a completion specification inside a container bash session | ||
|
|
||
| ### U4. Update README.md and .env.example | ||
|
|
||
| - **Goal:** Documentation reflects the new and updated tools | ||
| - **Requirements:** R1, R5 | ||
| - **Dependencies:** U1, U2 (versions must be finalized) | ||
| - **Files:** `README.md`, `.env.example` | ||
| - **Approach:** | ||
| - `.env.example`: bump `TERRAFORM_VERSION` to 1.15.6, add `TERRAGRUNT_VERSION=1.0.8` in the Infrastructure as code section (near Terraform/Packer) with a release page link in the version reference comment block | ||
| - `README.md`: add a Terragrunt row to the tools table (between Packer and kubectl, under "Infrastructure as code" grouping), add Terragrunt to the Repository Structure tree under `dependencies/` if any new dependency file is created (none expected — Terragrunt has no external Python/Ansible deps) | ||
| - **Patterns to follow:** Existing table rows use "See [Dockerfile](./Dockerfile)" for version reference | ||
| - **Test scenarios:** | ||
| - `.env.example`: verify `grep -v '^#' .env.example | grep -v '^$' | sed 's/^/--build-arg /'` passes Terragrunt's ARG correctly to `docker build` | ||
| - **Verification:** Visual review of both files confirms correct versions, consistent formatting, and working build arg passthrough | ||
|
|
||
| --- | ||
|
|
||
| ## Scope Boundaries | ||
|
|
||
| ### Deferred to Follow-Up Work | ||
|
|
||
| - Bumping other tools to their latest versions | ||
| - Adding Terragrunt-specific Ansible collections or Python packages (none currently needed) | ||
|
|
||
| --- | ||
|
|
||
| ## Risks & Dependencies | ||
|
|
||
| - **Terraform 1.14 → 1.15 minor bump:** HashiCorp maintains backward compatibility within 1.x. No breaking changes are expected in the CLI itself, but consumers should test their own Terraform configurations. | ||
| - **Terragrunt `--install-autocomplete` behavior:** The upstream docs show a `touch ~/.bashrc` prerequisite, which suggests the command may write per-user configuration. If so, the `complete -C` fallback in U3 handles this. | ||
|
|
||
| --- | ||
|
|
||
| ## Sources & Research | ||
|
|
||
| - Terraform releases: `https://releases.hashicorp.com/terraform/` — 1.15.6 confirmed via GitHub API | ||
| - Terragrunt releases: `https://github.com/gruntwork-io/terragrunt/releases` — v1.0.8 confirmed via GitHub API, SHA256SUMS and binary naming verified from release assets | ||
| - Terragrunt install docs: `https://terragrunt.gruntwork.io/docs/getting-started/install/` — `--install-autocomplete` for shell completions, raw binary + SHA256SUMS for verification | ||
| - Packer install block in `Dockerfile:159-172` — checksum verification pattern to mirror | ||
| - kubectl install block in `Dockerfile:285-291` — raw binary install pattern to mirror |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.