#!/usr/bin/env python3 # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you 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 # # http://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. # ruff: noqa: E501 import argparse import datetime import json import logging import subprocess from typing import Any from cmd_utils import Sh, init_log from http_utils import get DOCKER_API_BASE = "https://hub.docker.com/v2/" PAGE_SIZE = 25 TEST_DATA = None def docker_api(url: str) -> dict[str, Any]: """ Run a paginated fetch from the public Docker Hub API """ if TEST_DATA is not None: return TEST_DATA[url] pagination = f"?page_size={PAGE_SIZE}&page=1" url = DOCKER_API_BASE + url + pagination r, headers = get(url) reset = headers.get("x-ratelimit-reset") if reset is not None: reset = datetime.datetime.fromtimestamp(int(reset)) reset = reset.isoformat() logging.info( f"Docker API Rate Limit: {headers.get('x-ratelimit-remaining')} / {headers.get('x-ratelimit-limit')} (reset at {reset})" ) if "results" not in r: raise RuntimeError(f"Error fetching data, no results found in: {r}") return r def any_docker_changes_since(hash: str) -> bool: """ Check the docker/ directory, return True if there have been any code changes since the specified hash """ sh = Sh() cmd = f"git diff {hash} -- docker/" proc = sh.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) stdout = proc.stdout.strip() return stdout != "", stdout def does_commit_exist(hash: str) -> bool: """ Returns True if the hash exists in the repo """ sh = Sh() cmd = f"git rev-parse -q {hash}" proc = sh.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=False) print(proc.stdout) if proc.returncode == 0: return True if "unknown revision or path not in the working tree" in proc.stdout: return False raise RuntimeError(f"Unexpected failure when running: {cmd}") def find_hash_for_tag(tag: dict[str, Any]) -> str: """ Split the hash off of a name like -