feat: add semantic-release and binary releases (#3)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..b78ac58
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,94 @@
+name: Release  
+  
+on:  
+  push:  
+    branches: [master]  
+  pull_request:  
+    branches: [master]  
+  
+jobs:  
+  test:  
+    runs-on: ubuntu-latest  
+    strategy:  
+      matrix:  
+        python-version: ["3.9", "3.10", "3.11", "3.12"]  
+      
+    steps:  
+    - uses: actions/checkout@v4  
+    - name: Set up Python ${{ matrix.python-version }}  
+      uses: actions/setup-python@v4  
+      with:  
+        python-version: ${{ matrix.python-version }}  
+      
+    - name: Install dependencies  
+      run: |  
+        python -m pip install --upgrade pip  
+        pip install -r requirements.txt  
+  
+  build-binaries:  
+    needs: test  
+    runs-on: ${{ matrix.os }}  
+    strategy:  
+      matrix:  
+        os: [ubuntu-latest, windows-latest, macos-latest]  
+      
+    steps:  
+    - uses: actions/checkout@v4  
+    - name: Set up Python  
+      uses: actions/setup-python@v4  
+      with:  
+        python-version: 3.11  
+      
+    - name: Install dependencies  
+      run: |  
+        python -m pip install --upgrade pip  
+        pip install -r requirements.txt  
+        pip install pyinstaller  
+      
+    - name: Build binary  
+      run: python scripts/build_binaries.py  
+      
+    - name: Upload artifacts  
+      uses: actions/upload-artifact@v4  
+      with:  
+        name: binaries-${{ matrix.os }}  
+        path: dist/casbin-cli-*  
+  
+  release:  
+    needs: [test, build-binaries]  
+    runs-on: ubuntu-latest  
+    if: github.ref == 'refs/heads/master'  
+      
+    steps:  
+    - uses: actions/checkout@v4  
+      with:  
+        fetch-depth: 0  
+        token: ${{ secrets.GITHUB_TOKEN }}  
+      
+    - name: Set up Python  
+      uses: actions/setup-python@v4  
+      with:  
+        python-version: 3.11  
+      
+    - name: Install dependencies  
+      run: |  
+        python -m pip install --upgrade pip  
+        pip install -r requirements.txt  
+        pip install wheel twine  
+        npm install -g semantic-release @semantic-release/changelog @semantic-release/exec @semantic-release/github  
+      
+    - name: Download all artifacts  
+      uses: actions/download-artifact@v4  
+      with:  
+        path: artifacts  
+      
+    - name: Move binaries to dist  
+      run: |  
+        mkdir -p dist  
+        find artifacts -name "casbin-cli-*" -exec cp {} dist/ \;  
+      
+    - name: Semantic Release  
+      env:  
+        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        #PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}  
+      run: npx semantic-release
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index b7faf40..2efd350 100644
--- a/.gitignore
+++ b/.gitignore
@@ -205,3 +205,5 @@
 marimo/_static/
 marimo/_lsp/
 __marimo__/
+
+.idea
diff --git a/.releaserc.json b/.releaserc.json
new file mode 100644
index 0000000..5337483
--- /dev/null
+++ b/.releaserc.json
@@ -0,0 +1,38 @@
+{  
+  "branches": ["master"],
+  "repositoryUrl": "https://github.com/casbin/casbin-python-cli",
+  "plugins": [  
+    "@semantic-release/commit-analyzer",  
+    "@semantic-release/release-notes-generator",  
+    [  
+      "@semantic-release/changelog",  
+      {  
+        "changelogFile": "CHANGELOG.md"  
+      }  
+    ],  
+    [  
+      "@semantic-release/exec",  
+      {  
+        "prepareCmd": "python scripts/update_version.py ${nextRelease.version}"
+      }  
+    ],  
+    [  
+      "@semantic-release/github",  
+      {  
+        "assets": [  
+          {  
+            "path": "dist/*.whl",  
+            "label": "Python Wheel"  
+          },  
+          {  
+            "path": "dist/*.tar.gz",  
+            "label": "Source Distribution"  
+          },  
+          {  
+            "path": "dist/casbin-cli-*"
+          }  
+        ]  
+      }  
+    ]  
+  ]  
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index f309ec2..8384160 100644
--- a/README.md
+++ b/README.md
@@ -33,20 +33,39 @@
 ## Project Structure
 
 ```
-casbin-python-cli/
-├── casbin_cli/
-│   ├── __init__.py
-│   ├── client.py          # Main entry point and CLI argument parsing
-│   ├── command_executor.py # Dynamic method execution and JSON response
-│   ├── enforcer_factory.py # Enforcer creation and input validation
-│   ├── response.py        # JSON response formatting
-│   └── utils.py           # Utility functions
-├── examples/              # Example configuration files
-├── requirements.txt       # Python dependencies
-├── setup.py               # Package installation script
-└── README.md
+casbin-python-cli/  
+├── .github/  
+│   └── workflows/  
+│       └── release.yml           # GitHub Actions CI/CD  
+├── scripts/  
+│   ├── update_version.py         # Version management  
+│   └── build_binaries.py         # Binary building  
+├── casbin_cli/  
+│   ├── __init__.py  
+│   ├── __version__.py            # Version source  
+│   ├── client.py                 # Main CLI entry point  
+│   ├── command_executor.py       # Command execution  
+│   ├── enforcer_factory.py       # Enforcer creation  
+│   ├── response.py               # Response formatting  
+│   └── utils.py                  # Utilities  
+├── examples/                     # Example configurations  
+├── .releaserc.json              # Semantic release config  
+├── package.json                 # Node.js dependencies  
+├── requirements.txt             # Python dependencies  
+├── setup.py                     # Package setup  
+└── README.md  
 ```
 
+### Release Process
+
+Releases are automated via GitHub Actions:
+
+1. Push commits to `main` branch
+2. Semantic release analyzes commit messages
+3. Automatically generates version numbers and changelog
+4. Builds cross-platform binaries
+5. Publishes to PyPI and GitHub Releases
+
 ## Requirements
 
 - Python 3.6+
diff --git a/casbin_cli/__version__.py b/casbin_cli/__version__.py
new file mode 100644
index 0000000..d538f87
--- /dev/null
+++ b/casbin_cli/__version__.py
@@ -0,0 +1 @@
+__version__ = "1.0.0"
\ No newline at end of file
diff --git a/casbin_cli/client.py b/casbin_cli/client.py
index 8758843..09e6146 100644
--- a/casbin_cli/client.py
+++ b/casbin_cli/client.py
@@ -1,9 +1,10 @@
 import argparse  
 import sys  
 import json  
-from .command_executor import CommandExecutor  
-from .enforcer_factory import EnforcerFactory  
-from .utils import process_line_breaks  
+from casbin_cli.command_executor import CommandExecutor    
+from casbin_cli.enforcer_factory import EnforcerFactory    
+from casbin_cli.utils import process_line_breaks 
+from casbin_cli.__version__ import __version__
   
 class Client:  
     @staticmethod  
@@ -23,10 +24,10 @@
             if command_name in ['-h', '--help']:  
                 Client._print_help()  
                 return ""  
-            elif command_name in ['-v', '--version']:  
-                print("casbin-python-cli 1.0.0")  
-                print("pycasbin 1.17.0")  
-                return ""  
+            #elif command_name in ['-v', '--version']:  
+            #    print(f"casbin-python-cli {__version__}")  
+            #    print("pycasbin 1.17.0")  
+            #    return ""
               
             # Handle line breaks
             processed_args = [args[0]]  
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..25736da
--- /dev/null
+++ b/package.json
@@ -0,0 +1,11 @@
+{  
+  "name": "casbin-python-cli",  
+  "version": "1.0.0",  
+  "private": true,  
+  "devDependencies": {  
+    "@semantic-release/changelog": "^6.0.0",  
+    "@semantic-release/exec": "^6.0.0",  
+    "@semantic-release/github": "^8.0.0",  
+    "semantic-release": "^19.0.0"  
+  }  
+}
\ No newline at end of file
diff --git a/scripts/build_binaries.py b/scripts/build_binaries.py
new file mode 100644
index 0000000..7fa072d
--- /dev/null
+++ b/scripts/build_binaries.py
@@ -0,0 +1,57 @@
+# Copyright 2025 The casbin Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os  
+import sys  
+import subprocess  
+import platform  
+  
+def build_binary():  
+    """Build standalone binary using PyInstaller"""  
+      
+    # Install PyInstaller if not present  
+    subprocess.run([sys.executable, "-m", "pip", "install", "pyinstaller"], check=True)  
+      
+    # Get platform info  
+    system = platform.system().lower()  
+    arch = platform.machine().lower()  
+      
+    # Build binary  
+    binary_name = f"casbin-cli-{system}-{arch}"  
+    if system == "windows":  
+        binary_name += ".exe"  
+      
+    cmd = [  
+    "pyinstaller",  
+    "--onefile",  
+    "--name", binary_name,  
+    "--console",  
+    "--paths", ".",  
+    "--hidden-import", "casbin_cli",  
+    "--hidden-import", "casbin",  
+    "--hidden-import", "casbin_cli.client",  
+    "--hidden-import", "casbin_cli.command_executor",   
+    "--hidden-import", "casbin_cli.enforcer_factory",  
+    "--hidden-import", "casbin_cli.response",  
+    "--hidden-import", "casbin_cli.utils",  
+    "--collect-all", "casbin", 
+    "casbin_cli/client.py"  
+] 
+      
+    subprocess.run(cmd, check=True)  
+      
+    print(f"Binary built successfully: dist/{binary_name}")  
+  
+if __name__ == "__main__":  
+    build_binary()
\ No newline at end of file
diff --git a/scripts/update_version.py b/scripts/update_version.py
new file mode 100644
index 0000000..14bff6e
--- /dev/null
+++ b/scripts/update_version.py
@@ -0,0 +1,45 @@
+# Copyright 2025 The casbin Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys  
+import re  
+import os  
+  
+def update_version(new_version):  
+    """Update version in all relevant files"""  
+      
+    # Update setup.py  
+    setup_py_path = "setup.py"  
+    with open(setup_py_path, 'r') as f:  
+        content = f.read()  
+      
+    # Update client.py version display  
+    client_py_path = "casbin_cli/client.py"  
+    with open(client_py_path, 'r') as f:  
+        content = f.read()  
+      
+    # Create __version__.py  
+    version_py_path = "casbin_cli/__version__.py"  
+    with open(version_py_path, 'w') as f:  
+        f.write(f'__version__ = "{new_version}"\n')  
+      
+    print(f"Updated version to {new_version}")  
+  
+if __name__ == "__main__":  
+    if len(sys.argv) != 2:  
+        print("Usage: python update_version.py <version>")  
+        sys.exit(1)  
+      
+    new_version = sys.argv[1]  
+    update_version(new_version)
\ No newline at end of file
diff --git a/setup.py b/setup.py
index 177460b..7bef60a 100644
--- a/setup.py
+++ b/setup.py
@@ -1,9 +1,34 @@
+# Copyright 2025 The casbin Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
 from setuptools import setup, find_packages  
+import os  
+  
+# Read version from __version__.py  
+version_file = os.path.join(os.path.dirname(__file__), 'casbin_cli', '__version__.py')  
+if os.path.exists(version_file):  
+    exec(open(version_file).read())  
+    version = __version__  
+else:  
+    version = "1.0.0"  
   
 setup(  
     name="casbin-python-cli",  
-    version="1.0.0",  
+    version=version,  
     description="A command-line tool for PyCasbin",  
+    long_description=open("README.md").read(),  
+    long_description_content_type="text/markdown",  
     packages=find_packages(),  
     install_requires=[  
         "casbin>=1.17.0",