[BE] Add files field to the snippet create API endpoint

We need to add a new param files to the snippet (both project and personal ones) create API endpoint. In the future, this param will hold the array of files that we want to create inside the snippet.

But there is a problem. We don't want to break backward compatibility, therefore, we have to still maintain the old file_name and content fields. Hence, we have to play a little bit with the snippet definition to allow users to send file_name and content or snippet_files. My proposal would be:

  1. Make file_name and content optional because the user might use the param files instead.
  2. Define files as:
optional :files, type: Array do
  # Note that I chose `file_path` for the param name. This is because we can
  # use it directly in the multi_commit action in the service without translation
  requires :file_path, type: String, desc: 'The path of a snippet file'  
  requires :content, type: String, desc: 'The content of a snippet'
end
  1. Make files and content mutually exclusive
mutually_exclusive :files, :content
  1. Make file_name and content dependent from each other
optional :content, type: String, desc: 'The content of a snippet'
given :content do
  requires :file_name, type: String, desc: 'The name of a snippet file'
end

The final definition would be something like:

params do
  requires :title, type: String, desc: 'The title of a snippet'
  optional :file_name, type: String, desc: 'The name of a snippet file'  
  given :file_name do
    requires :content, type: String
  end
  optional :content, type: String, desc: 'The content of a snippet'
  given :content do
    requires :file_name, type: String
  end
  optional :description, type: String, desc: 'The description of a snippet'
  optional :visibility, type: String,
                        values: Gitlab::VisibilityLevel.string_values,
                        default: 'internal',
                        desc: 'The visibility of the snippet'
  optional :files, type: Array, as: :snippet_files do
    requires :file_path, type: String, desc: 'The path of a snippet file'  
    requires :content, type: String, desc: 'The content of a snippet'
  end
  mutually_exclusive :files, :content # To avoid having both params
  exactly_one_of :files, :content # To at least have one of both params
end

Disclaimer: I haven't tested this and there might be some easier definition, this was a quick guess

Since, in the end, we will have either files (as snippet_files) or file_name and content, we can pass either of both options to the Snippets::CreateService.

We need to add also a deprecation notice in the desc attribute for the file_name and content arguments. The intention is to remove them in the future (14.0) and use files only.

Edited by Francisco Javier López