smart-commit-tool 2.0.1__tar.gz → 2.0.3__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.
@@ -0,0 +1,68 @@
1
+ name: Smart Commit CI Pipeline
2
+
3
+ on:
4
+ push:
5
+ branches: [ "main", "master", "prod", "release" ]
6
+ pull_request:
7
+ branches: [ "main", "master", "prod", "release" ]
8
+
9
+ jobs:
10
+ validate:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ # Runs the pipeline on multiple Python versions automatically
16
+ python-version: ["3.10", "3.11", "3.12"]
17
+
18
+ steps:
19
+ - name: Checkout Repository
20
+ uses: actions/checkout@v4
21
+
22
+ - name: Set up Python ${{ matrix.python-version }}
23
+ uses: actions/setup-python@v5
24
+ with:
25
+ python-version: ${{ matrix.python-version }}
26
+ cache: 'pip' # Speeds up consecutive runs
27
+
28
+ - name: Install Dependencies (Adaptive Smart Installer)
29
+ run: |
30
+ python -m pip install --upgrade pip
31
+
32
+ echo "🔍 Detecting package manager..."
33
+
34
+ if [ -f "poetry.lock" ] || [ -f "pyproject.toml" ] && grep -q "tool.poetry" "pyproject.toml"; then
35
+ echo "🚀 Poetry detected!"
36
+ pip install poetry
37
+ # Force poetry to install globally so custom commands work without 'poetry run'
38
+ poetry config virtualenvs.create false
39
+ poetry install --no-interaction --no-ansi
40
+
41
+ elif [ -f "Pipfile.lock" ] || [ -f "Pipfile" ]; then
42
+ echo "🚀 Pipenv detected!"
43
+ pip install pipenv
44
+ pipenv install --system --dev
45
+
46
+ elif [ -f "pdm.lock" ] || [ -f "pyproject.toml" ] && grep -q "tool.pdm" "pyproject.toml"; then
47
+ echo "🚀 PDM detected!"
48
+ pip install pdm
49
+ pdm config python.use_venv false
50
+ pdm install
51
+
52
+ elif [ -f "requirements.txt" ]; then
53
+ echo "🚀 Standard requirements.txt detected!"
54
+ pip install -r requirements.txt
55
+ # Install package itself if setup.py exists
56
+ if [ -f "setup.py" ]; then pip install -e .; fi
57
+
58
+ elif [ -f "pyproject.toml" ]; then
59
+ echo "🚀 Standard PEP 621 pyproject.toml detected (Hatch, Flit, Setuptools)!"
60
+ # Attempt to install with dev dependencies if available, otherwise regular install
61
+ pip install -e .[dev] || pip install -e .
62
+
63
+ else
64
+ echo "⚠️ No known package manager found. Skipping dependency installation."
65
+ fi
66
+
67
+ - name: Run 'ruff check .'
68
+ run: ruff check .
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: smart-commit-tool
3
- Version: 2.0.1
3
+ Version: 2.0.3
4
4
  Summary: Automated pre-push workflow manager with built-in code quality enforcement and smart branch protection.
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.11
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "smart-commit-tool"
7
- version = "2.0.1"
7
+ version = "2.0.3"
8
8
  description = "Automated pre-push workflow manager with built-in code quality enforcement and smart branch protection."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -56,7 +56,6 @@ jobs:
56
56
  strategy:
57
57
  fail-fast: false
58
58
  matrix:
59
- # Runs the pipeline on multiple Python versions automatically
60
59
  python-version: ["3.10", "3.11", "3.12"]
61
60
 
62
61
  steps:
@@ -67,18 +66,20 @@ jobs:
67
66
  uses: actions/setup-python@v5
68
67
  with:
69
68
  python-version: ${{ matrix.python-version }}
70
- cache: 'pip' # Speeds up consecutive runs
69
+ cache: 'pip'
71
70
 
72
71
  - name: Install Dependencies (Adaptive Smart Installer)
73
72
  run: |
74
73
  python -m pip install --upgrade pip
75
74
 
75
+ # Ensure local bin is in PATH for all subsequent steps
76
+ echo "$HOME/.local/bin" >> $GITHUB_PATH
77
+
76
78
  echo "🔍 Detecting package manager..."
77
79
 
78
80
  if [ -f "poetry.lock" ] || [ -f "pyproject.toml" ] && grep -q "tool.poetry" "pyproject.toml"; then
79
81
  echo "🚀 Poetry detected!"
80
82
  pip install poetry
81
- # Force poetry to install globally so custom commands work without 'poetry run'
82
83
  poetry config virtualenvs.create false
83
84
  poetry install --no-interaction --no-ansi
84
85
 
@@ -96,12 +97,10 @@ jobs:
96
97
  elif [ -f "requirements.txt" ]; then
97
98
  echo "🚀 Standard requirements.txt detected!"
98
99
  pip install -r requirements.txt
99
- # Install package itself if setup.py exists
100
100
  if [ -f "setup.py" ]; then pip install -e .; fi
