Commit 22a7e20d authored by Steve Abrams's avatar Steve Abrams Committed by Mayra Cabrera

Param requires_python is optional for pypi

Make the requires_python optional for the pypi
upload endpoint to conform with pypi standards.

Changelog: fixed
parent ab64d740
...@@ -6,7 +6,7 @@ class Packages::Pypi::Metadatum < ApplicationRecord ...@@ -6,7 +6,7 @@ class Packages::Pypi::Metadatum < ApplicationRecord
belongs_to :package, -> { where(package_type: :pypi) }, inverse_of: :pypi_metadatum belongs_to :package, -> { where(package_type: :pypi) }, inverse_of: :pypi_metadatum
validates :package, presence: true validates :package, presence: true
validates :required_python, length: { maximum: 255 }, allow_blank: true validates :required_python, length: { maximum: 255 }, allow_nil: false
validate :pypi_package_type validate :pypi_package_type
......
...@@ -9,7 +9,7 @@ module Packages ...@@ -9,7 +9,7 @@ module Packages
::Packages::Package.transaction do ::Packages::Package.transaction do
meta = Packages::Pypi::Metadatum.new( meta = Packages::Pypi::Metadatum.new(
package: created_package, package: created_package,
required_python: params[:requires_python] required_python: params[:requires_python] || ''
) )
unless meta.valid? unless meta.valid?
......
# frozen_string_literal: true
class AddDefaultToRequiredPythonOnPackagesPypiMetadata < Gitlab::Database::Migration[1.0]
def up
change_column_default(:packages_pypi_metadata, :required_python, '')
end
def down
change_column_default(:packages_pypi_metadata, :required_python, nil)
end
end
483f8299688a6e24fa77867b7dab8a2dad0c2b7ebe43c56c81c02ab1e0dc4674
\ No newline at end of file
...@@ -18322,7 +18322,7 @@ ALTER SEQUENCE packages_packages_id_seq OWNED BY packages_packages.id; ...@@ -18322,7 +18322,7 @@ ALTER SEQUENCE packages_packages_id_seq OWNED BY packages_packages.id;
CREATE TABLE packages_pypi_metadata ( CREATE TABLE packages_pypi_metadata (
package_id bigint NOT NULL, package_id bigint NOT NULL,
required_python text, required_python text DEFAULT ''::text,
CONSTRAINT check_0d9aed55b2 CHECK ((required_python IS NOT NULL)), CONSTRAINT check_0d9aed55b2 CHECK ((required_python IS NOT NULL)),
CONSTRAINT check_379019d5da CHECK ((char_length(required_python) <= 255)) CONSTRAINT check_379019d5da CHECK ((char_length(required_python) <= 255))
); );
...@@ -175,6 +175,7 @@ PUT projects/:id/packages/pypi ...@@ -175,6 +175,7 @@ PUT projects/:id/packages/pypi
| Attribute | Type | Required | Description | | Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- | | --------- | ---- | -------- | ----------- |
| `id` | string | yes | The ID or full path of the project. | | `id` | string | yes | The ID or full path of the project. |
| `requires_python` | string | no | The PyPI required version. |
```shell ```shell
curl --request PUT \ curl --request PUT \
......
...@@ -170,9 +170,9 @@ module API ...@@ -170,9 +170,9 @@ module API
params do params do
requires :content, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)' requires :content, type: ::API::Validations::Types::WorkhorseFile, desc: 'The package file to be published (generated by Multipart middleware)'
requires :requires_python, type: String
requires :name, type: String requires :name, type: String
requires :version, type: String requires :version, type: String
optional :requires_python, type: String
optional :md5_digest, type: String optional :md5_digest, type: String
optional :sha256_digest, type: String optional :sha256_digest, type: String
end end
......
...@@ -8,6 +8,9 @@ RSpec.describe Packages::Pypi::Metadatum, type: :model do ...@@ -8,6 +8,9 @@ RSpec.describe Packages::Pypi::Metadatum, type: :model do
describe 'validations' do describe 'validations' do
it { is_expected.to validate_presence_of(:package) } it { is_expected.to validate_presence_of(:package) }
it { is_expected.to allow_value('').for(:required_python) }
it { is_expected.not_to allow_value(nil).for(:required_python) }
it { is_expected.not_to allow_value('a' * 256).for(:required_python) }
describe '#pypi_package_type' do describe '#pypi_package_type' do
it 'will not allow a package with a different package_type' do it 'will not allow a package with a different package_type' do
......
...@@ -185,6 +185,14 @@ RSpec.describe API::PypiPackages do ...@@ -185,6 +185,14 @@ RSpec.describe API::PypiPackages do
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member] it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end end
context 'without requires_python' do
let(:token) { personal_access_token.token }
let(:user_headers) { basic_auth_header(user.username, token) }
let(:headers) { user_headers.merge(workhorse_headers) }
it_behaves_like 'PyPI package creation', :developer, :created, true
end
end end
context 'with required_python too big' do context 'with required_python too big' do
......
# frozen_string_literal: true # frozen_string_literal: true
require 'spec_helper' require 'spec_helper'
RSpec.describe Packages::Pypi::CreatePackageService do RSpec.describe Packages::Pypi::CreatePackageService, :aggregate_failures do
include PackagesManagerApiSpecHelpers include PackagesManagerApiSpecHelpers
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
...@@ -39,6 +39,18 @@ RSpec.describe Packages::Pypi::CreatePackageService do ...@@ -39,6 +39,18 @@ RSpec.describe Packages::Pypi::CreatePackageService do
end end
end end
context 'without required_python' do
before do
params.delete(:requires_python)
end
it 'creates the package' do
expect { subject }.to change { Packages::Package.pypi.count }.by(1)
expect(created_package.pypi_metadatum.required_python).to eq ''
end
end
context 'with an invalid metadata' do context 'with an invalid metadata' do
let(:requires_python) { 'x' * 256 } let(:requires_python) { 'x' * 256 }
...@@ -73,7 +85,7 @@ RSpec.describe Packages::Pypi::CreatePackageService do ...@@ -73,7 +85,7 @@ RSpec.describe Packages::Pypi::CreatePackageService do
.and raise_error(/File name has already been taken/) .and raise_error(/File name has already been taken/)
end end
context 'with a pending_destruction package', :aggregate_failures do context 'with a pending_destruction package' do
before do before do
Packages::Package.pypi.last.pending_destruction! Packages::Package.pypi.last.pending_destruction!
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment