You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
482 lines
21 KiB
Bash
482 lines
21 KiB
Bash
#!/usr/bin/env bash
|
|
# vim:ts=4:sts=4:sw=4:et
|
|
#
|
|
# Author: Hari Sekhon
|
|
# Date: 2020-11-24 17:09:11 +0000 (Tue, 24 Nov 2020)
|
|
#
|
|
# https://github.com/HariSekhon/DevOps-Bash-tools
|
|
#
|
|
# License: see accompanying Hari Sekhon LICENSE file
|
|
#
|
|
# If you're using my code you're welcome to connect with me on LinkedIn and optionally send me feedback to help improve or steer this or other code I publish
|
|
#
|
|
# https://www.linkedin.com/in/HariSekhon
|
|
#
|
|
|
|
set -euo pipefail
|
|
[ -n "${DEBUG:-}" ] && set -x
|
|
srcdir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
# dipping into interactive library for opening browser to TeamCity to accept EULA
|
|
# XXX: order is important here because there is an interactive library of retry() and a scripting library version of retry() and we want the latter, which must be imported second
|
|
# shellcheck disable=SC1090
|
|
. "$srcdir/.bash.d/network.sh"
|
|
|
|
# shellcheck disable=SC1090
|
|
. "$srcdir/lib/utils.sh"
|
|
|
|
# shellcheck disable=SC2034
|
|
usage_description="
|
|
Boots TeamCity CI cluster with server and agent(s) in Docker, and builds the current repo
|
|
|
|
- boots TeamCity server and agent in Docker
|
|
- authorizes the agent(s) to begin building
|
|
- waits for you to accept the EULA
|
|
- prints the TeamCity URL
|
|
- opens the TeamCity web UI (on Mac only)
|
|
|
|
- creates an administator-level user (\$TEAMCITY_USER, / \$TEAMCITY_PASSWORD - defaults to admin / admin)
|
|
- sets the full name, email, and VCS commit username to Git's user.name and user.email if configured for TeamCity to Git VCS tracking integration
|
|
- opens the TeamCity web UI login page in browser (on Mac only)
|
|
|
|
- creates a GitHub OAuth connection if credentials are available (\$TEAMCITY_GITHUB_CLIENT_ID and \$TEAMCITY_GITHUB_CLIENT_SECRET)
|
|
- this saves you having to use your own username and password for the GitHub VCS such as the config repo - just click the GitHub icon next to the VCS url to auto-authenticate
|
|
|
|
- if there is a .teamcity.vcs.json VCS configuration in the current directory, creates the VCS to use as a config sync repo
|
|
- if this is a private repo, you either need to put the credentials in the file temporarily, or set the password to blank, and edit it after boot
|
|
- currently must use authentication even if th repo is public: https://youtrack.jetbrains.com/issue/TW-69183
|
|
- if GitHub OAuth connection credentials are available, will instead look for .teamcity.auth.vcs.json
|
|
- you'll need to disable & re-enable the project's Versioned Settings to get the import dialog for your projects before it starts sync'ing
|
|
- this is another TeamCity limitation: https://youtrack.jetbrains.com/issue/TW-58754
|
|
|
|
Usage:
|
|
|
|
${0##*/} [up]
|
|
|
|
${0##*/} down
|
|
|
|
${0##*/} ui - prints the TeamCity Server URL and on Mac automatically opens in browser
|
|
|
|
|
|
Idempotent, you can re-run this and continue from any stage
|
|
|
|
|
|
The official docker images from JetBrains are huge so the first pull may take a while
|
|
|
|
|
|
See Also:
|
|
|
|
teamcity_api.sh - makes heavy use of this script to handle setup API calls with authentication
|
|
|
|
|
|
Advanced:
|
|
|
|
TeamCity GitHub OAuth integration - set up your TeamCity OAuth credentials here:
|
|
|
|
https://github.com/settings/developers
|
|
|
|
If \$TEAMCITY_GITHUB_CLIENT_ID and \$TEAMCITY_GITHUB_CLIENT_SECRET are available in the environment it will configure a connection for your GitHub VCS roots authentication
|
|
|
|
|
|
If your GitHub OAuth connection has been created you can use this to authenticate the TeamCity VCS root in the Root project,
|
|
and use that to sync your Project configuration to/from Github under Project's Settings -> Versioned Settings using the VCS referenced from the Root project.
|
|
|
|
It's better to keep the TeamCity config VCS in the Root project because when you sync a project and it replaces the VCS json credential it breaks the GitHub sync
|
|
and needs to be re-created. By putting it in the Root project and only enabling VCS sync on the sub-project you avoid this problem.
|
|
|
|
|
|
Tested on TeamCity 2020.1, 2020.2
|
|
"
|
|
|
|
# used by usage() in lib/utils.sh
|
|
# shellcheck disable=SC2034
|
|
usage_args="[ up | down | ui ]"
|
|
|
|
help_usage "$@"
|
|
|
|
export COMPOSE_PROJECT_NAME="bash-tools"
|
|
export COMPOSE_FILE="$srcdir/docker-compose/teamcity.yml"
|
|
|
|
vcs_config=".teamcity.vcs.json"
|
|
# OAuth connection
|
|
vcs_config_auth=".teamcity.vcs.oauth.json"
|
|
# SSH key connection
|
|
vcs_config_ssh_auth=".teamcity.vcs.ssh.json"
|
|
|
|
TEAMCITY_SSH_KEY="${TEAMCITY_SSH_KEY:-$HOME/.ssh/id_rsa}"
|
|
|
|
project="GitHub"
|
|
|
|
#teamcity_port="$(docker-compose config | sed -n '/teamcity-server:[[:space:]]*$/,$p' | awk '/- published: [[:digit:]]+/{print $3; exit}')"
|
|
|
|
# don't take any change this script could run against a real teamcity server for safety
|
|
#export TEAMCITY_URL="http://${TEAMCITY_HOST:-localhost}:${TEAMCITY_PORT:-8111}"
|
|
export TEAMCITY_URL="http://${DOCKER_HOST:-localhost}:8111"
|
|
|
|
if ! type docker-compose &>/dev/null; then
|
|
"$srcdir/setup/install_docker_compose.sh"
|
|
fi
|
|
|
|
action="${1:-up}"
|
|
shift || :
|
|
|
|
if [ "$action" = up ]; then
|
|
timestamp "Booting TeamCity cluster:"
|
|
# starting agents later they won't be connected in time to become authorized
|
|
# only start the server, don't wait for the agent to download before triggering the URL to prompt user for initialization so it can progress while agent is downloading
|
|
#docker-compose up -d teamcity-server "$@"
|
|
docker-compose up -d "$@"
|
|
echo
|
|
elif [ "$action" = restart ]; then
|
|
docker-compose down
|
|
echo
|
|
exec "${BASH_SOURCE[0]}" up
|
|
elif [ "$action" = ui ]; then
|
|
echo "TeamCity Server URL: $TEAMCITY_URL"
|
|
if is_mac; then
|
|
open "$TEAMCITY_URL"
|
|
fi
|
|
exit 0
|
|
else
|
|
docker-compose "$action" "$@"
|
|
echo
|
|
exit 0
|
|
fi
|
|
|
|
# fails due to 302 redirect to http://localhost:8111/setupAdmin.html
|
|
# / and /setupAdmin.html and /login.html
|
|
#when_url_content "$TEAMCITY_URL/login.html" '(?i:teamcity)'
|
|
#when_ports_available 60 "${TEAMCITY_HOST:-localhost}" "${TEAMCITY_PORT:-8111}"
|
|
when_url_content 60 "$TEAMCITY_URL" '.*'
|
|
echo
|
|
|
|
# XXX: database.properties is mounted to skip the database step now
|
|
is_setup_in_progress(){
|
|
# don't let cut off output affect the return code
|
|
{ curl -sSL "$TEAMCITY_URL" || : ; } | \
|
|
grep -qi -e 'first.*start' \
|
|
-e 'database.*setup' \
|
|
-e 'TeamCity Maintenance' \
|
|
-e 'Setting up'
|
|
}
|
|
|
|
timestamp "TeamCity Server URL: $TEAMCITY_URL"
|
|
echo
|
|
if is_setup_in_progress; then
|
|
timestamp "Open TeamCity Server URL in web browser to continue, click proceed, accept EULA etc.."
|
|
echo
|
|
if is_mac; then
|
|
timestamp "detected running on Mac, opening TeamCity Server URL for you automatically"
|
|
echo
|
|
open "$TEAMCITY_URL"
|
|
fi
|
|
fi
|
|
|
|
# too late, agent won't arrive in the unauthorized list in time to be found and authorized before this script exits, agents must boot in parallel with server not later
|
|
# now download and start the agent(s) while the server is booting
|
|
#docker-compose up -d
|
|
|
|
# now continue configuring server
|
|
|
|
max_secs=300
|
|
|
|
SECONDS=0
|
|
timestamp "waiting for up to $max_secs seconds for user to click proceed through First Start and database setup pages"
|
|
while is_setup_in_progress; do
|
|
timestamp "waiting for you to click proceed through First Start & setup pages and then preliminary initialization to finish"
|
|
if [ $SECONDS -gt $max_secs ]; then
|
|
die "Did not progress past First Start and setup pages within $max_secs seconds"
|
|
fi
|
|
sleep 3
|
|
done
|
|
echo
|
|
|
|
# second run would break here as this wouldn't come again, must use .* search
|
|
# just to check we are not getting a temporary 404 or something that happens before the EULA comes up
|
|
#when_url_content 60 "$TEAMCITY_URL" "license.*agreement"
|
|
when_url_content 60 "$TEAMCITY_URL" ".*"
|
|
echo
|
|
|
|
SECONDS=0
|
|
timestamp "waiting for up to $max_secs seconds for user to accept EULA"
|
|
# curl gives an error when grep cuts its long EULA agreement short:
|
|
# (23) Failed writing body
|
|
while { curl -sSL "$TEAMCITY_URL" 2>/dev/null || : ; } |
|
|
grep -qi 'license.*agreement'; do
|
|
timestamp "waiting for you to accept the license agreement"
|
|
if [ $SECONDS -gt $max_secs ]; then
|
|
die "Did not accept EULA within $max_secs seconds"
|
|
fi
|
|
sleep 3
|
|
done
|
|
echo
|
|
|
|
SECONDS=0
|
|
timestamp "waiting for up to $max_secs seconds for TeamCity to finish initializing"
|
|
# too transitory to be idempotent
|
|
#while ! curl -sS "$TEAMCITY_URL" | grep -q 'TeamCity is starting'; do
|
|
# although hard to miss this log as not a fast scroll, might break idempotence for re-running later if logs are cycled out of buffer
|
|
#while ! docker-compose logs --tail 50 teamcity-server | grep -q 'TeamCity initialized'; do
|
|
while ! { docker-compose logs teamcity-server || : ; } |
|
|
grep -q -e 'Super user authentication token'; do
|
|
#-e 'TeamCity initialized' # happens just before but checking for the super user token achieves both and protects against race condition
|
|
timestamp 'waiting for TeamCity server to finish initializing and reveal superuser token in logs'
|
|
if [ $SECONDS -gt $max_secs ]; then
|
|
die "TeamCity server failed to initialize within $max_secs seconds (perhaps you didn't trigger the UI to continue initialization?)"
|
|
fi
|
|
sleep 3
|
|
done
|
|
echo
|
|
|
|
TEAMCITY_SUPERUSER_TOKEN="$(docker-compose logs teamcity-server | grep -E -o 'Super user authentication token: [[:alnum:]]+' | tail -n1 | awk '{print $5}' || :)"
|
|
|
|
if [ -z "$TEAMCITY_SUPERUSER_TOKEN" ]; then
|
|
timestamp "ERROR: Super user token not found in docker logs (maybe premature or late ie. logs were already cycled out of buffer?)"
|
|
exit 1
|
|
fi
|
|
|
|
export TEAMCITY_SUPERUSER_TOKEN
|
|
|
|
timestamp "TeamCity superuser token: $TEAMCITY_SUPERUSER_TOKEN"
|
|
timestamp "(this must be used with a blank username via basic auth if using the API)"
|
|
echo
|
|
|
|
teamcity_user="${TEAMCITY_USER:-admin}"
|
|
teamcity_password="${TEAMCITY_PASSWORD:-admin}"
|
|
|
|
user_already_exists=0
|
|
api_token=""
|
|
#timestamp "Checking if teamcity user '$teamcity_user' exists"
|
|
timestamp "Checking if any user already exists"
|
|
users="$("$srcdir/teamcity_api.sh" /users -sSL --fail | jq -r '.user[].username')"
|
|
#if grep -Fxq "$teamcity_user" <<< "$users"; then
|
|
# timestamp "teamcity user '$teamcity_user' user already detected, skipping creation"
|
|
if [ -n "${users//[[:space:]]/}" ]; then
|
|
timestamp "users already exist, not creating teamcity administrative user '$teamcity_user'"
|
|
user_already_exists=1
|
|
else
|
|
#timestamp "Creating teamcity user '$teamcity_user':"
|
|
timestamp "no users exist yet, creating teamcity user '$teamcity_user'"
|
|
"$srcdir/teamcity_api.sh" /users -sSL --fail \
|
|
-d "{ \"username\": \"$teamcity_user\", \"password\": \"$teamcity_password\"}"
|
|
# Note: Unnecessary use of -X or --request, POST is already inferred.
|
|
#-X POST \
|
|
# no newline returned if error eg.
|
|
# Details: jetbrains.buildServer.server.rest.errors.BadRequestException: Cannot create user as user with the same username already exists, caused by: jetbrains.buildServer.users.DuplicateUserAccountException: The specified username 'admin' is already in use by some other user.
|
|
# Invalid request. Please check the request URL and data are correct.
|
|
echo
|
|
echo
|
|
git_user="$(git config user.name)"
|
|
git_email="$(git config user.email)"
|
|
if [ -n "$git_user" ]; then
|
|
timestamp "Setting teamcity user $teamcity_user's username to '$git_user'"
|
|
"$srcdir/teamcity_api.sh" "/users/$teamcity_user/name" -X PUT -d "$git_user" -H 'Content-Type: text/plain' -H 'Accept: text/plain'
|
|
# API echo's username without newline
|
|
echo
|
|
timestamp "Setting teamcity user $teamcity_user's VCS default username to '$git_user'"
|
|
"$srcdir/teamcity_api.sh" "/users/admin/properties/plugin:vcs:anyVcs:anyVcsRoot" -X PUT -d "$git_user" -H 'Content-Type: text/plain' -H 'Accept: text/plain'
|
|
# API echo's username without newline
|
|
echo
|
|
fi
|
|
if [ -n "$git_email" ]; then
|
|
timestamp "Setting teamcity user $teamcity_user's email to '$git_email'"
|
|
"$srcdir/teamcity_api.sh" "/users/$teamcity_user/email" -X PUT -d "$git_email" -H 'Content-Type: text/plain' -H 'Accept: text/plain'
|
|
# prints email without newline
|
|
echo
|
|
fi
|
|
timestamp "Setting teamcity user '$teamcity_user' as system administrator:"
|
|
"$srcdir/teamcity_api.sh" "/users/username:$teamcity_user/roles/SYSTEM_ADMIN/g/" -sSL --fail -X PUT > /dev/null
|
|
# no newline returned
|
|
echo
|
|
api_token="$("$srcdir/teamcity_api.sh" "/users/$teamcity_user/tokens" -sSL | \
|
|
jq -r '.token[]' || :)"
|
|
# XXX: could create expiring self-deleting token here each time, but would make idempotence tricker
|
|
# due to timings and also use might want to use it in teamcity_api.sh later
|
|
if [ -n "$api_token" ]; then
|
|
timestamp "TeamCity user '$teamcity_user' already has an API token, skipping token creation"
|
|
timestamp "since we cannot get existing token value out of the API, will load TEAMCITY_SUPERUSER_TOKEN to environment to use instead"
|
|
else
|
|
timestamp "Creating API token for user '$teamcity_user'"
|
|
api_token="$("$srcdir/teamcity_api.sh" "/users/$teamcity_user/tokens/mytoken" -sSL --fail -X POST | jq -r '.value')"
|
|
timestamp "here is your user API token, export this and then you can easily use teamcity_api.sh:"
|
|
echo
|
|
# this takes precedence so disable it and use the user's api token instead
|
|
unset TEAMCITY_SUPERUSER_TOKEN
|
|
echo "export TEAMCITY_URL=$TEAMCITY_URL"
|
|
export TEAMCITY_URL="$TEAMCITY_URL"
|
|
echo "export TEAMCITY_TOKEN=$api_token"
|
|
export TEAMCITY_TOKEN="$api_token"
|
|
fi
|
|
fi
|
|
echo
|
|
|
|
if [ "$user_already_exists" = 0 ]; then
|
|
timestamp "Login here with username '$teamcity_user' and password: \$TEAMCITY_PASSWORD (default: admin):"
|
|
echo
|
|
login_url="$TEAMCITY_URL/login.html"
|
|
echo "$login_url"
|
|
echo
|
|
if is_mac; then
|
|
timestamp "detected running on Mac, opening TeamCity Server URL for you automatically"
|
|
open "$login_url"
|
|
echo
|
|
fi
|
|
echo
|
|
fi
|
|
|
|
timestamp "getting list of expected agents"
|
|
expected_agents="$(docker-compose config | awk '/^[[:space:]]+AGENT_NAME:/ {print $2}' | sed '/^[[:space:]]*$/d')"
|
|
num_expected_agents="$(grep -c . <<< "$expected_agents" || :)"
|
|
|
|
get_connected_agents(){
|
|
"$srcdir/teamcity_api.sh" "/agents?locator=connected:true,authorized:any" -sSL --fail |
|
|
jq -r '.agent[].name'
|
|
}
|
|
|
|
SECONDS=0
|
|
timestamp "waiting for $num_expected_agents expected agent(s) to connect before authorizing them"
|
|
while true; do
|
|
num_connected_agents="$(get_connected_agents | grep -c . || :)"
|
|
timestamp "connected agents: $num_connected_agents"
|
|
if [ "$num_connected_agents" -ge "$num_expected_agents" ]; then
|
|
timestamp "$num_connected_agents connected agents >= $num_expected_agents expected agents, continuing"
|
|
break
|
|
fi
|
|
if [ $SECONDS -gt $max_secs ]; then
|
|
timestamp "giving up waiting for connect agents after $max_secs"
|
|
break
|
|
fi
|
|
sleep 3
|
|
done
|
|
echo
|
|
|
|
timestamp "getting list of unauthorized agents"
|
|
# using our new teamcity API token, let's agents waiting to be authorized
|
|
unauthorized_agents="$("$srcdir/teamcity_api.sh" "/agents?locator=authorized:false" -sSL --fail | jq -r '.agent[].name')"
|
|
|
|
timestamp "authorizing any expected agents that are not currently authorized"
|
|
if [ -z "$unauthorized_agents" ]; then
|
|
timestamp "no unauthorized agents found"
|
|
fi
|
|
for agent in $unauthorized_agents; do
|
|
# XXX: recreated agents end up with a digit appended to the name to avoid clash with old stale agent reference
|
|
# if the agent disk state isn't lost this shouldn't be needed, but this environment is disposable so allow this
|
|
# this is only a local environment so we don't have to worry about rogue agents
|
|
for expected_agent in $expected_agents; do
|
|
# grep -f would be easier but don't want to depend on have the GNU version installed and then remapped via func
|
|
if [[ "$agent" =~ ^$expected_agent(-[[:digit:]]+)?$ ]]; then
|
|
timestamp "authorizing expected agent '$agent'"
|
|
# needs -H 'Accept: text/plain' to override the default -H 'Accept: application/json' from teamcity_api.sh
|
|
# otherwise gets 403 error and then even switching to -H 'Accept: text/plain' still breaks due to cookie jar behaviour,
|
|
# so teamcity_api.sh now uses a unique cookie jar per script run and clears the cookie jar first
|
|
"$srcdir/teamcity_api.sh" "/agents/$agent/authorized" -X PUT -d true -H 'Accept: text/plain' -H 'Content-Type: text/plain'
|
|
# no newline returned
|
|
echo
|
|
continue 2
|
|
fi
|
|
done
|
|
timestamp "WARNING: unauthorized agent '$agent' was not expected, not automatically authorizing"
|
|
done
|
|
echo
|
|
|
|
# this stops us accumulating huge numbers of agent-[[:digit:]] increments each time
|
|
timestamp "deleting old disconnected agent references"
|
|
# slight race condition here but it's not critical
|
|
disconnected_agents="$("$srcdir/teamcity_api.sh" "/agents?locator=connected:false" -sSL --fail | jq -r '.agent[].name')"
|
|
for disconnected_agent in $disconnected_agents; do
|
|
timestamp "deleting disconnected agent '$disconnected_agent'"
|
|
"$srcdir/teamcity_api.sh" "/agents/$disconnected_agent" -X DELETE
|
|
done
|
|
echo
|
|
|
|
if [ -f "$TEAMCITY_SSH_KEY" ]; then
|
|
# overwrites key if already exists
|
|
if "$srcdir/teamcity_upload_ssh_key.sh" "$TEAMCITY_SSH_KEY" "VCS SSH Key"; then
|
|
if [ -f "$vcs_config_ssh_auth" ]; then
|
|
echo
|
|
timestamp "switching VCS config to '$vcs_config_ssh_auth'"
|
|
vcs_config="$vcs_config_ssh_auth"
|
|
fi
|
|
fi
|
|
echo
|
|
fi
|
|
|
|
if [ -n "${TEAMCITY_GITHUB_CLIENT_ID:-}" ] && [ -n "${TEAMCITY_GITHUB_CLIENT_SECRET:-}" ]; then
|
|
# detects and skips creation if an OAuth connection named 'GitHub.com' already exists
|
|
"$srcdir/teamcity_create_github_oauth_connection.sh"
|
|
echo
|
|
if [ "$vcs_config" != "$vcs_config_ssh_auth" ]; then
|
|
if [ -f "$vcs_config_auth" ]; then
|
|
timestamp "switching VCS config to '$vcs_config_auth'"
|
|
vcs_config="$vcs_config_auth"
|
|
echo
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
if [ -f "$vcs_config" ]; then
|
|
#timestamp "Now creating primary project '$project'"
|
|
# XXX: TeamCity API doesn't yet support creating a project from a saved configuration via the API, see this ticket:
|
|
#
|
|
# https://youtrack.jetbrains.com/issue/TW-43542
|
|
#
|
|
# So we create an empty project, then configure a VCS root to GitHub and reconfigure the project to pull from a GitHub repo
|
|
# TODO: get the project name from the config file
|
|
"$srcdir/teamcity_create_project.sh" "$project"
|
|
echo
|
|
vcs_id="$(jq -r .id < "$vcs_config")"
|
|
project_id="$(jq -r .project.id < "$vcs_config")"
|
|
if "$srcdir/teamcity_vcs_roots.sh" | grep -qi "^${vcs_id}[[:space:]]"; then
|
|
timestamp "VCS root '$vcs_id' already exists, skipping creation"
|
|
else
|
|
if [ "$project_id" != "_Root" ]; then
|
|
timestamp "Creating VCS container project '$project_id' if not already exists..."
|
|
"$srcdir/teamcity_create_project.sh" "$project_id"
|
|
fi
|
|
# XXX: this fails when TeamCity has only just booted, probably due to some initialization timing, but works on second run, so just wait for it to succeed
|
|
# UPDATE: seems this errors the first time yet still creates it and the second try skips as already exists
|
|
retry 300 "$srcdir/teamcity_create_vcs_root.sh" "$vcs_config"
|
|
fi
|
|
echo
|
|
timestamp "Configuring project Versioned Settings to import all buildTypes and VCS"
|
|
"$srcdir/teamcity_project_set_versioned_settings.sh" "$project"
|
|
echo
|
|
echo
|
|
timestamp "NOTICE: you need to enable VCS authentication for write access to be able to sync project configs:"
|
|
timestamp " (even if you have GitHub OAuth connection automated, you still need to click on the GitHub icon to initialize the sign-in)"
|
|
echo
|
|
printf '\t%s\n' "$TEAMCITY_URL/admin/editVcsRoot.html?action=editVcsRoot&vcsRootId=$vcs_id"
|
|
echo
|
|
echo
|
|
timestamp "This is a limitation of the TeamCity API (as of Dec 2020), documented here:"
|
|
echo
|
|
printf '\t%s\n' "https://youtrack.jetbrains.com/issue/TW-69183"
|
|
echo
|
|
echo
|
|
timestamp "NOTICE: one you've enabled authenticated access to the VCS root you'll have to disable and re-enable the '$project' project's Versioned Settings to get the import dialog for config sync to start working"
|
|
echo
|
|
printf '\t%s\n' "$TEAMCITY_URL/admin/editProject.html?projectId=$project&tab=versionedSettings"
|
|
echo
|
|
echo
|
|
timestamp "This is a limitation of the TeamCity API (as of Dec 2020), documented here:"
|
|
echo
|
|
printf '\t%s\n' "https://youtrack.jetbrains.com/issue/TW-58754"
|
|
echo
|
|
echo
|
|
else
|
|
timestamp "no config found: $vcs_config - skipping VCS setup and versioning integration / import"
|
|
fi
|
|
echo
|
|
|
|
#timestamp "Optimistically setting any buildTypes descriptions from their GitHub repos (ignoring failures)"
|
|
#"$srcdir/teamcity_buildtypes_set_description_from_github.sh" || :
|
|
|
|
timestamp "Build status icons:"
|
|
echo
|
|
printf '\t%s\n' "$TEAMCITY_URL/app/rest/builds/<build>/statusIcon.svg"
|
|
echo
|
|
timestamp "(requires this setting for each buildType: General Settings -> 'enable status widget' to permit unauthenticated status badge access)"
|
|
echo
|
|
echo
|
|
timestamp "TeamCity is up and ready"
|