Skip to content

Spec: phpboyscout/cicd v0.6 — OpenTofu provider plugin cache

  • Repository: gitlab.com/phpboyscout/cicd
  • Released as: v0.6.0 (minor — new cache: + variables: on three components; behaviour-preserving).
  • Driver: provider downloads (hashicorp/aws from the OpenTofu registry → GitHub releases) flaked repeatedly across consumer pipelines. The companion infra-tools v0.3.0 pre-bakes the tflint ruleset (the other recurring flake); this spec handles the provider.

Summary

tofu-plan, tofu-apply and tofu-validate each run tofu init, which downloads the AWS provider. The provider is large and the download is a recurring flake. v0.6.0 caches it.

Decisions

D1 — Provider plugin cache via TF_PLUGIN_CACHE_DIR + GitLab cache:

Each of the three tofu-* jobs gains:

variables:
  TF_PLUGIN_CACHE_DIR: "$CI_PROJECT_DIR/.tofu-plugin-cache"
cache:
  - key: tofu-plugin-cache
    paths:
      - .tofu-plugin-cache/

and mkdir -p "$TF_PLUGIN_CACHE_DIR" before the first tofu init (OpenTofu errors if the cache dir is absent). tofu init populates the cache on first use and copies from it thereafter; GitLab persists it between pipelines.

Static cache key. Provider binaries are immutable and the cache is additive, so a fixed tofu-plugin-cache key keeps every locked version warm. Keying on .terraform.lock.hcl would evict the cache on every provider bump — exactly when re-download hurts. The three jobs share one key (they run in different stages, never concurrently within a pipeline; cross-pipeline writes are last-write-wins on an additive cache, which is benign).

The cache relies on the consumer's .terraform.lock.hcl carrying the h1: hash for linux_amd64 (the CI platform) — true for any lock file generated by tofu init on linux, which all phpboyscout consumers' are.

D2 — Default image_versionv0.3.0

infra-tools v0.3.0 pre-bakes the tflint AWS ruleset. Bumping the default image_version on all six components from v0.2.0 to v0.3.0 lets consumers pick up the warm ruleset (and this provider cache) on their next cicd-ref bump. Routine image-tag bump; the headline feature is the cache (D1).

D3 — Versioning

v0.6.0 — minor. New cache:/variables: keys are additive and behaviour-preserving (a cold cache just downloads as before). The image_version bump is the established routine. Pre-1.0 caveat from v0.1 applies.

Self-test

The tofu-plan / tofu-apply / tofu-validate self-test fixtures use terraform_data only (no AWS provider), so the cache stays empty — the self-tests validate the cache:/variables: config is well-formed and the mkdir + tofu init still pass. The cache's real exercise is the consumer pipelines, where the AWS provider is downloaded once and reused.

Risk register

Risk Mitigation
Lock file lacks the h1: hash for the cached platform → tofu re-downloads or errors All phpboyscout lock files are generated by tofu init on linux and carry linux_amd64 h1: hashes. TF_PLUGIN_CACHE_MAY_BREAK_DEPENDENCY_LOCK_FILE=true is the documented escape hatch if a consumer hits it.
Static-key cache grows unbounded Provider versions are few; runner cache-cleanup bounds it. Additive growth beats evict-on-bump.
Concurrent cross-pipeline cache writes race Last-write-wins on an additive, immutable-content cache is benign; the next run re-populates any gap.

Implementation plan

  1. Spec lands — this file.
  2. templates/tofu-plan.yml, tofu-apply.yml, tofu-validate.ymlTF_PLUGIN_CACHE_DIR + cache: + mkdir (D1).
  3. All six templatesimage_version default → v0.3.0 (D2).
  4. CHANGELOG [0.6.0]; merge develop → main, tag v0.6.0.
  5. Consumers bump tofu-* refs to @v0.6.0 (and their AWS provider locks to the current latest in the same wave).