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()
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)}"))
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')
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.')
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.')
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.')