# cmk-dev-site

## Development & Contribution

### Preparation

#### Install tooling

See also [Wiki - How to install bazelisk][ref-how-to-bazelisk]

```bash
cd git/check_mk
sudo ./buildscripts/infrastructure/build-nodes/scripts/install-development.sh --profile bazel --only
```

#### Create venv

Next, install `uv` from the directory of this README via Bazel and generate the `requirements.txt` file.
The file `requirements.txt` shall exist on the initial run, but it may be empty.

```bash
bazel run //:generate_requirements_txt
```

Finally generate the `.venv` with `uv` by using Bazel again

```bash
bazel run //:create_venv
```

Activate and use the created `.venv` with the following standard command

```bash
source .venv/bin/activate
```

### Workflow

Whenever you want to create a release, create a changelog snippet via
`changelog-generator create .snippets/some_name.md`, everything else will done
by the CI.

#### Background

The changelog is built with the help of [`changelog-generator`][ref-snippets2changelog] based on the snippets stored in `.snippets` which can be generated by `changelog-generator`.
If there is no snippet added with a commit and thereby no new version, no release will be published, neither to [test.pypi.org][ref-test-pypi-cmk-dev-site] nor after the submitted review to [pypi.org][ref-pypi-cmk-dev-site]

The version info file `__version__.py` in the python source code is generated and updated by [`changelog2version`][ref-changelog2version].

Each change pushed to be reviewed in Gerrit (containing a new snippet) is released on [test.pypi.org][ref-test-pypi-cmk-dev-site] with an incremented release candidate number based on the patchset number. Additionally Jenkins will create and push a tag for this change.

As soon as the change is submitted Jenkins will build the changelog based on the latest available snippets, create a tag and publish the package at [pypi.org][ref-pypi-cmk-dev-site]. This enables a version-merge-conflict free workflow. If a bugfix was started before e.g. the breaking change `0.7.12 -> 1.0.0` but merged after the breaking change the new version will automatically become `1.0.1`.

As mentioned at the beginning, if there is no new snippet added to a change, no new tag and no new release will be published after a submit of that change.

#### More Background

Create a new changelog snippet. If no new snippet is found on a merged change
no new release will be built and published.

If the change is based on a Jira ticket, use the Jira ticket name as snippet
name otherwise use a unique name.

```sh
uv run changelog-generator create .snippets/CMK-24265.md
```

After committing the snippet a changelog can be generated locally for testing purposes. For CI usage the `--in-place` flag is recommended to use as it will update the existing changelog with the collected snippets. For local usage remember to reset the changelog file before a second run, as the version would be updated recursively due to the way the changelog generator is working. It extracts the latest version from the changelog file and puts the found snippets on top.

Future changes to the changelog are ignored by

```sh
git update-index --assume-unchanged changelog.md
```

```sh
uv run \
    changelog-generator \
    changelog changelog.md \
    --snippets=.snippets \
    --in-place \
    --version-reference="https://review.lan.tribe29.com/gitweb?p=cmk-dev-site.git;a=tag;h=refs/tags/"
```

`hatch` requires a variable named `__version__` [containing the version as string](https://hatch.pypa.io/1.9/version/#configuration) but `changelog2version` is joining the `__version_info__` data at least until the used version `0.12.1` which requires the usage of a custom version template.

Update the version of the project in all required files by calling

```sh
uv run \
    changelog2version \
    --changelog_file changelog.md \
    --version_file cmk_dev_site/version.py \
    --template_file cmk_dev_site/custom_version_template.py.template \
    --additional_version_info="-rc42+$(git rev-parse HEAD)" \
    --print \
    | jq -r .info.version
```

* modify and check commits via `pre-commit run --all-files`
* after work is done locally:

  - update dependencies before/with a new release
```sh
uv lock --check
```
  - run unittests locally

```sh
uv run pytest
```
  - build and check package locally
```sh
uv build && \
uv run twine check dist/* &&
python3 -m pip uninstall -y cmk-dev-site && \
python3 -m pip install --user dist/cmk_dev_site-$(grep -E "^__version__.?=" cmk_dev_site/version.py | cut -d '"' -f 2 | sed 's/-//g')-py3-none-any.whl
```
  - commit, push and review the changes
```sh
git add ...
git commit -m "bump version, update dependencies"
git push origin HEAD:refs/for/main
```
  - test deployed packages by the Gerrit CV Jenkins job from `test.pypi.org`. The extra index URL is required to get those dependencies from `pypi.org` which are not available from `test.pypi.org`
```sh
pip install --no-cache-dir \
    -i https://test.pypi.org/simple/ \
    --extra-index-url https://pypi.org/simple \
    cmk-dev-site==<VERSION_WITH_RC>
```
  - finally merge the changes and let Jenkins create the release tag and deployment to [pypi.org][ref-pypi-cmk-dev-site]

<!-- Links -->
[ref-how-to-batelisk]: https://wiki.lan.checkmk.net/display/DEV/How+to+install+bazelisk
[ref-snippets2changelog]: https://github.com/brainelectronics/snippets2changelog
[ref-test-pypi-cmk-dev-site]: https://test-pypi.org/project/checkmk-toolbelt/
[ref-pypi-cmk-dev-site]: https://pypi.org/project/checkmk-toolbelt/
[ref-changelog2version]: https://github.com/brainelectronics/changelog2version
