Skip to content

Commit 22bf6ce

Browse files
authored
Add patch-release mode to upgrade script (#767)
With the new `--patch` option, `upgrade.sh` will now increment only the duckdb-rs crate patch version and leave DuckDB sources, generated bindings, and DuckDB download tags unchanged. Handy for Rust-only patch releases.
2 parents 2f11774 + e5c6785 commit 22bf6ce

3 files changed

Lines changed: 121 additions & 20 deletions

File tree

CONTRIBUTING.md

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,30 @@ cd ~/github/duckdb-rs
141141
ASAN_OPTIONS=detect_leaks=1 ASAN_SYMBOLIZER_PATH=/usr/local/opt/llvm/bin/llvm-symbolizer cargo test --features bundled -- --nocapture
142142
```
143143

144-
### Update to new version
144+
### Update to a new version
145145

146-
Everytime duckdb release to a new version, we also need to release a new version.
146+
When DuckDB releases a new version, duckdb-rs needs a matching release.
147+
148+
Use the top-level upgrade script for DuckDB version updates:
147149

148-
We can use the scripts to do the upgrades:
149150
```shell
150151
./upgrade.sh
151152
```
152-
Which use sed to update the version number and then call `./libduckdb-sys/upgrade.sh` to generated new bindings.
153153

154-
We may need to fix any error as duckdb's c-api may have breaking changes occasionally.
154+
This updates the workspace crate version, the exact workspace dependency pins
155+
that keep sibling crates in lockstep, README `Cargo.toml` examples, and DuckDB
156+
version references such as workflow tags and README download URLs. It then calls
157+
`./crates/libduckdb-sys/upgrade.sh` to regenerate bindings.
158+
159+
DuckDB's C API may occasionally have breaking changes, so version updates may
160+
also require code fixes.
161+
162+
For a duckdb-rs patch release that does not change the bundled DuckDB version:
163+
164+
```shell
165+
./upgrade.sh --patch
166+
```
167+
168+
Patch releases only update crate versions, exact workspace dependency pins,
169+
README `Cargo.toml` examples, and `Cargo.lock`. They do not update the DuckDB
170+
submodule, generated bindings, or DuckDB download tags.

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ These extensions are only available through the CMake build backend and imply `b
136136

137137
Starting with DuckDB `v1.5.0`, the duckdb-rs version encodes the DuckDB version in its second semver component.
138138
The format is `1.MAJOR_MINOR_PATCH.x`, e.g., DuckDB `v1.5.0` maps to duckdb-rs `1.10500.x`.
139+
Use a tilde requirement to receive duckdb-rs patch releases without automatically moving to a different bundled DuckDB version.
139140

140141
### Using stable releases from crates.io
141142

@@ -149,7 +150,7 @@ Or manually add it to your `Cargo.toml`:
149150

150151
```toml
151152
[dependencies]
152-
duckdb = { version = "=1.10503.0", features = ["bundled"] }
153+
duckdb = { version = "~1.10503.0", features = ["bundled"] }
153154
```
154155

155156
### Using the development version from git
@@ -188,7 +189,7 @@ You can adjust this behavior in a number of ways:
188189

189190
```toml
190191
[dependencies]
191-
duckdb = { version = "1.10503.0", features = ["bundled"] }
192+
duckdb = { version = "~1.10503.0", features = ["bundled"] }
192193
```
193194

194195
2. If you use the `bundled-cmake` feature, `libduckdb-sys` will build DuckDB from the local checkout in `crates/libduckdb-sys/duckdb-sources` using upstream CMake. This keeps plain `bundled` unchanged while allowing CMake-only extensions such as `icu`.

upgrade.sh

Lines changed: 97 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,20 @@ get_latest_release() {
1515
gh api "repos/$REPO/releases/latest" --jq '.tag_name'
1616
}
1717

18+
usage() {
19+
cat <<'EOF'
20+
Usage:
21+
./upgrade.sh [DUCKDB_VERSION]
22+
./upgrade.sh --patch
23+
24+
Without arguments, upgrade to the latest DuckDB release.
25+
With DUCKDB_VERSION, upgrade bundled DuckDB and reset the crate patch to 0.
26+
Full upgrades also update workflow and README download URLs and regenerate
27+
bindings. With --patch, increment only the duckdb-rs crate patch version and
28+
leave DuckDB sources, generated bindings, and DuckDB download tags unchanged.
29+
EOF
30+
}
31+
1832
current_workspace_version() {
1933
grep '^version = "' Cargo.toml | head -n1 | sed -E 's/version = "([^"]+)"/\1/'
2034
}
@@ -37,15 +51,93 @@ duckdb_version_to_crate_version() {
3751
printf '%s.%d%02d%02d.0' "$CRATE_MAJOR" "$DUCKDB_MAJOR" "$DUCKDB_MINOR" "$DUCKDB_PATCH"
3852
}
3953

40-
DUCKDB_VERSION=${1:-$(get_latest_release "duckdb/duckdb")}
41-
DUCKDB_VERSION="v${DUCKDB_VERSION#v}"
54+
valid_duckdb_version() {
55+
local DUCKDB_VERSION=${1#v}
56+
[[ "$DUCKDB_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]
57+
}
58+
59+
next_crate_patch_version() {
60+
local CRATE_VERSION=$1
61+
local MAJOR ENCODED PATCH
62+
IFS=. read -r MAJOR ENCODED PATCH <<<"$CRATE_VERSION"
63+
if [[ ! "$MAJOR" =~ ^[0-9]+$ || ! "$ENCODED" =~ ^[0-9]+$ || ! "$PATCH" =~ ^[0-9]+$ ]]; then
64+
echo "Invalid current crate version: $CRATE_VERSION" >&2
65+
exit 1
66+
fi
67+
printf '%s.%s.%s' "$MAJOR" "$ENCODED" "$((10#$PATCH + 1))"
68+
}
69+
70+
update_crate_versions() {
71+
cargo metadata --format-version 1 >/dev/null
72+
73+
sed_inplace "s!$CURRENT_CRATE_VERSION_PATTERN!$TARGET_CRATE_VERSION!g" \
74+
Cargo.toml \
75+
crates/duckdb/Cargo.toml \
76+
crates/libduckdb-sys/Cargo.toml \
77+
crates/duckdb-loadable-macros/Cargo.toml
78+
79+
# Update README Cargo.toml examples, not prose/history.
80+
sed_inplace "/version = \"/s!$CURRENT_CRATE_VERSION_PATTERN!$TARGET_CRATE_VERSION!g" README.md
81+
82+
local UPDATED_CRATE_VERSION
83+
UPDATED_CRATE_VERSION=$(current_workspace_version)
84+
if [ "$UPDATED_CRATE_VERSION" != "$TARGET_CRATE_VERSION" ]; then
85+
echo "Expected workspace version $TARGET_CRATE_VERSION, found $UPDATED_CRATE_VERSION" >&2
86+
exit 1
87+
fi
88+
89+
# Let Cargo rewrite Cargo.lock from the updated manifests instead of editing it as text.
90+
cargo metadata --format-version 1 >/dev/null
91+
}
92+
93+
PATCH_MODE=0
94+
95+
case "${1:-}" in
96+
-h|--help)
97+
usage
98+
exit 0
99+
;;
100+
--patch)
101+
PATCH_MODE=1
102+
if [ $# -ne 1 ]; then
103+
usage >&2
104+
exit 1
105+
fi
106+
;;
107+
-*)
108+
usage >&2
109+
exit 1
110+
;;
111+
esac
112+
113+
if [ "$PATCH_MODE" -eq 0 ] && [ $# -gt 1 ]; then
114+
usage >&2
115+
exit 1
116+
fi
117+
42118
CURRENT_CRATE_VERSION=$(current_workspace_version)
43119
CURRENT_DUCKDB_VERSION=$(crate_version_to_duckdb_version "$CURRENT_CRATE_VERSION")
44120
CRATE_MAJOR=$(echo "$CURRENT_CRATE_VERSION" | cut -d. -f1)
45-
TARGET_CRATE_VERSION=$(duckdb_version_to_crate_version "$DUCKDB_VERSION" "$CRATE_MAJOR")
46121
CURRENT_CRATE_VERSION_PATTERN=${CURRENT_CRATE_VERSION//./\\.}
47122
CURRENT_DUCKDB_VERSION_PATTERN=${CURRENT_DUCKDB_VERSION//./\\.}
48123

124+
if [ "$PATCH_MODE" -eq 1 ]; then
125+
TARGET_CRATE_VERSION=$(next_crate_patch_version "$CURRENT_CRATE_VERSION")
126+
echo "Start crate patch release for DuckDB $CURRENT_DUCKDB_VERSION"
127+
echo "Update crate version from $CURRENT_CRATE_VERSION to $TARGET_CRATE_VERSION"
128+
update_crate_versions
129+
exit 0
130+
fi
131+
132+
DUCKDB_VERSION=${1:-$(get_latest_release "duckdb/duckdb")}
133+
if ! valid_duckdb_version "$DUCKDB_VERSION"; then
134+
echo "Invalid DuckDB version: $DUCKDB_VERSION" >&2
135+
usage >&2
136+
exit 1
137+
fi
138+
DUCKDB_VERSION="v${DUCKDB_VERSION#v}"
139+
TARGET_CRATE_VERSION=$(duckdb_version_to_crate_version "$DUCKDB_VERSION" "$CRATE_MAJOR")
140+
49141
if [ "$DUCKDB_VERSION" = "$CURRENT_DUCKDB_VERSION" ]; then
50142
echo "Already up to date, latest DuckDB version is $DUCKDB_VERSION and workspace version is $CURRENT_CRATE_VERSION"
51143
exit 0
@@ -54,20 +146,12 @@ fi
54146
echo "Start to upgrade DuckDB from $CURRENT_DUCKDB_VERSION to $DUCKDB_VERSION"
55147
echo "Update crate version from $CURRENT_CRATE_VERSION to $TARGET_CRATE_VERSION"
56148

57-
sed_inplace "s!$CURRENT_CRATE_VERSION_PATTERN!$TARGET_CRATE_VERSION!g" \
58-
Cargo.toml \
59-
crates/duckdb/Cargo.toml \
60-
crates/libduckdb-sys/Cargo.toml \
61-
crates/duckdb-loadable-macros/Cargo.toml
149+
update_crate_versions
62150

63151
sed_inplace "s!$CURRENT_DUCKDB_VERSION_PATTERN!$DUCKDB_VERSION!g" \
64152
.github/workflows/rust.yaml
65153

66-
# Update README: only Cargo.toml examples and download URLs, not prose/history.
67-
sed_inplace "/version = \"/s!$CURRENT_CRATE_VERSION_PATTERN!$TARGET_CRATE_VERSION!g" README.md
154+
# Update README download URLs, not prose/history.
68155
sed_inplace "/releases\/download/s!$CURRENT_DUCKDB_VERSION_PATTERN!$DUCKDB_VERSION!g" README.md
69156

70-
# Let Cargo rewrite Cargo.lock from the updated manifests instead of editing it as text.
71-
cargo metadata --format-version 1 >/dev/null
72-
73157
exec ./crates/libduckdb-sys/upgrade.sh "$DUCKDB_VERSION"

0 commit comments

Comments
 (0)