Ejemplo n.º 1
0
def generate_release_notes_cli(
    repo_dir: str,
    github_cfg_name: str,
    github_repository_owner: str,
    github_repository_name: str,
    repository_branch: str,
    commit_range: str=None
):
    github_cfg = ctx().cfg_factory().github(github_cfg_name)

    githubrepobranch = GitHubRepoBranch(
        github_config=github_cfg,
        repo_owner=github_repository_owner,
        repo_name=github_repository_name,
        branch=repository_branch,
    )

    helper = GitHubRepositoryHelper.from_githubrepobranch(
        githubrepobranch=githubrepobranch,
    )
    git_helper = GitHelper.from_githubrepobranch(
        repo_path=repo_dir,
        githubrepobranch=githubrepobranch,
    )

    ReleaseNotes.create(
        github_helper=helper,
        git_helper=git_helper,
        repository_branch=repository_branch,
        commit_range=commit_range
    ).to_markdown()
Ejemplo n.º 2
0
    def _notify_broken_definition_owners(self, failed_descriptor):
        definition_descriptor = failed_descriptor.definition_descriptor
        main_repo = definition_descriptor.main_repo
        github_cfg = github_cfg_for_hostname(self._cfg_set,
                                             main_repo['hostname'])
        github_api = _create_github_api_object(github_cfg)
        repo_owner, repo_name = main_repo['path'].split('/')

        githubrepobranch = GitHubRepoBranch(
            github_config=github_cfg,
            repo_owner=repo_owner,
            repo_name=repo_name,
            branch=main_repo['branch'],
        )

        repo_helper = GitHubRepositoryHelper.from_githubrepobranch(
            githubrepobranch=githubrepobranch, )

        codeowners_enumerator = CodeownersEnumerator()
        codeowners_resolver = CodeOwnerEntryResolver(github_api=github_api)
        recipients = set(
            codeowners_resolver.resolve_email_addresses(
                codeowners_enumerator.enumerate_remote_repo(
                    github_repo_helper=repo_helper)))

        # in case no codeowners are available, resort to using the committer
        if not recipients:
            head_commit = repo_helper.repository.commit(main_repo['branch'])
            user_ids = {
                user_info.get('login')
                for user_info in (head_commit.committer, head_commit.author)
                if user_info.get('login')
            }
            for user_id in user_ids:
                user = github_api.user(user_id)
                if user.email:
                    recipients.add(user.email)

        # if there are still no recipients available print a warning
        if not recipients:
            warning(
                textwrap.dedent(f"""
                Unable to determine recipient for pipeline '{definition_descriptor.pipeline_name}'
                found in branch '{main_repo['branch']}' ({main_repo['path']}). Please make sure that
                CODEOWNERS and committers have exposed a public e-mail address in their profile.
                """))
        else:
            info(
                f'Sending notification e-mail to {recipients} ({main_repo["path"]})'
            )
            email_cfg = self._cfg_set.email()
            _send_mail(
                email_cfg=email_cfg,
                recipients=recipients,
                subject='Your pipeline definition in {repo} is erroneous'.
                format(repo=main_repo['path'], ),
                mail_template=
                (f"The pipeline definition for pipeline '{definition_descriptor.pipeline_name}' "
                 f" on branch '{main_repo['branch']}' contains errors.\n\n"
                 f"Error details:\n{str(failed_descriptor.error_details)}"))
