summaryrefslogtreecommitdiff
path: root/src/lib/release.sh
blob: acb3b541e806c9a17566e933ebce181419efc3e2 (plain)
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
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later

[[ -z ${DEVTOOLS_INCLUDE_RELEASE_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_RELEASE_SH=1

_DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
# shellcheck source=src/lib/db/update.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/update.sh
# shellcheck source=src/lib/util/pacman.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/pacman.sh
# shellcheck source=src/lib/valid-repos.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/valid-repos.sh

source /usr/share/makepkg/util/util.sh

set -e


pkgctl_release_usage() {
	local -r COMMAND=${_DEVTOOLS_COMMAND:-${BASH_SOURCE[0]##*/}}
	cat <<- _EOF_
		Usage: ${COMMAND} [OPTIONS] [PATH]...

		Release step to commit, tag and upload build artifacts

		Modified version controlled files will first be staged for commit,
		afterwards a Git tag matching the pkgver will be created and finally
		all build artifacts will be uploaded.

		By default the target pacman repository will be auto-detected by querying
		the repo it is currently released in. When initially adding a new package
		to the repositories, the target repo must be specified manually.

		OPTIONS
		    -m, --message MSG   Use the given <msg> as the commit message
		    -r, --repo REPO     Specify target repository for new packages not in any official repo
		    -s, --staging       Release to the staging counterpart of the auto-detected repo
		    -t, --testing       Release to the testing counterpart of the auto-detected repo
		    -u, --db-update     Automatically update the pacman database after uploading
		    -h, --help          Show this help text

		EXAMPLES
		    $ ${COMMAND}
		    $ ${COMMAND} --staging --message 'libyay 0.42 rebuild' libfoo libbar
		    $ ${COMMAND} --repo extra --db-update new-package
_EOF_
}

pkgctl_release_check_option_group() {
	local option=$1
	local repo=$2
	local testing=$3
	local staging=$4
	if [[ -n "${repo}" ]] || (( testing )) || (( staging )); then
		die "The argument '%s' cannot be used with one or more of the other specified arguments" "${option}"
		exit 1
	fi
	return 0
}

pkgctl_release() {
	if (( $# < 1 )) && [[ ! -f PKGBUILD ]]; then
		pkgctl_release_usage
		exit 1
	fi

	local MESSAGE=""
	local PKGBASES=()
	local REPO=""
	local TESTING=0
	local STAGING=0
	local DB_UPDATE=0

	local path pkgbase pkgnames repo repos

	# option checking
	while (( $# )); do
		case $1 in
			-h|--help)
				pkgctl_release_usage
				exit 0
				;;
			-m|--message)
				(( $# <= 1 )) && die "missing argument for %s" "$1"
				MESSAGE=$2
				shift 2
				;;
			-r|--repo)
				(( $# <= 1 )) && die "missing argument for %s" "$1"
				pkgctl_release_check_option_group '--repo' "${REPO}" "${TESTING}" "${STAGING}"
				REPO=$2
				shift 2
				;;
			-s|--staging)
				pkgctl_release_check_option_group '--staging' "${REPO}" "${TESTING}" "${STAGING}"
				STAGING=1
				shift
				;;
			-t|--testing)
				pkgctl_release_check_option_group '--testing' "${REPO}" "${TESTING}" "${STAGING}"
				TESTING=1
				shift
				;;
			-u|--db-update)
				DB_UPDATE=1
				shift
				;;
			-*)
				die "invalid option: %s" "$1"
				;;
			*)
				PKGBASES+=("$@")
				break
				;;
		esac
	done

	# Resolve package from current working directory
	if (( 0 == ${#PKGBASES[@]} )); then
		PKGBASES=("$PWD")
	fi

	# Update pacman cache for auto-detection
	if [[ -z ${REPO} ]]; then
		update_pacman_repo_cache
	# Check valid repos if not resolved dynamically
	elif ! in_array "${REPO}" "${DEVTOOLS_VALID_REPOS[@]}"; then
		die "Invalid repository target: %s" "${REPO}"
	fi

	for path in "${PKGBASES[@]}"; do
		pushd "${path}" >/dev/null
		pkgbase=$(basename "${path}")

		# auto-detect target repository
		if ! repo=$(get_pacman_repo_from_pkgbuild PKGBUILD); then
			die 'Failed to query pacman repo'
		fi

		# fail if an existing package specifies --repo
		if [[ -n "${repo}" ]] && [[ -n ${REPO} ]]; then
			# allow unstable to use --repo
			if [[ ${REPO} == *unstable ]]; then
				repo=${REPO}
			else
				die 'Using --repo for packages that exist in official repositories is disallowed'
			fi
		fi

		# fail if a new package does not specify --repo
		if [[ -z "${repo}" ]]; then
			if [[ -z ${REPO} ]]; then
				die 'Specify --repo for packages that do not yet exist in official repositories'
			fi
			repo=${REPO}
		fi

		if (( TESTING )); then
			repo="${repo}-testing"
		elif (( STAGING )); then
			repo="${repo}-staging"
		elif [[ $repo == core ]]; then
			repo="${repo}-testing"
		fi

		msg "Releasing ${pkgbase} to ${repo}"
		commitpkg "${repo}" "${MESSAGE}"

		unset repo
		popd >/dev/null
	done

	if (( DB_UPDATE )); then
		# shellcheck disable=2119
		pkgctl_db_update
	fi
}