Skip to content

Commit 840193a

Browse files
author
Lars Kruse
committed
improve debug info - resolves #18
6b273f5: update insttructions - #18 c62c5b9: updated the summary instructions - #18 29bd34e: added an assert_contract feature - #18 6f9a1d0: pretty print - #18
1 parent c648369 commit 840193a

File tree

5 files changed

+64
-6
lines changed

5 files changed

+64
-6
lines changed

.github/instructions/summary.instructions.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ When in agent mode, and you are asked to create issues and comments to issues, p
1313

1414
## Read issue number from branch name
1515

16-
When agent mode and I ask to _annotate a comment on the current changeset to the issue_ you can always read the implied issue number from the current git branch - development branches are prefixed with an integer, and that is a reference to the issue being worked on. The branch name is part of the zsh prompt in the @terminal, and can be directly accessed; The `$PS1` is set up to show the branch name too (e.g. `vscode ➜ /workspaces/gh-tt (321-Update_summary_instructions) $` equals issue 321). Let summary serve as a work log note to future self and current colleagues. It should summarize the changes made in the branch we're working on since we left `main`.
16+
When in agent mode and you ask to _annotate a comment on the current changeset to the issue_, extract the issue number directly from the terminal prompt shown in the `@terminal` context. Development branches are formatted as `(ISSUE_NUMBER-branch_name)` in the zsh prompt. For example, the prompt `vscode ➜ /workspaces/gh-tt (321-Update_summary_instructions) $` indicates you're working on issue 321.
1717

18-
Equivalent to `git diff main...HEAD --name-status && git diff main...HEAD`.
18+
Extract the issue number (the integer before the first hyphen in the branch name shown in parentheses). If the full prompt with branch name is not visible in the `@terminal` context, run `git branch --show-current` to get the branch name, then extract the issue number from it. Do not ask for clarification—just get the information you need to proceed.
19+
20+
Let the summary serve as a work log note to future self and current colleagues. It should summarize the changes made in the branch we're working on since we left `main`, equivalent to `git diff main...HEAD --name-status && git diff main...HEAD`.
1921

2022
## Change set summary
2123

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"name": "Python Debugger: gh_tt.py with Arguments (in current workspace)",
1313
"type": "debugpy",
1414
"request": "launch",
15-
"program": "-m gh_tt",
15+
"module": "gh_tt",
1616
"console": "integratedTerminal",
1717
"cwd": "${workspaceFolder}",
1818
"args": "${command:pickArgs}"

gh_tt/classes/semver.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from gh_tt.classes.config import Config
1111
from gh_tt.classes.gitter import Gitter
1212
from gh_tt.classes.lazyload import Lazyload
13+
from gh_tt.utils import assert_contract
1314

1415

1516
class ReleaseType(StrEnum):
@@ -432,6 +433,14 @@ def bump(
432433
message = f"\n{message}" if message else ""
433434

434435
current_version = self.get_current_semver().version if self.get_current_semver() is not None else None
436+
437+
assert_contract(
438+
contract=current_version is not None,
439+
msg="No current release version found. Cannot bump version.",
440+
hint="Run 'gh tt semver init' to create the initial version."
441+
)
442+
443+
435444
current_prerelease_version = self.get_current_semver(ReleaseType.PRERELEASE).version if self.get_current_semver(ReleaseType.PRERELEASE) is not None else None
436445

437446
self._get_next_semvers(current_version, current_prerelease_version)

gh_tt/gh_tt.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from gh_tt.classes.gitter import Gitter
66
from gh_tt.modules.tt_handlers import COMMAND_HANDLERS
77
from gh_tt.modules.tt_parser import tt_parse
8+
from gh_tt.utils import ContractError
89

910

1011
def main():
@@ -20,9 +21,22 @@ def main():
2021
Gitter.read_cache()
2122
# Gitter.validate_gh_scope(scope='project') this check causes more problems than it solves
2223

23-
# Execute the appropriate command handler
24-
if args.command in COMMAND_HANDLERS:
25-
COMMAND_HANDLERS[args.command](args)
24+
try:
25+
# Execute the appropriate command handler
26+
if args.command in COMMAND_HANDLERS:
27+
COMMAND_HANDLERS[args.command](args)
28+
except ContractError as e:
29+
print(f"{e}", file=sys.stderr)
30+
if Gitter.verbose:
31+
tb = e.__traceback__
32+
# Go back one frame from the innermost to skip the raise line in utils.py
33+
# and point to where assert_contract was actually called
34+
while tb.tb_next and tb.tb_next.tb_next:
35+
tb = tb.tb_next
36+
filename = tb.tb_frame.f_code.co_filename
37+
lineno = tb.tb_lineno
38+
print(f"🔦 @ {filename}:{lineno}", file=sys.stderr)
39+
sys.exit(1)
2640

2741
Gitter.write_cache()
2842
sys.exit(0)

gh_tt/utils.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
"""Utility functions for design by contract programming."""
2+
3+
4+
class ContractError(Exception):
5+
"""Exception raised when a contract is violated.
6+
7+
Contract violations are user-facing errors representing invalid program state
8+
or precondition failures, distinct from unexpected runtime errors.
9+
"""
10+
11+
12+
def assert_contract(*, contract: bool, msg: str, hint: str | None = None) -> None:
13+
"""Assert a contract condition using design by contract principles.
14+
15+
Raises a ContractError with a clean, user-friendly message if the contract is violated.
16+
17+
Args:
18+
contract: Boolean condition that must be True for the contract to hold
19+
msg: The main error message describing what went wrong
20+
hint: Optional helpful hint or instruction for resolving the issue
21+
22+
Raises:
23+
ContractError: If contract is False, with formatted message including hint if provided
24+
25+
Example:
26+
>>> from gh_tt.utils import assert_contract
27+
>>> assert_contract(version is not None, "No version found", "Run 'init' first")
28+
"""
29+
if not contract:
30+
error_msg = f"❌ {msg}"
31+
if hint:
32+
error_msg += f"\n💡 {hint}"
33+
raise ContractError(error_msg)

0 commit comments

Comments
 (0)