Skip to content

Commit efd8087

Browse files
committed
ci: harden sonatype publish status handling
1 parent a785a28 commit efd8087

File tree

4 files changed

+58
-30
lines changed

4 files changed

+58
-30
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env python3
2+
# Copyright 2026 Apollo Authors
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
"""Shared helpers for GitHub Actions scripts."""
16+
17+
from __future__ import annotations
18+
19+
import os
20+
21+
22+
def write_output(key: str, value: str) -> None:
23+
output_path = os.environ.get("GITHUB_OUTPUT", "").strip()
24+
if not output_path:
25+
return
26+
with open(output_path, "a", encoding="utf-8") as output:
27+
output.write(f"{key}={value}\n")

.github/scripts/release_extract_upload_context.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,7 @@
2121
import re
2222
from pathlib import Path
2323

24-
25-
def write_output(key: str, value: str) -> None:
26-
output_path = os.environ.get("GITHUB_OUTPUT", "").strip()
27-
if not output_path:
28-
return
29-
with open(output_path, "a", encoding="utf-8") as out:
30-
out.write(f"{key}={value}\n")
24+
from github_actions_utils import write_output
3125

3226

3327
def main() -> int:
@@ -40,8 +34,7 @@ def main() -> int:
4034

4135
uploaded_urls: list[str] = []
4236
for target_repo, url in pattern.findall(log_text):
43-
normalized = target_repo.rstrip(":")
44-
if normalized == repository_name:
37+
if target_repo == repository_name:
4538
uploaded_urls.append(url)
4639

4740
deduped_urls = sorted(set(uploaded_urls))

.github/scripts/release_resolve_repository_context.py

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
from pathlib import Path
2626
from typing import Any
2727

28+
from github_actions_utils import write_output
29+
2830
OSSRH_BASE = "https://ossrh-staging-api.central.sonatype.com"
2931

3032

@@ -40,24 +42,17 @@ def request_json(url: str, headers: dict[str, str]) -> tuple[int | None, dict[st
4042
except json.JSONDecodeError:
4143
return response.status, {"raw": body}
4244
except urllib.error.HTTPError as error:
45+
body = error.read().decode("utf-8")
4346
try:
44-
payload = json.loads(error.read().decode("utf-8"))
45-
except Exception: # noqa: BLE001
46-
payload = {"error": f"HTTP {error.code}"}
47+
payload = json.loads(body) if body else {}
48+
except json.JSONDecodeError:
49+
payload = {"raw": body}
4750
payload.setdefault("error", f"HTTP {error.code}")
4851
return error.code, payload
4952
except Exception as error: # noqa: BLE001
5053
return None, {"error": str(error)}
5154

5255

53-
def write_output(key: str, value: str) -> None:
54-
output_path = os.environ.get("GITHUB_OUTPUT", "").strip()
55-
if not output_path:
56-
return
57-
with open(output_path, "a", encoding="utf-8") as stream:
58-
stream.write(f"{key}={value}\n")
59-
60-
6156
def main() -> int:
6257
target_repository = os.environ.get("TARGET_REPOSITORY", "").strip()
6358
namespace = os.environ.get("TARGET_NAMESPACE", "").strip()

.github/scripts/sonatype_publish.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import urllib.request
2626
from typing import Any
2727

28+
from github_actions_utils import write_output
29+
2830
OSSRH_BASE = "https://ossrh-staging-api.central.sonatype.com"
2931
PORTAL_BASE = "https://central.sonatype.com"
3032

@@ -64,14 +66,6 @@ def extract_deployment_state(payload: dict[str, Any]) -> str:
6466
return "unknown"
6567

6668

67-
def write_output(key: str, value: str) -> None:
68-
output_path = os.environ.get("GITHUB_OUTPUT", "").strip()
69-
if not output_path:
70-
return
71-
with open(output_path, "a", encoding="utf-8") as stream:
72-
stream.write(f"{key}={value}\n")
73-
74-
7569
def to_int(value: str, default: int) -> int:
7670
try:
7771
return int(value)
@@ -190,7 +184,26 @@ def main() -> int:
190184
f"{PORTAL_BASE}/api/v1/publisher/status?"
191185
f"id={urllib.parse.quote(deployment_id)}"
192186
)
193-
_, status_payload = request_json("POST", status_url, headers)
187+
poll_status, status_payload = request_json(
188+
"POST",
189+
status_url,
190+
headers,
191+
)
192+
if poll_status is None or poll_status < 200 or poll_status >= 300:
193+
poll_error = (
194+
status_payload.get("error")
195+
if isinstance(status_payload, dict)
196+
else ""
197+
)
198+
if not poll_error:
199+
poll_error = (
200+
f"HTTP {poll_status}"
201+
if poll_status is not None
202+
else "HTTP unknown"
203+
)
204+
reason = f"Status polling API failed: {poll_error}"
205+
break
206+
194207
final_state = extract_deployment_state(status_payload)
195208

196209
if final_state == "PUBLISHED":
@@ -234,7 +247,7 @@ def main() -> int:
234247

235248
time.sleep(10)
236249

237-
if result != "published" and not reason and final_state != "unknown":
250+
if result != "published" and not reason:
238251
reason = (
239252
"Timed out waiting for deployment status. "
240253
f"Latest state={final_state}"

0 commit comments

Comments
 (0)