-
Notifications
You must be signed in to change notification settings - Fork 12
Finish milestone #178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jennyhickson
wants to merge
20
commits into
MetOffice:main
Choose a base branch
from
jennyhickson:finish_milestone
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+6,296
−2,853
Open
Finish milestone #178
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
beba078
Expand list of repositories for milestones
jennyhickson eaef11d
Extract project class into own file
jennyhickson 5bb7738
Rename directory
jennyhickson 5b0bd95
tidy unneeded structure.
jennyhickson 5210898
typo
jennyhickson e11cfa5
black
jennyhickson 6c8214a
refactor with classmethods
jennyhickson 134dc39
black
jennyhickson 94a9e0f
process filepath better
jennyhickson c756e7a
add milestone script
jennyhickson 0c2ab39
CR suggestions
jennyhickson de0bc74
functional
jennyhickson 8aee595
make data a list
jennyhickson 940973d
tidy milestone getter
jennyhickson cd34f3b
update captured data
jennyhickson 7b43072
Merge branch 'refactor_workload' into finish_milestone
jennyhickson f57c618
add total
jennyhickson f6e3fc5
Merge remote-tracking branch 'upstream/main' into finish_milestone
jennyhickson 85a0fe4
get milestones and repos
jennyhickson 67d21d2
tidy type hinting
jennyhickson File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,204 @@ | ||
| # ----------------------------------------------------------------------------- | ||
| # (C) Crown copyright Met Office. All rights reserved. | ||
| # The file LICENCE, distributed with this code, contains details of the terms | ||
| # under which the code may be used. | ||
| # ----------------------------------------------------------------------------- | ||
|
|
||
| """ | ||
| This script will run the processes needed to close off and finish a milestone | ||
| * Archive all completed PRs against the milestone in the Review Tracker Project | ||
| * Close the milestone in each repository | ||
| * Report on: | ||
| * Closed PRs at a different milestone | ||
| * Remaining open PRs and issues against this milestone | ||
| * Closed PRs against this milestone | ||
| """ | ||
| from collections import defaultdict | ||
| from pathlib import Path | ||
| import argparse | ||
| from review_project import ProjectData | ||
|
|
||
|
|
||
| def print_banner(message: str) -> None: | ||
| print("\n") | ||
| print("=" * len(message)) | ||
| print(message) | ||
| print("=" * len(message)) | ||
|
|
||
|
|
||
| def still_open(open_prs: dict, current_milestone: str) -> int: | ||
| """ | ||
| Report on all open pull requests for the current milestone | ||
| """ | ||
|
|
||
| print_banner(f"Checking for open pull requests for {current_milestone}") | ||
|
|
||
| total = 0 | ||
|
|
||
| for repo in open_prs: | ||
| print(f"{repo} \n{'-'*len(repo)}") | ||
| for pr in open_prs[repo]: | ||
| print(f"{pr.status: <18} #{pr.number: <5} {pr.title}") | ||
|
|
||
| count = len(open_prs[repo]) | ||
| print(f"-> {count} open pull request(s) in {repo} \n") | ||
| total += count | ||
|
|
||
| if total == 0: | ||
| print(f"No open pull requests for {current_milestone} \n") | ||
|
|
||
| return total | ||
|
|
||
|
|
||
| def closed_other(closed_prs: dict, current_milestone: str) -> int: | ||
| """ | ||
| Report on closed pull requests not at the current milestone. | ||
| """ | ||
|
|
||
| print_banner(f"Checking for closed pull requests not for {current_milestone}") | ||
|
|
||
| total = 0 | ||
|
|
||
| for milestone in closed_prs: | ||
| if milestone == current_milestone: | ||
| continue | ||
|
|
||
| for repo in closed_prs[milestone]: | ||
| print(f"{repo} \n{'-' * len(repo)}") | ||
| for pr in closed_prs[milestone][repo]: | ||
| print(f"#{pr.number : <5} {pr.title}") | ||
|
|
||
| count = len(closed_prs[milestone][repo]) | ||
| print( | ||
| f"-> {count} closed pull request(s) in {repo} at milestone {milestone} \n" | ||
| ) | ||
| total += count | ||
|
|
||
| if total == 0: | ||
| print(f"No closed pull requests not for {current_milestone} \n") | ||
|
|
||
| return total | ||
|
|
||
|
|
||
| def check_ready(open_prs: dict, closed_prs: dict, milestone: str) -> None: | ||
| """ | ||
| Check if the milestone is ready to be closed by confirming that: | ||
| * all pull requests for this milestone have been completed | ||
| * all closed pull requests in the project are in this milestone. | ||
|
|
||
| Give the user the choice to continue regardless since there may be valid | ||
| exceptions. | ||
| """ | ||
| total_open = still_open(open_prs[milestone], milestone) | ||
| total_other = closed_other(closed_prs, milestone) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to update the milestone on these PRs to match the closing milestone? I guess you'd logically do it after the |
||
|
|
||
| if total_open or total_other: | ||
| print("=" * 50) | ||
| print( | ||
| f"{total_open} open pull request(s) in {milestone} and " | ||
| f"{total_other} closed pull request(s) not in {milestone}." | ||
| ) | ||
| cont = input("Would you like to continue with closing this milestone? (y/n) ") | ||
|
|
||
| if cont == "n": | ||
| exit(0) | ||
| elif cont != "y": | ||
| print("Unrecognised input, please select y or n") | ||
|
|
||
|
|
||
| def report(closed: dict, milestone: str) -> None: | ||
| """ | ||
| Report on the pull requests completed in this milestone | ||
| """ | ||
|
|
||
| print_banner(f"Pull requests completed for {milestone}") | ||
|
|
||
| total = 0 | ||
| for repo in closed: | ||
| count = len(closed[repo]) | ||
| total += count | ||
| print(f"{repo: <20} {count: >3} pull requests") | ||
|
|
||
| print(f"{total} pull requests completed in {milestone}") | ||
|
|
||
|
|
||
|
|
||
| def parse_args(): | ||
| """ | ||
| Read command line args | ||
| """ | ||
|
|
||
| testfile = Path(__file__).parent / "test" / "test.json" | ||
|
|
||
| parser = argparse.ArgumentParser( | ||
| "Archive milestone contents within the project and close the " | ||
| "milestone within each repository." | ||
| ) | ||
|
|
||
| parser.add_argument("--milestone", help="Milestone to archive and close.") | ||
| parser.add_argument( | ||
| "--test", | ||
| action="store_true", | ||
| help="Use test input files.", | ||
| ) | ||
| parser.add_argument( | ||
| "--capture_project", | ||
| action="store_true", | ||
| help="Capture the current project status into the test file", | ||
| ) | ||
| parser.add_argument( | ||
| "--file", | ||
| default=testfile, | ||
| help="Filepath to test data for either capturing the project status, " | ||
| "or use as input data.", | ||
| ) | ||
| parser.add_argument( | ||
| "--dry", | ||
| action="store_true", | ||
| help="Dry run. Print commands, don't action them. Always true when " | ||
| "running with test data.", | ||
| ) | ||
|
|
||
| args = parser.parse_args() | ||
|
|
||
| args.file = Path(args.file) | ||
| args.file = args.file.expanduser().resolve() | ||
|
|
||
| if args.test: | ||
| args.dry = True | ||
|
|
||
| return args | ||
|
|
||
|
|
||
| def main( | ||
| milestone: str, test: bool, capture_project: bool, file: Path, dry: bool | ||
| ) -> None: | ||
|
|
||
| # Get milestone data | ||
| if test: | ||
| data = ProjectData.from_file(file) | ||
| else: | ||
| data = ProjectData.from_github(capture_project, file) | ||
|
|
||
| open_prs_by_milestones = data.get_by_milestone("open") | ||
| closed_prs_by_milestones = data.get_by_milestone("closed") | ||
|
|
||
| # Process data and report on status | ||
| check_ready(open_prs_by_milestones, closed_prs_by_milestones, milestone) | ||
| report(closed_prs_by_milestones[milestone], milestone) | ||
|
|
||
| # Archive pull requests at the milestone | ||
| print_banner(f"Archiving Milestone {milestone}") | ||
| data.archive_milestone(milestone, dry_run=dry) | ||
|
|
||
| # Close milestones | ||
| # TODO: run this command from here, rather than prompting user. Leaving | ||
| # like this until script feels stable. | ||
| print_banner("Milestone Completed in Simulation Systems Review Tracker project") | ||
| print("Run this command to close the milestone in all repositories:") | ||
| print(f'./sbin/gh_manage_milestones -t "{milestone}" -m close') | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| args = parse_args() | ||
| main(args.milestone, args.test, args.capture_project, args.file, args.dry) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure you're using this in this file?