This is a deliberately plain production runbook.
Examples use only local paths and assume the service user is
teamcity.
Create the base directory once.
sudo mkdir -p /data/tcbot/workClone the repository if it is not there yet:
cd /data/tcbot
git clone https://github.com/apache/ignite-teamcity-bot.git ignite-teamcity-botBefore each build, update the checkout:
cd /data/tcbot/ignite-teamcity-bot
git fetch origin master
git switch master
git pull --ff-only origin masterUse Java 17. Build with Gradle. This has been tested with Gradle 9.5 and Gradle 9.4.1.
cd /data/tcbot/ignite-teamcity-bot
gradle clean build --no-daemon
gradle :jetty-launcher:clean :jetty-launcher:distZip --no-daemonThe distribution archive is:
/data/tcbot/ignite-teamcity-bot/jetty-launcher/build/distributions/jetty-launcher.zipIt contains bin, lib, and war/ignite-tc-helper-web.war.
Stop TC Bot before copying or migrating anything:
sudo systemctl stop tcbot
sudo systemctl status tcbot
pgrep -af 'jetty-launcher|TcHelperJettyLauncher' || trueDo not continue until the Java process is gone.
Create one timestamped backup directory. Keep the old runtime and the whole work directory together, so rollback can use the same files that were running before the upgrade.
TS="$(date +%Y%m%d-%H%M%S)"
BACKUP="/data/tcbot/backup_for_update/$TS"
mkdir -p "$BACKUP"Back up the live runtime:
if [ -d /data/tcbot/jetty-launcher ]; then
cp -a /data/tcbot/jetty-launcher "$BACKUP/jetty-launcher"
fiBack up the live work directory. This is the database backup too, because Ignite persistence is inside work:
cp -a /data/tcbot/work "$BACKUP/work"Back up the generated launch scripts from the old runtime:
mkdir -p "$BACKUP/scripts"
if [ -d /data/tcbot/jetty-launcher/bin ]; then
cp -a /data/tcbot/jetty-launcher/bin "$BACKUP/scripts/bin"
fiWrite a tiny restore note into the backup:
{
echo "Created: $TS"
echo "Runtime: $BACKUP/jetty-launcher"
echo "Work: $BACKUP/work"
echo "Launch scripts: $BACKUP/scripts"
} > "$BACKUP/README.txt"Install the new archive into a staging directory first:
cd /data/tcbot/ignite-teamcity-bot
rm -rf /data/tcbot/jetty-launcher.new
unzip -oq jetty-launcher/build/distributions/jetty-launcher.zip -d /data/tcbot/jetty-launcher.newThe archive unpacks to /data/tcbot/jetty-launcher.new/jetty-launcher. Replace the live runtime only after the backup
exists:
rm -rf /data/tcbot/jetty-launcher
mv /data/tcbot/jetty-launcher.new/jetty-launcher /data/tcbot/jetty-launcher
rmdir /data/tcbot/jetty-launcher.newMake sure the live config exists:
if [ ! -f /data/tcbot/work/branches.json ]; then
cp /data/tcbot/ignite-teamcity-bot/conf/branches.json /data/tcbot/work/branches.json
fiCreate or update /etc/systemd/system/tcbot.service:
[Unit]
Description=Ignite TeamCity Bot
After=network-online.target
[Service]
Type=simple
User=teamcity
Group=teamcity
WorkingDirectory=/data/tcbot/jetty-launcher/bin
Environment="JAVA_HOME=/usr/lib/jvm/java-17"
Environment="TCBOT_WORK_DIR=/data/tcbot/work"
ExecStart=/data/tcbot/jetty-launcher/bin/jetty-launcher
Restart=on-failure
[Install]
WantedBy=multi-user.targetReload systemd and start the service:
sudo systemctl daemon-reload
sudo systemctl enable tcbot
sudo systemctl start tcbot
sudo systemctl status tcbotThe generated bin/jetty-launcher already contains the Java options required by the runtime. Do not duplicate those
options in the systemd unit unless the generated script cannot be used.
The production launcher creates /data/tcbot/work/diagnostic on startup. JVM heap dumps and fatal error logs are
written there as java_pid<pid>.hprof and hs_err_pid<pid>.log.
Check logs first:
journalctl -u tcbot -n 200 --no-pager
ls -la /data/tcbot/work
ls -la /data/tcbot/work/diagnosticIf the bot starts and opens the database, keep the backup. Do not delete it immediately after a major Java or Ignite upgrade.
Rollback uses the backup made in step 5.
sudo systemctl stop tcbot
TS="<backup timestamp>"
BACKUP="/data/tcbot/backup_for_update/$TS"
rm -rf /data/tcbot/jetty-launcher
cp -a "$BACKUP/jetty-launcher" /data/tcbot/jetty-launcher
rm -rf /data/tcbot/work
cp -a "$BACKUP/work" /data/tcbot/work
sudo systemctl start tcbot
sudo systemctl status tcbotIf the rollback target is a very old version, restore and use the old Java version from the same backup notes. Do not try to run a 2022-era runtime with the new Java 17 service file unless it was already tested that way.
Older deployments may have been built and run with Java 8 or Java 11 and an old Gradle version. Treat that upgrade as a migration, not as a simple overwrite.
-
Keep the old environment available.
Before changing the live service, record where the old Java and old runtime are:
readlink -f "$(command -v java)" java -version ls -la /data/tcbotIf rollback is needed, use the old runtime backup together with the old Java and old Gradle versions. Make sure the old Gradle is still available in
PATHbefore relying on rollback or on rebuilding the old version. Build the new checkout with Java 17 and a tested Gradle version: 9.5 or 9.4.1. Do not assume the old backup will run correctly on Java 17.If several historical builds must stay available, prefer versioned runtime directories and a symlink, for example
latest -> 2.17. -
Install the new source and new runtime into new paths first.
Use separate new directories for the checkout, runtime, and work directory. Do not delete the old runtime directory until the new service has started successfully and the backup has been verified.
-
Stop the old bot and back up everything.
Back up the old runtime and the whole old work directory before touching the database. The important database files are inside the work directory, commonly under
work/dbfor current versions and sometimes underwork/tcbot_srvin old versions. -
Copy the old work directory into the new location.
If the old work directory is elsewhere, copy it to
/data/tcbot/workwhile the bot is stopped:rm -rf /data/tcbot/work cp -a <old-work-dir> /data/tcbot/work
-
Start the new Java 17 service.
Start with the systemd unit from this document. Watch
journalctl -u tcbotand/data/tcbot/work/tcbot_logs. The first start may run built-in database checks and migrations during Ignite startup; let it finish instead of restarting repeatedly. Do not run the offline migrator directly as part of the normal installation procedure. -
Roll back as a full set if the migration fails.
Stop the new service, restore the old runtime and old work directory from the same timestamped backup, and start it with the old Java/runtime setup. Do not restore only the runtime while keeping a database already opened or migrated by the new version.
Local clean checks and emulated bot runs are documented in Testing.