feat: draft version

This commit is contained in:
2021-01-03 15:10:47 +03:00
parent f003ed21cd
commit 884bc0aa97
19 changed files with 494 additions and 0 deletions

0
src/__init__.py Normal file
View File

65
src/db.py Normal file
View File

@@ -0,0 +1,65 @@
import datetime
from sqlalchemy import create_engine, Column, Integer, Unicode, Boolean, Float, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.ext.declarative import declarative_base
from src.settings import DB_PATH
Base = declarative_base()
class TaskStatus:
Error = 0
InQueue = 1
Success = 2
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
# updated_at = Column(
# "updated_at", Integer, onupdate=lambda: int(datetime.datetime.now().timestamp())
# )
opt_out = Column(Boolean, default=False, nullable=False)
name = Column(Unicode(120), nullable=False, index=True, unique=True)
class Repository(Base):
__tablename__ = "repositories"
id = Column(Integer, primary_key=True)
user_id = Column(ForeignKey("users.id"), nullable=False)
user = relationship(User)
tasks = relationship("AnalyzeTask")
name = Column(Unicode(120), nullable=False, index=True)
stargazers_count = Column(Integer, nullable=False)
fork = Column(Boolean, nullable=False)
default_branch = Column(Unicode(80), nullable=False)
archived = Column(Boolean, nullable=False)
updated_at = Column(Integer, comment="Value from GitHub API", nullable=False, index=True)
created_at = Column(Integer, comment="Value from GitHub API", nullable=False)
size = Column(Integer, nullable=False, comment="Value from GitHub API")
private = Column(Boolean, nullable=False)
def get_clone_url(self):
return f"git@github.com:{self.user.name}/{self.name}"
class AnalyzeTask(Base):
__tablename__ = "analyze_tasks"
id = Column(Integer, primary_key=True)
repository_id = Column(ForeignKey("repositories.id"), nullable=False)
status = Column(Integer, default=TaskStatus.InQueue,nullable=False, index=True)
repository = relationship(Repository)
clone_duration = Column(Float, default=0., nullable=False, index=True)
duration = Column(Float, default=0., nullable=False, index=True)
created_at = Column(Integer, default=lambda: int(datetime.datetime.now().timestamp()), nullable=False, index=True)
worker = Column(Unicode(80), default="", nullable=False, index=True)
level = Column(Integer, default=0, nullable=False)
url = Column(Unicode(200), default="", nullable=False)
improvement_absolute = Column(Integer, default=0, nullable=False, index=True)
improvement_relative = Column(Float, default=0., nullable=False, index=True)
_engine = create_engine(DB_PATH)
DBSession = sessionmaker(bind=_engine)

45
src/git.py Normal file
View File

@@ -0,0 +1,45 @@
import logging
import subprocess
import os
import shlex
from src.settings import GIT_PRIVATE_KEY_PATH
_logger = logging.getLogger(__name__)
_logger.addHandler(logging.NullHandler())
os.environ['GIT_SSH_COMMAND'] = f"ssh -i {shlex.quote(GIT_PRIVATE_KEY_PATH)} -o IdentitiesOnly=yes"
def _check_preconditions():
assert subprocess.check_call(["git", "--version"]) == 0
def clone_repo(ssh_url: str, path: str):
subprocess.check_call(["git", "clone", ssh_url, path], stdout=subprocess.DEVNULL)
def create_and_open_branch(repo_path: str, branch_name: str):
subprocess.check_call(
["git", "checkout", "-b", branch_name], cwd=repo_path, stdout=subprocess.DEVNULL
)
def commit_and_push(repo_path: str, commit_message: str):
subprocess.check_call(["git", "add", "."], cwd=repo_path, stdout=subprocess.DEVNULL)
subprocess.check_call(
["git", "commit", "-m", commit_message], cwd=repo_path, stdout=subprocess.DEVNULL
)
branches = subprocess.check_output(
["git", "branch"], cwd=repo_path
).decode("utf-8")
current_branch = next(filter(lambda x: x.startswith("*"), branches.splitlines()))[1:].strip()
_logger.info(f"pushing branch {current_branch} in repo {repo_path}")
subprocess.check_call(
["git", "push", "--set-upstream", "origin", current_branch],
cwd=repo_path,
stdout=subprocess.DEVNULL,
)
_check_preconditions()

46
src/github.py Normal file
View File

@@ -0,0 +1,46 @@
import logging
import subprocess
from github import Github, Repository, PullRequest
_logger = logging.getLogger(__name__)
_logger.addHandler(logging.NullHandler())
_g = Github("993d405e652f72a58f64750a7cd6ac9052e01bd2")
user_login = _g.get_user().login
# def _fork_repo(r: Repository) -> Repository:
# r = _g.get_user().create_fork(r)
# return r
# print(r.size, r.stargazers_coun>t)
def create_fork(r: Repository) -> Repository:
return _g.get_user().create_fork(r)
def to_repository(full_name: str) -> Repository:
return _g.get_repo(full_name)
def get_possible_repos():
return [_g.get_repo("AlekseyLobanov/CrossGen")]
def create_pr(
base_repo: Repository, branch: str, title: str, body: str, master: str = "master"
) -> PullRequest:
base_repo.create_pull(
title=title,
body=body,
head=f"{user_login}:{branch}",
base=master,
draft=True,
maintainer_can_modify=True,
)
def is_for_fork(r: Repository):
return not r.fork

106
src/messages.py Normal file
View File

@@ -0,0 +1,106 @@
import datetime
import platform
from typing import Optional
class AnalyzeTask:
def __init__(self):
self.created_at = 0
self.url = ""
self.level = -1
self.task_id = -1
@classmethod
def from_data(cls, data):
res = cls()
res.created_at = data["created_at"]
res.url = data["url"]
res.level = data["level"]
res.task_id = data["task_id"]
return res
@property
def data(self):
return {
"created_at": self.created_at,
"url": self.url,
"level": self.level,
"task_id": self.task_id,
}
class AnalyzeResponse:
def __init__(self):
self.created_at = 0
self.url = ""
self.level = -1
self.task_id = -1
self.clone_duration = 0.0
self.duration = 0.0
self.improvement_absolute = 0
self.improvement_relative = 0
self.worker = ""
@classmethod
def from_data(cls, data):
res = cls()
res.created_at = data["created_at"]
res.url = data["url"]
res.level = data["level"]
res.task_id = data["task_id"]
res.duration = data["duration"]
res.clone_duration = data["clone_duration"]
res.worker = data["worker"]
res.improvement_absolute = data["improvement_absolute"]
res.improvement_relative = data["improvement_relative"]
return res
@property
def data(self):
if self.task_id < 0:
raise RuntimeError("No task_id")
return {
"created_at": self.created_at,
"url": self.url,
"level": self.level,
"task_id": self.task_id,
"duration": self.duration,
"clone_duration": self.clone_duration,
"worker": self.worker,
"improvement_absolute": self.improvement_absolute,
"improvement_relative": self.improvement_relative,
}
def create_analyze_task(url: str, level: int, task_id: Optional[int] = None) -> AnalyzeTask:
res = AnalyzeTask()
res.created_at = int(datetime.datetime.now().timestamp())
res.url = url
res.level = level
res.task_id = task_id
return res
def create_analyze_response(
task: AnalyzeTask,
initial_size: int,
final_size: int,
duration: float,
worker: str = platform.node(),
clone_duration: float = 0,
) -> AnalyzeResponse:
res = AnalyzeResponse()
res.created_at = task.created_at
res.url = task.url
res.level = task.level
res.task_id = task.task_id
res.clone_duration = clone_duration
res.duration = duration
res.worker = worker
if initial_size < 100:
res.improvement_absolute = res.improvement_relative = 0
else:
res.improvement_absolute = initial_size - final_size
res.improvement_relative = 1 - final_size / initial_size
return res