summaryrefslogtreecommitdiff
path: root/tools/add_module.py
blob: c0ef01628ac951cefc2bef07ed1fb1004c2a31be (plain)
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import sys
import subprocess
import argparse
from pathlib import Path, PurePosixPath
import tempfile
import tarfile
from integrity import file_hash
import json

def make_git_archive(repo_path: Path, tag: str, output_path: Path):
    try:
        subprocess.run(
            ["git", "archive", "--format=tar.gz", "--output", str(output_path.absolute()), tag],
            cwd=repo_path,
            check=True
        )
    except subprocess.CalledProcessError as e:
        print(f"Error creating git archive: {e}")
        sys.exit(1)

def extract_module_content(archive_path: Path) -> str:
    with tarfile.open(archive_path, "r:gz") as tar:
        file = tar.extractfile("MODULE.bazel")
        if file is None:
            print("Error: MODULE.bazel file not found in the archive.")
            sys.exit(1)
        return file.read().decode()

def upload_to_blob_storage(local_path: Path, remote_path: str, scp_port: int = 22):
    try:
        ssh_login = remote_path.split(":")[0]
        ssh_path = str(PurePosixPath(remote_path.split(":")[1]).parent)

        subprocess.run(
            ["ssh", "-p", str(scp_port), ssh_login, f"mkdir -p {ssh_path}"],
            check=True,
            stdout=sys.stdout,
            stderr=sys.stderr,
        )

        subprocess.run(
            ["scp", "-P", str(scp_port), str(local_path), remote_path],
            check=True,
            stdout=sys.stdout,
            stderr=sys.stderr,
        )
    except subprocess.CalledProcessError as e:
        print(f"Error uploading to blob storage: {e}")
        sys.exit(1)

MODULES_DIR = Path(__file__).parent.parent / "modules"

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Add a module to the registry.")
    parser.add_argument("module_name", type=str, help="Name of the module to add")
    parser.add_argument("module_version", type=str, help="Version of the module to add")
    parser.add_argument("local_git_repo_path", type=str, help="Path to the local git repository")
    parser.add_argument("remote_blob_path", type=str, help="SCP-compatible path to the remote blob storage folder")
    parser.add_argument("-t", "--tag", type=str, default=None, help="Git tag for the module version")
    parser.add_argument("-p", "--scp_port", type=int, default=22, help="Port for SCP connection (default: 22)")

    args = parser.parse_args()

    module_name = args.module_name
    module_version = args.module_version
    local_git_repo_path = Path(args.local_git_repo_path)
    git_repo_tag = args.tag or f"v{module_version}"

    if not local_git_repo_path.exists():
        print(f"Error: The specified local git repository path '{local_git_repo_path}' does not exist.")
        sys.exit(1)
    
    registry_module_path = MODULES_DIR / module_name / module_version
    if registry_module_path.exists():
        print(f"Error: The module '{module_name}' version '{module_version}' already exists in the registry.")
        sys.exit(1)
    
    tmp_dir = tempfile.TemporaryDirectory()

    archive_file = Path(tmp_dir.name) / f"archive.tar.gz"
    make_git_archive(local_git_repo_path, git_repo_tag, archive_file)

    module_content = extract_module_content(archive_file)
    integrity = file_hash(archive_file)
    partial_hash = integrity[7:17]

    registry_module_path.mkdir(parents=True, exist_ok=True)
    with open(registry_module_path / "MODULE.bazel", "wb+") as f:
        f.write(module_content.encode())
    
    blob_path = f"{module_name}/{module_version}-{partial_hash}.tar.gz"
    remote_blob_path = f"{args.remote_blob_path}/{blob_path}"

    upload_to_blob_storage(archive_file, remote_blob_path, args.scp_port)
    
    source_json = {
        "url": f"https://bazel.stevenlr.com/blobs/{blob_path}",
        "integrity": integrity,
    }

    with open(registry_module_path / "source.json", "wb+") as f:
        f.write(json.dumps(source_json, indent=2).encode())