set -eu
: "${RK_REPO:?rk sets this; run this script through rk setup}"
project="$(printf '%s' "$RK_REPO" | sed 's|/|%2F|g')"
root="${RK_REPO%%/*}"
compact() {
awk '{ text = text $0 "\n" } END {
out = ""; inside = 0; escaped = 0
for (i = 1; i <= length(text); i++) {
c = substr(text, i, 1)
if (inside) {
out = out c
if (escaped) escaped = 0
else if (c == "\\") escaped = 1
else if (c == "\"") inside = 0
} else if (c == "\"") { out = out c; inside = 1 }
else if (c !~ /[ \t\r\n]/) out = out c
}
printf "%s", out
}'
}
text_of() { grep -o "\"$1\":\"[^\"]*\"" | head -n 1 | cut -d '"' -f 4; }
number_of() { grep -o "\"$1\":[0-9]*" | head -n 1 | cut -d : -f 2; }
stored=0
if glab api "projects/$project/variables/RELEASE_BOT_TOKEN" >/dev/null 2>&1; then
stored=1
fi
store() {
if [ "$stored" = "1" ]; then
printf '%s' "$1" | glab variable update RELEASE_BOT_TOKEN --masked --repo "$RK_REPO"
else
printf '%s' "$1" | glab variable set RELEASE_BOT_TOKEN --masked --repo "$RK_REPO"
fi
}
if [ -n "${RK_BOT_TOKEN:-}" ]; then
store "$RK_BOT_TOKEN"
echo 'ok RELEASE_BOT_TOKEN overwritten from RK_BOT_TOKEN'
elif [ "${RK_GITLAB_COM:-false}" = "true" ]; then
namespace="$(glab api "namespaces/$root" | compact)"
plan="$(printf '%s' "$namespace" | text_of plan)"
kind="$(printf '%s' "$namespace" | text_of kind)"
group="$(printf '%s' "$namespace" | number_of id)"
if [ "$plan" != "free" ] || [ "$kind" != "group" ]; then
echo "FAIL the namespace $root reads plan ${plan:-unknown}, kind ${kind:-unknown}, whose bot is a project access token no step can re-read" >&2
echo 'remediation: rk setup step install-bot --apply replaces the token, or export RK_BOT_TOKEN to rotate one' >&2
exit 1
fi
project_id="$(glab api "projects/$project" | compact | number_of id)"
name="${RK_BOT_NAME:-release-bot-$project_id}"
if ! accounts="$(glab api --paginate "groups/$group/service_accounts?per_page=100")"; then
echo "FAIL the service accounts of $root could not be read" >&2
echo "remediation: the caller needs the Owner role on the top-level group $root, then rerun" >&2
exit 1
fi
account="$(printf '%s' "$accounts" | compact | tr '}' '\n' | grep -F "\"username\":\"$name\"" | number_of id)"
if [ -z "$account" ]; then
echo "FAIL no service account named $name exists in $root" >&2
echo 'remediation: rk setup step install-bot --apply creates it' >&2
exit 1
fi
expires="$(($(date -u +%Y) + 1))-$(date -u +%m)-01"
if ! response="$(glab api -X POST "groups/$group/service_accounts/$account/personal_access_tokens" \
-f "name=$name" \
-f 'description=release-kit bot identity' \
-F 'scopes=["api","write_repository"]' \
-f "expires_at=$expires")"; then
echo "FAIL a token could not be minted for the service account $name" >&2
echo "remediation: the caller needs the Owner role on the top-level group $root, then rerun" >&2
exit 1
fi
token="$(printf '%s' "$response" | compact | text_of token)"
if [ -z "$token" ]; then
echo 'FAIL the mint response carried no token value' >&2
echo "remediation: check the caller is an Owner of $root, then rerun" >&2
exit 1
fi
store "$token"
echo "ok minted a new token on the service account $name and stored RELEASE_BOT_TOKEN"
elif [ "$stored" != "1" ]; then
echo 'FAIL RELEASE_BOT_TOKEN is not stored on the project' >&2
echo 'remediation: rk setup step install-bot --apply creates and stores it' >&2
exit 1
fi
echo 'check: prints the variable key'
glab api "projects/$project/variables/RELEASE_BOT_TOKEN" | compact | grep -o '"key":"RELEASE_BOT_TOKEN"'