gomgr

command module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 16, 2026 License: Apache-2.0 Imports: 1 Imported by: 0

README

github-org-manager-go (gomgr)

Build Go Reference Go Report Card License GitHub release GitHub issues

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)
  • Rulesets: org-wide and repo-specific guard rails (branch protection, tag protection, push rules) with built-in presets — see Rulesets & guard rails
  • Custom repository roles: fully managed - define in YAML, gomgr creates/updates them (GitHub Enterprise Cloud)
  • Repository topics: add topics/labels to repositories for organization
  • Repository pinning: pin important repositories to organization profile (⚠️ GitHub API limitation: not currently supported for organizations - configuration accepted but manual pinning required via web UI)
  • Optional: create repos that don’t exist (create_repo: true)
  • Optional: inject .github/renovate.json into repos
  • ✅ Warnings & cleanups: unmanaged teams, members without team, unmanaged repos, unmanaged custom roles, unmanaged rulesets
  • Optional hard cleanups: delete unmanaged teams, remove members without team, delete unmanaged repos, delete unmanaged custom roles, delete unmanaged rulesets
  • ✅ Auth: GitHub App (recommended) or PAT
  • --dry plan with state comparison showing current GitHub state vs desired config state
  • ✅ Cross‑platform binaries via GitHub Releases; gomgr version stamped 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

  1. Prepare config directory (example shown below):
<config>/
├─ app.yaml
├─ org.yaml
└─ teams/
   └─ platform-team.yaml
  1. 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>
    
  1. Run a dry run, then apply
gomgr sync -c <config> --dry  # Shows JSON plan + summary of changes
gomgr sync -c <config>         # Actually applies changes

The dry run output includes:

  • Complete JSON plan with all change details
  • Current vs Desired State comparison - shows what exists in GitHub vs what's in your config
  • Summary showing counts by scope and action
  • List of any warnings

Example summary output:

================================================================
Summary of Proposed Changes
================================================================

Current State vs Desired State:
--------------------------------
  Teams:              5 → 6 (+1)
  Team Members:       12 → 14 (+2)
  Repositories:       15 → 18 (+3)
  Repo Permissions:   22 → 28 (+6)

Total changes: 7

Changes by scope:
  repo-file:           3
  repo-pin:            1
  repo-topics:         1
  team-repo:           3

Changes by action:
  ensure:              5
  grant:               3

Warnings: 1
  - Skipping pin for KaMuses/platform-index: GitHub API does not support pinning to organization profiles

================================================================

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
  warn_unmanaged_custom_roles: true  # warn about custom roles not in org.yaml
  warn_unmanaged_rulesets: true      # warn about rulesets not defined in YAML

# 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!)
delete_unmanaged_custom_roles: false # delete custom roles not in org.yaml (DESTRUCTIVE!)
delete_unmanaged_rulesets: false    # delete rulesets not in YAML (removes guard rails!)
create_repo: true                   # create repos if missing when referenced by teams

# Sign every commit gomgr writes with a Signed-off-by trailer. Required when
# the org enforces DCO via a ruleset `commit_message_pattern` rule — gomgr
# commits straight to the default branch, so no pull-request DCO check ever
# runs on them and an unsigned message is rejected at push time.
# Empty (the default) appends nothing.
sign_off: "my-app[bot] <12345+my-app[bot]@users.noreply.github.com>"

# Legacy convenience flags — still honoured, but `files:` is the preferred
# way to declare per-repo content. Legacy flags are materialised into
# FileSpec entries at load time.
add_renovate_config: true
add_default_readme: false
renovate_config: |
  {
    "$schema": "https://docs.renovatebot.com/renovate-schema.json",
    "extends": ["github>DragonSecurity/renovate-presets"]
  }

