youtrack-cli 0.3.6__tar.gz → 0.3.7__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.
Files changed (94) hide show
  1. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/PKG-INFO +4 -1
  2. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/README.md +3 -0
  3. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/commands/auth.rst +27 -0
  4. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/pyproject.toml +1 -1
  5. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/uv.lock +1 -1
  6. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/auth.py +14 -3
  7. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/client.py +10 -1
  8. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/main.py +17 -3
  9. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/.claude/settings.local.json +0 -0
  10. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/.github/dependabot.yml +0 -0
  11. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/.github/workflows/ci.yml +0 -0
  12. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/.github/workflows/release.yml +0 -0
  13. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/.gitignore +0 -0
  14. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/.pre-commit-config.yaml +0 -0
  15. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/.readthedocs.yaml +0 -0
  16. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/CLAUDE.md +0 -0
  17. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/PUBLISHING.md +0 -0
  18. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/Makefile +0 -0
  19. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/api/index.rst +0 -0
  20. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/changelog.rst +0 -0
  21. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/command-aliases.rst +0 -0
  22. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/commands/admin.rst +0 -0
  23. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/commands/articles.rst +0 -0
  24. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/commands/boards.rst +0 -0
  25. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/commands/config.rst +0 -0
  26. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/commands/index.rst +0 -0
  27. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/commands/issues.rst +0 -0
  28. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/commands/projects.rst +0 -0
  29. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/commands/reports.rst +0 -0
  30. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/commands/time.rst +0 -0
  31. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/commands/users.rst +0 -0
  32. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/conf.py +0 -0
  33. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/configuration.rst +0 -0
  34. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/development.rst +0 -0
  35. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/index.rst +0 -0
  36. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/installation.rst +0 -0
  37. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/learning-path.rst +0 -0
  38. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/logging.rst +0 -0
  39. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/performance.md +0 -0
  40. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/progress-indicators.md +0 -0
  41. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/quickstart.rst +0 -0
  42. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/requirements.txt +0 -0
  43. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/security.rst +0 -0
  44. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/troubleshooting.rst +0 -0
  45. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/workflows.rst +0 -0
  46. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/docs/youtrack-concepts.rst +0 -0
  47. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/justfile +0 -0
  48. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/package-lock.json +0 -0
  49. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/package.json +0 -0
  50. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/__init__.py +0 -0
  51. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/conftest.py +0 -0
  52. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/test_admin.py +0 -0
  53. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/test_articles.py +0 -0
  54. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/test_auth.py +0 -0
  55. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/test_boards.py +0 -0
  56. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/test_config.py +0 -0
  57. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/test_issues.py +0 -0
  58. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/test_logging.py +0 -0
  59. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/test_main.py +0 -0
  60. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/test_projects.py +0 -0
  61. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/test_reports.py +0 -0
  62. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/test_security.py +0 -0
  63. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/test_time.py +0 -0
  64. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tests/test_users.py +0 -0
  65. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/tox.ini +0 -0
  66. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/__init__.py +0 -0
  67. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/admin.py +0 -0
  68. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/articles.py +0 -0
  69. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/boards.py +0 -0
  70. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/cache.py +0 -0
  71. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/cli_utils/__init__.py +0 -0
  72. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/cli_utils/aliases.py +0 -0
  73. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/commands/__init__.py +0 -0
  74. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/commands/articles.py +0 -0
  75. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/commands/boards.py +0 -0
  76. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/commands/common.py +0 -0
  77. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/commands/issues.py +0 -0
  78. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/commands/projects.py +0 -0
  79. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/commands/time_tracking.py +0 -0
  80. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/commands/users.py +0 -0
  81. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/common.py +0 -0
  82. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/config.py +0 -0
  83. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/exceptions.py +0 -0
  84. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/issues.py +0 -0
  85. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/logging.py +0 -0
  86. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/performance.py +0 -0
  87. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/progress.py +0 -0
  88. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/projects.py +0 -0
  89. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/py.typed +0 -0
  90. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/reports.py +0 -0
  91. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/security.py +0 -0
  92. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/time.py +0 -0
  93. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/users.py +0 -0
  94. {youtrack_cli-0.3.6 → youtrack_cli-0.3.7}/youtrack_cli/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: youtrack-cli
