Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
c225522
build: migrate packaging and application to ctui 1.0.0rc1
meeas Sep 14, 2026
39d0633
feat: add native async Modbus transports and connection lifecycle
meeas Sep 14, 2026
b5dabf8
feat: migrate reads and writes to validated async commands
meeas Sep 14, 2026
c6054e2
feat: integrate project profiles, records, progress, and cancellation
meeas Sep 14, 2026
500949f
test: cover async commands, transports, and terminal behavior
meeas Sep 14, 2026
7914437
ci: validate v1.0.0rc1 releases and document the migration
meeas Sep 14, 2026
ac4af8d
feat: add async Modbus TLS connections
meeas Sep 14, 2026
4fcc4f2
docs: specify v1.0.0rc1 release target
meeas Sep 14, 2026
426048a
ci: align build test and release workflows with ctui
meeas Sep 14, 2026
d0e45e5
docs: add project instructions, status, and decision history
meeas Sep 18, 2026
4e34098
docs: separate global preferences from project guidance
meeas Sep 20, 2026
5eb04ee
feat: add project-scoped typed Modbus tags
meeas Sep 21, 2026
4718ddd
feat: show USB details in serial completion
meeas Sep 21, 2026
61df3a5
docs: document implementation contracts and reconcile project guidance
meeas Sep 21, 2026
cf3fb59
docs: require help for positional command arguments
meeas Sep 21, 2026
e0eec09
fix: group tag import and export commands
meeas Sep 21, 2026
6fd5c21
feat: complete tag import and export paths
meeas Sep 21, 2026
920daa0
feat: serialize multi-tag reads and retain partial results
meeas Oct 2, 2026
2c9afc7
feat: make tag imports atomic and preserve confirmed data
meeas Oct 2, 2026
4cb75fd
feat: add modbus servers, device emulation and proxying
meeas Oct 3, 2026
759b8f7
docs: clarify editable ctui development setup
meeas Oct 5, 2026
b8af8e4
refactor: rename tag management command to tags
meeas Oct 6, 2026
236ef82
feat: add fixed-cadence tag and raw polling
meeas Oct 7, 2026
b05ce13
fix: append output from ctmodbus commands
meeas Oct 7, 2026
aad20cd
Revert "fix: append output from ctmodbus commands"
meeas Oct 7, 2026
5ffde8c
feat: add server and proxy request logging
meeas Oct 7, 2026
ea96a46
feat: refactor component commands and configuration lifecycle
meeas Oct 7, 2026
f0cdb23
feat: add management popups and automatic CLI server keepalive
meeas Oct 7, 2026
5db3c8e
feat: add confirmed bulk tag deletion
meeas Oct 7, 2026
9c15d08
feat: support radix and signed register write lists
meeas Oct 24, 2026
1fda698
fix: require stable ctui 1.0.0
meeas Oct 24, 2026
96c3844
docs: refresh README and validate examples
meeas Oct 24, 2026
68d7aa3
docs: consolidate server and proxy guidance in README
meeas Oct 24, 2026
08de58b
docs: prepare 1.0.0 changelog
meeas Oct 24, 2026
5b3720f
chore: prepare 1.0.0 release
meeas Oct 24, 2026
85f59b4
test: fix cross-platform paths and polling timing
meeas Oct 24, 2026
b43c72e
test: stabilize Windows TLS fixture
meeas Oct 24, 2026
4d29571
docs: record passing release CI
meeas Oct 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 149 additions & 7 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,82 @@ name: "Publish release to PyPI"
on:
push:
tags:
# Publish on version tags, e.g. v0.1.0
# Publish on version tags, e.g. v1.0.0
- "v[0-9]+.[0-9]+.[0-9]+"
- "v[0-9]+.[0-9]+.[0-9]+rc[0-9]+"
- "v[0-9]+.[0-9]+.[0-9]+[ab][0-9]+"

jobs:
release-metadata:
name: Validate release metadata
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Verify tag matches package version
shell: bash
run: |
package_version="$(python3 - <<'PY'
import tomllib

with open("pyproject.toml", "rb") as project_file:
print(tomllib.load(project_file)["project"]["version"])
PY
)"
tag_version="${GITHUB_REF_NAME#v}"

if [[ "$tag_version" != "$package_version" ]]; then
echo "Release tag $GITHUB_REF_NAME does not match package version $package_version" >&2
exit 1
fi

verify:
name: Python ${{ matrix.python-version }} on ${{ matrix.os }}
needs:
- release-metadata
runs-on: ${{ matrix.os }}
permissions:
contents: read
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- ubuntu-24.04-arm
- windows-latest
- macos-latest
python-version:
- "3.11"
- "3.12"
- "3.13"
- "3.14"
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: false

- name: Install dependencies
run: uv sync --locked --python ${{ matrix.python-version }}

