Skip to content

Commit 5b6cf36

Browse files
committed
feat(service): warn about stale service configuration
2 parents ed4fd8a + 61b2f09 commit 5b6cf36

1 file changed

Lines changed: 158 additions & 0 deletions

File tree

src/commands/ServiceCommand.cpp

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,9 @@ namespace vix::commands
510510
out << "User=" << cfg.user << "\n";
511511
out << "WorkingDirectory=" << cfg.workingDir.string() << "\n";
512512

513+
if (const auto cliPath = current_vix_cli_path())
514+
out << "Environment=VIX_CLI_PATH=" << cliPath->string() << "\n";
515+
513516
if (cfg.vixDir)
514517
{
515518
out << "Environment=Vix_DIR=" << cfg.vixDir->string() << "\n";
@@ -527,6 +530,159 @@ namespace vix::commands
527530
return out.str();
528531
}
529532

533+
std::optional<std::string> systemctl_property(
534+
const std::string &serviceName,
535+
const std::string &property)
536+
{
537+
const std::string cmd =
538+
"systemctl show " +
539+
shell_quote(serviceName) +
540+
" -p " +
541+
shell_quote(property) +
542+
" --value 2>/dev/null";
543+
544+
return run_capture(cmd);
545+
}
546+
547+
fs::path canonical_or_absolute(const fs::path &path)
548+
{
549+
std::error_code ec;
550+
551+
fs::path resolved = fs::weakly_canonical(path, ec);
552+
553+
if (!ec && !resolved.empty())
554+
return resolved;
555+
556+
resolved = fs::absolute(path, ec);
557+
558+
if (!ec && !resolved.empty())
559+
return resolved;
560+
561+
return path;
562+
}
563+
564+
std::optional<fs::path> current_vix_cli_path()
565+
{
566+
if (const char *path = vix::utils::vix_getenv("VIX_CLI_PATH"))
567+
{
568+
if (*path)
569+
return fs::path(path);
570+
}
571+
572+
const auto found = run_capture("command -v vix 2>/dev/null");
573+
574+
if (!found)
575+
return std::nullopt;
576+
577+
return fs::path(*found);
578+
}
579+
580+
std::optional<std::string> parse_environment_value(
581+
const std::string &raw,
582+
const std::string &key)
583+
{
584+
std::istringstream stream(raw);
585+
std::string token;
586+
const std::string prefix = key + "=";
587+
588+
while (stream >> token)
589+
{
590+
if (token.rfind(prefix, 0) == 0)
591+
return token.substr(prefix.size());
592+
}
593+
594+
return std::nullopt;
595+
}
596+
597+
void warn_if_service_points_to_old_build_dir(const ServiceConfig &cfg)
598+
{
599+
const auto execStart =
600+
systemctl_property(cfg.serviceName, "ExecStart");
601+
602+
if (!execStart || execStart->empty())
603+
return;
604+
605+
const fs::path currentExec =
606+
canonical_or_absolute(cfg.execPath);
607+
608+
const std::string currentExecString = currentExec.string();
609+
610+
if (execStart->find(currentExecString) != std::string::npos)
611+
return;
612+
613+
vix::cli::util::warn_line(
614+
std::cerr,
615+
"Service executable points to a different build path.");
616+
617+
vix::cli::util::kv(
618+
std::cerr,
619+
"Service",
620+
*execStart);
621+
622+
vix::cli::util::kv(
623+
std::cerr,
624+
"Current",
625+
currentExecString);
626+
627+
vix::cli::util::warn_line(
628+
std::cerr,
629+
"Fix: run `vix service install` then `vix service restart`.");
630+
}
631+
632+
void warn_if_service_uses_different_vix_installation(const ServiceConfig &cfg)
633+
{
634+
const auto currentCli =
635+
current_vix_cli_path();
636+
637+
if (!currentCli)
638+
return;
639+
640+
const auto environment =
641+
systemctl_property(cfg.serviceName, "Environment");
642+
643+
if (!environment || environment->empty())
644+
return;
645+
646+
const auto serviceCli =
647+
parse_environment_value(*environment, "VIX_CLI_PATH");
648+
649+
if (!serviceCli || serviceCli->empty())
650+
return;
651+
652+
const fs::path current =
653+
canonical_or_absolute(*currentCli);
654+
655+
const fs::path service =
656+
canonical_or_absolute(fs::path(*serviceCli));
657+
658+
if (current == service)
659+
return;
660+
661+
vix::cli::util::warn_line(
662+
std::cerr,
663+
"Service uses a different Vix CLI installation.");
664+
665+
vix::cli::util::kv(
666+
std::cerr,
667+
"Current CLI",
668+
current.string());
669+
670+
vix::cli::util::kv(
671+
std::cerr,
672+
"Service CLI",
673+
service.string());
674+
675+
vix::cli::util::warn_line(
676+
std::cerr,
677+
"Fix: update production.service.environment.VIX_CLI_PATH, then run `vix service install`.");
678+
}
679+
680+
void warn_if_service_config_is_stale(const ServiceConfig &cfg)
681+
{
682+
warn_if_service_points_to_old_build_dir(cfg);
683+
warn_if_service_uses_different_vix_installation(cfg);
684+
}
685+
530686
int install_service()
531687
{
532688
const ServiceConfig cfg = load_service_config();
@@ -611,6 +767,8 @@ namespace vix::commands
611767

612768
if (action == "status")
613769
{
770+
warn_if_service_config_is_stale(cfg);
771+
614772
return std::system(
615773
("systemctl status " + shell_quote(cfg.serviceName)).c_str());
616774
}

0 commit comments

Comments
 (0)