diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..34b98d4 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,15 @@ +[paths] +source = + src + */site-packages + +[run] +branch = true +parallel = true +source = + guidellm + tests/unit + +[report] +show_missing = true +precision = 2 diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml index f8604d0..53ca774 100644 --- a/.github/workflows/development.yml +++ b/.github/workflows/development.yml @@ -1,43 +1,77 @@ -name: Development +--- +name: Development Branch Workflow on: pull_request: - branches: - - '**' + branches: ["**"] jobs: - unit-tests: + quality-checks: runs-on: ubuntu-latest strategy: matrix: - python: - - "3.12" - - "3.8" + python: ["3.9", "3.12"] steps: - uses: actions/checkout@v4 - - name: Set up Python + - name: Setup Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install dependencies run: pip install tox - - name: Run unit tests - run: tox -e test-unit -- -m "smoke or sanity" + - name: Run checks (quality, types, and pre-commit) + run: | + tox -e quality + tox -e types + pre-commit run --all-files + + unit-tests: + runs-on: ubuntu-latest + strategy: + matrix: + python: ["3.9", "3.12"] + steps: + - uses: actions/checkout@v4 + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + - name: Install dependencies + run: | + python -m pip install tox + - name: Run tests (smoke and sanity) + run: | + python -m tox -e test-unit -- -m "smoke or sanity" integration-tests: runs-on: ubuntu-latest strategy: matrix: - python: - - "3.12" - - "3.8" + python: ["3.9", "3.12"] steps: - uses: actions/checkout@v4 - - name: Set up Python + - name: Setup Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install dependencies - run: pip install tox - - name: Run integration tests - run: tox -e test-integration -- -m smoke + run: | + python -m pip install tox + - name: Run tests (smoke) + run: | + python -m tox -e test-integration -- -m smoke + + publish: + runs-on: ubuntu-latest + uses: neuralmagic/nm-actions/actions/python-tox-release@main + with: + publish_pypi: false + publish_nm_pypi: true + build_type: dev + secrets: + GCP_PROJECT: ${{ secrets.GCP_PROJECT }} + GCP_WORKLOAD_IDENTITY_PROVIDER: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} + GCP_NM_PYPI_SA: ${{ secrets.GCP_NM_PYPI_SA }} + NM_PYPI_SA: ${{ secrets.NM_PYPI_SA }} + PYPI_PUBLIC_USER: ${{ secrets.PYPI_PUBLIC_USER }} + PYPI_PUBLIC_AUTH: ${{ secrets.PYPI_PUBLIC_AUTH }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..68f150b --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,77 @@ +--- +name: Main Branch Workflow + +on: + push: + branches: [main] + +jobs: + quality-checks: + runs-on: ubuntu-latest + strategy: + matrix: + python: [ "3.9", "3.12" ] + steps: + - uses: actions/checkout@v4 + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + - name: Install dependencies + run: pip install tox + - name: Run checks (quality, types, and pre-commit) + run: | + tox -e quality + tox -e types + pre-commit run --all-files + + unit-tests: + runs-on: ubuntu-latest + strategy: + matrix: + python: ["3.9", "3.12"] + steps: + - uses: actions/checkout@v4 + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + - name: Install dependencies + run: | + python -m pip install tox + - name: Run tests with coverage@85% (smoke, sanity, and regression) + run: | + python -m tox -e cov-unit + + integration-tests: + runs-on: ubuntu-latest + strategy: + matrix: + python: ["3.9", "3.12"] + steps: + - uses: actions/checkout@v4 + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + - name: Install dependencies + run: | + python -m pip install tox + - name: Run tests (smoke) + run: | + python -m tox -e test-integration -- -m smoke + + publish: + runs-on: ubuntu-latest + uses: neuralmagic/nm-actions/actions/python-tox-release@main + with: + publish_pypi: false + publish_nm_pypi: true + build_type: nightly + secrets: + GCP_PROJECT: ${{ secrets.GCP_PROJECT }} + GCP_WORKLOAD_IDENTITY_PROVIDER: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} + GCP_NM_PYPI_SA: ${{ secrets.GCP_NM_PYPI_SA }} + NM_PYPI_SA: ${{ secrets.NM_PYPI_SA }} + PYPI_PUBLIC_USER: ${{ secrets.PYPI_PUBLIC_USER }} + PYPI_PUBLIC_AUTH: ${{ secrets.PYPI_PUBLIC_AUTH }} diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index bf7f34c..3c2b411 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -1,62 +1,50 @@ +--- name: Nightly on: schedule: - - cron: '0 0 * * *' # Runs at midnight every night + - cron: 0 0 * * * jobs: unit-tests: runs-on: ubuntu-latest strategy: matrix: - python: - - "3.12" - - "3.11" - - "3.10" - - "3.9" - - "3.8" + python: ["3.8", "3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 - - name: Set up Python + - name: Setup Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install dependencies - run: pip install tox - - name: Run unit tests - run: tox -e test-unit -- --cov-report=term-missing --cov --cov-fail-under=75 + run: | + python -m pip install tox + - name: Run tests (smoke, sanity, and regression) + run: | + python -m tox -e test-unit integration-tests: runs-on: ubuntu-latest strategy: matrix: - python: - - "3.12" - - "3.11" - - "3.10" - - "3.9" - - "3.8" + python: ["3.8", "3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 - - name: Set up Python + - name: Setup Python uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Install dependencies run: pip install tox - - name: Run integration tests + - name: Run tests (smoke and sanity) run: tox -e test-integration -- -m "smoke or sanity" e2e-tests: runs-on: ubuntu-latest strategy: matrix: - python: - - "3.12" - - "3.11" - - "3.10" - - "3.9" - - "3.8" + python: ["3.8", "3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 - name: Set up Python @@ -65,5 +53,48 @@ jobs: python-version: ${{ matrix.python }} - name: Install dependencies run: pip install tox - - name: Run e2e tests + - name: Run tests (smoke) run: tox -e test-e2e -- -m smoke + + check-publish: + runs-on: ubuntu-latest + needs: [ unit-tests, integration-tests, e2e-tests ] + steps: + - uses: actions/checkout@v4 + - name: Check changes (last nightly tag) + id: check_changes + run: | + git fetch origin + LAST_NIGHTLY_TAG=$(git describe --tags --match "nightly-*" --abbrev=0) + git diff --exit-code $LAST_NIGHTLY_TAG -- . || echo "changes" + - name: Set env + id: set_output + run: | + echo "::set-output name=changes_detected::$(git diff --exit-code $LAST_NIGHTLY_TAG -- . || echo 'true')" + + publish: + runs-on: ubuntu-latest + needs: [ check-publish ] + uses: neuralmagic/nm-actions/actions/python-tox-release@main + with: + publish_pypi: true + publish_nm_pypi: false + build_type: nightly + secrets: + GCP_PROJECT: ${{ secrets.GCP_PROJECT }} + GCP_WORKLOAD_IDENTITY_PROVIDER: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} + GCP_NM_PYPI_SA: ${{ secrets.GCP_NM_PYPI_SA }} + NM_PYPI_SA: ${{ secrets.NM_PYPI_SA }} + PYPI_PUBLIC_USER: ${{ secrets.PYPI_PUBLIC_USER }} + PYPI_PUBLIC_AUTH: ${{ secrets.PYPI_PUBLIC_AUTH }} + + tag: + runs-on: ubuntu-latest + needs: [ publish ] + if: ${{ needs.check-publish.outputs.changes_detected == 'true' }} + steps: + - uses: actions/checkout@v4 + - name: Tag nightly + run: | + git tag nightly-$(date +'%Y%m%d') + git push origin --tags diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 4ea5d8a..0000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: Publish Python distribution to PyPI - -on: - push: - tags: - - v* - -jobs: - build: - name: Build distribution - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.8" - - - name: Install pypa/build nad pypa/twine - run: >- - python3 -m pip install build twine --user - - - name: Build a binary wheel - run: python3 -m build - - publish-to-pypi: - name: Publish Python distribution to PyPI - needs: - - build - if: startsWith(github.ref, 'refs/tags/v') - runs-on: ubuntu-latest - steps: - - name: 🚀📦 Publish to PyPI - env: - TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} - TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - - run: python -m twine upload dist/* diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml deleted file mode 100644 index 95d44af..0000000 --- a/.github/workflows/quality.yml +++ /dev/null @@ -1,59 +0,0 @@ -name: Quality - -on: - push: - branches: - - main - pull_request: - branches: - - '**' - -jobs: - quality-check: - runs-on: ubuntu-latest - strategy: - matrix: - python: - - "3.12" - - "3.8" - steps: - - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python }} - - name: Install dependencies - run: pip install tox - - name: Run quality checks - run: tox -e quality - - type-check: - runs-on: ubuntu-latest - strategy: - matrix: - python: - - "3.12" - - "3.8" - steps: - - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: ${{ matrix.python }} - - name: Install dependencies - run: pip install tox - - name: Run type checks - run: tox -e types - - precommit-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 - with: - python-version: "3.8" - - name: Install pre-commit - run: pip install pre-commit - - name: Run pre-commit checks - run: pre-commit run --all-files diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d4fe249..ee77922 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,21 +1,17 @@ +--- name: Release on: push: - branches: - - release/** + tags: [v*] + branches: [release/**] jobs: unit-tests: runs-on: ubuntu-latest strategy: matrix: - python: - - "3.12" - - "3.11" - - "3.10" - - "3.9" - - "3.8" + python: ["3.12", "3.11", "3.10", "3.9", "3.8"] steps: - uses: actions/checkout@v4 - name: Set up Python @@ -31,12 +27,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python: - - "3.12" - - "3.11" - - "3.10" - - "3.9" - - "3.8" + python: ["3.12", "3.11", "3.10", "3.9", "3.8"] steps: - uses: actions/checkout@v4 - name: Set up Python @@ -52,12 +43,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python: - - "3.12" - - "3.11" - - "3.10" - - "3.9" - - "3.8" + python: ["3.12", "3.11", "3.10", "3.9", "3.8"] steps: - uses: actions/checkout@v4 - name: Set up Python @@ -68,3 +54,22 @@ jobs: run: pip install tox - name: Run e2e tests run: tox -e test-e2e -- --cov-report=term-missing --cov --cov-fail-under=75 + + publish: + name: Build & Publish the distribution + needs: [unit-tests, integration-tests, e2e-tests] + runs-on: ubuntu-latest + env: + GUIDELLM_BUILD_TYPE: release + GUIDELLM_BUILD_NUMBER: ${{ github.event.pull_request.number || github.run_number }} + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.8" + - name: Build and Publish Final Release + uses: neuralmagic/nm-actions/actions/publish_pypi@main + with: + publish_pypi: true + publish_pypi_internal: true diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml new file mode 100644 index 0000000..daf4e30 --- /dev/null +++ b/.github/workflows/staging.yml @@ -0,0 +1,74 @@ +--- +name: Staging + +on: + push: + branches: [release/**] + +jobs: + unit-tests: + runs-on: ubuntu-latest + strategy: + matrix: + python: ["3.12", "3.11", "3.10", "3.9", "3.8"] + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + - name: Install dependencies + run: pip install tox + - name: Run unit tests + run: tox -e test-unit -- --cov-report=term-missing --cov --cov-fail-under=75 + + integration-tests: + runs-on: ubuntu-latest + strategy: + matrix: + python: ["3.12", "3.11", "3.10", "3.9", "3.8"] + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + - name: Install dependencies + run: pip install tox + - name: Run integration tests + run: tox -e test-integration -- --cov-report=term-missing --cov --cov-fail-under=75 + + e2e-tests: + runs-on: ubuntu-latest + strategy: + matrix: + python: ["3.12", "3.11", "3.10", "3.9", "3.8"] + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python }} + - name: Install dependencies + run: pip install tox + - name: Run e2e tests + run: tox -e test-e2e -- --cov-report=term-missing --cov --cov-fail-under=75 + + publish: + name: Build & Publish the distribution + needs: [unit-tests, integration-tests, e2e-tests] + runs-on: ubuntu-latest + env: + GUIDELLM_BUILD_TYPE: release + GUIDELLM_BUILD_NUMBER: ${{ github.event.pull_request.number || github.run_number }} + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.8" + - name: Build and Publish a Candidate Release + uses: neuralmagic/nm-actions/actions/publish_pypi@main + with: + publish_pypi: false + publish_pypi_internal: true diff --git a/pyproject.toml b/pyproject.toml index 5854c77..4e295aa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -197,3 +197,10 @@ markers = [ "sanity: detailed tests to ensure major functions work correctly", "regression: tests to ensure that new changes do not break existing functionality" ] + +[tool.yamlfix] +whitelines = 1 +section_whitelines = 1 +line_length = 88 +none_representation = "null" +quote_representation = '"' diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index 13e1699..2dd1f57 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -9,6 +9,8 @@ ) +# FIX: This test is failing in case .env file or environment variables +# have some values defined. @pytest.mark.smoke() def test_default_settings(): settings = Settings() diff --git a/tox.ini b/tox.ini index d2fa64c..6ac57f3 100644 --- a/tox.ini +++ b/tox.ini @@ -11,6 +11,17 @@ commands = pytest tests/ {posargs} +[testenv:cov-unit] +usedevelop = true +description = Run unit tests with coverage +deps = + .[dev] +commands = + python -m pytest --cov=src tests/unit {posargs} + coverage html + coverage report --fail-under=85 + + [testenv:test-unit] description = Run unit tests deps = @@ -69,7 +80,6 @@ deps = loguru toml commands = - python utils/inject_build_props.py python -m build diff --git a/utils/__init__.py b/utils/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/utils/inject_build_props.py b/utils/inject_build_props.py deleted file mode 100644 index 74000dd..0000000 --- a/utils/inject_build_props.py +++ /dev/null @@ -1,79 +0,0 @@ -import os -import re -from datetime import datetime -from pathlib import Path - -import toml -from loguru import logger - - -def get_build_type(): - return os.getenv("GUIDELLM_BUILD_TYPE", "dev") - - -def get_build_number(): - return os.getenv("GUIDELLM_BUILD_NUMBER", "0") - - -def construct_project_name_and_version(build_type, build_number, current_version): - if not re.match(r"^\d+\.\d+\.\d+$", current_version): - raise ValueError( - f"Version '{current_version}' does not match the " - f"semantic versioning pattern '#.#.#'", - ) - - if build_type == "dev": - project_name = "guidellm_dev" - version = f"{current_version}.dev{build_number}" - elif build_type == "nightly": - project_name = "guidellm_nightly" - date_str = datetime.now().strftime("%Y%m%d") - version = f"{current_version}.{date_str}" - elif build_type == "release": - project_name = "guidellm" - version = current_version - else: - raise ValueError(f"Unknown build type: {build_type}") - - return project_name, version - - -def update_pyproject_toml(project_name, version): - try: - with Path("pyproject.toml").open() as file: - data = toml.load(file) - - data["project"]["name"] = project_name - data["project"]["version"] = version - - with Path("pyproject.toml").open("w") as file: - toml.dump(data, file) - - logger.info( - f"Updated project name to: {project_name} and version to: {version}", - ) - except (FileNotFoundError, toml.TomlDecodeError) as e: - logger.error(f"Error reading or writing pyproject.toml: {e}") - raise - - -def main(): - build_type = get_build_type() - build_number = get_build_number() - - with Path("pyproject.toml").open() as file: - pyproject_data = toml.load(file) - - current_version = pyproject_data["project"]["version"] - project_name, version = construct_project_name_and_version( - build_type, - build_number, - current_version, - ) - - if build_type != "release": - update_pyproject_toml(project_name, version) - - -if __name__ == "__main__": - main()