Request: Catkin plugin configurable PLUGIN_STAGE_SOURCES

I use aptly to freeze the ROS deb repositories and create more reproducible builds. However, I recently discovered that the catkin plugin ignores my sources.list (which is configured to use aptly) and pulls from the ROS repositories, hard coded in the PLUGIN_STAGE_SOURCES property.

Would it be possible to have the plugin respect the system sources.list? I’m assuming that’s how stage-packages or build-packages works and it would make sense for this to be consistent. If not, at least a way to disable or specify the sources would be nice.

I’m afraid not, as that would lead to a snap that could not be built in a clean environment (e.g. in CI). However, there is a way you can do this by providing your own custom Catkin plugin in the project in question. Create a snap/plugins directory within your project (alongside the snapcraft.yaml). Create a new file called snap/plugins/x-catkin.py. Make the contents of that file look something like this:

from snapcraft.plugins import catkin

class CustomCatkinPlugin(catkin.CatkinPlugin):

    @property
    def PLUGIN_STAGE_SOURCES(self):
        return """
deb http://${prefix}.ubuntu.com/${suffix}/ xenial main universe
deb http://${prefix}.ubuntu.com/${suffix}/ xenial-updates main universe
deb http://${prefix}.ubuntu.com/${suffix}/ xenial-security main universe
deb http://${security}.ubuntu.com/${suffix}/ xenial-security main universe
"""

That’s a minimum, I wouldn’t remove any of those repositories. However, you can add new lines there pointing to your own custom mirror. Then the rest of the behavior is inherited from the Catkin plugin and it works as normal. You use this custom Catkin plugin no differently: just specify plugin: catkin as usual, and Snapcraft will pick this one up instead of the built-in one.

As a side note, have you considered using rosinstall files to freeze things instead of an archive mirror?

Isn’t looking at sources.list exactly how the rest of snapcraft works? The following snap builds fine, so I’m assuming it got the ROS deb repositories from my system:

name: example
version: "0.0.0"
summary: example
description: example
confinement: strict

parts:
  example:
    plugin: nil
    build-packages: ['ros-kinetic-catkin']
    stage-packages: ['ros-kinetic-catkin']

Therefore, the CI could set it up as it would for any other custom repositories (ie, for Travis).

To my knowledge, a rosinstall file can only pull sources, and I don’t want to have to rebuild everything if it’s already been packaged into a deb.

Indeed, build-packages uses the sources.list, but using third-party sources there (PPAs etc.) isn’t something we support on purpose, and in fact discourage, for the same reason: it means your snap cannot be built just by running snapcraft, there’s some special setup that must happen first.

I see. Then what’s the recommended way of creating snaps that can be reproducibly built, regardless of whether the deb in a source has been updated? Ie, what is the recommended way to avoid using something like aptly?

That type of thing wasn’t possible with .deb’s since any dependencies also had to be present in the repos at install time, but the snap architecture unlocks it and it would be a nice thing to support.

To be clear, I’m not suggesting that you shouldn’t use aptly. I’m simply saying that the way to use it on the Snapcraft side is not via host modifications, but via the custom plugin that I provided earlier. That will give you a snapraft.yaml that can be built on a clean system.

Ok, I understand now. Thanks!