Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions .terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 69 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# cloud-compose repository instructions

This file is the concise entry point for agents and contributors. Start at
[docs/index.md](docs/index.md) for architecture, then
[docs/runtime-contracts.md](docs/runtime-contracts.md) for the trust boundary
this module enforces.

## Required contract

```bash
make lint-check
```

This runs `terraform fmt -check`, `actionlint`, the shell contract suite, and
`terraform-validate` (init + validate + test) across every directory in the
repo that contains `.tf` files.

## Local `.terraform.lock.hcl` drift on a machine that hasn't touched a
## directory's providers yet

`terraform-validate` will fail with `missing or corrupted provider plugins:
... does not match any of the checksums recorded in the dependency lock
file` the first time you run it from a machine/architecture whose provider
fetch path hasn't previously contributed a hash to that directory's lock
file. This is not corruption and not a network problem: HashiCorp's registry
can legitimately serve a byte-different (but equally valid, signed) archive
for the same provider version depending on which CDN edge answers the
request, and Terraform's `h1:` package hash is computed from that archive's
contents. `.terraform.lock.hcl` supports recording multiple valid `h1:`
hashes per version specifically for this; a plain `terraform init` refuses to
silently trust an unrecorded hash (that refusal is the actual integrity
protection working as intended), while `-upgrade` recomputes and appends the
new legitimate one.

The repo has more than one directory with its own `.tf` files and its own
`.terraform.lock.hcl` (root, `providers/*`, `modules/*`, `examples/*`,
`tests/smoke/*`). A lock file only picks up a new machine's hash for the
providers *that specific directory* declares, so hitting this in one
directory does not fix it anywhere else. If you hit this failure — most
likely the first time you run `terraform-validate` locally on a machine that
hasn't run it before (a new contributor, a new laptop, or after switching
architectures) — update every directory's lock file in one pass rather than
chasing failures one at a time:

```bash
for dir in $(find . -path "*/.terraform" -prune -o -path "./docs/site" -prune -o -name "*.tf" -exec dirname {} \; | sort -u); do
echo "=== $dir ==="
(cd "$dir" && terraform init -backend=false -upgrade -input=false >/dev/null && echo ok)
done
git status --short
```

Commit the resulting `.terraform.lock.hcl` changes alongside your actual
change — recording the additional legitimate hash for cross-platform (Mac +
Linux CI) contributors is expected, not scope creep. Then rerun
`bash ci/terraform-validate.sh` to confirm every directory is clean before
declaring the change complete.

## macOS-specific local caveats

