From e265ebe8199668e0c40cfe3be7959c77add4181d Mon Sep 17 00:00:00 2001 From: Vincent Auriau Date: Thu, 30 May 2024 11:44:58 +0200 Subject: [PATCH] ENH: Auto-Release to PyPI (#91) * FIX: repeated version of nbstripout * ADD: PyPI shield * ADD: .lock file * FIX: removed appearance of Python 3.8 * FIX: removed appearance of Python 3.8 * ENH: PR CI Python version 3.8->3.11 * ADD: custom publish action * ENH: readme * ENH: Attempt at splitting TestPyPI & PyPI --- .github/actions/publish/action.yaml | 125 +++++++++++++++++++++++ .github/workflows/release_pypi.yaml | 38 ++++--- .github/workflows/release_test_pypi.yaml | 21 ++++ README.md | 10 +- 4 files changed, 170 insertions(+), 24 deletions(-) create mode 100644 .github/actions/publish/action.yaml create mode 100644 .github/workflows/release_test_pypi.yaml diff --git a/.github/actions/publish/action.yaml b/.github/actions/publish/action.yaml new file mode 100644 index 00000000..23607e1b --- /dev/null +++ b/.github/actions/publish/action.yaml @@ -0,0 +1,125 @@ +name: "PyPI Poetry Publish" +: # from https://github.com/code-specialist/pypi-poetry-publish/blob/main/action.yaml +description: "Opinionated GitHub action to fully automate publishing packages to any PyPI registry - using Poetry and GitHub releases" +branding: + icon: "package" + color: "blue" + +inputs: + ACCESS_TOKEN: + description: "Access Token for GitHub with write access on the repository" + required: true + PYTHON_VERSION: + description: "Python Version" + required: false + default: "3.10" + PACKAGE_DIRECTORY: + description: "Directory of the package" + required: false + default: "./" + PUBLISH_REGISTRY_PASSWORD: + description: "Password for the user to publish to PyPI. May also be a Token - requires the `PUBLISH_REGISTRY_USERNAME` to be `__token__`" + required: true + PUBLISH_REGISTRY_USERNAME: + description: "The username for the registry. Defaults to __token__" + required: false + default: "__token__" + POETRY_VERSION: + description: "The version of Poetry to use" + required: false + default: "" + POETRY_CORE_VERSION: + description: "The version of Poetry Core to use" + required: false + default: "" + BRANCH: + description: "Branch to publish from" + required: false + default: "main" + POETRY_DEPENDENCY_REGISTRY_URL: + description: "Allows to define a custom registry to be used by Poetry for dependency installation" + required: false + POETRY_DEPENDENCY_REGISTRY_NAME: + description: "The name used for the custom registry in the dependencies" + required: false + POETRY_DEPENDENCY_REGISTRY_USERNAME: + description: "The username for the custom registry" + required: false + POETRY_DEPENDENCY_REGISTRY_PASSWORD: + description: "The password for the custom registry" + required: false + POETRY_DEPENDENCY_REGISTRY_AUTH: + description: "The authentication type for the custom registry" + required: false + default: "http-basic" + PUBLISH_REGISTRY: + description: "The registry to publish to" + required: false + default: "https://upload.pypi.org/legacy/" + UPDATE_CODE_VERSION: + description: "Whether or not to apply the version update in the code" + required: false + default: "true" + PUSH_BRANCH: + description: "Which branch to push the changes to" + required: false + default: "main" + +runs: + using: composite + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + with: + ref: ${{ inputs.BRANCH }} + token: ${{ inputs.ACCESS_TOKEN }} + + - name: Install poetry + run: pip install poetry${{ inputs.POETRY_VERSION != '' && format('=={0}', inputs.POETRY_VERSION) || '' }} poetry-core${{ inputs.POETRY_CORE_VERSION != '' && format('=={0}', inputs.POETRY_CORE_VERSION) || '' }} + shell: bash + + - name: Set up Python ${{ inputs.PYTHON_VERSION }} + uses: actions/setup-python@v4 + with: + python-version: ${{ inputs.PYTHON_VERSION }} + cache: poetry + check-latest: true + + - name: Set GitHub Tag as Package Version + run: | + sed -i -r 's/__version__ *= *".*"/__version__ = "${{ github.event.release.tag_name }}"/g' ${{ inputs.PACKAGE_DIRECTORY }}__init__.py + sed -i '0,/version =.*/s//version = "'"${{ github.event.release.tag_name }}"'"/' ./pyproject.toml + shell: bash + + - name: Add and Commit Version + run: | + if ${{ inputs.UPDATE_CODE_VERSION }} + then + git checkout -b ${{ inputs.PUSH_BRANCH }} + git add ${{ inputs.PACKAGE_DIRECTORY }}__init__.py ./pyproject.toml + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + git commit -m "Change version to ${{ github.event.release.tag_name }}" --allow-empty + git push origin HEAD:${{ inputs.PUSH_BRANCH }} + fi + shell: bash + + - name: Install dependencies + if: inputs.POETRY_DEPENDENCY_REGISTRY_URL != '' + run: | + poetry config repositories.${{ inputs.POETRY_DEPENDENCY_REGISTRY_NAME }} ${{ inputs.POETRY_DEPENDENCY_REGISTRY_URL }} + poetry config ${{ inputs.POETRY_DEPENDENCY_REGISTRY_AUTH }}.${{ inputs.POETRY_DEPENDENCY_REGISTRY_NAME }} ${{ inputs.POETRY_DEPENDENCY_REGISTRY_USERNAME }} ${{ inputs.POETRY_DEPENDENCY_REGISTRY_PASSWORD }} + poetry install --no-root + shell: bash + + - name: Install dependencies + if: inputs.POETRY_DEPENDENCY_REGISTRY_URL == '' + run: | + poetry install --no-root + shell: bash + + - name: Build and Publish + run: | + poetry config repositories.publish ${{ inputs.PUBLISH_REGISTRY }} + poetry publish -p ${{ inputs.PUBLISH_REGISTRY_PASSWORD }} -u ${{ inputs.PUBLISH_REGISTRY_USERNAME }} -r publish --build + shell: bash \ No newline at end of file diff --git a/.github/workflows/release_pypi.yaml b/.github/workflows/release_pypi.yaml index 7f3489a8..c033cf42 100644 --- a/.github/workflows/release_pypi.yaml +++ b/.github/workflows/release_pypi.yaml @@ -6,31 +6,35 @@ on: workflow_dispatch: jobs: - publish-service-client-package: + test-and-publish: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Print - run: ls /home/runner/work/choice-learn/choice-learn - - name: Publish choice-learn on TestPyPI - uses: code-specialist/pypi-poetry-publish@v1 + - name: Wait for publish on TestPyPI + uses: lewagon/wait-on-check-action@v1.3.4 with: - PACKAGE_DIRECTORY: "./choice_learn/" - PYTHON_VERSION: "3.8" - ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PUBLISH_REGISTRY_PASSWORD: ${{ secrets.TEST_PYPI_PASSWORD }} - PUBLISH_REGISTRY: "https://test.pypi.org/simple/" - BRANCH: main + ref: main + check-name: 'publish to PyPI' + repo-token: ${{ secrets.GITHUB_TOKEN }} + wait-interval: 20 + + - name: Install Python, choice-learn & run tests + uses: actions/setup-python@v5 + with: + python-version: '3.10' + - name: Install from TestPyPI & run tests with installed package run: | - pip uninstall -y -r <(pip freeze) - python3 -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ choice-learn + python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ choice-learn python tests/manual_run.py + - name: publish to PyPI - uses: code-specialist/pypi-poetry-publish@v1 + uses: ./.github/actions/publish with: PACKAGE_DIRECTORY: "./choice_learn/" - PYTHON_VERSION: "3.8" - ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PYTHON_VERSION: "3.9" PUBLISH_REGISTRY_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - BRANCH: main + PUBLISH_REGISTRY_USER: ${{ secrets.PYPI_USERNAME }} + UPDATE_CODE_VERSION: false + BRANCH: release_${{ github.event.release.tag_name }} + diff --git a/.github/workflows/release_test_pypi.yaml b/.github/workflows/release_test_pypi.yaml new file mode 100644 index 00000000..0b7ff846 --- /dev/null +++ b/.github/workflows/release_test_pypi.yaml @@ -0,0 +1,21 @@ +name: Build and publish choice-learn + +on: + release: + types: [ published ] + workflow_dispatch: + +jobs: + publish-service-client-package: + runs-on: ubuntu-latest + steps: + - name: Publish choice-learn on TestPyPI + uses: ./.github/actions/publish + with: + PACKAGE_DIRECTORY: "./choice_learn/" + PYTHON_VERSION: "3.9" + PUBLISH_REGISTRY_PASSWORD: ${{ secrets.TEST_PYPI_PASSWORD }} + PUBLISH_REGISTRY_USERNAME: ${{ secrets.TEST_PYPI_USERNAME }} + PUBLISH_REGISTRY: "https://test.pypi.org/simple/" + UPDATE_CODE_VERSION: TEST_PYPI_USERNAME + PUSH_BRANCH: release_${{ github.event.release.tag_name }} diff --git a/README.md b/README.md index c04cc305..c2ff988d 100644 --- a/README.md +++ b/README.md @@ -77,18 +77,18 @@ You can find the following tutorials to help you getting started with the packag To install the required packages in a virtual environment, run the following command: -** pip-install not possible yet, to come soon** +The easiest is to pip-install the package: ```bash pip install choice-learn ``` -In the mean time you can clone the repository: +Otherwise you can use the git repository to get the latest version: ```bash git clone git@github.com:artefactory/choice-learn.git ``` ### Dependencies -Choice-Learn requires the following: +For manual installation, Choice-Learn requires the following: - Python (>=3.9) - NumPy (>=1.24) - pandas (>=1.5) @@ -106,10 +106,6 @@ Finally for pricing or assortment optimization, you need either Gurobi or OR-Too - gurobipy (>=11.0.0) - ortools (>=9.6.2534) -Once you have created your conda/pip python==3.9 environment, you can install requirements by: -```bash -pip install choice-learn -```