Merge pull request #2709 from rolandwalker/devscript_get_release_tag

devscript: add command get_release_tag
This commit is contained in:
Roland Walker
2014-01-30 07:59:36 -08:00
2 changed files with 210 additions and 20 deletions
+40 -20
View File
@@ -11,35 +11,55 @@ Since we are still pre-1.0, this essentially means that we bump the PATCH
number when we fix bugs, and we bump the MINOR number when we add stuff. Pretty
simple.
The script `developer/bin/get_release_tag` can tell you the latest release
tag that exists and/or calculate the proposed next release tag. Docs are at
`get_release_tag -help`.
## Release Process
We'll get this scripted someday, but until then it's better to have it written
down then floating in a brain somewhere.
down than floating in a brain somewhere.
1. Do a `git log` since the last release to see what changed. You can scope it to
`lib` to just pick up code changes and filter out Casks noise.
Like this: `git log v0.25.0..HEAD lib`
2. Optionally run `developer/bin/project_stats <previous-release-tag>` for
overall release stats.
3. Bump the version, which is stored in the file `lib/cask/version.rb`. Decide
whether to bump minor or patch based on whether or not features were added.
4. Populate the CHANGELOG with a new section for the release you are creating.
`lib` to just pick up code changes and filter out Casks noise. Like this:
```bash
git log $(developer/bin/get_release_tag)..HEAD lib
```
2. Decide whether to bump the minor or patch fields in the next tag, based on
whether or not features were added. Run the shell command
```bash
new_tag=$(developer/bin/get_release_tag -next) # or -next -patch
```
and make sure the value in `$new_tag` is what you want.
3. Optionally run `developer/bin/project_stats release` for overall release stats.
4. Bump the `VERSION` string which is stored in the file `lib/cask/version.rb`.
It should match `$new_tag`.
5. Populate the CHANGELOG with a new section for the release you are creating.
Follow the patterns used elsewhere in the file.
5. Make a commit containing the CHANGELOG and version-bump. Like this:
6. Make a commit containing the CHANGELOG and version-bump. Like this:
```bash
git add CHANGELOG lib/cask/version.rb
git commit -m 'cut v0.26.0'
git commit -m "cut $new_tag"
```
6. Tag that commit, ensuring that you provide a message so we get an annotated
tag.
Like this: `git tag -m v0.26.0 v0.26.0`
7. Push the commit and the tag: `git push --follow-tags`
8. Open your browser to <https://github.com/phinze/homebrew-cask/releases> .
Then click the link for your newly pushed tag. Click the "Edit Tag" button in
the top right corner of that page.
9. Paste the markdown summary from the CHANGELOG in the body of the release and
click "Publish Release".
10. Rejoice! Have a :cookie:.
7. Tag that commit, ensuring that you provide a message so we get an annotated
tag. Like this:
```bash
git tag -m "$new_tag" "$new_tag"
```
8. Push the commit and the tag:
```bash
git push --follow-tags
```
9. Unset `$new_tag`, you don't need it anymore.
```bash
unset new_tag
```
10. Open your browser to <https://github.com/phinze/homebrew-cask/releases> .
Then click the link for your newly pushed tag. Click the "Edit Tag" button in
the top right corner of that page.
11. Paste the markdown summary from the CHANGELOG in the body of the release and
click "Publish Release".
12. Rejoice! Have a :cookie:.
## Things to Consider
+170
View File
@@ -0,0 +1,170 @@
#!/bin/bash
#
# get_release_tag
#
set -e; # exit on any uncaught error
set +o histexpand; # don't expand history expressions
shopt -s nocasematch; # case-insensitive regular expressions
opt_next='';
opt_latest='';
opt_verbose='';
die () {
local message="$@";
if ! [[ $message =~ "\n"$ ]]; then
message="${message}\n"
fi
printf "$message" 1>&2
exit 1
}
cd_to_project_root () {
local script_dir="$(/usr/bin/dirname $0)"
cd "$script_dir"
local git_root="$(git rev-parse --show-toplevel)"
if [[ -z "$git_root" ]]; then
die "Could not find git project root"
fi
cd "$git_root"
}
verify_git_object_is_new () {
if git rev-parse --verify "$1" >/dev/null 2>&1; then
die "\nERROR: proposed new tag: '$1' already exists as a commit object\n\n"
fi
}
sanity_check_parsed_version () {
if [[ $# -ne 3 ]]; then
die "Error: can't parse version tag, wrong number of elements"
fi
if ! [[ $1 =~ ^v[0-9]+$ ]]; then
die "Error: can't parse version tag, does not start with v[0-9]"
fi
}
output_proposed_tag () {
local new_tag="$1.$2.$3"
sanity_check_parsed_version "$@"
verify_git_object_is_new "$new_tag"
if [[ -n "$opt_verbose" ]]; then
printf "Latest tag\t$latest_tag\n"
printf "Proposed new tag\t$new_tag\n"
else
printf "$new_tag\n"
fi
}
generate_next_major_tag () {
local -a version_elts
IFS='.' read -a version_elts <<< "$1"
sanity_check_parsed_version "${version_elts[@]}"
version_elts[0]="${version_elts[0]#v}" # mangle v<digit> into number
(( version_elts[0] += 1 )) # increment version field
version_elts[0]="v${version_elts[0]}" # restore text v<digit>
version_elts[1]='0' # reset minor field
version_elts[2]='0' # reset patch field
output_proposed_tag "${version_elts[@]}"
}
generate_next_minor_tag () {
local -a version_elts
IFS='.' read -a version_elts <<< "$1";
sanity_check_parsed_version "${version_elts[@]}"
(( version_elts[1] += 1 )) # increment minor field
version_elts[2]='0' # reset patch field
output_proposed_tag "${version_elts[@]}"
}
generate_next_patch_tag () {
local -a version_elts
IFS='.' read -a version_elts <<< "$1"
sanity_check_parsed_version ${version_elts[@]}
(( version_elts[2] += 1 )) # increment patch field
output_proposed_tag "${version_elts[@]}"
}
process_args () {
local arg
for arg in "$@"; do
if [[ $arg =~ ^-+h(elp)?$ ]]; then
printf "get_release_tag [ -latest | -next | -patch | -major | -verbose | -help ]
Retrieve or calculate a release tag.
Arguments:
-latest Show the most recent tag in the repository, which is typically
the designation of the latest release. This is the default
when invoked with no arguments.
-next Calculate the next minor-release tag bump and return it.
-patch Calculate the next patch-release tag bump and return it.
Overrides -next if both are given.
-major Calculate the next major-release tag bump and return it.
Overrides -next if both are given.
-verbose Output a table, possibly including both latest existing and
proposed new tags.
See RELEASING.md for more information.
"
exit
elif [[ $arg =~ ^-+v(erbose)?$ ]]; then
opt_verbose='true'
elif [[ $arg =~ ^-+next$ ]]; then
if [[ -z "$opt_next" ]]; then
opt_next='minor'
fi
elif [[ $arg =~ ^-+patch$ ]]; then
if [[ "$opt_next" == 'major' ]]; then
die "Error: -patch is incompatible with -major";
fi
opt_next='patch'
elif [[ $arg =~ ^-+major$ ]]; then
if [[ "$opt_next" == 'patch' ]]; then
die "Error: -patch is incompatible with -major";
fi
opt_next='major'
elif [[ $arg =~ ^-+latest$ ]]; then
opt_latest='true'
else
die "Error: unknown argument '$arg'"
fi
if [[ -n "$opt_latest" && -n "$opt_next" ]]; then
die "Error: -latest is incompatible with -next/-patch/-major"
fi
done
}
_get_release_tag () {
cd_to_project_root;
local latest_tag="$(git describe --tags --abbrev=0 2>/dev/null)"
if [[ -z "$latest_tag" ]]; then
die "Error: no recent tag found"
elif [[ -z "$opt_next" ]]; then
if [[ -n "$opt_verbose" ]]; then
printf "Latest tag\t"
fi
printf "$latest_tag\n"
elif [[ "$opt_next" == 'major' ]]; then
generate_next_major_tag "$latest_tag"
elif [[ "$opt_next" == 'minor' ]]; then
generate_next_minor_tag "$latest_tag"
elif [[ "$opt_next" == 'patch' ]]; then
generate_next_patch_tag "$latest_tag"
else
die "Error: should not happen. Unknown argument?"
fi
}
process_args "$@";
_get_release_tag;
#