ferro-orm 0.3.0__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.github/PERMISSIONS.md +3 -2
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.github/workflows/publish.yml +4 -0
- ferro_orm-0.3.2/.github/workflows/release.yml +374 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.gitignore +1 -2
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/CHANGELOG.md +69 -4
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/Cargo.lock +158 -11
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/Cargo.toml +2 -2
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/PKG-INFO +6 -4
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/README.md +2 -3
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/TEST_RESULTS.md +4 -2
- ferro_orm-0.3.2/docs/api/fields.md +21 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/coming-soon.md +6 -2
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/concepts/architecture.md +4 -2
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/concepts/performance.md +7 -3
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/getting-started/tutorial.md +13 -13
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/guide/database.md +43 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/guide/migrations.md +35 -7
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/guide/models-and-fields.md +39 -26
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/guide/queries.md +3 -3
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/guide/relationships.md +1 -1
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/howto/pagination.md +5 -3
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/index.md +3 -3
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/migration-sqlalchemy.md +9 -6
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/pyproject.toml +10 -7
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/__init__.py +2 -1
- ferro_orm-0.3.2/src/ferro/_annotation_utils.py +28 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/base.py +50 -1
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/composite_uniques.py +3 -2
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/fields.py +18 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/metaclass.py +7 -1
- ferro_orm-0.3.2/src/ferro/migrations/alembic.py +345 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/models.py +18 -4
- ferro_orm-0.3.2/tests/test_alembic_autogenerate.py +190 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_alembic_bridge.py +21 -1
- ferro_orm-0.3.2/tests/test_alembic_nullability.py +270 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_alembic_type_mapping.py +3 -1
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_composite_unique.py +16 -16
- ferro_orm-0.3.2/tests/test_field_wrapper.py +95 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/uv.lock +10 -7
- ferro_orm-0.3.0/.github/workflows/release.yml +0 -491
- ferro_orm-0.3.0/docs/api/fields.md +0 -21
- ferro_orm-0.3.0/src/ferro/migrations/alembic.py +0 -233
- ferro_orm-0.3.0/tests/test_alembic_autogenerate.py +0 -94
- ferro_orm-0.3.0/tests/test_field_wrapper.py +0 -47
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.github/PYPI_CHECKLIST.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.github/PYPI_SETUP.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.github/generated/wheels.generated.yml +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.github/pull_request_template.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.github/workflows/ci.yml +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.github/workflows/packaging-smoke.yml +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.github/workflows/publish-docs.yml +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.pre-commit-config.yaml +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/.python-version +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/CONTRIBUTING.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/LICENSE +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/api/model.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/api/query.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/api/relationships.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/api/transactions.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/api/utilities.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/changelog.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/concepts/identity-map.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/concepts/type-safety.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/contributing.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/faq.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/getting-started/installation.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/getting-started/next-steps.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/guide/mutations.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/guide/transactions.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/howto/multiple-databases.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/howto/soft-deletes.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/howto/testing.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/howto/timestamps.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/stylesheets/extra.css +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/docs/why-ferro.md +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/justfile +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/mkdocs.yml +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/scripts/demo_queries.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/connection.rs +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/_core.pyi +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/_shadow_fk_types.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/migrations/__init__.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/py.typed +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/query/__init__.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/query/builder.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/query/nodes.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/relations/__init__.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/relations/descriptors.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/ferro/state.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/lib.rs +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/operations.rs +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/query.rs +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/schema.rs +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/src/state.rs +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/conftest.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_aggregation.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_auto_migrate.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_bulk_update.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_connection.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_constraints.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_crud.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_deletion.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_docs_examples.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_documentation_features.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_helpers.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_hydration.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_metaclass_internals.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_metadata.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_models.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_one_to_one.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_query_builder.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_refresh.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_relationship_engine.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_schema.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_schema_constraints.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_shadow_fk_types.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_string_search.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_structural_types.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_temporal_types.py +0 -0
- {ferro_orm-0.3.0 → ferro_orm-0.3.2}/tests/test_transactions.py +0 -0
|
@@ -71,6 +71,7 @@ permissions:
|
|
|
71
71
|
- Add labels or comments to PRs
|
|
72
72
|
|
|
73
73
|
**What It Does:**
|
|
74
|
+
- **Preflight** builds all release wheels at the workflow SHA (same matrix as post-release wheel builds), in parallel with the CI gate and packaging smoke jobs. If any platform fails, the Create Release job does not run.
|
|
74
75
|
- Analyzes conventional commits
|
|
75
76
|
- Determines next version
|
|
76
77
|
- Updates version in both Python and Rust files
|
|
@@ -88,7 +89,7 @@ permissions:
|
|
|
88
89
|
|
|
89
90
|
### 2. Build & Publish (jobs in `release.yml`)
|
|
90
91
|
|
|
91
|
-
**Trigger:** Part of `release.yml` after the
|
|
92
|
+
**Trigger:** Part of `release.yml` after the Create Release job (no reusable workflow). Wheel preflight runs in parallel with CI and packaging smoke, before that job.
|
|
92
93
|
|
|
93
94
|
Build, test, and publish jobs are defined directly in `release.yml` so PyPI Trusted Publishing receives a token with `workflow_ref: release.yml` (reusable workflows are not supported by PyPI).
|
|
94
95
|
|
|
@@ -248,7 +249,7 @@ Permission to manage GitHub Pages deployments:
|
|
|
248
249
|
|
|
249
250
|
### Release Completed But Publish/Docs Did Not Run
|
|
250
251
|
|
|
251
|
-
**Cause:** `release.yml` gates downstream jobs. If CI, packaging smoke, or release creation fails, publish/docs are skipped.
|
|
252
|
+
**Cause:** `release.yml` gates downstream jobs. If CI, packaging smoke, preflight wheel builds, or release creation fails, publish/docs are skipped.
|
|
252
253
|
|
|
253
254
|
**Solution:**
|
|
254
255
|
- Open the failed `release.yml` run and inspect the first failed job.
|
|
@@ -60,6 +60,10 @@ jobs:
|
|
|
60
60
|
|
|
61
61
|
- name: Build wheels
|
|
62
62
|
uses: PyO3/maturin-action@v1.48.0
|
|
63
|
+
env:
|
|
64
|
+
# ring (via rustls/sqlx): manylinux2014-cross gcc does not define __ARM_ARCH for .S asm.
|
|
65
|
+
# https://github.com/briansmith/ring/issues/1728
|
|
66
|
+
CFLAGS_aarch64_unknown_linux_gnu: ${{ matrix.platform.name == 'linux-aarch64' && '-D__ARM_ARCH=8' || '' }}
|
|
63
67
|
with:
|
|
64
68
|
target: ${{ matrix.platform.target }}
|
|
65
69
|
args: --release --out dist --find-interpreter
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
prerelease:
|
|
7
|
+
description: 'Create a pre-release'
|
|
8
|
+
required: false
|
|
9
|
+
type: boolean
|
|
10
|
+
default: false
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: release-${{ github.workflow }}-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
# Same maturin targets as build-wheels, but against the current ref *before*
|
|
18
|
+
# semantic-release mutates the repo. Runs in parallel with CI gate and
|
|
19
|
+
# packaging smoke so the wall-clock pipeline stays shorter.
|
|
20
|
+
preflight-build-wheels:
|
|
21
|
+
name: Preflight build wheels (${{ matrix.platform.name }})
|
|
22
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
23
|
+
strategy:
|
|
24
|
+
fail-fast: false
|
|
25
|
+
matrix:
|
|
26
|
+
platform:
|
|
27
|
+
- name: linux-x86_64
|
|
28
|
+
runner: ubuntu-latest
|
|
29
|
+
target: x86_64
|
|
30
|
+
manylinux: auto
|
|
31
|
+
- name: linux-aarch64
|
|
32
|
+
runner: ubuntu-latest
|
|
33
|
+
target: aarch64
|
|
34
|
+
manylinux: auto
|
|
35
|
+
- name: macos-aarch64
|
|
36
|
+
runner: macos-latest
|
|
37
|
+
target: aarch64
|
|
38
|
+
manylinux: ''
|
|
39
|
+
- name: windows-x64
|
|
40
|
+
runner: windows-latest
|
|
41
|
+
target: x64
|
|
42
|
+
manylinux: ''
|
|
43
|
+
|
|
44
|
+
steps:
|
|
45
|
+
- name: Checkout repository
|
|
46
|
+
uses: actions/checkout@v4
|
|
47
|
+
with:
|
|
48
|
+
ref: ${{ github.sha }}
|
|
49
|
+
|
|
50
|
+
- name: Set up Python
|
|
51
|
+
uses: actions/setup-python@v5
|
|
52
|
+
with:
|
|
53
|
+
python-version: '3.13'
|
|
54
|
+
|
|
55
|
+
- name: Build wheels (preflight)
|
|
56
|
+
uses: PyO3/maturin-action@v1.48.0
|
|
57
|
+
env:
|
|
58
|
+
# ring (via rustls/sqlx): manylinux2014-cross gcc does not define __ARM_ARCH for .S asm.
|
|
59
|
+
# https://github.com/briansmith/ring/issues/1728
|
|
60
|
+
CFLAGS_aarch64_unknown_linux_gnu: ${{ matrix.platform.name == 'linux-aarch64' && '-D__ARM_ARCH=8' || '' }}
|
|
61
|
+
with:
|
|
62
|
+
target: ${{ matrix.platform.target }}
|
|
63
|
+
args: --release --out dist --find-interpreter
|
|
64
|
+
manylinux: ${{ matrix.platform.manylinux }}
|
|
65
|
+
sccache: 'true'
|
|
66
|
+
|
|
67
|
+
ci-gate:
|
|
68
|
+
name: CI Gate
|
|
69
|
+
uses: ./.github/workflows/ci.yml
|
|
70
|
+
|
|
71
|
+
packaging-smoke:
|
|
72
|
+
name: Packaging Smoke Gate
|
|
73
|
+
uses: ./.github/workflows/packaging-smoke.yml
|
|
74
|
+
|
|
75
|
+
release:
|
|
76
|
+
name: Create Release
|
|
77
|
+
needs: [ci-gate, packaging-smoke, preflight-build-wheels]
|
|
78
|
+
runs-on: ubuntu-latest
|
|
79
|
+
outputs:
|
|
80
|
+
release_created: ${{ steps.verify_release.outputs.release_created }}
|
|
81
|
+
release_ref: ${{ steps.release_ref.outputs.release_ref }}
|
|
82
|
+
permissions:
|
|
83
|
+
contents: write
|
|
84
|
+
issues: write
|
|
85
|
+
pull-requests: write
|
|
86
|
+
|
|
87
|
+
steps:
|
|
88
|
+
- name: Checkout repository
|
|
89
|
+
uses: actions/checkout@v4
|
|
90
|
+
with:
|
|
91
|
+
fetch-depth: 0
|
|
92
|
+
ssh-key: ${{ secrets.RELEASE_DEPLOY_KEY }}
|
|
93
|
+
persist-credentials: false
|
|
94
|
+
|
|
95
|
+
- name: Set up Python
|
|
96
|
+
uses: actions/setup-python@v5
|
|
97
|
+
with:
|
|
98
|
+
python-version: '3.13'
|
|
99
|
+
|
|
100
|
+
- name: Install UV
|
|
101
|
+
uses: astral-sh/setup-uv@v5
|
|
102
|
+
with:
|
|
103
|
+
enable-cache: true
|
|
104
|
+
|
|
105
|
+
- name: Set up Rust
|
|
106
|
+
uses: dtolnay/rust-toolchain@stable
|
|
107
|
+
|
|
108
|
+
- name: Cache Rust dependencies
|
|
109
|
+
uses: Swatinem/rust-cache@v2
|
|
110
|
+
with:
|
|
111
|
+
prefix-key: "v1-rust"
|
|
112
|
+
|
|
113
|
+
- name: Install dependencies
|
|
114
|
+
run: |
|
|
115
|
+
uv sync --only-group release --no-install-project --python 3.13
|
|
116
|
+
|
|
117
|
+
- name: Configure Git
|
|
118
|
+
run: |
|
|
119
|
+
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
|
120
|
+
git config --local user.name "github-actions[bot]"
|
|
121
|
+
git remote set-url origin "git@github.com:${{ github.repository }}.git"
|
|
122
|
+
|
|
123
|
+
- name: Run semantic-release
|
|
124
|
+
env:
|
|
125
|
+
# Prefer a PAT so release events can trigger downstream workflows.
|
|
126
|
+
GH_TOKEN: ${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }}
|
|
127
|
+
run: |
|
|
128
|
+
# Use the --prerelease flag if requested via manual trigger
|
|
129
|
+
PRERELEASE_FLAG=""
|
|
130
|
+
if [ "${{ github.event.inputs.prerelease }}" == "true" ]; then
|
|
131
|
+
PRERELEASE_FLAG="--prerelease"
|
|
132
|
+
fi
|
|
133
|
+
|
|
134
|
+
# This command will:
|
|
135
|
+
# 1. Bump version in pyproject.toml and Cargo.toml
|
|
136
|
+
# 2. Update CHANGELOG.md
|
|
137
|
+
# 3. Create a commit and push it
|
|
138
|
+
# 4. Create a tag and push it
|
|
139
|
+
# 5. Create a GitHub Release (publishing is handled by the wheels/publish workflow)
|
|
140
|
+
uv run semantic-release version $PRERELEASE_FLAG
|
|
141
|
+
|
|
142
|
+
- name: Verify release commit updates changelog
|
|
143
|
+
id: verify_release
|
|
144
|
+
shell: bash
|
|
145
|
+
run: |
|
|
146
|
+
LAST_SUBJECT="$(git log -1 --pretty=%s)"
|
|
147
|
+
if [[ "$LAST_SUBJECT" != chore\(release\):* ]]; then
|
|
148
|
+
echo "No release commit created in this run; skipping changelog validation."
|
|
149
|
+
echo "release_created=false" >> "$GITHUB_OUTPUT"
|
|
150
|
+
echo "changelog_validated=skipped" >> "$GITHUB_OUTPUT"
|
|
151
|
+
echo "release_subject=$LAST_SUBJECT" >> "$GITHUB_OUTPUT"
|
|
152
|
+
exit 0
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
echo "release_created=true" >> "$GITHUB_OUTPUT"
|
|
156
|
+
echo "release_subject=$LAST_SUBJECT" >> "$GITHUB_OUTPUT"
|
|
157
|
+
|
|
158
|
+
CHANGED_FILES="$(git show --name-only --pretty='' HEAD)"
|
|
159
|
+
if [[ "$CHANGED_FILES" != *"CHANGELOG.md"* ]]; then
|
|
160
|
+
echo "WARNING: release commit does not include CHANGELOG.md update."
|
|
161
|
+
echo "Changed files:"
|
|
162
|
+
echo "$CHANGED_FILES"
|
|
163
|
+
echo "changelog_validated=missing" >> "$GITHUB_OUTPUT"
|
|
164
|
+
exit 0
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
echo "changelog_validated=passed" >> "$GITHUB_OUTPUT"
|
|
168
|
+
echo "Validated: release commit includes CHANGELOG.md."
|
|
169
|
+
|
|
170
|
+
- name: Capture released ref
|
|
171
|
+
id: release_ref
|
|
172
|
+
shell: bash
|
|
173
|
+
run: |
|
|
174
|
+
if [[ "${{ steps.verify_release.outputs.release_created }}" != "true" ]]; then
|
|
175
|
+
echo "release_ref=" >> "$GITHUB_OUTPUT"
|
|
176
|
+
exit 0
|
|
177
|
+
fi
|
|
178
|
+
|
|
179
|
+
RELEASE_TAG="$(git tag --points-at HEAD | head -n1)"
|
|
180
|
+
if [[ -z "$RELEASE_TAG" ]]; then
|
|
181
|
+
echo "ERROR: expected release tag on HEAD but none was found."
|
|
182
|
+
exit 1
|
|
183
|
+
fi
|
|
184
|
+
|
|
185
|
+
echo "release_ref=$RELEASE_TAG" >> "$GITHUB_OUTPUT"
|
|
186
|
+
echo "Using release ref: $RELEASE_TAG"
|
|
187
|
+
|
|
188
|
+
- name: Release summary
|
|
189
|
+
if: always()
|
|
190
|
+
shell: bash
|
|
191
|
+
run: |
|
|
192
|
+
{
|
|
193
|
+
echo "## Release workflow summary"
|
|
194
|
+
echo ""
|
|
195
|
+
echo "- Trigger: \`${{ github.event_name }}\`"
|
|
196
|
+
echo "- Ref: \`${{ github.ref_name }}\`"
|
|
197
|
+
echo "- Release commit created: \`${{ steps.verify_release.outputs.release_created || 'unknown' }}\`"
|
|
198
|
+
echo "- Changelog validation: \`${{ steps.verify_release.outputs.changelog_validated || 'unknown' }}\`"
|
|
199
|
+
echo "- Release ref: \`${{ steps.release_ref.outputs.release_ref || 'n/a' }}\`"
|
|
200
|
+
echo "- Last commit subject: \`${{ steps.verify_release.outputs.release_subject || 'n/a' }}\`"
|
|
201
|
+
} >> "$GITHUB_STEP_SUMMARY"
|
|
202
|
+
|
|
203
|
+
# Build and publish jobs are inlined here (not in a reusable workflow) so that
|
|
204
|
+
# PyPI Trusted Publishing sees workflow_ref = release.yml. Reusable workflows
|
|
205
|
+
# are not supported by PyPI Trusted Publishing.
|
|
206
|
+
build-wheels:
|
|
207
|
+
name: Build wheels (${{ matrix.platform.name }})
|
|
208
|
+
needs: [release]
|
|
209
|
+
if: needs.release.outputs.release_created == 'true'
|
|
210
|
+
runs-on: ${{ matrix.platform.runner }}
|
|
211
|
+
strategy:
|
|
212
|
+
fail-fast: false
|
|
213
|
+
matrix:
|
|
214
|
+
platform:
|
|
215
|
+
- name: linux-x86_64
|
|
216
|
+
runner: ubuntu-latest
|
|
217
|
+
target: x86_64
|
|
218
|
+
manylinux: auto
|
|
219
|
+
- name: linux-aarch64
|
|
220
|
+
runner: ubuntu-latest
|
|
221
|
+
target: aarch64
|
|
222
|
+
manylinux: auto
|
|
223
|
+
- name: macos-aarch64
|
|
224
|
+
runner: macos-latest
|
|
225
|
+
target: aarch64
|
|
226
|
+
manylinux: ''
|
|
227
|
+
- name: windows-x64
|
|
228
|
+
runner: windows-latest
|
|
229
|
+
target: x64
|
|
230
|
+
manylinux: ''
|
|
231
|
+
|
|
232
|
+
steps:
|
|
233
|
+
- name: Checkout repository
|
|
234
|
+
uses: actions/checkout@v4
|
|
235
|
+
with:
|
|
236
|
+
ref: ${{ needs.release.outputs.release_ref }}
|
|
237
|
+
|
|
238
|
+
- name: Set up Python
|
|
239
|
+
uses: actions/setup-python@v5
|
|
240
|
+
with:
|
|
241
|
+
python-version: '3.13'
|
|
242
|
+
|
|
243
|
+
- name: Build wheels
|
|
244
|
+
uses: PyO3/maturin-action@v1.48.0
|
|
245
|
+
env:
|
|
246
|
+
# ring (via rustls/sqlx): manylinux2014-cross gcc does not define __ARM_ARCH for .S asm.
|
|
247
|
+
# https://github.com/briansmith/ring/issues/1728
|
|
248
|
+
CFLAGS_aarch64_unknown_linux_gnu: ${{ matrix.platform.name == 'linux-aarch64' && '-D__ARM_ARCH=8' || '' }}
|
|
249
|
+
with:
|
|
250
|
+
target: ${{ matrix.platform.target }}
|
|
251
|
+
args: --release --out dist --find-interpreter
|
|
252
|
+
manylinux: ${{ matrix.platform.manylinux }}
|
|
253
|
+
sccache: 'true'
|
|
254
|
+
|
|
255
|
+
- name: Upload wheels
|
|
256
|
+
uses: actions/upload-artifact@v4
|
|
257
|
+
with:
|
|
258
|
+
name: wheels-${{ matrix.platform.name }}
|
|
259
|
+
path: dist/*.whl
|
|
260
|
+
|
|
261
|
+
build-sdist:
|
|
262
|
+
name: Build sdist
|
|
263
|
+
needs: [release]
|
|
264
|
+
if: needs.release.outputs.release_created == 'true'
|
|
265
|
+
runs-on: ubuntu-latest
|
|
266
|
+
steps:
|
|
267
|
+
- name: Checkout repository
|
|
268
|
+
uses: actions/checkout@v4
|
|
269
|
+
with:
|
|
270
|
+
ref: ${{ needs.release.outputs.release_ref }}
|
|
271
|
+
|
|
272
|
+
- name: Build sdist
|
|
273
|
+
uses: PyO3/maturin-action@v1.48.0
|
|
274
|
+
with:
|
|
275
|
+
command: sdist
|
|
276
|
+
args: --out dist
|
|
277
|
+
|
|
278
|
+
- name: Upload sdist
|
|
279
|
+
uses: actions/upload-artifact@v4
|
|
280
|
+
with:
|
|
281
|
+
name: sdist
|
|
282
|
+
path: dist/*.tar.gz
|
|
283
|
+
|
|
284
|
+
test-wheels:
|
|
285
|
+
name: Test wheels (${{ matrix.os }})
|
|
286
|
+
needs: [release, build-wheels]
|
|
287
|
+
if: needs.release.outputs.release_created == 'true'
|
|
288
|
+
runs-on: ${{ matrix.os }}
|
|
289
|
+
strategy:
|
|
290
|
+
fail-fast: false
|
|
291
|
+
matrix:
|
|
292
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
293
|
+
steps:
|
|
294
|
+
- name: Checkout repository
|
|
295
|
+
uses: actions/checkout@v4
|
|
296
|
+
with:
|
|
297
|
+
ref: ${{ needs.release.outputs.release_ref }}
|
|
298
|
+
|
|
299
|
+
- name: Set up Python
|
|
300
|
+
uses: actions/setup-python@v5
|
|
301
|
+
with:
|
|
302
|
+
python-version: '3.13'
|
|
303
|
+
|
|
304
|
+
- name: Download wheels
|
|
305
|
+
uses: actions/download-artifact@v4
|
|
306
|
+
with:
|
|
307
|
+
path: dist
|
|
308
|
+
pattern: wheels-*
|
|
309
|
+
merge-multiple: true
|
|
310
|
+
|
|
311
|
+
- name: Install wheel
|
|
312
|
+
shell: bash
|
|
313
|
+
run: |
|
|
314
|
+
python -m pip install --upgrade pip
|
|
315
|
+
python -m pip install --find-links dist ferro-orm
|
|
316
|
+
|
|
317
|
+
- name: Test import
|
|
318
|
+
shell: bash
|
|
319
|
+
run: |
|
|
320
|
+
python -c "import ferro; print('Ferro imported successfully')"
|
|
321
|
+
|
|
322
|
+
- name: Run basic smoke test
|
|
323
|
+
shell: bash
|
|
324
|
+
run: |
|
|
325
|
+
python -c "
|
|
326
|
+
import asyncio
|
|
327
|
+
from ferro import Model, FerroField, connect
|
|
328
|
+
from typing import Annotated
|
|
329
|
+
|
|
330
|
+
class TestModel(Model):
|
|
331
|
+
id: Annotated[int, FerroField(primary_key=True)]
|
|
332
|
+
name: str
|
|
333
|
+
|
|
334
|
+
async def test():
|
|
335
|
+
await connect('sqlite::memory:')
|
|
336
|
+
print('Connection test passed')
|
|
337
|
+
|
|
338
|
+
asyncio.run(test())
|
|
339
|
+
"
|
|
340
|
+
|
|
341
|
+
publish-pypi:
|
|
342
|
+
name: Publish to PyPI
|
|
343
|
+
needs: [release, build-wheels, build-sdist, test-wheels]
|
|
344
|
+
if: needs.release.outputs.release_created == 'true'
|
|
345
|
+
runs-on: ubuntu-latest
|
|
346
|
+
environment:
|
|
347
|
+
name: pypi
|
|
348
|
+
url: https://pypi.org/p/ferro-orm
|
|
349
|
+
permissions:
|
|
350
|
+
id-token: write
|
|
351
|
+
steps:
|
|
352
|
+
- name: Download all artifacts
|
|
353
|
+
uses: actions/download-artifact@v4
|
|
354
|
+
with:
|
|
355
|
+
path: dist
|
|
356
|
+
merge-multiple: true
|
|
357
|
+
|
|
358
|
+
- name: Publish to PyPI
|
|
359
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
360
|
+
with:
|
|
361
|
+
skip-existing: true
|
|
362
|
+
verbose: true
|
|
363
|
+
|
|
364
|
+
deploy-docs:
|
|
365
|
+
name: Deploy Documentation
|
|
366
|
+
needs: [release, publish-pypi]
|
|
367
|
+
if: needs.release.outputs.release_created == 'true'
|
|
368
|
+
uses: ./.github/workflows/publish-docs.yml
|
|
369
|
+
permissions:
|
|
370
|
+
contents: read
|
|
371
|
+
pages: write
|
|
372
|
+
id-token: write
|
|
373
|
+
with:
|
|
374
|
+
ref: ${{ needs.release.outputs.release_ref }}
|
|
@@ -1,7 +1,75 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
## v0.3.
|
|
4
|
+
## v0.3.2 (2026-04-24)
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
- Move alembic reqs to optional dependencies
|
|
9
|
+
([`87f0e81`](https://github.com/syn54x/ferro-orm/commit/87f0e8157640ac9984da20e0c4c7290dbfcf4bfd))
|
|
10
|
+
|
|
11
|
+
### Build System
|
|
12
|
+
|
|
13
|
+
- **sqlx**: Enable rustls TLS for PostgreSQL connections
|
|
14
|
+
([`807fa81`](https://github.com/syn54x/ferro-orm/commit/807fa8196a3742a5a50380fe6dbf727045798cc3))
|
|
15
|
+
|
|
16
|
+
### Chores
|
|
17
|
+
|
|
18
|
+
- Sync uv.lock with project version 0.3.1
|
|
19
|
+
([`c3c9f91`](https://github.com/syn54x/ferro-orm/commit/c3c9f91907a3ece8ce7bc70f08979f1dd269a87c))
|
|
20
|
+
|
|
21
|
+
### Continuous Integration
|
|
22
|
+
|
|
23
|
+
- Build preflight wheels earlier to fail faster
|
|
24
|
+
([`475c93c`](https://github.com/syn54x/ferro-orm/commit/475c93caa1d51fb07d7eda875205086761d64e8f))
|
|
25
|
+
|
|
26
|
+
- Fix linux-aarch64 wheel builds for ring/rustls asm
|
|
27
|
+
([`5eadddc`](https://github.com/syn54x/ferro-orm/commit/5eadddc922b51448ad4da3841a84fd4931b19814))
|
|
28
|
+
|
|
29
|
+
- Gate release on preflight wheel builds for all platforms
|
|
30
|
+
([`6ec48a2`](https://github.com/syn54x/ferro-orm/commit/6ec48a275b8dc9868612a3f374595ce63fe151ca))
|
|
31
|
+
|
|
32
|
+
- Restore legacy release workflow
|
|
33
|
+
([`d3ee87c`](https://github.com/syn54x/ferro-orm/commit/d3ee87c68995a1163480eb9be8a3111032e94842))
|
|
34
|
+
|
|
35
|
+
### Documentation
|
|
36
|
+
|
|
37
|
+
- Add Supabase PostgreSQL connection and TLS guidance
|
|
38
|
+
([`b1d61ad`](https://github.com/syn54x/ferro-orm/commit/b1d61ad4395a17c7c2270c1d4776500c436c22d1))
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
## v0.3.1 (2026-04-23)
|
|
42
|
+
|
|
43
|
+
### Bug Fixes
|
|
44
|
+
|
|
45
|
+
- Alembic autogenerate named SQLAlchemy enums for PostgreSQL
|
|
46
|
+
([`25a00e8`](https://github.com/syn54x/ferro-orm/commit/25a00e84502ae1f8ba502718934d93eedfa4ce09))
|
|
47
|
+
|
|
48
|
+
- **migrations**: Align nullable inference with field types
|
|
49
|
+
([`885f0fe`](https://github.com/syn54x/ferro-orm/commit/885f0fe155dfa643e29b9425ff1ede62f3f0b269))
|
|
50
|
+
|
|
51
|
+
- **migrations**: Propagate ForeignKey(unique=True) to Alembic metadata
|
|
52
|
+
([#22](https://github.com/syn54x/ferro-orm/pull/22),
|
|
53
|
+
[`9329e8f`](https://github.com/syn54x/ferro-orm/commit/9329e8fba2f0efd201bea4545393654c7d1dd34e))
|
|
54
|
+
|
|
55
|
+
### Continuous Integration
|
|
56
|
+
|
|
57
|
+
- Fix release
|
|
58
|
+
([`e2822f6`](https://github.com/syn54x/ferro-orm/commit/e2822f6c9bacc6fc955e56b2ca8e120cc22b0b72))
|
|
59
|
+
|
|
60
|
+
- Fix release
|
|
61
|
+
([`e5c1adc`](https://github.com/syn54x/ferro-orm/commit/e5c1adcc10eb44845ef95d78226840ecdbfd0ebd))
|
|
62
|
+
|
|
63
|
+
- Fix release
|
|
64
|
+
([`688d01b`](https://github.com/syn54x/ferro-orm/commit/688d01bdae0aff1f82e4a1bb60dd1b8ab35e1d01))
|
|
65
|
+
|
|
66
|
+
### Documentation
|
|
67
|
+
|
|
68
|
+
- Prefer Field over FerroField
|
|
69
|
+
([`3385cfa`](https://github.com/syn54x/ferro-orm/commit/3385cfadf0951f80827dac1aa08f73430a02023f))
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
## v0.3.0 (2026-04-23)
|
|
5
73
|
|
|
6
74
|
### Bug Fixes
|
|
7
75
|
|
|
@@ -18,9 +86,6 @@
|
|
|
18
86
|
|
|
19
87
|
### Continuous Integration
|
|
20
88
|
|
|
21
|
-
- Fix release
|
|
22
|
-
([`688d01b`](https://github.com/syn54x/ferro-orm/commit/688d01bdae0aff1f82e4a1bb60dd1b8ab35e1d01))
|
|
23
|
-
|
|
24
89
|
- Fix release
|
|
25
90
|
([`249e460`](https://github.com/syn54x/ferro-orm/commit/249e46058bac87215920083a9d45557f3c58b62f))
|
|
26
91
|
|