Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
Signed-off-by: Tim Beermann <beermann@osism.tech>
  • Loading branch information
Tim Beermann committed Mar 21, 2023
0 parents commit 7f5594a
Show file tree
Hide file tree
Showing 22 changed files with 1,142 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[flake8]
ignore = E501
37 changes: 37 additions & 0 deletions .github/workflows/build_container.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
name: Build GHOM

"on":
workflow_dispatch:
push:
branches:
- 'main'
paths:
- 'Dockerfile'
- 'requirements.txt'
- 'ghom'

jobs:
build-ghom:
runs-on: ubuntu-latest
steps:
- name: Clone current repository
uses: actions/checkout@v3

- name: Build using buildah
id: build
uses: redhat-actions/buildah-build@v2
with:
image: ghcr.io/tibeer/ghom
tags: ghcr.io/tibeer/ghom:latest
containerfiles: |
./Containerfile
- name: Push to ghcr.io
uses: redhat-actions/push-to-registry@v2
with:
image: ${{ steps.build.outputs.image }}
tags: ${{ steps.build.outputs.tags }}
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ github.token }}
34 changes: 34 additions & 0 deletions .github/workflows/ghom_workflow.yml.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
name: Run GHOM

"on":
workflow_dispatch:
push:
branches:
- 'main'
paths:
- 'ghom.yaml'

jobs:
run-ghom:
permissions: write-all
runs-on: ubuntu-latest
steps:
- name: Clone current repository
uses: actions/checkout@v3
# If you use this workflow on a private repository, uncommit this and adapt accordingly
#with:
# repository: tibeer/ghom
# token: ${{ secrets.GITHUB_TOKEN }}

- name: Run ghom
uses: tibeer/ghom@main
with:
ghom_token: ${{ secrets.ghom_token }}
# The default path of your ghom config file. Please note that this has to be an
# absolute path (/github/workspace is the default path for your checked our repo)
#ghom_config: '/github/workspace/ghom.yaml'
# Enable debug mode. Do not perform any changes, only print what would be done.
# Please note, that this might result in a few errors, because ghom requires
# changes to be made for depencies (e.g. team-repos require repos to be available).
#ghom_dry: 'False'
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.py[cod]
11 changes: 11 additions & 0 deletions Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM python:3.10

WORKDIR /usr/src/app

COPY requirements.txt ./

RUN pip install --no-cache-dir -r requirements.txt

COPY ghom /usr/local/lib/python3.10/site-packages/ghom

ENTRYPOINT ["/usr/local/bin/python", "-m", "ghom.main"]
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# GHOM - GitHub Organization Manager - WIP!!!

Ghom is a tool to manage your GitHub organisation.
Currently work in progress.

## How to use

In any case you need to change the settings in your organization to allow changes from actions. Head over to <https://github.com/organizations/YOUR_ORG/settings/actions>, scroll down to _Workflow permissions_ and select __Read and write permissions__. Otherwise github actions cannot change settings on your organization.

### Automated (recommended)

1. Create a fresh new GitHub organization. You may use ghom also on an existing org, but I will not guarantee for flawless integration. In any case: Use with caution.
2. Create a repository containing a `ghom.yaml` file.
3. Create a workflow like shown [here](.github/workflows/ghom_workflow.yml.example) in the same repository.
4. Trigger the workflow it by either merging a PR to main (containing a change in `ghom.yaml`) or by manual execution.

### Manual

```sh
export GITHUB_REPOSITORY_OWNER=ghomtest
export INPUT_GHOM_CONFIG=ghom.yaml
export INPUT_GHOM_TOKEN=ghp_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
export INPUT_GHOM_DRY=False
python3 -m ghom.main
```

## FAQ

Q: How to deal with private repositories?\
A: Look [here](docs/private_repositories.md)

Q: Why do you have to use a GHP token?\
A: A GitHub app would require a running server. I could provide one, but this would have the drawback, that the rate limit would affect all users simultaniously. Either we "gain" more possible requests than needed. Or a user with a humoungus organization size installs the app and will block the app for all users...

Q: How to deal with my large organization that is too large to fit into 5000 api requests per hour?\
A: Switch back to manual adjustment or split the ghom file into multiple parts. The principle is basically the same as if you would use [private repositories](docs/private_repositories.md). If you have another (elegant) solution, let me know!

Q: Why do repositories have to be initialized with the default README.md file?\
A: Otherwise branch protections cannot be set.

Q: Why is the code so redundant?\
A: To keep it simple. If you have a solution, that removes redundant code while keeping it easy to maintain and understand, feel free to create a pull request.

Q: Why is there no script to generate a `ghom.yaml` file from an existing org?\
A: I had no interest in creating one yet. Chances are low that I find the motivation in the future :)

## Known issues

Branch protection rules are a bit flanky. You can only delete them, if default rules are set. Leaving them empty would result in keeping the current rules.

If you create a new team, the owner of the organization will be added automatically to this team. Therefore you'll see first the creation of the and and second the deletion of a team member. This behavior is due to GitHub internal handeling of these API requests and cannot be changed.
21 changes: 21 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
name: 'ghom-ghom'
description: 'GitHub Organization Manager'
inputs:
ghom_token:
description: 'Provide a user GHP (as a secret)'
required: true
ghom_config:
description: 'Provide an alternative path to the ghom config file'
required: false
default: "/github/workspace/ghom.yaml"
ghom_dry:
description: 'Enable dry run mode'
required: false
default: "False"
runs:
using: 'docker'
image: 'docker://ghcr.io/tibeer/ghom:1.0.0'
branding:
color: white
icon: users
16 changes: 16 additions & 0 deletions docs/private_repositories.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Private repositories

