Iterative Module Development
Once you have created the first version of your module, you can use the procedure outlined on this page to iterate on your design, and test changes quickly.
Generally, when developing a module, you have two options for iterative development, depending on the specific platform you want your module to support:
- Test Locally: If you want your module to support the same platform as your development workstation, you can test your module locally.
For example, if you are developing a module on a macOS computer with an M2 processor (the
arm64
architecture), and want your module to support only macOS computers running thearm64
architecture, you can perform your module development and testing workflow entirely on your macOS workstation. - Sync Code and Test Remotely: If you want your module to support a different architecture than your development workstation, you can sync your module code to a machine running your desired target architecture and test remotely.
For example, if you are developing a module on a macOS computer, but want your module to support a Raspberry Pi running Linux on the
arm64
architecture, you can set up syncing for your module code to be able to continue development on your macOS workstation, but test on your remote Raspberry Pi.
Both of these options involve deploying your module to the target test system as a local module, without uploading it to the Viam Registry. Even if you have already published a version of your module to the registry, you might still find it useful to follow the steps in this section to verify that changes you make as part of releasing a new version work as expected on your target platform.
Then, once you have tested it, you can upload your module to the Viam Registry. You can use prerelease versioning to publish a version of your module to the registry without affecting machines that are using stable versions of your module.
If you are developing a module for the same target architecture as your development workstation, you can test your module locally using the following procedure:
Navigate to the Viam app and add a new machine to serve as your development machine. Be sure to follow the steps shown in the Viam app to install
viam-server
on your local machine.If you are using a programming language that requires that you build your module, such as Go or C++, follow the instructions for your language to compile or package your module. If you are using a programming language that does not require compilation, such as Python, you can skip this step.
Navigate to the Viam app, select your machine, and add your module as a local module to your machine. For the Executable path field, enter the absolute path on your machine’s filesystem to either:
- the module’s executable file, such as
run.sh
or a compiled binary. - a packaged tarball of your module, ending in
.tar.gz
or.tgz
. If you are providing a tarball file in this field, be sure that your packaged tarball contains your module’smeta.json
file within it.
If you have previously added your module as a registry module, you will need to first remove the registry version of your module before then adding the local version.
- the module’s executable file, such as
Click the Save button in the top right corner of the page.
Check the LOGS tab for your machine in the Viam app to ensure that
viam-server
properly started your module. For example, the following log message indicates thatviam-server
was able to find and start the local module namedmy-module
successfully:1/16/24, 4:44:25.085 PM info robot_server modmanager/manager.go:862 registering component from module module my-module API rdk:component:base model acme:demo:mybase
Make your desired code changes to your module using your favorite editor. Save your changes.
If applicable (for example, using Go or C++), compile or package your module again. Otherwise (for example, using Python), skip this step.
Restart
viam-server
on your machine in order for it to pick up the code changes to your module, using your system’s service management command. For example:On macOS, using
brew
:brew services restart viam-server
On Linux, using
systemctl
:sudo systemctl restart viam-server
Once
viam-server
has restarted, check the LOGS tab for your machine in the Viam app again to ensure thatviam-server
properly started your module.Then test your module to verify that your code changes work as expected.
Repeat steps 6 - 10 to continue developing your module, as needed. Remember to check the LOGS tab each time to verify that the module registered successfully, and to troubleshoot any error or warning messages. If you haven’t already, you can add custom log messages to your code, which appear under the LOGS tab to assist with troubleshooting.
If you are developing a module for a different target architecture than your development workstation, you can sync your module code and test your module remotely using the following procedure:
Navigate to the Viam app and add a new machine to serve as your development machine. Be sure to follow the steps shown in the Viam app to install
viam-server
on the target machine you want to test and build on. For example, to test and build your module on your Raspberry Pi, be sure to installviam-server
on the Pi itself, not your macOS workstation.Set up file sync between your development workstation and the machine running your target platform that you want to build and test on, using your favorite file sync utility. For example, you could use mutagen.io to sync your files using the following steps:
Install Mutagen on your development workstation, following the instructions for your operating system:
To install Mutagen on macOS:
brew install mutagen-io/mutagen/mutagen
To install Mutagen on Linux, download the latest release from GitHub. Mutagen is not currently available for Linux through package managers.
If you haven’t already, ensure that your target test system is up and running, and accessible to
ssh
. Mutagen usesssh
to sync files between your systems in an unattended manner (that is, without user input), and so requires that you set up a validssh
key for it to use to authenticate during syncs. If you already have anssh
keypair configured to your remote testing system, you can skip this step and proceed to step 3. Follow the steps below to create a newssh
key to use, and copy it to your remote testing system:Create a new
ssh
key on your development workstation, meeting your security requirements. For example, on a macOS machine, you can generate anssh
key using theed25519
algorithm with a key size of4096
bits using the following command:ssh-keygen -t ed25519 -b 4096 -C "developer@example.com"
When prompted to select a file location, press enter to accept the default location.
This command will generate a new key in your
~/.ssh/
directory. If you already have anssh
key in that directory with the same name, you will be prompted to overwrite your existing key: typen
(for “no”) to cancel. You can use your existing key in the next steps.Verify that you have both parts of the
ssh
keypair present as follows:ls -l ~/.ssh/id_ed25519*
For example, on macOS, you should see files similar to
/Users/username/.ssh/id_ed25519
and/Users/username/.ssh/id_ed25519.pub
.Copy the
.pub
file only to your target remote system using thessh-copy-id
command. For example, to transfer aid_ed25519.pub
file from a macOS machine to a remote Linux system namedmy-pi.local
for the userusername
, you could use the following commands:ssh-copy-id -i ~/.ssh/id_ed25519.pub username@my-pi.local
Provide the
ssh
password for your user account when prompted. Do not copy the private key file, which does not have a file extension.
Then, start a new
ssh
session to your remote system, and verify that you are able to connect without being prompted for a password. Mutagen requires a working, passwordlessssh
configuration in order to be able to sync files. If you receive aconnection refused
error, or are still prompted for a password, see the Troubleshootingssh
section for further guidance.
Return to your local development system, and navigate to your module’s directory. For example, if you are developing a module named
my-module
in the home directory:cd ~/my-module
Set up a new Mutagen sync from this directory to sync to your remote system, providing the local path to your module and the target path on the remote system to sync your module files:
mutagen sync create /path/to/local/module username@remote-hostname.local:/path/to/remote/sync-target
For example, you could use the following to transfer the example module from earlier to the same location on the remote system, if desired:
mutagen sync create ~/my-module username@my-pi.local:/home/username/my-module
In an
ssh
session to your remote system, ensure that you now see the synced files appear as expected in the filesystem location you chose to sync to. If the files haven’t appeared, consult the Mutagen documentation for further troubleshooting.Return to your local development system, and navigate back to your module directory.
If you are using a programming language that requires that you build your module, such as Go or C++, follow the instructions for your language to compile or package your module. If you are using a programming language that does not require compilation, such as Python, you can skip this step.
Navigate to the Viam app, select your machine, and add your module as a local module to your machine. Provide the Executable path in the configuration, pointing to the compiled or built binary, or the executable script, depending on your language. Provide the remote system’s path to this file, for example:
/home/username/my-module/run.sh . With the Mutagen sync in place, Mutagen transfers the binary or executable automatically when you created it in the previous step. If you have previously added your module as a registry module, you will need to first remove the registry version of your module before then adding the local version.Click the Save button in the top right corner of the page.
Check the LOGS tab for your machine in the Viam app to ensure that
viam-server
properly started your module. For example, the following log message indicates thatviam-server
was able to find and start the local module namedmy-module
successfully:1/16/24, 4:44:25.085 PM info robot_server modmanager/manager.go:862 registering component from module module my-module API rdk:component:base model acme:demo:mybase
Make your desired code changes to your module using your favorite editor. Save your changes.
If applicable (for example, using Go or C++), compile or package your module again. Otherwise (for example, using Python), skip this step.
Restart
viam-server
on your remote system in order for it to pick up the code changes to your module, using your system’s service management command. For example, on Linux usingsystemctl
:sudo systemctl restart viam-server
Once
viam-server
has restarted, check the LOGS tab for your machine in the Viam app again to ensure thatviam-server
properly started your module.Then test your module to verify that your code changes work as expected.
Repeat steps 11 - 15 to continue developing your module, as needed. Remember to check the LOGS tab each time to verify that the module registered successfully, and to troubleshoot any error or warning messages. If you haven’t already, you can add custom log messages to your code, which appear under the LOGS tab to assist with troubleshooting.
When you are satisfied that your module is ready for release, follow the steps to upload your module to the Viam Registry, to facilitate streamlined deployment to other machines or to make it available to the Viam community.
Troubleshooting ssh
Connection refused
If you receive connection refused
or similar messages when attempting to connect to the remote system using your ssh
key, ensure the permissions of the key are correct:
Start an
ssh
session to your remote system using your password.Make sure that the public key you created with
ssh-keygen
and copied withssh-copy-id
has the correct file permissions on the remote filesystem:ls -l ~/.ssh/id_ed25519.pub
If the permissions shown are not exactly
-rw-r--r--
, use the following command to set them appropriately:chmod 644 ~/.ssh/id_ed25519.pub
Then test your ssh
connection once more to ensure that you are connected without being prompted for a password.
Prompted for ssh
account password
If you are able to ssh
to the remote system, but are still prompted for your password each time you attempt to connect with a message similar to username@amy-pi.local's password:
, check your remote system’s sshd
configuration:
Start an
ssh
session to your remote system using your password.Make sure that the
sshd
configuration for your remote system includes the following settings:PubkeyAuthentication yes
For example, on Ubuntu, you can check your
sshd
configuration with the following command:grep -i pubkey /etc/ssh/sshd_config
- If this value is set to
no
, change this value toyes
. - If this value is prepended by
#
character, remove it so that the line reads exactly:PubkeyAuthentication yes
.
- If this value is set to
If you needed to change this value in either way listed, restart the
sshd
service from yourssh
session to your remote system. For example, if your remote system is Linux, you would run the following on the remote system:sudo systemctl restart sshd
Note that restarting the
sshd
service in this manner will disconnect your currentssh
session to the remote system. For more information on thesshd
service and related service management, please consult the documentation for your specific operating system.
Then test your ssh
connection once more to ensure that you are connected without being prompted for a password.
Prompted for ssh
key passphrase
If you are prompted with a message similar to Enter passphrase for key '/Users/username/.ssh/id_ed25519'
, add your ssh
key passphrase to your local macOS keychain:
For macOS 12.0 or later, run the following on your local macOS system:
ssh-add --apple-use-keychain ~/.ssh/id_ed25519
For macOS 11.0 or previous, run the following on your local macOS system:
ssh-add -K ~/.ssh/id_ed25519
Then test your ssh
connection once more to ensure that you are connected without being prompted for a password.
Use prerelease versioning
To publish a module version that is not yet fully tested, you can publish it as a prerelease (also called “release candidate”) version of a module to the modular registry. Publishing a prerelease version will not affect any machines that are using the existing module. Regardless of the machine’s version pinning setting, only machines that are set to the exact prerelease version will be updated.
For example, imagine your latest stable version is 0.1.2
.
If you publish a prerelease version tagged 0.1.2-rc0
, all machines continue to use version 0.1.2
.
Similarly, if you publish a prerelease version tagged 0.1.3-rc0
, all machines will stay on version 0.1.2
.
If you pin a machine to the exact version number 0.1.3-rc0
, only then will that machine use the prerelease version.
Syntax
Your tags should adhere to semantic versioning specification (SemVer), meaning that the tag should begin with a major version number, then a minor version number, then a patch version number, separated by periods.
It is up to you as the developer to choose when to increment each number.
You can append any label after the major, minor, and patch version numbers.
For example, you can label your prerelease version 0.1.2-rc0
or 0.1.2-beta
.
If your tag does not adhere to SemVer, cloud builds will fail.
Update your GitHub action file
If you are using Cloud Build, be sure to update your GitHub action file tags to include the release candidate version.
You can use "*"
to trigger the build action on all tags regardless of correct syntax, or you can use the following regular expression to trigger the build action on all tags that have valid syntax:
/^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/gm
Have questions, or want to meet other people working on robots? Join our Community Discord.
If you notice any issues with the documentation, feel free to file an issue or edit this file.
Was this page helpful?
Glad to hear it! If you have any other feedback please let us know:
We're sorry about that. To help us improve, please tell us what we can do better:
Thank you!