- `ci/application-env-contract.sh` deliberately runs part of its check under
`env -i PATH=/usr/bin:/bin bash --noprofile --norc -c '...'` to exercise
the application-env trust boundary under a minimal, untrusted-style
environment. On macOS, `/bin/bash` (and `/usr/bin/bash`) is always the
frozen GPLv2 bash 3.2.57 system shell, regardless of what modern bash you
have installed via Homebrew or earlier in your `PATH` — that hardcoded
`PATH` inside the check ignores your shell entirely. This is expected and
cannot be fixed by installing a newer bash; run this specific check inside
a Linux container if you need to reproduce it locally, or trust CI for it.
Empty file modified ci/backup-contract.sh
100644 → 100755
Empty file.
Empty file modified ci/bootstrap-recovery-contract.sh
100644 → 100755
Empty file.
Empty file modified ci/cos-jq-portability-contract.sh
100644 → 100755
Empty file.
Empty file modified ci/disaster-recovery-contract.sh
100644 → 100755
Empty file.
Empty file modified ci/filesystem-prep-contract.sh
100644 → 100755
Empty file.
Empty file modified ci/fixtures/checked-lifecycle-executor.sh
100644 → 100755
Empty file.
Empty file modified ci/host-runtime-security.sh
100644 → 100755
Empty file.
Empty file modified ci/inline-data-program-contract.sh
100644 → 100755
Empty file.
Empty file modified ci/key-rotation-contract.sh
100644 → 100755
Empty file.
Empty file modified ci/managed-artifact-contract.sh
100644 → 100755
Empty file.
Empty file modified ci/overlay-contract.sh
100644 → 100755
Empty file.
Empty file modified ci/runtime-config-contract.sh
100644 → 100755
Empty file.
Empty file modified ci/sitectl-version-contract.sh
100644 → 100755
Empty file.
Empty file modified ci/source-trust-contract.sh
100644 → 100755
Empty file.
51 changes: 29 additions & 22 deletions ci/terraform-validate.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -84,35 +84,42 @@ validate_root() {

echo "Validating Terraform in ${rel}"

init_status=0
# A shared plugin cache can let `terraform init` install a package without
# fully re-verifying it against this directory's lock file; a truncated or
# otherwise corrupted cache entry then only surfaces later, when validate
# or test actually loads the provider plugin. Retry the whole
# init+validate(+test) sequence together and purge the cache between
# attempts, rather than only wrapping init, so a corrupted entry discovered
# at any step gets a clean re-download on the next attempt.
for attempt in 1 2 3; do
if TF_DATA_DIR="$data_dir" terraform -chdir="$root" init "${init_args[@]}" >/dev/null; then
init_status=0
init_status=0
TF_DATA_DIR="$data_dir" terraform -chdir="$root" init "${init_args[@]}" >/dev/null || init_status=$?

validate_status=0
if [[ "$init_status" -eq 0 ]]; then
TF_DATA_DIR="$data_dir" terraform -chdir="$root" validate -no-color || validate_status=$?
fi

provider_status=0
if [[ "$init_status" -eq 0 && "$validate_status" -eq 0 ]]; then
validate_public_provider_graph "$root" "$data_dir" "$rel" || provider_status=$?
fi

test_status=0
if [[ "$init_status" -eq 0 && "$validate_status" -eq 0 && "$provider_status" -eq 0 ]] && find "$root" -maxdepth 1 -name '*.tftest.hcl' -print -quit | grep -q .; then
TF_DATA_DIR="$data_dir" terraform -chdir="$root" test -no-color || test_status=$?
fi

if [[ "$init_status" -eq 0 && "$validate_status" -eq 0 && "$provider_status" -eq 0 && "$test_status" -eq 0 ]]; then
break
else
init_status=$?
fi
if [[ "$attempt" -lt 3 ]]; then
echo "terraform init failed in ${rel}; retrying in $((attempt * 10))s (attempt ${attempt}/3)" >&2
rm -rf "${TF_PLUGIN_CACHE_DIR:?}"/*
echo "Terraform validation failed in ${rel}; retrying in $((attempt * 10))s (attempt ${attempt}/3)" >&2
sleep $((attempt * 10))
fi
done

validate_status=0
if [[ "$init_status" -eq 0 ]]; then
TF_DATA_DIR="$data_dir" terraform -chdir="$root" validate -no-color || validate_status=$?
fi

provider_status=0
if [[ "$init_status" -eq 0 && "$validate_status" -eq 0 ]]; then
validate_public_provider_graph "$root" "$data_dir" "$rel" || provider_status=$?
fi

test_status=0
if [[ "$init_status" -eq 0 && "$validate_status" -eq 0 && "$provider_status" -eq 0 ]] && find "$root" -maxdepth 1 -name '*.tftest.hcl' -print -quit | grep -q .; then
TF_DATA_DIR="$data_dir" terraform -chdir="$root" test -no-color || test_status=$?
fi

if [[ "$created_lock" == "true" ]]; then
rm -f "$lockfile"
fi
Expand Down Expand Up @@ -156,7 +163,7 @@ main() {
find "$repo_root" \
-path "*/.terraform" -prune -o \
-path "$repo_root/docs/site" -prune -o \
-name "*.tf" -printf '%h\n' |
-name "*.tf" -exec dirname {} \; |
sort -u
)

Expand Down
Empty file modified ci/testdata/disaster-recovery/compose-apps.sh
100644 → 100755
Empty file.
Empty file modified ci/testdata/disaster-recovery/fake-docker.sh
100644 → 100755
Empty file.
Empty file modified ci/testdata/disaster-recovery/fake-install.sh
100644 → 100755
Empty file.
Empty file modified ci/testdata/disaster-recovery/fake-stat.sh
100644 → 100755
Empty file.
Empty file modified ci/testdata/disaster-recovery/good-driver.sh
100644 → 100755
Empty file.
Empty file modified ci/testdata/disaster-recovery/incomplete-driver.sh
100644 → 100755
Empty file.
Empty file modified ci/testdata/disaster-recovery/profile.sh
100644 → 100755
Empty file.
Empty file modified ci/vault-runtime-contract.sh
100644 → 100755
Empty file.
Empty file modified internal/contracttest/testdata/cloud-smoke-lifecycle/ssh.sh
100644 → 100755
Empty file.
53 changes: 53 additions & 0 deletions modules/digitalocean/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

97 changes: 97 additions & 0 deletions modules/gcp/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading