aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/set_versions.py
blob: de9069397c00c18211c5f7dd0c91b0f67824ccf4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
"""
Generate a Dockerfile from in.Dockerfile and a version JSON file, and write version info.

If the argument --error-modified is passed, the script will not write any output
and will exit with status code 1 if the output files were modified.
"""

import difflib
import sys
from pathlib import Path
from textwrap import dedent

try:
    from scripts.python_version import ALL_VERSIONS, MAIN_VERSION
except ModuleNotFoundError:
    sys.path.insert(0, Path(__file__).parent.parent.absolute().as_posix())
    from scripts.python_version import ALL_VERSIONS, MAIN_VERSION

DOCKERFILE_TEMPLATE = Path("scripts/in.Dockerfile").read_text("utf-8")
DOCKERFILE = Path("Dockerfile")
ERROR_MODIFIED = "--error-modified" in sys.argv

# Download and copy multiple python images into one layer
python_build = ""
previous_layer = "first"

for version in ALL_VERSIONS:
    if version.is_main:
        # Main is handled separately later
        continue

    # Add the current version to the Dockerfile
    layer_name = version.version_name.replace(".", "-")  # Dots aren't valid in layer names
    python_build += dedent(
        f"""
        FROM python:{version.image_tag} as base-{layer_name}
        COPY --from=base-{previous_layer} / /
    """
    )
    previous_layer = layer_name

# Main version is installed twice, once at the very beginning to make sure
# its files aren't overwritten, and once at the end which actually makes use of the version
python_build = f"FROM python:{MAIN_VERSION.image_tag} as base-first\n" + python_build

# Write new dockerfile
# fmt: off
# Black makes the following block much less readable
dockerfile_out = (
    "# THIS FILE IS AUTOGENERATED, DO NOT MODIFY! #\n"
    + DOCKERFILE_TEMPLATE
    .replace("{python_install_commands}", python_build)
    .replace("{final_base}", previous_layer).replace("{main_version_tag}", MAIN_VERSION.image_tag)
)
# fmt: on

if ERROR_MODIFIED:
    if (original := DOCKERFILE.read_text("utf-8")) != dockerfile_out:
        print("Dockerfile modified:")
        print("\n".join(difflib.unified_diff(dockerfile_out.splitlines(), original.splitlines())))
        raise SystemExit(1)
    else:
        exit(0)
else:
    DOCKERFILE.write_text(dockerfile_out, "utf-8")

print("Finished!")