From c8e7a2f7f500712c72098adeb95201877c78b76a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BD=D0=B8=D0=BA?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=90?= =?UTF-8?q?=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=B8=D1=87?= Date: Thu, 4 Jun 2020 21:35:23 +0300 Subject: [PATCH] Initial Commit --- README.md | 21 ++++++++++ main.py | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ props.py | 6 +++ 3 files changed, 146 insertions(+) create mode 100644 README.md create mode 100644 main.py create mode 100644 props.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..5863fcb --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# BitBucket to Gitea migration tool. + +## Description +Using BitBucket API we're getting repos, project of this repo, description and clone link. +Then, using Gitea API, creating organizations(gitea has no projects, but organizations replacing it fully), then starting migration for each repo from BitBucket. + +## Using +* Create authentification token in bitbucket +* Create authentification token in gitea +* Create file props.py with parameters: +``` +BitBucketURL='bitbucket url' +authTokenBB='bitbucket auth token' +GiteaURL='gitea url' +authTokenGitea='gitea auth token' +migrationUsername='user in bb, that have access to all repos' +migrationPassword='password' +``` + +run with +```python3 main.py``` diff --git a/main.py b/main.py new file mode 100644 index 0000000..259db7f --- /dev/null +++ b/main.py @@ -0,0 +1,119 @@ +import props +import requests +import json +import sys +import logging + +#test commit + +logging.basicConfig(level=logging.INFO, filename='migration.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s') + +headersBB = { + 'Authorization': 'Bearer ' + props.authTokenBB +} +headersGitea = { + 'Authorization': 'token ' + props.authTokenGitea, + 'Content-Type': 'application/json' +} + +def getGiteaOrganizationID(orgName): + """ Gitea not accepting organization name as parameter, only it's uid, so we're gonna need to get it from API""" + GiteaOrgsOrgAPIurl = props.GiteaURL + '/api/v1/orgs/' + orgName + try: + GiteaGetOrgResponse = requests.get(GiteaOrgsOrgAPIurl, headers=headersGitea) + GiteaGetOrgResponse.raise_for_status() + except Exception as e: + print("%s, %s" % (e, GiteaGetOrgResponse.text)) + logging.error("%s, %s" % (e, GiteaGetOrgResponse.text)) + else: + GiteaOrgIdResponse = json.loads(GiteaGetOrgResponse.text)['id'] + return GiteaOrgIdResponse + + +def startRepoMigration(cloneUrl, repoName, projectName): + """ we're now have all, that we need, let's start migration """ + print("\nstarting migration of %s......\n" % (repoName)) + logging.info("starting migration of %s......" % (repoName)) + + GiteaRepoAPIurl = props.GiteaURL + '/api/v1/repos/migrate' + uid = getGiteaOrganizationID(projectName) + repoPostData = { + "auth_password": props.migrationPassword, + "auth_username": props.migrationUsername, + "clone_addr": cloneUrl, + # "description": "string", + "issues": True, + "labels": True, + "milestones": True, + "mirror": True, + "private": True, + "pull_requests": True, + "releases": True, + "repo_name": repoName, + "uid": uid, + "wiki": True + } + try: + startRepoMigrationresponse = requests.post(GiteaRepoAPIurl, json = repoPostData, headers = headersGitea) + startRepoMigrationresponse.raise_for_status() + except Exception as e: + print("%s, : Exception: %s, Response: %s" % (repoName, e, startRepoMigrationresponse.text)) + logging.error("%s, : Exception: %s, Response: %s" % (repoName, e, startRepoMigrationresponse.text)) + else: + print("%s %s" % (repoName, startRepoMigrationresponse.text)) + logging.info("%s %s" % (repoName, startRepoMigrationresponse.text)) + +def createGiteaOrganization(projectName, fullName, description): + """ before migration, we're gonna need to create organization, in which project will be stored """ + print("\ncreating organization %s......\n" % (projectName)) + logging.info("creating organization %s......" % (projectName)) + GiteaOrgsAPIurl = props.GiteaURL + '/api/v1/orgs' + orgPostData = { + "username": projectName, + "full_name": fullName, + "description": description, + "repo_admin_change_team_access": True, + "visibility": "private" + } + try: + createGiteaOrganizationresponse = requests.post(GiteaOrgsAPIurl, json = orgPostData, headers = headersGitea) + createGiteaOrganizationresponse.raise_for_status() + except Exception as e: + print("Exception: %s \n Response: %s" % (e, createGiteaOrganizationresponse.text)) + logging.error("Exception: %s \n Response: %s" % (e, createGiteaOrganizationresponse.text)) + else: + print("Response: %s" % (createGiteaOrganizationresponse.text)) + logging.info("Response: %s" % (createGiteaOrganizationresponse.text)) + +def getReposBB(): + """Get all bitbucket repos and it's parameters: clone url, repo name, project name, description.""" + BitBucketAPIurl = props.BitBucketURL + "/rest/api/1.0/repos?limit=1000" + try: + response = requests.get(BitBucketAPIurl, headers=headersBB) + response.raise_for_status() + except Exception as e: + print("Exception: %s \n Response: %s" % (e, response.text)) + logging.error("Exception: %s \n Response: %s" % (e, response.text)) + else: + reposJson = json.loads(response.text)['values'] + for repo in reposJson: + repoName = repo['name'] + projectName = repo['project']['name'] + try: + description = repo['project']['description'] + except KeyError: + description = 'None' + cloneLink = props.BitBucketURL + "/scm/" + projectName + "/" + repoName + ".git" + print("Migrating: repo: %s with description: %s from project: %s via clonelink: %s" % (repoName, description, projectName, cloneLink)) + logging.info("Migrating: repo: %s with description: %s from project: %s via clonelink: %s" % (repoName, description, projectName, cloneLink)) + + createGiteaOrganization(projectName, projectName, description) + startRepoMigration(cloneLink, repoName, projectName) + logging.info("_____________________________________________________________________________") + # sys.exit(1) + + +def main(): + getReposBB() + +main() diff --git a/props.py b/props.py new file mode 100644 index 0000000..d3c24cd --- /dev/null +++ b/props.py @@ -0,0 +1,6 @@ +BitBucketURL='https://bitbucket.example.com' +authTokenBB='bitbucket auth token' +GiteaURL='https://gitea.example.com' +authTokenGitea='gitea auth token' +migrationUsername='user@example.com' +migrationPassword='password'