| """A tool to perform release steps.""" |
| |
| import argparse |
| import logging |
| import os |
| import sys |
| |
| from dev.release.add_backports import AddBackports |
| from dev.release.backport_create_releases import BackportCreateReleases |
| from dev.release.backport_prepare import BackportPrepare |
| from dev.release.complete_prepare import CompletePrepare |
| from dev.release.complete_sync_changelog import CompleteSyncChangelog |
| from dev.release.create_rc import CreateRc |
| from dev.release.create_release_branch import CreateReleaseBranch |
| from dev.release.create_release_issue import CreateReleaseIssue |
| from dev.release.determine_next_version import DetermineNextVersion |
| from dev.release.on_pr_merged import OnPrMerged |
| from dev.release.prepare import Prepare |
| from dev.release.process_backports import ProcessBackports |
| from dev.release.process_news import ProcessNews |
| from dev.release.promote import Promote |
| from dev.release.sync_changelog import SyncChangelog |
| from dev.release.utils import format_exception |
| |
| cmds = [ |
| DetermineNextVersion, |
| CreateReleaseIssue, |
| Prepare, |
| CompletePrepare, |
| CompleteSyncChangelog, |
| CreateReleaseBranch, |
| AddBackports, |
| ProcessBackports, |
| ProcessNews, |
| SyncChangelog, |
| OnPrMerged, |
| CreateRc, |
| Promote, |
| BackportPrepare, |
| BackportCreateReleases, |
| ] |
| |
| |
| def create_parser(): |
| """Creates the argument parser with subcommands.""" |
| parser = argparse.ArgumentParser( |
| description="Automate release steps for rules_python." |
| ) |
| |
| subparsers = parser.add_subparsers( |
| dest="command", required=True, help="Subcommands" |
| ) |
| |
| for cmd in cmds: |
| cmd.add_parser(subparsers) |
| |
| return parser |
| |
| |
| class GitHubActionsLogHandler(logging.Handler): |
| """Outputs GitHub Actions workflow command annotations for log records.""" |
| |
| def emit(self, record: logging.LogRecord) -> None: |
| if record.levelno >= logging.ERROR: |
| prefix = "::error::" |
| elif record.levelno >= logging.WARNING: |
| prefix = "::warning::" |
| elif record.levelno >= logging.INFO: |
| prefix = "::notice::" |
| else: |
| return |
| try: |
| msg = record.getMessage() |
| print(f"{prefix}{msg}", file=sys.stdout, flush=True) |
| except Exception: |
| self.handleError(record) |
| |
| |
| def main(): |
| logging.basicConfig( |
| format="%(levelname)s:%(filename)s:%(lineno)d: %(message)s", |
| level=logging.INFO, |
| stream=sys.stderr, |
| ) |
| logging.getLogger().addHandler(GitHubActionsLogHandler()) |
| print(f"sys.argv: {sys.argv}") |
| if "BUILD_WORKSPACE_DIRECTORY" in os.environ: |
| os.chdir(os.environ["BUILD_WORKSPACE_DIRECTORY"]) |
| |
| parser = create_parser() |
| args = parser.parse_args() |
| |
| exit_code = 1 |
| try: |
| # args.command is the run_from_args classmethod of the selected command |
| exit_code = args.command(args) |
| except Exception as e: |
| sys.stdout.flush() |
| print(f"Fatal error: {format_exception(e)}", file=sys.stderr) |
| sys.exit(1) |
| |
| sys.exit(exit_code if exit_code is not None else 0) |
| |
| |
| if __name__ == "__main__": |
| main() |