@@ -95,6 +95,105 @@ def fetch_github_actions_artifacts(token, version):
9595 return download_artifacts_github_actions (session , token , run_url )
9696
9797
98+ def wait_for_build_complete_circleci (session , token , pipeline_id ):
99+ while True :
100+ response = session .get (
101+ f"https://circleci.com/api/v2/pipeline/{ pipeline_id } /workflow" ,
102+ headers = {
103+ "Circle-Token" : token ,
104+ },
105+ )
106+ response .raise_for_status ()
107+ status = response .json ()["items" ][0 ]["status" ]
108+ if status == "success" :
109+ break
110+ elif status != "running" :
111+ raise ValueError (f"CircleCI build failed with status { status } " )
112+ time .sleep (3 )
113+
114+
115+ def download_artifacts_circleci (session , urls ):
116+ paths = []
117+ for url in urls :
118+ name = url .split ("/" )[- 1 ]
119+ response = session .get (
120+ url ,
121+ headers = {},
122+ )
123+ out_path = os .path .join (
124+ os .path .dirname (__file__ ),
125+ "dist" ,
126+ os .path .basename (name ),
127+ )
128+ with open (out_path , "wb" ) as f :
129+ f .write (response .content )
130+ paths .append (out_path )
131+ return paths
132+
133+
134+ def fetch_circleci_artifacts (token , version ):
135+ session = requests .Session ()
136+
137+ response = session .get (
138+ "https://circleci.com/api/v2/pipeline?org-slug=gh/pyca" ,
139+ headers = {"Circle-Token" : token },
140+ )
141+ response .raise_for_status ()
142+ pipeline_id = None
143+ for item in response .json ()["items" ]:
144+ if item ["project_slug" ] == "gh/pyca/cryptography" :
145+ if item ["vcs" ].get ("tag" , None ) == version :
146+ pipeline_id = item ["id" ]
147+ break
148+
149+ if pipeline_id is None :
150+ raise ValueError (
151+ f"Could not find a pipeline for version { version } "
152+ )
153+
154+ wait_for_build_complete_circleci (session , token , pipeline_id )
155+ urls = fetch_circleci_artifact_urls (session , token , item ["id" ])
156+ return download_artifacts_circleci (session , urls )
157+
158+
159+ def fetch_circleci_artifact_urls (session , token , pipeline_id ):
160+ response = session .get (
161+ f"https://circleci.com/api/v2/pipeline/{ pipeline_id } /workflow" ,
162+ headers = {"Circle-Token" : token },
163+ )
164+ response .raise_for_status ()
165+ workflow_id = response .json ()["items" ][0 ]["id" ]
166+ job_response = session .get (
167+ f"https://circleci.com/api/v2/workflow/{ workflow_id } /job" ,
168+ headers = {"Circle-Token" : token },
169+ )
170+ job_response .raise_for_status ()
171+ artifact_urls = []
172+ for job in job_response .json ()["items" ]:
173+ urls = fetch_circleci_artifact_url_from_job (
174+ session , token , job ["job_number" ]
175+ )
176+ artifact_urls .extend (urls )
177+
178+ return artifact_urls
179+
180+
181+ def fetch_circleci_artifact_url_from_job (session , token , job ):
182+ response = session .get (
183+ f"https://circleci.com/api/v2/project/gh/pyca/cryptography/"
184+ f"{ job } /artifacts" ,
185+ headers = {"Circle-Token" : token },
186+ )
187+ response .raise_for_status ()
188+ urls = []
189+ for item in response .json ()["items" ]:
190+ url = item .get ("url" , None )
191+ if url is not None :
192+ urls .append (url )
193+
194+ return urls
195+
196+
98197@click .command ()
99198@click .argument ("version" )
100199def release (version ):
@@ -106,7 +205,12 @@ def release(version):
106205 f"https://github.com/settings/tokens/new?"
107206 f"description={ version } &scopes=repo"
108207 )
208+ print (
209+ "Get a CircleCI token at: "
210+ "https://app.circleci.com/settings/user/tokens"
211+ )
109212 github_token = getpass .getpass ("Github person access token: " )
213+ circle_token = getpass .getpass ("CircleCI token: " )
110214
111215 # Tag and push the tag (this will trigger the wheel builder in Actions)
112216 run ("git" , "tag" , "-s" , version , "-m" , "{0} release" .format (version ))
@@ -116,9 +220,13 @@ def release(version):
116220 github_actions_artifact_paths = fetch_github_actions_artifacts (
117221 github_token , version
118222 )
223+ # Download wheels from CircleCI
224+ circle_artifact_paths = fetch_circleci_artifacts (circle_token , version )
225+
226+ artifact_paths = github_actions_artifact_paths + circle_artifact_paths
119227
120228 # Upload wheels and sdist
121- run ("twine" , "upload" , * github_actions_artifact_paths )
229+ run ("twine" , "upload" , * artifact_paths )
122230
123231
124232if __name__ == "__main__" :
0 commit comments