Skip to content

Support blank values in Conan packages for username and channel

👾 Context

The Conan Repository is used by users to host their Conan packages.

Conan packages have fields that are used to locate a package. Think of them as coordinates:

  1. name
  2. version
  3. user
  4. channel

The first two are the usual suspects in the Package Registry. The other two are specific for Conan packages. As such, they are stored in an extra table that holds additional information about the package (packages_conan_metadata)

$ conan interacts with the GitLab Packages Registry using a http API. During the implementation of that API, some validations around the coordinates were put in place to require them and to have them in the proper format.

As described in #345055 (closed), the problem is that the user and the channel are actually optional. As such, users can choose to left them to a side and create a package with only the name and version set.

In the analysis, we can see that $ conan will actually send _ values for empty user and channel. I'm assuming that this is explained by the fact that those parameters are used in the API url itself. Eg. /api/v4/projects/83/packages/conan/v1/conans/Hello/0.1/_/_/digest. If we don't have a value for empty user/channel, we would end up with /api/v4/projects/83/packages/conan/v1/conans/Hello/0.1///digest and that's a good recipe to 💥

I'd like to point out to the validation run by $ conan (as found by the analysis): both fields have to be blank. We can't have a blank user with a channel set.

Last piece of context, the Conan Repository can be accessed at two levels:

  • the project level (all the API urls are prefixed by /api/v4/projects/<project_id>/packages/conan/)
  • the instance level (all the API urls are prefixed by /api/v4/packages/conan)

The instance level doesn't have any hint about which project the backend should operate on. For this, we have a naming convention. Basically, the user field must be the project path that we want to target. As such, the instance level can't support the _ values for user.

The problem above can be summarized to a validation problem: we need to accept the _ value for user and channel. This MR tries to solve it. Note that we will not try to convert _ to a nil or NULL value. This would bring way more changes (including database changes). A smaller iteration on this is to consider _ as a regular value. What _ means for $ conan is not really useful in the Package Registry.

🔬 What does this MR do and why?

  • Updates validations to accept _ values
    • This is done at two levels:
      • The metadata model
      • The grape API
  • Accepts only _ values for both fields
    • This is done at two levels:
      • The metadata model
      • The grape API
  • Updates the related specs
    • Please read the note about quarantined spec.
  • Updates the documentation
  • This is potentially a breaking change: we could render the upload API endpoint useless with this change. To mitigate this, we're going to use a feature flag.

📸 Screenshots or screen recordings

1️⃣ For a package with user and channel set

Imagine that we have a package Bananas/1.3.7 with user foobar and channel alpha.

Pushing:

using master using this MR (feature flag enabled) using this MR (feature flag disabled)
$ conan upload Bananas/1.3.7@foobar/alpha --all -r gitlab Works 🎉 Works 🎉 Works 🎉

Pulling:

From a folder with conanfile.txt:

[requires]
Bananas/1.3.7@foobar/alpha

[generators]
cmake
using master using this MR (feature flag enabled) using this MR (feature flag disabled)
$ conan install . -r gitlab Bananas/1.3.7@foobar/alpha: Package installed 6a83d7f783e7ee89a83cf2fe72b5f5f67538e2a6 🎉 Bananas/1.3.7@foobar/alpha: Package installed 6a83d7f783e7ee89a83cf2fe72b5f5f67538e2a6 Works 🎉 Bananas/1.3.7@foobar/alpha: Package installed 6a83d7f783e7ee89a83cf2fe72b5f5f67538e2a6 Works 🎉

2️⃣ For a package with user and channel not set

Imagine that we have a package Bananas/1.3.7 with no user and channel set.

Pushing:

using master using this MR (feature flag enabled) using this MR (feature flag disabled)
$ conan Bananas/1.3.7 --all -r gitlab ERROR: Bananas/1.3.7: Upload recipe to 'gitlab' failed: {"error":"package_username is invalid, package_channel is invalid"}. [Remote: gitlab] 💥 Works 🎉 ERROR: Bananas/1.3.7: Upload recipe to 'gitlab' failed: {"error":"package_username is invalid, package_channel is invalid"}. [Remote: gitlab] 💥

Pulling:

From a folder with conanfile.txt:

[requires]
Bananas/1.3.7

[generators]
cmake
using master using this MR (feature flag enabled) using this MR (feature flag disabled)
$ conan install . -r gitlab ERROR: {"error":"package_username is invalid, package_channel is invalid"}. [Remote: gitlab] 💥 Bananas/1.3.7: Package installed 6a83d7f783e7ee89a83cf2fe72b5f5f67538e2a6 Works 🎉 ERROR: {"error":"package_username is invalid, package_channel is invalid"}. [Remote: gitlab] 💥

The MR and the related feature flag are working properly

How to set up and validate locally

  1. Set up conan
  2. Create a package
  3. Add a remote
  4. Enabled the feature flag in a rails console (or not):
    Feature.enable(:packages_conan_allow_empty_username_channel)
  5. Push the package

$ conan will cache packages locally. If you try to push a package and pull it from the same machine, $ conan can decide to not pull the files from the GitLab Packages registry. To remove the cached versions of your package, use $ conan remove.

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by David Fernandez

Merge request reports