Skip to content

Commit 592f6f8

Browse files
committed
2027 deploy works
- Need to refactor this commit and maybe do some of this in 2025/2026 first?
1 parent c7ed72f commit 592f6f8

File tree

4 files changed

+133
-150
lines changed

4 files changed

+133
-150
lines changed

robotpy_installer/cli_deploy.py

Lines changed: 91 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from . import pypackages, pyproject, robot_utils, sshcontroller
1919
from .installer import PipInstallError, PythonMissingError, RobotpyInstaller
2020
from .installer import _ROBOTPY_PYTHON_VERSION_TUPLE as required_pyversion
21+
from .installer import _ROBOT_VENV_PYTHON
2122
from .errors import Error
2223
from .utils import handle_cli_error, print_err, yesno
2324

@@ -241,20 +242,18 @@ def run(
241242
)
242243
raise Error(msg)
243244

244-
with sshcontroller.ssh_from_cfg(
245-
project_path,
246-
main_file,
247-
username=robot_utils.ssh_username,
248-
password=robot_utils.ssh_password,
245+
installer = RobotpyInstaller()
246+
247+
with installer.connect_to_robot(
248+
project_path=project_path,
249+
main_file=main_file,
249250
robot_or_team=robot or team,
250-
no_resolve=no_resolve,
251+
ignore_image_version=ignore_image_version,
251252
) as ssh:
252253
self._ensure_requirements(
253254
project,
254-
project_path,
255-
main_file,
255+
installer,
256256
ssh,
257-
ignore_image_version,
258257
no_install,
259258
force_install,
260259
no_uninstall,
@@ -353,20 +352,15 @@ def _get_robot_packages(
353352
return self._robot_packages
354353

355354
def _clear_pip_packages(self, installer: RobotpyInstaller):
356-
rio_packages = self._get_robot_packages(installer.ssh)
357-
to_uninstall = [p for p in rio_packages.keys() if p != "pip"]
358-
if to_uninstall:
359-
installer.pip_uninstall(to_uninstall)
360-
355+
installer.uninstall_venv()
361356
self._packages_in_cache = None
357+
self._robot_packages = None
362358

363359
def _ensure_requirements(
364360
self,
365361
project: typing.Optional[pyproject.RobotPyProjectToml],
366-
project_path: pathlib.Path,
367-
main_file: pathlib.Path,
362+
installer: RobotpyInstaller,
368363
ssh: sshcontroller.SshController,
369-
ignore_image_version: bool,
370364
no_install: bool,
371365
force_install: bool,
372366
no_uninstall: bool,
@@ -375,23 +369,20 @@ def _ensure_requirements(
375369
python_invalid: typing.Union[bool, str] = False
376370
requirements_installed = False
377371

378-
installer = RobotpyInstaller()
379-
380372
# does c++/java exist
381373
with wrap_ssh_error("removing c++/java user programs"):
382374
cpp_java_exists = not robot_utils.uninstall_cpp_java(ssh)
383375

384376
# does python exist
385-
with wrap_ssh_error("checking if python exists"):
386-
python_exists = (
387-
ssh.exec_cmd("[ -x /usr/local/bin/python3 ]").returncode == 0
388-
)
377+
with wrap_ssh_error("checking if python was installed"):
378+
python_exists = installer.is_python_installed()
389379
if not python_exists:
390380
logger.warning("Python is not installed on SystemCore")
391381

392382
if python_exists:
383+
393384
with wrap_ssh_error("getting python version"):
394-
python_version = robot_utils.get_python3_version(ssh)
385+
python_version = installer.get_python_version()
395386

396387
if python_version != required_pyversion:
397388
python_exists = False
@@ -401,14 +392,14 @@ def _ensure_requirements(
401392

402393
if no_install:
403394
raise Error(
404-
f"Unsupported version of python ({m}.{mn}) was found on the SystemCore\n"
395+
f"Unsupported version of python ({m}.{mn}) was found on the robot\n"
405396
"- could not update it because no-install was specified\n"
406397
)
407398

408399
# Warn the user before changing their rio
409400
print(
410401
"\n"
411-
f"Deployer has detected that the version of Python installed on the SystemCore ({m}.{mn})\n"
402+
f"Deployer has detected that the version of Python installed on the robot ({m}.{mn})\n"
412403
"is not supported by this installer. The installer will now uninstall that\n"
413404
f"and install Python {rm}.{rmn}.\n"
414405
)
@@ -422,7 +413,7 @@ def _ensure_requirements(
422413
elif not force_install:
423414
pkgdata = self._get_robot_packages(ssh)
424415

425-
logger.debug("SystemCore has these packages installed:")
416+
logger.debug("Robot has these packages installed:")
426417
for pkg, version in pkgdata.items():
427418
logger.debug("- %s (%s)", pkg, version[0])
428419

@@ -435,7 +426,7 @@ def _ensure_requirements(
435426
),
436427
)
437428
if not requirements_installed:
438-
logger.warning("Project requirements not installed on SystemCore")
429+
logger.warning("Project requirements not installed on robot")
439430
for msg in desc:
440431
logger.warning("- %s", msg)
441432
else:
@@ -452,17 +443,17 @@ def _ensure_requirements(
452443
# before changing their rio
453444
print(
454445
"\n"
455-
"Deployer has detected that the packages installed on your SystemCore do not match\n"
446+
"Deployer has detected that the packages installed on your robot do not match\n"
456447
"the requirements in pyproject.toml. The installer will now:\n"
457448
)
458449
if not no_uninstall:
459450
prompt = "Continue with uninstall + install?"
460-
print("* Uninstall ALL Python packages from the SystemCore")
451+
print("* Uninstall ALL Python packages from the robot")
461452
else:
462453
prompt = "Continue with install?"
463454

464455
print(
465-
"* Install required packages on the SystemCore\n"
456+
"* Install required packages on the robot\n"
466457
"\n"
467458
"If you do not wish to do this, specify --no-install as a deploy argument, or answer 'n'.\n"
468459
)
@@ -478,93 +469,73 @@ def _ensure_requirements(
478469
):
479470
if no_install and not python_exists:
480471
raise Error(
481-
"python3 was not found on the SystemCore\n"
472+
"python3 was not found on the robot\n"
482473
"- could not install it because no-install was specified\n"
483474
"- Use 'python -m robotpy installer install-python' to install python separately"
484475
)
485476

486-
# This also will give more memory
487-
ssh.exec_bash(
488-
". /etc/profile.d/frc-path.sh",
489-
". /etc/profile.d/natinst-path.sh",
490-
robot_utils.kill_robot_cmd,
491-
)
477+
ssh.exec_bash(robot_utils.kill_robot_cmd)
492478

493-
with installer.connect_to_robot(
494-
project_path=project_path,
495-
main_file=main_file,
496-
ignore_image_version=ignore_image_version,
497-
ssh=ssh,
498-
):
499-
if not kill_script_updated:
500-
robot_utils.update_kill_script(installer.ssh)
501-
502-
if cpp_java_exists:
503-
robot_utils.uninstall_cpp_java_admin(installer.ssh)
504-
505-
if python_invalid:
506-
with wrap_ssh_error("uninstalling python"):
507-
self._clear_pip_packages(installer)
508-
logger.info("Uninstalling %s from SystemCore", python_invalid)
509-
installer.ssh.exec_cmd(
510-
f"opkg remove {python_invalid}",
511-
check=True,
512-
print_output=True,
513-
)
514-
515-
if not python_exists:
516-
try:
517-
installer.install_python()
518-
except PythonMissingError as e:
519-
raise PythonMissingError(
520-
f"{e}\n\n"
521-
"Run 'python -m robotpy sync' to download your project requirements from the internet (or --no-install to ignore)"
522-
) from e
479+
if python_invalid:
480+
with wrap_ssh_error("uninstalling python"):
481+
self._clear_pip_packages(installer)
482+
logger.info("Uninstalling %s from robot", python_invalid)
483+
installer.uninstall_python()
484+
python_exists = False
523485

524-
if not requirements_installed:
525-
assert project is not None
526-
packages = project.get_install_list()
527-
528-
# Check if everything is in the cache before doing the install
529-
cached = self._get_cached_packages(installer)
530-
ok, missing = project.are_requirements_met(
531-
cached,
532-
pypackages.robot_env(),
533-
pypackages.make_cache_extra_resolver(cached),
486+
if not python_exists:
487+
try:
488+
installer.install_python()
489+
except PythonMissingError as e:
490+
raise PythonMissingError(
491+
f"{e}\n\n"
492+
"Run 'python -m robotpy sync' to download your project requirements from the internet (or --no-install to ignore)"
493+
) from e
494+
495+
if not requirements_installed:
496+
assert project is not None
497+
packages = project.get_install_list()
498+
499+
# Check if everything is in the cache before doing the install
500+
cached = self._get_cached_packages(installer)
501+
ok, missing = project.are_requirements_met(
502+
cached,
503+
pypackages.robot_env(),
504+
pypackages.make_cache_extra_resolver(cached),
505+
)
506+
if not ok:
507+
errmsg = ["Project requirements not found in download cache!"]
508+
errmsg.extend([f"- {msg}" for msg in missing])
509+
errmsg += [
510+
"",
511+
"Run 'python -m robotpy sync' to download your project requirements",
512+
"from the internet (or specify --no-install to not attempt installation).",
513+
]
514+
raise Error("\n".join(errmsg))
515+
516+
if not no_uninstall:
517+
logger.info(
518+
"Clearing existing packages on robot before install (specify --no-uninstall to not do this)"
534519
)
535-
if not ok:
536-
errmsg = ["Project requirements not found in download cache!"]
537-
errmsg.extend([f"- {msg}" for msg in missing])
538-
errmsg += [
539-
"",
540-
"Run 'python -m robotpy sync' to download your project requirements",
541-
"from the internet (or specify --no-install to not attempt installation).",
542-
]
543-
raise Error("\n".join(errmsg))
544-
545-
if not no_uninstall:
546-
logger.info(
547-
"Clearing existing packages on SystemCore before install (specify --no-uninstall to not do this)"
548-
)
549-
# The user may have deleted something from the project
550-
# requirements so the only way to ensure the exact
551-
# environment is to first clear the environment.
552-
# - can't do a partial uninstall without completely
553-
# resolving everything
554-
self._clear_pip_packages(installer)
555-
556-
logger.info("Installing project requirements on SystemCore:")
557-
for package in packages:
558-
logger.info("- %s", package)
559-
560-
try:
561-
installer.pip_install(False, False, False, False, [], packages)
562-
except PipInstallError as e:
563-
raise PipInstallError(
564-
f"{e}\n\n"
565-
"If 'no matching distribution found', run 'python -m robotpy sync' to download your\n"
566-
"project requirements from the internet (or --no-install to ignore)."
567-
) from e
520+
# The user may have deleted something from the project
521+
# requirements so the only way to ensure the exact
522+
# environment is to first clear the environment.
523+
# - can't do a partial uninstall without completely
524+
# resolving everything
525+
self._clear_pip_packages(installer)
526+
527+
logger.info("Installing project requirements on robot:")
528+
for package in packages:
529+
logger.info("- %s", package)
530+
531+
try:
532+
installer.pip_install(False, False, False, False, [], packages)
533+
except PipInstallError as e:
534+
raise PipInstallError(
535+
f"{e}\n\n"
536+
"If 'no matching distribution found', run 'python -m robotpy sync' to download your\n"
537+
"project requirements from the internet (or --no-install to ignore)."
538+
) from e
568539

569540
def _do_deploy(
570541
self,
@@ -580,12 +551,7 @@ def _do_deploy(
580551
# GradleRIO kills the robot before deploying it, so we do that too
581552
logger.info("Killing robot program")
582553
with wrap_ssh_error("killing robot program"):
583-
ssh.exec_bash(
584-
". /etc/profile.d/frc-path.sh",
585-
". /etc/profile.d/natinst-path.sh",
586-
"/usr/local/frc/bin/frcKillRobot.sh -t",
587-
check=False,
588-
)
554+
ssh.exec_bash(robot_utils.kill_robot_cmd, check=False)
589555

590556
deploy_dir = pathlib.PurePosixPath("/home/systemcore")
591557
py_deploy_subdir = "py"
@@ -599,18 +565,12 @@ def _do_deploy(
599565

600566
if debug:
601567
compileall_flags = ""
602-
deployed_cmd = (
603-
"env LD_LIBRARY_PATH=/usr/local/frc/lib/ "
604-
f"/usr/local/bin/python3 -u -m robotpy --main {py_deploy_dir}/{robot_filename} -v run"
605-
)
568+
deployed_cmd = f"{_ROBOT_VENV_PYTHON} -u -m robotpy --main {py_deploy_dir}/{robot_filename} -v run"
606569
deployed_cmd_fname = "robotDebugCommand"
607570
bash_cmd = "/bin/bash -cex"
608571
else:
609572
compileall_flags = "-O"
610-
deployed_cmd = (
611-
"env LD_LIBRARY_PATH=/usr/local/frc/lib/ "
612-
f"/usr/local/bin/python3 -u -O -m robotpy --main {py_deploy_dir}/{robot_filename} run"
613-
)
573+
deployed_cmd = f"{_ROBOT_VENV_PYTHON} -u -O -m robotpy --main {py_deploy_dir}/{robot_filename} run"
614574
deployed_cmd_fname = "robotCommand"
615575
bash_cmd = "/bin/bash -ce"
616576

@@ -622,6 +582,8 @@ def _do_deploy(
622582
f'echo "{deployed_cmd}" > {deploy_dir}/{deployed_cmd_fname}', check=True
623583
)
624584

585+
ssh.exec_cmd(f"chmod +x {robot_utils.robot_command}", check=True)
586+
625587
if debug:
626588
with wrap_ssh_error("touching frcDebug"):
627589
ssh.exec_cmd("touch /tmp/frcdebug", check=True)
@@ -658,12 +620,10 @@ def _do_deploy(
658620
sshcmd = (
659621
f"{bash_cmd} '"
660622
f"{replace_cmd};"
661-
f"/usr/local/bin/python3 {compileall_flags} -m compileall -q -r 5 /home/systemcore/py;"
662-
". /etc/profile.d/frc-path.sh; "
663-
". /etc/profile.d/natinst-path.sh; "
664-
f"chown -R lvuser:ni {py_deploy_dir}; "
665-
"sync; "
666-
"/usr/local/frc/bin/frcKillRobot.sh -t -r || true"
623+
f"{_ROBOT_VENV_PYTHON} {compileall_flags} -m compileall -q -r 5 /home/systemcore/py;"
624+
"sudo sync; "
625+
"sudo systemctl enable robot;"
626+
"sudo systemctl start robot;"
667627
"'"
668628
)
669629

robotpy_installer/cli_undeploy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def run(
7979
ssh.exec_cmd("rm -rf /home/systemcore/py")
8080

8181
# for good measure, delete the start command too
82-
ssh.exec_cmd("rm -f /home/systemcore/robotCommand")
82+
ssh.exec_cmd(f"rm -f {robot_utils.robot_command}")
8383

8484
except sshcontroller.SshExecError as e:
8585
print_err("ERROR:", str(e))

0 commit comments

Comments
 (0)