diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ba5b31f..2bfca1fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,7 +2,10 @@ name: Jinja CI on: pull_request: paths: + - .github/workflows/ci.yml + - dockerhub_doc_config_update.py - generate_dockerfiles.py + - test_dockerhub_doc_config_update.py - test_generate_dockerfiles.py - requirements.txt branches: [ main ] @@ -23,5 +26,8 @@ jobs: - name: Install dependencies run: "pip3 install -r requirements.txt" - - name: Run tests + - name: Run test_generate_dockerfiles run: "python3 test_generate_dockerfiles.py" + + - name: Run test_dockerhub_doc_config_update + run: "python3 test_dockerhub_doc_config_update.py" diff --git a/.github/workflows/test-pr.yml b/.github/workflows/test-pr.yml index 53435729..9b9ea7a2 100644 --- a/.github/workflows/test-pr.yml +++ b/.github/workflows/test-pr.yml @@ -22,10 +22,15 @@ jobs: steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: docker-library/bashbrew@9eef708e6a0b1b5d8bbda769c766777fe45026eb # v0.1.13 + - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0 + with: + python-version: "3.x" + - name: Install dependencies + run: "pip3 install -r requirements.txt" - id: generate-jobs name: Generate Jobs run: | - export GENERATE_STACKBREW_LIBRARY='./dockerhub_doc_config_update.sh /dev/stdout' + export GENERATE_STACKBREW_LIBRARY='python3 dockerhub_doc_config_update.py -o /dev/stdout' export GITHUB_REPOSITORY="eclipse-temurin" strategy="$("$BASHBREW_SCRIPTS/github-actions/generate.sh")" echo "strategy=$strategy" >> "$GITHUB_OUTPUT" diff --git a/README.md b/README.md index 455dc58b..b84609c1 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Once you've merged the PR, you can update the official Docker Hub manifest. This git fetch --all # Checkout the main branch git checkout main -./dockerhub_doc_config_update.sh +./dockerhub_doc_config_update.py ``` This script will create a file called _eclipse-temurin_ by default. diff --git a/config/hotspot.yml b/config/temurin.yml similarity index 95% rename from config/hotspot.yml rename to config/temurin.yml index 317ad82f..72c0bf58 100644 --- a/config/hotspot.yml +++ b/config/temurin.yml @@ -16,50 +16,57 @@ supported_distributions: OS: [alpine, focal, jammy, noble, ubi9-minimal, windowsservercore-1809, nanoserver-1809, windowsservercore-ltsc2022, nanoserver-ltsc2022] Versions: [8, 11, 17, 21, 23] +metadata: + image_types: [jdk, jre] + latest_version: 21 + default_linux_image: noble + default_alpine_image: alpine-3.21 + configurations: + + alpine-linux: + - directory: alpine/3.20 + architectures: [aarch64, x64] + image: alpine:3.20 + os: alpine-linux + + - directory: alpine/3.21 + architectures: [aarch64, x64] + image: alpine:3.21 + os: alpine-linux + linux: - - directory: ubuntu/noble - image: ubuntu:24.04 - architectures: [aarch64, arm, ppc64le, riscv64, s390x, x64] + - directory: ubuntu/focal + architectures: [aarch64, arm, ppc64le, s390x, x64] + image: ubuntu:20.04 + deprecated: 20 os: ubuntu - + - directory: ubuntu/jammy image: ubuntu:22.04 architectures: [aarch64, arm, ppc64le, s390x, x64] deprecated: 23 os: ubuntu - - directory: ubuntu/focal - architectures: [aarch64, arm, ppc64le, s390x, x64] - image: ubuntu:20.04 - deprecated: 20 + - directory: ubuntu/noble + image: ubuntu:24.04 + architectures: [aarch64, arm, ppc64le, riscv64, s390x, x64] os: ubuntu - directory: ubi/ubi9-minimal architectures: [aarch64, ppc64le, s390x, x64] image: redhat/ubi9-minimal os: ubi9-minimal - - alpine-linux: - - directory: alpine/3.21 - architectures: [aarch64, x64] - image: alpine:3.21 - os: alpine-linux - - - directory: alpine/3.20 - architectures: [aarch64, x64] - image: alpine:3.20 - os: alpine-linux windows: - - directory: windows/windowsservercore-1809 + - directory: windows/windowsservercore-ltsc2025 architectures: [x64] - image: mcr.microsoft.com/windows/servercore:1809 + image: mcr.microsoft.com/windows/servercore:ltsc2025 os: servercore - - directory: windows/nanoserver-1809 + - directory: windows/nanoserver-ltsc2025 architectures: [x64] - image: mcr.microsoft.com/windows/nanoserver:1809 + image: mcr.microsoft.com/windows/nanoserver:ltsc2025 os: nanoserver - directory: windows/windowsservercore-ltsc2022 @@ -72,12 +79,12 @@ configurations: image: mcr.microsoft.com/windows/nanoserver:ltsc2022 os: nanoserver - - directory: windows/windowsservercore-ltsc2025 + - directory: windows/windowsservercore-1809 architectures: [x64] - image: mcr.microsoft.com/windows/servercore:ltsc2025 + image: mcr.microsoft.com/windows/servercore:1809 os: servercore - - directory: windows/nanoserver-ltsc2025 + - directory: windows/nanoserver-1809 architectures: [x64] - image: mcr.microsoft.com/windows/nanoserver:ltsc2025 + image: mcr.microsoft.com/windows/nanoserver:1809 os: nanoserver diff --git a/dockerhub_doc_config_update.py b/dockerhub_doc_config_update.py new file mode 100755 index 00000000..01933bc8 --- /dev/null +++ b/dockerhub_doc_config_update.py @@ -0,0 +1,310 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import argparse +import os +import subprocess +import requests +import yaml +import re +from pathlib import Path + +parser = argparse.ArgumentParser( + description="Generate the official manifest for Eclipse Temurin images" +) + +parser.add_argument( + "--output", + "-o", + default="eclipse-temurin", + help="Output file for the official manifest", +) + +args = parser.parse_args() + +# Load the YAML configuration +with open("config/temurin.yml", "r") as file: + config = yaml.safe_load(file) + + +# Configuration settings +metadata = config["metadata"] +latest_version = metadata["latest_version"] +image_types = metadata["image_types"] +default_linux_image = metadata["default_linux_image"] +default_alpine_image = metadata["default_alpine_image"] +supported_versions = config["supported_distributions"]["Versions"] + + +# Fetch the latest manifest +def fetch_latest_manifest(): + """Fetch the latest manifest from the official-images repository.""" + url = "https://raw.githubusercontent.com/docker-library/official-images/master/library/eclipse-temurin" + response = requests.get(url) + response.raise_for_status() + with open("official-eclipse-temurin", "w") as f: + f.write(response.text) + + +# Get the latest git commit +def get_git_commit(): + """Get the latest git commit.""" + return ( + subprocess.check_output(["git", "log", "-1", "--pretty=format:%H"]) + .decode() + .strip() + ) + + +# Parse Dockerfile to extract relevant information +def parse_dockerfile(dockerfile_path, osname): + """Parse the Dockerfile to extract the Java version and supported architectures.""" + java_version = "" + architectures = [] + + with open(os.path.join(dockerfile_path, "Dockerfile"), "r") as dockerfile: + lines = dockerfile.readlines() + + # Extract JAVA_VERSION + for line in lines: + if "ENV JAVA_VERSION=" in line: + java_version = re.search(r"JAVA_VERSION=([\w\+\.\-]+)", line).group(1) + break + + if osname == "windows": + return java_version, ["windows-amd64"] + + # Extract architectures from the `case` statement + inside_case_statement = False + for line in lines: + if line.strip().startswith('case "${ARCH}" in'): + inside_case_statement = True + continue + if inside_case_statement: + match = re.match(r"\s*(\w+)\)", line) + if match: + arch = match.group(1) + match arch: + case "x86_64": + arch = "amd64" + case "armhf": + arch = "arm32v7" + case "arm64" | "aarch64": + arch = "arm64v8" + case "ppc64el": + arch = "ppc64le" + architectures.append(arch) + elif line.strip() == ";;": + continue + elif line.strip() == "*)": + break # End of case statement + + # sort the architectures alphabetically + architectures.sort() + + return java_version, architectures + + +def generate_tags(java_version, version, pkg, distro): + """Generate tags for the given Java version, package, and distro.""" + base_tags = [] + base_tags.append(f"{java_version}-{pkg}-{distro}") + base_tags.append(f"{version}-{pkg}-{distro}") + if pkg == "jdk": + base_tags.append(f"{version}-{distro}") + if distro == default_alpine_image: + base_tags.append(f"{java_version}-{pkg}-alpine") + base_tags.append(f"{version}-{pkg}-alpine") + if pkg == "jdk": + base_tags.append(f"{version}-alpine") + return base_tags + + +def generate_shared_tags(java_version, version, pkg, distro, os): + """Generate shared tags for the given Java version, package, and distro.""" + shared_tags = [] + if os == "windows": + if distro.startswith("nanoserver"): + shared_tags.append(f"{java_version}-{pkg}-nanoserver") + shared_tags.append(f"{version}-{pkg}-nanoserver") + if pkg == "jdk": + shared_tags.append(f"{version}-nanoserver") + else: + shared_tags.append(f"{java_version}-{pkg}-windowsservercore") + shared_tags.append(f"{version}-{pkg}-windowsservercore") + if pkg == "jdk": + shared_tags.append(f"{version}-windowsservercore") + + if ( + os == "windows" and distro.startswith("windowsservercore") + ) or distro == default_linux_image: + shared_tags.append(f"{java_version}-{pkg}") + shared_tags.append(f"{version}-{pkg}") + if pkg == "jdk": + shared_tags.append(f"{version}") + if version == latest_version: + shared_tags.append("latest") + return shared_tags + + +# Generate the official header +def print_official_header(file): + file.write("# Eclipse Temurin OpenJDK images provided by the Eclipse Foundation.\n") + file.write("\n") + file.write("Maintainers: George Adams (@gdams),\n") + file.write(" Stewart Addison (@sxa)\n") + file.write("GitRepo: https://github.com/adoptium/containers.git\n") + file.write("GitFetch: refs/heads/main\n") + file.write("Builder: buildkit\n") + + +# Generate tags, architectures, and print to file +def generate_official_image_info(file, ver, pkg, os, dfdir): + # Extract distro name from path + distro = dfdir.split("/")[3] + if os == "alpine-linux": + distro = "alpine-" + distro + + # Parse Dockerfile to get JAVA_VERSION and architectures + java_version, arches = parse_dockerfile(dfdir, os) + + # Generate tags and other metadata + full_version = java_version.replace("+", "_").replace("jdk-", "").replace("jdk", "") + tags = generate_tags(full_version, ver, pkg, distro) + shared_tags = generate_shared_tags(full_version, ver, pkg, distro, os) + commit = get_git_commit() + + # Fetch the latest manifest block + official_manifest = Path("official-eclipse-temurin").read_text() + official_gitcommit = "" + # Retrieve the latest manifest block + all_tags = "|".join(tags) + for line in official_manifest.splitlines(): + if re.search(all_tags, line): + # return block starting from the matching line until a blank line + official_manifest = "\n".join( + official_manifest.splitlines()[ + official_manifest.splitlines().index(line) : + ] + ) + official_gitcommit = re.search( + r"GitCommit: ([a-f0-9]+)", official_manifest + ).group(1) + + if official_gitcommit: + if ( + subprocess.call( + [ + "git", + "diff", + "--quiet", + f"{commit}:{dfdir}/Dockerfile", + f"{official_gitcommit}:{dfdir}/Dockerfile", + ] + ) + == 0 + ): + diff = ( + subprocess.check_output( + [ + "git", + "diff", + f"{commit}:{dfdir}/Dockerfile", + f"{official_gitcommit}:{dfdir}/Dockerfile", + ] + ) + .decode() + .strip() + ) + diff_count = len(diff.splitlines()) + # check for diff in the entrypoint.sh file + if Path(f"{dfdir}/entrypoint.sh").exists(): + # check if the entrypoint.sh file is different from the official one + if ( + subprocess.call( + [ + "git", + "diff", + "--quiet", + f"{commit}:{dfdir}/entrypoint.sh", + f"{official_gitcommit}:{dfdir}/entrypoint.sh", + ] + ) + == 0 + ): + diff = ( + subprocess.check_output( + [ + "git", + "diff", + f"{commit}:{dfdir}/entrypoint.sh", + f"{official_gitcommit}:{dfdir}/entrypoint.sh", + ] + ) + .decode() + .strip() + ) + diff_count += len(diff.splitlines()) + else: + # Forcefully sets a diff if the file doesn't exist + diff_count = 1 + else: + # Forcefully sets a diff if a new dockerfile has been added + diff_count = 1 + + commit = official_gitcommit if diff_count == 0 else get_git_commit() + + # Write to the output file + file.write(f"Tags: {', '.join(tags)}\n") + if len(shared_tags) > 0: + file.write(f"SharedTags: {', '.join(shared_tags)}\n") + file.write(f"Architectures: {', '.join(arches)}\n") + file.write(f"GitCommit: {commit}\n") + file.write(f"Directory: {dfdir}\n") + if os == "windows": + file.write("Builder: classic\n") + constraint = distro + if "nanoserver" in distro: + # trim version from distro name + version = distro.replace("nanoserver", "") + constraint = f"{constraint}, windowsservercore{version}" + file.write(f"Constraints: {constraint}\n") + file.write("\n") + + +# Main execution logic +def main(): + fetch_latest_manifest() + + with open(args.output, "w") as file: + print_official_header(file) + + for ver in supported_versions: + file.write( + f"\n#------------------------------v{ver} images---------------------------------\n" + ) + for pkg in image_types: + for os_family, configurations in config["configurations"].items(): + for configuration in configurations: + directory = configuration["directory"] + for dockerfile in Path(".").rglob( + f"{ver}/{pkg}/{directory}/Dockerfile" + ): + dfdir = str(dockerfile.parent) + generate_official_image_info( + file, ver, pkg, os_family, dfdir + ) + + +if __name__ == "__main__": + main() diff --git a/dockerhub_doc_config_update.sh b/dockerhub_doc_config_update.sh deleted file mode 100755 index d91639f5..00000000 --- a/dockerhub_doc_config_update.sh +++ /dev/null @@ -1,259 +0,0 @@ -#!/bin/bash -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Script that generates the `eclipse-temurin` config file for the official docker -# image github repo and the doc updates for the unofficial docker image repo. -# Process to update the official docker image repo -# 1. Run ./update_all.sh to update all the dockerfiles in the current repo. -# 2. Submit PR to push the newly generated dockerfiles to the current repo. -# 3. After above PR is merged, git pull the latest changes. -# 4. Run this command -# -set -o pipefail - -if [[ -z "$1" ]]; then - official_docker_image_file="eclipse-temurin" -else - official_docker_image_file="$1" -fi - -supported_versions="8 11 17 21 23" -# set this to the latest LTS version -latest_version="21" -all_jvms="hotspot" -all_packages="jdk jre" - -# Fetch the latest manifest from the official repo -wget -q -O official-eclipse-temurin https://raw.githubusercontent.com/docker-library/official-images/master/library/eclipse-temurin - -oses="alpine ubuntu ubi windowsservercore-ltsc2025 nanoserver-ltsc2025 windowsservercore-ltsc2022 nanoserver-ltsc2022 windowsservercore-1809 nanoserver-1809" -# The image which is used by default when pulling shared tags on linux e.g 8-jdk -default_linux_image="noble" -default_alpine_image=alpine-3.21 - -# Get the latest git commit of the current repo. -# This is assumed to have all the latest dockerfiles already. -gitcommit=$(git log | head -1 | awk '{ print $2 }') - -print_official_text() { - echo "$*" >> ${official_docker_image_file} -} - -print_official_header() { - print_official_text "# Eclipse Temurin OpenJDK images provided by the Eclipse Foundation." - print_official_text - print_official_text "Maintainers: George Adams (@gdams)," - print_official_text " Stewart Addison (@sxa)" - print_official_text "GitRepo: https://github.com/adoptium/containers.git" - print_official_text "GitFetch: refs/heads/main" - print_official_text "Builder: buildkit" -} - -function generate_official_image_tags() { - # Generate the tags - full_version=$(grep "JAVA_VERSION=" "${file}" | awk -F '=' '{ print $2 }') - - # Remove any `jdk` references in the version - ojdk_version=$(echo "${full_version}" | sed 's/\(jdk-\)//;s/\(jdk\)//' | awk -F '_' '{ print $1 }') - # Replace "+" with "_" in the version info as docker does not support "+" - ojdk_version=${ojdk_version//+/_} - - case $os in - "alpine") distro="alpine-"$(echo $dfdir | awk -F '/' '{ print $4 }' ) ;; - "ubuntu") distro=$(echo $dfdir | awk -F '/' '{ print $4 }' ) ;; - "ubi") distro=$(echo $dfdir | awk -F '/' '{ print $4 }' ) ;; - "windows") distro=$(echo $dfdir | awk -F '/' '{ print $4 }' ) ;; - *) distro=$os;; - esac - - # Official image build tags are as below - # 8-jre - # 8u212-jdk - full_ver_tag="${ojdk_version}-${pkg}" - - unset extra_shared_tags extra_ver_tags - full_ver_tag="${full_ver_tag}-${distro}" - # Commented out as this added the -hotspot tag which we don't need for temurin - # extra_ver_tags=", ${ver}-${pkg}" - - ver_tag="${ver}-${pkg}-${distro}" - all_tags="${full_ver_tag}, ${ver_tag}" - # jdk builds also have additional tags - if [ "${pkg}" == "jdk" ]; then - jdk_tag="${ver}-${distro}" - all_tags="${all_tags}, ${jdk_tag}" - # make "eclipse-temurin:latest" point to newest supported JDK - # shellcheck disable=SC2154 - if [ "${ver}" == "${latest_version}" ]; then - if [ "${vm}" == "hotspot" ] && [ "${os}" != "alpine" ]; then - extra_shared_tags=", latest" - fi - fi - fi - - unset windows_shared_tags - shared_tags=$(echo ${all_tags} | sed "s/-$distro//g") - if [ $os == "windows" ]; then - windows_version=$(echo $distro | awk -F '-' '{ print $1 }' ) - windows_version_number=$(echo $distro | awk -F '-' '{ print $2 }' ) - windows_shared_tags=$(echo ${all_tags} | sed "s/$distro/$windows_version/g") - case $distro in - nanoserver*) - constraints="${distro}, windowsservercore-${windows_version_number}" - all_shared_tags="${windows_shared_tags}" - ;; - *) - constraints="${distro}" - all_shared_tags="${windows_shared_tags}, ${shared_tags}${extra_shared_tags}" - ;; - esac - else - all_shared_tags="${shared_tags}${extra_shared_tags}" - fi -} - -function generate_official_image_arches() { - # Generate the supported arches for the above tags. - # Official images supports amd64, arm64vX, s390x, ppc64le amd windows-amd64 - if [ $os == "windows" ]; then - arches="windows-amd64" - else - # shellcheck disable=SC2046,SC2005,SC1003,SC2086,SC2063 - arches=$(echo $(grep ') \\' ${file} | grep -v "*" | sed 's/) \\//g; s/|//g')) - arches=$(echo ${arches} | sed 's/x86_64/amd64/g') # replace x86_64 with amd64 - arches=$(echo ${arches} | sed 's/ppc64el/ppc64le/g') # replace ppc64el with ppc64le - arches=$(echo ${arches} | sed 's/arm64/arm64v8/g') # replace arm64 with arm64v8 - arches=$(echo ${arches} | sed 's/aarch64/arm64v8/g') # replace aarch64 with arm64v8 - arches=$(echo ${arches} | sed 's/armhf/arm32v7/g') # replace armhf with arm32v7 - # sort arches alphabetically - arches=$(echo ${arches} | tr ' ' '\n' | sort | tr '\n' ' ' | sed 's/ /, /g' | sed 's/, $//') - fi -} - -function print_official_image_file() { - # Retrieve the latest manifest block - official_manifest=$(sed -n "/${all_tags}/,/^$/p" official-eclipse-temurin) - if [[ "${official_manifest}" != "" ]]; then - # Retrieve the git commit sha from the official manifest - official_gitcommit=$(echo "${official_manifest}" | grep 'GitCommit: ' | awk '{print $2}') - # See if there are any changes between the two commit sha's - if git diff "$gitcommit:$dfdir/$dfname" "$official_gitcommit:$dfdir/$dfname" >/dev/null 2>&1; then - diff_count=$(git diff "$gitcommit:$dfdir/$dfname" "$official_gitcommit:$dfdir/$dfname" | wc -l) - # check for diff in the entrypoint.sh file - if [ -f "$dfdir/entrypoint.sh" ]; then - diff_count=$((diff_count + $(git diff "$gitcommit:$dfdir/entrypoint.sh" "$official_gitcommit:$dfdir/entrypoint.sh" | wc -l))) - fi - else - # Forcefully sets a diff if the file doesn't exist - diff_count=1 - fi - else - # Forcefully sets a diff if a new dockerfile has been added - diff_count=1 - fi - - if [[ ${diff_count} -eq 0 ]]; then - commit="${official_gitcommit}" - else - commit="${gitcommit}" - fi - - # Print them all - { - if [[ "${distro}" == "${default_alpine_image}" ]]; then - # Append -alpine to each shared tag - all_tags="${all_tags}, ${all_shared_tags//, /-alpine, }-alpine" - fi - echo "Tags: ${all_tags}" - if [[ "${os}" == "windows" ]] || [[ "${distro}" == "${default_linux_image}" ]]; then - echo "SharedTags: ${all_shared_tags}" - fi - echo "Architectures: ${arches}" - echo "GitCommit: ${commit}" - echo "Directory: ${dfdir}" - if [ $os == "windows" ]; then - echo "Builder: classic" - echo "Constraints: ${constraints}" - fi - echo "" - } >> ${official_docker_image_file} -} - -rm -f ${official_docker_image_file} -print_official_header - -official_os_ignore_array=(clefos debian debianslim leap tumbleweed) - -# Generate config and doc info only for "supported" official builds. -function generate_official_image_info() { - # If it is an unsupported OS from the array above, return. - for arr_os in "${official_os_ignore_array[@]}"; - do - if [ "${os}" == "${arr_os}" ]; then - return; - fi - done - if [ "${os}" == "windows" ]; then - distro=$(echo $dfdir | awk -F '/' '{ print $4 }' ) - # 20h2 and 1909 is not supported upstream - if [[ "${distro}" == "windowsservercore-20h2" ]] || [[ "${distro}" == "windowsservercore-1909" ]] || [[ "${distro}" == "windowsservercore-ltsc2019" ]] ; then - return; - fi - if [[ "${distro}" == "nanoserver-20h2" ]] || [[ "${distro}" == "nanoserver-1909" ]]; then - return; - fi - fi - # We do not push our nightly and slim images either. - if [ "${build}" == "nightly" ] || [ "${btype}" == "slim" ]; then - return; - fi - - generate_official_image_tags - generate_official_image_arches - print_official_image_file -} - -# Iterate through all the VMs, for each supported version and packages to -# generate the config file for the official docker images. -# Official docker images = https://hub.docker.com/_/adoptopenjdk -for vm in ${all_jvms} -do - for ver in ${supported_versions} - do - print_official_text - print_official_text "#------------------------------v${ver} images---------------------------------" - for pkg in ${all_packages} - do - for os in ${oses} - do - for file in $(find . -name "Dockerfile" | grep "/${ver}" | grep "${pkg}" | grep "${os}" | sort -n) - do - # file will look like ./19/jdk/alpine/Dockerfile.releases.full - # dockerfile name - dfname=$(basename "${file}") - # dockerfile dir - dfdir=$(dirname $file | cut -c 3-) - os=$(echo "${file}" | awk -F '/' '{ print $4 }') - # build = release or nightly - # build=$(echo "${dfname}" | awk -F "." '{ print $3 }') - build="release" - # btype = full or slim - # btype=$(echo "${dfname}" | awk -F "." '{ print $4 }') - build="full" - generate_official_image_info - done - done - done - done -done diff --git a/generate_dockerfiles.py b/generate_dockerfiles.py index 4576050d..aa35abff 100644 --- a/generate_dockerfiles.py +++ b/generate_dockerfiles.py @@ -65,7 +65,7 @@ def archHelper(arch, os_name): # Load the YAML configuration -with open("config/hotspot.yml", "r") as file: +with open("config/temurin.yml", "r") as file: config = yaml.safe_load(file) # Iterate through OS families and then configurations @@ -79,6 +79,9 @@ def archHelper(arch, os_name): versions = configuration.get( "versions", config["supported_distributions"]["Versions"] ) + image_types = configuration.get( + "image_types", config["metadata"]["image_types"] + ) # Define the path for the template based on OS template_name = f"{os_name}.Dockerfile.j2" @@ -90,7 +93,7 @@ def archHelper(arch, os_name): if deprecated and version >= deprecated: continue print("Generating Dockerfiles for", base_image, "-", version) - for image_type in ["jdk", "jre"]: + for image_type in image_types: output_directory = os.path.join(str(version), image_type, directory) os.makedirs(output_directory, exist_ok=True) diff --git a/test_dockerhub_doc_config_update.py b/test_dockerhub_doc_config_update.py new file mode 100644 index 00000000..b989818f --- /dev/null +++ b/test_dockerhub_doc_config_update.py @@ -0,0 +1,104 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import unittest +from unittest.mock import patch, mock_open +from pathlib import Path +import dockerhub_doc_config_update + + +class TestManifestGeneration(unittest.TestCase): + @patch("dockerhub_doc_config_update.requests.get") + def test_fetch_latest_manifest(self, mock_get): + mock_get.return_value.status_code = 200 + mock_get.return_value.text = "test manifest content" + + dockerhub_doc_config_update.fetch_latest_manifest() + + with open("official-eclipse-temurin", "r") as f: + self.assertEqual(f.read(), "test manifest content") + + @patch("subprocess.check_output", return_value=b"mock-git-commit-hash") + def test_get_git_commit(self, mock_subprocess): + commit = dockerhub_doc_config_update.get_git_commit() + self.assertEqual(commit, "mock-git-commit-hash") + + def test_parse_dockerfile(self): + dockerfile_content = """\ + ENV JAVA_VERSION=jdk-11.0.16+8 + case "${ARCH}" in + x86_64) + echo "amd64 selected" + ;; + arm64) + echo "arm64v8 selected" + ;; + esac + """ + + with patch("builtins.open", mock_open(read_data=dockerfile_content)): + java_version, architectures = dockerhub_doc_config_update.parse_dockerfile( + "path/to/Dockerfile", "linux" + ) + self.assertEqual(java_version, "jdk-11.0.16+8") + self.assertEqual(architectures, ["amd64", "arm64v8"]) + + def test_generate_tags(self): + tags = dockerhub_doc_config_update.generate_tags( + "11.0.16_8", "11", "jdk", "alpine-3.21" + ) + expected_tags = [ + "11.0.16_8-jdk-alpine-3.21", + "11-jdk-alpine-3.21", + "11-alpine-3.21", + "11.0.16_8-jdk-alpine", + "11-jdk-alpine", + "11-alpine", + ] + self.assertEqual(tags, expected_tags) + + def test_generate_shared_tags(self): + shared_tags = dockerhub_doc_config_update.generate_shared_tags( + "11.0.16_8", "11", "jdk", "noble", "linux" + ) + expected_shared_tags = ["11.0.16_8-jdk", "11-jdk", "11"] + self.assertEqual(shared_tags, expected_shared_tags) + + +@patch("manifest_generator.get_git_commit", return_value="mock-git-commit-hash") +@patch("pathlib.Path.read_text", return_value="Tags: 11-jdk-alpine-3.21") +def test_generate_official_image_info(self, mock_read_text, mock_git_commit): + # Mock an open file + output_file = mock_open() + with patch("builtins.open", output_file): + with open("dummy_output", "w") as file: # Simulate a file object + dockerhub_doc_config_update.generate_official_image_info( + file, "11", "jdk", "linux", "11/jdk/alpine/3.21" + ) + + # Extract the written data from the mock file handle + handle = output_file() + written_content = "".join(call[0][0] for call in handle.write.call_args_list) + + # Verify parts of the generated content + self.assertIn( + "Tags: 11.0.16_8-jdk-alpine-3.21, 11-jdk-alpine-3.21, 11-alpine-3.21", + written_content, + ) + self.assertIn("Architectures: amd64, arm64v8", written_content) + self.assertIn("GitCommit: mock-git-commit-hash", written_content) + self.assertIn("Directory: 11/jdk/alpine/3.21", written_content) + + +if __name__ == "__main__": + unittest.main()