Beispiel #1
0
def find(_, name, commit=None, profile=None):
    """
    Find the first release containing a specific commit.
    """
    if commit is None:
        commit = "HEAD"

    repo = utils.git_repo()
    oid = utils.revparse(repo, commit)

    client = utils.s3_client(profile)

    releases = {
        release.commit: release
        for release in get_releases(client, name)
    }

    release = None
    for log in utils.git_log(repo):
        if log.hex in releases:
            release = releases[log.hex]

        if oid.hex == log.hex:
            break

    if release:
        utils.printfmt(release)

    else:
        LOG.error("Commit not released yet")
Beispiel #2
0
def list_releases(name, last, contains, bucket=None):
    repo = None
    contains_oid = None

    if contains:
        repo = utils.git_repo()
        contains_oid = utils.revparse(repo, contains)
        if contains_oid not in repo:
            raise Exception(f"Commit {contains_oid} does not exist in repo")

    releases = get_releases(utils.s3_client(), name, bucket=bucket)

    release_data = []
    now = datetime.now(tz=timezone.utc)
    last = int(last) if last else None
    for i, rel in enumerate(releases):
        if i == last:
            break
        release_dict = {
            "version": rel.version,
            "commit": rel.commit,
            "timestamp": rel.timestamp,
            "age": now - rel.timestamp,
            "author": rel.author,
            "rollback": rel.rollback,
            "action_type": rel.action_type,
        }
        if contains:
            release_dict["contains"] = release_contains(repo, rel, contains_oid, name)
        release_data.append(release_dict)

    utils.printfmt(release_data, tabular=True)
Beispiel #3
0
 def resolve_range(ref):
     if ref.startswith("v") and ref[1:].isdigit():
         release = get_release(client, name, int(ref[1:]))
         ref = release.commit
     return utils.revparse(repo, ref)
Beispiel #4
0
def new(
    ctx,
    name,
    commit=None,
    version=None,
    dry=False,
    yes=False,
    image_name=None,
    image_id=None,
    rollback=False,
    filter_files_path=None,
    profile=None,
):
    """
    Create a new release.
    """
    repo = utils.git_repo()

    client = utils.s3_client(profile)
    latest = next(get_releases(client, name), None)
    latest_oid = git.Oid(hex=latest.commit) if latest else None

    if commit is None:
        commit = "HEAD"

    commit_oid = utils.revparse(repo, commit)

    if version is None:
        # create next version
        version = 1 if latest is None else latest.version + 1

    else:
        version = int(version)

    if image_id is None:
        image_id = _get_image_id(ctx,
                                 commit_oid,
                                 name=name,
                                 image_name=image_name)

        if image_id is None:
            utils.fatal("Image not found")

    keep_only_files = None
    if filter_files_path:
        with open(filter_files_path) as fp:
            keep_only_files = [line.strip() for line in fp]

    changelog = utils.changelog(repo,
                                commit_oid,
                                latest_oid,
                                keep_only_files=keep_only_files)

    action_type = ActionType.automated if config.IS_CONCOURSE else ActionType.manual

    release = Release(
        version=version,
        commit=commit_oid.hex,
        changelog=changelog.short_text,
        version_id="",
        image=image_id,
        timestamp=datetime.now(),
        author=utils.get_author(repo, commit_oid),
        rollback=changelog.rollback,
        action_type=action_type,
        commits=[commit.hex for commit in changelog.logs],
    )

    utils.printfmt(release)

    if dry:
        return

    if release.rollback:
        utils.warning("This is a rollback! :warning:\n")

        if not rollback:
            utils.warning("Missing flag --rollback\n")
            utils.fatal("Aborted!")

    if not yes:

        if release.rollback:
            ok = utils.confirm(
                "Are you sure you want to create a rollback release?",
                style=utils.TextStyle.yellow,
            )

            if not ok:
                utils.fatal("Aborted!")

        ok = utils.confirm("Are you sure you want to create this release?")
        if not ok:
            utils.fatal("Aborted!")

    put_release(client, _get_bucket(), name, release)

    utils.success("Created new release :tada:\n")
