GH Mass-administration: Terraform

This is a part of my guide to how I manage multiple GitHub repositories. This post focuses on configuring repository settings on GitHub using Terraform. Back to main guide. Repository Management with Terraform I use Terraform to declaratively configure: Repo metadata: description, topics, features Branch settings: default branch and protection rules GitHub Actions secrets: shared credentials for NuGet and Docker Example Configuration Github.tf defines: locals { github_owner = "LordMike" github_token = "REPLACE_ME" repositories = jsondecode(file("repos.json")).repositories repos = keys(local.repositories) repos_public = [for r in local.repos : r if lookup(local.repositories[r], "public", true)] nuget_repos = [for r in local.repos : r if lookup(local.repositories[r], "nuget", true)] docker_repos = [for r in local.repos : r if lookup(local.repositories[r], "docker", false)] docker_username = "lordmike" docker_key = "REPLACE_ME" nuget_key = "REPLACE_ME" } provider "github" { owner = local.github_owner token = local.github_token } resource "github_repository" "repository" { for_each = toset(local.repos) name = split("/", each.key)[1] description = lookup(local.repositories[each.key], "description", "") topics = lookup(local.repositories[each.key], "topics", null) has_issues = lookup(local.repositories[each.key], "has_issues", true) has_wiki = lookup(local.repositories[each.key], "has_wiki", false) has_projects = lookup(local.repositories[each.key], "has_projects", false) has_downloads = lookup(local.repositories[each.key], "has_downloads", false) delete_branch_on_merge = lookup(local.repositories[each.key], "delete_branch_on_merge", true) } resource "github_branch_default" "default_branch" { for_each = toset(local.repos) repository = split("/", each.key)[1] branch = "master" } resource "github_branch_protection" "protect_master" { for_each = toset(local.repos_public) repository_id = split("/", each.key)[1] pattern = "master" enforce_admins = false allows_deletions = false allows_force_pushes = false } resource "github_actions_secret" "nuget_key" { for_each = toset(local.nuget_repos) repository = split("/", each.key)[1] secret_name = "NUGET_KEY" plaintext_value = local.nuget_key } resource "github_actions_secret" "docker_username" { for_each = toset(local.docker_repos) repository = split("/", each.key)[1] secret_name = "DOCKER_USERNAME" plaintext_value = local.docker_username } resource "github_actions_secret" "docker_key" { for_each = toset(local.docker_repos) repository = split("/", each.key)[1] secret_name = "DOCKER_KEY" plaintext_value = local.docker_key } Tips Use for_each and filtered locals (e.g. docker_repos) to simplify resource declarations Use lookup to define defaults and override per-repo settings Terraform Imports (for existing repos) Use terraform import with escaped resource keys: ...

March 28, 2021 · 2 min · Michael Bisbjerg

Consuming NuGet packages from my GitHub

This is a short guide on how to consume packages from my GitHub packages feed. The official docs are here. Notes: How to find your NuGet.Config My feed URL: https://nuget.pkg.github.com/LordMike/index.json You must authenticate using a GitHub access token with read:packages permission — create one here. The config file must exist — use dotnet new nugetconfig to create it. Method A: Add source user-wide (CLI) dotnet new nugetconfig dotnet nuget add source \ -n gh-lordmike \ https://nuget.pkg.github.com/LordMike/index.json \ -u MyGithubUser \ -p MyGithubToken This adds a user-wide source, allowing all projects to consume from it. On Windows, the password is encrypted on disk. ...

March 28, 2021 · 1 min · Michael Bisbjerg

Mass-administration of GitHub repositories

This is a collection of notes on how I manage multiple GitHub repositories. All repositories under my account are maintained using this system. Features I need the following: Standardized repository configuration — Easily change topics, descriptions, settings across all repos. Unified GitHub Actions workflows — Shared build, test, release pipelines (e.g., NuGet, Docker Hub). Synchronized repository content — Shared files like .gitignore, Directory.Build.props, and CI/CD workflows. In short, I want to template my repositories—but also update those templates over time. ...

March 27, 2021 · 1 min · Michael Bisbjerg

Renaming an index in Elastic (slight hacks)

Sometimes you need to rename an Elasticsearch index—maybe to reuse the name for an alias. Officially, this isn’t supported. But with some manual edits and caution, it can be done. ⚠️ Warning: This is dangerous and unsupported. Back up your data first. Recommended Alternatives Reindex API Snapshot and restore Index split If these don’t work for your case, read on. The Hacky Method Stop the Elasticsearch node. Find the metadata files: ...

March 5, 2021 · 1 min · Michael Bisbjerg

Move WSL to different drive

Windows Subsystem for Linux is awesome, but storing its files on the system drive can be limiting. Here’s how to move WSL distributions to another disk. List Containers wsl --list Sample output: Windows Subsystem for Linux Distributions: ubuntu (Default) docker-desktop-data docker-desktop Move a Container Shut down WSL to avoid issues: wsl --shutdown Export the container: wsl --export ubuntu N:\ubuntu.tar Unregister the container: wsl --unregister ubuntu Re-import to new location: wsl --import ubuntu N:\WSL\ubuntu N:\ubuntu.tar --version 2 (Optional) Delete the exported .tar file after verifying the setup. This approach preserves the distro while allowing full control over its storage location. ...

February 17, 2021 · 1 min · Michael Bisbjerg