@@ -95,6 +95,103 @@ 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 (f"Could not find a pipeline for version { version } " )
151+
152+ wait_for_build_complete_circleci (session , token , pipeline_id )
153+ urls = fetch_circleci_artifact_urls (session , token , item ["id" ])
154+ return download_artifacts_circleci (session , urls )
155+
156+
157+ def fetch_circleci_artifact_urls (session , token , pipeline_id ):
158+ response = session .get (
159+ f"https://circleci.com/api/v2/pipeline/{ pipeline_id } /workflow" ,
160+ headers = {"Circle-Token" : token },
161+ )
162+ response .raise_for_status ()
163+ workflow_id = response .json ()["items" ][0 ]["id" ]
164+ job_response = session .get (
165+ f"https://circleci.com/api/v2/workflow/{ workflow_id } /job" ,
166+ headers = {"Circle-Token" : token },
167+ )
168+ job_response .raise_for_status ()
169+ artifact_urls = []
170+ for job in job_response .json ()["items" ]:
171+ urls = fetch_circleci_artifact_url_from_job (
172+ session , token , job ["job_number" ]
173+ )
174+ artifact_urls .extend (urls )
175+
176+ return artifact_urls
177+
178+
179+ def fetch_circleci_artifact_url_from_job (session , token , job ):
180+ response = session .get (
181+ f"https://circleci.com/api/v2/project/gh/pyca/cryptography/"
182+ f"{ job } /artifacts" ,
183+ headers = {"Circle-Token" : token },
184+ )
185+ response .raise_for_status ()
186+ urls = []
187+ for item in response .json ()["items" ]:
188+ url = item .get ("url" , None )
189+ if url is not None :
190+ urls .append (url )
191+
192+ return urls
193+
194+
98195@click .command ()
99196@click .argument ("version" )
100197def release (version ):
@@ -106,7 +203,12 @@ def release(version):
106203 f"https://github.com/settings/tokens/new?"
107204 f"description={ version } &scopes=repo"
108205 )
206+ print (
207+ "Get a CircleCI token at: "
208+ "https://app.circleci.com/settings/user/tokens"
209+ )
109210 github_token = getpass .getpass ("Github person access token: " )
211+ circle_token = getpass .getpass ("CircleCI token: " )
110212
111213 # Tag and push the tag (this will trigger the wheel builder in Actions)
112214 run ("git" , "tag" , "-s" , version , "-m" , "{0} release" .format (version ))
@@ -116,9 +218,13 @@ def release(version):
116218 github_actions_artifact_paths = fetch_github_actions_artifacts (
117219 github_token , version
118220 )
221+ # Download wheels from CircleCI
222+ circle_artifact_paths = fetch_circleci_artifacts (circle_token , version )
223+
224+ artifact_paths = github_actions_artifact_paths + circle_artifact_paths
119225
120226 # Upload wheels and sdist
121- run ("twine" , "upload" , * github_actions_artifact_paths )
227+ run ("twine" , "upload" , * artifact_paths )
122228
123229
124230if __name__ == "__main__" :
0 commit comments