101
101
 
102
102
  elif [ -f "pyproject.toml" ]; then
103
- echo "🚀 Standard PEP 621 pyproject.toml detected (Hatch, Flit, Setuptools)!"
104
- # Attempt to install with dev dependencies if available, otherwise regular install
103
+ echo "🚀 Standard PEP 621 pyproject.toml detected!"
105
104
  pip install -e .[dev] || pip install -e .
106
105
 
107
106
  else
@@ -7,21 +7,32 @@ from ..logger import Console, logger
7
7
  class GitService:
8
8
  @classmethod
9
9
  def _run(cls, cmd: list[str], silent: bool = True) -> subprocess.CompletedProcess:
10
- """Internal helper for executing Git commands."""
10
+ """Internal helper for executing Git commands with combined output."""
11
11
  logger.debug(f"Git CMD: {' '.join(cmd)}")
12
- return subprocess.run(cmd, capture_output=silent, text=True)
12
+ return subprocess.run(cmd, capture_output=True, text=True)
13
13
 
14
14
  @classmethod
15
15
  def ensure_repo(cls):
16
- """Checks for repository initialization and Detached HEAD state."""
17
- if not Path(".git").exists():
16
+ """Checks for repository initialization, Detached HEAD, and ongoing merges/rebases."""
17
+ git_dir = Path(".git")
18
+ if not git_dir.exists():
18
19
  Console.warning("Git not initialized. Initializing now...")
19
20
  cls._run(["git", "init"])
21
+ is_rebase = (git_dir / "rebase-apply").exists() or (
22
+ git_dir / "rebase-merge"
23
+ ).exists()
24
+ is_merge = (git_dir / "MERGE_HEAD").exists()
25
+
26
+ if is_rebase or is_merge:
27
+ raise GitOperationError(
28
+ "🛑 Git is currently in the middle of a REBASE or MERGE.\n"
29
+ "Please resolve conflicts manually or run 'git rebase --abort', then try again."
30
+ )
20
31
 
21
32
  res = cls._run(["git", "branch", "--show-current"])
22
33
  if not res.stdout.strip():
23
34
  raise GitOperationError(
24
- "You are in a DETACHED HEAD state. Process stopped for safety."
35
+ "You are in a DETACHED HEAD state. Please switch to a branch (e.g., 'git checkout main')."
25
36
  )
26
37
 
27
38
  @classmethod
@@ -76,33 +87,41 @@ class GitService:
76
87
 
77
88
  @classmethod
78
89
  def commit(cls, message: str):
79
- """Commits changes and extracts Git output if it fails."""
90
+ """Commits changes. Ignores 'nothing to commit' errors to allow push-only flows."""
80
91
  res = cls._run(["git", "commit", "-m", message])
92
+
81
93
  if res.returncode != 0:
82
- error_msg = res.stderr.strip() or res.stdout.strip()
83
- raise GitOperationError(f"Commit failed. Git says:\n{error_msg}")
94
+ output = (res.stdout + res.stderr).lower()
95
+ if "nothing to commit" in output or "working tree clean" in output:
96
+ return
97
+
98
+ raise GitOperationError(
99
+ f"Commit failed. Git says:\n{res.stderr or res.stdout}"
100
+ )
84
101
 
85
102
  @classmethod
86
103
  def push_with_retry(cls, branch: str):
87
- """Pushes to remote, attempting a pull --rebase if rejected."""
104
+ """Pushes to remote, attempting a pull --rebase if rejected or diverged."""
88
105
  Console.info(f"Pushing to branch: {branch}...")
89
106
  res = cls._run(["git", "push", "-u", "origin", branch])
90
107
 
91
108
  if res.returncode == 0:
92
109
  Console.success(f"Code successfully pushed to origin/{branch}!")
93
110
  return
111
+ Console.warning("Push rejected or branches diverged. Remote changes detected.")
112
+ Console.info("Synchronizing via pull --rebase...")
94
113
 
95
- Console.warning("Push rejected. Remote changes detected.")
96
- Console.info("Synchronizing (pull --rebase)...")
97
114
  pull_res = cls._run(["git", "pull", "origin", branch, "--rebase"])
98
115
 
99
116
  if pull_res.returncode != 0:
100
117
  error_msg = pull_res.stderr.strip() or pull_res.stdout.strip()
118
+ cls._run(["git", "rebase", "--abort"])
101
119
  raise GitOperationError(
102
- f"🛑 Rebase conflict detected!\nGit says: {error_msg}"
120
+ f"🛑 Rebase conflict! Conflicts were detected with remote files.\n"
121
+ f"Sync aborted. Please resolve manually. Git says:\n{error_msg}"
103
122
  )
104
123
 
105
- Console.success("Sync successful. Retrying push...")
124
+ Console.success("Sync successful. Retrying final push...")
106
125
  push_retry = cls._run(["git", "push", "-u", "origin", branch])
107
126
 
108
127
  if push_retry.returncode != 0: