def from_githubrepobranch( githubrepobranch: GitHubRepoBranch, repo_path: str, ): return GitHelper( repo=repo_path, github_cfg=githubrepobranch.github_config(), github_repo_path=githubrepobranch.github_repo_path(), )
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 _examinee( github_helper=MagicMock(), githubrepobranch=GitHubRepoBranch( github_config='test_config', repo_owner='test_owner', repo_name='test_name', branch='master', ), repo_dir=str(tmp_path), release_version='1.0.0', ): return concourse.steps.release.PublishReleaseNotesStep( github_helper=github_helper, githubrepobranch=githubrepobranch, repo_dir=repo_dir, release_version=release_version, )
def _examinee( slack_cfg_name='test_config', slack_channel='test_channel', githubrepobranch=GitHubRepoBranch( github_config='test_config', repo_owner='test_owner', repo_name='test_name', branch='master', ), release_version='1.0.0', ): return concourse.steps.release.PostSlackReleaseStep( slack_cfg_name=slack_cfg_name, slack_channel=slack_channel, githubrepobranch=githubrepobranch, release_version=release_version, )
def _examinee( githubrepobranch=GitHubRepoBranch( github_config='test_config', repo_owner='test_owner', repo_name='test_name', branch='master', ), repo_dir=str(tmp_path), release_version='1.0.0', tag_helper_return_value=False, ): # Create a github_helper mock that always reports a tag as existing/not existing, # depending on the passed value github_helper_mock = MagicMock(spec=GitHubRepositoryHelper) return concourse.steps.release.GitHubReleaseStep( github_helper=github_helper_mock, githubrepobranch=githubrepobranch, repo_dir=repo_dir, release_version=release_version, component_descriptor_v2_path=component_descriptor_v2, ctf_path=ctf_path, )
def _examinee( github_helper=MagicMock(), githubrepobranch=GitHubRepoBranch( github_config='test_config', repo_owner='test_owner', repo_name='test_name', branch='master', ), repository_hostname="example.com", repository_path="a_name", repo_dir=str(tmp_path), release_version='1.0.0', ): return concourse.steps.release.PublishReleaseNotesStep( github_helper=github_helper, githubrepobranch=githubrepobranch, repository_hostname=repository_hostname, repository_path=repository_path, repo_dir=repo_dir, release_version=release_version, component_descriptor_v2_path=component_descriptor_v2, ctf_path=ctf_path, )
def create_upgrade_pr( component: gci.componentmodel.Component, from_ref: gci.componentmodel.ComponentReference, to_ref: gci.componentmodel.ComponentReference, to_version: str, pull_request_util, upgrade_script_path, upgrade_script_relpath, githubrepobranch: GitHubRepoBranch, repo_dir, github_cfg_name, merge_policy: MergePolicy, merge_method: MergeMethod, after_merge_callback=None, container_image: str = None, ): if container_image: dockerutil.launch_dockerd_if_not_running() ls_repo = pull_request_util.repository from_component_descriptor = cnudie.retrieve.component_descriptor( name=from_ref.componentName, version=from_ref.version, ctx_repo=component.current_repository_ctx(), ) from_component = from_component_descriptor.component # prepare env for upgrade script and after-merge-callback cmd_env = os.environ.copy() # TODO: Handle upgrades for types other than 'component' cmd_env['DEPENDENCY_TYPE'] = product.v2.COMPONENT_TYPE_NAME cmd_env['DEPENDENCY_NAME'] = to_ref.componentName cmd_env['LOCAL_DEPENDENCY_NAME'] = to_ref.name cmd_env['DEPENDENCY_VERSION'] = to_version if container_image: cmd_env['REPO_DIR'] = (repo_dir_in_container := '/mnt/main_repo') else: cmd_env['REPO_DIR'] = repo_dir cmd_env['GITHUB_CFG_NAME'] = github_cfg_name cmd_env['CTX_REPO_URL'] = component.current_repository_ctx().baseUrl if not container_image: # create upgrade diff subprocess.run([str(upgrade_script_path)], check=True, env=cmd_env) else: # run check-script in container oci_registry_cfg = cr.find_config(image_reference=container_image) if oci_registry_cfg: docker_cfg_dir = tempfile.TemporaryDirectory() dockerutil.mk_docker_cfg_dir( cfg={'auths': oci_registry_cfg.as_docker_auths()}, cfg_dir=docker_cfg_dir.name, exist_ok=True, ) else: docker_cfg_dir = None upgrade_script_path_in_container = os.path.join( repo_dir_in_container, upgrade_script_relpath, ) docker_argv = dockerutil.docker_run_argv( image_reference=container_image, argv=(upgrade_script_path_in_container, ), env=cmd_env, mounts={ repo_dir: repo_dir_in_container, }, cfg_dir=docker_cfg_dir.name, ) logger.info(f'will run: ${docker_argv=}') try: subprocess.run( docker_argv, check=True, ) finally: if docker_cfg_dir: docker_cfg_dir.cleanup() from_version = from_ref.version commit_message = f'Upgrade {to_ref.name}\n\nfrom {from_version} to {to_version}' upgrade_branch_name = push_upgrade_commit( ls_repo=ls_repo, commit_message=commit_message, githubrepobranch=githubrepobranch, repo_dir=repo_dir, ) # branch was created. Cleanup if something fails try: release_notes = _import_release_notes( component=from_component, to_version=to_version, pull_request_util=pull_request_util, ) except Exception: logger.warning('failed to retrieve release-notes') traceback.print_exc() release_notes = 'failed to retrieve release-notes' pull_request = ls_repo.create_pull( title=github.util.PullRequestUtil.calculate_pr_title( reference=to_ref, from_version=from_version, to_version=to_version), base=githubrepobranch.branch(), head=upgrade_branch_name, body=release_notes or 'failed to retrieve release-notes', ) if merge_policy is MergePolicy.MANUAL: return if merge_method is MergeMethod.MERGE: pull_request.merge(merge_method='merge') elif merge_method is MergeMethod.REBASE: pull_request.merge(merge_method='rebase') elif merge_method is MergeMethod.SQUASH: pull_request.merge(merge_method='squash') else: raise NotImplementedError(f'{merge_method=}') try: ls_repo.ref(f'heads/{upgrade_branch_name}').delete() except github3.exceptions.NotFoundError: pass if after_merge_callback: subprocess.run([os.path.join(repo_dir, after_merge_callback)], check=True, env=cmd_env)
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 create_upgrade_pr( component: gci.componentmodel.Component, from_ref: gci.componentmodel.ComponentReference, to_ref: gci.componentmodel.ComponentReference, to_version: str, pull_request_util, upgrade_script_path, githubrepobranch: GitHubRepoBranch, repo_dir, github_cfg_name, cfg_factory, merge_policy, after_merge_callback=None, ): ls_repo = pull_request_util.repository from_version = from_ref.version # prepare env for upgrade script and after-merge-callback cmd_env = os.environ.copy() # TODO: Handle upgrades for types other than 'component' cmd_env['DEPENDENCY_TYPE'] = product.v2.COMPONENT_TYPE_NAME cmd_env['DEPENDENCY_NAME'] = to_ref.componentName cmd_env['LOCAL_DEPENDENCY_NAME'] = to_ref.name cmd_env['DEPENDENCY_VERSION'] = to_version cmd_env['REPO_DIR'] = repo_dir cmd_env['GITHUB_CFG_NAME'] = github_cfg_name cmd_env['CTX_REPO_URL'] = component.current_repository_ctx().baseUrl # create upgrade diff subprocess.run( [str(upgrade_script_path)], check=True, env=cmd_env ) commit_message = f'Upgrade {to_ref.name}\n\nfrom {from_version} to {to_version}' upgrade_branch_name = push_upgrade_commit( ls_repo=ls_repo, commit_message=commit_message, githubrepobranch=githubrepobranch, repo_dir=repo_dir, ) github_cfg, repo_owner, repo_name = get_source_repo_config_for_component_reference( component=component, component_reference=from_ref, component_version=from_version, ) release_notes = create_release_notes( from_component_ref=from_ref, ctx_repo_base_url=component.current_repository_ctx().baseUrl, from_github_cfg=github_cfg, from_repo_owner=repo_owner, from_repo_name=repo_name, from_version=from_version, to_version=to_version, ) if not release_notes: release_notes = pull_request_util.retrieve_pr_template_text() pull_request = ls_repo.create_pull( title=github.util.PullRequestUtil.calculate_pr_title( reference=to_ref, from_version=from_version, to_version=to_version ), base=githubrepobranch.branch(), head=upgrade_branch_name, body=release_notes, ) if merge_policy is MergePolicy.MANUAL: return # auto-merge - todo: make configurable (e.g. merge method) pull_request.merge() try: ls_repo.ref(f'heads/{upgrade_branch_name}').delete() except github3.exceptions.NotFoundError: pass if after_merge_callback: subprocess.run( [os.path.join(repo_dir, after_merge_callback)], check=True, env=cmd_env )
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.')
def create_upgrade_pr( from_ref, to_ref, pull_request_util, upgrade_script_path, githubrepobranch: GitHubRepoBranch, repo_dir, github_cfg_name, cfg_factory, merge_policy, after_merge_callback=None, ): ls_repo = pull_request_util.repository # have component create upgradation diff cmd_env = os.environ.copy() cmd_env['DEPENDENCY_TYPE'] = to_ref.type_name() cmd_env['DEPENDENCY_NAME'] = to_ref.name() cmd_env['DEPENDENCY_VERSION'] = to_ref.version() cmd_env['REPO_DIR'] = repo_dir cmd_env['GITHUB_CFG_NAME'] = github_cfg_name # pass type-specific attributes if to_ref.type_name() == 'container_image': cmd_env['DEPENDENCY_IMAGE_REFERENCE'] = to_ref.image_reference() subprocess.run( [str(upgrade_script_path)], check=True, env=cmd_env ) commit_msg = 'Upgrade {cn}\n\nfrom {ov} to {nv}'.format( cn=to_ref.name(), ov=from_ref.version(), nv=to_ref.version(), ) # mv diff into commit and push it helper = gitutil.GitHelper.from_githubrepobranch( githubrepobranch=githubrepobranch, repo_path=repo_dir, ) commit = helper.index_to_commit(message=commit_msg) ci.util.info(f'commit for upgrade-PR: {commit.hexsha}') new_branch_name = ci.util.random_str(prefix='ci-', length=12) repo_branch = githubrepobranch.branch() head_sha = ls_repo.ref(f'heads/{repo_branch}').object.sha ls_repo.create_ref(f'refs/heads/{new_branch_name}', head_sha) def rm_pr_branch(): ls_repo.ref(f'heads/{new_branch_name}').delete() try: helper.push(from_ref=commit.hexsha, to_ref=f'refs/heads/{new_branch_name}') except: ci.util.warning('an error occurred - removing now useless pr-branch') rm_pr_branch() raise helper.repo.git.checkout('.') try: with tempfile.TemporaryDirectory() as temp_dir: from_github_cfg = cfg_factory.github(from_ref.config_name()) from_github_helper = GitHubRepositoryHelper( github_cfg=from_github_cfg, owner=from_ref.github_organisation(), name=from_ref.github_repo(), ) from_git_helper = gitutil.GitHelper.clone_into( target_directory=temp_dir, github_cfg=from_github_cfg, github_repo_path=from_ref.github_repo_path() ) commit_range = '{from_version}..{to_version}'.format( from_version=from_ref.version(), to_version=to_ref.version() ) release_note_blocks = ReleaseNotes.create( github_helper=from_github_helper, git_helper=from_git_helper, commit_range=commit_range ).release_note_blocks() if release_note_blocks: text = '*Release Notes*:\n{blocks}'.format( blocks=release_note_blocks ) else: text = pull_request_util.retrieve_pr_template_text() except: ci.util.warning('an error occurred during release notes processing (ignoring)') text = None import traceback ci.util.warning(traceback.format_exc()) pull_request = ls_repo.create_pull( title=github.util.PullRequestUtil.calculate_pr_title( reference=to_ref, from_version=from_ref.version(), to_version=to_ref.version() ), base=repo_branch, head=new_branch_name, body=text, ) if merge_policy is MergePolicy.MANUAL: return # auto-merge - todo: make configurable (e.g. merge method) pull_request.merge() rm_pr_branch() if after_merge_callback: subprocess.run( [os.path.join(repo_dir, after_merge_callback)], check=True, env=cmd_env )