Skip to content
Snippets Groups Projects
check_schema_delta.py 3.38 KiB
Newer Older
  • Learn to ignore specific revisions
  • #!/usr/bin/env python3
    
    # Check that no schema deltas have been added to the wrong version.
    
    import re
    from typing import Any, Dict, List
    
    import click
    import git
    
    SCHEMA_FILE_REGEX = re.compile(r"^synapse/storage/schema/(.*)/delta/(.*)/(.*)$")
    
    
    @click.command()
    @click.option(
        "--force-colors",
        is_flag=True,
        flag_value=True,
        default=None,
        help="Always output ANSI colours",
    )
    def main(force_colors: bool) -> None:
        click.secho(
            "+++ Checking schema deltas are in the right folder",
            fg="green",
            bold=True,
            color=force_colors,
        )
    
        click.secho("Updating repo...")
    
        repo = git.Repo()
        repo.remote().fetch()
    
        click.secho("Getting current schema version...")
    
        r = repo.git.show("origin/develop:synapse/storage/schema/__init__.py")
    
        locals: Dict[str, Any] = {}
        exec(r, locals)
        current_schema_version = locals["SCHEMA_VERSION"]
    
        diffs: List[git.Diff] = repo.remote().refs.develop.commit.diff(None)
    
    
        # Get the schema version of the local file to check against current schema on develop
    
        with open("synapse/storage/schema/__init__.py") as file:
    
            local_schema = file.read()
        new_locals: Dict[str, Any] = {}
        exec(local_schema, new_locals)
        local_schema_version = new_locals["SCHEMA_VERSION"]
    
        if local_schema_version != current_schema_version:
            # local schema version must be +/-1 the current schema version on develop
            if abs(local_schema_version - current_schema_version) != 1:
                click.secho(
                    "The proposed schema version has diverged more than one version from develop, please fix!",
                    fg="red",
                    bold=True,
                    color=force_colors,
                )
                click.get_current_context().exit(1)
    
            # right, we've changed the schema version within the allowable tolerance so
            # let's now use the local version as the canonical version
            current_schema_version = local_schema_version
    
        click.secho(f"Current schema version: {current_schema_version}")
    
    
        seen_deltas = False
        bad_files = []
        for diff in diffs:
            if not diff.new_file or diff.b_path is None:
                continue
    
            match = SCHEMA_FILE_REGEX.match(diff.b_path)
            if not match:
                continue
    
            seen_deltas = True
    
            _, delta_version, _ = match.groups()
    
            if delta_version != str(current_schema_version):
                bad_files.append(diff.b_path)
    
        if not seen_deltas:
            click.secho(
                "No deltas found.",
                fg="green",
                bold=True,
                color=force_colors,
            )
            return
    
        if not bad_files:
            click.secho(
                f"All deltas are in the correct folder: {current_schema_version}!",
                fg="green",
                bold=True,
                color=force_colors,
            )
            return
    
        bad_files.sort()
    
        click.secho(
            "Found deltas in the wrong folder!",
            fg="red",
            bold=True,
            color=force_colors,
        )
    
        for f in bad_files:
            click.secho(
                f"\t{f}",
                fg="red",
                bold=True,
                color=force_colors,
            )
    
        click.secho()
        click.secho(
            f"Please move these files to delta/{current_schema_version}/",
            fg="red",
            bold=True,
            color=force_colors,
        )
    
        click.get_current_context().exit(1)
    
    
    if __name__ == "__main__":
        main()