1
0
Fork 0

feat: github>forgejo migration script

This commit is contained in:
Marc 2024-07-19 20:46:38 -04:00
parent b7887da3ee
commit 0fa2782343
Signed by: marc
GPG key ID: 048E042F22B5DC79
2 changed files with 124 additions and 1 deletions

View file

@ -1,3 +1,27 @@
# bag-of-tricks # bag-of-tricks
Random utilities and one-off scripts. Random utilities and one-off scripts.
## Expectations
Scripts contained here are expected to be runnable via `pipx` and to define their dependencies using [inline
metadata](https://packaging.python.org/en/latest/specifications/inline-script-metadata/#script-type).
```py
# /// script
# dependencies = [
# "package1",
# "package2"
# ]
# ///
import package1
import package2
# Logic
```
## Usage
Provided that scripts have an inline `script` block that defines any extra dependencies they expect, `pipx run <path> ...args` is all that's needed to execute scripts in an isolated environment.

View file

@ -0,0 +1,99 @@
"""
Repository migration script
Facilitates the migration from Github to Forgejo by importing
all public/private repositories owned by the user attached to
the personal token included.
Expects a single argument that points to a json configuration
shaped like Config.
"""
# /// script
# dependencies = [
# "httpx",
# "pydantic"
# ]
# ///
import sys
import httpx
import pydantic
class Config(pydantic.BaseModel):
gh_user: str
gh_token: str
gh_host: str
gh_api_host: str
forgejo_host: str
forgejo_user: str
forgejo_token: str
def get_config(path: str) -> Config:
return Config.parse_file(path)
def get_gh_client(config: Config):
return httpx.Client(
headers={
"Authorization": f"Bearer {config.gh_token}",
"X-Github-Api-Version": "2022-11-28",
},
base_url=config.gh_api_host,
)
def get_forgejo_client(config: Config):
return httpx.Client(
headers={"Authorization": f"token {config.forgejo_token}"},
base_url=config.forgejo_host,
)
def get_repositories_from_github(config: Config) -> list[str]:
"""Gets all repositories for given user."""
with get_gh_client(config) as client:
response = client.get(
f"/user/repos", params={"per_page": 100, "affiliation": "owner"}
)
for repository in response.json():
full_name = repository["full_name"]
if not full_name.startswith(config.gh_user):
print(f"Skipped {full_name}: not owned.")
continue
yield full_name
def migrate_to_forgejo(repository_name: str, config: Config):
with get_forgejo_client(config) as client:
response = client.post(
"/repos/migrate",
data={
"auth_username": config.gh_user,
"auth_token": config.gh_token,
"clone_addr": f"{config.gh_host}/{repository_name}.git",
"repo_name": repository_name.split("/")[1],
},
timeout=None,
)
if response.status_code == 409:
print(f"Did not migrate {repository_name}: already exists")
elif response.status_code == 201:
print(f"Migrated {repository_name}")
if __name__ == "__main__":
config = get_config(sys.argv[1])
for repo in get_repositories_from_github(config):
print(f"Migrating {repo}...")
migrate_to_forgejo(repo, config)