Migrating from GitHub to Gitea
Tags: git, python, systemadministration, automation
Published: 2018-12-23 00:07:53

---
title: Migrating from GitHub to Gitea
published: true
description: Automating a move from Github to private Git infrastructure
tags: git, python, system-administration, automation
---

I recently made the move, for a variety of [reasons](https://github.com/taotetek/WhyILeftGithub/blob/master/README.md), from a public Github profile to private git infrastructure. One of the solutions I tried was Gitea, an opensource, self-hosted solution with a Github-like UI and a very accessible API. 

Gitea has facilities in the UI to import repositories, but I had a lot of repos to recreate, and wanted to migrate quickly, so I wrote a script to consume both ends' APIs:

Import the Github python client, and the `os`, `re    uests`, and `json` packages into your script, and plugin your Github and Gitea credentials and endpoint (the server address) information:

```python
from github import Github
import os
import json
import requests

#Github
GH_ACCESS_TOKEN = os.environ['GH_ACCESS_TOKEN']
#Gitea
GITEA_ACCESS_TOKEN = os.environ['GITEA_ACCESS_TOKEN']
GITEA_USER = ""
GITEA_PASS = ""
TARGET_HOST = "https://git.yourserver.co"
MIGRATE_URI = "/api/v1/repos/migrate"
ENDPOINT = "%s%s" % (TARGET_HOST, MIGRATE_URI)

g = Github(GH_ACCESS_TOKEN)

EXCLUDE = []
```

and in `EXCLUDE`, put in a comma-delimited list of repo names from Github you don't want to migrate, i.e.:

```python
EXCLUDE = ["repo1", "repo2"...]
```

Our first function will just build a list of your repos, and some pertinent information relevant to Gitea required for create a new repo on that end, mostly just the name, description, whether or not it's private, and the URL to clone from:

```python
def getRepos(g):
	repos = []
	for repo in g.get_user().get_repos():
			r = {}
			r['name'] = str(repo.name)
			r['url'] = str(repo.url)
			r['description'] = str(repo.description)
			r['private'] = str(repo.private)
    		repos.append(r)
	return repos
```

This returns a list of dictionaries structured like:

```
{"name": "repo_name", "url": "https://github.com/...", ... }
```

The next function we'll start will ingest an object like the one above to create a new respository:

```python
def createRepo(source_url,name,description,private):
	headers = { "accept": "application/json", "content-type": "application/json" }
	headers["Authorization"] = "token %s" % (GITEA_ACCESS_TOKEN)

	migrate_data = { "mirror": "false",  "uid": 1 }
	migrate_data["auth_password"] = "%s" % (GITEA_PASS)
	migrate_data["auth_username"] = "%s" % (GITEA_USER)
	migrate_data["description"] = "%s" % (description)
	migrate_data["repo_name"] = "%s" % (name)
	migrate_data["private"] = "%s" % (private)
	migrate_data["clone_url"] = "%s" % (source_url)
...
```

The above is creating the required authentication headers, and then the request body with the repo data we specified in the `getRepos` function. We'll finish this function by sending this request:

```python
...

	try:
		r = requests.post(url=ENDPOINT, data=json.dumps(migrate_data), headers=json.dumps(headers))

		if r.status_code != 200:
			return "Non-OK Response: %s" % (r.status_code)
		else:
			return "Done: %s" % (source_url)
	except Exception as e:
		return e
```

Now, to connect these two tasks together, we're going to create a handler to create the repository list, and then instantiate our second function to create the new repo from it:

```python
def runMigration(r,x):
	exclude_repos = x
	for repo in r:
		if repo not in exclude_repos:
			print "Working on %s" % (repo['name'])
			print createRepo(repo['url'],repo['name'],repo['description'],repo['private'])
		else:
			print "Excluding %s" % (repo['name'])
	return "Done"
```

You'll see this iterates the repo list, checks that you have not excluded it, and then creates the new repo. 

Putting it all together, it will look like this, and be ready to run:

[Github Migration Script](https://bitbucket.org/snippets/jmarhee/Eea5gn)

For whatever your given git solution, a script like this can similarly process data from Github, and create new repos on the new host (if it has an API, a similar flow for your `createRepo` function will likely suffice! However, you can use that fed data, and use a library like [GitPython](https://pypi.org/project/GitPython/) to create the new clone locally, etc.)--this can help make such a move to a decentralized platform just that much more painless!