3
- Version: 0.3.6
3
+ Version: 0.3.7
4
4
  Summary: YouTrack CLI - Command line interface for JetBrains YouTrack issue tracking system
5
5
  Project-URL: Homepage, https://github.com/ryan-murphy/yt-cli
6
6
  Project-URL: Documentation, https://yt-cli.readthedocs.io/
@@ -112,6 +112,9 @@ pip install -e . --group dev
112
112
  # Login to your YouTrack instance
113
113
  yt auth login
114
114
 
115
+ # Login with SSL certificate verification disabled (for self-signed certificates)
116
+ yt auth login --no-verify-ssl
117
+
115
118
  # Verify authentication
116
119
  yt auth token --show
117
120
  ```
@@ -72,6 +72,9 @@ pip install -e . --group dev
72
72
  # Login to your YouTrack instance
73
73
  yt auth login
74
74
 
75
+ # Login with SSL certificate verification disabled (for self-signed certificates)
76
+ yt auth login --no-verify-ssl
77
+
75
78
  # Verify authentication
76
79
  yt auth token --show
77
80
  ```
@@ -57,6 +57,9 @@ Authenticate with YouTrack and save credentials for subsequent CLI usage.
57
57
  * - ``--username, -n``
58
58
  - string
59
59
  - Username for reference (optional)
60
+ * - ``--no-verify-ssl``
61
+ - flag
62
+ - Disable SSL certificate verification (use with caution for self-signed certificates)
60
63
 
61
64
  **Examples:**
62
65
 
@@ -74,6 +77,9 @@ Authenticate with YouTrack and save credentials for subsequent CLI usage.
74
77
  # Completely non-interactive (not recommended for security)
75
78
  yt auth login --base-url https://company.youtrack.cloud --token YOUR_API_TOKEN
76
79
 
80
+ # Login with self-signed SSL certificate
81
+ yt auth login --base-url https://internal.youtrack.local --no-verify-ssl
82
+
77
83
  **Security Notes:**
78
84
 
79
85
  * API tokens are prompted securely and hidden during input
@@ -339,6 +345,21 @@ Connection Problems
339
345
  yt auth logout
340
346
  yt auth login --base-url https://correct.youtrack.cloud
341
347
 
348
+ SSL Certificate Issues
349
+ ~~~~~~~~~~~~~~~~~~~~~
350
+
351
+ .. code-block:: bash
352
+
353
+ # For self-signed certificates or internal CAs
354
+ yt auth login --base-url https://internal.youtrack.local --no-verify-ssl
355
+
356
+ # Test connectivity with SSL verification disabled
357
+ curl -k -H "Authorization: Bearer YOUR_TOKEN" \
358
+ "https://internal.youtrack.local/api/admin/projects"
359
+
360
+ # Note: SSL verification setting is saved with credentials
361
+ # All subsequent API calls will use the same SSL verification setting
362
+
342
363
  Error Handling
343
364
  --------------
344
365
 
@@ -364,6 +385,11 @@ Common error scenarios and solutions:
364
385
  * Verify connectivity to YouTrack instance
365
386
  * Check firewall and proxy settings
366
387
 
388
+ **SSL Certificate Errors**
389
+ * For self-signed certificates: ``yt auth login --no-verify-ssl``
390
+ * For corporate CAs: Add CA certificate to system trust store
391
+ * Warning: Only disable SSL verification on trusted networks
392
+
367
393
  **Corrupted Credentials**
368
394
  * Clear stored credentials: ``yt auth logout``
369
395
  * Re-authenticate: ``yt auth login``
@@ -393,6 +419,7 @@ The configuration file contains encrypted authentication data:
393
419
  YOUTRACK_BASE_URL=https://company.youtrack.cloud
394
420
  YOUTRACK_TOKEN=perm:encrypted_token_data
395
421
  YOUTRACK_USERNAME=john.doe
422
+ YOUTRACK_VERIFY_SSL=true
396
423
 
397
424
  Custom Configuration
398
425
  ~~~~~~~~~~~~~~~~~~~
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "youtrack-cli"
3
- version = "0.3.6"
3
+ version = "0.3.7"
4
4
  description = "YouTrack CLI - Command line interface for JetBrains YouTrack issue tracking system"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9, <3.14"
@@ -1751,7 +1751,7 @@ wheels = [
1751
1751
 
1752
1752
  [[package]]
1753
1753
  name = "youtrack-cli"
1754
- version = "0.3.6"
1754
+ version = "0.3.7"
1755
1755
  source = { editable = "." }
1756
1756
  dependencies = [
1757
1757
  { name = "click" },
@@ -58,6 +58,7 @@ class AuthManager:
58
58
  username: Optional[str] = None,
59
59
  token_expiry: Optional[datetime] = None,
60
60
  use_keyring: bool = True,
61
+ verify_ssl: bool = True,
61
62
  ) -> None:
62
63
  """Save authentication credentials to config file or keyring.
63
64
 
@@ -67,6 +68,7 @@ class AuthManager:
67
68
  username: Username (optional)
68
69
  token_expiry: Token expiration date (optional)
69
70
  use_keyring: Whether to use keyring for secure storage
71
+ verify_ssl: Whether SSL verification is enabled
70
72
  """
71
73
  if use_keyring and self.security_config.enable_credential_encryption:
72
74
  # Store in keyring with encryption
@@ -76,6 +78,8 @@ class AuthManager:
76
78
  self.credential_manager.store_credential("youtrack_username", username)
77
79
  if token_expiry:
78
80
  self.credential_manager.store_credential("youtrack_token_expiry", token_expiry.isoformat())
81
+ # Store SSL verification setting
82
+ self.credential_manager.store_credential("youtrack_verify_ssl", str(verify_ssl))
79
83
 
80
84
  self.console.print("[green]✓[/green] Credentials stored securely in keyring")
81
85
  else:
@@ -90,6 +94,8 @@ class AuthManager:
90
94
  f.write(f"YOUTRACK_USERNAME={username}\n")
91
95
  if token_expiry:
92
96
  f.write(f"YOUTRACK_TOKEN_EXPIRY={token_expiry.isoformat()}\n")
97
+ # Save SSL verification setting
98
+ f.write(f"YOUTRACK_VERIFY_SSL={str(verify_ssl).lower()}\n")
93
99
 
94
100
  self.console.print(
95
101
  "[yellow]⚠[/yellow] Credentials stored in plain text file. Consider using keyring for better security."
@@ -181,12 +187,13 @@ class AuthManager:
181
187
  elif expiration_info["status"] == "expiring":
182
188
  self.console.print(f"[yellow]⚠ {expiration_info['message']}[/yellow]")
183
189
 
184
- async def verify_credentials(self, base_url: str, token: str) -> dict[str, str]:
190
+ async def verify_credentials(self, base_url: str, token: str, verify_ssl: bool = True) -> dict[str, str]:
185
191
  """Verify credentials with YouTrack API.
186
192
 
187
193
  Args:
188
194
  base_url: YouTrack instance URL
189
195
  token: API token
196
+ verify_ssl: Whether to verify SSL certificates
190
197
 
191
198
  Returns:
192
199
  Dictionary with verification result
@@ -196,12 +203,16 @@ class AuthManager:
196
203
  """
197
204
  headers = {"Authorization": f"Bearer {token}", "Accept": "application/json"}
198
205
 
199
- async with httpx.AsyncClient() as client:
206
+ # Configure SSL verification
207
+ client_kwargs = {"timeout": 10.0}
208
+ if not verify_ssl:
209
+ client_kwargs["verify"] = False
210
+
211
+ async with httpx.AsyncClient(**client_kwargs) as client:
200
212
  try:
201
213
  response = await client.get(
202
214
  f"{base_url.rstrip('/')}/api/users/me",
203
215
  headers=headers,
204
- timeout=10.0,
205
216
  )
206
217
  response.raise_for_status()
207
218
 
@@ -36,6 +36,7 @@ class HTTPClientManager:
36
36
  max_connections: int = 100,
37
37
  keepalive_expiry: float = 30.0,
38
38
  default_timeout: float = 30.0,
39
+ verify_ssl: bool = True,
39
40
  ):
40
41
  """Initialize the HTTP client manager.
41
42
 
@@ -44,6 +45,7 @@ class HTTPClientManager:
44
45
  max_connections: Maximum number of total connections
45
46
  keepalive_expiry: How long to keep idle connections alive (seconds)
46
47
  default_timeout: Default timeout for requests (seconds)
48
+ verify_ssl: Whether to verify SSL certificates
47
49
  """
48
50
  self._limits = httpx.Limits(
49
51
  max_keepalive_connections=max_keepalive_connections,
@@ -51,6 +53,7 @@ class HTTPClientManager:
51
53
  keepalive_expiry=keepalive_expiry,
52
54
  )
53
55
  self._timeout = httpx.Timeout(default_timeout)
56
+ self._verify_ssl = verify_ssl
54
57
  self._client: Optional[httpx.AsyncClient] = None
55
58
  self._lock = asyncio.Lock()
56
59
 
@@ -63,11 +66,13 @@ class HTTPClientManager:
63
66
  limits=self._limits,
64
67
  timeout=self._timeout,
65
68
  follow_redirects=True,
69
+ verify=self._verify_ssl,
66
70
  )
67
71
  logger.debug(
68
72
  "HTTP client initialized",
69
73
  max_keepalive=self._limits.max_keepalive_connections,
70
74
  max_connections=self._limits.max_connections,
75
+ verify_ssl=self._verify_ssl,
71
76
  )
72
77
  return self._client
73
78
 
@@ -374,7 +379,11 @@ def get_client_manager() -> HTTPClientManager:
374
379
  """Get the global HTTP client manager instance."""
375
380
  global _client_manager
376
381
  if _client_manager is None:
377
- _client_manager = HTTPClientManager()
382
+ # Check for SSL verification setting from environment
383
+ import os
384
+
385
+ verify_ssl = os.getenv("YOUTRACK_VERIFY_SSL", "true").lower() != "false"
386
+ _client_manager = HTTPClientManager(verify_ssl=verify_ssl)
378
387
  # Type checker note: _client_manager is guaranteed to be non-None here
379
388
  return _client_manager # type: ignore[return-value]
380
389
 
@@ -607,21 +607,35 @@ def auth(ctx: click.Context) -> None:
607
607
  )
608
608
  @click.option("--token", "-t", prompt=True, hide_input=True, help="YouTrack API token")
609
609
  @click.option("--username", "-n", help="Username (optional)")
610
+ @click.option(
611
+ "--no-verify-ssl",
612
+ is_flag=True,
613
+ help="Disable SSL certificate verification (use with caution)",
614
+ )
610
615
  @click.pass_context
611
- def login(ctx: click.Context, base_url: str, token: str, username: Optional[str]) -> None:
616
+ def login(
617
+ ctx: click.Context,
618
+ base_url: str,
619
+ token: str,
620
+ username: Optional[str],
621
+ no_verify_ssl: bool,
622
+ ) -> None:
612
623
  """Authenticate with YouTrack."""
613
624
  console = Console()
614
625
  auth_manager = AuthManager(ctx.obj.get("config"))
615
626
 
616
627
  console.print("🔐 Authenticating with YouTrack...", style="blue")
617
628
 
629
+ if no_verify_ssl:
630
+ console.print("⚠️ SSL certificate verification disabled. Use with caution!", style="yellow")
631
+
618
632
  try:
619
633
  # Verify credentials
620
- result = asyncio.run(auth_manager.verify_credentials(base_url, token))
634
+ result = asyncio.run(auth_manager.verify_credentials(base_url, token, verify_ssl=not no_verify_ssl))
621
635
 
622
636
  if result["status"] == "success":
623
637
  # Save credentials
624
- auth_manager.save_credentials(base_url, token, username)
638
+ auth_manager.save_credentials(base_url, token, username, verify_ssl=not no_verify_ssl)
625
639
 
626
640
  console.print("✅ Authentication successful!", style="green")
627
641
  console.print(f"Logged in as: {result['username']}", style="green")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes