|
16 | 16 | jobs: |
17 | 17 | Test: |
18 | 18 | runs-on: ubuntu-latest |
| 19 | + timeout-minutes: 10 |
19 | 20 | strategy: |
20 | 21 | fail-fast: false |
| 22 | + max-parallel: 10 |
21 | 23 | matrix: |
22 | 24 | domain: |
23 | 25 | [ |
@@ -70,38 +72,82 @@ jobs: |
70 | 72 | - name: Check domain redirections |
71 | 73 | shell: python |
72 | 74 | run: | |
73 | | - import requests |
74 | 75 | import time |
| 76 | + from urllib.parse import urlparse |
| 77 | +
|
| 78 | + import requests |
| 79 | + from requests.adapters import HTTPAdapter |
| 80 | + from urllib3.util.retry import Retry |
| 81 | +
|
| 82 | + VALID_DESTINATIONS = {"ultralytics.com", "www.ultralytics.com", "yolo11.com", "www.yolo11.com"} |
| 83 | + REQUEST_TIMEOUT = (10, 20) |
| 84 | + BASE_DELAY = 5 |
| 85 | + MAX_DELAY = 120 |
| 86 | + USER_AGENT = ( |
| 87 | + "Mozilla/5.0 (compatible; UltralyticsDomainCheck/1.0; +https://github.com/ultralytics/docs)" |
| 88 | + ) |
75 | 89 |
|
76 | | - def check_domain_redirection(domain, prefix, max_attempts=5): |
77 | | - """Check if the given domain redirects correctly, with delays between retries.""" |
78 | | - valid_destinations = ["ultralytics.com", "yolo11.com"] |
| 90 | + def build_session(): |
| 91 | + """Create a session with lightweight retries for transient HTTP errors.""" |
| 92 | + retry = Retry( |
| 93 | + total=2, |
| 94 | + connect=2, |
| 95 | + read=2, |
| 96 | + status=2, |
| 97 | + backoff_factor=1, |
| 98 | + status_forcelist=(429, 500, 502, 503, 504), |
| 99 | + allowed_methods=frozenset(["GET"]), |
| 100 | + raise_on_status=False, |
| 101 | + ) |
| 102 | + adapter = HTTPAdapter(max_retries=retry) |
| 103 | + session = requests.Session() |
| 104 | + session.headers.update({"User-Agent": USER_AGENT}) |
| 105 | + session.mount("https://", adapter) |
| 106 | + session.mount("http://", adapter) |
| 107 | + return session |
| 108 | +
|
| 109 | + def is_valid_destination(url): |
| 110 | + """Check the final redirect hostname against approved destinations.""" |
| 111 | + hostname = (urlparse(url).hostname or "").lower() |
| 112 | + return hostname in VALID_DESTINATIONS |
| 113 | +
|
| 114 | + def check_domain_redirection(domain, prefix, session, max_attempts=5): |
| 115 | + """Check if the given domain redirects correctly, with exponential delays between retries.""" |
79 | 116 | url = f"https://{prefix}{domain}" |
80 | 117 | print(f"\nChecking {url}") |
81 | 118 |
|
82 | 119 | for attempt in range(max_attempts): |
| 120 | + response = None |
83 | 121 | try: |
84 | 122 | if attempt > 0: |
85 | | - delay = 2 ** attempt # 2, 4, 8, 16, 32 seconds... |
| 123 | + delay = min(BASE_DELAY * (2 ** attempt), MAX_DELAY) # 10, 20, 40, 80... |
| 124 | + print(f"Retrying in {delay}s (attempt {attempt + 1}/{max_attempts})") |
86 | 125 | time.sleep(delay) |
87 | 126 |
|
88 | | - response = requests.get(url, allow_redirects=True, timeout=10) |
| 127 | + response = session.get(url, allow_redirects=True, timeout=REQUEST_TIMEOUT, stream=True) |
89 | 128 | response.raise_for_status() |
90 | 129 |
|
91 | | - # Check if the final URL contains any of the valid destinations |
92 | | - if any(dest in response.url for dest in valid_destinations) and response.status_code == 200: |
93 | | - print("Success ✅") |
| 130 | + if is_valid_destination(response.url) and response.status_code == 200: |
| 131 | + print(f"Success ✅ -> {response.url}") |
94 | 132 | return True |
95 | 133 |
|
| 134 | + print(f"Unexpected final URL: {response.url} (status {response.status_code}) ❌") |
| 135 | + return False |
| 136 | +
|
96 | 137 | except requests.RequestException as e: |
97 | 138 | print(f"Error: {e}") |
98 | 139 | if attempt == max_attempts - 1: |
99 | 140 | print(f"Failed after {max_attempts} attempts ❌") |
100 | 141 | return False |
| 142 | + finally: |
| 143 | + if response is not None: |
| 144 | + response.close() |
101 | 145 |
|
102 | 146 | return False |
103 | 147 |
|
104 | | - success = check_domain_redirection('${{ matrix.domain }}', '${{ matrix.prefix }}') |
| 148 | + session = build_session() |
| 149 | + success = check_domain_redirection('${{ matrix.domain }}', '${{ matrix.prefix }}', session) |
| 150 | + session.close() |
105 | 151 | if not success: |
106 | 152 | raise Exception(f"Domain check failed for ${{ matrix.domain }} with prefix '${{ matrix.prefix }}'") |
107 | 153 |
|
|
0 commit comments