From 009ebe31e79dfc63e685708c7f1aeedf08f53645 Mon Sep 17 00:00:00 2001 From: franktore Date: Fri, 3 Jul 2026 15:47:43 +0200 Subject: [PATCH 1/8] eat: add trusted PyPI publishing workflow and package metadata add GitHub Actions workflow for trusted publishing to TestPyPI (manual) and PyPI (tag-based) enrich package metadata (license SPDX, URLs, keywords, classifiers, package include) mark package maturity as Production/Stable update README with PyPI install instructions and supported Python version --- .github/workflows/publish-pypi.yml | 83 ++++++++++++++++++++++++++++++ README.md | 12 ++++- pyproject.toml | 22 +++++++- 3 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/publish-pypi.yml diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml new file mode 100644 index 0000000..a24ac66 --- /dev/null +++ b/.github/workflows/publish-pypi.yml @@ -0,0 +1,83 @@ +name: Publish Python Package + +'on': + push: + tags: + - v* + workflow_dispatch: + inputs: + publish_to_testpypi: + description: Publish package to TestPyPI instead of PyPI + required: true + default: false + type: boolean + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Install build tools + run: python -m pip install --upgrade build twine + + - name: Build distributions + run: python -m build + + - name: Check package metadata + run: python -m twine check dist/* + + - name: Upload distributions + uses: actions/upload-artifact@v4 + with: + name: python-dist + path: dist/ + + publish-testpypi: + if: github.event_name == 'workflow_dispatch' && inputs.publish_to_testpypi + runs-on: ubuntu-latest + needs: build + permissions: + id-token: write + environment: + name: development + url: https://test.pypi.org/p/omnia-timeseries + steps: + - name: Download distributions + uses: actions/download-artifact@v4 + with: + name: python-dist + path: dist/ + + - name: Publish to TestPyPI (trusted publishing) + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + + publish-pypi: + if: startsWith(github.ref, 'refs/tags/v') + runs-on: ubuntu-latest + needs: build + permissions: + id-token: write + environment: + name: production + url: https://pypi.org/p/omnia-timeseries + steps: + - name: Download distributions + uses: actions/download-artifact@v4 + with: + name: python-dist + path: dist/ + + - name: Publish to PyPI (trusted publishing) + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/README.md b/README.md index 9b73fb6..9cd076d 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,22 @@ Python package for interacting with the [Omnia Industrial IoT Timeseries API](https://github.com/equinor/OmniaPlant/wiki). -## How do I get set up? ### +## Installation -To use the Python package, install it in the following manner: +Install from PyPI: + +``` +pip install omnia-timeseries +``` + +Install from GitHub (latest unreleased changes): ``` pip install git+https://github.com/equinor/omnia-timeseries-python.git@main ``` +Supported Python versions: 3.8+ + For support, create an issue on GitHub. ## Example usage diff --git a/pyproject.toml b/pyproject.toml index 5cadec3..a81b567 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,25 @@ version = "1.4.4.1" description = "Official Python SDK for the Omnia Timeseries API" readme = "README.md" authors = ["Equinor Omnia Industrial IoT Team "] -license = "LICENSE" +license = "MIT" +homepage = "https://github.com/equinor/omnia-timeseries-python" +repository = "https://github.com/equinor/omnia-timeseries-python" +documentation = "https://github.com/equinor/omnia-timeseries-python/blob/main/README.md" +keywords = ["omnia", "timeseries", "azure", "sdk", "industrial-iot"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: Software Development :: Libraries :: Python Modules", +] +packages = [{ include = "omnia_timeseries", from = "src" }] [tool.poetry.dependencies] python = ">=3.8,<3.9.0 || >3.9.1,<4.0" @@ -26,6 +44,8 @@ black = ">=22.0,<26.0" [tool.poetry.urls] repository = "https://github.com/equinor/omnia-timeseries-python" +issues = "https://github.com/equinor/omnia-timeseries-python/issues" +changelog = "https://github.com/equinor/omnia-timeseries-python/blob/main/CHANGELOG.md" [tool.black] line-length = 88 From 8ca962ebf10e9ed659f92c3a1ef323ebbe218698 Mon Sep 17 00:00:00 2001 From: franktore Date: Fri, 3 Jul 2026 15:59:10 +0200 Subject: [PATCH 2/8] test workflow --- .github/workflows/publish-pypi.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index a24ac66..ae8bfa2 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -2,6 +2,8 @@ name: Publish Python Package 'on': push: + branches: + - feature/make-ready-for-publish-on-pypi tags: - v* workflow_dispatch: From 9d9300fb1918e6704ab909d13d95544c5b54fdfc Mon Sep 17 00:00:00 2001 From: franktore Date: Fri, 3 Jul 2026 16:04:13 +0200 Subject: [PATCH 3/8] trigger workflow --- .github/workflows/publish-pypi.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index ae8bfa2..5ae41f5 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -45,7 +45,9 @@ jobs: path: dist/ publish-testpypi: - if: github.event_name == 'workflow_dispatch' && inputs.publish_to_testpypi + if: | + (github.event_name == 'workflow_dispatch' && inputs.publish_to_testpypi) || + (github.event_name == 'push' && github.ref == 'refs/heads/feature/make-ready-for-publish-on-pypi') runs-on: ubuntu-latest needs: build permissions: From a0eeee5a8bbe29d43e6c6cb755ef26b51ec5fce4 Mon Sep 17 00:00:00 2001 From: franktore Date: Fri, 3 Jul 2026 16:12:19 +0200 Subject: [PATCH 4/8] cleanup test-steps --- .github/workflows/publish-pypi.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 5ae41f5..a24ac66 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -2,8 +2,6 @@ name: Publish Python Package 'on': push: - branches: - - feature/make-ready-for-publish-on-pypi tags: - v* workflow_dispatch: @@ -45,9 +43,7 @@ jobs: path: dist/ publish-testpypi: - if: | - (github.event_name == 'workflow_dispatch' && inputs.publish_to_testpypi) || - (github.event_name == 'push' && github.ref == 'refs/heads/feature/make-ready-for-publish-on-pypi') + if: github.event_name == 'workflow_dispatch' && inputs.publish_to_testpypi runs-on: ubuntu-latest needs: build permissions: From 82c306be2a485df41cddf758cd056cb6c053c959 Mon Sep 17 00:00:00 2001 From: franktore Date: Fri, 3 Jul 2026 16:17:16 +0200 Subject: [PATCH 5/8] fix: harden TestPyPI dispatch condition and align metadata/docs formatting coerce workflow_dispatch boolean input with fromJSON in publish workflow align README Python support note with declared version constraints normalize classifiers indentation in pyproject.toml to spaces --- .github/workflows/publish-pypi.yml | 2 +- README.md | 2 +- pyproject.toml | 22 +++++++++++----------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index a24ac66..cf18de5 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -43,7 +43,7 @@ jobs: path: dist/ publish-testpypi: - if: github.event_name == 'workflow_dispatch' && inputs.publish_to_testpypi + if: github.event_name == 'workflow_dispatch' && fromJSON(inputs.publish_to_testpypi) runs-on: ubuntu-latest needs: build permissions: diff --git a/README.md b/README.md index 9cd076d..b124c27 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Install from GitHub (latest unreleased changes): pip install git+https://github.com/equinor/omnia-timeseries-python.git@main ``` -Supported Python versions: 3.8+ +Supported Python versions: 3.8+ (excluding 3.9.0 and 3.9.1) For support, create an issue on GitHub. diff --git a/pyproject.toml b/pyproject.toml index a81b567..ac5cf96 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,17 +10,17 @@ repository = "https://github.com/equinor/omnia-timeseries-python" documentation = "https://github.com/equinor/omnia-timeseries-python/blob/main/README.md" keywords = ["omnia", "timeseries", "azure", "sdk", "industrial-iot"] classifiers = [ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Topic :: Software Development :: Libraries :: Python Modules", + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: Software Development :: Libraries :: Python Modules", ] packages = [{ include = "omnia_timeseries", from = "src" }] From bb566921041493b181b7899f20835841e3c4b071 Mon Sep 17 00:00:00 2001 From: franktore Date: Sat, 4 Jul 2026 10:02:07 +0200 Subject: [PATCH 6/8] docs(ci): document release versioning and enforce tag-version parity add release/versioning policy to CONTRIBUTING for PyPI releases require git tag version to match pyproject version in publish workflow fail tag-triggered publish early when versions are inconsistent --- .github/workflows/publish-pypi.yml | 18 ++++++++++++++++++ CONTRIBUTING.md | 20 ++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index cf18de5..f742808 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -22,6 +22,24 @@ jobs: - name: Checkout uses: actions/checkout@v5 + - name: Verify tag matches pyproject version + if: startsWith(github.ref, 'refs/tags/v') + run: | + TAG_VERSION="${GITHUB_REF_NAME#v}" + PYPROJECT_VERSION=$(python - <<'PY' + import tomllib + + with open("pyproject.toml", "rb") as f: + data = tomllib.load(f) + print(data["tool"]["poetry"]["version"]) + PY + ) + + if [[ "$TAG_VERSION" != "$PYPROJECT_VERSION" ]]; then + echo "Tag version ($TAG_VERSION) does not match pyproject version ($PYPROJECT_VERSION)." + exit 1 + fi + - name: Set up Python uses: actions/setup-python@v5 with: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 427aa72..7f57ee4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,6 +20,26 @@ Here are some resources to help you get started with open source contributions: * Create a PR * Code review +### Release and versioning + +Follow the steps below for any release that is intended for PyPI. + +1. Update the package version in `pyproject.toml` under `[tool.poetry].version`. +2. Update `CHANGELOG.md` with the release notes for that exact version. +3. Merge the release PR to `main`. +4. Create and push a Git tag that exactly matches the package version prefixed with `v`. + +Examples: + +- `pyproject.toml` version `1.4.5` -> tag `v1.4.5` +- `pyproject.toml` version `1.4.5.post1` -> tag `v1.4.5.post1` + +Versioning policy: + +- Use `X.Y.Z` for normal releases (features/fixes). +- Use `X.Y.Z.postN` for packaging-only corrections where runtime behavior is unchanged. +- Do not create a release tag without first updating `pyproject.toml` to the matching version. + ### Issues #### Create a new issue From abf4f270ba73779876b0b082f75a625c19eb75da Mon Sep 17 00:00:00 2001 From: franktore Date: Mon, 6 Jul 2026 09:55:20 +0200 Subject: [PATCH 7/8] Bump project version to v1.4.4.3 (packaging-only) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ac5cf96..cc73a6d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "omnia_timeseries" -version = "1.4.4.1" +version = "1.4.4.3" description = "Official Python SDK for the Omnia Timeseries API" readme = "README.md" authors = ["Equinor Omnia Industrial IoT Team "] From 751a97a18bf9224f2eb94d4c90b4795c70969f4f Mon Sep 17 00:00:00 2001 From: franktore Date: Mon, 6 Jul 2026 10:58:35 +0200 Subject: [PATCH 8/8] explicit policy enforcment. tag must be acactly 'v' plus pyproject-version --- .github/workflows/publish-pypi.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index f742808..96ab015 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -23,9 +23,8 @@ jobs: uses: actions/checkout@v5 - name: Verify tag matches pyproject version - if: startsWith(github.ref, 'refs/tags/v') + if: startsWith(github.ref, 'refs/tags/') run: | - TAG_VERSION="${GITHUB_REF_NAME#v}" PYPROJECT_VERSION=$(python - <<'PY' import tomllib @@ -35,8 +34,10 @@ jobs: PY ) - if [[ "$TAG_VERSION" != "$PYPROJECT_VERSION" ]]; then - echo "Tag version ($TAG_VERSION) does not match pyproject version ($PYPROJECT_VERSION)." + EXPECTED_TAG="v${PYPROJECT_VERSION}" + + if [[ "$GITHUB_REF_NAME" != "$EXPECTED_TAG" ]]; then + echo "Release tag must be '${EXPECTED_TAG}', but got '${GITHUB_REF_NAME}'." exit 1 fi