forked from actions/typescript-action
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrelease
More file actions
executable file
·186 lines (161 loc) · 6.91 KB
/
release
File metadata and controls
executable file
·186 lines (161 loc) · 6.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#!/bin/bash
# Exit early
# See: https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#The-Set-Builtin
set -e
# About:
#
# This is a helper script to tag and push a new release. GitHub Actions use
# release tags to allow users to select a specific version of the action to use.
#
# See: https://github.com/actions/typescript-action#publishing-a-new-release
# See: https://github.com/actions/toolkit/blob/master/docs/action-versioning.md#recommendations
#
# This script will do the following:
#
# 1. Retrieve the latest release tag
# 2. Display the latest release tag
# 3. Prompt the user for a new release tag
# 4. Validate the new release tag
# 5. Remind user to update the version field in package.json
# 6. Tag a new release
# 7. Set 'is_major_release' variable
# 8. Point separate major release tag (e.g. v1, v2) to the new release
# 9. Push the new tags (with commits, if any) to remote
# 10. If this is a major release, create a 'releases/v#' branch and push
# 11. Create a GitHub release with auto-generated release notes
#
# Usage:
#
# script/release
# Variables
semver_tag_regex='v[0-9]+\.[0-9]+\.[0-9]+$'
semver_tag_glob='v[0-9].[0-9].[0-9]*'
git_remote='origin'
major_semver_tag_regex='\(v[0-9]*\)'
# Terminal colors
OFF='\033[0m'
BOLD_RED='\033[1;31m'
BOLD_GREEN='\033[1;32m'
BOLD_BLUE='\033[1;34m'
BOLD_PURPLE='\033[1;35m'
BOLD_UNDERLINED='\033[1;4m'
BOLD='\033[1m'
# 1. Retrieve the latest release tag
if ! latest_tag=$(git describe --abbrev=0 --match="$semver_tag_glob"); then
# There are no existing release tags
echo -e "No tags found (yet) - Continue to create and push your first tag"
latest_tag="[unknown]"
fi
# 2. Display the latest release tag
echo -e "The latest release tag is: ${BOLD_BLUE}${latest_tag}${OFF}"
# 3. Prompt the user for a new release tag
read -r -p 'Enter a new release tag (vX.X.X format): ' new_tag
# 4. Validate the new release tag
if echo "$new_tag" | grep -q -E "$semver_tag_regex"; then
# Release tag is valid
echo -e "Tag: ${BOLD_BLUE}$new_tag${OFF} is valid syntax"
else
# Release tag is not in `vX.X.X` format
echo -e "Tag: ${BOLD_BLUE}$new_tag${OFF} is ${BOLD_RED}not valid${OFF} (must be in ${BOLD}vX.X.X${OFF} format)"
exit 1
fi
# 5. Remind user to update the version field in package.json
echo -e -n "Make sure the version field in package.json is ${BOLD_BLUE}$new_tag${OFF}. Yes? [Y/${BOLD_UNDERLINED}n${OFF}] "
read -r YN
if [[ ! ($YN == "y" || $YN == "Y") ]]; then
# Package.json version field is not up to date
echo -e "Please update the package.json version to ${BOLD_PURPLE}$new_tag${OFF} and commit your changes"
exit 1
fi
# 6. Tag a new release
git tag "$new_tag" --annotate --message "$new_tag Release"
echo -e "Tagged: ${BOLD_GREEN}$new_tag${OFF}"
# 7. Set 'is_major_release' variable
new_major_release_tag=$(expr "$new_tag" : "$major_semver_tag_regex")
if [[ "$latest_tag" = "[unknown]" ]]; then
# This is the first major release
is_major_release='yes'
else
# Compare the major version of the latest tag with the new tag
latest_major_release_tag=$(expr "$latest_tag" : "$major_semver_tag_regex")
if ! [[ "$new_major_release_tag" = "$latest_major_release_tag" ]]; then
is_major_release='yes'
else
is_major_release='no'
fi
fi
# 8. Point separate major release tag (e.g. v1, v2) to the new release
if [ $is_major_release = 'yes' ]; then
# Create a new major version tag and point it to this release
git tag "$new_major_release_tag" --annotate --message "$new_major_release_tag Release"
echo -e "New major version tag: ${BOLD_GREEN}$new_major_release_tag${OFF}"
else
# Update the major version tag to point it to this release
git tag "$latest_major_release_tag" --force --annotate --message "Sync $latest_major_release_tag tag with $new_tag"
echo -e "Synced ${BOLD_GREEN}$latest_major_release_tag${OFF} with ${BOLD_GREEN}$new_tag${OFF}"
fi
# 9. Push the new tags (with commits, if any) to remote
git push --follow-tags
if [ $is_major_release = 'yes' ]; then
# New major version tag is pushed with the '--follow-tags' flags
echo -e "Tags: ${BOLD_GREEN}$new_major_release_tag${OFF} and ${BOLD_GREEN}$new_tag${OFF} pushed to remote"
else
# Force push the updated major version tag
git push $git_remote "$latest_major_release_tag" --force
echo -e "Tags: ${BOLD_GREEN}$latest_major_release_tag${OFF} and ${BOLD_GREEN}$new_tag${OFF} pushed to remote"
fi
# 10. If this is a major release, create a 'releases/v#' branch and push
if [ $is_major_release = 'yes' ]; then
git branch "releases/$new_major_release_tag" "$new_major_release_tag"
echo -e "Branch: ${BOLD_BLUE}releases/$new_major_release_tag${OFF} created from ${BOLD_BLUE}$new_major_release_tag${OFF} tag"
git push --set-upstream $git_remote "releases/$new_major_release_tag"
echo -e "Branch: ${BOLD_GREEN}releases/$new_major_release_tag${OFF} pushed to remote"
fi
# 11. Create a GitHub release
echo -e "Creating GitHub release for ${BOLD_BLUE}$new_tag${OFF}..."
# Get repository information from git remote
if ! remote_url=$(git remote get-url origin 2>/dev/null); then
echo -e "${BOLD_RED}Failed to get git remote URL. Please ensure you're in a git repository with an 'origin' remote.${OFF}"
exit 1
fi
# Extract owner/repo from remote URL
# Handle both HTTPS and SSH formats:
# https://github.com/owner/repo.git -> owner/repo
# git@github.com:owner/repo.git -> owner/repo
if [[ $remote_url =~ github\.com[/:]([^/]+)/([^/.]+) ]]; then
repo_owner="${BASH_REMATCH[1]}"
repo_name="${BASH_REMATCH[2]}"
github_repository="$repo_owner/$repo_name"
echo -e "Detected repository: ${BOLD_BLUE}$github_repository${OFF}"
else
echo -e "${BOLD_RED}Could not parse repository information from git remote URL: $remote_url${OFF}"
echo -e "Expected format: https://github.com/owner/repo or git@github.com:owner/repo"
exit 1
fi
# Check if gh CLI is available
if ! command -v gh &>/dev/null; then
echo -e "${BOLD_RED}GitHub CLI (gh) is not installed. Please install it to create releases automatically.${OFF}"
echo -e "You can manually create the release at: https://github.com/$github_repository/releases/new"
echo -e "Tag: ${BOLD_BLUE}$new_tag${OFF}"
exit 1
fi
# Check if user is authenticated with GitHub CLI
if ! gh auth status &>/dev/null; then
echo -e "${BOLD_RED}Not authenticated with GitHub CLI. Please run 'gh auth login' first.${OFF}"
echo -e "You can manually create the release at: https://github.com/$github_repository/releases/new"
echo -e "Tag: ${BOLD_BLUE}$new_tag${OFF}"
exit 1
fi
# Generate release notes automatically
echo -e "Generating release notes..."
if gh release create "$new_tag" --generate-notes --draft --repo "$github_repository"; then
echo -e "Draft release created: ${BOLD_GREEN}$new_tag${OFF}"
echo -e "Please review and publish the release at: https://github.com/$github_repository/releases"
else
echo -e "${BOLD_RED}Failed to create GitHub release.${OFF}"
echo -e "You can manually create the release at: https://github.com/$github_repository/releases/new"
echo -e "Tag: ${BOLD_BLUE}$new_tag${OFF}"
exit 1
fi
# Completed
echo -e "${BOLD_GREEN}Done!${OFF}"