Ejemplo n.º 3
0
def deploy_and_run_smoketest_pipeline(
    config_dir: str,
    config_name: str,
    concourse_team_name: str,
    cc_pipelines_repo_dir: str,
    cc_utils_repo_dir: str,
    wait_for_job_execution: bool=False,
):
    config_factory = ConfigFactory.from_cfg_dir(cfg_dir=config_dir)
    config_set = config_factory.cfg_set(cfg_name=config_name)
    concourse_cfg = config_set.concourse()

    # as this is an integration test, hard-code assumptions about the layout of
    # our pipelines repository
    template_path = os.path.join(cc_utils_repo_dir, 'concourse', 'templates')
    template_include_dir = os.path.join(cc_utils_repo_dir, 'concourse')
    pipeline_name = 'cc-smoketest'

    # retrieve pipeline-definition from github at hardcoded location
    github_cfg = config_set.github()

    githubrepobranch = GitHubRepoBranch(
        github_config=github_cfg,
        repo_owner='kubernetes',
        repo_name='cc-smoketest',
        branch='master',
    )

    helper = GitHubRepositoryHelper.from_githubrepobranch(
      githubrepobranch=githubrepobranch,
    )
    pipeline_definition = yaml.load(
        helper.retrieve_text_file_contents(
            file_path='.ci/smoketest-pipeline.yaml',
        ),
        Loader=yaml.SafeLoader,
    )

    definition_descriptor = DefinitionDescriptor(
        pipeline_name=pipeline_name,
        pipeline_definition=pipeline_definition[pipeline_name],
        main_repo={'path': 'kubernetes/cc-smoketest', 'branch': 'master'},
        concourse_target_cfg=concourse_cfg,
        concourse_target_team=concourse_team_name,
    )

    preprocessor = DefinitionDescriptorPreprocessor()
    template_retriever = TemplateRetriever(template_path=template_path)
    renderer = Renderer(
        template_retriever=template_retriever,
        template_include_dir=template_include_dir,
        cfg_set=config_set,
    )
    deployer = ConcourseDeployer(
        unpause_pipelines=True,
        expose_pipelines=True
    )

    definition_descriptor = preprocessor.process_definition_descriptor(definition_descriptor)
    rendering_result = renderer.render(definition_descriptor)

    info('deploying pipeline')
    deployment_result = deployer.deploy(rendering_result.definition_descriptor)

    if not deployment_result.deploy_status & DeployStatus.SUCCEEDED:
        fail('deployment failed')
Ejemplo n.º 4
0
def release_and_prepare_next_dev_cycle(
    githubrepobranch: GitHubRepoBranch,
    repository_version_file_path: str,
    release_version: str,
    repo_dir: str,
    release_notes_policy: str,
    release_commit_publishing_policy: str,
    release_commit_callback: str = None,
    next_version_callback: str = None,
    version_operation: str = "bump_minor",
    prerelease_suffix: str = "dev",
    author_name: str = "gardener-ci",
    author_email: str = "*****@*****.**",
    component_descriptor_file_path: str = None,
    slack_cfg_name: str = None,
    slack_channel: str = None,
    rebase_before_release: bool = False,
    commit_message_prefix: str = None,
):
    transaction_ctx = TransactionContext()  # shared between all steps/trxs

    release_notes_policy = ReleaseNotesPolicy(release_notes_policy)
    release_commit_publishing_policy = ReleaseCommitPublishingPolicy(
        release_commit_publishing_policy)
    github_helper = GitHubRepositoryHelper.from_githubrepobranch(
        githubrepobranch)
    git_helper = GitHelper.from_githubrepobranch(
        githubrepobranch=githubrepobranch,
        repo_path=repo_dir,
    )

    step_list = []

    if rebase_before_release:
        rebase_step = RebaseStep(
            git_helper=git_helper,
            repository_branch=githubrepobranch.branch(),
        )
        step_list.append(rebase_step)

    release_commit_step = ReleaseCommitStep(
        git_helper=git_helper,
        repo_dir=repo_dir,
        release_version=release_version,
        repository_version_file_path=repository_version_file_path,
        repository_branch=githubrepobranch.branch(),
        commit_message_prefix=commit_message_prefix,
        release_commit_callback=release_commit_callback,
        publishing_policy=release_commit_publishing_policy,
    )
    step_list.append(release_commit_step)

    if version_operation != version.NOOP:
        next_cycle_commit_step = NextDevCycleCommitStep(
            git_helper=git_helper,
            repo_dir=repo_dir,
            release_version=release_version,
            repository_version_file_path=repository_version_file_path,
            repository_branch=githubrepobranch.branch(),
            version_operation=version_operation,
            prerelease_suffix=prerelease_suffix,
            next_version_callback=next_version_callback,
            publishing_policy=release_commit_publishing_policy,
        )
        step_list.append(next_cycle_commit_step)

    github_release_step = GitHubReleaseStep(
        github_helper=github_helper,
        githubrepobranch=githubrepobranch,
        repo_dir=repo_dir,
        release_version=release_version,
        component_descriptor_file_path=component_descriptor_file_path,
    )
    step_list.append(github_release_step)

    release_transaction = Transaction(ctx=transaction_ctx, steps=step_list)

    release_transaction.validate()
    if not release_transaction.execute():
        raise RuntimeError('An error occurred while creating the Release.')

    publish_release_notes_step = PublishReleaseNotesStep(
        githubrepobranch=githubrepobranch,
        github_helper=github_helper,
        release_version=release_version,
        repo_dir=repo_dir,
    )

    cleanup_draft_releases_step = TryCleanupDraftReleasesStep(
        github_helper=github_helper, )

    cleanup_draft_releases_transaction = Transaction(
        ctx=transaction_ctx,
        steps=(cleanup_draft_releases_step, ),
    )

    if not cleanup_draft_releases_transaction.execute():
        ci.util.warning('An error occured while cleaning up draft releases')

    if release_notes_policy == ReleaseNotesPolicy.DISABLED:
        return info('release notes were disabled - skipping')
    elif release_notes_policy == ReleaseNotesPolicy.DEFAULT:
        pass
    else:
        raise NotImplementedError(release_notes_policy)

    release_notes_transaction = Transaction(
        ctx=transaction_ctx,
        steps=(publish_release_notes_step, ),
    )
    release_notes_transaction.validate()
    if not release_notes_transaction.execute():
        raise RuntimeError(
            'An error occurred while publishing the release notes.')

    if slack_cfg_name and slack_channel:
        release_notes = transaction_ctx.step_output(
            publish_release_notes_step.name()).get('release notes')

        post_to_slack_step = PostSlackReleaseStep(
            slack_cfg_name=slack_cfg_name,
            slack_channel=slack_channel,
            release_version=release_version,
            release_notes=release_notes,
            githubrepobranch=githubrepobranch,
        )
        slack_transaction = Transaction(
            ctx=transaction_ctx,
            steps=(post_to_slack_step, ),
        )
        slack_transaction.validate()
        if not slack_transaction.execute():
            raise RuntimeError(
                'An error occurred while posting the release notes to Slack.')
