Skip to content

Commit dd9fdb0

Browse files
tcdentclaude
andcommitted
Add release process docs and v0.2.0rc2 changelog
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 9507ce2 commit dd9fdb0

2 files changed

Lines changed: 204 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,118 @@
11
# Changelog
22

3+
## v0.2.0rc2
4+
5+
Second release candidate for 0.2.0. Completes the async migration and
6+
stabilizes the worker pool architecture.
7+
8+
### Breaking Changes
9+
10+
**Fully async database layer**
11+
- `configure_engine()` and `get_session()` now require an async SQLAlchemy engine (`AsyncEngine`) and return `AsyncSession`
12+
- Database URLs must use async drivers (e.g. `sqlite+aiosqlite://`, `postgresql+asyncpg://`)
13+
- `sqlalchemy[asyncio]` is now a core dependency; `aiosqlite` added as dev dependency
14+
15+
**Async activity query API**
16+
- `activity.list()`, `activity.detail()`, and `activity.count_active()` are now async and accept `AsyncSession`
17+
- Activity handlers are now async (`async def __call__`)
18+
19+
**Removed `session` parameter from activity mutations**
20+
- `activity.create()`, `activity.update()`, `activity.complete()`, and `activity.error()` no longer accept a `session` parameter — the handler owns its own session lifecycle
21+
22+
**Queue priority parameter**
23+
- `BaseQueueBackend.push()` signature changed from `high_priority: bool` to `priority: Priority | None`
24+
- Affects Redis, Kafka, and any custom queue backend implementations
25+
26+
### New Features
27+
28+
**CLI entrypoint**
29+
- New `agentexec` CLI command via `[project.scripts]`
30+
31+
**Activity model `create()` classmethod**
32+
- `Activity.create()` encapsulates record + initial log entry creation in one async call
33+
34+
**Async engine disposal**
35+
- `dispose_engine()` ensures the async engine's background threads exit cleanly on shutdown
36+
37+
### Architecture Changes
38+
39+
**Worker pool refactor**
40+
- Workers now use the `spawn` multiprocessing start method with explicit context — no inherited state
41+
- `StateEvent` replaced with stdlib `multiprocessing.Event` — removes dependency on the state backend for shutdown coordination
42+
- Event handling and scheduling extracted into `_EventHandler` and `_Scheduler` classes
43+
- Worker processes are now daemonic with `SIGINT` ignored — clean shutdown driven by the event
44+
- `pool.start()` handles `CancelledError` directly for Ctrl+C shutdown
45+
46+
**Logging overhaul**
47+
- Removed `worker/logging.py` and `core/logging.py` — all modules use stdlib `logging.getLogger(__name__)`
48+
- Spawned workers bootstrap a `StreamHandler` on the root logger so logs reach stderr
49+
- Pool messages use `logger.info`/`logger.error` instead of `print()`
50+
51+
### Bug Fixes
52+
53+
- Fixed crash when worker receives a task for an unregistered task name (now logs error and skips)
54+
- Failed tasks now log full tracebacks via `logger.exception` instead of `logger.error`
55+
- Kafka consumer handles `None` message values without crashing
56+
- `ActivityUpdated.status` is now `Status` enum instead of raw string
57+
- `raise e` instead of bare `raise` in task execution for clearer tracebacks
58+
59+
### Improvements
60+
61+
- Dependency groups use PEP 735 `[dependency-groups]` instead of `[tool.uv]`
62+
- Ruff line-length increased to 110
63+
- Removed verbose docstring examples and redundant comments throughout activity models
64+
- `selectinload` for eager loading of activity logs in `get_by_agent_id`
65+
- Redis backend adds `type: ignore` annotations for redis-py async stubs
66+
67+
## v0.2.0rc1
68+
69+
First release candidate for 0.2.0. Major refactor of the backend, queue,
70+
activity, and worker systems.
71+
72+
### Breaking Changes
73+
74+
**Backend module restructure**
75+
- `agentexec.state.redis_backend` renamed to `agentexec.state.redis` — update `AGENTEXEC_STATE_BACKEND` if set explicitly
76+
- `AGENTEXEC_QUEUE_NAME` renamed to `AGENTEXEC_QUEUE_PREFIX` (old name still accepted as alias)
77+
78+
**Async activity API**
79+
- Activity functions are now async: `await ax.activity.create(...)`, `await ax.activity.update(...)`, etc.
80+
81+
**Task context serialization**
82+
- `Task.context` is now `Mapping[str, Any]` (raw dict), not a typed BaseModel — hydration happens at execution time
83+
- `Task.create()` is now async
84+
85+
**Removed APIs**
86+
- `set_global_session`/`get_global_session`/`remove_global_session` — use `configure_engine`/`get_session`
87+
- `state.backend.publish`/`subscribe` (pubsub), `index_add`/`index_range`/`index_remove`, `clear`, `configure`
88+
89+
### New Features
90+
91+
**Partitioned Redis queues**
92+
- Tasks with `lock_key` route to dedicated partition queues with per-partition locking and SCAN-based fair dequeue
93+
94+
**Activity handler pattern**
95+
- Pluggable persistence via `PostgresHandler` (default) and `IPCHandler` (worker processes)
96+
97+
**Task retry**
98+
- Failed tasks requeue as high priority with `AGENTEXEC_MAX_TASK_RETRIES` (default 3)
99+
100+
**Kafka backend (experimental)**
101+
- `pip install agentexec[kafka]` for queue and schedule via Kafka
102+
103+
**Typed worker IPC**
104+
- `TaskFailed`, `LogEntry`, `ActivityUpdated` messages over `multiprocessing.Queue`
105+
106+
**Schedule composite keys**
107+
- `{task_name}:{cron}:{context_hash}` for unique schedule identity
108+
109+
### Improvements
110+
111+
- Class-based backend architecture with ABCs (`BaseStateBackend`, `BaseQueueBackend`, `BaseScheduleBackend`)
112+
- `Task` is pure data, `TaskDefinition` owns behavior
113+
- Session management via `configure_engine`/`get_session` (Pool owns the engine)
114+
- Status enum extracted to `activity/status.py` (no SQLAlchemy dependency)
115+
3116
## v0.1.7
4117

5118
### New Features

RELEASE.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Release Process
2+
3+
This document describes how to publish a new release of agentexec.
4+
5+
## Overview
6+
7+
Creating a **GitHub Release** triggers three publish workflows automatically:
8+
9+
| Workflow | Target | Secret Required |
10+
|---|---|---|
11+
| `publish.yml` | PyPI | `PYPI_API_TOKEN` |
12+
| `docker-publish.yml` | ghcr.io (`agentexec-worker`) | `GITHUB_TOKEN` (built-in) |
13+
| `npm-publish.yml` | npm (`agentexec-ui`) | `NPM_TOKEN` |
14+
15+
Docker and npm publishing can also be triggered manually via workflow dispatch.
16+
17+
## Steps
18+
19+
### 1. Ensure CI is green
20+
21+
Push all changes to `main` and verify the CI workflow passes (unit tests on
22+
Python 3.12/3.13 and Kafka integration tests).
23+
24+
### 2. Bump the version
25+
26+
Update the version in `pyproject.toml`:
27+
28+
```toml
29+
version = "X.Y.Z" # stable release
30+
version = "X.Y.ZrcN" # release candidate
31+
```
32+
33+
For the UI package, also update `ui/package.json`.
34+
35+
Commit and push:
36+
37+
```bash
38+
git add pyproject.toml
39+
git commit -m "Bump version to X.Y.Z"
40+
git push
41+
```
42+
43+
### 3. Update CHANGELOG.md
44+
45+
Add a new section at the top of `CHANGELOG.md` with release notes covering
46+
breaking changes, new features, improvements, bug fixes, and testing updates.
47+
48+
### 4. Tag the release
49+
50+
```bash
51+
git tag vX.Y.Z
52+
git push origin vX.Y.Z
53+
```
54+
55+
### 5. Create the GitHub Release
56+
57+
This is what triggers the publish workflows.
58+
59+
```bash
60+
gh release create vX.Y.Z --title "vX.Y.Z" --notes-file CHANGELOG.md
61+
```
62+
63+
For release candidates, mark as a pre-release:
64+
65+
```bash
66+
gh release create vX.Y.ZrcN --title "vX.Y.ZrcN" --generate-notes --prerelease
67+
```
68+
69+
### 6. Verify
70+
71+
Check that all three publish workflows succeeded:
72+
73+
```bash
74+
gh run list --limit 5
75+
```
76+
77+
- **PyPI**: https://pypi.org/project/agentexec/
78+
- **Docker**: https://ghcr.io/agent-ci/agentexec-worker
79+
- **npm**: https://www.npmjs.com/package/agentexec-ui
80+
81+
## Manual Publishing
82+
83+
Docker and npm workflows support manual dispatch for one-off builds:
84+
85+
```bash
86+
# Docker with a custom tag
87+
gh workflow run docker-publish.yml -f tag=dev
88+
89+
# npm with a version override
90+
gh workflow run npm-publish.yml -f version=0.2.0-beta.1
91+
```

0 commit comments

Comments
 (0)