diff options
Diffstat (limited to 'import_issues.py')
-rwxr-xr-x | import_issues.py | 93 |
1 files changed, 86 insertions, 7 deletions
diff --git a/import_issues.py b/import_issues.py index 1c27f80..b7195bf 100755 --- a/import_issues.py +++ b/import_issues.py @@ -50,7 +50,13 @@ # and USERS dicts below, if desired, or these features can be disabled. See the # documentation for these variables. # -# 4. The projects I have tested this on are small, and don't make use of many of +# 4. If your project has confidential issues or comments in it, then you will +# need to decide to exclude them with --skip-confidential, or include them all +# with --include-confidential. If there are confidential items and you don't +# pass either of these options, then an exception will be thrown. If you need +# more fine-grained control over confidential items, edit issues.ndjson by hand. +# +# 5. The projects I have tested this on are small, and don't make use of many of # Gitlab's features. This may bork on more complex projects. @@ -210,6 +216,7 @@ def open_ticket( created_at: str, closed_at: Optional[str], is_closed: bool, + is_confidential: bool, label_names: List[str], milestone_name: Optional[str], gitlab_ticket_url: str, @@ -236,6 +243,9 @@ def open_ticket( if label_names: pheaders.append("Labels: " + ", ".join(sorted(label_names))) + if is_confidential: + pheaders.append("Confidential: true") + lines.append(" \\\n".join(pheaders)) lines.append("") lines.append(body) @@ -307,12 +317,22 @@ def send_comment( created_at: str, last_edited_at: str, is_system: bool, + is_confidential: bool, ): lines = [] + pheaders = [] + + # Pseudo-headers, if any. + if is_confidential: + pheaders.append("Confidential: true") + + if pheaders: + lines.append(" \\\n".join(pheaders)) + lines.append("") + # Authorship note for a regular comment. if is_system: - # (Skipping pseudoheaders array here, only have one.) - lines.append(f"Changed at: {created_at}") + lines.append(f"Changed on {created_at} by {author_name}:") else: lines.append(f"On {created_at}, {author_name} wrote:") @@ -378,6 +398,8 @@ def run( gitlab_project_url: str, skip_missing_issues: bool, create_missing_issues: bool, + include_confidential: bool, + skip_confidential: bool, ): milestone_jsons = [] with open(export_dir_path / 'milestones.ndjson') as milestones_file: @@ -393,15 +415,51 @@ def run( for line in issues_file: issue_jsons.append(json.loads(line)) + if skip_confidential: + issue_jsons = [x for x in issue_jsons if not x.get('confidential')] + for issue_json in issue_jsons: + issue_json['notes'] = [ + n + for n in issue_json['notes'] + if not n.get('confidential') + ] + + elif not include_confidential: + have_confidential_issues = any( + x.get('confidential') + for x in issue_jsons + ) + have_confidential_notes = any( + n.get('confidential') + for x in issue_jsons + for n in x['notes'] + ) + confidential_types = [] + if have_confidential_issues: + confidential_types.append('issues') + if have_confidential_notes: + confidential_types.append('notes') + assert not (have_confidential_issues or have_confidential_notes), \ + f"Found confidential {' and '.join(confidential_types)}; please " \ + f"decide whether these should all be included, then pass either " \ + f"--include-confidential or --skip-confidential, or edit " \ + f"issues.ndjson for more fine-grained control." + issue_jsons.sort(key=lambda x: x['iid']) max_issue_id = max(x['iid'] for x in issue_jsons) present_issue_id_set = {x['iid'] for x in issue_jsons} missing_issue_ids = set(range(1, max_issue_id + 1)) - present_issue_id_set if missing_issue_ids and not (skip_missing_issues or create_missing_issues): + if skip_confidential: + because_confidential_msg = \ + " (possibly because some confidential issues were excluded)" + else: + because_confidential_msg = "" + raise RuntimeError( - f"Don't have all issues from 1 to {max_issue_id}, please pass " - f"--create-missing-issues or --skip-missing-issues to proceed." + f"Don't have all issues from 1 to {max_issue_id}{because_confidential_msg}, " + f"please pass --create-missing-issues or --skip-missing-issues to proceed." ) issues_by_id = {} @@ -463,6 +521,7 @@ def run( created_at=issue_json['created_at'], closed_at=issue_json['closed_at'], is_closed=(issue_json['state'] == 'closed'), + is_confidential=(issue_json.get('confidential') is True), label_names=[x['label']['title'] for x in issue_json['label_links']], milestone_name=issue_json.get('milestone', {}).get('title') or None, gitlab_ticket_url=f"{gitlab_project_url}/-/issues/{gitlab_issue_id}", @@ -519,6 +578,7 @@ def run( created_at=note_json['created_at'], last_edited_at=note_json['last_edited_at'], is_system=note_json['system'], + is_confidential=(note_json['confidential'] is True), ) print("-------- CLOSING CLOSED ISSUES") @@ -619,6 +679,18 @@ def main(): ) parser.add_argument( + '--include-confidential', + action='store_true', + help="Include confidential tickets and notes.", + ) + + parser.add_argument( + '--skip-confidential', + action='store_true', + help="Skip confidential tickets and notes.", + ) + + parser.add_argument( 'export_dir', help='Exported Gitlab tree/project/ directory containing ndjson files.', ) @@ -639,6 +711,11 @@ def main(): assert not (skip_missing_issues and create_missing_issues), \ f"Can accept at most one of --skip-missing-issues and --create-missing-issues." + include_confidential = args['include_confidential'] + skip_confidential = args['skip_confidential'] + assert not (include_confidential and skip_confidential), \ + f"Can accept at most one of --include-confidential and --skip-confidential." + if mode == 'print': smtp = None elif mode == 'send': @@ -672,8 +749,10 @@ def main(): frm=frm, export_dir_path=export_dir_path, gitlab_project_url=args['gitlab_project_url'].rstrip('/'), - skip_missing_issues=args['skip_missing_issues'], - create_missing_issues=args['create_missing_issues'], + skip_missing_issues=skip_missing_issues, + create_missing_issues=create_missing_issues, + include_confidential=include_confidential, + skip_confidential=skip_confidential, ) if mode == 'send': |