Ejemplo n.º 5
0
def release_and_prepare_next_dev_cycle(
    githubrepobranch: GitHubRepoBranch,
    repository_version_file_path: str,
    release_version: str,
    repo_dir: str,
    release_notes_policy: str,
    release_commit_callback: str = None,
    next_version_callback: str = None,
    version_operation: str = "bump_minor",
    prerelease_suffix: str = "dev",
    author_name: str = "gardener-ci",
    author_email: str = "*****@*****.**",
    component_descriptor_file_path: str = None,
    slack_cfg_name: str = None,
    slack_channel: str = None,
    rebase_before_release: bool = False,
):
    release_notes_policy = ReleaseNotesPolicy(release_notes_policy)
    github_helper = GitHubRepositoryHelper.from_githubrepobranch(
        githubrepobranch)
    git_helper = GitHelper.from_githubrepobranch(
        githubrepobranch=githubrepobranch,
        repo_path=repo_dir,
    )

    release_commits_step = ReleaseCommitsStep(
        git_helper=git_helper,
        repo_dir=repo_dir,
        release_version=release_version,
        repository_version_file_path=repository_version_file_path,
        repository_branch=githubrepobranch.branch(),
        version_operation=version_operation,
        prerelease_suffix=prerelease_suffix,
        release_commit_callback=release_commit_callback,
        next_version_callback=next_version_callback,
        rebase_before_release=rebase_before_release,
    )

    github_release_step = GitHubReleaseStep(
        github_helper=github_helper,
        githubrepobranch=githubrepobranch,
        repo_dir=repo_dir,
        release_version=release_version,
        component_descriptor_file_path=component_descriptor_file_path,
    )

    release_transaction = Transaction(
        release_commits_step,
        github_release_step,
    )

    release_transaction.validate()
    if not release_transaction.execute():
        raise RuntimeError('An error occurred while creating the Release.')

    publish_release_notes_step = PublishReleaseNotesStep(
        githubrepobranch=githubrepobranch,
        github_helper=github_helper,
        release_version=release_version,
        repo_dir=repo_dir,
    )

    cleanup_draft_releases_step = CleanupDraftReleaseStep(
        github_helper=github_helper,
        release_version=release_version,
    )

    if release_notes_policy == ReleaseNotesPolicy.DISABLED:
        return info('release notes were disabled - skipping')
    elif release_notes_policy == ReleaseNotesPolicy.DEFAULT:
        pass
    else:
        raise NotImplementedError(release_notes_policy)

    release_notes_steps = [
        publish_release_notes_step,
        cleanup_draft_releases_step,
    ]

    release_notes_transaction = Transaction(*release_notes_steps)
    release_notes_transaction.validate()
    if not release_notes_transaction.execute():
        raise RuntimeError(
            'An error occurred while publishing the release notes.')

    if slack_cfg_name and slack_channel:
        context = release_notes_transaction.context()
        release_notes = context.step_output(
            publish_release_notes_step.name()).get('release notes')

        post_to_slack_step = PostSlackReleaseStep(
            slack_cfg_name=slack_cfg_name,
            slack_channel=slack_channel,
            release_version=release_version,
            release_notes=release_notes,
            githubrepobranch=githubrepobranch,
        )
        slack_transaction = Transaction(post_to_slack_step)
        slack_transaction.validate()
        if not slack_transaction.execute():
            raise RuntimeError(
                'An error occurred while posting the release notes to Slack.')
