11import datetime
2- import github
3- from github import Github
2+ import json
43import os
4+ import sys
5+ import urllib .error
6+ import urllib .parse
7+ import urllib .request
58
69"""
710Creates or updates a build status comment on a Pull Request, for branch deployments.
811"""
912
13+ GITHUB_API = "https://api.github.com"
14+
1015SUCCESS_IMAGE_URL = (
1116 "https://raw.githubusercontent.com/dagster-io/dagster-cloud-action/main/assets/success.png"
1217)
1722 "https://raw.githubusercontent.com/dagster-io/dagster-cloud-action/main/assets/failed.png"
1823)
1924
25+
2026def main ():
21- # Fetch various pieces of info from the environment
22- g = Github (os .getenv ("GITHUB_TOKEN" ))
27+ token = os .getenv ("GITHUB_TOKEN" )
2328 pr_id = int (os .getenv ("INPUT_PR" ))
2429 repo_id = os .getenv ("GITHUB_REPOSITORY" )
2530 action = os .getenv ("INPUT_ACTION" )
@@ -30,23 +35,7 @@ def main():
3035
3136 location_name = os .getenv ("INPUT_LOCATION_NAME" )
3237
33- repo = g .get_repo (repo_id )
34- pr = repo .get_pull (pr_id )
35-
36- comments = pr .get_issue_comments ()
37- comment_to_update = None
38-
39- # Check if a comment exists on the PR from the github actions user
40- # which is specific to this location name
41- # otherwise we create a new comment
42- for comment in comments :
43- if (
44- comment .user .login == "github-actions[bot]"
45- and "Dagster Cloud" in comment .body
46- and f"`{ location_name } `" in comment .body
47- ):
48- comment_to_update = comment
49- break
38+ comment_to_update_id = _find_existing_comment (token , repo_id , pr_id , location_name )
5039
5140 deployment_url = f"{ org_url } /{ deployment_name } /home"
5241
@@ -64,18 +53,78 @@ def main():
6453
6554 time_str = datetime .datetime .now (datetime .timezone .utc ).strftime ("%b %d, %Y at %I:%M %p (%Z)" )
6655
67- message = f"""
56+ body = f"""
6857Your pull request is automatically being deployed to Dagster Cloud.
6958
7059| Location | Status | Link | Updated |
71- | ----------------- | --------------- | ------- | --------------- |
60+ | ----------------- | --------------- | ------- | --------------- |
7261| `{ location_name } ` | { status_image } | { message } | { time_str } |
7362 """
7463
75- if comment_to_update :
76- comment_to_update .edit (message )
64+ if comment_to_update_id is not None :
65+ _request (
66+ "PATCH" ,
67+ f"{ GITHUB_API } /repos/{ repo_id } /issues/comments/{ comment_to_update_id } " ,
68+ token ,
69+ {"body" : body },
70+ )
7771 else :
78- pr .create_issue_comment (message )
72+ _request (
73+ "POST" ,
74+ f"{ GITHUB_API } /repos/{ repo_id } /issues/{ pr_id } /comments" ,
75+ token ,
76+ {"body" : body },
77+ )
78+
79+
80+ def _find_existing_comment (token , repo_id , pr_id , location_name ):
81+ # Check if a comment exists on the PR from the github actions user
82+ # which is specific to this location name
83+ page = 1
84+ while True :
85+ url = (
86+ f"{ GITHUB_API } /repos/{ repo_id } /issues/{ pr_id } /comments"
87+ f"?per_page=100&page={ page } "
88+ )
89+ comments = _request ("GET" , url , token )
90+ if not comments :
91+ return None
92+ for comment in comments :
93+ user_login = (comment .get ("user" ) or {}).get ("login" )
94+ body = comment .get ("body" ) or ""
95+ if (
96+ user_login == "github-actions[bot]"
97+ and "Dagster Cloud" in body
98+ and f"`{ location_name } `" in body
99+ ):
100+ return comment ["id" ]
101+ if len (comments ) < 100 :
102+ return None
103+ page += 1
104+
105+
106+ def _request (method , url , token , payload = None ):
107+ data = None
108+ headers = {
109+ "Accept" : "application/vnd.github+json" ,
110+ "X-GitHub-Api-Version" : "2022-11-28" ,
111+ "User-Agent" : "dagster-cloud-action" ,
112+ }
113+ if token :
114+ headers ["Authorization" ] = f"Bearer { token } "
115+ if payload is not None :
116+ data = json .dumps (payload ).encode ("utf-8" )
117+ headers ["Content-Type" ] = "application/json"
118+ req = urllib .request .Request (url , data = data , headers = headers , method = method )
119+ try :
120+ with urllib .request .urlopen (req ) as resp :
121+ body = resp .read ()
122+ if not body :
123+ return None
124+ return json .loads (body )
125+ except urllib .error .HTTPError as err :
126+ print (f"GitHub API { method } { url } failed: { err } " , file = sys .stderr )
127+ raise
79128
80129
81130if __name__ == "__main__" :
0 commit comments