# Templated files that gomgr ensures exist in every managed repository.
# Each `content` is rendered through Go's text/template package with
# {Org, Repo} as context. `only` restricts an entry to specific repos via
# path.Match-style globs; omitting `only` matches every managed repo.
files:
  - path: README.md
    message: "chore: add README"
    branch: main
    content: |
      # {{.Repo}}

      Part of the [{{.Org}}](https://github.com/{{.Org}}) organization.

  - path: LICENSE
    only:
      - "public-*"
      - "oss-*"
    content: |
      MIT License
      Copyright (c) {{.Org}} ...

  - path: .github/CODEOWNERS
    content: |
      * @{{.Org}}/platform-team
Files & templating (app.files)

The files: list on app.yaml replaces the older add_default_readme / renovate_config special cases with a single mechanism for declaring any file that should exist in every managed repo.

  • path (required): repo-relative path, e.g. README.md, .github/workflows/ci.yml.
  • content (required): Go text/template source. {{.Org}} and {{.Repo}} are available; referencing an unknown field is a hard error at plan time (via missingkey=error).
  • message (optional): commit message; defaults to chore: add <path>.
  • branch (optional): target branch; defaults to main.
  • only (optional): list of path.Match globs against the repo name. Empty/omitted matches every repo.

Legacy add_default_readme and add_renovate_config still work — at load time they are converted into FileSpec entries and prepended to files:. If you list the same path: yourself, your entry overrides the legacy one, so you can keep the flags on and still supply a custom README.

Repository visibility

Advanced repo configs accept a visibility: field: public, private (the default), or internal (GHEC only). It is respected when gomgr creates the repository:

repositories:
  public-docs:
    permission: push
    visibility: public      # created public; pairs well with FileSpec `only: [public-*]`
  internal-playbook:
    permission: push
    visibility: internal    # GHEC-only; visible to the whole enterprise
  private-notes:
    permission: admin       # visibility omitted → private (backwards-compatible)
org.yaml

Define organization owners and custom repository roles:

owners:
  - alice
  - bob

# Custom repository roles (requires GitHub Enterprise Cloud)
# gomgr will create/update these roles automatically
custom_roles:
  - name: actions-manager
    description: Manage GitHub Actions workflows and runners
    base_role: read  # read, triage, write, maintain, admin
    permissions:
      - write_actions
      - read_actions_variables
      - write_actions_variables
      
  - name: release-manager
    description: Create and manage releases
    base_role: write
    permissions:
      - create_releases
      - edit_releases
      - manage_environments

org.yaml is also where organization-wide rulesets live — see Rulesets & guard rails below.

Available Permissions (partial list - see GitHub Docs for full list):

  • Actions: write_actions, read_actions_variables, write_actions_variables
  • Releases: create_releases, edit_releases, delete_releases
  • Environments: manage_environments, read_deployment_environments, write_deployment_environments
  • Runners: admin_self_hosted_runners, read_self_hosted_runners
  • Security: read_code_scanning_alerts, write_code_scanning_alerts, read_secret_scanning_alerts, write_secret_scanning_alerts
  • And many more...
teams/*.yaml
name: Platform Team
slug: platform-team            # optional; default = kebab(name)
description: Core platform engineers
privacy: closed                # closed | secret
parents: []                    # (future enhancement)

# Multiple maintainers (team leads, senior engineers)
maintainers:
  - alice-backend-lead
  - bob-senior-engineer
  - charlie-tech-lead

# Multiple members (regular team members)
members:
  - david-developer
  - emma-engineer
  - frank-junior-dev
  - grace-contractor

repositories:
  # Simple permission string (backward compatible)
  # Built-in roles: pull|triage|push|maintain|admin
  infra: maintain
  
  # Advanced config with topics and pinning
  api:
    permission: push
    topics:
      - backend
      - api
      - project-platform
  
  # Custom repository roles (requires GitHub Enterprise Cloud)
  # Custom roles allow fine-grained permissions like managing GitHub Actions
  # without full repository admin access. Custom roles must be defined in org.yaml
  # and gomgr will create/update them automatically.
  # See: https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-user-access-to-your-organizations-repositories/managing-repository-roles/managing-custom-repository-roles-for-an-organization
  ci-workflows:
    permission: actions-manager  # Custom role name (must be defined in org.yaml)
    topics:
      - cicd
      - github-actions
  
  # Template repository - can be reused by other repos
  # Mark a repository as a template with `template: true`
  # Templates are marked in GitHub and can be inherited by other repos in config
  template-go-api:
    permission: push
    template: true
    topics:
      - backend
      - api
      - go-template
  
  # Repository using template (inherits permission and topics)
  my-api:
    from: template-go-api      # Reference to template repo (currently only same-org supported)
    topics:
      - my-project             # Additional topics (merged with template topics)
    # Will inherit: permission: push, and topics: backend, api, go-template
  
  # Repository using template with override
  admin-api:
    from: template-go-api
    permission: admin          # Override template permission
    topics:
      - admin-service
    # Will inherit topics: backend, api, go-template from template
  
  # Repository with pinning (note: pinning is not supported by GitHub API for organizations)
  platform-index:
    permission: admin
    topics:
      - project-platform
      - documentation
    pinned: true  # Will be shown in plan but skipped with a warning - pin manually via GitHub web UI

Loader ignores non‑YAML files in teams/ and skips empty/invalid entries.


Extended Team Examples

The examples/config/teams/ directory includes comprehensive team definition examples demonstrating various organizational patterns:

Example Teams

Backend Team (backend-team.yaml)

  • Multiple maintainers (team leads, senior engineers)
  • Multiple members (developers, contractors, interns)
  • Demonstrates different permission levels (admin, push, maintain, triage, pull)
  • Shows diverse repository types (APIs, microservices, libraries, documentation)

Frontend Team (frontend-team.yaml)

  • Cross-functional team with specialized roles (React, Vue, UX, accessibility)
  • Web and mobile application management
  • Shared component libraries and design systems

DevOps Team (devops-team.yaml)

  • Infrastructure and CI/CD management
  • Terraform, Kubernetes, and cloud configurations
  • Monitoring, security, and automation repositories

Security Team (security-team.yaml)

  • Uses privacy: secret for sensitive access
  • Read access to multiple repos for security audits
  • Admin access to security-specific repositories
  • Compliance and vulnerability management

GitHub Actions Team (github-actions-team.yaml)

  • Demonstrates custom repository roles (requires GitHub Enterprise Cloud)
  • Shows how to use fine-grained permissions for CI/CD management
  • Examples of custom roles: actions-manager, release-manager, runner-admin, security-scanner
Best Practices Demonstrated
  1. Multiple Maintainers: Include multiple team leads to avoid single points of failure
  2. Diverse Membership: Mix senior engineers, regular developers, contractors, and interns
  3. Descriptive Privacy: Use closed for most teams, secret for sensitive security teams
  4. Clear Descriptions: Write meaningful team descriptions for easy discovery
  5. Permission Hierarchy: Use appropriate permission levels based on responsibility
  6. Topic Organization: Tag repositories with relevant topics for discoverability
  7. Custom Roles: Leverage fine-grained permissions for specialized access patterns

Template Repository Pattern

gomgr supports marking repositories as templates and referencing them from other repositories. This enables consistent configuration across multiple repositories:

Template Repository Features:

  • Mark a repository as a template with template: true
  • Template repositories can define permission and topics that other repos inherit
  • Reference templates using from: template-repo-name (same-org only - cross-org not yet supported)
  • New repositories with from: are created using GitHub's template repository feature
  • Topics are automatically merged (template topics + repo-specific topics)
  • Permissions can be inherited or overridden
  • Templates are marked using the GitHub API's template repository flag

How it works:

  1. Define a template repository with template: true
  2. Other repositories reference it with from: template-name
  3. When creating a new repo with from:, GitHub's CreateFromTemplate API is used
  4. The referencing repo inherits permission (if not specified) and topics from the template
  5. Add repo-specific topics to extend the template's topics
  6. Override permission if needed for specific use cases

Benefits:

  • Consistency across similar repositories (e.g., all microservices)
  • DRY principle - define common configuration once
  • Easy to update multiple repos by changing the template
  • Clear relationships between repos in your configuration

Limitations:

  • Currently only supports same-organization templates
  • Cross-organization template references are not yet supported

Rulesets & guard rails

Rulesets are GitHub's successor to branch protection, and gomgr manages them the same way it manages everything else: declaratively, idempotently, and with a --dry plan you can read before anything changes.

They come in two scopes, and both apply at once — GitHub evaluates every ruleset that matches a push and enforces the strictest outcome, so a repository ruleset tightens the org baseline rather than replacing it:

Scope Declared in Covers
Organization org.yamlrulesets: Every repository the repository_name condition matches
Repository teams/*.yaml → a repo's rulesets: That repository alone
Presets

A preset is a named guard rail. Reference one and you get its target, conditions and rules without restating them:

Preset What it enforces
branch-protection Default branch: no deletion, no force-push, changes via a pull request with 1 approval, stale reviews dismissed, review threads resolved
strict-branch-protection The same, tightened: 2 approvals, code-owner review, last-push approval, linear history
tag-protection Tags cannot be moved or deleted
no-force-push Every branch is append-only. The minimum guard rail if you are not ready to require reviews
require-signed-commits Every commit on the default branch carries a verified signature
require-dco Commit messages must contain Signed-off-by:, enforced at the ref rather than by a pull-request check
no-committed-keys Push rule rejecting .pem, .key, .p12, .pfx, .jks, .keystore, .ppk

Anything you set alongside a preset wins, at whole-rule granularity: naming a rule key replaces the preset's version of that rule outright rather than merging into it field by field. Setting a boolean rule to false switches the preset's version off.

# org.yaml
rulesets:
  - name: default-branch-protection
    preset: branch-protection
    conditions:
      repository_name:
        include: ["~ALL"]
        exclude: ["sandbox-*"]
    bypass_actors:
      - type: Integration
        app: self          # gomgr's own GitHub App — see the warning below
        mode: always

  # Same preset, two approvals instead of one, only on production services.
  - name: production-branch-protection
    preset: branch-protection
    conditions:
      repository_name:
        include: ["svc-*"]
    rules:
      pull_request:
        required_approving_review_count: 2
        require_code_owner_review: true
        required_review_thread_resolution: true
# teams/security-team.yaml
repositories:
  vulnerability-reports:
    permission: admin
    rulesets:
      - name: locked-down-main
        preset: strict-branch-protection
      - name: no-committed-keys
        preset: no-committed-keys
⚠️ Do not lock gomgr out of its own repositories

gomgr commits templated files (app.files, CODEOWNERS, renovate.json) straight to the default branch. A ruleset that requires a pull request or signed commits on that branch rejects those pushes. Either exempt the app:

bypass_actors:
  - type: Integration
    app: self       # resolves to app.app_id; requires GitHub App auth, not a PAT
    mode: always

…or scope the ruleset away from the repositories gomgr writes to. gomgr raises this as a plan warning when it spots the combination, so --dry tells you before the sync does.

Rolling a guard rail out safely

Set enforcement: evaluate to have GitHub record what would have been blocked without blocking it. Read the ruleset's insights page, then flip to active.

  - name: require-ci-green
    target: branch
    enforcement: evaluate     # active | evaluate | disabled
    conditions:
      ref_name:
        include: ["~DEFAULT_BRANCH"]
      repository_name:
        include: ["~ALL"]
    rules:
      required_status_checks:
        strict: true
        checks:
          - context: build
          - context: test
Reference

Ruleset fields

Field Notes
name Required. Also the identity gomgr matches on, case-insensitively
preset Optional built-in guard rail (table above)
target branch (default), tag, or push
enforcement active (default), evaluate, or disabled
conditions.ref_name include / exclude fnmatch patterns, plus ~ALL and ~DEFAULT_BRANCH. Defaults to ~ALL; not used by push rulesets
conditions.repository_name include / exclude / protected. Organization rulesets only; defaults to ~ALL
bypass_actors Who may bypass. Compared exactly — an actor nobody configured is removed
rules The rules themselves

Bypass actors

bypass_actors:
  - type: Team
    team: platform-team       # slug, resolved to a team ID
    mode: pull_request        # always | pull_request (default always)
  - type: Integration
    app: self                 # "self" or a numeric GitHub App ID
  - type: RepositoryRole
    actor_id: 5               # role ID from the repository-roles API
  # Identified by type alone — these take no ID:
  - type: OrganizationAdmin
  - type: EnterpriseOwner
  - type: DeployKey

OrganizationAdmin, EnterpriseOwner and DeployKey are recognized by their type; GitHub reports them with no actor_id and gomgr sends none. Team, Integration and RepositoryRole each need an identity — a slug, an app, or a role ID respectively.

Role IDs are not guessable and gomgr does not map role names to them; read the IDs your organization actually uses from the repository roles API.

Rules

Branch and tag targets: creation, update, deletion, required_linear_history, required_signatures, non_fast_forward, pull_request, required_status_checks, required_deployments, merge_queue, commit_message_pattern, commit_author_email_pattern, committer_email_pattern, branch_name_pattern, tag_name_pattern, workflows, code_scanning.

Push target: file_extension_restriction, file_path_restriction, max_file_path_length, max_file_size. Push rulesets need GitHub Enterprise Cloud on private repositories.

gomgr validate -c <config> checks all of this offline — unknown presets, invalid enumerations, duplicate names, and rules used on the wrong target — so you find mistakes before GitHub answers with an opaque 422.

Cleanup

warn_unmanaged_rulesets: true reports rulesets that exist on GitHub but are not in your YAML. delete_unmanaged_rulesets: true removes them. Rulesets inherited from the organization or an enterprise are never touched at the repository scope — they are not that scope's to delete.


Custom Repository Roles Management

Requires GitHub Enterprise Cloud

gomgr now fully manages GitHub's custom repository roles, automatically creating and updating them based on your configuration. Custom roles allow fine-grained permissions beyond the standard roles (pull, triage, push, maintain, admin).

Key Features:

  • Automated Role Management: Define roles in org.yaml and gomgr creates/updates them automatically
  • Fine-grained permissions: Grant access to specific capabilities (Actions, runners, secrets, environments)
  • Separation of concerns: Allow CI/CD management without code modification access
  • Idempotent updates: Roles are kept in sync with your configuration
  • Optional cleanup: Warn about or delete unmanaged custom roles

Configuration Workflow:

  1. Define roles in org.yaml:

    custom_roles:
      - name: actions-manager
        description: Manage CI/CD workflows
        base_role: read
        permissions:
          - write_actions
          - read_actions_variables
          - write_actions_variables
    
  2. Use role names in team configurations:

    # teams/cicd-team.yaml
    repositories:
      ci-workflows:
        permission: actions-manager  # Custom role
        topics: [cicd, github-actions]
    
  3. Apply configuration - gomgr will:

    • Create custom roles if they don't exist
    • Update roles if configuration changed
    • Warn about unmanaged roles (if configured)
    • Optionally delete unmanaged roles (if configured)

Example Use Cases:

  • Actions Manager: Manage workflows, runners, and secrets without code access
  • Release Manager: Create releases and manage deployment environments
  • Security Scanner: Configure security scanning without repository admin access
  • Runner Admin: Manage self-hosted runners for CI/CD infrastructure

Order of Operations:

  1. Custom roles are created/updated first (before teams/repositories)
  2. Teams can then use the custom roles in repository permissions
  3. Custom roles are deleted last (if cleanup is enabled)

Configuration Options (app.yaml):

dry_warnings:
  warn_unmanaged_custom_roles: true  # Warn about roles not in config

delete_unmanaged_custom_roles: false  # Delete roles not in config (DESTRUCTIVE!)

Important Notes:

  • Custom roles require GitHub Enterprise Cloud
  • Role creation requires "Custom repository roles" (write) or "Administration" (write) permission
  • Once created, roles can be assigned to teams just like built-in roles
  • See examples/config/org.yaml for complete examples

Project Organization Pattern

gomgr supports organizing repositories by project with topics, pinning, and naming conventions:

Note: Repository pinning is not currently supported by the GitHub API for organization profiles. The pinned field is accepted in configuration but the actual pinning operation will be skipped with a warning. You can manually pin repositories through the GitHub web interface.

Example: Multi-repo project setup

  1. Define a project name (slug), e.g., platform
  2. Prefix all project repositories: platform-api, platform-web, platform-infra
  3. Tag all repos with topic: project-platform
  4. Create an index repository: platform-index with README linking to all project repos
  5. Pin the index repo to make it prominent on the org profile (must be done manually via GitHub web UI due to API limitations)

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 index repository (can be manually pinned via GitHub web UI)
  • Maintain consistent naming and organization across projects

Auth & Permissions

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.

Required Organization Permissions:

Core features:

  • Members: Read/Write - manage org members
  • Administration: Read/Write - manage teams and repositories
    • Or minimum: Teams: Read/Write + Repository: Administration (Read/Write)
  • Metadata: Read - read org metadata

Custom Repository Roles (if using this feature):

  • Custom repository roles: Read/Write - create and manage custom roles
    • Alternative: Administration: Read/Write (includes custom roles)

Required Repository Permissions:

  • Administration: Read/Write - grant team access, create repos, mark templates
  • Contents: Read/Write - create files (if using Renovate config injection or default README)
  • Metadata: Read - read repository metadata

Note: If you don't use certain features (e.g., creating repos, custom roles, file injection), you can reduce permissions accordingly.

Personal Access Token (PAT)

Use a classic PAT with scopes:

  • admin:org - manage teams, members, and custom repository roles
  • repo - set team repo access, create repos, and manage repository settings
  • read:org - read org metadata

Fine-grained PAT (alternative):

  • Organization permissions: Administration (Read/Write), Custom repository roles (Read/Write)
  • Repository permissions: Administration (Read/Write), Contents (Read/Write)

CLI

  • gomgr sync -c <config> [--dry] [--debug]
    Plans and applies org state. With --dry, shows a JSON plan followed by a human-readable summary of proposed changes without applying them.

  • 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 custom roles → create teams → set memberships → ensure repos → mark templates → grant permissions → write files (renovate/readme) → set topics → pin repos → cleanups (optional) → delete custom roles (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 version via -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/gomgr --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"

Development

Testing

The project includes a comprehensive test suite and Makefile for development:

# Run all tests
make test

# Run tests with coverage report
make test-coverage

# Run verbose tests
make test-verbose

# Check code formatting
make fmt-check

# Format code
make fmt

# Run go vet
make vet
Code Quality Tools

Install development tools (golangci-lint, gosec):

make install-tools

Run code quality checks:

# Run linter
make lint

# Run security scanner
make security

# Run all basic checks (format, vet, test)
make check

# Run all checks including lint and security
make check-all
Building
# Build binary
make build

# Clean build artifacts
make clean

# Run full CI pipeline
make ci
CI/CD

The repository includes GitHub Actions workflows:

  • .github/workflows/ci.yaml: Runs tests, linting, and security checks on every push/PR
  • .github/workflows/release.yaml: Builds and releases binaries on version tags

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 version shows dev: build without -ldflags -X or not from a tag. Use the release workflow or pass a version when building.
  • Renovate config not created: ensure add_renovate_config: true and renovate_config is non‑empty; repo must exist or create_repo: true.
  • Repository pinning warnings: The GitHub API does not support pinning repositories to organization profiles programmatically. The pinned: true configuration is accepted but the operation is skipped with a warning. You must manually pin repositories through the GitHub web interface.
  • Template reference not found: ensure the template repository is defined in the same team configuration or another team file with template: true set. Cross-organization templates are not yet supported.
  • Custom role not found: ensure custom roles are defined in org.yaml before using them in team repository permissions. Custom roles require GitHub Enterprise Cloud.

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 make check before submitting (or make check-all for full checks including linting),
  • ensure make build succeeds.

See the Development section above for available commands and tooling.


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

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal
gh

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL