Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
26 changes: 26 additions & 0 deletions .github/workflows/check-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Check release metadata

on:
pull_request:
paths:
- 'pyproject.toml'
- 'CHANGELOG.md'

permissions:
contents: read

jobs:
check:
name: Verify changelog matches version bump
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0

- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: '3.12'

- name: Check release metadata
run: python scripts/check-release.py
33 changes: 33 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: CI

on:
push:
branches: ["main", "master"]
pull_request:

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
test:
name: Test (Python 3.12)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v6
with:
enable-cache: true

- name: Set up Python
run: uv python install 3.12

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

- name: Test
run: uv run pytest -v
1 change: 0 additions & 1 deletion .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ jobs:

- name: Verify tag matches pyproject version
run: |
# Release tags must start with `v` followed by a PEP 440 version (e.g. v1.2.3, v1.2.3a1).
if [[ ! "$GITHUB_REF_NAME" =~ ^v[0-9] ]]; then
echo "Release tag '$GITHUB_REF_NAME' must start with 'v' followed by a digit (e.g. v1.0.0)" >&2
exit 1
Expand Down
54 changes: 54 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: GitHub Release

on:
push:
tags:
- 'v[0-9]*'

permissions:
contents: write

jobs:
release:
name: Create GitHub Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: '3.12'

- name: Read package metadata
id: meta
run: |
pkg_name=$(python -c "import tomllib,pathlib; print(tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['name'])")
pkg_version="${GITHUB_REF_NAME#v}"
echo "name=${pkg_name}" >> "$GITHUB_OUTPUT"
echo "version=${pkg_version}" >> "$GITHUB_OUTPUT"

- name: Extract changelog notes
id: notes
run: |
set -euo pipefail
version="${GITHUB_REF_NAME#v}"
if [[ -f CHANGELOG.md ]]; then
body="$(python scripts/extract-changelog.py "$version")"
else
body="Release ${version}."
fi
delimiter="EOF_${RANDOM}_${RANDOM}"
{
echo "body<<${delimiter}"
echo "$body"
echo "${delimiter}"
} >> "$GITHUB_OUTPUT"
Comment on lines +41 to +45
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: using EOF as the heredoc delimiter for multiline GITHUB_OUTPUT is fragile — if any future changelog entry contains a line that is exactly EOF, this step will produce a malformed output and the release notes will be wrong or the step will fail. GitHub's own docs recommend a random delimiter. (not blocking)

delim="EOF_$(openssl rand -hex 8)"
{
  echo "body<<$delim"
  echo "$body"
  echo "$delim"
} >> "$GITHUB_OUTPUT"


- name: Create GitHub Release
uses: softprops/action-gh-release@1e812e8210a4a8a0b23075e5795f2a4e2b2a0b7 # v2.2.2
with:
tag_name: ${{ github.ref_name }}
name: ${{ steps.meta.outputs.name }} ${{ steps.meta.outputs.version }}
body: ${{ steps.notes.outputs.body }}
generate_release_notes: false
make_latest: true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: make_latest: true is unconditional, but the tag pattern 'v[0-9]*' matches pre-releases like v1.0.0a1 / v2.0.0rc1. Marking a pre-release as "latest" on GitHub is usually wrong (it surfaces as the default download for users). Consider deriving this from whether the version has a PEP 440 suffix, e.g. compute is_prerelease in the meta step and pass make_latest: ${{ steps.meta.outputs.is_prerelease == 'false' }}. (not blocking)

39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 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.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.2.0] - 2026-05-24

### Changed

- Switch managed database operations from the connections API to the dedicated `/databases` API (`hotdata>=0.2.3` required).
- `create_managed_database` first parameter renamed from `name` to `description` (keyword-only).
- `ManagedDatabase` dataclass: replace `name`/`source_type` fields with `description`/`default_connection_id`.
- `resolve_managed_database` tries direct ID lookup first, then falls back to a description scan.
- `list_managed_databases` now fetches all databases regardless of source type.
- `list_managed_tables`, `load_managed_table`, and `delete_managed_table` use `default_connection_id` instead of database `id` for connection-scoped operations.

### Added

- `create_managed_database` accepts an optional `expires_at` parameter.

### Removed

