Ctrl K
ComunidadGuías…

build/buildrelease-repo.py

Rama master · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/python3 -u

import getopt
import re
import os
from os import path
import shutil
import subprocess
import sys
import tempfile

# clone URL for MantisBT repository
clone_url = 'https://github.com/mantisbt/mantisbt.git'

build_script_name = 'buildrelease.py'

# List of refs to ignore (regular expressions)
# - HEAD (generally the same as master)
# - dependabot branches
# - 1.x refs
ignorelist = [
              r'^origin\/HEAD$',
              r'-1\.[\d]+\.[\w\d]+',
              r'^origin\/dependabot\/',
             ]

# Script options
options = "hfr:bacds:"
long_options = ["help", "fresh", "ref=", "branches", "auto-suffix", "clean",
                "docbook", "suffix="]


def usage():
    print(f'''Builds one or more releases (zip/tarball) for the specified
references or for all branches.

Usage: {path.basename(__file__)} [options] /path/for/tarballs [/path/to/repo]

Options:
    -h | --help                  Show this usage message

    -f | --fresh                 Create a fresh clone in repository path,
                                 or temporary path
    -r | --ref <ref>[,<ref>...]  Build a release for named refs <ref>
    -b | --branches              Build a release for all branches
    -a | --auto-suffix           Automatically append the HEAD commit's sha1
                                 to the version suffix

The following options are passed on to '{build_script_name}':
    -c | --clean                 Remove build directories when completed
    -d | --docbook               Build the docbook manuals
    -s | --suffix <suffix>       Include version suffix in config files
''')
# end usage()


def get_head_commit_sha():
    result = subprocess.run(['git', 'log', '--pretty=format:%h', '-n1'],
                            check=True, text=True, capture_output=True)
    return result.stdout


def ignore(ref):
    """
    Decide which refs to ignore based on regexen listed in 'ignorelist'.
    """
    for regex in [re.compile(r) for r in ignorelist]:
        if len(regex.findall(ref)) > 0:
            return True
    return False
# end ignore()


def main():
    try:
        opts, args = getopt.gnu_getopt(sys.argv[1:], options, long_options)
    except getopt.GetoptError as err:
        print(err)
        usage()
        sys.exit(2)

    pass_opts = []
    refs = []
    all_branches = False
    version_suffix = ""
    auto_suffix = False
    fresh_clone = False
    delete_clone = False

    # noinspection PyUnboundLocalVariable
    for opt, val in opts:
        if opt in ("-h", "--help"):
            usage()
            sys.exit(0)

        elif opt in ("-f", "--fresh"):
            fresh_clone = True

        elif opt in ("-r", "--ref"):
            refs.extend(val.split(","))

        elif opt in ("-b", "--branches"):
            all_branches = True

        elif opt in ("-c", "--clean"):
            pass_opts.append("-c")
        elif opt in ("-d", "--docbook"):
            pass_opts.append("-d")

        elif opt in ("-a", "--auto-suffix"):
            auto_suffix = True

        elif opt in ("-s", "--suffix"):
            version_suffix = val

    # noinspection PyUnboundLocalVariable
    if len(args) < 1:
        usage()
        sys.exit(1)

    release_path = path.abspath(args[0])
    repo_path = "."

    if len(args) > 1:
        repo_path = path.abspath(args[1])

    # Create a new repo clone
    if fresh_clone:
        print("Origin MantisBT repository:", clone_url)
        if repo_path == ".":
            if not path.isdir(release_path):
                print("Creating release path...")
                os.mkdir(release_path)
            repo_path = tempfile.mkdtemp(dir=release_path, prefix="mantisbt-", suffix=".git")
            delete_clone = True
        try:
            subprocess.run(['git', 'clone', clone_url, repo_path], check=True)
        except subprocess.CalledProcessError:
            print("ERROR: clone failed")
            sys.exit(1)

    # Change to the repo path
    script_dir = path.dirname(path.abspath(__file__))
    os.chdir(repo_path)

    # Update the repository
    if not fresh_clone:
        print(f"Updating repository at '{repo_path}'")
        subprocess.run(['git', 'fetch'], check=True)

    # Consolidate refs/branches
    if all_branches:
        subprocess.run(['git', 'remote', 'prune', 'origin'], check=True)
        result = subprocess.run(['git', 'for-each-ref', '--format=%(refname:short)', 'refs/remotes'],
                                check=True, text=True, capture_output=True)
        refs.extend(result.stdout.split())

    if not refs:
        refs.append(get_head_commit_sha())

    refs = [ref for ref in refs if not ignore(ref)]

    # Info
    print("\nWill build the following releases:")
    for ref in refs:
        print("  " + ref)

    # Regex to strip 'origin/' from ref names
    refnameregex = re.compile('(?:[a-zA-Z0-9-.]+/)?(.*)')

    for ref in refs:
        print(f"\nChecking out '{ref}'")
        subprocess.run(['git', 'checkout', '-f', '-q', ref], check=True)
        subprocess.run(['git', 'log', '-n1', '--pretty="HEAD is now at %h... %s"'],
                       check=True)
        print()

        # Composer
        if path.isfile('composer.json'):
            print("Installing Composer packages")
            composer = ['composer', 'install', '--no-plugins', '--no-scripts', '--no-dev', '--no-progress']
            try:
                subprocess.run(composer, check=True)
            except subprocess.CalledProcessError as e:
                print("ERROR:", e)
                sys.exit(1)
            print()

        # Update and reset submodules
        print("Updating submodules")
        subprocess.run(['git', 'submodule', 'update', '--init'], check=True)
        subprocess.run(['git', 'submodule', 'foreach', 'git', 'checkout', '--', '.'], check=True)

        # Handle suffix/auto-suffix generation
        commit_hash = get_head_commit_sha()
        if commit_hash != ref:
            ref = refnameregex.search(ref).group(1)
            commit_hash = f"{ref}-{commit_hash}"

        if auto_suffix and version_suffix:
            suffix = [f"--suffix={version_suffix}-{commit_hash}"]
        elif auto_suffix:
            suffix = ["--suffix=" + commit_hash]
        elif version_suffix:
            suffix = ["--suffix=" + version_suffix]
        else:
            suffix = []

        # Absolute path to buildrelease.py in the target repository, with a
        # fallback to the directory of the currently executing script
        buildscript = path.join(repo_path, 'build', build_script_name)
        if not path.exists(buildscript):
            buildscript = path.join(script_dir, build_script_name)
            print(f"Build script ({build_script_name}) not found in {ref}")
            print(f"Using '{buildscript}' instead.")

        # Start building
        try:
            cmd = [buildscript] + pass_opts + suffix + [release_path, repo_path]
            print("Running:", " ".join(cmd))
            subprocess.run(cmd, check=True)
        except subprocess.CalledProcessError as e:
            print(e)
            sys.exit(1)

    # Cleanup temporary repo if needed
    if delete_clone:
        print("\nRemoving temporary clone.")
        shutil.rmtree(repo_path)

    # Done
    print("\nAll builds completed.")

# end main()


if __name__ == "__main__":
    main()