bmsdna-devtools 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/PKG-INFO +1 -1
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/bmsdna/devtools/cli.py +28 -1
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/bmsdna/devtools/gh_pr.py +10 -2
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/bmsdna/devtools/pr_build.py +7 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/pyproject.toml +1 -1
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/uv.lock +1 -1
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/.github/workflows/python-publish.yml +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/.github/workflows/python-test.yml +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/.gitignore +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/.python-version +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/README.md +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/bmsdna/devtools/__init__.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/bmsdna/devtools/ado_auth.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/bmsdna/devtools/app_service_logs.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/bmsdna/devtools/cli_tools.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/bmsdna/devtools/commit.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/bmsdna/devtools/env_config.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/bmsdna/devtools/gitrepo.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/bmsdna/devtools/logs.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/bmsdna/devtools/pr_markdown.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/bmsdna/devtools/worktree.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/justfile +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/skills/bmsdna-devtools/SKILL.md +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/tests/test_app_service_logs.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/tests/test_commit.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/tests/test_env_config.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/tests/test_gh_pr.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/tests/test_gitrepo.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/tests/test_pr_build.py +0 -0
- {bmsdna_devtools-0.3.0 → bmsdna_devtools-0.4.0}/tests/test_pr_markdown.py +0 -0
|
@@ -57,6 +57,7 @@ def _attach_screenshots(attach: Callable[[], None]) -> None:
|
|
|
57
57
|
@pr_app.command("create")
|
|
58
58
|
def pr_create(
|
|
59
59
|
target: str = typer.Option("main", "--target", help="Target branch (e.g. main, test)"),
|
|
60
|
+
draft: bool = typer.Option(False, "--draft", help="Create the PR as a draft (not ready for review)"),
|
|
60
61
|
screenshot: list[str] = typer.Option(
|
|
61
62
|
[], "--screenshot", help="Path to an image to attach to the PR description (repeatable)"
|
|
62
63
|
),
|
|
@@ -77,10 +78,11 @@ def pr_create(
|
|
|
77
78
|
source_branch = current_branch()
|
|
78
79
|
if isinstance(remote, GitHubRemote):
|
|
79
80
|
gh = require_gh()
|
|
80
|
-
returncode = gh_pr.create(gh, target, args or [])
|
|
81
|
+
returncode = gh_pr.create(gh, target, args or [], draft=draft)
|
|
81
82
|
build_policy = gh_pr.has_build_policy(gh, target)
|
|
82
83
|
if returncode == 0 and screenshot:
|
|
83
84
|
_attach_screenshots(lambda: gh_pr.add_screenshots(gh, remote.owner, remote.repo, source_branch, screenshot))
|
|
85
|
+
publish_hint = "`gh pr ready`"
|
|
84
86
|
else:
|
|
85
87
|
az = require_az()
|
|
86
88
|
cmd = [
|
|
@@ -88,6 +90,7 @@ def pr_create(
|
|
|
88
90
|
"--target-branch", target,
|
|
89
91
|
"--source-branch", source_branch,
|
|
90
92
|
"--auto-complete", "false",
|
|
93
|
+
*(["--draft", "true"] if draft else []),
|
|
91
94
|
*(args or []),
|
|
92
95
|
]
|
|
93
96
|
returncode = subprocess.run(cmd).returncode
|
|
@@ -100,6 +103,10 @@ def pr_create(
|
|
|
100
103
|
pr_build.add_screenshots(session, remote, pr, screenshot)
|
|
101
104
|
|
|
102
105
|
_attach_screenshots(_add)
|
|
106
|
+
publish_hint = "`az repos pr update --id <PR-ID> --draft false`"
|
|
107
|
+
|
|
108
|
+
if returncode == 0 and draft:
|
|
109
|
+
print(f"\nCreated as a draft PR. Run `bdt pr publish` (or {publish_hint}) to mark it ready for review.")
|
|
103
110
|
|
|
104
111
|
if returncode == 0 and build_policy:
|
|
105
112
|
print("\nRun `bdt pr status` to check whether the CI build passes.")
|
|
@@ -107,6 +114,26 @@ def pr_create(
|
|
|
107
114
|
raise typer.Exit(returncode)
|
|
108
115
|
|
|
109
116
|
|
|
117
|
+
@pr_app.command("publish")
|
|
118
|
+
def pr_publish(
|
|
119
|
+
target: str = typer.Option("main", "--target", help="Target branch of the PR (Azure DevOps only)"),
|
|
120
|
+
pat: str | None = typer.Option(
|
|
121
|
+
None,
|
|
122
|
+
"--pat",
|
|
123
|
+
envvar=["AZURE_DEVOPS_EXT_PAT", "AZURE_DEVOPS_PAT"],
|
|
124
|
+
help="Azure DevOps PAT (else falls back to `az` login)",
|
|
125
|
+
),
|
|
126
|
+
) -> None:
|
|
127
|
+
"""Mark the draft PR opened from the current branch as ready for review (Azure DevOps or GitHub, auto-detected)."""
|
|
128
|
+
remote = current_remote()
|
|
129
|
+
source_branch = current_branch()
|
|
130
|
+
if isinstance(remote, GitHubRemote):
|
|
131
|
+
gh_pr.publish(require_gh())
|
|
132
|
+
else:
|
|
133
|
+
session, pr = _resolve_ado_pr(pat, remote, source_branch, target)
|
|
134
|
+
pr_build.publish(session, remote, pr)
|
|
135
|
+
|
|
136
|
+
|
|
110
137
|
@pr_app.command("status")
|
|
111
138
|
def pr_status(
|
|
112
139
|
target_branch: str = typer.Option("main", "--target-branch", help="Target branch of the PR (Azure DevOps only — gh has no equivalent filter, it always resolves the PR for the current branch)"),
|
|
@@ -140,17 +140,25 @@ def run(gh: str, wait: bool) -> None:
|
|
|
140
140
|
return
|
|
141
141
|
|
|
142
142
|
|
|
143
|
-
def create(gh: str, target: str, extra_args: list[str]) -> int:
|
|
143
|
+
def create(gh: str, target: str, extra_args: list[str], draft: bool = False) -> int:
|
|
144
144
|
"""Create a GitHub PR from the current branch into `target`.
|
|
145
145
|
|
|
146
146
|
--fill autofills title/body from commit info so this never blocks on an
|
|
147
147
|
interactive prompt; pass --title/--body in extra_args to override (gh
|
|
148
148
|
lets explicit values take precedence over --fill).
|
|
149
149
|
"""
|
|
150
|
-
cmd = [gh, "pr", "create", "--base", target, "--fill", *extra_args]
|
|
150
|
+
cmd = [gh, "pr", "create", "--base", target, "--fill", *(["--draft"] if draft else []), *extra_args]
|
|
151
151
|
return subprocess.run(cmd).returncode
|
|
152
152
|
|
|
153
153
|
|
|
154
|
+
def publish(gh: str) -> None:
|
|
155
|
+
"""Mark the current branch's draft PR as ready for review."""
|
|
156
|
+
r = subprocess.run([gh, "pr", "ready"], capture_output=True, encoding="utf-8")
|
|
157
|
+
if r.returncode != 0:
|
|
158
|
+
sys.exit((r.stderr or r.stdout).strip() or "`gh pr ready` failed")
|
|
159
|
+
print("Marked PR as ready for review")
|
|
160
|
+
|
|
161
|
+
|
|
154
162
|
def _git(args: list[str], env: dict[str, str] | None = None) -> str:
|
|
155
163
|
r = subprocess.run(["git", *args], capture_output=True, encoding="utf-8", env=env)
|
|
156
164
|
if r.returncode != 0:
|
|
@@ -189,6 +189,13 @@ def update(
|
|
|
189
189
|
print(f"Updated PR #{pr_id}")
|
|
190
190
|
|
|
191
191
|
|
|
192
|
+
def publish(session: requests.Session, remote: AdoRemote, pr: dict) -> None:
|
|
193
|
+
"""Mark a draft PR as ready for review (clears isDraft)."""
|
|
194
|
+
pr_id = pr["pullRequestId"]
|
|
195
|
+
_patch_pr(session, remote, pr_id, {"isDraft": False})
|
|
196
|
+
print(f"Marked PR #{pr_id} as ready for review")
|
|
197
|
+
|
|
198
|
+
|
|
192
199
|
def add_comment(session: requests.Session, remote: AdoRemote, pr_id: int, content: str) -> None:
|
|
193
200
|
"""Post a new top-level comment thread on the PR."""
|
|
194
201
|
r = session.post(
|
|
@@ -10,7 +10,7 @@ packages = ["bmsdna"]
|
|
|
10
10
|
|
|
11
11
|
[project]
|
|
12
12
|
name = "bmsdna-devtools"
|
|
13
|
-
version = "0.
|
|
13
|
+
version = "0.4.0"
|
|
14
14
|
description = "Shared Azure DevOps / GitHub / git / Azure Monitor developer tooling for BMS projects"
|
|
15
15
|
readme = "README.md"
|
|
16
16
|
requires-python = ">=3.11"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|