diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index e871931..9cbc962 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,6 +1,15 @@ -SUMMARY: -"please provide a brief summary" +## Summary: -TEST PLAN: -"please outline how the changes were tested" +Short paragraph detailing the pull request changes and reasoning in addition to any relevant context. +## Details: + +- Detailed list of changes made in the pull request + +## Test Plan: + +- Detailed list of steps to test the changes made in the pull request + +## Related Issues: + +- List of related issues or other pull requests; ex: "Fixes #1234" \ No newline at end of file diff --git a/.github/workflows/hygiene.yml b/.github/workflows/hygiene.yml new file mode 100644 index 0000000..4709083 --- /dev/null +++ b/.github/workflows/hygiene.yml @@ -0,0 +1,19 @@ +--- +name: hygiene checks + +on: + push: null + +jobs: + quality: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Install dependencies + run: pip install tox + - name: Run quality checks + run: tox -e quality diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fd919b4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,164 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +*.swp + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/latest/usage/project/#working-with-version-control +.pdm.toml +.pdm-python +.pdm-build/ + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ diff --git a/.mdformat.toml b/.mdformat.toml new file mode 100644 index 0000000..36d8d6d --- /dev/null +++ b/.mdformat.toml @@ -0,0 +1,3 @@ +wrap = "no" +number = true +end_of_line = "lf" diff --git a/.yamlfix.toml b/.yamlfix.toml new file mode 100644 index 0000000..a6e2298 --- /dev/null +++ b/.yamlfix.toml @@ -0,0 +1,17 @@ +allow_duplicate_keys = false +comments_min_spaces_from_content = 2 +comments_require_starting_space = true +whitelines = 1 +comments_whitelines = 1 +section_whitelines = 1 +explicit_start = true +sequence_style = "flow_style" +indent_mapping = 2 +ident_offset = 2 +indent_sequence = 4 +line_length = 88 +none_representation = "null" +quote_basic_values = false +quote_keys_and_basic_values = false +quote_representation = "'" +preserve_quotes = false diff --git a/README.md b/README.md index 3b4a31a..11e68fc 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,79 @@ -# Neural Magic Actions -Actions for Neural Magic GHA +# NM GitHub Actions + +### Curated collection of commonly used GitHub Actions and workflows within Neural Magic's and vLLM's Processes + +## Overview + +This repository hosts a collection of GitHub Actions developed and maintained by Neural Magic. These actions aim to improve automation, CI/CD pipelines, and workflow orchestration. They are designed for performance, scalability, and ease of use and support a range of deployment, testing, and optimization workflows. + +### Key Actions + +- Coming soon + +Each action supports various configurable arguments to tailor the workflows to your project needs. + +## Getting Started + +To start using one of our GitHub Actions, include the relevant action within your workflow configuration file: + +```yaml +name: Example Workflow +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v2 + + - name: ACTION + uses: neuralmagic/nm-actions/ACTION@main + with: + config-file: .eslintrc +``` + +This example shows how to integrate an NM action into a workflow. Visit each action's README for more configuration options and examples. + +## Development + +To contribute to NM Public Actions, follow these steps: + +1. Fork the repository. +2. Create a new branch. +3. Make your changes. +4. `pip install tox` and run `tox -e quality` to ensure your changes meet the quality standards and `tox -e style` to enforce the style guide and formatting. +5. Submit a pull request. + +## Resources + +### Documentation + +Each GitHub Action contains a `README.md` alongside any supporting documents. To learn more, dive into the action you'd like to use. + +### Releases + +Visit our [GitHub Releases page](https://github.com/neuralmagic/nm-actions/releases) and review the release notes to stay updated with the latest releases. + +### License + +NM Public Actions are licensed under the [Apache License 2.0](https://github.com/neuralmagic/guidellm/blob/main/LICENSE). + +## Community + +### Contribute + +We appreciate contributions to the code, examples, integrations, documentation, bug reports, and feature requests! To contribute: + +1. Fork the repository. +2. Make your changes. +3. Submit a pull request. + +### Join + +We invite you to join our growing community of developers, researchers, and enthusiasts passionate about LLMs and optimization. Whether you're looking for help, want to share your own experiences, or stay up to date with the latest developments, there are plenty of ways to get involved: + +- [**Neural Magic Community Slack**](https://neuralmagic.com/community/) - Join our Slack channel to connect with other NM users and developers. Ask questions, share your work, and get real-time support. +- [**GitHub Issues**](https://github.com/neuralmagic/nm-actions/issues) - Report bugs, request features, or browse existing issues. Your feedback helps us improve. +- [**Subscribe to Updates**](https://neuralmagic.com/subscribe/) - Sign up for the latest news, announcements, and updates about NM Public Actions, webinars, events, and more. +- [**Contact Us**](http://neuralmagic.com/contact/) - Use our contact form for general questions about Neural Magic or NM Public Actions. diff --git a/actions/build-ml-whl/action.yaml b/actions/build-ml-whl/action.yaml index 2e2bcea..43e92ba 100644 --- a/actions/build-ml-whl/action.yaml +++ b/actions/build-ml-whl/action.yaml @@ -1,69 +1,71 @@ -name: "Build Wheel" -description: "Build wheel for ML repos e.g. sparseml, compressed-tensors" +--- +name: Build Wheel +description: Build wheel for ML repos e.g. sparseml, compressed-tensors inputs: - dev: - description: 'If the build is a dev build' - required: false - default: false - release: - description: 'If the build is a release build' - required: false - default: false - name: - description: 'Name to append to the wheel' - required: false - venv: - description: 'path of virtualenv if using it' - required: false + dev: + description: If the build is a dev build + required: false + default: false + release: + description: If the build is a release build + required: false + default: false + name: + description: Name to append to the wheel + required: false + venv: + description: path of virtualenv if using it + required: false + outputs: - whlname: - description: 'wheel filename' - value: ${{ steps.build.outputs.whlname }} - tarname: - description: 'tar.gz filename' - value: ${{ steps.build.outputs.tarname }} - status: - description: 'status of wheel build' - value: ${{ steps.build.outputs.status }} + whlname: + description: wheel filename + value: ${{ steps.build.outputs.whlname }} + tarname: + description: tar.gz filename + value: ${{ steps.build.outputs.tarname }} + status: + description: status of wheel build + value: ${{ steps.build.outputs.status }} # can we just pass in build args instead of updating the variables in version.py? runs: - using: "composite" + using: composite steps: - name: build id: build shell: bash - run: | - if [[ ! -z "${{ inputs.venv }}" ]]; then - source ${{ inputs.venv }}/bin/activate - fi - pip install wheel - name="${{ inputs.name }}" - ver_file=$(find . -type f -name "version.py") - if ${{ inputs.release }}; then - sed -i 's/is_release = False/is_release = True/g' ${ver_file} - sed -i 's/build_type = "dev"/build_type = "release"/g' ${ver_file} - elif ${{ inputs.dev }}; then - sed -i 's/is_dev = False/is_dev = True/g' ${ver_file} - sed -i 's/dev_number = None/dev_number = '"$name"'/g' ${ver_file} - else - sed -i 's/build_type = "dev"/build_type = "nightly"/g' ${ver_file} - fi - status=0 - makefile_path=$(find . -type f -name "Makefile") - cd $(dirname ${makefile_path}) - make -B build || status=$? - ls dist/; mkdir build-results - echo " - - - - - " > build-results/result.xml - echo "=========== Build log ===========" - echo "$status" - echo "whlname=$(find dist -name '*.whl' -exec basename {} \;)" >> "$GITHUB_OUTPUT" - echo "tarname=$(find dist -name '*.tar.gz' -exec basename {} \;)" >> "$GITHUB_OUTPUT" - echo "status=${status}" >> "$GITHUB_OUTPUT" - exit ${status} + run: |- + if [[ ! -z "${{ inputs.venv }}" ]]; then + source ${{ inputs.venv }}/bin/activate + fi + pip install wheel + name="${{ inputs.name }}" + ver_file=$(find . -type f -name "version.py") + if ${{ inputs.release }}; then + sed -i 's/is_release = False/is_release = True/g' ${ver_file} + sed -i 's/build_type = "dev"/build_type = "release"/g' ${ver_file} + elif ${{ inputs.dev }}; then + sed -i 's/is_dev = False/is_dev = True/g' ${ver_file} + sed -i 's/dev_number = None/dev_number = '"$name"'/g' ${ver_file} + else + sed -i 's/build_type = "dev"/build_type = "nightly"/g' ${ver_file} + fi + status=0 + makefile_path=$(find . -type f -name "Makefile") + cd $(dirname ${makefile_path}) + make -B build || status=$? + ls dist/; mkdir build-results + echo " + + + + + " > build-results/result.xml + echo "=========== Build log ===========" + echo "$status" + echo "whlname=$(find dist -name '*.whl' -exec basename {} \;)" >> "$GITHUB_OUTPUT" + echo "tarname=$(find dist -name '*.tar.gz' -exec basename {} \;)" >> "$GITHUB_OUTPUT" + echo "status=${status}" >> "$GITHUB_OUTPUT" + exit ${status} diff --git a/actions/create-virtualenv/action.yml b/actions/create-virtualenv/action.yml index c71976f..030ecd5 100644 --- a/actions/create-virtualenv/action.yml +++ b/actions/create-virtualenv/action.yml @@ -1,22 +1,25 @@ +--- name: create virtualenv -description: 'create virtualenv using input name' +description: create virtualenv using input name + inputs: venv: - description: 'name of virtualenv' + description: name of virtualenv required: true + outputs: penv: - description: 'path of the created virtualenv' + description: path of the created virtualenv value: ${{ steps.env.outputs.penv }} + runs: using: composite steps: - - id: env - run: | - # install virtualenv - python -m pip install virtualenv - python -m virtualenv ${{ inputs.venv }} - pwd; ls -al - echo "penv=$(pwd)/${{ inputs.venv }}" >> "$GITHUB_OUTPUT" - shell: bash - + - id: env + run: | + # install virtualenv + python -m pip install virtualenv + python -m virtualenv ${{ inputs.venv }} + pwd; ls -al + echo "penv=$(pwd)/${{ inputs.venv }}" >> "$GITHUB_OUTPUT" + shell: bash diff --git a/actions/find-asset/README.md b/actions/find-asset/README.md index 320858a..d84010e 100644 --- a/actions/find-asset/README.md +++ b/actions/find-asset/README.md @@ -2,7 +2,6 @@ Used to find asset in downloaded build assets folder. The search is done via the bash utility `find`, so REGEX is suggested. Outputs REPO relative path to found asset. If nothing is found, then output will be empty. - ## Usage ### Example diff --git a/actions/find-asset/action.yml b/actions/find-asset/action.yml index 0ec87ef..15a8315 100644 --- a/actions/find-asset/action.yml +++ b/actions/find-asset/action.yml @@ -1,16 +1,20 @@ +--- name: download run assets from GCP -description: 'find asset using specified identifier and return REPO relative filepath' +description: find asset using specified identifier and return REPO relative filepath + inputs: run_id: - description: 'GHA run id of build' + description: GHA run id of build required: true asset_identifier: - description: 'REGEX that is used to find the asset.' + description: REGEX that is used to find the asset. required: true + outputs: asset: - description: 'REPO relative path to downloaded "whl"' + description: REPO relative path to downloaded "whl" value: ${{ steps.find.outputs.asset }} + runs: using: composite steps: diff --git a/actions/gcp-download-assets/README.md b/actions/gcp-download-assets/README.md index 96ff939..bf17b85 100644 --- a/actions/gcp-download-assets/README.md +++ b/actions/gcp-download-assets/README.md @@ -2,13 +2,10 @@ Used to download build assets from GCP. Assets are identified by the Github Actions Run that generated them. The download is recusive and will download whatever was placed under the "run id" prefix. - **Requires "runner" to already be authenticated.** - **Requires access to Github secret `GCP_BUILD_ASSETS`** - ## Usage ### Example diff --git a/actions/gcp-download-assets/action.yml b/actions/gcp-download-assets/action.yml index 1cb5ccc..04a3788 100644 --- a/actions/gcp-download-assets/action.yml +++ b/actions/gcp-download-assets/action.yml @@ -1,16 +1,20 @@ +--- name: download run assets from GCP -description: 'recursively downloads build assets from specified GHA run' +description: recursively downloads build assets from specified GHA run + inputs: bucket_source: - description: 'bucket source, location from which assets are downloaded' + description: bucket source, location from which assets are downloaded required: true run_id: - description: 'GHA run id of build' + description: GHA run id of build required: true + outputs: asset: - description: 'REPO relative path to downloaded "whl"' + description: REPO relative path to downloaded "whl" value: ${{ steps.download.outputs.asset }} + runs: using: composite steps: diff --git a/actions/gcp-upload-asset/README.md b/actions/gcp-upload-asset/README.md index 4cf8577..9ac2bac 100644 --- a/actions/gcp-upload-asset/README.md +++ b/actions/gcp-upload-asset/README.md @@ -4,7 +4,6 @@ Used to upload build asset to GCP. Requires that the assets are available locall **Requires "runner" to already be authenticated.** - ## Usage ### Example diff --git a/actions/gcp-upload-asset/action.yml b/actions/gcp-upload-asset/action.yml index 0dc6632..c5ed70f 100644 --- a/actions/gcp-upload-asset/action.yml +++ b/actions/gcp-upload-asset/action.yml @@ -1,12 +1,15 @@ +--- name: upload asset to GCP -description: 'upload specified asset to specified bucket target' +description: upload specified asset to specified bucket target + inputs: bucket_target: - description: 'bucket target, result will be object at "bucket_target/asset"' + description: bucket target, result will be object at "bucket_target/asset" required: true asset: - description: 'REPO relative path for asset to be uploaded' + description: REPO relative path for asset to be uploaded required: true + runs: using: composite steps: diff --git a/actions/install-automation-components/action.yml b/actions/install-automation-components/action.yml index fa2d792..8f02b78 100644 --- a/actions/install-automation-components/action.yml +++ b/actions/install-automation-components/action.yml @@ -1,3 +1,4 @@ +--- name: Install Automation Components description: Install various components used during automation @@ -5,7 +6,7 @@ runs: using: composite steps: - shell: bash - run: | + run: |- # packages sudo apt-get update --fix-missing sudo apt-get install -y curl git-all wget jq diff --git a/actions/install-testmo/action.yml b/actions/install-testmo/action.yml index 32edf22..2aa2d99 100644 --- a/actions/install-testmo/action.yml +++ b/actions/install-testmo/action.yml @@ -1,3 +1,4 @@ +--- name: Install Testmo CLI tool description: Install Testmo including requirements (Node.js) @@ -6,7 +7,7 @@ runs: steps: - uses: actions/setup-node@v4 with: - node-version: 'lts/*' + node-version: lts/* - shell: bash - run: | + run: |- npm install --global @testmo/testmo-cli diff --git a/actions/install-whl/action.yml b/actions/install-whl/action.yml index 9dc729f..571c35d 100644 --- a/actions/install-whl/action.yml +++ b/actions/install-whl/action.yml @@ -1,15 +1,18 @@ +--- name: install whl -description: 'installs found whl based on python version into specified venv' +description: installs found whl based on python version into specified venv + inputs: venv: - description: "path of virtualenv" + description: path of virtualenv required: true name: - description: "name contained in the whl name, e.g. llmcompressor, compressed_tensors etc" + description: name contained in the whl name, e.g. llmcompressor, compressed_tensors etc required: true extra: - description: "extra dependency of the whl to install" + description: extra dependency of the whl to install required: false + runs: using: composite steps: diff --git a/actions/publish-whl/action.yml b/actions/publish-whl/action.yml index 14f8875..12345e8 100644 --- a/actions/publish-whl/action.yml +++ b/actions/publish-whl/action.yml @@ -1,19 +1,23 @@ +--- name: publish whl to public pypi -description: 'upload specified whl to public pypi' +description: upload specified whl to public pypi + inputs: username: - description: 'username associated with upload' + description: username associated with upload required: true password: - description: 'password associated with username' + description: password associated with username required: true whl: - description: 'filepath of whl to put pushed' + description: filepath of whl to put pushed required: true + outputs: status: - description: 'return status from upload' + description: return status from upload value: ${{ steps.upload.outputs.status }} + runs: using: composite steps: diff --git a/actions/python-tox-release/action.yml b/actions/python-tox-release/action.yml index 3e105da..6ad407a 100644 --- a/actions/python-tox-release/action.yml +++ b/actions/python-tox-release/action.yml @@ -1,13 +1,15 @@ -name: 'Python Tox Release Action' -description: 'A reusable GitHub Action to finalize pyproject.toml, build Python package, and publish to PyPI' +--- +name: Python Tox Release Action +description: A reusable GitHub Action to finalize pyproject.toml, build Python package, and + publish to PyPI inputs: publish_pypi: - description: 'Boolean to push to public PyPI' + description: Boolean to push to public PyPI required: true type: boolean publish_nm_pypi: - description: 'Boolean to push to Neural Magic internal PyPI' + description: Boolean to push to Neural Magic internal PyPI required: true type: boolean build_type: @@ -17,28 +19,25 @@ inputs: outputs: wheel: - description: 'The built wheel output from the build' + description: The built wheel output from the build value: ${{ steps.build.outputs.wheel }} tar: - description: 'The built tar output from the build' + description: The built tar output from the build value: ${{ steps.build.outputs.tar }} runs: - using: 'composite' + using: composite steps: - name: Checkout code uses: actions/checkout@v4 - - name: Set up Python uses: actions/setup-python@v5 with: python-version: 3.10 - - name: Install dependencies run: | python -m pip install --upgrade pip python -m pip install ./ - - name: Determine Build Number if: ${{ inputs.build_type }} == 'dev' id: get_pr_number @@ -50,11 +49,9 @@ runs: echo "Using PR number as build number: ${{ github.event.pull_request.number }}" echo "BUILD_NUMBER=${{ github.event.pull_request.number }}" >> $GITHUB_ENV fi - - name: Finalize package toml run: | toml_finalizer --build_type=${{ inputs.build_type }} --dev_build_number=${{ env.BUILD_NUMBER }} - - name: Build package id: build run: | @@ -63,7 +60,6 @@ runs: echo "TAR=$(find dist -name '*.tar.gz')" >> $GITHUB_ENV echo "wheel=${{ env.WHEEL }}" >> $GITHUB_OUTPUT echo "tar=${{ env.TAR }}" >> $GITHUB_OUTPUT - - name: Authenticate to GCP if: ${{ inputs.publish_nm_pypi }} uses: google-github-actions/auth@v2.1.3 @@ -71,14 +67,12 @@ runs: project_id: ${{ secrets.GCP_PROJECT }} workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.NM_PYPI_SA }} - - name: Upload to Internal PyPI if: ${{ inputs.publish_nm_pypi }} uses: neuralmagic/nm-actions/actions/gcp-upload-asset@main with: bucket_target: ${{ secrets.GCP_NM_PYPI_DIST }} asset: ${{ env.WHEEL }} - - name: Publish to Public PyPI if: ${{ inputs.publish_pypi }} uses: neuralmagic/nm-actions/actions/publish-whl@main diff --git a/actions/s3_pull/action.yaml b/actions/s3_pull/action.yaml index 1ad9132..7636ebe 100644 --- a/actions/s3_pull/action.yaml +++ b/actions/s3_pull/action.yaml @@ -1,19 +1,21 @@ -name: "Pull PyPi Wheel" -description: "Pull PyPi wheel" +--- +name: Pull PyPi Wheel +description: Pull PyPi wheel inputs: filename: - description: 'File to pull from s3 bucket' + description: File to pull from s3 bucket required: true dst: - description: 'Folder to pull down wheel file' + description: Folder to pull down wheel file required: false - default: true + default: true + runs: - using: "composite" + using: composite steps: - name: Push to s3 shell: bash - run: | - aws s3 cp ${{ inputs.filename }} ${{ inputs.dst }} - exitCode=$? + run: |- + aws s3 cp ${{ inputs.filename }} ${{ inputs.dst }} + exitCode=$? diff --git a/actions/s3_push/action.yaml b/actions/s3_push/action.yaml index b279029..9ee277b 100644 --- a/actions/s3_push/action.yaml +++ b/actions/s3_push/action.yaml @@ -1,34 +1,36 @@ -name: "Push PyPi Wheel" -description: "Push PyPi wheel" +--- +name: Push PyPi Wheel +description: Push PyPi wheel inputs: filename: - description: 'File to push to s3' + description: File to push to s3 required: true internal: - description: 'Push to internal pypi or not' + description: Push to internal pypi or not required: false - default: true + default: true bucket_name: type: string required: true + outputs: wheel: - description: 'Full path of the wheel' + description: Full path of the wheel value: ${{ steps.push-s3.outputs.wheel }} runs: - using: "composite" + using: composite steps: - name: Push to s3 id: push-s3 shell: bash - run: | - if ${{ inputs.internal }}; then - dst=s3://${{ inputs.bucket_name }}/internal/${{ github.event.repository.name }}/ - else - dst=s3://${{ inputs.bucket_name }}/${{ github.event.repository.name }}/ - fi - echo "wheel=$dst$(basename ${{ inputs.filename }})" >> $GITHUB_OUTPUT - aws s3 cp ${{ inputs.filename }} $dst - exitCode=$? + run: |- + if ${{ inputs.internal }}; then + dst=s3://${{ inputs.bucket_name }}/internal/${{ github.event.repository.name }}/ + else + dst=s3://${{ inputs.bucket_name }}/${{ github.event.repository.name }}/ + fi + echo "wheel=$dst$(basename ${{ inputs.filename }})" >> $GITHUB_OUTPUT + aws s3 cp ${{ inputs.filename }} $dst + exitCode=$? diff --git a/actions/set-cuda-env/action.yml b/actions/set-cuda-env/action.yml index 759f7b2..05195cb 100644 --- a/actions/set-cuda-env/action.yml +++ b/actions/set-cuda-env/action.yml @@ -1,12 +1,14 @@ +--- name: set cuda env -description: 'sets environment variables related to CUDA' +description: sets environment variables related to CUDA + runs: using: composite steps: - - run: | - echo "TORCH_CUDA_ARCH_LIST=7.0 7.5 8.0 8.6 8.9 9.0+PTX" >> $GITHUB_ENV - echo "PATH=/usr/local/cuda-12.1/bin:${PATH}" >> $GITHUB_ENV - echo "LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64::/usr/local/cuda-12.1/lib64:" >> $GITHUB_ENV - env: + - run: | + echo "TORCH_CUDA_ARCH_LIST=7.0 7.5 8.0 8.6 8.9 9.0+PTX" >> $GITHUB_ENV + echo "PATH=/usr/local/cuda-12.1/bin:${PATH}" >> $GITHUB_ENV + echo "LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64::/usr/local/cuda-12.1/lib64:" >> $GITHUB_ENV + env: HF_TOKEN_SECRET: ${{ inputs.hf_token }} - shell: bash + shell: bash diff --git a/actions/set-python/README.md b/actions/set-python/README.md index 381ee17..35b76f3 100644 --- a/actions/set-python/README.md +++ b/actions/set-python/README.md @@ -12,14 +12,14 @@ This action requires `pyenv` to be installed. ### Inputs -* `python`: the python version to use -* `venv`: the base name for the virtual environment +- `python`: the python version to use +- `venv`: the base name for the virtual environment ### Outputs -* `version`: the full Python version (from `python --version`) -* `venv_path`: the full path to the virtual environment’s base folder - * ex. `source ${{ steps.set_python.outputs.venv_path }}/bin/activate` +- `version`: the full Python version (from `python --version`) +- `venv_path`: the full path to the virtual environment’s base folder + - ex. `source ${{ steps.set_python.outputs.venv_path }}/bin/activate` ### Example diff --git a/actions/set-python/action.yml b/actions/set-python/action.yml index b023c83..fe0bb47 100644 --- a/actions/set-python/action.yml +++ b/actions/set-python/action.yml @@ -1,3 +1,4 @@ +--- name: Set Python With Pyenv description: Sets the Python version with pyenv and creates a virtual environment @@ -22,16 +23,13 @@ runs: steps: - id: set_python shell: bash - run: | + run: |- pyenv local ${{ inputs.python }} - COMMIT=${{ github.sha }} VENV="${{ inputs.venv }}-${COMMIT:0:7}" pyenv virtualenv --force "$VENV" - VENV_PATH="$(pyenv root)/versions/${{ inputs.python }}/envs/$VENV" source "$VENV_PATH/bin/activate" VERSION=$(python --version) - echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "venv_path=$VENV_PATH" >> "$GITHUB_OUTPUT" diff --git a/actions/summary-build/action.yml b/actions/summary-build/action.yml index 36cd333..bc35780 100644 --- a/actions/summary-build/action.yml +++ b/actions/summary-build/action.yml @@ -1,32 +1,35 @@ +--- name: build summary -description: 'creates a GHA run summary' +description: creates a GHA run summary + inputs: label: - description: 'GHA runner label' + description: GHA runner label required: true gitref: - description: 'git commit hash or branch name' + description: git commit hash or branch name required: true whl_status: - description: 'status from build step' + description: status from build step required: true + runs: using: composite steps: - - run: | - if [ ${{ inputs.whl_status }} -eq 0 ]; then - # green check - WHL_EMOJI=$(echo -e "\xE2\x9C\x85") - else - # red x - WHL_EMOJI=$(echo -e "\xE2\x9D\x8C") - fi - echo "" - echo "| Parameter | |" >> $GITHUB_STEP_SUMMARY - echo "|---|---|" >> $GITHUB_STEP_SUMMARY - echo "| label: | \`${{ inputs.label }}\` |" >> $GITHUB_STEP_SUMMARY - echo "| git sha: | \`${{ github.sha }}\` |" >> $GITHUB_STEP_SUMMARY - echo "| github actor: | '${{ github.actor }}' |" >> $GITHUB_STEP_SUMMARY - echo "| gitref: | '${{ inputs.gitref }}' |" >> $GITHUB_STEP_SUMMARY - echo "| whl: | ${WHL_EMOJI} |" >> $GITHUB_STEP_SUMMARY - shell: bash + - run: | + if [ ${{ inputs.whl_status }} -eq 0 ]; then + # green check + WHL_EMOJI=$(echo -e "\xE2\x9C\x85") + else + # red x + WHL_EMOJI=$(echo -e "\xE2\x9D\x8C") + fi + echo "" + echo "| Parameter | |" >> $GITHUB_STEP_SUMMARY + echo "|---|---|" >> $GITHUB_STEP_SUMMARY + echo "| label: | \`${{ inputs.label }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| git sha: | \`${{ github.sha }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| github actor: | '${{ github.actor }}' |" >> $GITHUB_STEP_SUMMARY + echo "| gitref: | '${{ inputs.gitref }}' |" >> $GITHUB_STEP_SUMMARY + echo "| whl: | ${WHL_EMOJI} |" >> $GITHUB_STEP_SUMMARY + shell: bash diff --git a/actions/summary-test/action.yml b/actions/summary-test/action.yml index e9810e6..310a533 100644 --- a/actions/summary-test/action.yml +++ b/actions/summary-test/action.yml @@ -1,45 +1,48 @@ +--- name: test summary -description: 'creates a neuralmagic GHA run summary' +description: creates a neuralmagic GHA run summary + inputs: test_label: - description: 'GHA runner label' + description: GHA runner label required: true gitref: - description: 'git commit hash or branch name' + description: git commit hash or branch name required: true testmo_run_url: - description: 'testmo URL for this particular run' + description: testmo URL for this particular run required: true python: - description: 'python version info' + description: python version info required: true whl: - description: 'whl file tested' + description: whl file tested required: true test_status: - description: 'status from test step' + description: status from test step required: true + runs: using: composite steps: - - run: | - if [ ${{ inputs.test_status }} -eq 0 ]; then - # green check - TEST_EMOJI=$(echo -e "\xE2\x9C\x85") - else - # red x - TEST_EMOJI=$(echo -e "\xE2\x9D\x8C") - fi - echo "| Parameter | |" >> $GITHUB_STEP_SUMMARY - echo "|---|---|" >> $GITHUB_STEP_SUMMARY - echo "| label: | \`${{ inputs.test_label }}\` |" >> $GITHUB_STEP_SUMMARY - echo "| git sha: | \`${{ github.sha }}\` |" >> $GITHUB_STEP_SUMMARY - echo "| github actor: | '${{ github.actor }}' |" >> $GITHUB_STEP_SUMMARY - echo "| gitref: | '${{ inputs.gitref }}' |" >> $GITHUB_STEP_SUMMARY - echo "| branch name: | '${{ github.ref_name }}' |" >> $GITHUB_STEP_SUMMARY - echo "| python: | ${{ inputs.python }} |" >> $GITHUB_STEP_SUMMARY - echo "| whl: | ${{ inputs.whl }} |" >> $GITHUB_STEP_SUMMARY - echo "| test: | ${TEST_EMOJI} |" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo "#### TestMo URL: ${{ inputs.testmo_run_url }}" >> $GITHUB_STEP_SUMMARY - shell: bash + - run: | + if [ ${{ inputs.test_status }} -eq 0 ]; then + # green check + TEST_EMOJI=$(echo -e "\xE2\x9C\x85") + else + # red x + TEST_EMOJI=$(echo -e "\xE2\x9D\x8C") + fi + echo "| Parameter | |" >> $GITHUB_STEP_SUMMARY + echo "|---|---|" >> $GITHUB_STEP_SUMMARY + echo "| label: | \`${{ inputs.test_label }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| git sha: | \`${{ github.sha }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| github actor: | '${{ github.actor }}' |" >> $GITHUB_STEP_SUMMARY + echo "| gitref: | '${{ inputs.gitref }}' |" >> $GITHUB_STEP_SUMMARY + echo "| branch name: | '${{ github.ref_name }}' |" >> $GITHUB_STEP_SUMMARY + echo "| python: | ${{ inputs.python }} |" >> $GITHUB_STEP_SUMMARY + echo "| whl: | ${{ inputs.whl }} |" >> $GITHUB_STEP_SUMMARY + echo "| test: | ${TEST_EMOJI} |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "#### TestMo URL: ${{ inputs.testmo_run_url }}" >> $GITHUB_STEP_SUMMARY + shell: bash diff --git a/actions/testmo-run-complete/action.yml b/actions/testmo-run-complete/action.yml index 0f89cd8..6972287 100644 --- a/actions/testmo-run-complete/action.yml +++ b/actions/testmo-run-complete/action.yml @@ -1,17 +1,20 @@ +--- name: complete testmo run -description: 'complete neuralmagic testmo run' +description: complete neuralmagic testmo run + inputs: testmo_url: - description: 'testmo URL' + description: testmo URL required: true testmo_token: - description: 'testmo token' + description: testmo token required: true testmo_run_id: - description: 'testmo run id' + description: testmo run id required: true + runs: - using: "composite" + using: composite steps: - run: | echo "completing TESTMO run ..." diff --git a/actions/testmo-run-create/action.yml b/actions/testmo-run-create/action.yml index 08208e6..2ec836f 100644 --- a/actions/testmo-run-create/action.yml +++ b/actions/testmo-run-create/action.yml @@ -1,27 +1,31 @@ +--- name: create testmo run -description: 'create neuralmagic testmo run and return its ID' +description: create neuralmagic testmo run and return its ID + inputs: testmo_url: - description: 'testmo URL' + description: testmo URL required: true testmo_token: - description: 'testmo token' + description: testmo token required: true source: - description: "source for testmo, e.g. 'build-test'" + description: source for testmo, e.g. 'build-test' required: true project_id: - description: "testmo project id" + description: testmo project id required: true run_name: - description: 'run name' + description: run name required: false + outputs: id: - description: 'testmo run id' + description: testmo run id value: ${{ steps.testmo_id.outputs.id }} + runs: - using: "composite" + using: composite steps: - name: create run id: testmo_id diff --git a/actions/testmo-run-submit-thread/action.yml b/actions/testmo-run-submit-thread/action.yml index b63bb57..3da964e 100644 --- a/actions/testmo-run-submit-thread/action.yml +++ b/actions/testmo-run-submit-thread/action.yml @@ -1,27 +1,31 @@ +--- name: submit results to testmo run -description: 'asynchronously submit step results to neuralmagic testmo run' +description: asynchronously submit step results to neuralmagic testmo run + inputs: testmo_url: - description: 'testmo URL' + description: testmo URL required: true testmo_token: - description: 'testmo token' + description: testmo token required: true testmo_run_id: - description: 'testmo run id' + description: testmo run id required: true results: - description: "directory of JUnit '*.xml' formatted result files" + description: directory of JUnit '*.xml' formatted result files required: true step_status: - description: 'status of reported step' + description: status of reported step required: true + outputs: status: - description: "status of updating testmo. if there was no update, then 'success' is returned." + description: status of updating testmo. if there was no update, then 'success' is returned. value: ${{ steps.submit_thread.outputs.status }} + runs: - using: "composite" + using: composite steps: - id: submit_thread run: | diff --git a/actions/upload-whl/action.yml b/actions/upload-whl/action.yml index 044e38d..547fd80 100644 --- a/actions/upload-whl/action.yml +++ b/actions/upload-whl/action.yml @@ -1,25 +1,29 @@ +--- name: upload whl -description: 'upload specified whl to pypi server' +description: upload specified whl to pypi server + inputs: server: - description: 'pypi server ip' + description: pypi server ip required: true port: - description: 'port to use for pypi server, e.g. 8080' + description: port to use for pypi server, e.g. 8080 required: true username: - description: 'username associated with upload' + description: username associated with upload required: true password: - description: 'password associated with username' + description: password associated with username required: true whl: - description: 'filepath of whl to put pushed' + description: filepath of whl to put pushed required: true + outputs: status: - description: 'return status from upload' + description: return status from upload value: ${{ steps.upload.outputs.status }} + runs: using: composite steps: diff --git a/actions/verify-python/action.yml b/actions/verify-python/action.yml index 1ce9475..b0fe0be 100644 --- a/actions/verify-python/action.yml +++ b/actions/verify-python/action.yml @@ -1,13 +1,17 @@ +--- name: verify python -description: 'verify env python version if matching the expected version' +description: verify env python version if matching the expected version + inputs: python-version: - description: "version of python to verify, e.g. 3.10" + description: version of python to verify, e.g. 3.10 required: true + outputs: version: - description: "result from 'python --version'" + description: result from 'python --version' value: ${{ steps.env_python.outputs.version }} + runs: using: composite steps: diff --git a/mypy.ini b/mypy.ini new file mode 100644 index 0000000..00b457e --- /dev/null +++ b/mypy.ini @@ -0,0 +1,12 @@ +[mypy] +files = ["src/guidellm", "tests"] +python_version = '3.8' +warn_redundant_casts = true +warn_unused_ignores = false +show_error_codes = true +namespace_packages = true +exclude = ["venv", ".tox"] + +# Silence "type import errors" as our 3rd-party libs does not have types +# Check: https://mypy.readthedocs.io/en/latest/config_file.html#import-discovery +follow_imports = 'silent' diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 0000000..c7a04fc --- /dev/null +++ b/ruff.toml @@ -0,0 +1,69 @@ +line-length = 88 +indent-width = 4 +exclude = ["build", "dist", "env", ".venv"] + +[format] +quote-style = "double" +indent-style = "space" + +[lint] +ignore = [ + "PLR0913", + "TCH001", + "COM812", + "ISC001", + "TCH002", + "PLW1514", # allow Path.open without encoding +] +select = [ + # Rules reference: https://docs.astral.sh/ruff/rules/ + + # Code Style / Formatting + "E", # pycodestyle: checks adherence to PEP 8 conventions including spacing, indentation, and line length + "W", # pycodestyle: checks adherence to PEP 8 conventions including spacing, indentation, and line length + "A", # flake8-builtins: prevents shadowing of Python built-in names + "C", # Convention: ensures code adheres to specific style and formatting conventions + "COM", # flake8-commas: enforces the correct use of trailing commas + "ERA", # eradicate: detects commented-out code that should be removed + "I", # isort: ensures imports are sorted in a consistent manner + "ICN", # flake8-import-conventions: enforces import conventions for better readability + "N", # pep8-naming: enforces PEP 8 naming conventions for classes, functions, and variables + "NPY", # NumPy: enforces best practices for using the NumPy library + "PD", # pandas-vet: enforces best practices for using the pandas library + "PT", # flake8-pytest-style: enforces best practices and style conventions for pytest tests + "PTH", # flake8-use-pathlib: encourages the use of pathlib over os.path for file system operations + "Q", # flake8-quotes: enforces consistent use of single or double quotes + "TCH", # flake8-type-checking: enforces type checking practices and standards + "TID", # flake8-tidy-imports: enforces tidy and well-organized imports + "RUF022", # flake8-ruff: enforce sorting of __all__ in modules + + # Code Structure / Complexity + "C4", # flake8-comprehensions: improves readability and performance of list, set, and dict comprehensions + "C90", # mccabe: checks for overly complex code using cyclomatic complexity + "ISC", # flake8-implicit-str-concat: prevents implicit string concatenation + "PIE", # flake8-pie: identifies and corrects common code inefficiencies and mistakes + "R", # Refactor: suggests improvements to code structure and readability + "SIM", # flake8-simplify: simplifies complex expressions and improves code readability + + # Code Security / Bug Prevention + "ARG", # flake8-unused-arguments: detects unused function and method arguments + "ASYNC", # flake8-async: identifies incorrect or inefficient usage patterns in asynchronous code + "B", # flake8-bugbear: detects common programming mistakes and potential bugs + "BLE", # flake8-blind-except: prevents blind exceptions that catch all exceptions without handling + "E", # Error: detects and reports errors in the code + "F", # Pyflakes: detects unused imports, shadowed imports, undefined variables, and various formatting errors in string operations + "INP", # flake8-no-pep420: prevents implicit namespace packages by requiring __init__.py + "PGH", # pygrep-hooks: detects deprecated and dangerous code patterns + "PL", # Pylint: comprehensive source code analyzer for enforcing coding standards and detecting errors + "RSE", # flake8-raise: ensures exceptions are raised correctly + "S", # flake8-bandit: detects security issues and vulnerabilities in the code + "SLF", # flake8-self: prevents incorrect usage of the self argument in class methods + "T10", # flake8-debugger: detects the presence of debugging tools such as pdb + "T20", # flake8-print: detects print statements left in the code + "UP", # pyupgrade: automatically upgrades syntax for newer versions of Python + "W", # Warning: provides warnings about potential issues in the code + "YTT", # flake8-2020: identifies code that will break with future Python releases + + # Code Documentation + "FIX", # flake8-fixme: detects FIXMEs and other temporary comments that should be resolved +] diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..c8fb379 --- /dev/null +++ b/tox.ini @@ -0,0 +1,35 @@ +[tox] +min_version = 4.0 +env_list = py38,py39,py310,py311,py312 + + +[testenv:quality] +description = Run all quality checks +deps = + mypy~=1.10.1 + ruff~=0.5.2 + mdformat~=0.7.17 + mdformat-footnote~=0.1.1 + mdformat-frontmatter~=2.0.8 + mdformat-gfm~=0.3.6 + yamlfix~=1.17.0 +commands = + ruff check + python -m mdformat --check README.md actions/ + yamlfix --check --config-file .yamlfix.toml -i .github/**/*.yml -i .github/**/*.yaml -i actions/**/*.yml -i actions/**/*.yaml ./ + +[testenv:style] +description = Run style checks and fixes +deps = + mypy~=1.10.1 + ruff~=0.5.2 + mdformat~=0.7.17 + mdformat-footnote~=0.1.1 + mdformat-frontmatter~=2.0.8 + mdformat-gfm~=0.3.6 + yamlfix~=1.17.0 +commands = + ruff format + ruff check --fix + python -m mdformat README.md actions/ + yamlfix --config-file .yamlfix.toml -i .github/**/*.yml -i .github/**/*.yaml -i actions/**/*.yml -i actions/**/*.yaml ./