diff --git a/AGENTS.md b/AGENTS.md index 7273b28..dd92037 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,6 +11,15 @@ Use a feature branch and open a pull request rather than pushing directly to environment gates approve it. Do not push any branch unless explicitly requested. +## Branch Protection + +Branch protection on `main` is intentionally relaxed for this solo-maintainer, +personal-dev organization: no required status check contexts and zero required +approving reviews (see the comment in `gh-protections.tf`). PRs are used for CI +validation, plan output, and change history, not as a review gate. Do not +tighten `contexts` or `required_approving_review_count` unless explicitly +requested. + ## Pre-commit Configuration Pre-commit configuration is centralized at @@ -40,6 +49,16 @@ tracked copy. **Pre-commit failures:** If hooks fail unexpectedly, the canonical config may have changed. Re-run `make test` to refresh it and run the checks. +## Dependency Updates + +Dependabot version updates are managed here in `gh-dependabot.tf` via +`github_repository_file` resources, so all active repositories receive their +`.github/dependabot.yml` from one place. To change update policy, edit the +`dependabot_ecosystems` map; do not hand-edit `.github/dependabot.yml` in +downstream repositories. Pre-commit hook revisions are not covered by +Dependabot: they are owned by the canonical config in +`images/tfroot-runner/pre-commit-config.yaml`. + ## Related Repositories - `images` - Contains tfroot-runner image and canonical pre-commit config @@ -53,3 +72,4 @@ objects: - repositories: `` - `main` branch protections: `:main` - Actions secrets: `/` +- repository files: `/` (append `:` for non-default branches) diff --git a/README.md b/README.md index 0a622ed..d2447b7 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ No modules. | [github_branch_protection.protections](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/branch_protection) | resource | | [github_membership.admin](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/membership) | resource | | [github_repository.repositories](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository) | resource | +| [github_repository_file.dependabot](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository_file) | resource | | [github_team.admins](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/team) | resource | | [github_team.developers](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/team) | resource | | [github_team_membership.admins_xnoto](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/team_membership) | resource | diff --git a/gh-dependabot.tf b/gh-dependabot.tf new file mode 100644 index 0000000..b88b011 --- /dev/null +++ b/gh-dependabot.tf @@ -0,0 +1,71 @@ +# Dependabot version updates are managed centrally here so every active +# repository receives the same `.github/dependabot.yml` policy. Do not add +# hand-maintained dependabot configs to downstream repositories. +# +# OpenTofu roots use the dedicated `opentofu` ecosystem (GA since 2025-12-16), +# not `terraform`. Lock files are not git-tracked in these repos, so only +# version constraints in .tf files are bumped. +# +# Deliberately not covered: +# - pre-commit hook revisions: owned by images/tfroot-runner/pre-commit-config.yaml +# - tool ARG pins in images/*/Containerfile: Dependabot only updates FROM tags +# - Kubernetes image tags in kustomize-cluster: no Dependabot ecosystem exists + +locals { + dependabot_ecosystems = { + ".github" = ["github-actions"] + "cflan" = ["github-actions", "pip"] + "images" = ["github-actions", "docker"] + "kustomize-cluster" = ["github-actions"] + "shared-workflows" = ["github-actions"] + "terraform-libvirt-domain" = ["github-actions", "opentofu"] + "tfroot-aws" = ["github-actions", "opentofu"] + "tfroot-cloudflare" = ["github-actions", "opentofu"] + "tfroot-github" = ["github-actions", "opentofu"] + "tfroot-libvirt" = ["github-actions", "opentofu"] + "www" = ["github-actions"] + } + dependabot_docker_directories = ["gh-cli", "tfroot-runner"] + + dependabot_configs = { + for repo, ecosystems in local.dependabot_ecosystems : repo => { + version = 2 + updates = concat( + [for ecosystem in ecosystems : { + package-ecosystem = ecosystem + directory = "/" + schedule = { + interval = "weekly" + } + groups = { + (ecosystem) = { + patterns = ["*"] + } + } + } if ecosystem != "docker"], + [for directory in local.dependabot_docker_directories : { + package-ecosystem = "docker" + directory = "/${directory}" + schedule = { + interval = "weekly" + } + groups = { + docker = { + patterns = ["*"] + } + } + } if contains(ecosystems, "docker")] + ) + } + } +} + +resource "github_repository_file" "dependabot" { + for_each = local.dependabot_configs + + repository = github_repository.repositories[each.key].name + file = ".github/dependabot.yml" + content = "# Managed by tfroot-github (gh-dependabot.tf); local edits are overwritten.\n${yamlencode(each.value)}" + commit_message = "chore: sync managed dependabot configuration" + overwrite_on_create = true +} diff --git a/gh-protections.tf b/gh-protections.tf index e3d4b7e..10a8d1d 100644 --- a/gh-protections.tf +++ b/gh-protections.tf @@ -1,3 +1,9 @@ +# Branch protection here is intentionally relaxed for a solo-maintainer, +# personal-dev organization: `contexts` is empty (CI is advisory, not a merge +# gate) and `required_approving_review_count` is zero. The PR workflow exists +# for CI validation, plan output, and change history — not review ceremony. +# If collaborators join or a repo gains external contributors, tighten +# `contexts` and `required_approving_review_count` at that time. resource "github_branch_protection" "protections" { for_each = toset([for repo in local.github_repositories : repo if !contains(local.archived_github_repositories, repo)]) repository_id = github_repository.repositories[each.key].node_id