def can_merge_pull_request(repo: Repository, pull: PullRequest) -> bool: if pull.user.login not in USER_WHITELIST: return False if pull.mergeable_state != "clean": return False if not any(label.name == AUTO_MERGE_LABEL for label in pull.labels): return False if not any(review.state == "APPROVED" for review in pull.get_reviews()): return False return True head_commit = repo.get_commit(pull.head.sha) circle_success = False percy_success = False for status in head_commit.get_statuses(): if status.state == "success": if status.context == "ci/circleci: build": circle_success = True elif status.context == "percy/web": percy_success = True return circle_success and percy_success
def get_parents(repo: Repository, sha: str) -> List[str]: value = redis.get_list(f'github:parents:{repo.full_name}:{sha}') if value is None: # print(f'getting parents for {sha}') commit = repo.get_commit(sha) parents = [p.sha for p in commit.parents] redis.store(f'github:parents:{repo.full_name}:{sha}', list(parents), ex=604800) return parents return value
def ci_passed(commit_sha: str, repo: Repository) -> bool: commit = repo.get_commit(commit_sha) # Forcing this lazy list since there shouldn't be so many check runs check_runs = [] for check in CI_CHECK_NAMES: check_runs += [r for r in commit.get_check_runs(check_name=check)] if not check_runs: logging.info( f"Commit {commit_sha} has no check runs. Marking CI as not passing." ) return False return all(run.conclusion == "success" for run in check_runs)
def create_pr_message(self, skill_git: Git, skill_repo: Repository) -> tuple: """Reads git commits from skill repo to create a list of changes as the PR content""" title = 'Upgrade ' + self.skill.name body = body_template.format( skill_name=self.skill.name, commits='\n'.join( ' - [{}]({})'.format(skill_git.show('-s', sha, format='%s'), skill_repo.get_commit(sha).html_url) for sha in skill_git.rev_list( '--ancestry-path', '{}..{}'.format(self.skill.entry.sha, 'HEAD')).split('\n'))) return title, body
def process_commit(self, repo: Repository, commit_id) -> bool: files = {} files_content = {} scan_result = {} commit_data = repo.get_commit(sha=commit_id) files = commit_data.raw_data.get('files') for file in files: code = (file['patch']) lines = code.split("\n") file_scan = False for line in lines: #if one line was added or changed scan the full file. if line[0] == '+' or line[0] == 'M': file_scan = True break #wfp calculation if file_scan: contents = repo.get_contents(file['filename'], ref=commit_id) if contents: files_content[file['filename']] = contents.decoded_content try: asset_json = repo.get_contents(self.sbom_file).decoded_content except Exception: self.logger.info("No assets") asset_json = {} self.logger.debug(asset_json) scan_result = self.scanner.scan_files(files_content, asset_json) result = {'comment': 'No results', 'validation': True, 'cyclondx': {}} if scan_result: result = self.scanner.format_scan_results(scan_result) # Add a comment to the commit if (not result['validation'] or self.comment_always) and result['comment']: full_comment = result['comment'] if result['cyclondx']: full_comment += "\n Please find the CycloneDX component details to add to your %s to declare the missing components here:\n" % self.sbom_file if asset_json: full_comment += "```\n" + json.dumps( result['cyclondx']['components'], indent=2) + "\n```" else: full_comment += "```\n" + json.dumps(result['cyclondx'], indent=2) + "\n```" self.logger.debug(full_comment) commit_data.create_comment(full_comment) return result['validation'], full_comment