GH Mass-administration: Content

This is part of my guide on how I manage multiple GitHub repositories. This post focuses on streamlining shared content, such as workflows and configuration files. Back to main guide. File Sets I define sets of reusable files that can be applied across multiple repositories: standardContent: Generic files like .gitignore standardDotnetNuget: Shared .NET workflows and Directory.Build.props standardDocker: Docker-related workflows and .dockerignore These sets are declared in repos.json: { "content": { "standardContent": { ".gitignore": "standard_content/.gitignore" }, "standardDocker": { ".github/workflows/docker-dev.yml": "standard_content/docker-dev.yml" } }, "repositories": { "LordMike/MBW.BlueRiiot2MQTT": { "standardContent": true, "standardDocker": true } } } Each repository opts into content sets by enabling the respective boolean key. ...

March 28, 2021 · 1 min · Michael Bisbjerg

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