Skip to content

Commit 1b7a381

Browse files
committed
Add release script
This release script will create patch branches so CI is also updated to run on patch branches.
1 parent 3c6b67a commit 1b7a381

File tree

4 files changed

+257
-37
lines changed

4 files changed

+257
-37
lines changed

.github/workflows/rust.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
name: Rust - Continuous Integration
22

33
on:
4-
push:
5-
branches: [ master ]
64
pull_request:
7-
branches: [ master ]
5+
push:
6+
branches:
7+
- master
8+
- '[0-9]+.[0-9]+'
89

910
env:
1011
CARGO_TERM_COLOR: always

Cargo.toml

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,51 @@
1-
[package]
2-
name = "modular-bitfield"
3-
version = "0.11.2"
4-
edition = "2021"
1+
[workspace]
2+
members = [
3+
"impl"
4+
]
5+
resolver = "2"
6+
7+
[workspace.package]
58
authors = ["Robin Freyler <[email protected]>"]
9+
edition = "2021"
610
license = "MIT OR Apache-2.0"
7-
readme = "README.md"
8-
9-
repository = "https://github.com/robbepop/modular-bitfield"
11+
publish = false # Use `release.sh`
1012
documentation = "https://docs.rs/modular-bitfield"
11-
description = "Allows to easily define bitfield types with modular building blocks."
13+
repository = "https://github.com/Robbepop/modular-bitfield"
14+
rust-version = "1.56.0"
15+
version = "0.12.0-pre"
16+
17+
[package]
18+
name = "modular-bitfield"
19+
description = "Easily define bitfield types with modular building blocks."
1220
categories = ["data-structures", "no-std"]
13-
keywords = ["bitfield", "bit", "bitfields"]
21+
keywords = ["bitfield", "bit", "bitfields"]
22+
readme = "README.md"
23+
authors.workspace = true
24+
documentation.workspace = true
25+
edition.workspace = true
26+
license.workspace = true
27+
publish.workspace = true
28+
repository.workspace = true
29+
rust-version.workspace = true
30+
version.workspace = true
31+
32+
[dependencies]
33+
modular-bitfield-impl = { path = "impl", version = "0.12.0-pre" }
34+
static_assertions = "1.1"
1435

1536
[dev-dependencies]
37+
# To run benchmarks, these packages need to be present, but until
38+
# <https://github.com/rust-lang/cargo/issues/1596> is fixed, there is no way to
39+
# have conditional dev-dependencies. Criterion is a fat dependency with its own
40+
# fat dependencies and this causes dev builds to take longer than they need to.
41+
# Until the benches can be rewritten to use libtest or similar just disable
42+
# building these crates, since they are practically never used. (Using a regular
43+
# conditional feature would work, but that would cause this feature and these
44+
# packages to show up as optional runtime dependencies, which they never
45+
# actually are.)
46+
# bitfield = "0.19"
47+
# criterion = "0.5"
1648
trybuild = "1.0"
17-
criterion = "0.5"
18-
bitfield = "0.19"
1949

2050
[[bench]]
2151
name = "benchmarks"
@@ -36,14 +66,5 @@ harness = false
3666
name = "playground"
3767
path = "playground.rs"
3868

39-
[dependencies]
40-
modular-bitfield-impl = { path = "impl", version = "0.11.2" }
41-
static_assertions = "1.1"
42-
4369
[profile.bench]
4470
codegen-units = 1
45-
46-
[workspace]
47-
members = [
48-
"impl"
49-
]

impl/Cargo.toml

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
[package]
22
name = "modular-bitfield-impl"
3-
version = "0.11.2"
4-
edition = "2018"
5-
authors = ["Robin Freyler <[email protected]>"]
6-
license = "MIT OR Apache-2.0"
7-
readme = "../README.md"
8-
9-
repository = "https://github.com/robbepop/modular-bitfield"
10-
documentation = "https://docs.rs/modular-bitfield"
11-
description = "Bitfields for structs that allow for modular use of enums."
12-
categories = ["data-structures"]
13-
keywords = ["bitfield", "bit", "bitfields"]
3+
description = "Derive macro for modular-bitfield"
4+
authors.workspace = true
5+
documentation.workspace = true
6+
edition.workspace = true
7+
license.workspace = true
8+
publish.workspace = true
9+
repository.workspace = true
10+
rust-version.workspace = true
11+
version.workspace = true
1412

1513
[lib]
1614
proc-macro = true
@@ -19,6 +17,3 @@ proc-macro = true
1917
quote = "1"
2018
syn = { version = "2", features = ["full"] }
2119
proc-macro2 = "1"
22-
23-
[dev-dependencies]
24-
modular-bitfield = { path = "..", version = "0.11.2" }

