diff --git a/.github/workflows/package-build.yaml b/.github/workflows/package-build.yaml index 97d0fb91..94281391 100644 --- a/.github/workflows/package-build.yaml +++ b/.github/workflows/package-build.yaml @@ -6,40 +6,28 @@ on: - "v*" jobs: - check-branch: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Verify tag is on main - run: | - if [ "$(git branch --contains $GITHUB_REF)" != "* main" ]; then - echo "Tag $GITHUB_REF is not on main branch" - exit 1 - fi build: - needs: check-branch runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] include: - os: ubuntu-latest - artifact_name: linux-x64 + artifact_name: linux - os: windows-latest - artifact_name: windows-x64.exe + artifact_name: win32.exe - os: macos-latest - artifact_name: macos-x64 + artifact_name: macos steps: - uses: actions/checkout@v4 - - name: Set up Python uses: actions/setup-python@v4 with: python-version: "3.10" architecture: ${{ runner.os == 'Windows' && 'x64' || '' }} - - name: Install tools + - name: Install build tools run: | python -m pip install --upgrade pip pip install pyinstaller @@ -47,7 +35,7 @@ jobs: - name: Install package run: | pip install . - + - name: Create Linux executable if: matrix.os == 'ubuntu-latest' run: | @@ -91,42 +79,56 @@ jobs: dist/ecooptimizer-server-dev-* if-no-files-found: error - create-release: + publish-pypi: needs: build runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + - name: Install build tools + run: | + python -m pip install --upgrade pip + pip install build twine + - name: Build source distribution + run: | + python -m build + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist/ + env: + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} + + create-release: + needs: [build, publish-pypi] + runs-on: ubuntu-latest steps: - name: Download all artifacts uses: actions/download-artifact@v4 with: path: artifacts pattern: artifacts-* - merge-multiple: false # Keep separate folders per OS + merge-multiple: false - name: Create release uses: softprops/action-gh-release@v1 with: tag_name: ${{ github.ref }} - name: ${{ github.ref_name }} + name: ${{ github.ref_name }} Test 1 body: | ${{ github.event.head_commit.message }} - - ## EcoOptimizer Server Executables - This release contains the standalone server executables for launching the EcoOptimizer analysis engine. - These are designed to work with the corresponding **EcoOptimizer VS Code Extension**. - - ### Included Artifacts - - **Production Server**: `ecooptimizer-server-` - (Stable version for production use) - - **Development Server**: `ecooptimizer-server-dev-` - (Development version with debug features) - - ### Platform Support - - Linux (`linux-x64`) - - Windows (`windows-x64.exe`) - - macOS (`macos-x64`) + + **Artifacts:** + - Source distribution (.tar.gz) published to PyPI + - Executables for Windows, macOS, and Linux files: | - artifacts/artifacts-ubuntu-latest/dist/* - artifacts/artifacts-windows-latest/dist/* - artifacts/artifacts-macos-latest/dist/* + artifacts/artifacts-ubuntu-latest/* + artifacts/artifacts-windows-latest/* + artifacts/artifacts-macos-latest/* + draft: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3f8602fe..2f612c51 100644 --- a/.gitignore +++ b/.gitignore @@ -307,4 +307,6 @@ tests/benchmarking/output/ # Coverage .coverage -coverage.* \ No newline at end of file +coverage.* + +src/ecooptimizer/_version.py \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 25181b22..b13e0b75 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,9 @@ [build-system] -requires = ["setuptools >= 61.0"] +requires = ["setuptools >= 61.0", "setuptools_scm[toml]>=6.0"] build-backend = "setuptools.build_meta" [project] name = "ecooptimizer" -version = "0.0.1" dependencies = [ "pylint", "rope", @@ -17,6 +16,7 @@ dependencies = [ "libcst", "websockets", ] +version = "0.1.0" requires-python = ">=3.9" authors = [ { name = "Sevhena Walker" }, @@ -47,10 +47,22 @@ eco-ext = "ecooptimizer.api.__main__:main" eco-ext-dev = "ecooptimizer.api.__main__:dev" [project.urls] -Documentation = "https://readthedocs.org" Repository = "https://github.com/ssm-lab/capstone--source-code-optimizer" "Bug Tracker" = "https://github.com/ssm-lab/capstone--source-code-optimizer/issues" +[tool.setuptools_scm] +write_to = "src/ecooptimizer/_version.py" +fallback_version = "0.1.0" + +[tool.setuptools] +packages = ["ecooptimizer"] + +[tool.setuptools.package-dir] +ecooptimizer = "src/ecooptimizer" + +[tool.setuptools.exclude-package-data] +"*" = ["docs/*", "tests/*", ".github/*"] + [tool.pytest.ini_options] norecursedirs = ["tests/temp*", "tests/input", "tests/_input_copies"] addopts = ["--basetemp=tests/temp_dir"] diff --git a/src/ecooptimizer/api/__main__.py b/src/ecooptimizer/api/__main__.py index 08bb0e6d..160d3efb 100644 --- a/src/ecooptimizer/api/__main__.py +++ b/src/ecooptimizer/api/__main__.py @@ -1,7 +1,7 @@ """Application entry point and server configuration for EcoOptimizer.""" +import argparse import logging -import sys import uvicorn from ecooptimizer.api.app import app @@ -27,7 +27,7 @@ def filter(self, record: logging.LogRecord) -> bool: logging.getLogger("uvicorn.access").addFilter(HealthCheckFilter()) -def start(): +def start(host: str = "127.0.0.1", port: int = 8000): """Starts the Uvicorn server with configured settings. Displays startup banner and handles different run modes. @@ -52,8 +52,8 @@ def start(): uvicorn.run( app, - host="127.0.0.1", - port=8000, + host=host, + port=port, log_level="info", access_log=True, timeout_graceful_shutdown=2, @@ -62,8 +62,14 @@ def start(): def main(): """Main entry point that sets mode based on command line arguments.""" - CONFIG["mode"] = "development" if "--dev" in sys.argv else "production" - start() + parser = argparse.ArgumentParser() + parser.add_argument("--dev", action="store_true", help="Run in development mode") + parser.add_argument("--port", type=int, default=8000, help="Port to run on") + parser.add_argument("--host", default="127.0.0.1", help="Host to bind to") + args = parser.parse_args() + + CONFIG["mode"] = "development" if args.dev else "production" + start(args.host, args.port) def dev(): diff --git a/src/ecooptimizer/api/error_handler.py b/src/ecooptimizer/api/error_handler.py index e29b0d56..75d8b5d1 100644 --- a/src/ecooptimizer/api/error_handler.py +++ b/src/ecooptimizer/api/error_handler.py @@ -2,7 +2,6 @@ import logging import os import stat -import traceback from fastapi import Request from fastapi.responses import JSONResponse @@ -69,10 +68,7 @@ async def global_error_handler(request: Request, e: Exception) -> JSONResponse: content={"detail": e.message}, ) else: - logger.error( - f"Unexpected error at {request.url.path}\n" - f"{''.join(traceback.format_exception(type(e), e, e.__traceback__))}" - ) + logger.error(f"Unexpected error at {request.url.path}", e) return JSONResponse( status_code=500, content={"detail": "Internal server error"},