forked from dz0ny/create-pr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
165 lines (134 loc) · 4.72 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import requests
from os import environ as env
from contextlib import contextmanager
from dataclasses import dataclass
from pathlib import Path
import json
from dacite import from_dict
import typing as t
from base64 import b64encode, b64decode
@dataclass(frozen=True)
class Sender:
type: str # "User"
login: str # "Codertocat"
id: int # 21031067
url: str # "https://api.github.com/users/Codertocat"
@dataclass(frozen=True)
class Release:
url: str # "https://api.github.com/repos/Codertocat/Hello-World/releases/11248810"
html_url: str # "https://github.com/Codertocat/Hello-World/releases/tag/0.0.1"
id: int # 11248810
node_id: str # "MDc6UmVsZWFzZTExMjQ4ODEw"
tag_name: str # "0.0.1"
target_commitish: str # "master"
created_at: str # "2018-05-30T20:18:05Z"
published_at: str # "2018-05-30T20:18:44Z"
@dataclass(frozen=True)
class Repository:
id: int
name: str # "Hello-World"
full_name: str # "Codertocat/Hello-World"
private: bool # false
description: t.Optional[str] # "Hello-World Repo"
fork: bool # false
url: str # "https://api.github.com/repos/Codertocat/Hello-World"
default_branch: str # "master"
@dataclass(frozen=True)
class Event:
repository: Repository
sender: Sender
release: t.Optional[Release]
@classmethod
def fromPath(cls, event_path: str) -> "Event":
text = Path(event_path).read_text()
data = json.loads(text)
return from_dict(cls, data)
@property
def is_release(self) -> bool:
return bool(self.release)
@property
def base(self) -> str:
return self.repository.url
@dataclass
class File:
type: str # "file"
encoding: str # "base64"
size: int # 5362
name: str # "README.md"
path: str # "README.md"
content: str # "encoded content ..."
sha: str # "3d21ec53a331a6f037a91c368710b99387d012c1"
url: str # "https://api.github.com/repos/octokit/octokit.rb/contents/README.md"
def patch(self, message: str, branch: str) -> dict:
return {
"message": message,
"content": self.content.decode("utf8"),
"sha": self.sha,
"branch": branch,
}
@property
def text(self) -> str:
return b64decode(self.content).decode("utf8")
@text.setter
def text(self, data: str):
self.content = b64encode(data.encode("utf8"))
@classmethod
def fromJSON(cls, data: dict) -> "File":
return from_dict(cls, data)
class GitHub:
http: requests.Session
api = "https://api.github.com"
def __init__(self, repo: str, branch: str, github_token: str):
self.http = requests.Session()
self.http.headers["Authorization"] = f"Token {github_token}"
self.http.headers["Accept"] = "application/vnd.github.v3+json"
self.branch = branch
self.repo = repo
def get(self, path: str) -> File:
res = self.http.get(f"{self.api}/repos/{self.repo}/contents/{path}")
res.raise_for_status()
return File.fromJSON(res.json())
def create_pr(self, title: str, body: str):
res = self.http.post(
f"{self.api}/repos/{self.repo}/pulls",
json={"title": title, "body": body, "head": self.branch, "base": "master"},
)
res.raise_for_status()
return res.json()
def create_branch(self):
res = self.http.get(f"{self.api}/repos/{self.repo}/git/refs/heads/master")
res.raise_for_status()
master = res.json()
res = self.http.post(
f"{self.api}/repos/{self.repo}/git/refs",
json={"ref": f"refs/heads/{self.branch}", "sha": master["object"]["sha"]},
)
res.raise_for_status()
return res.json()
def add(self, file: File, message: str):
res = self.http.put(
f"{self.api}/repos/{self.repo}/contents/{file.path}",
json=file.patch(message, self.branch),
)
res.raise_for_status()
return res.json()
@contextmanager
def commit(repo: str, new_branch: str, token: str) -> "GitHub":
gh: GitHub = GitHub(repo, new_branch, token)
gh.create_branch()
yield gh
# Example
"""
if __name__ == "__main__":
event = Event.fromPath(env["GITHUB_EVENT_PATH"])
if not event.is_release:
raise Exception("This event is not from release")
with commit("gh/repo", f"update_{event.release.tag_name}", env["PTA_TOKEN"]) as gh:
versions = gh.get("bin/runtime/versions")
versions.text: str = versions.text.replace("foo.bar", "def.bar")
gh.add(versions, "Update image to latest version")
gh.create_pr(
"Update image to latest version",
"This updates web image to the latest released version",
)
"""