crackerjack 0.27.1__tar.gz → 0.27.4__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.
Potentially problematic release.
This version of crackerjack might be problematic. Click here for more details.
- {crackerjack-0.27.1/crackerjack → crackerjack-0.27.4}/.gitignore +3 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/PKG-INFO +1 -1
- {crackerjack-0.27.1 → crackerjack-0.27.4/crackerjack}/.gitignore +3 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/crackerjack/crackerjack.py +128 -23
- {crackerjack-0.27.1 → crackerjack-0.27.4}/crackerjack/py313.py +5 -1
- {crackerjack-0.27.1 → crackerjack-0.27.4}/crackerjack/pyproject.toml +1 -1
- {crackerjack-0.27.1 → crackerjack-0.27.4}/pyproject.toml +1 -1
- {crackerjack-0.27.1 → crackerjack-0.27.4}/uv.lock +1 -1
- {crackerjack-0.27.1 → crackerjack-0.27.4}/.envrc +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/.github/FUNDING.yml +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/.libcst.codemod.yaml +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/.pre-commit-config-ai.yaml +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/.pre-commit-config-fast.yaml +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/.pre-commit-config.yaml +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/CLAUDE.md +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/LICENSE +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/README-AI-AGENT.md +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/README.md +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/RULES.md +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/crackerjack/.libcst.codemod.yaml +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/crackerjack/.pdm.toml +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/crackerjack/.pre-commit-config-ai.yaml +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/crackerjack/.pre-commit-config.yaml +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/crackerjack/__init__.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/crackerjack/__main__.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/crackerjack/errors.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/crackerjack/interactive.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/TESTING.md +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/__init__.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/conftest.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/data/comments_sample.txt +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/data/docstrings_sample.txt +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/data/expected_comments_sample.txt +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/data/init.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/test_crackerjack.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/test_crackerjack_runner.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/test_errors.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/test_interactive.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/test_interactive_run.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/test_main.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/test_multiline_functions.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/test_py313_advanced.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/test_py313_features.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/test_pytest_features.py +0 -0
- {crackerjack-0.27.1 → crackerjack-0.27.4}/tests/test_structured_errors.py +0 -0
|
@@ -540,9 +540,15 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
|
540
540
|
|
|
541
541
|
def process_lines():
|
|
542
542
|
lines = code.split("\n")
|
|
543
|
-
function_tracker
|
|
544
|
-
|
|
545
|
-
|
|
543
|
+
function_tracker: dict[str, t.Any] = {
|
|
544
|
+
"in_function": False,
|
|
545
|
+
"function_indent": 0,
|
|
546
|
+
}
|
|
547
|
+
import_tracker: dict[str, t.Any] = {
|
|
548
|
+
"in_imports": False,
|
|
549
|
+
"last_import_type": None,
|
|
550
|
+
}
|
|
551
|
+
previous_lines: list[str] = []
|
|
546
552
|
for i, line in enumerate(lines):
|
|
547
553
|
line = line.rstrip()
|
|
548
554
|
stripped_line = line.lstrip()
|
|
@@ -856,8 +862,8 @@ class CodeCleaner(BaseModel, arbitrary_types_allowed=True):
|
|
|
856
862
|
|
|
857
863
|
try:
|
|
858
864
|
async with aiofiles.open(file_path, encoding="utf-8") as f: # type: ignore[misc]
|
|
859
|
-
code = await f.read() # type: ignore[misc]
|
|
860
|
-
original_code = code
|
|
865
|
+
code: str = await f.read() # type: ignore[misc]
|
|
866
|
+
original_code: str = code
|
|
861
867
|
cleaning_failed = False
|
|
862
868
|
try:
|
|
863
869
|
code = self.remove_line_comments_streaming(code)
|
|
@@ -1115,7 +1121,9 @@ class ConfigManager(BaseModel, arbitrary_types_allowed=True):
|
|
|
1115
1121
|
) -> None:
|
|
1116
1122
|
for setting, value in our_config.items():
|
|
1117
1123
|
if isinstance(value, dict):
|
|
1118
|
-
self._merge_nested_config(
|
|
1124
|
+
self._merge_nested_config(
|
|
1125
|
+
setting, t.cast(dict[str, t.Any], value), pkg_config
|
|
1126
|
+
)
|
|
1119
1127
|
else:
|
|
1120
1128
|
self._merge_direct_config(setting, value, pkg_config)
|
|
1121
1129
|
|
|
@@ -1134,11 +1142,13 @@ class ConfigManager(BaseModel, arbitrary_types_allowed=True):
|
|
|
1134
1142
|
self, key: str, value: t.Any, nested_config: dict[str, t.Any]
|
|
1135
1143
|
) -> None:
|
|
1136
1144
|
if isinstance(value, str | list) and "crackerjack" in str(value):
|
|
1137
|
-
nested_config[key] = self.swap_package_name(value)
|
|
1145
|
+
nested_config[key] = self.swap_package_name(t.cast(str | list[str], value))
|
|
1138
1146
|
elif self._is_mergeable_list(key, value):
|
|
1139
1147
|
existing = nested_config.get(key, [])
|
|
1140
1148
|
if isinstance(existing, list) and isinstance(value, list):
|
|
1141
|
-
nested_config[key] = list(
|
|
1149
|
+
nested_config[key] = list(
|
|
1150
|
+
set(t.cast(list[str], existing) + t.cast(list[str], value))
|
|
1151
|
+
)
|
|
1142
1152
|
else:
|
|
1143
1153
|
nested_config[key] = value
|
|
1144
1154
|
elif key not in nested_config:
|
|
@@ -1148,11 +1158,13 @@ class ConfigManager(BaseModel, arbitrary_types_allowed=True):
|
|
|
1148
1158
|
self, setting: str, value: t.Any, pkg_config: dict[str, t.Any]
|
|
1149
1159
|
) -> None:
|
|
1150
1160
|
if isinstance(value, str | list) and "crackerjack" in str(value):
|
|
1151
|
-
pkg_config[setting] = self.swap_package_name(value)
|
|
1161
|
+
pkg_config[setting] = self.swap_package_name(t.cast(str | list[str], value))
|
|
1152
1162
|
elif self._is_mergeable_list(setting, value):
|
|
1153
1163
|
existing = pkg_config.get(setting, [])
|
|
1154
1164
|
if isinstance(existing, list) and isinstance(value, list):
|
|
1155
|
-
pkg_config[setting] = list(
|
|
1165
|
+
pkg_config[setting] = list(
|
|
1166
|
+
set(t.cast(list[str], existing) + t.cast(list[str], value))
|
|
1167
|
+
)
|
|
1156
1168
|
else:
|
|
1157
1169
|
pkg_config[setting] = value
|
|
1158
1170
|
elif setting not in pkg_config:
|
|
@@ -1611,7 +1623,9 @@ class ProjectManager(BaseModel, arbitrary_types_allowed=True):
|
|
|
1611
1623
|
with open("complexipy.json", encoding="utf-8") as f:
|
|
1612
1624
|
complexity_data = json.load(f)
|
|
1613
1625
|
if isinstance(complexity_data, list):
|
|
1614
|
-
return self._parse_complexity_list(
|
|
1626
|
+
return self._parse_complexity_list(
|
|
1627
|
+
t.cast(list[dict[str, t.Any]], complexity_data)
|
|
1628
|
+
)
|
|
1615
1629
|
return self._parse_complexity_dict(complexity_data)
|
|
1616
1630
|
except (FileNotFoundError, json.JSONDecodeError):
|
|
1617
1631
|
return {"status": "complexity_analysis_not_available"}
|
|
@@ -1768,7 +1782,7 @@ class ProjectManager(BaseModel, arbitrary_types_allowed=True):
|
|
|
1768
1782
|
return {"directories": directories, "total_directories": len(directories)}
|
|
1769
1783
|
|
|
1770
1784
|
def _analyze_file_distribution(self) -> dict[str, t.Any]:
|
|
1771
|
-
file_types = {}
|
|
1785
|
+
file_types: dict[str, int] = {}
|
|
1772
1786
|
total_files = 0
|
|
1773
1787
|
for file_path in self.pkg_path.rglob("*"):
|
|
1774
1788
|
if file_path.is_file() and not str(file_path).startswith(
|
|
@@ -2115,11 +2129,13 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2115
2129
|
project_manager: ProjectManager | None = None
|
|
2116
2130
|
_file_cache: dict[str, list[Path]] = {}
|
|
2117
2131
|
_file_cache_with_mtime: dict[str, tuple[float, list[Path]]] = {}
|
|
2132
|
+
_state_file: Path = Path(".crackerjack-state")
|
|
2118
2133
|
|
|
2119
2134
|
def __init__(self, **data: t.Any) -> None:
|
|
2120
2135
|
super().__init__(**data)
|
|
2121
2136
|
self._file_cache = {}
|
|
2122
2137
|
self._file_cache_with_mtime = {}
|
|
2138
|
+
self._state_file = Path(".crackerjack-state")
|
|
2123
2139
|
self.code_cleaner = CodeCleaner(console=self.console)
|
|
2124
2140
|
self.config_manager = ConfigManager(
|
|
2125
2141
|
our_path=self.our_path,
|
|
@@ -2140,6 +2156,73 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2140
2156
|
dry_run=self.dry_run,
|
|
2141
2157
|
)
|
|
2142
2158
|
|
|
2159
|
+
def _read_state(self) -> dict[str, t.Any]:
|
|
2160
|
+
import json
|
|
2161
|
+
|
|
2162
|
+
if self._state_file.exists():
|
|
2163
|
+
try:
|
|
2164
|
+
return json.loads(self._state_file.read_text(encoding="utf-8"))
|
|
2165
|
+
except (json.JSONDecodeError, OSError):
|
|
2166
|
+
return {}
|
|
2167
|
+
return {}
|
|
2168
|
+
|
|
2169
|
+
def _write_state(self, state: dict[str, t.Any]) -> None:
|
|
2170
|
+
from contextlib import suppress
|
|
2171
|
+
|
|
2172
|
+
with suppress(OSError):
|
|
2173
|
+
import json
|
|
2174
|
+
|
|
2175
|
+
self._state_file.write_text(json.dumps(state, indent=2), encoding="utf-8")
|
|
2176
|
+
|
|
2177
|
+
def _clear_state(self) -> None:
|
|
2178
|
+
if self._state_file.exists():
|
|
2179
|
+
from contextlib import suppress
|
|
2180
|
+
|
|
2181
|
+
with suppress(OSError):
|
|
2182
|
+
self._state_file.unlink()
|
|
2183
|
+
|
|
2184
|
+
def _has_version_been_bumped(self, version_type: str) -> bool:
|
|
2185
|
+
state = self._read_state()
|
|
2186
|
+
current_version = self._get_current_version()
|
|
2187
|
+
last_bumped_version = state.get("last_bumped_version")
|
|
2188
|
+
last_bump_type = state.get("last_bump_type")
|
|
2189
|
+
|
|
2190
|
+
return (
|
|
2191
|
+
last_bumped_version == current_version
|
|
2192
|
+
and last_bump_type == version_type
|
|
2193
|
+
and not state.get("publish_completed", False)
|
|
2194
|
+
)
|
|
2195
|
+
|
|
2196
|
+
def _mark_version_bumped(self, version_type: str) -> None:
|
|
2197
|
+
current_version = self._get_current_version()
|
|
2198
|
+
state = self._read_state()
|
|
2199
|
+
state.update(
|
|
2200
|
+
{
|
|
2201
|
+
"last_bumped_version": current_version,
|
|
2202
|
+
"last_bump_type": version_type,
|
|
2203
|
+
"publish_completed": False,
|
|
2204
|
+
}
|
|
2205
|
+
)
|
|
2206
|
+
self._write_state(state)
|
|
2207
|
+
|
|
2208
|
+
def _mark_publish_completed(self) -> None:
|
|
2209
|
+
state = self._read_state()
|
|
2210
|
+
state["publish_completed"] = True
|
|
2211
|
+
self._write_state(state)
|
|
2212
|
+
|
|
2213
|
+
def _get_current_version(self) -> str:
|
|
2214
|
+
from contextlib import suppress
|
|
2215
|
+
|
|
2216
|
+
with suppress(Exception):
|
|
2217
|
+
import tomllib
|
|
2218
|
+
|
|
2219
|
+
pyproject_path = Path("pyproject.toml")
|
|
2220
|
+
if pyproject_path.exists():
|
|
2221
|
+
with pyproject_path.open("rb") as f:
|
|
2222
|
+
data = tomllib.load(f)
|
|
2223
|
+
return data.get("project", {}).get("version", "unknown")
|
|
2224
|
+
return "unknown"
|
|
2225
|
+
|
|
2143
2226
|
def _setup_package(self) -> None:
|
|
2144
2227
|
self.pkg_name = self.pkg_path.stem.lower().replace("-", "_")
|
|
2145
2228
|
self.pkg_dir = self.pkg_path / self.pkg_name
|
|
@@ -2156,6 +2239,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2156
2239
|
self.project_manager.pkg_dir = self.pkg_dir
|
|
2157
2240
|
|
|
2158
2241
|
def _update_project(self, options: t.Any) -> None:
|
|
2242
|
+
assert self.project_manager is not None
|
|
2159
2243
|
if not options.no_config_updates:
|
|
2160
2244
|
self.project_manager.update_pkg_configs()
|
|
2161
2245
|
result: CompletedProcess[str] = self.execute_command(
|
|
@@ -2178,6 +2262,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2178
2262
|
self.execute_command(update_cmd)
|
|
2179
2263
|
|
|
2180
2264
|
def _clean_project(self, options: t.Any) -> None:
|
|
2265
|
+
assert self.code_cleaner is not None
|
|
2181
2266
|
if options.clean:
|
|
2182
2267
|
if self.pkg_dir:
|
|
2183
2268
|
self.console.print("\n" + "-" * 80)
|
|
@@ -2197,6 +2282,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2197
2282
|
self.code_cleaner.clean_files(tests_dir)
|
|
2198
2283
|
|
|
2199
2284
|
async def _clean_project_async(self, options: t.Any) -> None:
|
|
2285
|
+
assert self.code_cleaner is not None
|
|
2200
2286
|
if options.clean:
|
|
2201
2287
|
if self.pkg_dir:
|
|
2202
2288
|
self.console.print("\n" + "-" * 80)
|
|
@@ -2483,12 +2569,20 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2483
2569
|
def _bump_version(self, options: OptionsProtocol) -> None:
|
|
2484
2570
|
for option in (options.publish, options.bump):
|
|
2485
2571
|
if option:
|
|
2572
|
+
version_type = str(option)
|
|
2573
|
+
if self._has_version_been_bumped(version_type):
|
|
2574
|
+
self.console.print("\n" + "-" * 80)
|
|
2575
|
+
self.console.print(
|
|
2576
|
+
f"[bold yellow]📦 VERSION[/bold yellow] [bold bright_white]Version already bumped ({version_type}), skipping to avoid duplicate bump[/bold bright_white]"
|
|
2577
|
+
)
|
|
2578
|
+
self.console.print("-" * 80 + "\n")
|
|
2579
|
+
return
|
|
2486
2580
|
self.console.print("\n" + "-" * 80)
|
|
2487
2581
|
self.console.print(
|
|
2488
2582
|
f"[bold bright_magenta]📦 VERSION[/bold bright_magenta] [bold bright_white]Bumping {option} version[/bold bright_white]"
|
|
2489
2583
|
)
|
|
2490
2584
|
self.console.print("-" * 80 + "\n")
|
|
2491
|
-
if
|
|
2585
|
+
if version_type in ("minor", "major"):
|
|
2492
2586
|
from rich.prompt import Confirm
|
|
2493
2587
|
|
|
2494
2588
|
if not Confirm.ask(
|
|
@@ -2500,6 +2594,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2500
2594
|
)
|
|
2501
2595
|
return
|
|
2502
2596
|
self.execute_command(["uv", "version", "--bump", option])
|
|
2597
|
+
self._mark_version_bumped(version_type)
|
|
2503
2598
|
break
|
|
2504
2599
|
|
|
2505
2600
|
def _publish_project(self, options: OptionsProtocol) -> None:
|
|
@@ -2519,7 +2614,18 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2519
2614
|
"[bold bright_red]❌ Build failed. Please fix errors.[/bold bright_red]"
|
|
2520
2615
|
)
|
|
2521
2616
|
raise SystemExit(1)
|
|
2522
|
-
|
|
2617
|
+
try:
|
|
2618
|
+
self.execute_command(["uv", "publish"])
|
|
2619
|
+
self._mark_publish_completed()
|
|
2620
|
+
self._clear_state()
|
|
2621
|
+
self.console.print(
|
|
2622
|
+
"\n[bold bright_green]✅ Package published successfully![/bold bright_green]"
|
|
2623
|
+
)
|
|
2624
|
+
except SystemExit:
|
|
2625
|
+
self.console.print(
|
|
2626
|
+
"\n[bold bright_red]❌ Publish failed. Run crackerjack again to retry publishing without re-bumping version.[/bold bright_red]"
|
|
2627
|
+
)
|
|
2628
|
+
raise
|
|
2523
2629
|
|
|
2524
2630
|
def _commit_and_push(self, options: OptionsProtocol) -> None:
|
|
2525
2631
|
if options.commit:
|
|
@@ -2594,21 +2700,18 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2594
2700
|
"-c",
|
|
2595
2701
|
".pre-commit-config.yaml",
|
|
2596
2702
|
]
|
|
2597
|
-
result = self.execute_command(cmd
|
|
2703
|
+
result = self.execute_command(cmd)
|
|
2598
2704
|
if result.returncode > 0:
|
|
2599
2705
|
self.console.print(
|
|
2600
2706
|
"\n[bold bright_red]❌ Comprehensive quality checks failed![/bold bright_red]"
|
|
2601
2707
|
)
|
|
2602
|
-
self.console.print(f"[dim]STDOUT:[/dim]\n{result.stdout}")
|
|
2603
|
-
if result.stderr:
|
|
2604
|
-
self.console.print(f"[dim]STDERR:[/dim]\n{result.stderr}")
|
|
2605
2708
|
self.console.print(
|
|
2606
|
-
"\n[bold red]Cannot proceed with publishing/committing until all quality checks pass.
|
|
2709
|
+
"\n[bold red]Cannot proceed with publishing/committing until all quality checks pass.[/bold red]\n"
|
|
2607
2710
|
)
|
|
2608
2711
|
raise SystemExit(1)
|
|
2609
2712
|
else:
|
|
2610
2713
|
self.console.print(
|
|
2611
|
-
"[bold bright_green]✅ All comprehensive quality checks passed![/bold bright_green]"
|
|
2714
|
+
"\n[bold bright_green]✅ All comprehensive quality checks passed![/bold bright_green]"
|
|
2612
2715
|
)
|
|
2613
2716
|
|
|
2614
2717
|
async def _run_comprehensive_quality_checks_async(
|
|
@@ -2653,7 +2756,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2653
2756
|
if result.stderr:
|
|
2654
2757
|
self.console.print(f"[dim]Error details: {result.stderr}[/dim]")
|
|
2655
2758
|
self.console.print(
|
|
2656
|
-
"\n[bold red]Cannot proceed with publishing/committing until all quality checks pass.
|
|
2759
|
+
"\n[bold red]Cannot proceed with publishing/committing until all quality checks pass.[/bold red]\n"
|
|
2657
2760
|
)
|
|
2658
2761
|
raise SystemExit(1)
|
|
2659
2762
|
else:
|
|
@@ -2662,6 +2765,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2662
2765
|
)
|
|
2663
2766
|
|
|
2664
2767
|
def process(self, options: OptionsProtocol) -> None:
|
|
2768
|
+
assert self.project_manager is not None
|
|
2665
2769
|
self.console.print("\n" + "-" * 80)
|
|
2666
2770
|
self.console.print(
|
|
2667
2771
|
"[bold bright_cyan]⚒️ CRACKERJACKING[/bold bright_cyan] [bold bright_white]Starting workflow execution[/bold bright_white]"
|
|
@@ -2689,8 +2793,8 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2689
2793
|
self._run_tests(options)
|
|
2690
2794
|
self._run_comprehensive_quality_checks(options)
|
|
2691
2795
|
self._bump_version(options)
|
|
2692
|
-
self._publish_project(options)
|
|
2693
2796
|
self._commit_and_push(options)
|
|
2797
|
+
self._publish_project(options)
|
|
2694
2798
|
self.console.print("\n" + "-" * 80)
|
|
2695
2799
|
self.console.print(
|
|
2696
2800
|
"[bold bright_green]✨ CRACKERJACK COMPLETE[/bold bright_green] [bold bright_white]Workflow completed successfully![/bold bright_white]"
|
|
@@ -2698,6 +2802,7 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2698
2802
|
self.console.print("-" * 80 + "\n")
|
|
2699
2803
|
|
|
2700
2804
|
async def process_async(self, options: OptionsProtocol) -> None:
|
|
2805
|
+
assert self.project_manager is not None
|
|
2701
2806
|
self.console.print("\n" + "-" * 80)
|
|
2702
2807
|
self.console.print(
|
|
2703
2808
|
"[bold bright_cyan]⚒️ CRACKERJACKING[/bold bright_cyan] [bold bright_white]Starting workflow execution (async optimized)[/bold bright_white]"
|
|
@@ -2725,8 +2830,8 @@ class Crackerjack(BaseModel, arbitrary_types_allowed=True):
|
|
|
2725
2830
|
await self._run_tests_async(options)
|
|
2726
2831
|
await self._run_comprehensive_quality_checks_async(options)
|
|
2727
2832
|
self._bump_version(options)
|
|
2728
|
-
self._publish_project(options)
|
|
2729
2833
|
self._commit_and_push(options)
|
|
2834
|
+
self._publish_project(options)
|
|
2730
2835
|
self.console.print("\n" + "-" * 80)
|
|
2731
2836
|
self.console.print(
|
|
2732
2837
|
"[bold bright_green]✨ CRACKERJACK COMPLETE[/bold bright_green] [bold bright_white]Workflow completed successfully![/bold bright_white]"
|
|
@@ -111,7 +111,11 @@ def process_hook_results[T, R](
|
|
|
111
111
|
) -> list[R]:
|
|
112
112
|
processed_results: list[R] = []
|
|
113
113
|
for result in results:
|
|
114
|
-
if
|
|
114
|
+
if (
|
|
115
|
+
isinstance(result, dict)
|
|
116
|
+
and "status" in result
|
|
117
|
+
and result["status"] == HookStatus.SUCCESS
|
|
118
|
+
):
|
|
115
119
|
processed_results.append(success_handler(result))
|
|
116
120
|
else:
|
|
117
121
|
processed_results.append(failure_handler(result))
|
|
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
|
|
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
|