Ejemplo n.º 6
0
def release_and_prepare_next_dev_cycle(
    component_name: str,
    githubrepobranch: GitHubRepoBranch,
    release_commit_publishing_policy: str,
    release_notes_policy: str,
    release_version: str,
    repo_hostname: str,
    repo_path: str,
    repo_dir: str,
    repository_version_file_path: str,
    git_tags: list,
    github_release_tag: dict,
    release_commit_callback_image_reference: str,
    component_descriptor_v2_path: str = None,
    ctf_path: str = None,
    next_cycle_commit_message_prefix: str = None,
    next_version_callback: str = None,
    prerelease_suffix: str = "dev",
    rebase_before_release: bool = False,
    release_on_github: bool = True,
    release_commit_callback: str = None,
    release_commit_message_prefix: str = None,
    slack_channel_configs: list = [],
    version_operation: str = "bump_minor",
):
    transaction_ctx = TransactionContext()  # shared between all steps/trxs

    release_notes_policy = ReleaseNotesPolicy(release_notes_policy)
    release_commit_publishing_policy = ReleaseCommitPublishingPolicy(
        release_commit_publishing_policy)
    github_helper = GitHubRepositoryHelper.from_githubrepobranch(
        githubrepobranch)
    git_helper = GitHelper.from_githubrepobranch(
        githubrepobranch=githubrepobranch,
        repo_path=repo_dir,
    )

    step_list = []

    if rebase_before_release:
        rebase_step = RebaseStep(
            git_helper=git_helper,
            repository_branch=githubrepobranch.branch(),
        )
        step_list.append(rebase_step)

    release_commit_step = ReleaseCommitStep(
        git_helper=git_helper,
        repo_dir=repo_dir,
        release_version=release_version,
        repository_version_file_path=repository_version_file_path,
        repository_branch=githubrepobranch.branch(),
        release_commit_message_prefix=release_commit_message_prefix,
        release_commit_callback=release_commit_callback,
        release_commit_callback_image_reference=
        release_commit_callback_image_reference,
        publishing_policy=release_commit_publishing_policy,
    )
    step_list.append(release_commit_step)

    create_tag_step = CreateTagsStep(
        git_tags=git_tags,
        github_release_tag=github_release_tag,
        git_helper=git_helper,
        github_helper=github_helper,
        release_version=release_version,
        publishing_policy=release_commit_publishing_policy,
    )
    step_list.append(create_tag_step)

    if version_operation != version.NOOP:
        next_cycle_commit_step = NextDevCycleCommitStep(
            git_helper=git_helper,
            repo_dir=repo_dir,
            release_version=release_version,
            repository_version_file_path=repository_version_file_path,
            repository_branch=githubrepobranch.branch(),
            version_operation=version_operation,
            prerelease_suffix=prerelease_suffix,
            next_version_callback=next_version_callback,
            publishing_policy=release_commit_publishing_policy,
            next_cycle_commit_message_prefix=next_cycle_commit_message_prefix,
        )
        step_list.append(next_cycle_commit_step)

    if release_on_github:
        github_release_step = GitHubReleaseStep(
            github_helper=github_helper,
            githubrepobranch=githubrepobranch,
            repo_dir=repo_dir,
            component_name=component_name,
            release_version=release_version,
        )
        step_list.append(github_release_step)

    upload_component_descriptor_step = UploadComponentDescriptorStep(
        github_helper=github_helper,
        component_descriptor_v2_path=component_descriptor_v2_path,
        ctf_path=ctf_path,
        release_on_github=release_on_github,
    )
    step_list.append(upload_component_descriptor_step)

    release_transaction = Transaction(
        ctx=transaction_ctx,
        steps=step_list,
    )

    release_transaction.validate()
    if not release_transaction.execute():
        raise RuntimeError('An error occurred while creating the Release.')

    if release_on_github:
        publish_release_notes_step = PublishReleaseNotesStep(
            githubrepobranch=githubrepobranch,
            github_helper=github_helper,
            repository_hostname=repo_hostname,
            repository_path=repo_path,
            release_version=release_version,
            component_descriptor_v2_path=component_descriptor_v2_path,
            ctf_path=ctf_path,
            repo_dir=repo_dir,
        )

    cleanup_draft_releases_step = TryCleanupDraftReleasesStep(
        github_helper=github_helper, )

    cleanup_draft_releases_transaction = Transaction(
        ctx=transaction_ctx,
        steps=(cleanup_draft_releases_step, ),
    )

    if not cleanup_draft_releases_transaction.execute():
        logger.warning('An error occured while cleaning up draft releases')

    if release_notes_policy == ReleaseNotesPolicy.DISABLED:
        return logger.info('release notes were disabled - skipping')
    elif release_notes_policy == ReleaseNotesPolicy.DEFAULT:
        pass
    else:
        raise NotImplementedError(release_notes_policy)

    if release_on_github:
        release_notes_transaction = Transaction(
            ctx=transaction_ctx,
            steps=(publish_release_notes_step, ),
        )
        release_notes_transaction.validate()
        if not release_notes_transaction.execute():
            raise RuntimeError(
                'An error occurred while publishing the release notes.')

    if slack_channel_configs:
        if not release_on_github:
            raise RuntimeError('Cannot post to slack without a github release')
        release_notes = transaction_ctx.step_output(
            publish_release_notes_step.name()).get('release notes')
        all_slack_releases_successful = True
        for slack_cfg in slack_channel_configs:
            slack_cfg_name = slack_cfg['slack_cfg_name']
            slack_channel = slack_cfg['channel_name']
            post_to_slack_step = PostSlackReleaseStep(
                slack_cfg_name=slack_cfg_name,
                slack_channel=slack_channel,
                release_version=release_version,
                release_notes=release_notes,
                githubrepobranch=githubrepobranch,
            )
            slack_transaction = Transaction(
                ctx=transaction_ctx,
                steps=(post_to_slack_step, ),
            )
            slack_transaction.validate()
            all_slack_releases_successful = (all_slack_releases_successful
                                             and slack_transaction.execute())
        if not all_slack_releases_successful:
            raise RuntimeError(
                'An error occurred while posting the release notes to Slack.')