Skip to content
Merged
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
83 changes: 83 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Release

on:
push:
tags: ["v*"]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: astral-sh/setup-uv@v5

- name: Assert tag matches pyproject version
run: |
TAG="${GITHUB_REF_NAME#v}"
VERSION="$(python3 -c 'import tomllib; print(tomllib.load(open("pyproject.toml","rb"))["project"]["version"])')"
if [ "$TAG" != "$VERSION" ]; then
echo "Tag v$TAG does not match pyproject version $VERSION" >&2
exit 1
fi
Comment on lines +15 to +22

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: extend the assertion to cover dbt/adapters/hotdata/__version__.py (not blocking).

The repo declares the version in two places. dbt/adapters/hotdata/__version__.py:1 also holds 0.2.0. This step compares the tag against pyproject.toml only.

A maintainer can bump pyproject.toml, tag, and pass this guard while __version__.py stays at the old value. The wheel then ships metadata version 0.3.0 next to a module reporting 0.2.0. dbt-core imports dbt.adapters.<name>.__version__ to print installed adapter versions, so dbt --version shows the stale number to users.

That module is not optional. Both workflows list it as a required wheel file, so the file reaches every install.

Suggested addition after the existing comparison:

MODVER="$(python3 -c 'ns={}; exec(open("dbt/adapters/hotdata/__version__.py").read(), ns); print(ns["version"])')"
if [ "$MODVER" != "$VERSION" ]; then
  echo "__version__.py $MODVER does not match pyproject version $VERSION" >&2
  exit 1
fi


- name: Build
run: uv build

- name: Assert wheel contents
# Same guard as CI: a packaging change that drops the macros or config
# files produces a wheel that imports fine but cannot run a model.
run: |
python3 - <<'EOF'
import glob, sys, zipfile

wheel = glob.glob("dist/*.whl")[0]
names = set(zipfile.ZipFile(wheel).namelist())
required = [
"dbt/adapters/hotdata/__init__.py",
"dbt/adapters/hotdata/__version__.py",
"dbt/adapters/hotdata/client.py",
"dbt/adapters/hotdata/column.py",
"dbt/adapters/hotdata/connections.py",
"dbt/adapters/hotdata/credentials.py",
"dbt/adapters/hotdata/impl.py",
"dbt/adapters/hotdata/relation.py",
"dbt/adapters/hotdata/seeds.py",
"dbt/include/hotdata/__init__.py",
"dbt/include/hotdata/dbt_project.yml",
"dbt/include/hotdata/profile_template.yml",
"dbt/include/hotdata/macros/adapters.sql",
"dbt/include/hotdata/macros/materializations/table.sql",
"dbt/include/hotdata/macros/materializations/incremental.sql",
"dbt/include/hotdata/macros/materializations/seed.sql",
"dbt/include/hotdata/macros/materializations/view.sql",
"dbt/include/hotdata/macros/materializations/snapshot.sql",
]
Comment on lines +36 to +55

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: extract this list into a script shared with ci.yml (not blocking).

.github/workflows/ci.yml:48-67 holds an identical 18-entry list. Two copies drift apart over time.

Consider a future macro file added to the CI list but missed here. The release guard silently stops covering that file. The release guard is the more important of the two, because it inspects the exact artifact that ships to PyPI.

Move the script to scripts/assert_wheel_contents.py. Then both workflows run python3 scripts/assert_wheel_contents.py and share one list.

missing = [name for name in required if name not in names]
if missing:
sys.exit(f"wheel {wheel} is missing: {missing}")
print(f"ok: {wheel} contains all {len(required)} required files")
EOF

- uses: actions/upload-artifact@v4
with:
name: dist
path: dist/
if-no-files-found: error

publish:
needs: build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/project/dbt-hotdata/
permissions:
# Required for PyPI trusted publishing (OIDC) — no API token needed.
id-token: write
steps:
- uses: actions/download-artifact@v4
with:
name: dist
path: dist/

- uses: pypa/gh-action-pypi-publish@release/v1
Loading