Commit Graph

144 Commits

Author SHA1 Message Date
benvin b2168a999b Merge pull request 'git: add autobackup-operator repository' (#69) from benvin/autobackup-operator-repo into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #69
2026-08-13 23:36:30 +10:00
unkin-agent c0d8d3d112 git: add autobackup-operator repository
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Provision the Gitea repo for the autobackup-operator, a Kubernetes
operator that creates S3 buckets and backup schedules from
backups.unkin.net/* annotations on PVCs and CNPG clusters. Matches the
convention of sibling operator repos (private=false, squash merges,
main branch protection with pre-commit/test/build checks).
2026-08-13 23:31:39 +10:00
benvin e50d01402e Merge pull request 'git: add ghp fork repository' (#68) from benvin/ghp-repo into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #68
2026-08-13 22:59:09 +10:00
unkin-agent 07b236fb98 git: add ghp fork repository
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Fork goodtune/ghp into git.unkin.net/unkin/ghp to carry an
admin-service-token auth patch for the Vault ghp token engine.
2026-08-13 22:49:58 +10:00
benvin 63be799b84 Merge pull request 'Add agent-tools repository' (#67) from benvin/agent-tools-repo into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #67
2026-08-12 21:32:46 +10:00
unkin-agent e69288f348 agent-tools: shorten description
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
2026-08-12 21:31:56 +10:00
unkin-agent 3844cf9406 agent-tools: require CI status checks + squash merge (mirror node-lookup)
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
2026-08-12 21:26:35 +10:00
unkin-agent 62e6aa1a85 repository: add agent-tools repo for agentpr/watchpr CLI tools
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
2026-08-12 21:22:21 +10:00
benvin 8ed3dc8348 Merge pull request 'repository: require CI status check on jellyfin-ha-src main' (#66) from benvin/jellyfin-required-ci into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #66
2026-08-11 21:31:29 +10:00
benvin dcf30f3036 Merge pull request 'repository: stop migration_mirror_interval planning an update every run' (#65) from benvin/branch-protection-whitelist-drift into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #65
2026-08-11 21:25:28 +10:00
unkinben 7e25e5c3fa repository: require CI status check on jellyfin-ha-src main
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Why: the jellyfin-ha-src main branch is protected but merges are not gated
on CI, so a pull request can be merged while its Woodpecker build is red.

How: add the ci/woodpecker/pr/ci context to the main branch protection
rule. The gitea provider computes enable_status_check from a non-empty
context list, so this turns required status checks on and blocks merge
until that exact check passes.
2026-08-11 21:23:21 +10:00
unkinben cad35f8d9b repository: stop migration_mirror_interval planning an update every run
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Why:
- The go-gitea/gitea provider schema defaults migration_mirror_interval to
  "8h0m0s", but on read it writes repo.MirrorInterval straight back into state,
  and Gitea returns an empty MirrorInterval for non-mirror repositories.
- So the stored value ("") never matches the schema default ("8h0m0s"), and tofu
  plans an in-place update of every gitea_repository on every run even with no
  config change, keeping terraform-git plans perpetually dirty.
- migration_mirror_interval is the only migration_* field read back from the API;
  the rest are write-only migration options, so no sibling field churns.

Change:
- Add a targeted ignore_changes on migration_mirror_interval at the repository
  module so the provider default no longer fights Gitea's empty value, making
  every repository idempotent. It is a migration-only knob with no drift to track
  for these non-mirror repos.
2026-08-11 21:14:24 +10:00
benvin 6d937ae6cd Merge pull request 'repository: protect jellyfin-ha-src main branch' (#64) from benvin/jellyfin-ha-src-protection into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #64
2026-08-11 20:45:40 +10:00
unkinben db62cd1b26 repository: protect jellyfin-ha-src main branch
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Now that the source fork is seeded on main with the pinned upstream tree and a
pristine upstream ref, enable branch protection on main: block direct pushes
and require an Owners approval so future changes land through reviewed pull
requests.
2026-08-10 23:55:07 +10:00
benvin 5bf5f9d85e Merge pull request 'repository: add jellyfin-ha-src source fork' (#63) from benvin/jellyfin-ha-src into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #63
2026-08-10 23:43:04 +10:00
unkinben 4ca5145d50 repository: add jellyfin-ha-src source fork
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Add the jellyfin-ha-src Gitea repository that carries the HA source fork of
ZoltyMat/jellyfin-ha with local patches, replacing the direct upstream clone
in the build pipeline.

Declare the repository as public with a main default branch and
delete-branch-after-merge enabled. Leave branch protection unset so the
initial fork seed can push the pinned upstream tree and a pristine upstream
ref directly to main; protection is added in a follow-up change once the fork
is seeded.
2026-08-10 23:35:19 +10:00
benvin 62596a8086 Merge pull request 'team: stop spurious edits that fail Gitea 1.26 permission validation' (#62) from benvin/gitea-provider-1.26 into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #62
2026-08-10 23:05:51 +10:00
unkinben df118383da team: stop spurious edits that fail Gitea 1.26 permission validation
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Why:
- The go-gitea/gitea provider's SDK (v0.25.1, already shipped in provider
  0.8.1 on main) rejects a team permission of `none` on every EditTeam with
  "permission mode invalid"; it only accepts read/write/admin/owner
  client-side. The same check exists in the older 0.21.0 SDK, so the provider
  version is not the lever here.
- The team module's `units` (server returns an unordered space-separated
  string that never matches the provider's comma-ordered default) and
  `repositories` (provider sorts state; `include_all_repositories` populates
  every repo) drift on representation alone, so every apply plans an in-place
  update for every team.
- Each update calls EditTeam, which replays the stored `permission=none` kept
  by `ignore_changes` and fails, blocking apply for every non-owner team
  (docker/terraform/rpmbuild/puppet/pybuild/forgebot/agents) and the whole
  terraform-git apply, including the unkin-agent rollout.

Change:
- Add `units` and `repositories` to the team `ignore_changes` so provider
  representation churn no longer triggers an EditTeam call.
- Preserve each team's current on-server permission and repository membership
  (no access change).
2026-08-09 12:31:19 +10:00
benvin 15978c486f Merge pull request 'Import pre-existing Gitea branch protections' (#61) from benvin/imports-branch-protection into main
ci/woodpecker/push/apply Pipeline failed
Reviewed-on: #61
2026-08-09 12:01:51 +10:00
unkinben a43267532a Import pre-existing Gitea branch protections
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Why:
- tofu apply fails with "Branch protection already exist" because the nine
  repos protected in #60 already have live branch protection in Gitea that is
  absent from Terraform state, so Terraform tries to create rules that already
  exist and Gitea rejects them.
- The pinned go-gitea/gitea provider 0.7.0 defines no importer for
  gitea_repository_branch_protection, so the existing rules cannot be adopted
  on that version.

How:
- Bump the gitea provider from 0.7.0 to 0.8.1, which adds an importer for
  gitea_repository_branch_protection (id format <org>/<repo>/<rule_name>).
- Add import blocks adopting the nine existing branch protections into state
  instead of recreating them.
2026-08-09 11:45:26 +10:00
benvin d7d6794a51 Merge pull request 'Add unkin-agent Gitea identity with write but no merge' (#59) from benvin/unkin-agent-identity into main
ci/woodpecker/push/apply Pipeline failed
Reviewed-on: #59
2026-08-08 23:34:24 +10:00
benvin 7c4defde29 Merge pull request 'Protect default branches of unprotected active repos' (#60) from benvin/protect-unprotected-repos into main
ci/woodpecker/push/apply Pipeline failed
Reviewed-on: #60
2026-08-08 23:17:44 +10:00
unkinben f720133314 Protect default branches of unprotected active repos
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Why:
- An audit for the new unkin-agent bot (org-wide write) found repos with
  no branch_protection at all, so the agent (or anyone with write) could
  push straight to their default branch.
- The rest of the estate protects default branches; these repos were the gap.

How:
- Add enable_push: false + approval_whitelist_teams: Owners on each active
  repo's default branch, matching the estate's most common convention
  (PR-only; Owners can still open and approve).
- Omit status checks on these repos as none run CI, so a required context
  would permanently block merges.
- Leave the 8 archived repos untouched: they are read-only, nothing can push
  to them, and branch-protection creation on archived repos is rejected.
2026-08-08 22:58:54 +10:00
unkinben 4953142200 Add unkin-agent Gitea identity with write but no merge
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Why: AI coding agents currently push and open PRs as Ben's own account
using Ben's token, so their work is unattributable and carries Ben's full
owner privileges. A dedicated least-privilege identity separates agent work
from Ben's and keeps merge a human decision.

How:
- add the unkin-agent bot user (non-admin, no org/repo creation, limited
  visibility); it authenticates via ephemeral vault-plugin-secrets-gitea
  tokens, not a stored password
- add the agents team granting Write on all unkin repositories, the minimum
  needed to push branches and open PRs; unkin-agent is its only member
- add merge_whitelist_teams Owners to every default-branch protection rule
  that lacked a merge whitelist, so Write no longer implies merge and only
  Owners (Ben) can merge across the estate
2026-08-08 22:37:52 +10:00
benvin 4be9899e8e Merge pull request 'Add NetBox Vault secrets engine + provider repositories' (#57) from benvin/netbox-vault-repos into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #57
2026-08-06 22:13:36 +10:00
benvin 04b5f5c3bd Merge pull request 'Rename terraform-ipam -> terraform-infra' (#58) from benvin/rename-terraform-infra into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #58
2026-08-05 19:40:17 +10:00
unkinben f54e63caee Rename terraform-ipam -> terraform-infra
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Scope grew beyond IPAM (devices, provisioning). Renaming the config file renames
the managed repo; the gitea provider archives the old terraform-ipam repo
(archive_on_destroy=true) and creates terraform-infra. terraform-ipam only holds an
auto-init README, so nothing is lost.

Claude-Session: https://claude.ai/code/session_01JUoARVdmhxKQHyyyp1pxeT
2026-08-05 00:51:36 +10:00
unkinben 674e659080 Add vault-plugin-secrets-netbox + terraform-provider-vault-secrets-netbox repositories
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Provisions the two Gitea repos for the NetBox Vault secrets engine and its
paired Terraform provider.

Claude-Session: https://claude.ai/code/session_01JUoARVdmhxKQHyyyp1pxeT
2026-08-05 00:44:33 +10:00
benvin 9e16d7c5de Merge pull request 'Add terraform-ipam repository' (#56) from benvin/ipam-repo into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #56
2026-08-03 00:15:37 +10:00
unkinben 41ac196b89 Add terraform-ipam repository
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
New repo for YAML-driven NetBox IPAM + Kea DHCP management.

Claude-Session: https://claude.ai/code/session_01JUoARVdmhxKQHyyyp1pxeT
2026-08-03 00:09:05 +10:00
benvin fb6f45faf0 Merge pull request 'Add vault-plugin-secrets-apptoken repository' (#55) from benvin/add-apptoken-plugin-repo into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #55
2026-08-02 21:50:29 +10:00
unkinben 1dfbddab92 Add vault-plugin-secrets-apptoken repository
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Provision the Gitea repo for a generic app-token Vault/OpenBao secrets
engine that issues short-lived signed JWTs for self-made services,
replacing per-app static bearer Secrets. Mirrors the existing plugin repo
entries (squash-only, main branch protection, PR CI checks).

Claude-Session: https://claude.ai/code/session_01JUoARVdmhxKQHyyyp1pxeT
2026-08-02 21:36:48 +10:00
benvin 52b39bf668 Merge pull request 'Add terraform-provider-kea repository' (#54) from benvin/terraform-provider-kea-repo into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #54
2026-08-02 19:37:00 +10:00
unkinben 5a2529f0c4 Add terraform-provider-kea repository
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Provisions the Gitea repo for the Terraform provider wrapping the
kea-operator KeaAPI (subnets + client classes).

Claude-Session: https://claude.ai/code/session_01JUoARVdmhxKQHyyyp1pxeT
2026-08-02 19:33:07 +10:00
benvin 3b229deb1b Merge pull request 'Add kea-operator Gitea repository' (#53) from benvin/kea-operator-repo into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #53
2026-08-02 17:22:40 +10:00
unkinben 8fc5105d10 Add kea-operator Gitea repository
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Provision the repo for the new Kea DHCP Kubernetes operator that replaces
the ISC dhcpd PXE-boot VM.

- add config/git.unkin.net/unkin/repository/kea-operator.yaml
Claude-Session: https://claude.ai/code/session_01JUoARVdmhxKQHyyyp1pxeT
2026-08-02 16:56:38 +10:00
benvin c920451844 Merge pull request 'argocd-apps: require the vector-test PR check' (#52) from benvin/argocd-vector-test-required into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #52
2026-07-30 21:10:33 +10:00
unkinben 493c33483b argocd-apps: require the vector-test PR check
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-30 21:09:39 +10:00
benvin 58dafb7ac2 Merge pull request 'Add bootapi-images repository' (#51) from benvin/bootapi-images-repo into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #51
2026-07-30 21:03:18 +10:00
unkinben 68584acffb Add bootapi-images repository
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
bootapi-images builds the AlmaLinux node rootfs tarballs that bootapi's
image-based provisioning (liveimg) unpacks, and on a v* tag publishes
almalinux9-node-<ver>.tar.zst to the artifactapi rootfs-images local repo. Split
out of bootapi-templates so that repo stays templates-only.

Modeled on the bootapi-templates entry: public, squash, delete-branch-after-merge,
main protection requiring the pre-commit + lint Woodpecker checks and benvin
approval.

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-30 20:55:45 +10:00
benvin bd66d55c99 Merge pull request 'Add bootapi-templates repository' (#50) from benvin/bootapi-templates-repo into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #50
2026-07-28 23:08:51 +10:00
unkinben fe662001c5 Add bootapi-templates repository
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
bootapi-templates holds the live kickstart/iPXE templates and the distro catalog
that bootapi pulls via git-sync (every ~3m, like argocd), so template/OS changes
ship without rebuilding bootapi. Its CI validates that every template parses and
renders for every catalog distro (via 'bootapi validate') plus shellcheck on the
%post snippets.

Modeled on the bootapi repo entry: public, squash, delete-branch-after-merge,
main protection requiring the pre-commit + validate Woodpecker checks and benvin
approval.

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-28 22:35:46 +10:00
benvin c0fc234a1c Merge pull request 'Add bootapi repository' (#49) from benvin/bootapi-repo into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #49
2026-07-28 18:41:49 +10:00
unkinben d53b6841e1 Add bootapi repository
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
bootapi is a Go service replacing Cobbler's PXE/kickstart side: it renders
kickstart files and iPXE boot scripts from NetBox data and serves them to
PXE-booting hosts. The ENC half already moved to encapi; bootapi covers the
provisioning/boot half.

Adds config/git.unkin.net/unkin/repository/bootapi.yaml modeled on encapi:
public repo, squash merges, delete-branch-after-merge, main branch protection
requiring the pre-commit/test/build Woodpecker checks and benvin approval.

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-28 16:58:21 +10:00
benvin 38849ba79f Merge pull request 'vault provider: skip child token creation in CI' (#48) from benvin/vault-skip-child-token into main
ci/woodpecker/push/apply Pipeline was successful
Reviewed-on: #48
2026-07-27 22:03:28 +10:00
unkinben 0385d2a1ef vault provider: skip child token creation in CI
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-27 21:52:24 +10:00
benvin c068f56eca Merge pull request 'Add logarchiver repository' (#47) from benvin/logarchiver-repo into main
ci/woodpecker/push/apply Pipeline failed
Reviewed-on: #47
2026-07-27 21:48:24 +10:00
benvin 99b13d81bc Merge pull request 'user: add gitea-vault-admin site-admin bot with one-time Vault KV seeding' (#46) from benvin/gitea-vault-admin into main
ci/woodpecker/push/apply Pipeline failed
Reviewed-on: #46
2026-07-27 21:47:31 +10:00
benvin 9cee6024d3 Add logarchiver repository
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Registers the logarchiver Gitea repo: a k8s Go service that archives
raw logs from NATS JetStream to S3 as zstd-compressed, GPG-encrypted,
indexed objects, plus a CLI to search and retrieve them. It replaces the
Vector archiver leg of the centralized logging stack (argocd-apps #296)
with zstd compression, OpenPGP encryption keyed from the Vault GPG
secrets engine, and a ClickHouse-backed searchable index.

- Add config/git.unkin.net/unkin/repository/logarchiver.yaml modeled on
  the existing Go-service repos (encapi, cephrgw-operator): public repo,
  main default branch, squash merges, branch protection requiring the
  woodpecker pre-commit/test/build PR checks with benvin approval.

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-27 21:36:15 +10:00
unkinben bd7bef9f99 user: add gitea-vault-admin site-admin bot and one-time Vault KV seeding
ci/woodpecker/pr/plan Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
Why: the vault-plugin-secrets-gitea engine needs a purpose-built Gitea
site-admin credential to mint and delete per-user tokens. Provision that
account and its Vault seed here so the credential is generated once and never
exposed. Ben asked that the password be written to Vault exactly once and
never updated afterwards.

Change:
- Add config/git.unkin.net/user/gitea-vault-admin.yaml: a local site-admin bot
  (admin: true, limited visibility, no org/repo creation).
- Extend the user module with an optional vault_seed_path/vault_seed_mount: when
  set, write the account's generated password to Vault KV as admin_username and
  admin_password via vault_kv_secret_v2, with lifecycle ignore_changes on
  data_json so the write is create-only and never churns (random_password
  already never regenerates). This keeps the seed stable and prevents a re-apply
  from overwriting a password later rotated out-of-band by rotate-root.
- Add the hashicorp/vault provider (module plus root generate block); it reads
  VAULT_ADDR and VAULT_TOKEN already exported by the Makefile k8s login.

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
2026-07-27 19:26:24 +10:00