README
¶
github-org-manager-go (gomgr)
A fast, idempotent GitHub Organization Manager written in Go. Define your org as YAML and apply it with a single command. Ships with a release workflow and a CI workflow to run sync against one or many org-config folders.
Highlights
- ✅ YAML-driven org config (
app.yaml,org.yaml,teams/*.yaml) - ✅ Teams, maintainers, members (idempotent add/update)
- ✅ Repo permission grants (pull/triage/push/maintain/admin)
- ✅ Repository topics: add topics/labels to repositories for organization
- ✅ Repository pinning: pin important repositories to organization profile
- ✅ Optional: create repos that don’t exist (
create_repo: true) - ✅ Optional: inject
.github/renovate.jsoninto repos - ✅ Warnings & cleanups: unmanaged teams, members without team, unmanaged repos
- ✅ Optional hard cleanups: delete unmanaged teams, remove members without team, delete unmanaged repos
- ✅ Auth: GitHub App (recommended) or PAT
- ✅
--dryplan with stable output; safe apply - ✅ Cross‑platform binaries via GitHub Releases;
gomgr versionstamped at build
Install
Option 1 — Download a release
Grab a binary from Releases and put it on your $PATH.
gomgr version
Option 2 — Build from source
go build -trimpath -buildvcs=true -ldflags "-s -w -X github.com/DragonSecurity/github-org-manager-go/internal/version.Version=$(git describe --tags --always --dirty)" -o gomgr .
Quickstart
- Prepare config directory (example shown below):
<config>/
├─ app.yaml
├─ org.yaml
└─ teams/
└─ platform-team.yaml
- Auth (choose one):
-
GitHub App (recommended)
export GITHUB_APP_ID=1719369 export GITHUB_APP_PRIVATE_KEY="$(cat /path/to/private-key.pem)" # or set app.yaml: private_key: <path or PEM>Installation: install the app on your target org and grant the permissions listed below.
-
PAT
export GITHUB_TOKEN=<personal-access-token>
- Run a dry run, then apply
gomgr sync -c <config> --dry
gomgr sync -c <config>
Configuration
app.yaml
org: KaMuses
# GitHub App auth (preferred):
app_id: 1719369 # or set via env GITHUB_APP_ID
private_key: ./app-private.pem # file path or raw PEM; env GITHUB_APP_PRIVATE_KEY also works
dry_warnings:
warn_unmanaged_teams: true
warn_members_without_any_team: true
warn_unmanaged_repos: true # warn about repos not defined in any team
# Optional enforcement / extras:
remove_members_without_team: true # remove org members not in any team
delete_unconfigured_teams: true # delete teams not defined in YAML
delete_unmanaged_repos: false # delete repos not defined in any team (DESTRUCTIVE!)
create_repo: true # create repos if missing when referenced by teams
add_renovate_config: true # create .github/renovate.json in repos
renovate_config: |
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["github>DragonSecurity/renovate-presets"]
}
org.yaml
Currently used for owners (extension point):
owners:
- alice
- bob
teams/*.yaml
name: Platform Team
slug: platform-team # optional; default = kebab(name)
description: Core platform engineers
privacy: closed # closed | secret
parents: [] # (future enhancement)
maintainers:
- alice
members:
- bob
repositories:
# Simple permission string (backward compatible)
infra: maintain # pull|triage|push|maintain|admin
# Advanced config with topics and pinning
api:
permission: push
topics:
- backend
- api
- project-platform
# Repository with pinning (appears on org profile)
platform-index:
permission: admin
topics:
- project-platform
- documentation
pinned: true
Loader ignores non‑YAML files in
teams/and skips empty/invalid entries.
Project Organization Pattern
gomgr supports organizing repositories by project with topics, pinning, and naming conventions:
Example: Multi-repo project setup
- Define a project name (slug), e.g.,
platform - Prefix all project repositories:
platform-api,platform-web,platform-infra - Tag all repos with topic:
project-platform - Create an index repository:
platform-indexwith README linking to all project repos - Pin the index repo to make it prominent on the org profile
Example configuration:
name: Platform Team
repositories:
platform-index:
permission: admin
topics:
- project-platform
- documentation
pinned: true
platform-api:
permission: push
topics:
- project-platform
- backend
platform-web:
permission: push
topics:
- project-platform
- frontend
platform-infra:
permission: maintain
topics:
- project-platform
- infrastructure
This pattern makes it easy to:
- Discover all repositories belonging to a project using GitHub's topic search
- Provide project documentation via the pinned index repository
- Maintain consistent naming and organization across projects
Auth & Permissions
GitHub App (recommended)
Set GITHUB_APP_ID and GITHUB_APP_PRIVATE_KEY (or app_id/private_key in app.yaml). The app must be installed on the org.
Typical minimum permissions (tighten to least privilege for your use-case):
- Organization: Members (Read/Write), Teams (Read/Write)
- Repository: Administration (Read/Write) to grant team access & create repos; Contents (Read/Write) to create files like Renovate config; Metadata (Read)
Exact permissions depend on which features you enable (e.g., if you don’t create repos or write files, you can drop those).
Personal Access Token (PAT)
Use a classic PAT with scopes:
admin:org(manage teams/members)repo(set team repo access and create repos)read:org(read org metadata)
CLI
-
gomgr sync -c <config> [--dry] [--debug]
Plans and applies org state. -
gomgr setup-team -n "Team Name" -c <config> [-f out/path.yaml]
Bootstraps a team YAML. -
gomgr version
Prints version (stamped at build). If built with VCS info, also prints revision/dirty/commit time.
Order of operations (apply):
create teams → set memberships → ensure repos → grant permissions → write renovate (optional) → set topics & pins → cleanups (optional)
CI: Releases
This repo includes .github/workflows/release.yml:
- Trigger on tag push (
v*.*.*) or manual. - Builds for linux/darwin/windows × amd64/arm64.
- Stamps
gomgr versionvia-ldflags. - Uploads packaged artifacts and
checksums.txt.
Tag to release:
git tag v0.1.0
git push origin v0.1.0
CI: Org sync workflow (for your org-config repo)
Example (.github/workflows/org-sync.yml):
name: Synchronise organization users and teams (gomgr)
on:
push:
branches: [ "main" ]
workflow_dispatch:
jobs:
sync:
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
config:
- { folder: "dragonsecurity/dragonsecurity", gom_version: "v0.12.2" }
- { folder: "dragonsecurity/dragondevcc", gom_version: "v0.10.2" }
- { folder: "dragonsecurity/kamuses", gom_version: "v0.10.2" }
continue-on-error: true # allow other matrix jobs to finish if one fails
steps:
- uses: actions/checkout@v4
- name: Install gh
uses: cli/gh-action@v2
- name: Download gomgr
env: { GH_TOKEN: ${{ github.token }} }
run: |
VERSION="${{ matrix.config.gom_version }}"
OS=linux ARCH=amd64
ASSET="gomgr_${VERSION}_${OS}_${ARCH}.tar.gz"
mkdir -p .gomgr
gh release download "$VERSION" --repo DragonSecurity/github-org-manager-go --pattern "$ASSET" --dir .gomgr
tar -xzf ".gomgr/$ASSET" -C .gomgr
sudo mv $(find .gomgr -type f -name gomgr) /usr/local/bin/gomgr
sudo chmod +x /usr/local/bin/gomgr
- run: gomgr version
- name: Synchronise settings
run: gomgr sync -c ${{ matrix.config.folder }}
env:
GITHUB_APP_PRIVATE_KEY: ${{ secrets.DSEC_USER_MANAGEMENT_APP_PRIVATE_KEY }}
GITHUB_APP_ID: "1719369"
Troubleshooting
- 404 on
/teams//members: empty/invalid team YAML or calling membership on a team that doesn’t exist yet. Loader ignores non‑YAML files and planner guards empty slugs; team creation happens before membership. gomgr versionshowsdev: build without-ldflags -Xor not from a tag. Use the release workflow or pass a version when building.- Renovate config not created: ensure
add_renovate_config: trueandrenovate_configis non‑empty; repo must exist orcreate_repo: true.
Roadmap / TODO
- Compare & update team fields (description/privacy/parents)
- Optionally remove extra team members / revoke extra repo perms
- Optionally remove extra topics from repos (current behavior: union of all topics)
- Custom default branch for file writes
- Parallel apply with rate‑limit aware workers
- More comprehensive plan diff output
Contributing
PRs welcome! Please:
- open an issue first for larger changes,
- keep commits small & focused,
- add tests where practical,
- run
golangci-lint(if configured).
Security
This tool modifies org membership and repository access. Use dry‑run in CI and restrict credentials using least privilege. Prefer GitHub Apps over PATs.
License
See LICENSE.
Documentation
¶
There is no documentation for this package.