Skip to content

Instantly share code, notes, and snippets.

@shikajiro
Created September 9, 2016 00:29
Show Gist options
  • Save shikajiro/54b971d35b244f43288e7177a6871d45 to your computer and use it in GitHub Desktop.
Save shikajiro/54b971d35b244f43288e7177a6871d45 to your computer and use it in GitHub Desktop.
backlogが出力したcsvファイルをgitlabに登録するスクリプト
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
backlogが出力したcsvファイルをgitlabに登録するスクリプト
user_id は予め登録しておく必要があります。
users に追記してください。
gitlabのtokenは暫定で特定ユーザーのものを利用しています。
使い方
./backlog2gitlab.py project_id gitlab_private_token filename.csv
csvのデータを全て登録する
./backlog2gitlab.py 1234567890 hogehoge tasks.csv
gitlabに登録されているissueをほぼ全て削除する
タスク量が多い場合は複数回実行すること
./backlog2gitlab.py 1234567890 hogehoge clear
"""
import csv
import requests
import sys
from datetime import datetime
BASE_URL = "https://gitlab.com/api/v3"
HEADERS = {}
USERS = {
# backlog_user_id : gitlab_user_id,
1073892321: 694413, # shikajiro
}
def convert_status(bl_status_id):
if bl_status_id == 4:
return "close"
return None
def create_issue(project_id,
title,
description,
assignee_id,
milestone_id,
labels,
created_at,
due_date,
confidential=False,
):
"""
curl --request POST --header "PRIVATE-TOKEN: ybK4qZF4sshtm_hQKzN-" https://gitlab.com/api/v3/projects/1638259/issues?title=Issues%20with%20auth&labels=bug
id integer yes The ID of a project
title string yes The title of an issue
description string no The description of an issue
confidential boolean no Set an issue to be confidential. Default is false.
assignee_id integer no The ID of a user to assign issue
milestone_id integer no The ID of a milestone to assign issue
labels string no Comma-separated label names for an issue
created_at string no Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z (requires admin or project owner rights)
due_date string no Date time string in the format YEAR-MONTH-DAY, e.g. 2016-03-11
"""
url = "{0}/projects/{1}/issues".format(BASE_URL, project_id)
payload = {
"title": title,
"description": description,
"confidential": confidential,
"assignee_id": assignee_id,
"milestone_id": milestone_id,
"labels": labels,
"created_at": datetime.strptime(created_at, "%Y-%m-%d %H:%M").strftime("%Y-%m-%dT%H:%M:00Z"),
"due_date": due_date,
}
res = requests.post(url, headers=HEADERS, data=payload)
print "create issue"
print res.json()
return res.json()
def close_issue(project_id, issue_id):
print "try close issue {0}".format(issue_id)
url = "{0}/projects/{1}/issues/{2}".format(BASE_URL, project_id, issue_id)
payload = {
"state_event": "close",
}
res = requests.put(url, headers=HEADERS, data=payload)
print res.json()
return res.json()
def delete_issue(project_id, issue_id):
print "try delete issue {0}".format(issue_id)
url = "{0}/projects/{1}/issues/{2}".format(BASE_URL, project_id, issue_id)
res = requests.delete(url, headers=HEADERS)
print res.json()
return res.json()
def get_issues(project_id):
print "try get issues"
result = []
for page in range(1, 30):
url = "{0}/projects/{1}/issues?page={2}".format(BASE_URL, project_id, page)
res = requests.get(url, headers=HEADERS)
print res.json()
result.extend(res.json())
return result
def create_note(project_id,
issue_id,
body,
created_at=None):
"""
:param project_id (required) - The ID of a project
:param issue_id (required) - The ID of an issue
:param body (required) - The content of a note
:param created_at (optional) - Date time string, ISO 8601 formatted, e.g. 2016-03-11T03:45:40Z
:return:
"""
url = "{0}/projects/{1}/issues/{2}/notes".format(BASE_URL, project_id, issue_id)
payload = {
"body": body,
# "created_at": created_at,
}
return requests.post(url, headers=HEADERS, data=payload)
def create_milestone(project_id, title, description=None, due_date=None):
url = "{0}/projects/{1}/milestones".format(BASE_URL, project_id)
payload = {
"title": title,
# "description": description,
# "due_date": due_date,
}
print payload
res = requests.post(url, headers=HEADERS, data=payload)
return res.json()
def get_milestones(project_id):
maps = {}
for i in range(1, 4):
url = "{0}/projects/{1}/milestones?page={2}".format(BASE_URL, project_id, i)
res = requests.get(url, headers=HEADERS)
res_json = res.json()
maps.update({j["title"]: j["id"] for j in res_json})
print "get_milestones"
print maps
return maps
if __name__ == "__main__":
p_id = None
csv_file = None
param = sys.argv
if len(param) < 4:
print "Arguments shortage."
quit()
# プロジェクトIDを取得
if len(param) >= 2:
p_id = param[1]
if not isinstance(p_id, int):
print "project_id is not currect."
quit()
if len(param) >= 3:
token = param[2]
if not isinstance(token, str):
print "token is not currect."
quit()
HEADERS = {'PRIVATE-TOKEN': token}
# clear を指定した場合は
if len(param) >= 4:
three = param[3]
if not isinstance(three, str):
quit()
if three == "clear":
print "clear issues"
issues = get_issues(p_id)
for issue in issues:
delete_issue(p_id, issue["id"])
quit()
if ".csv" in three:
csv_file = three
print "start backlog2gitlab. project_id={0} csv_file0{1}".format(p_id, csv_file)
milestones = get_milestones(p_id)
reader = csv.reader(open(csv_file, 'r'))
reader.next()
for row in reader:
kind = row[6].decode('utf-8')
category = row[8].decode('utf-8')
version = row[10].decode('utf-8')
title = row[11].decode('utf-8')
description = row[12].decode('utf-8')
status_id = row[13]
status = row[14].decode('utf-8')
milestone_id = row[17]
milestone_name = row[18].decode('utf-8').strip()
assignee_id = row[21]
assignee_name = row[22].decode('utf-8')
created_at = row[25]
due_date = row[27]
updated_at = row[30]
comment = row[33].decode('utf-8') # 33 after
print(
"kind=" + kind + ", \n" +
"category=" + category + ", \n" +
"version=" + version + ", \n" +
"title=" + title + ", \n" +
"description=" + description + ", \n" +
"status_id=" + status_id + ", \n" +
"status=" + status + ", \n" +
# "priority_id=" + priority_id + ", \n" +
# "priority=" + priority + ", \n" +
"milestone_id=" + milestone_id + ", \n" +
"milestone_name=" + milestone_name + ", \n" +
"assignee_id=" + assignee_id + ", \n" +
"assignee_name=" + assignee_name + ", \n" +
"created_at=" + created_at + ", \n" +
"updated_at=" + updated_at + ", \n" +
"due_date=" + due_date + ", \n" +
"comment=" + comment + "\n\n"
"")
# gitlabに存在しないマイルストーンを追加
if milestone_name and milestone_name not in milestones.keys():
m = create_milestone(p_id, milestone_name)
print m
milestones[milestone_name] = m["id"]
# 種別、カテゴリ、発生バージョンはラベルとして登録
labels = [kind, category, version]
user_id = None
if assignee_id:
user_id = USERS.get(int(assignee_id))
milestone = None
if milestone_name:
milestone = milestones.get(milestone_name)
issue = create_issue(p_id,
title,
description,
user_id,
milestone,
labels,
created_at,
due_date)
# closeタスクはpost時に設定できないので、編集処理にてクローズを行う
if status_id == "4":
close_issue(p_id, issue["id"])
# コメントはcsvの33列目以降に存在するので、列が無くなるまで取得し、登録する
note_index = 33
while True:
print "start create comment index={0}".format(note_index)
if len(row) < note_index:
break
try:
body = row[note_index]
if body:
print "write comment {0} => {1}".format(note_index, body)
create_note(p_id, issue["id"], body)
except IndexError:
print "end comment"
note_index += 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment