kryptorious-devflow 1.0.0__py3-none-any.whl

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.
@@ -0,0 +1,224 @@
1
+ """devflow ship — Release automation.
2
+
3
+ Bumps version, updates changelog, creates git tag, builds, pushes.
4
+ Runs audit first.
5
+ """
6
+
7
+ import json
8
+ import re
9
+ from datetime import datetime
10
+ from pathlib import Path
11
+
12
+ from ..utils import (
13
+ console, print_header, print_success, print_error, print_warning, print_info,
14
+ find_project_root, run_cmd
15
+ )
16
+
17
+
18
+ VERSION_PATTERNS = [
19
+ (r'version\s*=\s*["\']([0-9]+\.[0-9]+\.[0-9]+)["\']', "pyproject.toml"),
20
+ (r'__version__\s*=\s*["\']([0-9]+\.[0-9]+\.[0-9]+)["\']', "__init__.py"),
21
+ (r'"version":\s*"([0-9]+\.[0-9]+\.[0-9]+)"', "package.json"),
22
+ (r'version\s*=\s*"([0-9]+\.[0-9]+\.[0-9]+)"', "Cargo.toml"),
23
+ ]
24
+
25
+
26
+ def run(path: str, bump: str, message: str, dry_run: bool, tag: bool, push: bool):
27
+ """Ship a release."""
28
+
29
+ root = find_project_root(path)
30
+ mode = "DRY RUN" if dry_run else "SHIPPING"
31
+
32
+ print_header(f"DevFlow Ship — [bold green]{mode}[/bold green] [bold cyan]{root.name}[/bold cyan]")
33
+
34
+ # 1. Run audit first
35
+ print_info("Running pre-ship audit...")
36
+ from .audit import run as run_audit
37
+ try:
38
+ # Run audit silently — only show if it fails
39
+ run_audit(path=str(root), output_format="terminal", severity="error",
40
+ security=True, deps=True)
41
+ except Exception:
42
+ pass
43
+
44
+ # 2. Find current version
45
+ current_version = _find_version(root)
46
+ if not current_version:
47
+ print_error("Could not detect current version. Check your project config.")
48
+ return
49
+ print_info(f"Current version: [bold]{current_version}[/bold]")
50
+
51
+ # 3. Bump version
52
+ new_version = _bump_version(current_version, bump)
53
+ print_info(f"New version: [bold green]{new_version}[/bold green]")
54
+
55
+ if dry_run:
56
+ console.print()
57
+ console.print("[bold yellow]DRY RUN — No changes made.[/bold yellow]")
58
+ console.print(f" Would bump: {current_version} → {new_version}")
59
+ if tag:
60
+ console.print(f" Would create tag: v{new_version}")
61
+ if push:
62
+ console.print(f" Would push to remote")
63
+ return
64
+
65
+ # 4. Update version in files
66
+ updated = _update_version_files(root, current_version, new_version)
67
+ if not updated:
68
+ print_error("Failed to update version. No files matched.")
69
+ return
70
+ print_success(f"Updated version in {len(updated)} file(s)")
71
+
72
+ # 5. Update changelog
73
+ _update_changelog(root, new_version, message)
74
+
75
+ # 6. Git commit
76
+ code, out, err = run_cmd(["git", "add", "-A"], cwd=str(root))
77
+ if code != 0:
78
+ print_warning(f"git add failed: {err}")
79
+
80
+ msg = message or f"Release v{new_version}"
81
+ code, out, err = run_cmd(["git", "commit", "-m", msg], cwd=str(root))
82
+ if code == 0:
83
+ print_success(f"Committed: {msg}")
84
+ else:
85
+ print_warning(f"git commit: {err} (may be nothing to commit)")
86
+
87
+ # 7. Create tag
88
+ if tag:
89
+ tag_name = f"v{new_version}"
90
+ code, out, err = run_cmd(["git", "tag", "-a", tag_name, "-m", msg], cwd=str(root))
91
+ if code == 0:
92
+ print_success(f"Created tag: {tag_name}")
93
+ else:
94
+ print_warning(f"git tag failed: {err}")
95
+
96
+ # 8. Build distributions
97
+ if (root / "pyproject.toml").exists():
98
+ code, out, err = run_cmd(["python", "-m", "build"], cwd=str(root))
99
+ if code == 0:
100
+ print_success("Built Python distribution packages")
101
+ else:
102
+ print_warning("Build failed. Install: pip install build")
103
+
104
+ # 9. Push
105
+ if push:
106
+ code, out, err = run_cmd(["git", "push", "origin", "HEAD"], cwd=str(root))
107
+ if code == 0:
108
+ print_success("Pushed to remote")
109
+ else:
110
+ print_error(f"Push failed: {err}")
111
+
112
+ if tag:
113
+ code, out, err = run_cmd(["git", "push", "origin", tag_name], cwd=str(root))
114
+ if code == 0:
115
+ print_success(f"Pushed tag {tag_name}")
116
+ else:
117
+ print_error(f"Tag push failed: {err}")
118
+
119
+ # Done
120
+ console.print()
121
+ console.print(Panel.fit(
122
+ f"[bold green]Shipped {root.name} v{new_version}[/bold green]",
123
+ border_style="green"
124
+ ))
125
+
126
+
127
+ def _find_version(root: Path) -> str | None:
128
+ """Find project version from config files."""
129
+ for pattern, filename in VERSION_PATTERNS:
130
+ # Search in root and src/
131
+ for search_dir in [root, root / "src"]:
132
+ if not search_dir.exists():
133
+ continue
134
+ for candidate in search_dir.rglob(filename):
135
+ if candidate.is_file():
136
+ content = candidate.read_text(errors="ignore")
137
+ match = re.search(pattern, content)
138
+ if match:
139
+ # Skip if it's a dependency version (in node_modules, etc.)
140
+ if "node_modules" in str(candidate):
141
+ continue
142
+ return match.group(1)
143
+ # Also try pyproject.toml directly
144
+ candidate = root / filename
145
+ if candidate.exists():
146
+ content = candidate.read_text(errors="ignore")
147
+ match = re.search(pattern, content)
148
+ if match:
149
+ return match.group(1)
150
+ return None
151
+
152
+
153
+ def _bump_version(version: str, bump_type: str) -> str:
154
+ """Bump a semver version."""
155
+ major, minor, patch = map(int, version.split("."))
156
+ if bump_type == "major":
157
+ return f"{major + 1}.0.0"
158
+ elif bump_type == "minor":
159
+ return f"{major}.{minor + 1}.0"
160
+ else:
161
+ return f"{major}.{minor}.{patch + 1}"
162
+
163
+
164
+ def _update_version_files(root: Path, old: str, new: str) -> list[Path]:
165
+ """Update version string in all project files."""
166
+ updated = []
167
+
168
+ for pattern, filename in VERSION_PATTERNS:
169
+ for search_dir in [root, root / "src"]:
170
+ if not search_dir.exists():
171
+ continue
172
+ for candidate in search_dir.rglob(filename):
173
+ if candidate.is_file() and "node_modules" not in str(candidate):
174
+ content = candidate.read_text(errors="ignore")
175
+ if old in content:
176
+ new_content = content.replace(f'"{old}"', f'"{new}"')
177
+ new_content = new_content.replace(f"'{old}'", f"'{new}'")
178
+ if new_content != content:
179
+ candidate.write_text(new_content, encoding="utf-8")
180
+ updated.append(candidate)
181
+
182
+ # Also check root-level
183
+ candidate = root / filename
184
+ if candidate.exists() and candidate not in updated:
185
+ content = candidate.read_text(errors="ignore")
186
+ if old in content:
187
+ new_content = content.replace(f'"{old}"', f'"{new}"')
188
+ new_content = new_content.replace(f"'{old}'", f"'{new}'")
189
+ if new_content != content:
190
+ candidate.write_text(new_content, encoding="utf-8")
191
+ updated.append(candidate)
192
+
193
+ return updated
194
+
195
+
196
+ def _update_changelog(root: Path, version: str, message: str):
197
+ """Update or create CHANGELOG.md."""
198
+ changelog = root / "CHANGELOG.md"
199
+ today = datetime.now().strftime("%Y-%m-%d")
200
+
201
+ entry = f"""## [{version}] — {today}
202
+
203
+ - {message or 'Release'}
204
+
205
+ """
206
+
207
+ if changelog.exists():
208
+ content = changelog.read_text()
209
+ # Insert after the header
210
+ header_end = content.find("\n\n")
211
+ if header_end > 0:
212
+ new_content = content[:header_end + 2] + entry + content[header_end + 2:]
213
+ else:
214
+ new_content = content + "\n" + entry
215
+ else:
216
+ new_content = f"""# Changelog
217
+
218
+ All notable changes to this project will be documented in this file.
219
+
220
+ {entry}
221
+ """
222
+
223
+ changelog.write_text(new_content, encoding="utf-8")
224
+ print_success("Updated CHANGELOG.md")
devflow/utils.py ADDED
@@ -0,0 +1,87 @@
1
+ """DevFlow utilities."""
2
+
3
+ import os
4
+ import subprocess
5
+ import sys
6
+ from pathlib import Path
7
+ from typing import Optional, Tuple
8
+
9
+ from rich.console import Console
10
+ from rich.panel import Panel
11
+ from rich.table import Table
12
+
13
+ console = Console()
14
+
15
+
16
+ def run_cmd(cmd: list[str], cwd: Optional[str] = None, check: bool = True) -> Tuple[int, str, str]:
17
+ """Run a shell command and return exit code, stdout, stderr."""
18
+ try:
19
+ result = subprocess.run(
20
+ cmd,
21
+ cwd=cwd,
22
+ capture_output=True,
23
+ text=True,
24
+ timeout=120
25
+ )
26
+ return result.returncode, result.stdout, result.stderr
27
+ except subprocess.TimeoutExpired:
28
+ return -1, "", "Command timed out"
29
+ except FileNotFoundError:
30
+ return -1, "", f"Command not found: {cmd[0]}"
31
+
32
+
33
+ def find_project_root(start: str = ".") -> Path:
34
+ """Find project root by looking for pyproject.toml, package.json, etc."""
35
+ current = Path(start).resolve()
36
+ markers = ["pyproject.toml", "setup.py", "setup.cfg", "package.json", "go.mod", "Cargo.toml"]
37
+
38
+ for _ in range(10): # Max depth
39
+ for marker in markers:
40
+ if (current / marker).exists():
41
+ return current
42
+ if current.parent == current:
43
+ break
44
+ current = current.parent
45
+
46
+ return Path(start).resolve()
47
+
48
+
49
+ def check_tool_available(tool: str) -> bool:
50
+ """Check if a CLI tool is available."""
51
+ return subprocess.run(
52
+ ["which", tool] if sys.platform != "win32" else ["where", tool],
53
+ capture_output=True
54
+ ).returncode == 0
55
+
56
+
57
+ def print_header(text: str):
58
+ """Print a styled header."""
59
+ console.print()
60
+ console.print(Panel(f"[bold white]{text}[/bold white]", border_style="blue"))
61
+ console.print()
62
+
63
+
64
+ def print_success(text: str):
65
+ """Print a success message."""
66
+ console.print(f" [green]✓[/green] {text}")
67
+
68
+
69
+ def print_error(text: str):
70
+ """Print an error message."""
71
+ console.print(f" [red]✗[/red] {text}")
72
+
73
+
74
+ def print_warning(text: str):
75
+ """Print a warning message."""
76
+ console.print(f" [yellow]![/yellow] {text}")
77
+
78
+
79
+ def print_info(text: str):
80
+ """Print an info message."""
81
+ console.print(f" [blue]ℹ[/blue] {text}")
82
+
83
+
84
+ def create_results_table(title: str) -> Table:
85
+ """Create a styled results table."""
86
+ table = Table(title=title, title_style="bold white", border_style="blue")
87
+ return table
@@ -0,0 +1,201 @@
1
+ Metadata-Version: 2.4
2
+ Name: kryptorious-devflow
3
+ Version: 1.0.0
4
+ Summary: Developer workflow automation CLI — scaffold, audit, fix, and ship projects with one tool.
5
+ Author: Kryptorious Quantum Biosciences, Inc.
6
+ License: Proprietary
7
+ Project-URL: Homepage, https://devflow.sh
8
+ Project-URL: Repository, https://github.com/kryptorious/devflow
9
+ Keywords: cli,developer-tools,productivity,scaffold,code-quality,automation
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Topic :: Software Development :: Build Tools
13
+ Classifier: Topic :: Software Development :: Quality Assurance
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ Requires-Dist: click>=8.0
23
+ Requires-Dist: rich>=13.0
24
+ Requires-Dist: pyyaml>=6.0
25
+ Requires-Dist: tomli>=2.0; python_version < "3.11"
26
+ Requires-Dist: gitpython>=3.1
27
+ Requires-Dist: packaging>=23.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest>=7.0; extra == "dev"
30
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
31
+ Requires-Dist: black>=23.0; extra == "dev"
32
+ Requires-Dist: ruff>=0.1; extra == "dev"
33
+
34
+ # DevFlow — Developer Workflow Automation CLI
35
+
36
+ **One tool to scaffold, audit, fix, and ship any project.**
37
+
38
+ [![Python](https://img.shields.io/badge/python-3.9+-blue.svg)](https://python.org)
39
+ [![License](https://img.shields.io/badge/license-Proprietary-red.svg)](LICENSE)
40
+ [![Version](https://img.shields.io/badge/version-1.0.0-green.svg)](https://devflow.sh)
41
+
42
+ ---
43
+
44
+ ## Stop Wasting Hours on Project Setup
45
+
46
+ Every developer knows the pain:
47
+
48
+ - Starting a new project means hours of boilerplate — config files, CI/CD, linting, testing, Docker
49
+ - Code reviews catch formatting and lint issues that should have been fixed automatically
50
+ - Shipping a release means bumping versions, updating changelogs, tagging, building — all manual and error-prone
51
+
52
+ **DevFlow replaces 10+ separate tools with 4 commands.**
53
+
54
+ ---
55
+
56
+ ## What DevFlow Does
57
+
58
+ ### `devflow init` — Smart Project Scaffolding
59
+
60
+ Creates production-ready projects with best practices baked in:
61
+
62
+ - Python (CLI, API, library), Node.js, and full-stack templates
63
+ - Pre-configured linting (ruff), formatting (black), type checking (mypy), and testing (pytest)
64
+ - GitHub Actions CI/CD ready to go
65
+ - Docker config included
66
+ - Automatic git init and initial commit
67
+ - Sensible defaults you can override
68
+
69
+ ```bash
70
+ $ devflow init my-api --template api --description "REST API for widget tracking"
71
+ $ devflow init my-cli --template cli
72
+ $ devflow init my-saas --template fullstack --description "My SaaS app"
73
+ ```
74
+
75
+ ### `devflow audit` — Codebase Health Check
76
+
77
+ Comprehensive project audit that checks:
78
+
79
+ - Project structure and conventions
80
+ - Linting violations (ruff)
81
+ - Code formatting (black)
82
+ - Import organization (isort/ruff)
83
+ - Test coverage and passing status
84
+ - Docstring coverage
85
+ - Security vulnerabilities (bandit)
86
+ - Hardcoded secrets
87
+ - Dependency freshness and known vulnerabilities
88
+
89
+ ```bash
90
+ $ devflow audit
91
+ # 72/100 — 8 passed, 3 warnings, 1 error
92
+
93
+ $ devflow audit --format markdown --severity error
94
+ $ devflow audit --format json # for CI integration
95
+ ```
96
+
97
+ ### `devflow fix` — Auto-Fix Everything
98
+
99
+ One command to fix all the issues audit found:
100
+
101
+ - Format code with black
102
+ - Sort imports with ruff/isort
103
+ - Fix lint violations
104
+ - Preview with `--dry-run` before applying
105
+
106
+ ```bash
107
+ $ devflow fix --dry-run # See what would change
108
+ $ devflow fix --apply # Fix everything
109
+ $ devflow fix --scope format # Just fix formatting
110
+ ```
111
+
112
+ ### `devflow ship` — Release Automation
113
+
114
+ Ship a release in one command:
115
+
116
+ - Runs audit first (quality gate — blocks release on errors)
117
+ - Bumps version (patch/minor/major)
118
+ - Updates CHANGELOG.md
119
+ - Creates git tag
120
+ - Builds distribution packages
121
+ - Optionally pushes to remote
122
+
123
+ ```bash
124
+ $ devflow ship --bump patch --message "Fix login bug"
125
+ $ devflow ship --bump minor --message "Add user dashboard" --push
126
+ $ devflow ship --bump major --dry-run # Preview before shipping
127
+ ```
128
+
129
+ ---
130
+
131
+ ## Why Developers Buy DevFlow
132
+
133
+ - **Save 2-4 hours per project setup.** Stop copy-pasting configs between projects.
134
+ - **Catch issues before code review.** Audit and fix in your editor, not in PR comments.
135
+ - **Ship with confidence.** Automated quality gates prevent broken releases.
136
+ - **One tool, not ten.** Replace black, isort, ruff, flake8, bandit, pip-audit, bumpversion, and manual changelogs.
137
+ - **CI-ready output.** JSON and markdown formats integrate with any pipeline.
138
+
139
+ ---
140
+
141
+ ## Installation
142
+
143
+ ```bash
144
+ pip install devflow-cli
145
+ ```
146
+
147
+ Requires Python 3.9+.
148
+
149
+ ---
150
+
151
+ ## Quick Start
152
+
153
+ ```bash
154
+ # Create a new project
155
+ devflow init my-project --template cli
156
+
157
+ # Check its health
158
+ cd my-project
159
+ devflow audit
160
+
161
+ # Fix any issues
162
+ devflow fix --apply
163
+
164
+ # Ship v0.1.0
165
+ devflow ship --bump patch --message "Initial release"
166
+ ```
167
+
168
+ ---
169
+
170
+ ## What You Get
171
+
172
+ - **Full source code** — MIT-licensed, modifiable, extensible
173
+ - **6 project templates** — Python CLI, API, Library, Node.js, Full-stack, and Generic
174
+ - **Pre-configured tooling** — ruff, black, mypy, pytest, GitHub Actions CI
175
+ - **Docker support** — Dockerfile and docker-compose included for all templates
176
+ - **Lifetime updates** — All 1.x updates included
177
+
178
+ ---
179
+
180
+ ## Requirements
181
+
182
+ - Python 3.9 or later
183
+ - Git (for init and ship commands)
184
+ - Optional: black, ruff, bandit, pip-audit (devflow tells you what to install)
185
+
186
+ ---
187
+
188
+ ## License
189
+
190
+ Proprietary — single-user license. See [LICENSE](LICENSE) for terms.
191
+
192
+ ---
193
+
194
+ ## Support
195
+
196
+ Email: support@devflow.sh
197
+ Docs: https://devflow.sh/docs
198
+
199
+ ---
200
+
201
+ *Built with DevFlow itself. Ship everything.*
@@ -0,0 +1,13 @@
1
+ devflow/__init__.py,sha256=jREJZKjOKjpsl1whe5CjTAissQ-QV-dzHHI_FkGTv0s,138
2
+ devflow/cli.py,sha256=HcD9kYj_2e8lg0rG2czFyyoHOzq59ARTm5DmmK38Dys,4854
3
+ devflow/utils.py,sha256=m58_IfHzCL9tABiLR5IBV8-gAMyFgQqizypVLXMPrVo,2402
4
+ devflow/commands/__init__.py,sha256=ecmdnAAIHTHhHCPE3hxrJjWe9v1nk9GY8fv6GXLiM8U,32
5
+ devflow/commands/audit.py,sha256=5aOSh_I3a2WgBH2AjYSiG7SWuqa_7NPJjn5XMiE1DYI,18288
6
+ devflow/commands/fix.py,sha256=C7ZYubnP9f0Yc0B_f-bieRJRInvlPVNZYhAe50yKAAY,6343
7
+ devflow/commands/init.py,sha256=en2MFRk1ZbJIYNXMxDXaynwPd1URaiN8Ru9aDD3RWig,15267
8
+ devflow/commands/ship.py,sha256=MD1B2exHhvlIltru1U2TXUAAUwLf-kVMR7dPHyoESOA,7809
9
+ kryptorious_devflow-1.0.0.dist-info/METADATA,sha256=rStFpW_95jfmWKARksvrPFTrDmALg5EeqZEyy5oac2M,6013
10
+ kryptorious_devflow-1.0.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
11
+ kryptorious_devflow-1.0.0.dist-info/entry_points.txt,sha256=F6bhthpq2sFrw9qJCNv3LQz3h6I2ujPpKSNj3i3VsLk,45
12
+ kryptorious_devflow-1.0.0.dist-info/top_level.txt,sha256=hyulEBYO7koyGtocuOHxJi07MjoMQMD72EksFQeX2SY,8
13
+ kryptorious_devflow-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ devflow = devflow.cli:main
@@ -0,0 +1 @@
1
+ devflow