bbdc-cli 0.4.0__tar.gz → 0.4.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bbdc-cli
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Typer CLI for Bitbucket Data Center
5
5
  Project-URL: Repository, https://github.com/marcosgalleterobbva/bb-cli
6
6
  Keywords: bitbucket,cli,typer,data-center,server
@@ -60,7 +60,11 @@ pipx uninstall bbdc-cli
60
60
  The CLI uses two environment variables:
61
61
 
62
62
  - `BITBUCKET_SERVER`: base REST URL ending in `/rest`
63
- - `BITBUCKET_API_TOKEN`: Bitbucket personal access token (PAT)
63
+ - `BITBUCKET_API_TOKEN`: Bitbucket token (PAT or HTTP access token)
64
+
65
+ BBVA note:
66
+ - Most users will authenticate with Project/Repository HTTP access tokens.
67
+ - Those tokens usually work for repository/project workflows, but some user-account endpoints can return `401`.
64
68
 
65
69
  Example (BBVA-style context path):
66
70
 
@@ -105,6 +109,10 @@ Get information about your authenticated account:
105
109
  # consolidated snapshot (recent repos + SSH keys + GPG keys)
106
110
  bbdc account me
107
111
 
112
+ # if some account endpoints are not permitted with your token,
113
+ # account me returns partial JSON with "partial" + "errors"
114
+ bbdc account me --json
115
+
108
116
  # include user profile and settings when your slug is known
109
117
  bbdc account me --user-slug your.user --include-settings
110
118
 
@@ -228,6 +236,19 @@ Recommended split of responsibilities:
228
236
 
229
237
  This separation is the correct approach and avoids coupling Codex behavior to package release timing.
230
238
 
239
+ ### Codex runtime execution caveat
240
+
241
+ For this BBVA infrastructure, assume Codex runtimes cannot execute `bbdc` against Bitbucket (DNS/VPN/network
242
+ constraints), even though the same command works on the user's machine.
243
+
244
+ Typical error:
245
+ - `Request failed: HTTPSConnectionPool(... NameResolutionError ... Failed to resolve ...)`
246
+
247
+ Recommended workflow in Codex:
248
+ 1. Codex generates exact `bbdc` commands.
249
+ 2. User runs commands locally in their terminal.
250
+ 3. User shares output back to Codex for analysis or next steps.
251
+
231
252
  ## Troubleshooting
232
253
 
233
254
  `BITBUCKET_SERVER` must end with `/rest`.
@@ -242,6 +263,9 @@ Unauthorized / 401 / 403:
242
263
  - Token missing or incorrect
243
264
  - Token lacks required permissions for that project/repo
244
265
  - Your Bitbucket instance may require a different auth scheme (rare if PAT is enabled)
266
+ - In BBVA, Project/Repository HTTP access tokens may return `401` on user-account endpoints
267
+ (`account ssh-keys`, `account gpg-keys`, `account user`, `account settings`)
268
+ - `account me` now returns partial results when some account endpoints are unauthorized; inspect `errors` in output
245
269
 
246
270
  404 Not Found:
247
271
 
@@ -41,7 +41,11 @@ pipx uninstall bbdc-cli
41
41
  The CLI uses two environment variables:
42
42
 
43
43
  - `BITBUCKET_SERVER`: base REST URL ending in `/rest`
44
- - `BITBUCKET_API_TOKEN`: Bitbucket personal access token (PAT)
44
+ - `BITBUCKET_API_TOKEN`: Bitbucket token (PAT or HTTP access token)
45
+
46
+ BBVA note:
47
+ - Most users will authenticate with Project/Repository HTTP access tokens.
48
+ - Those tokens usually work for repository/project workflows, but some user-account endpoints can return `401`.
45
49
 
46
50
  Example (BBVA-style context path):
47
51
 
@@ -86,6 +90,10 @@ Get information about your authenticated account:
86
90
  # consolidated snapshot (recent repos + SSH keys + GPG keys)
87
91
  bbdc account me
88
92
 
93
+ # if some account endpoints are not permitted with your token,
94
+ # account me returns partial JSON with "partial" + "errors"
95
+ bbdc account me --json
96
+
89
97
  # include user profile and settings when your slug is known
90
98
  bbdc account me --user-slug your.user --include-settings
91
99
 
@@ -209,6 +217,19 @@ Recommended split of responsibilities:
209
217
 
210
218
  This separation is the correct approach and avoids coupling Codex behavior to package release timing.
211
219
 