release.sh

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
#!/usr/bin/env bash
2+
3+
set -ueo pipefail
4+
5+
DEFAULT_REPO=Robbepop/modular-bitfield
6+
DEFAULT_BRANCH=master
7+
8+
usage() {
9+
echo "Usage: $0 [branch] [version]"
10+
echo
11+
echo "Specifying a branch will create a new patch release from that branch."
12+
echo "Otherwise, a new release will be created from '$DEFAULT_BRANCH'."
13+
echo
14+
echo "Specifying a version will create a release with that specific version."
15+
echo "Otherwise, the version number for the release will be adapted from"
16+
echo "Cargo.toml."
17+
echo
18+
echo "After tagging, the version number in Cargo.toml will automatically be"
19+
echo "bumped unless a pre-release version number was passed explicitly to"
20+
echo "this script, in which case the version number in Cargo.toml will be"
21+
echo "restored."
22+
echo
23+
echo "If the version number for the new release ends in .0, a new minor"
24+
echo "release branch will also be created."
25+
echo
26+
echo "Supported environment variables:"
27+
echo " REPO: The GitHub repository (user/repo) to use for the release."
28+
echo " Defaults to $DEFAULT_REPO."
29+
exit 0
30+
}
31+
32+
set_package_publish() {
33+
sed -i'' -e "s/^\\(publish[[:space:]]*=[[:space:]]*\\).*$/\\1$1/" Cargo.toml
34+
}
35+
36+
set_package_version() {
37+
sed -i'' -e "s/^\\(version[[:space:]]*=[[:space:]]*\\)\"[^\"]*\"/\\1\"$1\"/" Cargo.toml
38+
sed -i'' -e "s/^\\(modular-bitfield-impl[[:space:]]*=.*version[[:space:]]*=[[:space:]]*\\)\"[^\"]*\"/\\1\"$1\"/" Cargo.toml
39+
}
40+
41+
if [ "${1-}" == "--help" ]; then
42+
usage
43+
elif [ -n "${1-}" ]; then
44+
BRANCH=$1
45+
else
46+
BRANCH=$DEFAULT_BRANCH
47+
fi
48+
49+
if [ -n "${2-}" ]; then
50+
VERSION=$2
51+
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-.*)?$ ]]; then
52+
echo "Invalid version '$VERSION'; versions must be in the form"
53+
echo "\`major.minor.patch[-extra]\`."
54+
exit 1
55+
fi
56+
else
57+
VERSION=
58+
fi
59+
60+
REPO=${REPO:-$DEFAULT_REPO}
61+
ROOT_DIR=$(cd "$(dirname "$0")" && pwd)
62+
BUILD_DIR="$ROOT_DIR/build-release"
63+
64+
if [ -d "$BUILD_DIR" ]; then
65+
echo "Existing build directory detected at $BUILD_DIR"
66+
echo "Aborted."
67+
exit 1
68+
fi
69+
70+
echo "This is an internal modular-bitfield release script!"
71+
echo -n "Press 'y' to create a new modular-bitfield release from $REPO branch $BRANCH"
72+
if [ -z "$VERSION" ]; then
73+
echo "."
74+
else
75+
echo -e "\nwith version override $VERSION."
76+
fi
77+
echo "(You can abort pushing upstream later on if something goes wrong.)"
78+
read -r -s -n 1
79+
80+
if [ "$REPLY" != "y" ]; then
81+
echo "Aborted."
82+
exit 0
83+
fi
84+
85+
# Using a pristine copy of the repo for the release to avoid local changes
86+
# making their way into the release process, and to avoid polluting the local
87+
# repo with wrong changes if the release process is aborted
88+
cd "$ROOT_DIR"
89+
mkdir "$BUILD_DIR"
90+
git clone --recursive "[email protected]:$REPO" "$BUILD_DIR"
91+
92+
cd "$BUILD_DIR"
93+
94+
# Newly created tags and updated branches are stored so they can be pushed all
95+
# at once at the end after the other work is guaranteed to be successful
96+
PUSH_BRANCHES="$BRANCH"
97+
98+
echo -e "\nBuilding $BRANCH branch...\n"
99+
100+
git checkout "$BRANCH"
101+
102+
# head is needed in case the version number was manually updated to something
103+
# which has a tag with a number in it, otherwise there will be multiple matches
104+
# on the line instead of just the first one
105+
VERSION_CARGO_NO_TAGS=$(grep -o '^version[[:space:]]*=[[:space:]]*"[^"]*"' Cargo.toml | grep -o "[0-9][0-9.]*" | head -1)
106+
107+
if [ -z "$VERSION" ]; then
108+
VERSION=$VERSION_CARGO_NO_TAGS
109+
VERSION_NO_TAGS=$VERSION_CARGO_NO_TAGS
110+
else
111+
VERSION_NO_TAGS=$(echo "$VERSION" | grep -o "[0-9][0-9.]*")
112+
fi
113+
114+
# Converting the version number to an array to auto-generate the next
115+
# release version number
116+
IFS="." read -r -a PRE_VERSION_SPLIT <<< "$VERSION_NO_TAGS"
117+
118+
if [[ "$VERSION" =~ ^[0-9][0-9.]*\.0$ ]]; then
119+
# Minor release gets a branch
120+
MAKE_BRANCH="${PRE_VERSION_SPLIT[0]}.${PRE_VERSION_SPLIT[1]}"
121+
BRANCH_VERSION="${PRE_VERSION_SPLIT[0]}.${PRE_VERSION_SPLIT[1]}.$((PRE_VERSION_SPLIT[2] + 1))-pre"
122+
123+
# The next release is usually going to be a minor release; if the next
124+
# version is to be a major release, the package version in Git will need
125+
# to be manually updated or someone will have to pass a major version number
126+
# to the release script at the last second
127+
PRE_VERSION="${PRE_VERSION_SPLIT[0]}.$((PRE_VERSION_SPLIT[1] + 1)).0-pre"
128+
else
129+
# Patch releases do not get branches
130+
MAKE_BRANCH=
131+
BRANCH_VERSION=
132+
133+
if [[ "$VERSION" == "$VERSION_NO_TAGS" ]]; then
134+
# The next release version will always be another patch version
135+
PRE_VERSION="${PRE_VERSION_SPLIT[0]}.${PRE_VERSION_SPLIT[1]}.$((PRE_VERSION_SPLIT[2] + 1))-pre"
136+
else
137+
# The version being released is a pre-release, so do not bump anything
138+
PRE_VERSION="$VERSION_CARGO_NO_TAGS-pre"
139+
fi
140+
fi
141+
142+
TAG_VERSION="v$VERSION"
143+
144+
# At this point:
145+
# $VERSION is the version of modular-bitfield that is being released
146+
# $TAG_VERSION is the name that will be used for the Git tag for the release
147+
# $PRE_VERSION is the next pre-release version of modular-bitfield that will be
148+
# set on the original branch after tagging
149+
# $MAKE_BRANCH is the name of the new minor release branch that should be
150+
# created (if this is not a patch release)
151+
# $BRANCH_VERSION is the pre-release version of modular-bitfield that will be
152+
# set on the minor release branch
153+
154+
# Something is messed up and this release has already happened
155+
if [ "$(git tag | grep -c "^$TAG_VERSION$")" -gt 0 ]; then
156+
echo -e "\nTag $TAG_VERSION already exists! Please check the branch.\n"
157+
exit 1
158+
fi
159+
160+
set_package_version "$VERSION"
161+
set_package_publish "true"
162+
163+
git commit -m "Updating metadata for $VERSION" -m "[ci skip]" Cargo.toml
164+
git tag -s -m "Release $VERSION" "$TAG_VERSION"
165+
166+
set_package_version "$PRE_VERSION"
167+
set_package_publish "false # Use \`release.sh\`"
168+
169+
git commit -m "Updating source version to $PRE_VERSION" -m "[ci skip]" Cargo.toml
170+
171+
if [ "$MAKE_BRANCH" != "" ]; then
172+
git checkout -b "$MAKE_BRANCH" "$TAG_VERSION"
173+
set_package_version "$BRANCH_VERSION"
174+
set_package_publish "false # Use \`release.sh\`"
175+
176+
git commit -m "Updating source version to $BRANCH_VERSION" -m "[ci skip]" Cargo.toml
177+
PUSH_BRANCHES="$PUSH_BRANCHES $MAKE_BRANCH"
178+
PUSH_BRANCHES_MSG=" and branches ${PUSH_BRANCHES}"
179+
fi
180+
181+
echo -e "\nDone!\n"
182+
echo "Please confirm packaging success, then press 'y', ENTER to push"
183+
echo "tags $TAG_VERSION${PUSH_BRANCHES_MSG:-}, or any other key to bail."
184+
read -r -p "> "
185+
186+
if [ "$REPLY" != "y" ]; then
187+
echo "Aborted."
188+
exit 0
189+
fi
190+
191+
for BRANCH in $PUSH_BRANCHES; do
192+
git push origin "$BRANCH"
193+
done
194+
195+
git push origin --tags
196+
git checkout "$TAG_VERSION"
197+
cargo publish -p modular-bitfield-impl
198+
cargo publish -p modular-bitfield
199+
200+
cd "$ROOT_DIR"
201+
rm -rf "$BUILD_DIR"
202+
203+
echo -e "\nAll done! Yay!"

0 commit comments

Comments
 (0)