You can split `ghom.yaml` files into multiple parts or even across different repositories.
Both methods have in common that you require more than one workflow.

Because of this, one workflow might interfer with the other one, especially when it comes to deletion.
Let's assume the following scenario:

- Workflow A takes care of public repositories
- Workflow B takes care of private repositories and also teams (only global teams, not repo specific ones), because they should be kept private

If workflow A has `allow_team_removal` set to __true__, it will most likely happen that all your teams managed by workflow B will be deleted. This is not a flaw in the code but rather originates from the design conzept. Ghom indends to be idempotent, so it works as expected.

Rather use multiple ghom files, all with e.g. `allow_team_removal` all set to __false__ except for one file. This file should then also contain all teams.

By using this method you can A) hide sensitive content in private repositories and B) can bypass API rate limits. Though, you might need multiple bot accounts with seperate GHP tokens.
54 changes: 54 additions & 0 deletions docs/release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Release

## How to create a release

This is mainly for @tibeer to create a new release of this action.

1. Tag the container with a new version:

Always create a new tag for all three possible tags: `major`, `major.minor`, `major.minor.patch`

```sh
# define new tag
export MAJOR=1
export MINOR=51
export PATCH=3
# get latest image
podman pull "ghcr.io/tibeer/ghom:latest"
# push new tags
podman push "ghcr.io/tibeer/ghom:latest" "ghcr.io/tibeer/ghom:${MAJOR}"
podman push "ghcr.io/tibeer/ghom:latest" "ghcr.io/tibeer/ghom:${MAJOR}.${MINOR}"
podman push "ghcr.io/tibeer/ghom:latest" "ghcr.io/tibeer/ghom:${MAJOR}.${MINOR}.${PATCH}"
# also remove latest image
podman image rm "ghcr.io/tibeer/ghom:latest"
```

2. Change the `action.yml` file container tag to the most detailed version: `major.minor.patch`
3. Tag the repository with a new version

```sh
# define new tag
export MAJOR=1
export MINOR=51
export PATCH=3
# tag current state
git tag "${MAJOR}" main
git tag "${MAJOR}.${MINOR}" main
git tag "${MAJOR}.${MINOR}.${PATCH}" main
# push tags
git push origin "${MAJOR}"
git push origin "${MAJOR}.${MINOR}"
git push origin "${MAJOR}.${MINOR}.${PATCH}"
```

4. Create a new release: <https://github.com/tibeer/ghom/releases/new>

## Release pattern

We'll use [semver](https://semver.org/) vor versioning (and we'll not use a stupid "v" prefix).

1. Major: Something drastically changes (e.g. PyGithub is replaced by something else, ghom config file is not backwards compatible)
2. Minor: Functionality is added
3. Patch: Bug fixes

Testing will always be done on the "latest" tag.
97 changes: 97 additions & 0 deletions ghom.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
---
allow_team_removal: true
allow_team_repo_removal: true
allow_team_member_removal: true
allow_member_removal: true
allow_label_removal: true
allow_repository_removal: false
owners:
- tibeer
members:
- tibeerbot
teams:
admins:
description: ""
private: false
maintainers:
- tibeerbot
members:
- tibeerbot
maintainers:
description: ""
private: false
maintainers:
- tibeerbot
ops:
description: "Ops team"
private: false
repository_defaults:
has_wiki: false
has_issues: true
has_projects: false
has_downloads: false # no idea, what this sets, cannot find it
allow_squash_merge: true
allow_merge_commit: false
allow_rebase_merge: false
delete_branch_on_merge: true
homepage: ""
description: ""
private: false
default_branch_protection:
branch_name: main
active: true
required_pull_request_review_count: 0 # 1-6, 0 to disable
required_pull_request_owner_review: true
enforce_admins: false
#allow_force_pushes: false # Not implemented yet in PyGithub
default_teams:
# permissions can be one of: pull, triage, push, maintain, admin
admins: "admin"
maintainers: "maintain"
repositories:
.github:
archived: false
homepage: "https://github.com/ghomtest"
default_branch_protection:
branch_name: gh_pages
active: false
labels:
- name: documentation
description: "overwrite documentation label colors"
color: a2ffff
- name: addition
description: "special label only for this repo"
color: a00000
teams:
ops: "push"
ghom:
repo02:
repo03:
labels:
- name: bug
description: "Something isn't working"
color: d73a4a
- name: documentation
description: "Improvements or additions to documentation"
color: 0075ca
- name: duplicate
description: "This issue or pull request already exists"
color: cfd3d7
- name: enhancement
description: "New feature or request"
color: a2eeef
- name: good first issue
description: "Good for newcomers"
color: 7057ff
- name: help wanted
description: "Extra attention is needed"
color: 008672
- name: invalid
description: "This doesn't seem right"
color: e4e669
- name: question
description: "Further information is requested"
color: d876e3
- name: wontfix
description: "This will not be worked on"
color: ffffff
Empty file added ghom/__init__.py
Empty file.
Loading

0 comments on commit 7f5594a

Please sign in to comment.