220
+ ### Codex runtime execution caveat
221
+
222
+ For this BBVA infrastructure, assume Codex runtimes cannot execute `bbdc` against Bitbucket (DNS/VPN/network
223
+ constraints), even though the same command works on the user's machine.
224
+
225
+ Typical error:
226
+ - `Request failed: HTTPSConnectionPool(... NameResolutionError ... Failed to resolve ...)`
227
+
228
+ Recommended workflow in Codex:
229
+ 1. Codex generates exact `bbdc` commands.
230
+ 2. User runs commands locally in their terminal.
231
+ 3. User shares output back to Codex for analysis or next steps.
232
+
212
233
  ## Troubleshooting
213
234
 
214
235
  `BITBUCKET_SERVER` must end with `/rest`.
@@ -223,6 +244,9 @@ Unauthorized / 401 / 403:
223
244
  - Token missing or incorrect
224
245
  - Token lacks required permissions for that project/repo
225
246
  - Your Bitbucket instance may require a different auth scheme (rare if PAT is enabled)
247
+ - In BBVA, Project/Repository HTTP access tokens may return `401` on user-account endpoints
248
+ (`account ssh-keys`, `account gpg-keys`, `account user`, `account settings`)
249
+ - `account me` now returns partial results when some account endpoints are unauthorized; inspect `errors` in output
226
250
 
227
251
  404 Not Found:
228
252
 
@@ -420,6 +420,21 @@ def _resolve_user_slug(user_slug: Optional[str]) -> str:
420
420
  )
421
421
 
422
422
 
423
+ def _account_http_token_hint() -> str:
424
+ return (
425
+ "BBVA token note: Project/Repository HTTP access tokens may not have permission for "
426
+ "user-account endpoints (ssh keys, gpg keys, user profile/settings). "
427
+ "This is different from repository/project PR operations."
428
+ )
429
+
430
+
431
+ def _format_account_error(error: BBError) -> str:
432
+ message = str(error)
433
+ if message.startswith("HTTP 401"):
434
+ return f"{message}\nHint: {_account_http_token_hint()}"
435
+ return message
436
+
437
+
423
438
  ROLE_CHOICES = {"AUTHOR", "REVIEWER", "PARTICIPANT"}
424
439
  STATUS_CHOICES = {"UNAPPROVED", "NEEDS_WORK", "APPROVED"}
425
440
  COMMENT_STATE_CHOICES = {"OPEN", "RESOLVED"}
@@ -1283,19 +1298,52 @@ def _op_account_me(
1283
1298
  limit: int,
1284
1299
  max_items: int,
1285
1300
  ) -> Dict[str, Any]:
1286
- recent_repos = _op_account_recent_repos(bb, limit=limit, max_items=max_items)["data"]
1287
- ssh_keys = _op_account_ssh_keys(bb, user=None, limit=limit, max_items=max_items)["data"]
1288
- gpg_keys = _op_account_gpg_keys(bb, user=None, limit=limit, max_items=max_items)["data"]
1301
+ errors: Dict[str, str] = {}
1302
+
1303
+ def collect_list(
1304
+ key: str,
1305
+ getter,
1306
+ ) -> List[Dict[str, Any]]:
1307
+ try:
1308
+ return getter()["data"]
1309
+ except BBError as e:
1310
+ errors[key] = _format_account_error(e)
1311
+ return []
1312
+
1313
+ recent_repos = collect_list(
1314
+ "recent_repositories",
1315
+ lambda: _op_account_recent_repos(bb, limit=limit, max_items=max_items),
1316
+ )
1317
+ ssh_keys = collect_list(
1318
+ "ssh_keys",
1319
+ lambda: _op_account_ssh_keys(bb, user=None, limit=limit, max_items=max_items),
1320
+ )
1321
+ gpg_keys = collect_list(
1322
+ "gpg_keys",
1323
+ lambda: _op_account_gpg_keys(bb, user=None, limit=limit, max_items=max_items),
1324
+ )
1289
1325
 
1290
1326
  resolved_user_slug: Optional[str] = None
1291
1327
  user_profile: Optional[Dict[str, Any]] = None
1292
1328
  user_settings: Optional[Dict[str, Any]] = None
1293
1329
  if include_profile or include_settings:
