diff --git a/.github/workflows/branchOffCadenzaVersion.yml b/.github/workflows/branchOffCadenzaVersion.yml deleted file mode 100644 index 28e8d8d..0000000 --- a/.github/workflows/branchOffCadenzaVersion.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Branch off Cadenza Version - -on: - workflow_dispatch: - inputs: - cadenza-version: - type: string - required: true - description: | - Next Cadenza Main Version - (e.g. '10.4' for setting the main branch up for development against Cadenza 10.4. This would make 10.4.0-dev the new main branch version.) - - -jobs: - release: - runs-on: ubuntu-latest - - steps: - - name: Validate version input - if: "${{ github.event.inputs.cadenza-version != '' }}" - run: | - if ! [[ '${{ github.event.inputs.cadenza-version }}' =~ ^[0-9]+\.[0-9]+$ ]]; then - echo "Cadenza Version must be specified in the format x.x (e.g. 10.4). Was '${{ github.event.inputs.cadenza-version }}'." >&2 - exit 1 - fi - - - uses: actions/create-github-app-token@v1 - id: app-token - with: - app-id: ${{ vars.DISY_RELEASE_APP_ID }} - private-key: ${{ secrets.DISY_RELEASE_APP_SECRET }} - - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - token: ${{ steps.app-token.outputs.token }} - - - name: Set up Python - uses: actions/setup-python@v3 - with: - python-version: ${{ vars.PYTHON_VERSION }} - - # poetry is needed for building and for poetry-bumpversion for version management - - name: Install poetry - run: | - pipx install poetry - poetry self add poetry-bumpversion - - - # Needed for creating the tag - - name: Configure Git - run: | - git config --global user.email "github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - - - name: Determine branch name - run: echo "BRANCH_NAME=v$(poetry version patch --dry-run -s | cut -d. -f1,2).x" >> $GITHUB_ENV - - - name: Create branch for current version - run: git branch ${{ env.BRANCH_NAME }} main - - - name: Bump package version of main - run: | - poetry version ${{ github.event.inputs.cadenza-version }}.0-dev - echo "NEW_VERSION=$(poetry version -s)" >> $GITHUB_ENV - - - name: Commit and tag changes - run: | - git add "pyproject.toml" - git commit -m "chore: branch off main as ${{ env.BRANCH_NAME }} and bump main version to ${{ env.NEW_VERSION }}" - - - name: Push changes - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: git push -u origin ${{ env.BRANCH_NAME }} && git push origin && git push --tags diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cec17be..c8500ef 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,8 +1,17 @@ name: Release on: - workflow_dispatch - + workflow_dispatch: + inputs: + deployment-env: + type: choice + description: 'Deployment environment' + required: true + options: + - test.pypi.org + - pypi.org + default: 'test.pypi.org' + jobs: release: runs-on: ubuntu-latest @@ -48,46 +57,55 @@ jobs: git config --global user.email "github-actions[bot]@users.noreply.github.com" git config --global user.name "github-actions[bot]" - - name: Prepare package version (e.g. 1.2.3-dev => 1.2.3) + # either bump release or pre-release version, depending on user input + - name: Prepare package version (e.g. 1.2.3a0.dev => 1.2.3a0) FOR TEST (!) pre-release + if: "${{ github.event.inputs.deployment-env == 'test.pypi.org' }}" run: | - echo "RELEASE_VERSION=$(poetry version patch --dry-run -s)" >> $GITHUB_ENV + poetry version "$(poetry version -s | head -n 1 | sed 's/\.dev$//')" + RELEASE_VERSION=$(poetry version -s) && echo "RELEASE_VERSION=$RELEASE_VERSION" >> $GITHUB_ENV - - name: Set release tag to 'latest' + - name: Prepare package version (e.g. 1.2.3.dev => 1.2.3, 1.2.3a0.dev => 1.2.3) for release + if: "${{ github.event.inputs.deployment-env == 'pypi.org' }}" run: | - echo "RELEASE_TAG=latest" >> $GITHUB_ENV - + echo "RELEASE_VERSION=$(poetry version patch -s | head -n 1)" >> $GITHUB_ENV # Create a dist/wheel for the bumped version now after "poetry version" has run - name: Build run: | poetry build - # either push to test.pypi.org or pypi.org depending on user input - - name: Publish package distributions to Test (!) PyPI - # if: "${{ github.event.inputs.deployment-env == 'test.pypi.org' }}" + # either push to test.pypi.org or pypi.org, depending on user input + - name: Publish package distributions TO TEST (!) PyPI + if: "${{ github.event.inputs.deployment-env == 'test.pypi.org' }}" uses: pypa/gh-action-pypi-publish@release/v1 with: repository-url: https://test.pypi.org/legacy/ + - name: Publish package distributions to PyPI + if: "${{ github.event.inputs.deployment-env == 'pypi.org' }}" + uses: pypa/gh-action-pypi-publish@release/v1 - #- name: Publish package distributions to PyPI - # if: "${{ github.event.inputs.deployment-env == 'pypi.org' }}" - # uses: pypa/gh-action-pypi-publish@release/v1 - - - # Update changelog unreleased section with new version - - name: Update changelog + - name: Update changelog, only for proper release + if: "${{ github.event.inputs.deployment-env == 'pypi.org' }}" uses: superfaceai/release-changelog-action@v2 with: path-to-changelog: CHANGELOG.md version: ${{ env.RELEASE_VERSION }} operation: release - - name: Commit and tag changes + - name: Commit and tag changes without changelog FOR TEST (!) prerelease + if: "${{ github.event.inputs.deployment-env == 'test.pypi.org' }}" + run: | + git add "pyproject.toml" + git commit -m "Chore: pre-release ${{ env.RELEASE_VERSION }}" + git tag ${{ env.RELEASE_VERSION }} + + - name: Commit and tag changes + if: "${{ github.event.inputs.deployment-env == 'pypi.org' }}" run: | git add "pyproject.toml" git add "CHANGELOG.md" - git commit -m "chore: release ${{ env.RELEASE_VERSION }}" + git commit -m "Chore: release ${{ env.RELEASE_VERSION }}" git tag ${{ env.RELEASE_VERSION }} - name: Push changes @@ -95,7 +113,9 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: git push origin && git push --tags + # TODO only for full release? What does this action do exactly? - id: get-changelog + if: "${{ github.event.inputs.deployment-env == 'pypi.org' }}" name: Get version changelog uses: superfaceai/release-changelog-action@v2 with: @@ -103,7 +123,9 @@ jobs: version: ${{ env.RELEASE_VERSION }} operation: read + # TODO this should only happen when releasing to PyPI, right? - name: Update GitHub release documentation + if: "${{ github.event.inputs.deployment-env == 'pypi.org' }}" uses: softprops/action-gh-release@v1 with: tag_name: ${{ env.RELEASE_VERSION }} @@ -111,16 +133,16 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Bump package version to new dev version (e.g. 1.2.3 => 1.2.4-dev) + - name: Bump package version to new prerelease dev version (e.g. 1.2.3 => 1.2.4a0.dev, 1.2.3a0 => 1.2.3a1.dev) run: | - poetry version --dry-run "$(poetry version patch --dry-run -s)-dev" + poetry version "$(poetry version prerelease --dry-run -s | head -n 1).dev" DEV_VERSION=$(poetry version -s) && echo "DEV_VERSION=$DEV_VERSION" >> $GITHUB_ENV # Determine DEV_VERSION - - name: Commit version bump + - name: Commit version bump (push happens later) run: | git add "pyproject.toml" - git commit -m "chore: bump up version to ${{ env.DEV_VERSION }}" - + git commit -m "Chore: bump up version to ${{ env.DEV_VERSION }}" + - name: Push changes env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 0828c01..03d4f2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,13 @@ # Changelog All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased +### Changed +- The version scheme on cadenzaanalytics is now based on the Cadenza main version (starting with Cadenza 10.3). New versions have the format x.x.y, where x.x is the Cadenza main version and y a functional change or bugfix. + ## 0.1.26 - 2025-03-11 - Support multipart/form-data that is parsed as files and not as forms diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..c849586 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,69 @@ +# Development of Cadenza Analytics Python + +## Development Environment +Development is possible via most common IDEs such as Visual Studio Code or PyCharm. +Make sure to mark the `src` directory as "Sources Root" to make sure cross imports from the `examples` directory work as expected and that imports within `cadenzaanalytics` can get resolved by the IDE. + +## Python version +We aim to support older python versions and dependencies, but best experience and most features will be available for newer versions, currently this is Python `9.12`. + +## Versioning +Versioning of `cadenzaanalytics` will happen via [poetry-bumpversion](https://github.com/monim67/poetry-bumpversion). +On release, this will bump the version depending on the chosen release type. +For test releases, a prerelease (alpha) version is used (e.g. `10.3.0a0`). + +## Documentation +On a proper release (i.e. not a test release), all "Unreleased" changes in the [Changelog](CHANGELOG.md) will be automatically tagged with the released version. +So make sure to add relevant changelog notes for every change you make and follow the style described in the changelog file. + +Also, on a release, documentation for all version branches will be generated using `pdoc` and uploaded to this repositories githubpages at https://disyinformationssysteme.github.io/cadenza-analytics-python. +This documentation workflow can also be triggered manually on the dedicated branch `githubpages`. + +## Pylint +[Pylint](https://github.com/pylint-dev/pylint) is used for making sure that `cadenzaanalytics` follows some common styles. +If necessary some rules can be disabled globally in the [.pylintrc](.pylintrc) file or in the corresponding python file. +There is a GitHub workflow to validate this. +For some IDEs like PyCharm there are also plugins for Pylint so that linting can happen within the IDE and errors in the pipeline can be avoided. + +## Releasing: +Make sure to check the following +- Does the [Changelog](CHANGELOG.md) contain all relevant information? +- Are all relevant workflows green? +- Do you want to make a test release to https://test.pypi.org? +This is helpful to test `cadenzaanalytics` with existing extensions. +To get the latest version immediately it might be good to disable caches, e.g. via `pip install --upgrade cadenzaanalytics --extra-index-url https://test.pypi.org/simple --no-cache-dir`. +For a first installation in a new (virtual) environment, you can use `pip install cadenzaanalytics --extra-index-url https://test.pypi.org/simple` +- In test releases, CI changes to the repository (bumping the version, updating the changelog, etc.) are _not_ pushed. +- To make a non-test release, choose the `pypi.org` deployment environment in the release dialog. + +## Dockerized Example Extension +To run the example (and your production application) in a docker container you will need to define the wsgi server that will run the flask app. +The provided Dockerfile in the examples uses gunicorn with some example options, for more details consult the [documentation](https://docs.gunicorn.org/en/latest/settings.html). +Important is that gunicorn has access to a function creating or providing the flask app object, which for `cadenzanalytics` is the `CadenzaAnalyticsExtensionService`. +The requirements file can use test releases when adding `--extra-index-url https://test.pypi.org/simple` in the first line. +It can (re)define versions of its own or transient dependencies, but most importantly needs the `cadenzaanalytics` dependency. +```commandline +cd /examples/calculation +docker build . -t cadenza-analytics-example +docker image list +docker run -p 8080:8080 YOUR_CREATED_IMAGE_ID +``` + +## Technical notes +The release process uses PyPi's [trusted publishing](https://docs.pypi.org/trusted-publishers/), so is based on +OIDC id token and uses no API token from PyPi. +The relevant permission `id-token: write` must be given to the release-job. + +The test environment test.pypi.org makes no guarantee on availability of the package or even on the account. +So it might be necessary to recreate an account at some point in time. + +To test and play around with poetry-bumpversion locally, you can use it as follows, see documentation of [poetry](https://python-poetry.org/docs/#installing-with-pipx) and [poetry-bumpversion](https://pypi.org/project/poetry-bumpversion/) +```commandline +pipx install poetry +pipx run poetry self add poetry-bumpversion +pipx run poetry version minor -s +``` + +The documentation build workflow runs on a separate branch `githubpages` for all version branches. +In order to enable cross-branch triggering of this workflow, a valid PAT with read content and read/write workflows permissions needs to be stored in the secret `WORKFLOW_TRIGGER_TOKEN`. +An alternative is to manually trigger the workflow. diff --git a/README.md b/README.md index a02986b..2aec098 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Cadenza Analytics Python -**cadenzaanalytics** is the official package for fast and easy creation of [disy Cadenza](https://www.disy.net/en/products/disy-cadenza/) analytics extensions with Python. It enables the extension of disy Cadenza for advanced analytics purposes with the usage of python code. +**cadenzaanalytics** is the official package for fast and easy creation of [disy Cadenza](https://www.disy.net/en/products/disy-cadenza/) analytics extensions with Python. +It enables the extension of disy Cadenza for advanced analytics purposes with the usage of python code. -Currently, this package is in **beta status**: it can be used for testing, but there -may be breaking changes before a full release. +Currently, this package is in **beta status**: it can be used for testing, but there may be breaking changes before a full release. Find the docs at https://disyinformationssysteme.github.io/cadenza-analytics-python @@ -17,62 +17,17 @@ Find the docs at https://disyinformationssysteme.github.io/cadenza-analytics-pyt ## Example: -Example extension can be found in [examples](examples). +Example extensions can be found in [examples](https://github.com/DisyInformationssysteme/cadenza-analytics-python/tree/main/examples). -To test a example extension, clone this repository, install the dependencies, navigate to the folder, e.g. `examples/calculation/extension`. Run the example file in your python environment e.g.: +To test an example extension, clone this repository, install the dependencies, navigate to the folder, e.g. `examples/calculation/extension`. +Run the example file in your python environment e.g.: ``` python example_extensions.py ``` -A development server will be started on localhost `http://127.0.0.1:5005`. The analytics extension can now be registered and used in disy Cadenza. +A development server will be started on localhost `http://127.0.0.1:5005`. +The analytics extension can now be registered and used in disy Cadenza. It is not recommended to use the development server in a production environment. -## Development of Cadenza Analytics Python - -### Development Environment -Development is possible via most common IDEs such as Visual Studio Code or PyCharm. Make sure to mark the `src` directory as "Sources Root" to make sure cross imports from the `examples` directory work as expected and that imports within `cadenzaanalytics` can get resolved by the IDE. - -### Python version -We aim to support older python versions and dependencies, but best experience and most features will be available for newer versions, currently this is Python `9.12`. -### Versioning -Versioning of `cadenzaanalytics` will happen via [poetry-bumpversion](https://github.com/monim67/poetry-bumpversion). On release, this will bump the version depending on the chosen release type. -The project uses semantic versioning with a major, minor and patch version. - -### Documentation -On release, all "Unreleased" changes in the [Changelog](CHANGELOG.md) will be automatically tagged with the released version. -So make sure to add relevant changelog notes for every change you make and follow the style described in the changelog file. - -### Pylint -[Pylint](https://github.com/pylint-dev/pylint) is used for making sure that `cadenzaanalytics` follows some common styles. If necessary some rules can be disabled globally in the [.pylintrc](.pylintrc) file or in the corresponding python file. There is a GitHub workflow to validate this. For some IDEs like PyCharm there are also plugins for Pylint so that linting can happen within the IDE and errors in the pipeline can be avoided. -### Releasing: -Make sure to check the following -- Does the [Changelog](CHANGELOG.md) contain all relevant information? -- Are all relevant workflows green? -- Do you want to make a test release to https://test.pypi.org? This is helpful to test `cadenzaanalytics` with existing extensions. To get the latest version immediately it might be good to disable caches, e.g. via `pip install --upgrade cadenzaanalytics --extra-index-url https://test.pypi.org/simple --no-cache-dir`. For a first installation in a new (virtual) environment, you can use `pip install cadenzaanalytics --extra-index-url https://test.pypi.org/simple` -- To make a non-test release, choose the pypi.org deployment environment in the release dialog. - -### Dockerized Example Extension -To run the example (and your production application) in a docker container you will need to define the wsgi server that will run the flask app. -The provided Dockerfile in the examples uses gunicorn with some example options, for more details consult the [documentation](https://docs.gunicorn.org/en/latest/settings.html). Important is that gunicorn has access to a function creating or providing the flask app object, which for `cadenzanalytics` is the `CadenzaAnalyticsExtensionService`. -The requirements file can use test releases when adding `--extra-index-url https://test.pypi.org/simple` in the first line. It can (re)define versions of its own or transient dependencies, but most importantly needs the `cadenzaanalytics` dependency. -```commandline -cd /examples/calculation -docker build . -t cadenza-analytics-example -docker image list -docker run -p 8080:8080 YOUR_CREATED_IMAGE_ID -``` -### Technical notes -The release process uses PyPi's [trusted publishing](https://docs.pypi.org/trusted-publishers/), so is based on -OIDC id token and uses no API token from PyPi. The relevant permission `id-token: write` must be given to the release-job. - -The test environment test.pypi.org makes no guarantee on availability of the package or even on the account. So it might be necessary to recreate an account at some point in time. - -To test and play around with poetry-bumpversion locally, you can use it as follows, see documentation of [poetry](https://python-poetry.org/docs/#installing-with-pipx) and [poetry-bumpversion](https://pypi.org/project/poetry-bumpversion/) -```commandline -pipx install poetry -pipx run poetry self add poetry-bumpversion -pipx run poetry version minor -s -``` - ## License: -[License](LICENSE.md) +[License](https://github.com/DisyInformationssysteme/cadenza-analytics-python/tree/main/LICENSE.md)