mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-11-06 19:06:58 +00:00
* feat(ci): support optional Docker targets for query regression Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(ci): enable Docker when provisioning image regression runners Signed-off-by: WenyXu <wenymedia@gmail.com> * feat(ci): publish precompiled query regression helpers with pin update PRs Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(ci): retry helper image publication on registry timeouts Signed-off-by: WenyXu <wenymedia@gmail.com> * fix(ci): publish helper artifacts with hosted Skopeo job Signed-off-by: WenyXu <wenymedia@gmail.com> * refactor(ci): update helper image through repository variable Signed-off-by: WenyXu <wenymedia@gmail.com> --------- Signed-off-by: WenyXu <wenymedia@gmail.com>
83 lines
3.4 KiB
Python
83 lines
3.4 KiB
Python
#!/usr/bin/env python3
|
|
# Copyright 2023 Greptime Team
|
|
#
|
|
# 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
|
|
#
|
|
# 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.
|
|
|
|
"""Extract digest-pinned query regression tools from an artifact image."""
|
|
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import os
|
|
import re
|
|
import subprocess
|
|
from pathlib import Path
|
|
|
|
BINARIES = ("query_perf_fixture", "query_regression_runner")
|
|
|
|
|
|
def resolve_image(value):
|
|
if value == "pinned":
|
|
value = os.environ.get("QUERY_REGRESSION_HELPERS_IMAGE", "")
|
|
if not re.fullmatch(r"[a-zA-Z0-9][a-zA-Z0-9._/:@-]*@sha256:[0-9a-f]{64}", value):
|
|
raise ValueError("helpers_image requires an image@sha256 digest; set QUERY_REGRESSION_HELPERS_IMAGE by publishing a verified image before using 'pinned'")
|
|
return value
|
|
|
|
|
|
def run(*args):
|
|
return subprocess.check_output(args, text=True).strip()
|
|
|
|
|
|
def extract(image, destination, checksums=None):
|
|
expected = None
|
|
if checksums is not None:
|
|
entries = [line.split() for line in checksums.read_text().splitlines()]
|
|
expected = {name: digest for digest, name in entries}
|
|
if set(expected) != set(BINARIES) or len(entries) != len(BINARIES):
|
|
raise ValueError("Checksums must contain exactly the two helper binaries")
|
|
image = resolve_image(image)
|
|
destination.mkdir(parents=True, exist_ok=True)
|
|
run("docker", "pull", image)
|
|
metadata = json.loads(run("docker", "image", "inspect", image))[0]
|
|
revision = (metadata.get("Config", {}).get("Labels") or {}).get("org.opencontainers.image.revision", "")
|
|
if not re.fullmatch(r"[0-9a-f]{40}", revision):
|
|
raise ValueError("Helper image is missing its source revision label")
|
|
container = run("docker", "create", image, "/query_perf_fixture", "--help")
|
|
try:
|
|
for binary in BINARIES:
|
|
target = destination / binary
|
|
run("docker", "cp", f"{container}:/{binary}", str(target))
|
|
target.chmod(0o755)
|
|
if expected is None:
|
|
run(str(target.resolve()), "--help")
|
|
else:
|
|
with target.open("rb") as file:
|
|
actual = hashlib.file_digest(file, "sha256").hexdigest()
|
|
if actual != expected[binary]:
|
|
raise ValueError(f"Published helper checksum mismatch: {binary}")
|
|
finally:
|
|
run("docker", "rm", "--force", "--volumes", container)
|
|
provenance = {"image": image, "image_id": metadata["Id"], "source_revision": revision}
|
|
(destination / "helpers-image.json").write_text(json.dumps(provenance, indent=2) + "\n")
|
|
print(json.dumps(provenance))
|
|
return provenance
|
|
|
|
|
|
if __name__ == "__main__":
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("image")
|
|
parser.add_argument("destination", type=Path)
|
|
parser.add_argument("--checksums", type=Path, help="Verify build checksums instead of executing on this host")
|
|
args = parser.parse_args()
|
|
extract(args.image, args.destination, args.checksums)
|