Beispiel #5
0
def list_projects(
    contains, only, permissions, utc, env, releases_only, profile
) -> List[Project]:

    contains_oid = None
    repo = None

    if contains:
        repo = utils.git_repo()
        contains_oid = utils.revparse(repo, contains)
        if contains_oid not in repo:
            raise Exception(f"Commit {contains_oid} does not exist in repo")

    if only is not None:
        only = re.compile(only)

    if env is not None:
        env = set(env.split(","))

    client = utils.s3_client(profile)
    config = utils.get_config()
    release_bucket = config["release"]["s3_bucket"]
    deploys = config["deploy"]

    resp = client.list_objects_v2(Bucket=release_bucket)

    project_names = sorted(data["Key"] for data in resp.get("Contents", []))

    can_release = {}
    can_deploy = {}

    if permissions:
        iam_client = utils.iam_client(profile)

        can_release = check_perms(iam_client, release_bucket, project_names, profile)
        can_deploy = {
            env_name: check_perms(iam_client, cfg["s3_bucket"], project_names, profile)
            for env_name, cfg in deploys.items()
        }

    _projects = []

    now = datetime.now(tz=timezone.utc)
    localzone = get_localzone()

    for name in project_names:
        if only and only.search(name) is None:
            continue

        try:
            release = fetch_release(client, release_bucket, name)
        except InvalidRelease:
            continue

        timestamp_utc = release.timestamp
        timestamp = timestamp_utc if utc else timestamp_utc.astimezone(localzone)

        if releases_only or env is None:
            _projects.append(
                Project(
                    name=name,
                    version=release.version,
                    behind=0,
                    commit=release.commit,
                    timestamp=timestamp,
                    age=now - timestamp_utc,
                    type=ProjectType.release,
                    contains=(
                        release_contains(repo, release, contains_oid, name)
                        if contains
                        else None
                    ),
                    env_name="",
                    permission=can_release.get(name),
                    action_type=release.action_type,
                    author=release.author,
                )
            )

        if releases_only:
            continue

        for env_name, cfg in deploys.items():
            try:
                deploy = fetch_release(client, cfg["s3_bucket"], name)
            except InvalidRelease:
                continue

            timestamp_utc = deploy.timestamp
            timestamp = timestamp_utc if utc else timestamp_utc.astimezone(localzone)

            if not env or env_name in env:
                _projects.append(
                    Project(
                        name=name,
                        version=deploy.version,
                        behind=release.version - deploy.version,
                        commit=deploy.commit,
                        timestamp=timestamp,
                        age=now - timestamp_utc,
                        type=ProjectType.deploy,
                        env_name=env_name,
                        contains=(
                            release_contains(repo, deploy, contains_oid, name)
                            if contains
                            else None
                        ),
                        permission=can_deploy.get(env_name, {}).get(name),
                        action_type=deploy.action_type,
                        author=deploy.author,
                    )
                )

    return _projects
Beispiel #6
0
def ls(
    _,
    author=False,
    contains=None,
    sort=None,
    reverse=False,
    only=None,
    permissions=False,
):
    """
    List all the projects managed with catapult.

    Optionally pass a full SHA-1 hash of a commit in the current repo,
    and each release/deploy will be marked with 'Y' if it contains that
    commit, 'N' if it doesn't, or '?' if it can't be determined (eg
    perhaps the App belongs to another repo).
    """

    contains_oid = None
    repo = None

    optional_columns = {
        "author": bool(author),
        "contains": bool(contains),
        "permission": bool(permissions),
    }

    if contains:
        repo = utils.git_repo()
        contains_oid = utils.revparse(repo, contains)
        if contains_oid not in repo:
            raise Exception(f"Commit {contains_oid} does not exist in repo")

    valid_sort_keys = list(Project._fields)

    for column_name, show_column in optional_columns.items():
        if not show_column:
            valid_sort_keys.remove(column_name)

    sort_keys = [] if sort is None else sort.split(",")
    if any(sort_key not in valid_sort_keys for sort_key in sort_keys):
        raise Exception(
            f"Invalid sort key in {sort!r}. Valid sort keys: {valid_sort_keys}"
        )

    if only is not None:
        only = only.split(",")

    client = utils.s3_client()
    config = utils.get_config()
    release_bucket = config["release"]["s3_bucket"]
    deploys = config["deploy"]

    resp = client.list_objects_v2(Bucket=release_bucket)

    project_names = sorted(data["Key"] for data in resp.get("Contents", []))

    can_release = {}
    can_deploy = {}

    if permissions:
        iam_client = utils.iam_client()

        can_release = check_perms(iam_client, release_bucket, project_names)
        can_deploy = {
            env_name: check_perms(iam_client, cfg["s3_bucket"], project_names)
            for env_name, cfg in deploys.items()
        }

    _projects = []

    now = datetime.now(tz=timezone.utc)

    for name in project_names:
        if only and name not in only:
            continue

        try:
            release = get_release(client, release_bucket, name)
        except InvalidRelease:
            continue

        _projects.append(
            Project(
                name=name,
                version=release.version,
                behind=0,
                commit=release.commit,
                timestamp=release.timestamp,
                age=now - release.timestamp,
                type=ProjectType.release,
                contains=(release_contains(repo, release, contains_oid, name)
                          if contains else None),
                env_name="",
                permission=can_release.get(name),
                action_type=release.action_type,
                author=release.author,
            ))

        for env_name, cfg in deploys.items():
            try:
                deploy = get_release(client, cfg["s3_bucket"], name)
            except InvalidRelease:
                continue

            _projects.append(
                Project(
                    name=name,
                    version=deploy.version,
                    behind=release.version - deploy.version,
                    commit=deploy.commit,
                    timestamp=deploy.timestamp,
                    age=now - deploy.timestamp,
                    type=ProjectType.deploy,
                    env_name=env_name,
                    contains=(release_contains(repo, deploy, contains_oid,
                                               name) if contains else None),
                    permission=can_deploy.get(env_name, {}).get(name),
                    action_type=deploy.action_type,
                    author=deploy.author,
                ))

    project_dicts = []
    for project in _projects:
        project_dict = project._asdict()
        for column_name, show_column in optional_columns.items():
            if not show_column:
                project_dict.pop(column_name)

        style = (utils.TextStyle.yellow
                 if project_dict["type"] is ProjectType.release else
                 utils.TextStyle.blue)
        project_dict["name"] = utils.Formatted(project_dict["name"], style)
        project_dict["type"] = utils.Formatted(project_dict["type"].name,
                                               style)
        project_dicts.append(project_dict)

    if sort_keys:
        project_dicts.sort(key=itemgetter(*sort_keys), reverse=reverse)

    utils.printfmt(project_dicts, tabular=True)