release-me-sh 0.11.11 → 0.12.0
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.
- package/package.json +25 -17
- package/plugins/npm-post.sh +39 -47
- package/plugins/npm.sh +27 -24
- package/presets/conventional-commits.sh +1 -1
- package/presets/workspace.sh +1 -1
- package/release.sh +482 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "release-me-sh",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Fast minimal release workflow script written in Bash with plugins and presets support",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bash",
|
|
@@ -20,12 +20,20 @@
|
|
|
20
20
|
"license": "Apache-2.0",
|
|
21
21
|
"author": "Davlatjon Shavkatov <opensource@dalisoft.uz>",
|
|
22
22
|
"bin": {
|
|
23
|
-
"release-me": "release
|
|
24
|
-
"release-me-sh": "release
|
|
23
|
+
"release-me": "release.sh",
|
|
24
|
+
"release-me-sh": "release.sh"
|
|
25
25
|
},
|
|
26
|
-
"files": [
|
|
26
|
+
"files": [
|
|
27
|
+
"presets",
|
|
28
|
+
"plugins",
|
|
29
|
+
"release.sh"
|
|
30
|
+
],
|
|
27
31
|
"browserslist": {
|
|
28
|
-
"production": [
|
|
32
|
+
"production": [
|
|
33
|
+
">0.5%",
|
|
34
|
+
"not dead",
|
|
35
|
+
"not op_mini all"
|
|
36
|
+
],
|
|
29
37
|
"development": [
|
|
30
38
|
"last 3 chrome version",
|
|
31
39
|
"last 3 firefox version",
|
|
@@ -44,19 +52,19 @@
|
|
|
44
52
|
"docs:write-heading-ids": "docusaurus write-heading-ids"
|
|
45
53
|
},
|
|
46
54
|
"devDependencies": {
|
|
47
|
-
"@biomejs/biome": "^
|
|
48
|
-
"@docusaurus/core": "3.
|
|
49
|
-
"@docusaurus/module-type-aliases": "^3.
|
|
50
|
-
"@docusaurus/preset-classic": "3.
|
|
51
|
-
"@docusaurus/types": "^3.
|
|
52
|
-
"@evilmartians/lefthook": "^1.
|
|
53
|
-
"@ls-lint/ls-lint": "^2.
|
|
54
|
-
"@swc/core": "^1.
|
|
55
|
+
"@biomejs/biome": "^2.5.15",
|
|
56
|
+
"@docusaurus/core": "3.10.2",
|
|
57
|
+
"@docusaurus/module-type-aliases": "^3.10.2",
|
|
58
|
+
"@docusaurus/preset-classic": "3.10.2",
|
|
59
|
+
"@docusaurus/types": "^3.10.2",
|
|
60
|
+
"@evilmartians/lefthook": "^2.1.15",
|
|
61
|
+
"@ls-lint/ls-lint": "^2.3.1",
|
|
62
|
+
"@swc/core": "^1.16.13",
|
|
55
63
|
"commitlint-rs-npm": "dalisoft/commitlint-rs-npm#v0.1.11",
|
|
56
|
-
"dprint": "^0.
|
|
57
|
-
"prism-react-renderer": "^2.
|
|
58
|
-
"prismjs": "^1.
|
|
59
|
-
"swc-loader": "^0.2.
|
|
64
|
+
"dprint": "^0.58.0",
|
|
65
|
+
"prism-react-renderer": "^2.4.1",
|
|
66
|
+
"prismjs": "^1.30.0",
|
|
67
|
+
"swc-loader": "^0.2.7"
|
|
60
68
|
},
|
|
61
69
|
"engines": {
|
|
62
70
|
"node": ">=18.19.1"
|
package/plugins/npm-post.sh
CHANGED
|
@@ -106,62 +106,54 @@ release() {
|
|
|
106
106
|
# Committing a `npm` tag
|
|
107
107
|
log "Committing npm tag..."
|
|
108
108
|
log_verbose "Git hash: ${CHECKOUT_SHA}!"
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if ! $
|
|
116
|
-
|
|
117
|
-
|
|
109
|
+
|
|
110
|
+
# Don't load this plugin if
|
|
111
|
+
# - `--dry-run` used
|
|
112
|
+
# - `package.json` is missing
|
|
113
|
+
# - `package.json` is not changed on `Git` tracking
|
|
114
|
+
if ! ${IS_DRY_RUN-}; then
|
|
115
|
+
if [ ! -f package.json ] || [ -z "$(git diff --name-only package.json 2>/dev/null)" ]; then
|
|
116
|
+
log "Project does not have package.json or package.json not changed"
|
|
117
|
+
return 1
|
|
118
|
+
fi
|
|
119
|
+
prepare
|
|
120
|
+
git add package.json
|
|
121
|
+
|
|
122
|
+
if ${IS_WORKSPACE-}; then
|
|
123
|
+
if [ -z "${PKG_NAME}" ]; then
|
|
124
|
+
log_verbose "[npm-post] Workspace defined but no package name defined"
|
|
118
125
|
return 1
|
|
119
126
|
fi
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
log_verbose "[npm-post] Workspace defined but no package name defined"
|
|
126
|
-
return 1
|
|
127
|
-
fi
|
|
128
|
-
|
|
129
|
-
if [ -z "${GPG_NO_SIGN-}" ] && [ -n "${GPG_KEY-}" ] && [ -n "${GPG_KEY_ID-}" ]; then
|
|
130
|
-
git commit --sign -m "chore(${PKG_NAME}): update \`package.json\` version to ${NEXT_RELEASE_VERSION-} [skip ci]" --no-verify
|
|
131
|
-
elif [ -z "${SSH_NO_SIGN-}" ] && [ -n "${SSH_PUBLIC_KEY-}" ]; then
|
|
132
|
-
git commit --sign -m "chore(${PKG_NAME}): update \`package.json\` version to ${NEXT_RELEASE_VERSION} [skip ci]" --no-verify
|
|
133
|
-
else
|
|
134
|
-
git commit --no-gpg-sign -m "chore(${PKG_NAME}): update \`package.json\` version to ${NEXT_RELEASE_VERSION} [skip ci]" --no-verify
|
|
135
|
-
fi
|
|
127
|
+
|
|
128
|
+
if [ -z "${GPG_NO_SIGN-}" ] && [ -n "${GPG_KEY-}" ] && [ -n "${GPG_KEY_ID-}" ]; then
|
|
129
|
+
git commit --sign -m "chore(${PKG_NAME}): update \`package.json\` version to ${NEXT_RELEASE_VERSION-} [skip ci]" --no-verify
|
|
130
|
+
elif [ -z "${SSH_NO_SIGN-}" ] && [ -n "${SSH_PUBLIC_KEY-}" ]; then
|
|
131
|
+
git commit --sign -m "chore(${PKG_NAME}): update \`package.json\` version to ${NEXT_RELEASE_VERSION} [skip ci]" --no-verify
|
|
136
132
|
else
|
|
137
|
-
|
|
138
|
-
git commit --sign -m "chore(ci): update \`package.json\` version to ${NEXT_RELEASE_VERSION} [skip ci]" --no-verify
|
|
139
|
-
elif [ -z "${SSH_NO_SIGN-}" ] && [ -n "${SSH_PUBLIC_KEY-}" ]; then
|
|
140
|
-
git commit --sign -m "chore(ci): update \`package.json\` version to ${NEXT_RELEASE_VERSION} [skip ci]" --no-verify
|
|
141
|
-
else
|
|
142
|
-
git commit --no-gpg-sign -m "chore(ci): update \`package.json\` version to ${NEXT_RELEASE_VERSION} [skip ci]" --no-verify
|
|
143
|
-
fi
|
|
133
|
+
git commit --no-gpg-sign -m "chore(${PKG_NAME}): update \`package.json\` version to ${NEXT_RELEASE_VERSION} [skip ci]" --no-verify
|
|
144
134
|
fi
|
|
145
|
-
|
|
146
|
-
if [ -n "${
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
git
|
|
150
|
-
CHECKOUT_SHA=$(git rev-parse HEAD)
|
|
151
|
-
log "Committed npm [${NEXT_RELEASE_TAG-}] tag"
|
|
135
|
+
else
|
|
136
|
+
if [ -z "${GPG_NO_SIGN-}" ] && [ -n "${GPG_KEY-}" ] && [ -n "${GPG_KEY_ID-}" ]; then
|
|
137
|
+
git commit --sign -m "chore(ci): update \`package.json\` version to ${NEXT_RELEASE_VERSION-} [skip ci]" --no-verify
|
|
138
|
+
elif [ -z "${SSH_NO_SIGN-}" ] && [ -n "${SSH_PUBLIC_KEY-}" ]; then
|
|
139
|
+
git commit --sign -m "chore(ci): update \`package.json\` version to ${NEXT_RELEASE_VERSION} [skip ci]" --no-verify
|
|
152
140
|
else
|
|
153
|
-
|
|
141
|
+
git commit --no-gpg-sign -m "chore(ci): update \`package.json\` version to ${NEXT_RELEASE_VERSION} [skip ci]" --no-verify
|
|
154
142
|
fi
|
|
143
|
+
fi
|
|
155
144
|
|
|
156
|
-
|
|
145
|
+
if [ -n "${GIT_REMOTE_ORIGIN}" ]; then
|
|
146
|
+
# GitHub workflow re-trigger hack to make it work properly
|
|
147
|
+
git pull
|
|
148
|
+
git push --no-verify
|
|
149
|
+
CHECKOUT_SHA=$(git rev-parse HEAD)
|
|
150
|
+
log "Committed npm [${NEXT_RELEASE_TAG-}] tag"
|
|
157
151
|
else
|
|
158
|
-
log "
|
|
152
|
+
log "Committing npm [${NEXT_RELEASE_TAG}] tag failed"
|
|
159
153
|
fi
|
|
154
|
+
|
|
155
|
+
cleanup
|
|
160
156
|
else
|
|
161
|
-
|
|
162
|
-
npm Token is not found
|
|
163
|
-
Please export npm Token so this plugin can be used
|
|
164
|
-
"
|
|
165
|
-
exit 1
|
|
157
|
+
log "Skipped committing npm [${NEXT_RELEASE_TAG}] tag in DRY-RUN mode."
|
|
166
158
|
fi
|
|
167
159
|
}
|
package/plugins/npm.sh
CHANGED
|
@@ -2,40 +2,43 @@
|
|
|
2
2
|
set -eu
|
|
3
3
|
|
|
4
4
|
release() {
|
|
5
|
-
# Publish a `npm` tag
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
log_verbose "npm tag: ${NEXT_RELEASE_TAG-} and version: ${NEXT_RELEASE_VERSION-}!"
|
|
5
|
+
# Publish a `npm` tag with token or Trusted publishing (OIDC)
|
|
6
|
+
log "Publishing npm tag..."
|
|
7
|
+
log_verbose "npm tag: ${NEXT_RELEASE_TAG-} and version: ${NEXT_RELEASE_VERSION-}!"
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
# Don't load this plugin if
|
|
10
|
+
# - `--dry-run` used
|
|
11
|
+
# - `package.json` is missing
|
|
12
|
+
if ! ${IS_DRY_RUN-}; then
|
|
13
|
+
if [ ! -f package.json ]; then
|
|
14
|
+
log "Project does not have package.json"
|
|
15
|
+
return 1
|
|
16
|
+
fi
|
|
18
17
|
|
|
18
|
+
if [ -n "${NPM_TOKEN-}" ]; then
|
|
19
19
|
TEMP_FILE=$(mktemp)
|
|
20
20
|
printf "%s\n" "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" >>"${TEMP_FILE}"
|
|
21
|
+
export NODE_AUTH_TOKEN="${NPM_TOKEN}"
|
|
22
|
+
fi
|
|
21
23
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
# Bump `package.json` `version` for properly publishing
|
|
25
|
+
sed -i.bak "s/\"version\": \"[^\"]*\",/\"version\": \"${NEXT_BUILD_VERSION-}\",/" "package.json"
|
|
26
|
+
rm -rf package.json.bak
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
# without a token npm >= 11.5.1 exchanges the CI's OIDC token
|
|
29
|
+
# (Trusted publishing) for a short-lived publish token
|
|
30
|
+
if [ -n "${TEMP_FILE-}" ]; then
|
|
27
31
|
npm publish --provenance --userconfig "${TEMP_FILE}"
|
|
32
|
+
else
|
|
33
|
+
npm publish --provenance
|
|
34
|
+
fi
|
|
28
35
|
|
|
29
|
-
|
|
36
|
+
log "Published [${NEXT_RELEASE_TAG}]!"
|
|
37
|
+
|
|
38
|
+
if [ -n "${TEMP_FILE-}" ]; then
|
|
30
39
|
rm -rf "${TEMP_FILE}"
|
|
31
|
-
else
|
|
32
|
-
log "Skipped npm tag [${NEXT_RELEASE_TAG}] in DRY-RUN mode."
|
|
33
40
|
fi
|
|
34
41
|
else
|
|
35
|
-
|
|
36
|
-
npm Token is not found
|
|
37
|
-
Please export npm Token so this plugin can be used
|
|
38
|
-
"
|
|
39
|
-
exit 1
|
|
42
|
+
log "Skipped npm tag [${NEXT_RELEASE_TAG}] in DRY-RUN mode."
|
|
40
43
|
fi
|
|
41
44
|
}
|
|
@@ -4,7 +4,7 @@ set -eu
|
|
|
4
4
|
# RegExp as variable
|
|
5
5
|
regexp_commit_primary="^([a-z]+)(\(([^\)]+)\))?:\ (.+)$"
|
|
6
6
|
regexp_commit_major="^([a-z]+)(\(([^\)]+)\))?!?:\ (.+)$"
|
|
7
|
-
string_commit_major="
|
|
7
|
+
string_commit_major="BREAKING[ -]CHANGE:"
|
|
8
8
|
|
|
9
9
|
# Release types
|
|
10
10
|
RELEASE_SKIP_TYPES=("build" "chore" "style" "ci" "skip ci")
|
package/presets/workspace.sh
CHANGED
|
@@ -4,7 +4,7 @@ set -eu
|
|
|
4
4
|
# RegExp as variable
|
|
5
5
|
regexp_commit_primary="^([a-z]+)(\(([^\)]+)\))?:\ (.+)$"
|
|
6
6
|
regexp_commit_major="^([a-z]+)(\(([^\)]+)\))?!?:\ (.+)$"
|
|
7
|
-
string_commit_major="
|
|
7
|
+
string_commit_major="BREAKING[ -]CHANGE:"
|
|
8
8
|
|
|
9
9
|
# Release types
|
|
10
10
|
RELEASE_SKIP_TYPES=("build" "chore" "style" "ci" "skip ci")
|
package/release.sh
ADDED
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -eu
|
|
3
|
+
shopt -s inherit_errexit
|
|
4
|
+
|
|
5
|
+
readonly CLI_PREFIX="[release-me]"
|
|
6
|
+
readonly DESCRIPTION="Fast minimal release workflow script written in Bash with plugins and presets support"
|
|
7
|
+
readonly USAGE="${CLI_PREFIX} Usage: release-me [options]
|
|
8
|
+
${DESCRIPTION}
|
|
9
|
+
|
|
10
|
+
Options:
|
|
11
|
+
-d, --dry-run Dry run. Skip tag creation, only show logs (if exists).
|
|
12
|
+
-w, --workspace Use in workspace environment for publishing workspaces separately.
|
|
13
|
+
--use-version Use project version from manifest. Requires workspace and a valid manifest.
|
|
14
|
+
--verbose Verbose mode, shows more detailed logs.
|
|
15
|
+
--quiet Quiet mode, shows less logs than default behavior.
|
|
16
|
+
--plugins=* Plugins option for loading plugins.
|
|
17
|
+
--preset= Presets option for parsing commits.
|
|
18
|
+
--stable If project has a \`0.x\` version, it will bump to \`1.x\`.
|
|
19
|
+
--pre-release Mark project release as non-production ready.
|
|
20
|
+
-h, --help Show this help.
|
|
21
|
+
-v, --version Show version.
|
|
22
|
+
"
|
|
23
|
+
|
|
24
|
+
##############################
|
|
25
|
+
####### Root variables #######
|
|
26
|
+
##############################
|
|
27
|
+
READLINK=$(readlink -f -- "$0")
|
|
28
|
+
SCRIPT_DIR=$(dirname -- "${READLINK}")
|
|
29
|
+
CURRENT_DATE=$(date +'%Y-%m-%d')
|
|
30
|
+
IS_GIT_REPO=$(git rev-parse --is-inside-work-tree 2>/dev/null || printf "%s" "")
|
|
31
|
+
GIT_LOG_ENTRY_SEPARATOR='____'
|
|
32
|
+
GIT_LOG_COMMIT_SEPARATOR='START_OF_COMMIT'
|
|
33
|
+
GIT_LOG_FORMAT="${GIT_LOG_COMMIT_SEPARATOR}%n%h${GIT_LOG_ENTRY_SEPARATOR}%H${GIT_LOG_ENTRY_SEPARATOR}%s${GIT_LOG_ENTRY_SEPARATOR}%b"
|
|
34
|
+
GIT_LOG_PARSE_REGEX="(.*)${GIT_LOG_ENTRY_SEPARATOR}(.*)${GIT_LOG_ENTRY_SEPARATOR}(.*)(${GIT_LOG_ENTRY_SEPARATOR}(.*)?)"
|
|
35
|
+
GIT_REMOTE_ORIGIN=$(git remote get-url origin 2>/dev/null || printf "%s" "")
|
|
36
|
+
GIT_REPO_NAME=
|
|
37
|
+
|
|
38
|
+
if [[ "${GIT_REMOTE_ORIGIN}" == "git@"* ]]; then
|
|
39
|
+
GIT_REPO_NAME=$(git remote get-url origin | cut -d ':' -f 2 | sed s/.git//)
|
|
40
|
+
elif [[ "${GIT_REMOTE_ORIGIN}" == "https"* ]]; then
|
|
41
|
+
GIT_REPO_NAME=$(git remote get-url origin | cut -d ':' -f 2 | sed s/\\/\\/github.com\\///)
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
IS_WORKSPACE=false
|
|
45
|
+
IS_USE_PKG_VERSION=false
|
|
46
|
+
IS_DRY_RUN=false
|
|
47
|
+
IS_QUIET=false
|
|
48
|
+
IS_VERBOSE=false
|
|
49
|
+
IS_STABLE_VERSION=false
|
|
50
|
+
PRE_RELEASE_VERSION=false
|
|
51
|
+
PLUGINS=("git")
|
|
52
|
+
PRESET="conventional-commits"
|
|
53
|
+
|
|
54
|
+
# set `verbose` on `CI`
|
|
55
|
+
if [[ -n "${CI:-}" ]]; then
|
|
56
|
+
IS_VERBOSE=true
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
##############################
|
|
60
|
+
###### Helpers & Utils #######
|
|
61
|
+
##############################
|
|
62
|
+
|
|
63
|
+
# proper handling of lines counter
|
|
64
|
+
# as `grep -c '^'` fails if there nothing
|
|
65
|
+
# and `wc -l` if there 1 commit
|
|
66
|
+
# so this utility was made
|
|
67
|
+
|
|
68
|
+
glc() {
|
|
69
|
+
local COUNT=0
|
|
70
|
+
while read -r line; do
|
|
71
|
+
if [[ -n "${line}" ]]; then
|
|
72
|
+
COUNT=$((COUNT + 1))
|
|
73
|
+
fi
|
|
74
|
+
done <<<"$(cat /dev/stdin)"
|
|
75
|
+
|
|
76
|
+
printf "%s" "${COUNT}"
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
parse_options() {
|
|
80
|
+
while :; do
|
|
81
|
+
local KEY="${1-}"
|
|
82
|
+
case "${KEY}" in
|
|
83
|
+
-v | --version)
|
|
84
|
+
printf "%s" "${CLI_PREFIX} last version available at GitHub"
|
|
85
|
+
exit 0
|
|
86
|
+
;;
|
|
87
|
+
-h | -\? | --help)
|
|
88
|
+
printf "%s" "${USAGE}"
|
|
89
|
+
exit 0
|
|
90
|
+
;;
|
|
91
|
+
-w | --workspace)
|
|
92
|
+
IS_WORKSPACE=true
|
|
93
|
+
;;
|
|
94
|
+
--plugins=*)
|
|
95
|
+
local IFS=','
|
|
96
|
+
read -ra PLUGINS <<<"${KEY#*=}"
|
|
97
|
+
;;
|
|
98
|
+
--preset=*)
|
|
99
|
+
read -r PRESET <<<"${KEY#*=}"
|
|
100
|
+
;;
|
|
101
|
+
--stable)
|
|
102
|
+
IS_STABLE_VERSION=true
|
|
103
|
+
PRE_RELEASE_VERSION=false
|
|
104
|
+
;;
|
|
105
|
+
--pre-release)
|
|
106
|
+
# shellcheck disable=2034
|
|
107
|
+
PRE_RELEASE_VERSION=true
|
|
108
|
+
IS_STABLE_VERSION=false
|
|
109
|
+
;;
|
|
110
|
+
--use-version)
|
|
111
|
+
IS_USE_PKG_VERSION=true
|
|
112
|
+
;;
|
|
113
|
+
-d | --dry-run)
|
|
114
|
+
# shellcheck disable=2034
|
|
115
|
+
IS_DRY_RUN=true
|
|
116
|
+
;;
|
|
117
|
+
-q | --quiet)
|
|
118
|
+
IS_QUIET=true
|
|
119
|
+
IS_VERBOSE=false
|
|
120
|
+
;;
|
|
121
|
+
--verbose)
|
|
122
|
+
IS_VERBOSE=true
|
|
123
|
+
IS_QUIET=false
|
|
124
|
+
# export GIT_TRACE=1
|
|
125
|
+
;;
|
|
126
|
+
-?*)
|
|
127
|
+
printf "%s" "${CLI_PREFIX} Unknown option: ${KEY}"
|
|
128
|
+
exit 1
|
|
129
|
+
;;
|
|
130
|
+
?*)
|
|
131
|
+
printf "%s" "${CLI_PREFIX} Unknown argument: ${KEY}"
|
|
132
|
+
exit 1
|
|
133
|
+
;;
|
|
134
|
+
*)
|
|
135
|
+
break
|
|
136
|
+
;;
|
|
137
|
+
esac
|
|
138
|
+
shift
|
|
139
|
+
done
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
is_valid_commit_type() {
|
|
143
|
+
local key="$1"
|
|
144
|
+
shift
|
|
145
|
+
local arr=("$@")
|
|
146
|
+
|
|
147
|
+
for element in "${arr[@]}"; do
|
|
148
|
+
if [[ "${key}" == "${element}"* ]]; then
|
|
149
|
+
return 0
|
|
150
|
+
fi
|
|
151
|
+
done
|
|
152
|
+
return 1
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
##############################
|
|
156
|
+
##### Logging helpers #######
|
|
157
|
+
##############################
|
|
158
|
+
log() {
|
|
159
|
+
if ! ${IS_QUIET}; then
|
|
160
|
+
if [[ "${2-}" == "-q" ]]; then
|
|
161
|
+
printf "%b\n" "$1"
|
|
162
|
+
else
|
|
163
|
+
printf "%b\n" "${CLI_PREFIX} $1"
|
|
164
|
+
fi
|
|
165
|
+
fi
|
|
166
|
+
}
|
|
167
|
+
log_verbose() {
|
|
168
|
+
if ${IS_VERBOSE}; then
|
|
169
|
+
if [[ "${2-}" == "-q" ]]; then
|
|
170
|
+
printf "%b\n" "$1"
|
|
171
|
+
else
|
|
172
|
+
printf "%b\n" "${CLI_PREFIX} $1"
|
|
173
|
+
fi
|
|
174
|
+
fi
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
##############################
|
|
178
|
+
##### Early exit errors ######
|
|
179
|
+
##############################
|
|
180
|
+
|
|
181
|
+
if [[ "${IS_GIT_REPO}" != true ]]; then
|
|
182
|
+
log "Current directory is not a Git repository!"
|
|
183
|
+
exit 1
|
|
184
|
+
fi
|
|
185
|
+
|
|
186
|
+
parse_options "$@"
|
|
187
|
+
|
|
188
|
+
up_to_date() {
|
|
189
|
+
log "${CLI_PREFIX} $1" -q
|
|
190
|
+
printf "%s\n" "${CLI_PREFIX} Your project is up-to-date"
|
|
191
|
+
exit 0
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if [[ "${PRESET}" != "" ]]; then
|
|
195
|
+
SOURCE_PRESET_FILE="${SCRIPT_DIR}/presets/${PRESET}.sh"
|
|
196
|
+
# shellcheck disable=SC1090 source=/dev/null
|
|
197
|
+
source "${SOURCE_PRESET_FILE}"
|
|
198
|
+
fi
|
|
199
|
+
|
|
200
|
+
##############################
|
|
201
|
+
##### Package variables ######
|
|
202
|
+
##############################
|
|
203
|
+
|
|
204
|
+
PKG_NAME=""
|
|
205
|
+
NEXT_VERSION=(0 0 0)
|
|
206
|
+
CURRENT_VERSION=(0 0 0)
|
|
207
|
+
|
|
208
|
+
parse_packages() {
|
|
209
|
+
if ! ${IS_WORKSPACE}; then
|
|
210
|
+
return 0
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
if [[ -f "./package.json" ]]; then
|
|
214
|
+
PKG_NAME=$(awk -F': ' '/"name":/ {gsub(/[",]/, "", $2); print $2}' "./package.json")
|
|
215
|
+
if ${IS_USE_PKG_VERSION}; then
|
|
216
|
+
PKG_VERSION=$(awk -F': ' '/"version":/ {gsub(/[",]/, "", $2); print $2}' "./package.json")
|
|
217
|
+
fi
|
|
218
|
+
elif [[ -f "./Cargo.toml" ]]; then
|
|
219
|
+
PKG_NAME=$(sed -n 's/^name = "\(.*\)"/\1/p' "./Cargo.toml")
|
|
220
|
+
if ${IS_USE_PKG_VERSION}; then
|
|
221
|
+
PKG_VERSION=$(sed -n 's/^version = "\(.*\)"/\1/p' "./Cargo.toml")
|
|
222
|
+
fi
|
|
223
|
+
elif [[ -f "./setup.py" ]]; then
|
|
224
|
+
PKG_NAME=$(sed -n "s/.*name=['\"]\([^'\"]*\)['\"].*/\1/p" "./setup.py")
|
|
225
|
+
if ${IS_USE_PKG_VERSION}; then
|
|
226
|
+
PKG_VERSION=$(sed -n 's/^ *version\s*=\s*["'\'']\([^"'\'']*\)["'\''].*/\1/p' "./setup.py")
|
|
227
|
+
fi
|
|
228
|
+
else
|
|
229
|
+
cat <<EOF
|
|
230
|
+
This project currently supports only Node.js, Rust and Python projects.
|
|
231
|
+
Please wait for updates to get support in other languages!
|
|
232
|
+
EOF
|
|
233
|
+
exit 1
|
|
234
|
+
fi
|
|
235
|
+
|
|
236
|
+
if ${IS_WORKSPACE} && [[ -z "${PKG_NAME}" ]]; then
|
|
237
|
+
cat <<EOF
|
|
238
|
+
This release aims to being workspace release
|
|
239
|
+
but missing name and could not be release
|
|
240
|
+
EOF
|
|
241
|
+
exit 1
|
|
242
|
+
fi
|
|
243
|
+
|
|
244
|
+
if ${IS_USE_PKG_VERSION}; then
|
|
245
|
+
local IFS='.'
|
|
246
|
+
read -ra NEXT_VERSION <<<"${PKG_VERSION}"
|
|
247
|
+
CURRENT_VERSION=("${NEXT_VERSION[@]}")
|
|
248
|
+
fi
|
|
249
|
+
|
|
250
|
+
log_verbose "Workspace mode is enabled"
|
|
251
|
+
log_verbose "Workspace project name: ${PKG_NAME}"
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
##############################
|
|
255
|
+
####### Git variables ########
|
|
256
|
+
##############################
|
|
257
|
+
|
|
258
|
+
GIT_LAST_PROJECT_TAG=""
|
|
259
|
+
GIT_LAST_PROJECT_TAG_VER=""
|
|
260
|
+
|
|
261
|
+
get_git_variables() {
|
|
262
|
+
GIT_TAGS_LIST=$(git for-each-ref --sort=creatordate --format '%(refname)' refs/tags)
|
|
263
|
+
|
|
264
|
+
if ${IS_WORKSPACE}; then
|
|
265
|
+
GIT_LAST_PROJECT_TAG=$(printf "%b" "${GIT_TAGS_LIST}" | grep "${PKG_NAME}" | tail -1 | cut -d '/' -f 3-)
|
|
266
|
+
else
|
|
267
|
+
GIT_LAST_PROJECT_TAG=$(printf "%s" "${GIT_TAGS_LIST}" | tail -1 | cut -d '/' -f 3-)
|
|
268
|
+
fi
|
|
269
|
+
|
|
270
|
+
if [[ ${GIT_LAST_PROJECT_TAG} != "" ]]; then
|
|
271
|
+
GIT_LAST_PROJECT_TAG_VER=$(printf "%s" "${GIT_LAST_PROJECT_TAG}" | rev | cut -d 'v' -f 1 | rev)
|
|
272
|
+
fi
|
|
273
|
+
|
|
274
|
+
if [[ -n "${GIT_LAST_PROJECT_TAG_VER}" ]]; then
|
|
275
|
+
if ! ${IS_USE_PKG_VERSION}; then
|
|
276
|
+
mapfile -d '.' -t NEXT_VERSION < <(printf '%s' "${GIT_LAST_PROJECT_TAG_VER}")
|
|
277
|
+
CURRENT_VERSION=("${NEXT_VERSION[@]}")
|
|
278
|
+
fi
|
|
279
|
+
|
|
280
|
+
if [[ "${IS_STABLE_VERSION}" == false && ${PRE_RELEASE_VERSION} == false && "${NEXT_VERSION[0]}" -gt 0 ]]; then
|
|
281
|
+
IS_STABLE_VERSION=true
|
|
282
|
+
fi
|
|
283
|
+
fi
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
##############################
|
|
287
|
+
######## Git handling ########
|
|
288
|
+
##############################
|
|
289
|
+
|
|
290
|
+
GIT_LOGS=""
|
|
291
|
+
|
|
292
|
+
get_git_commits() {
|
|
293
|
+
local IFS=
|
|
294
|
+
local GIT_LOGS_LENGTH=0
|
|
295
|
+
|
|
296
|
+
# Fast early-catch empty repository
|
|
297
|
+
if ! git rev-parse HEAD 1>/dev/null 2>&1; then
|
|
298
|
+
log "You have not committed yet
|
|
299
|
+
You have to commit your initial/first commit."
|
|
300
|
+
exit 1
|
|
301
|
+
fi
|
|
302
|
+
|
|
303
|
+
# Check if exists last tag and is not empty
|
|
304
|
+
if [[ -n "${GIT_LAST_PROJECT_TAG}" ]]; then
|
|
305
|
+
log_verbose "Last project tag [${GIT_LAST_PROJECT_TAG}] found"
|
|
306
|
+
# Get and cache commits variable, so later
|
|
307
|
+
# can be checked for commits length and avaibality
|
|
308
|
+
if ${IS_WORKSPACE}; then
|
|
309
|
+
GIT_LOGS=$(git log "${GIT_LAST_PROJECT_TAG}...HEAD" --grep "${PKG_NAME}" --pretty=format:"${GIT_LOG_FORMAT}" --reverse)
|
|
310
|
+
GIT_LOGS_LENGTH=$(git log "${GIT_LAST_PROJECT_TAG}...HEAD" --grep "${PKG_NAME}" --pretty=format:"%s" | glc -)
|
|
311
|
+
else
|
|
312
|
+
GIT_LOGS=$(git log "${GIT_LAST_PROJECT_TAG}...HEAD" --pretty=format:"${GIT_LOG_FORMAT}" --reverse)
|
|
313
|
+
GIT_LOGS_LENGTH=$(git rev-list --count "${GIT_LAST_PROJECT_TAG}...HEAD")
|
|
314
|
+
fi
|
|
315
|
+
else
|
|
316
|
+
log_verbose "Last project tag not found"
|
|
317
|
+
if ${IS_WORKSPACE}; then
|
|
318
|
+
GIT_LOGS=$(git log HEAD --grep "${PKG_NAME}" --pretty=format:"${GIT_LOG_FORMAT}" --reverse)
|
|
319
|
+
GIT_LOGS_LENGTH=$(git log HEAD --grep "${PKG_NAME}" --pretty=format:"%s" | glc -)
|
|
320
|
+
else
|
|
321
|
+
GIT_LOGS=$(git log HEAD --pretty=format:"${GIT_LOG_FORMAT}" --reverse)
|
|
322
|
+
GIT_LOGS_LENGTH=$(git rev-list --count HEAD)
|
|
323
|
+
fi
|
|
324
|
+
fi
|
|
325
|
+
|
|
326
|
+
if [[ ${GIT_LOGS_LENGTH} -eq 0 ]]; then
|
|
327
|
+
up_to_date "Your project has no new commits"
|
|
328
|
+
else
|
|
329
|
+
if [[ -n "${GIT_LAST_PROJECT_TAG}" ]]; then
|
|
330
|
+
log_verbose "Found ${GIT_LOGS_LENGTH} commits since last release"
|
|
331
|
+
else
|
|
332
|
+
log_verbose "Found ${GIT_LOGS_LENGTH} commits but did not found any release"
|
|
333
|
+
fi
|
|
334
|
+
fi
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
##############################
|
|
338
|
+
#### Git commits handling ####
|
|
339
|
+
##############################
|
|
340
|
+
NEXT_BUILD_VERSION=""
|
|
341
|
+
NEXT_RELEASE_VERSION=""
|
|
342
|
+
NEXT_RELEASE_TAG=""
|
|
343
|
+
RELEASE_BODY=""
|
|
344
|
+
|
|
345
|
+
PATCH_UPGRADED=false
|
|
346
|
+
MINOR_UPGRADED=false
|
|
347
|
+
MAJOR_UPGRADED=false
|
|
348
|
+
|
|
349
|
+
process_commit_entry() {
|
|
350
|
+
local commit="$1"
|
|
351
|
+
local commit_body_extra="$2"
|
|
352
|
+
|
|
353
|
+
if [[ "${commit}" =~ ${GIT_LOG_PARSE_REGEX} ]]; then
|
|
354
|
+
if [[ -n "${commit_body_extra}" ]]; then
|
|
355
|
+
if [[ -n "${BASH_REMATCH[5]-}" ]]; then
|
|
356
|
+
BASH_REMATCH[5]="${BASH_REMATCH[5]}"$'\n'"${commit_body_extra}"
|
|
357
|
+
else
|
|
358
|
+
BASH_REMATCH[5]="${commit_body_extra}"
|
|
359
|
+
fi
|
|
360
|
+
fi
|
|
361
|
+
log_verbose "${BASH_REMATCH[3]}" "-q"
|
|
362
|
+
CHECKOUT_SHA=${BASH_REMATCH[1]}
|
|
363
|
+
|
|
364
|
+
preset_command=$(command -v parse_commit)
|
|
365
|
+
if [[ -n "${preset_command}" ]]; then
|
|
366
|
+
parse_commit BASH_REMATCH
|
|
367
|
+
fi
|
|
368
|
+
fi
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
handle_git_commits() {
|
|
372
|
+
log_verbose "Analyzing commits...\n"
|
|
373
|
+
|
|
374
|
+
local IFS=
|
|
375
|
+
local commit=""
|
|
376
|
+
local commit_body_extra=""
|
|
377
|
+
while read -r line || [[ -n "${line}" ]]; do
|
|
378
|
+
if [[ "${line}" == "${GIT_LOG_COMMIT_SEPARATOR}" ]]; then
|
|
379
|
+
if [[ -n "${commit}" ]]; then
|
|
380
|
+
process_commit_entry "${commit}" "${commit_body_extra}"
|
|
381
|
+
fi
|
|
382
|
+
commit=""
|
|
383
|
+
commit_body_extra=""
|
|
384
|
+
read -r commit || commit=""
|
|
385
|
+
else
|
|
386
|
+
if [[ -n "${commit}" ]]; then
|
|
387
|
+
if [[ -z "${commit_body_extra}" ]]; then
|
|
388
|
+
commit_body_extra="${line}"
|
|
389
|
+
else
|
|
390
|
+
commit_body_extra+=$'\n'"${line}"
|
|
391
|
+
fi
|
|
392
|
+
fi
|
|
393
|
+
fi
|
|
394
|
+
done <<<"${GIT_LOGS}"
|
|
395
|
+
if [[ -n "${commit}" ]]; then
|
|
396
|
+
process_commit_entry "${commit}" "${commit_body_extra}"
|
|
397
|
+
fi
|
|
398
|
+
log_verbose "" "-q"
|
|
399
|
+
log_verbose "Analyzed commits!"
|
|
400
|
+
|
|
401
|
+
log_verbose "Preparing changes diff..."
|
|
402
|
+
build_release
|
|
403
|
+
log_verbose "Prepared changes diff!"
|
|
404
|
+
|
|
405
|
+
log_verbose "Analyzing updates..."
|
|
406
|
+
if [[ "${IS_STABLE_VERSION}" == true && "${NEXT_VERSION[0]}" -eq 0 ]]; then
|
|
407
|
+
NEXT_VERSION=(1 0 0)
|
|
408
|
+
elif [[ ${MAJOR_UPGRADED} == true && "${NEXT_VERSION[0]}" -gt 0 ]]; then
|
|
409
|
+
NEXT_VERSION[0]=$((NEXT_VERSION[0] + 1))
|
|
410
|
+
NEXT_VERSION[1]=0
|
|
411
|
+
NEXT_VERSION[2]=0
|
|
412
|
+
elif ${MINOR_UPGRADED} || [[ ${MAJOR_UPGRADED} == true && "${NEXT_VERSION[0]}" -eq 0 ]]; then
|
|
413
|
+
NEXT_VERSION[1]=$((NEXT_VERSION[1] + 1))
|
|
414
|
+
NEXT_VERSION[2]=0
|
|
415
|
+
elif ${PATCH_UPGRADED}; then
|
|
416
|
+
NEXT_VERSION[2]=$((NEXT_VERSION[2] + 1))
|
|
417
|
+
fi
|
|
418
|
+
|
|
419
|
+
local IFS='.'
|
|
420
|
+
NEXT_BUILD_VERSION="${NEXT_VERSION[*]}"
|
|
421
|
+
CURRENT_BUILD_VERSION="${CURRENT_VERSION[*]}"
|
|
422
|
+
|
|
423
|
+
if [[ "${NEXT_BUILD_VERSION}" == "${CURRENT_BUILD_VERSION}" ]]; then
|
|
424
|
+
up_to_date "Your project has no incremental update"
|
|
425
|
+
else
|
|
426
|
+
log_verbose "Analyzing updates done!"
|
|
427
|
+
fi
|
|
428
|
+
|
|
429
|
+
CURRENT_RELEASE_TAG=""
|
|
430
|
+
|
|
431
|
+
if ${IS_WORKSPACE}; then
|
|
432
|
+
NEXT_RELEASE_VERSION="v${NEXT_BUILD_VERSION}"
|
|
433
|
+
NEXT_RELEASE_TAG="${PKG_NAME}-${NEXT_RELEASE_VERSION}"
|
|
434
|
+
CURRENT_RELEASE_TAG="${PKG_NAME}-v${CURRENT_BUILD_VERSION}"
|
|
435
|
+
else
|
|
436
|
+
NEXT_RELEASE_VERSION="v${NEXT_BUILD_VERSION}"
|
|
437
|
+
NEXT_RELEASE_TAG="${NEXT_RELEASE_VERSION}"
|
|
438
|
+
CURRENT_RELEASE_TAG="v${CURRENT_BUILD_VERSION}"
|
|
439
|
+
fi
|
|
440
|
+
|
|
441
|
+
if [[ -n "${GIT_LAST_PROJECT_TAG_VER}" ]]; then
|
|
442
|
+
RELEASE_DIFF_URL="https://github.com/${GIT_REPO_NAME}/compare/${CURRENT_RELEASE_TAG}...${NEXT_RELEASE_TAG}"
|
|
443
|
+
RELEASE_BODY_TITLE="[${NEXT_RELEASE_TAG}](${RELEASE_DIFF_URL}) (${CURRENT_DATE})"
|
|
444
|
+
else
|
|
445
|
+
RELEASE_BODY_TITLE="${NEXT_RELEASE_TAG} (${CURRENT_DATE})"
|
|
446
|
+
fi
|
|
447
|
+
|
|
448
|
+
RELEASE_BODY="# ${RELEASE_BODY_TITLE}\n${RELEASE_BODY}"
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
##############################
|
|
452
|
+
######## Handle push ########
|
|
453
|
+
##############################
|
|
454
|
+
|
|
455
|
+
handle_pushes() {
|
|
456
|
+
log_verbose "Applying changes..."
|
|
457
|
+
log_verbose "Found tag commit [${CHECKOUT_SHA}]"
|
|
458
|
+
|
|
459
|
+
for plugin in "${PLUGINS[@]}"; do
|
|
460
|
+
log_verbose "Loading plugin \`${plugin}\`..."
|
|
461
|
+
local SOURCE_PLUGIN_FILE="${SCRIPT_DIR}/plugins/${plugin}.sh"
|
|
462
|
+
# shellcheck disable=SC1090 source=/dev/null
|
|
463
|
+
source "${SOURCE_PLUGIN_FILE}"
|
|
464
|
+
release_command=$(command -v release)
|
|
465
|
+
if [[ -n "${release_command}" ]]; then
|
|
466
|
+
release
|
|
467
|
+
fi
|
|
468
|
+
unset release
|
|
469
|
+
log_verbose "Applied plugin ${plugin}!"
|
|
470
|
+
done
|
|
471
|
+
|
|
472
|
+
log_verbose "Applied changes!"
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
##############################
|
|
476
|
+
######### Initialize #########
|
|
477
|
+
##############################
|
|
478
|
+
parse_packages
|
|
479
|
+
get_git_variables
|
|
480
|
+
get_git_commits
|
|
481
|
+
handle_git_commits
|
|
482
|
+
handle_pushes
|