11#!/usr/bin/env python3
22"""
3- Script to check for new Microsoft OpenJDK versions and update java-versions.yml
3+ Script to check for new JDK versions and update java-versions.yml
4+ - JDK 8: From Adoptium (Eclipse Temurin)
5+ - JDK 11+: From Microsoft OpenJDK
46"""
57
68import argparse
9+ import json
710import os
811import re
912import sys
1619from urllib .error import URLError , HTTPError
1720
1821
19- # JDK versions to check (excluding JDK 8 as it's not from Microsoft)
20- JDK_VERSIONS = [11 , 17 , 21 , 25 ]
22+ # JDK versions to check
23+ JDK_VERSIONS = [8 , 11 , 17 , 21 , 25 ]
2124
22- # Microsoft OpenJDK download URL patterns
25+ # Microsoft OpenJDK download URL patterns (JDK 11+)
2326LINUX_URL_TEMPLATE = "https://aka.ms/download-jdk/microsoft-jdk-{version}-linux-x64.tar.gz"
2427WINDOWS_URL_TEMPLATE = "https://aka.ms/download-jdk/microsoft-jdk-{version}-windows-x64.zip"
2528
29+ # Adoptium API for JDK 8
30+ ADOPTIUM_API_URL = "https://api.adoptium.net/v3/info/release_versions?version=[8,9)&release_type=ga&sort_method=DATE&sort_order=DESC&page_size=1"
31+ ADOPTIUM_DOWNLOAD_URL_TEMPLATE = "https://api.adoptium.net/v3/binary/latest/8/ga/{os}/x64/jdk/hotspot/normal/eclipse"
32+
33+
34+ def get_jdk8_version_from_adoptium ():
35+ """
36+ Get the latest JDK 8 version from Adoptium API.
37+ Returns tuple: (security_version, build_number) e.g., ('472', '08')
38+ """
39+ try :
40+ request = Request (ADOPTIUM_API_URL )
41+ request .add_header ('User-Agent' , 'Mozilla/5.0 (compatible; Azure-Functions-Java-Worker-Version-Checker/1.0)' )
42+
43+ with urlopen (request , timeout = 30 ) as response :
44+ data = json .loads (response .read ().decode ('utf-8' ))
45+
46+ if 'versions' in data and len (data ['versions' ]) > 0 :
47+ version_info = data ['versions' ][0 ]
48+ security = str (version_info ['security' ])
49+ build = str (version_info ['build' ]).zfill (2 ) # Pad to 2 digits
50+ semver = version_info ['semver' ]
51+
52+ print (f" Detected version: { semver } (security: { security } , build: { build } )" )
53+ return security , build
54+ else :
55+ print (" Warning: No version found in Adoptium API response" )
56+ return None , None
57+ except (URLError , HTTPError ) as e :
58+ print (f" Error fetching Adoptium API: { e } " )
59+ return None , None
60+ except json .JSONDecodeError as e :
61+ print (f" Error parsing Adoptium API response: { e } " )
62+ return None , None
63+
2664
2765def get_version_from_url (url ):
2866 """
@@ -58,7 +96,10 @@ def download_and_extract_jdk(url, os_type, extract_dir):
5896 print (f" Downloading from { url } " )
5997
6098 try :
61- with urlopen (url , timeout = 300 ) as response :
99+ request = Request (url )
100+ request .add_header ('User-Agent' , 'Mozilla/5.0 (compatible; Azure-Functions-Java-Worker-Version-Checker/1.0)' )
101+
102+ with urlopen (request , timeout = 300 ) as response :
62103 archive_data = response .read ()
63104
64105 # Save to temporary file
@@ -95,7 +136,8 @@ def download_and_extract_jdk(url, os_type, extract_dir):
95136
96137def validate_jdk_version (jdk_path , os_type , expected_version ):
97138 """
98- Validate the JDK by running 'java --version' and checking the output.
139+ Validate the JDK by running 'java -version' or 'java --version' and checking the output.
140+ JDK 8 uses -version, JDK 9+ uses --version (but both work with -version)
99141 """
100142 print (f" Validating JDK installation..." )
101143
@@ -109,18 +151,21 @@ def validate_jdk_version(jdk_path, os_type, expected_version):
109151 raise FileNotFoundError (f"Java executable not found at { java_exe } " )
110152
111153 try :
112- # Run java --version
154+ # Run java -version (works for all JDK versions)
155+ # Note: -version outputs to stderr, not stdout
113156 result = subprocess .run (
114- [str (java_exe ), '-- version' ],
157+ [str (java_exe ), '-version' ],
115158 capture_output = True ,
116159 text = True ,
117160 timeout = 10
118161 )
119162
120- print (f" Java version output:\n { result .stdout } " )
163+ # Check both stdout and stderr as -version outputs to stderr
164+ output = result .stdout + result .stderr
165+ print (f" Java version output:\n { output } " )
121166
122167 # Check if expected version is in the output
123- if expected_version in result . stdout :
168+ if expected_version in output :
124169 print (f" [OK] Validation successful: Found version { expected_version } " )
125170 return True
126171 else :
@@ -139,38 +184,74 @@ def check_jdk_version(jdk_version, os_type):
139184 """
140185 Check the latest version for a specific JDK major version and OS.
141186 Downloads, validates, and returns the version string.
187+ For JDK 8, returns tuple: (security_version, build_number)
188+ For JDK 11+, returns version string
142189 """
143190 print (f"\n Checking JDK { jdk_version } for { os_type } ..." )
144191
145- # Determine URL template
146- if os_type == 'linux' :
147- url = LINUX_URL_TEMPLATE .format (version = jdk_version )
148- else :
149- url = WINDOWS_URL_TEMPLATE .format (version = jdk_version )
150-
151- # Get version from URL redirect
152- version = get_version_from_url (url )
153-
154- if not version :
155- print (f" Failed to detect version for JDK { jdk_version } on { os_type } " )
156- return None
157-
158- print (f" Detected version: { version } " )
159-
160- # Download and validate
161- with tempfile .TemporaryDirectory () as tmp_dir :
162- try :
163- jdk_path = download_and_extract_jdk (url , os_type , tmp_dir )
164-
165- if validate_jdk_version (jdk_path , os_type , version ):
166- return version
167- else :
168- print (f" Validation failed for JDK { jdk_version } { os_type } version { version } " )
192+ # Special handling for JDK 8 (from Adoptium)
193+ if jdk_version == 8 :
194+ # Get version info from API
195+ security , build = get_jdk8_version_from_adoptium ()
196+
197+ if not security or not build :
198+ print (f" Failed to detect version for JDK 8" )
199+ return None
200+
201+ # Determine download URL
202+ adoptium_os = 'linux' if os_type == 'linux' else 'windows'
203+ url = ADOPTIUM_DOWNLOAD_URL_TEMPLATE .format (os = adoptium_os )
204+
205+ # For validation, construct the expected version string
206+ # Adoptium uses format like "1.8.0_472"
207+ expected_version = f"1.8.0_{ security } "
208+
209+ # Download and validate
210+ with tempfile .TemporaryDirectory () as tmp_dir :
211+ try :
212+ jdk_path = download_and_extract_jdk (url , os_type , tmp_dir )
213+
214+ if validate_jdk_version (jdk_path , os_type , expected_version ):
215+ return (security , build )
216+ else :
217+ print (f" Validation failed for JDK 8 { os_type } version { expected_version } " )
218+ sys .exit (1 )
219+
220+ except Exception as e :
221+ print (f" Error during download/validation: { e } " )
169222 sys .exit (1 )
223+
224+ # Microsoft OpenJDK handling (JDK 11+)
225+ else :
226+ # Determine URL template
227+ if os_type == 'linux' :
228+ url = LINUX_URL_TEMPLATE .format (version = jdk_version )
229+ else :
230+ url = WINDOWS_URL_TEMPLATE .format (version = jdk_version )
231+
232+ # Get version from URL redirect
233+ version = get_version_from_url (url )
234+
235+ if not version :
236+ print (f" Failed to detect version for JDK { jdk_version } on { os_type } " )
237+ return None
238+
239+ print (f" Detected version: { version } " )
240+
241+ # Download and validate
242+ with tempfile .TemporaryDirectory () as tmp_dir :
243+ try :
244+ jdk_path = download_and_extract_jdk (url , os_type , tmp_dir )
170245
171- except Exception as e :
172- print (f" Error during download/validation: { e } " )
173- sys .exit (1 )
246+ if validate_jdk_version (jdk_path , os_type , version ):
247+ return version
248+ else :
249+ print (f" Validation failed for JDK { jdk_version } { os_type } version { version } " )
250+ sys .exit (1 )
251+
252+ except Exception as e :
253+ print (f" Error during download/validation: { e } " )
254+ sys .exit (1 )
174255
175256
176257def load_current_versions (yaml_file ):
@@ -181,10 +262,18 @@ def load_current_versions(yaml_file):
181262 content = f .read ()
182263
183264 versions = {}
184- # Pattern to match variables like: JDK11_LINUX_VERSION: '11.0.26'
185- pattern = r"(JDK\d+_(?:LINUX|WINDOWS)_VERSION):\s*'([^']+)'"
265+ # Pattern to match version variables like: JDK11_LINUX_VERSION: '11.0.26'
266+ version_pattern = r"(JDK\d+_(?:LINUX|WINDOWS)_VERSION):\s*'([^']+)'"
267+
268+ for match in re .finditer (version_pattern , content ):
269+ var_name = match .group (1 )
270+ value = match .group (2 )
271+ versions [var_name ] = value
186272
187- for match in re .finditer (pattern , content ):
273+ # Pattern to match build variables like: JDK8_LINUX_BUILD: '06'
274+ build_pattern = r"(JDK8_(?:LINUX|WINDOWS)_BUILD):\s*'([^']+)'"
275+
276+ for match in re .finditer (build_pattern , content ):
188277 var_name = match .group (1 )
189278 value = match .group (2 )
190279 versions [var_name ] = value
@@ -247,7 +336,7 @@ def main():
247336 current_versions = load_current_versions (yaml_file )
248337 print (f"\n Current { os_type } versions:" )
249338 for key , value in sorted (current_versions .items ()):
250- if 'JDK8' not in key and os_type .upper () in key :
339+ if os_type .upper () in key :
251340 print (f" { key } : { value } " )
252341
253342 # Check all JDK versions for this OS only
@@ -256,8 +345,16 @@ def main():
256345 for jdk_version in JDK_VERSIONS :
257346 version = check_jdk_version (jdk_version , os_type )
258347 if version :
259- var_name = f"JDK{ jdk_version } _{ os_type .upper ()} _VERSION"
260- detected_versions [var_name ] = version
348+ # JDK 8 returns tuple (security, build), others return version string
349+ if jdk_version == 8 :
350+ security , build = version
351+ version_var = f"JDK8_{ os_type .upper ()} _VERSION"
352+ build_var = f"JDK8_{ os_type .upper ()} _BUILD"
353+ detected_versions [version_var ] = security
354+ detected_versions [build_var ] = build
355+ else :
356+ var_name = f"JDK{ jdk_version } _{ os_type .upper ()} _VERSION"
357+ detected_versions [var_name ] = version
261358
262359 # Compare and determine if update is needed
263360 print ("\n " + "=" * 80 )
0 commit comments