1294
- resolved_user_slug = _resolve_user_slug(user_slug)
1295
- if include_profile:
1296
- user_profile = _op_account_user(bb, resolved_user_slug)["data"]
1297
- if include_settings:
1298
- user_settings = _op_account_user_settings(bb, resolved_user_slug)["data"]
1330
+ try:
1331
+ resolved_user_slug = _resolve_user_slug(user_slug)
1332
+ except BBError as e:
1333
+ errors["resolved_user_slug"] = _format_account_error(e)
1334
+ resolved_user_slug = None
1335
+
1336
+ if resolved_user_slug:
1337
+ if include_profile:
1338
+ try:
1339
+ user_profile = _op_account_user(bb, resolved_user_slug)["data"]
1340
+ except BBError as e:
1341
+ errors["user"] = _format_account_error(e)
1342
+ if include_settings:
1343
+ try:
1344
+ user_settings = _op_account_user_settings(bb, resolved_user_slug)["data"]
1345
+ except BBError as e:
1346
+ errors["settings"] = _format_account_error(e)
1299
1347
 
1300
1348
  payload: Dict[str, Any] = {
1301
1349
  "counts": {
@@ -1313,6 +1361,17 @@ def _op_account_me(
1313
1361
  payload["user"] = user_profile
1314
1362
  if user_settings is not None:
1315
1363
  payload["settings"] = user_settings
1364
+ if errors:
1365
+ payload["partial"] = True
1366
+ payload["errors"] = errors
1367
+ payload["notes"] = [
1368
+ "Some account endpoints were not accessible with the current token.",
1369
+ _account_http_token_hint(),
1370
+ ]
1371
+ return {
1372
+ "message": f"Fetched partial authenticated account information ({len(errors)} section(s) failed)",
1373
+ "data": payload,
1374
+ }
1316
1375
 
1317
1376
  return {"message": "Fetched authenticated account information", "data": payload}
1318
1377
 
@@ -1596,7 +1655,10 @@ def account_recent_repos(
1596
1655
  ):
1597
1656
  """Get recently accessed repositories for the authenticated user."""
1598
1657
  bb = client()
1599
- resp = _op_account_recent_repos(bb, limit=limit, max_items=max_items)
1658
+ try:
1659
+ resp = _op_account_recent_repos(bb, limit=limit, max_items=max_items)
1660
+ except BBError as e:
1661
+ raise BBError(_format_account_error(e))
1600
1662
  if json_out:
1601
1663
  _print_json(resp["data"])
1602
1664
  else:
@@ -1612,7 +1674,10 @@ def account_ssh_keys(
1612
1674
  ):
1613
1675
  """Get SSH keys for the authenticated user (or another user with sufficient permissions)."""
1614
1676
  bb = client()
1615
- resp = _op_account_ssh_keys(bb, user=user, limit=limit, max_items=max_items)
1677
+ try:
1678
+ resp = _op_account_ssh_keys(bb, user=user, limit=limit, max_items=max_items)
1679
+ except BBError as e:
1680
+ raise BBError(_format_account_error(e))
1616
1681
  if json_out:
1617
1682
  _print_json(resp["data"])
1618
1683
  else:
@@ -1628,7 +1693,10 @@ def account_gpg_keys(
1628
1693
  ):
1629
1694
  """Get GPG keys for the authenticated user (or another user with sufficient permissions)."""
1630
1695
  bb = client()
1631
- resp = _op_account_gpg_keys(bb, user=user, limit=limit, max_items=max_items)
1696
+ try:
1697
+ resp = _op_account_gpg_keys(bb, user=user, limit=limit, max_items=max_items)
1698
+ except BBError as e:
1699
+ raise BBError(_format_account_error(e))
1632
1700
  if json_out:
1633
1701
  _print_json(resp["data"])
1634
1702
  else:
@@ -1645,8 +1713,11 @@ def account_user(
1645
1713
  ):
1646
1714
  """Get user details for the authenticated user account (or a supplied user slug)."""
1647
1715
  bb = client()
1648
- slug = _resolve_user_slug(user_slug)
1649
- resp = _op_account_user(bb, slug)
1716
+ try:
1717
+ slug = _resolve_user_slug(user_slug)
1718
+ resp = _op_account_user(bb, slug)
1719
+ except BBError as e:
1720
+ raise BBError(_format_account_error(e))
1650
1721
  _print_json(resp["data"])
1651
1722
 
1652
1723
 
@@ -1660,8 +1731,11 @@ def account_settings(
1660
1731
  ):
1661
1732
  """Get account settings for the authenticated user account (or a supplied user slug)."""
1662
1733
  bb = client()
1663
- slug = _resolve_user_slug(user_slug)
1664
- resp = _op_account_user_settings(bb, slug)
1734
+ try:
1735
+ slug = _resolve_user_slug(user_slug)
1736
+ resp = _op_account_user_settings(bb, slug)
1737
+ except BBError as e:
1738
+ raise BBError(_format_account_error(e))
1665
1739
  _print_json(resp["data"])
1666
1740
 
1667
1741
 
@@ -1684,8 +1758,12 @@ def account_me(
1684
1758
  ),
1685
1759
  limit: int = typer.Option(25, help="Page size for account-related paged endpoints"),
1686
1760
  max_items: int = typer.Option(100, help="Max items per account-related endpoint"),
1761
+ json_out: bool = typer.Option(False, "--json", help="Print raw JSON response"),
1687
1762
  ):
1688
- """Get a consolidated snapshot of the authenticated account (repos, SSH keys, GPG keys)."""
1763
+ """Get a consolidated snapshot of the authenticated account.
1764
+
1765
+ This command returns partial data when some account endpoints are unauthorized for the token in use.
1766
+ """
1689
1767
  bb = client()
1690
1768
  resp = _op_account_me(
1691
1769
  bb,
@@ -1695,7 +1773,10 @@ def account_me(
1695
1773
  limit=limit,
1696
1774
  max_items=max_items,
1697
1775
  )
1698
- _print_json(resp["data"])
1776
+ if json_out:
1777
+ _print_json(resp["data"])
1778
+ else:
1779
+ _print_json(resp["data"])
1699
1780
 
1700
1781
 
1701
1782
  @pr_app.command("list")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bbdc-cli
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Typer CLI for Bitbucket Data Center
5
5
  Project-URL: Repository, https://github.com/marcosgalleterobbva/bb-cli
6
6
  Keywords: bitbucket,cli,typer,data-center,server
@@ -60,7 +60,11 @@ pipx uninstall bbdc-cli
60
60
  The CLI uses two environment variables:
61
61
 
62
62
  - `BITBUCKET_SERVER`: base REST URL ending in `/rest`
63
- - `BITBUCKET_API_TOKEN`: Bitbucket personal access token (PAT)
63
+ - `BITBUCKET_API_TOKEN`: Bitbucket token (PAT or HTTP access token)
64
+
65
+ BBVA note:
66
+ - Most users will authenticate with Project/Repository HTTP access tokens.
67
+ - Those tokens usually work for repository/project workflows, but some user-account endpoints can return `401`.
64
68
 
65
69
  Example (BBVA-style context path):
66
70
 
@@ -105,6 +109,10 @@ Get information about your authenticated account:
105
109
  # consolidated snapshot (recent repos + SSH keys + GPG keys)
106
110
  bbdc account me
107
111
 
112
+ # if some account endpoints are not permitted with your token,
113
+ # account me returns partial JSON with "partial" + "errors"
114
+ bbdc account me --json
115
+
108
116
  # include user profile and settings when your slug is known
109
117
  bbdc account me --user-slug your.user --include-settings
110
118
 
@@ -228,6 +236,19 @@ Recommended split of responsibilities:
228
236
 
229
237
  This separation is the correct approach and avoids coupling Codex behavior to package release timing.
230
238
 
239
+ ### Codex runtime execution caveat
240
+
241
+ For this BBVA infrastructure, assume Codex runtimes cannot execute `bbdc` against Bitbucket (DNS/VPN/network
242
+ constraints), even though the same command works on the user's machine.
243
+
244
+ Typical error:
245
+ - `Request failed: HTTPSConnectionPool(... NameResolutionError ... Failed to resolve ...)`
246
+
247
+ Recommended workflow in Codex:
248
+ 1. Codex generates exact `bbdc` commands.
249
+ 2. User runs commands locally in their terminal.
250
+ 3. User shares output back to Codex for analysis or next steps.
251
+
231
252
  ## Troubleshooting
232
253
 
233
254
  `BITBUCKET_SERVER` must end with `/rest`.
@@ -242,6 +263,9 @@ Unauthorized / 401 / 403:
242
263
  - Token missing or incorrect
243
264
  - Token lacks required permissions for that project/repo
244
265
  - Your Bitbucket instance may require a different auth scheme (rare if PAT is enabled)
266
+ - In BBVA, Project/Repository HTTP access tokens may return `401` on user-account endpoints
267
+ (`account ssh-keys`, `account gpg-keys`, `account user`, `account settings`)
268
+ - `account me` now returns partial results when some account endpoints are unauthorized; inspect `errors` in output
245
269
 
246
270
  404 Not Found:
247
271
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "bbdc-cli"
7
- version = "0.4.0"
7
+ version = "0.4.2"
8
8
  description = "Typer CLI for Bitbucket Data Center"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
File without changes
File without changes