- name: Run tests
run: >-
uv run --python ${{ matrix.python-version }}
python -m unittest discover -s tests -v

build:
needs:
- verify
runs-on: ubuntu-latest
permissions:
contents: read
Expand All @@ -24,20 +93,33 @@ jobs:
with:
enable-cache: false

- name: Install dependencies
run: uv sync --locked --python 3.11

- name: Check formatting
run: uv run --python 3.11 black --check src tests

- name: Check import order
run: uv run --python 3.11 isort --check-only src tests

- name: Lint
run: uv run --python 3.11 pylint src/ctmodbus

- name: Build
run: uv build

# # Optional, but recommended: run smoke tests on distributions
# - name: Smoke test (wheel)
# run: uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py
# - name: Smoke test (source distribution)
# run: uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py
- name: Smoke test wheel
run: uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py

- name: Smoke test source distribution
run: uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py

- name: Upload distributions as artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: dist
path: dist/
if-no-files-found: error

publish:
needs:
Expand All @@ -49,6 +131,11 @@ jobs:
contents: write
id-token: write
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
Expand All @@ -60,6 +147,54 @@ jobs:
name: dist
path: dist/

- name: Prepare curated release notes
env:
TAG_VERSION: ${{ github.ref_name }}
run: |
python3 - <<'PY'
import os
import re
from pathlib import Path

tag_version = os.environ["TAG_VERSION"].removeprefix("v")
base_version = re.sub(r"(?:a|b|rc)\d+$", "", tag_version)
candidates = [tag_version]
if base_version != tag_version:
candidates.append(base_version)

lines = Path("CHANGELOG.md").read_text(encoding="utf-8").splitlines()
start = None
for candidate in candidates:
prefix = f"## [{candidate}]"
start = next(
(index + 1 for index, line in enumerate(lines)
if line.startswith(prefix)),
None,
)
if start is not None:
break

if start is None:
raise SystemExit(
f"CHANGELOG.md has no section for {tag_version} or {base_version}"
)

end = next(
(index for index in range(start, len(lines))
if lines[index].startswith("## [")),
len(lines),
)
notes = "\n".join(lines[start:end]).strip()
if base_version != tag_version:
notice = (
f"> **Prerelease:** {tag_version} is a release candidate for "
f"ctmodbus {base_version}. Test it before using it in production."
)
notes = f"{notice}\n\n{notes}"

Path("release-notes.md").write_text(notes + "\n", encoding="utf-8")
PY

- name: Generate PEP 740 attestations
uses: astral-sh/attest-action@f589a42a7efb6fe400b4f400de60b4bc90390027 # v0.0.6

Expand All @@ -70,8 +205,15 @@ jobs:
env:
GH_TOKEN: ${{ github.token }}
run: |
gh release create "$GITHUB_REF_NAME" \
release_options=()
if [[ "$GITHUB_REF_NAME" =~ (a|b|rc)[0-9]+$ ]]; then
release_options+=(--prerelease --latest=false)
fi

gh release create "$GITHUB_REF_NAME" dist/* \
--repo "$GITHUB_REPOSITORY" \
--verify-tag \
--generate-notes \
--notes-file release-notes.md \
"${release_options[@]}" \
--title "$GITHUB_REF_NAME"
110 changes: 110 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: Test

on:
push:
branches:
- "**"
pull_request:
workflow_dispatch:

permissions:
contents: read

jobs:
tests:
name: Python ${{ matrix.python-version }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- ubuntu-24.04-arm
- windows-latest
- macos-latest
python-version:
- "3.11"
- "3.12"
- "3.13"
- "3.14"

steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: false

- name: Install Python
run: uv python install ${{ matrix.python-version }}

- name: Install dependencies
run: uv sync --locked --python ${{ matrix.python-version }}

- name: Run tests
run: >-
uv run --python ${{ matrix.python-version }}
python -m unittest discover -s tests -v

quality:
name: Formatting and import order
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: false

- name: Install dependencies
run: uv sync --locked --python 3.11

- name: Check formatting
run: uv run --python 3.11 black --check src tests

- name: Check import order
run: uv run --python 3.11 isort --check-only src tests

- name: Lint
run: uv run --python 3.11 pylint src/ctmodbus

artifacts:
name: Build and smoke-test distributions
needs:
- tests
- quality
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
enable-cache: false

- name: Build distributions
run: uv build

- name: Smoke-test wheel
run: uv run --isolated --no-project --with dist/*.whl tests/smoke_test.py

- name: Smoke-test source distribution
run: uv run --isolated --no-project --with dist/*.tar.gz tests/smoke_test.py

- name: Upload distributions
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ctmodbus-distributions
path: dist/
if-no-files-found: error
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
.mypy_cache/
*.pyc
__pycache__/
src/ctserial/__pycache__/
dist/
ctmodbus.egg-info/
.venv/
build/
build/
Loading
Loading