- `MANAGED_SOURCE_TYPE`, `build_managed_config`, and `create_connection_request` removed from the public API.

## [0.1.1] - 2026-05-19

### Added

- Managed database helpers on `HotdataClient`.

## [0.1.0] - 2026-05-06

### Added

- Initial release.
11 changes: 4 additions & 7 deletions CONTRACT.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ The supported import surface is:
- `ManagedDatabase`
- `ManagedTable`
- `LoadManagedTableResult`
- `MANAGED_SOURCE_TYPE`
- `DEFAULT_SCHEMA`
- `build_managed_config`
- `create_connection_request`
- `is_parquet_path`

Adapters should import from `hotdata_runtime` and treat this surface as the stable API.
Expand All @@ -58,10 +55,10 @@ Adapters should import from `hotdata_runtime` and treat this surface as the stab
- `columns_for_qualified(qualified, connection_id=...)` resolves table columns, and
adapters should pass `connection_id` when known.
- `uploads()` returns the uploads API wrapper for parquet staging.
- `list_managed_databases()` returns managed-catalog connections (`source_type: managed`).
- `resolve_managed_database(name_or_id)` resolves a managed database by name or id.
- `create_managed_database(name, schema=..., tables=...)` creates a managed database and optionally declares tables up front.
- `delete_managed_database(name_or_id)` deletes a managed database connection.
- `list_managed_databases()` returns all databases via the `/databases` API.
- `resolve_managed_database(name_or_id)` resolves a database by id (direct lookup) or description (list scan).
- `create_managed_database(description=..., schema=..., tables=..., expires_at=...)` creates a database via the `/databases` API and optionally declares tables up front.
- `delete_managed_database(name_or_id)` deletes a database via the `/databases` API.
- `list_managed_tables(database, schema=...)` lists tables in a managed database.
- `upload_parquet(path)` uploads a local parquet file and returns an upload id.
- `load_managed_table(database, table, schema=..., upload_id=..., file=...)` publishes parquet data into a declared managed table.
Expand Down
43 changes: 43 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Releasing

Every release uses `./scripts/release.sh`. Do not bump versions, tag, or create GitHub Releases manually.

## One-time setup

- Install [GitHub CLI](https://cli.github.com/) (`gh`) and authenticate.
- Ensure PyPI [trusted publishing](https://docs.pypi.org/trusted-publishers/) is configured for this repo (`publish.yml` uses the `pypi` GitHub environment).

## Release steps

1. Add user-facing notes under `## [Unreleased]` in `CHANGELOG.md`.
2. Prepare the release PR:

```bash
./scripts/release.sh prepare patch # or minor | major | 1.2.3
```

3. Merge the PR after CI passes (including the changelog check).
4. Publish from a clean default branch checkout:

```bash
git checkout main # or master for hotdata-marimo
git pull
./scripts/release.sh publish
```

## What happens automatically

Pushing a `vX.Y.Z` tag triggers two workflows:

| Workflow | Purpose |
|----------|---------|
| `publish.yml` | Build wheel/sdist and publish to PyPI |
| `release.yml` | Create the GitHub Release with notes from `CHANGELOG.md` |

## Enforcement

- **PR check** (`check-release.yml`): if `pyproject.toml` version changes, `CHANGELOG.md` must contain a matching `## [X.Y.Z]` section.
- **Tag check** (`publish.yml`): the tag (without `v`) must match `[project].version` in `pyproject.toml`.
- **Publish guard** (`release.sh publish`): refuses to tag if the changelog section is missing.

Together, these make it hard to ship a version without changelog notes or a GitHub Release.
6 changes: 0 additions & 6 deletions hotdata_runtime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
LoadManagedTableResult,
ManagedDatabase,
ManagedTable,
MANAGED_SOURCE_TYPE,
build_managed_config,
create_connection_request,
is_parquet_path,
)
from hotdata_runtime.env import (
Expand All @@ -42,12 +39,9 @@
"DEFAULT_SCHEMA",
"HotdataClient",
"LoadManagedTableResult",
"MANAGED_SOURCE_TYPE",
"ManagedDatabase",
"ManagedTable",
"QueryResult",
"build_managed_config",
"create_connection_request",
"is_parquet_path",
"workspace_health_lines",
"default_api_key",
Expand Down
Loading
Loading