Commit af55ffd2 authored by Sofia Vistas's avatar Sofia Vistas Committed by Dan Davison

Use remove_via_api! for package resources

Prior to this change, there was no way
to remove the package from a given project
unless using the UI. This could cause a
test to fail and leave the package publish
to be deleted and accumulating space.

This change introduces the resource for Package,
focusing on implementing the deletion capability
via the API instead
parent da278bda
...@@ -96,6 +96,7 @@ module QA ...@@ -96,6 +96,7 @@ module QA
autoload :ProjectSnippet, 'qa/resource/project_snippet' autoload :ProjectSnippet, 'qa/resource/project_snippet'
autoload :Design, 'qa/resource/design' autoload :Design, 'qa/resource/design'
autoload :RegistryRepository, 'qa/resource/registry_repository' autoload :RegistryRepository, 'qa/resource/registry_repository'
autoload :Package, 'qa/resource/package'
module KubernetesCluster module KubernetesCluster
autoload :Base, 'qa/resource/kubernetes_cluster/base' autoload :Base, 'qa/resource/kubernetes_cluster/base'
......
# frozen_string_literal: true
require 'securerandom'
module QA
module Resource
class Package < Base
attr_accessor :name
attribute :project do
Project.fabricate_via_api! do |resource|
resource.name = 'project-with-package'
resource.description = 'Project with Package'
end
end
attribute :id do
packages = project.packages
return unless (this_package = packages&.find { |package| package[:name] == "#{project.path_with_namespace}/#{name}" }) # rubocop:disable Cop/AvoidReturnFromBlocks
this_package[:id]
end
def fabricate!
end
def fabricate_via_api!
resource_web_url(api_get)
rescue ResourceNotFoundError
super
end
def remove_via_api!
packages = project.packages
if packages && !packages.empty?
QA::Runtime::Logger.debug("Deleting package '#{name}' from '#{project.path_with_namespace}' via API")
super
end
end
def api_delete_path
"/projects/#{project.id}/packages/#{id}"
end
def api_get_path
"/projects/#{project.id}/packages"
end
end
end
end
...@@ -155,6 +155,10 @@ module QA ...@@ -155,6 +155,10 @@ module QA
"#{api_get_path}/registry/repositories" "#{api_get_path}/registry/repositories"
end end
def api_packages_path
"#{api_get_path}/packages"
end
def api_commits_path def api_commits_path
"#{api_get_path}/repository/commits" "#{api_get_path}/repository/commits"
end end
...@@ -262,7 +266,11 @@ module QA ...@@ -262,7 +266,11 @@ module QA
def registry_repositories def registry_repositories
response = get Runtime::API::Request.new(api_client, "#{api_registry_repositories_path}").url response = get Runtime::API::Request.new(api_client, "#{api_registry_repositories_path}").url
parse_body(response)
end
def packages
response = get Runtime::API::Request.new(api_client, "#{api_packages_path}").url
parse_body(response) parse_body(response)
end end
......
# frozen_string_literal: true # frozen_string_literal: true
require 'securerandom'
module QA module QA
RSpec.describe 'Package', :orchestrated, :packages do RSpec.describe 'Package', :orchestrated, :packages do
describe 'Composer Repository' do describe 'Composer Repository' do
include Runtime::Fixtures include Runtime::Fixtures
let(:package_name) { 'my_package' }
let(:project) do let(:project) do
Resource::Project.fabricate_via_api! do |project| Resource::Project.fabricate_via_api! do |project|
project.name = 'composer-package-project' project.name = 'composer-package-project'
end end
end end
let(:package) do
Resource::Package.new.tap do |package|
package.name = "my_package-#{SecureRandom.hex(4)}"
package.project = project
end
end
let!(:runner) do let!(:runner) do
Resource::Runner.fabricate! do |runner| Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}" runner.name = "qa-runner-#{Time.now.to_i}"
...@@ -30,7 +37,7 @@ module QA ...@@ -30,7 +37,7 @@ module QA
let(:composer_json_file) do let(:composer_json_file) do
<<~EOF <<~EOF
{ {
"name": "#{project.path_with_namespace}/#{package_name}", "name": "#{project.path_with_namespace}/#{package.name}",
"description": "Library XY", "description": "Library XY",
"type": "library", "type": "library",
"license": "GPL-3.0-only", "license": "GPL-3.0-only",
...@@ -94,14 +101,15 @@ module QA ...@@ -94,14 +101,15 @@ module QA
after do after do
runner.remove_via_api! runner.remove_via_api!
package.remove_via_api!
end end
it 'publishes a composer package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1088' do it 'publishes a composer package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1088' do
Page::Project::Menu.perform(&:click_packages_link) Page::Project::Menu.perform(&:click_packages_link)
Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package_name) expect(index).to have_package(package.name)
index.click_package(package_name) index.click_package(package.name)
end end
Page::Project::Packages::Show.perform(&:click_delete) Page::Project::Packages::Show.perform(&:click_delete)
...@@ -109,7 +117,7 @@ module QA ...@@ -109,7 +117,7 @@ module QA
Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
aggregate_failures 'package deletion' do aggregate_failures 'package deletion' do
expect(index).to have_content("Package deleted successfully") expect(index).to have_content("Package deleted successfully")
expect(index).not_to have_package(package_name) expect(index).not_to have_package(package.name)
end end
end end
end end
......
...@@ -5,14 +5,19 @@ module QA ...@@ -5,14 +5,19 @@ module QA
describe 'Conan Repository' do describe 'Conan Repository' do
include Runtime::Fixtures include Runtime::Fixtures
let(:package_name) { 'conantest' }
let(:project) do let(:project) do
Resource::Project.fabricate_via_api! do |project| Resource::Project.fabricate_via_api! do |project|
project.name = 'conan-package-project' project.name = 'conan-package-project'
end end
end end
let(:package) do
Resource::Package.new.tap do |package|
package.name = 'conantest'
package.project = project
end
end
let!(:runner) do let!(:runner) do
Resource::Runner.fabricate! do |runner| Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}" runner.name = "qa-runner-#{Time.now.to_i}"
...@@ -29,6 +34,7 @@ module QA ...@@ -29,6 +34,7 @@ module QA
after do after do
runner.remove_via_api! runner.remove_via_api!
package.remove_via_api!
end end
it 'publishes, installs, and deletes a Conan package', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1077' do it 'publishes, installs, and deletes a Conan package', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1077' do
...@@ -47,10 +53,10 @@ module QA ...@@ -47,10 +53,10 @@ module QA
stage: deploy stage: deploy
script: script:
- "conan remote add gitlab #{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/conan" - "conan remote add gitlab #{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/conan"
- "conan new #{package_name}/0.1 -t" - "conan new #{package.name}/0.1 -t"
- "conan create . mycompany/stable" - "conan create . mycompany/stable"
- "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package_name}/0.1@mycompany/stable --all --remote=gitlab" - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package.name}/0.1@mycompany/stable --all --remote=gitlab"
- "conan install conantest/0.1@mycompany/stable --remote=gitlab" - "conan install #{package.name}/0.1@mycompany/stable --remote=gitlab"
tags: tags:
- "runner-for-#{project.name}" - "runner-for-#{project.name}"
YAML YAML
...@@ -71,15 +77,15 @@ module QA ...@@ -71,15 +77,15 @@ module QA
Page::Project::Menu.perform(&:click_packages_link) Page::Project::Menu.perform(&:click_packages_link)
Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package_name) expect(index).to have_package(package.name)
index.click_package(package_name) index.click_package(package.name)
end end
Page::Project::Packages::Show.perform(&:click_delete) Page::Project::Packages::Show.perform(&:click_delete)
Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
expect(index).to have_content("Package deleted successfully") expect(index).to have_content("Package deleted successfully")
expect(index).not_to have_package(package_name) expect(index).not_to have_package(package.name)
end end
end end
end end
......
...@@ -3,14 +3,19 @@ ...@@ -3,14 +3,19 @@
module QA module QA
RSpec.describe 'Package', :orchestrated, :packages do RSpec.describe 'Package', :orchestrated, :packages do
describe 'Generic Repository' do describe 'Generic Repository' do
let(:package_name) { 'my_package' }
let(:project) do let(:project) do
Resource::Project.fabricate_via_api! do |project| Resource::Project.fabricate_via_api! do |project|
project.name = 'generic-package-project' project.name = 'generic-package-project'
end end
end end
let(:package) do
Resource::Package.new.tap do |package|
package.name = "my_package"
package.project = project
end
end
let!(:runner) do let!(:runner) do
Resource::Runner.fabricate! do |runner| Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}" runner.name = "qa-runner-#{Time.now.to_i}"
...@@ -90,14 +95,15 @@ module QA ...@@ -90,14 +95,15 @@ module QA
after do after do
runner.remove_via_api! runner.remove_via_api!
package.remove_via_api!
end end
it 'uploads a generic package, downloads and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1108' do it 'uploads a generic package, downloads and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1108' do
Page::Project::Menu.perform(&:click_packages_link) Page::Project::Menu.perform(&:click_packages_link)
Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package_name) expect(index).to have_package(package.name)
index.click_package(package_name) index.click_package(package.name)
end end
Page::Project::Packages::Show.perform(&:click_delete) Page::Project::Packages::Show.perform(&:click_delete)
...@@ -105,7 +111,7 @@ module QA ...@@ -105,7 +111,7 @@ module QA
Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
aggregate_failures 'package deletion' do aggregate_failures 'package deletion' do
expect(index).to have_content("Package deleted successfully") expect(index).to have_content("Package deleted successfully")
expect(index).to have_no_package(package_name) expect(index).to have_no_package(package.name)
end end
end end
end end
......
...@@ -23,6 +23,13 @@ module QA ...@@ -23,6 +23,13 @@ module QA
end end
end end
let(:package) do
Resource::Package.new.tap do |package|
package.name = package_name
package.project = project
end
end
let!(:runner) do let!(:runner) do
Resource::Runner.fabricate! do |runner| Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}" runner.name = "qa-runner-#{Time.now.to_i}"
...@@ -39,6 +46,7 @@ module QA ...@@ -39,6 +46,7 @@ module QA
after do after do
runner.remove_via_api! runner.remove_via_api!
package.remove_via_api!
end end
it 'publishes a maven package via gradle', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1074' do it 'publishes a maven package via gradle', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1074' do
......
...@@ -31,6 +31,13 @@ module QA ...@@ -31,6 +31,13 @@ module QA
end end
end end
let(:package) do
Resource::Package.new.tap do |package|
package.name = package_name
package.project = project
end
end
let!(:runner) do let!(:runner) do
Resource::Runner.fabricate! do |runner| Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}" runner.name = "qa-runner-#{Time.now.to_i}"
......
...@@ -5,8 +5,7 @@ module QA ...@@ -5,8 +5,7 @@ module QA
describe 'npm registry' do describe 'npm registry' do
include Runtime::Fixtures include Runtime::Fixtures
let(:registry_scope) { project.group.sandbox.path } let!(:registry_scope) { project.group.sandbox.path }
let(:package_name) { "@#{registry_scope}/#{project.name}" }
let(:auth_token) do let(:auth_token) do
unless Page::Main::Menu.perform(&:signed_in?) unless Page::Main::Menu.perform(&:signed_in?)
Flow::Login.sign_in Flow::Login.sign_in
...@@ -15,12 +14,23 @@ module QA ...@@ -15,12 +14,23 @@ module QA
Resource::PersonalAccessToken.fabricate!.token Resource::PersonalAccessToken.fabricate!.token
end end
let(:project) do let!(:project) do
Resource::Project.fabricate_via_api! do |project| Resource::Project.fabricate_via_api! do |project|
project.name = 'npm-registry-project' project.name = 'npm-registry-project'
end end
end end
let(:package) do
Resource::Package.new.tap do |package|
package.name = "@#{registry_scope}/#{project.name}"
package.project = project
end
end
after do
package.remove_via_api!
end
it 'publishes an npm package and then deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/944' do it 'publishes an npm package and then deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/944' do
uri = URI.parse(Runtime::Scenario.gitlab_address) uri = URI.parse(Runtime::Scenario.gitlab_address)
gitlab_host_with_port = "#{uri.host}:#{uri.port}" gitlab_host_with_port = "#{uri.host}:#{uri.port}"
...@@ -29,7 +39,7 @@ module QA ...@@ -29,7 +39,7 @@ module QA
file_path: 'package.json', file_path: 'package.json',
content: <<~JSON content: <<~JSON
{ {
"name": "#{package_name}", "name": "#{package.name}",
"version": "1.0.0", "version": "1.0.0",
"description": "Example package for GitLab npm registry", "description": "Example package for GitLab npm registry",
"publishConfig": { "publishConfig": {
...@@ -56,20 +66,20 @@ module QA ...@@ -56,20 +66,20 @@ module QA
Page::Project::Menu.perform(&:click_packages_link) Page::Project::Menu.perform(&:click_packages_link)
Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package_name) expect(index).to have_package(package.name)
index.click_package(package_name) index.click_package(package.name)
end end
Page::Project::Packages::Show.perform do |show| Page::Project::Packages::Show.perform do |show|
expect(show).to have_package_info(package_name, "1.0.0") expect(show).to have_package_info(package.name, "1.0.0")
show.click_delete show.click_delete
end end
Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
expect(index).to have_content("Package deleted successfully") expect(index).to have_content("Package deleted successfully")
expect(index).not_to have_package(package_name) expect(index).not_to have_package(package.name)
end end
end end
end end
......
...@@ -6,8 +6,6 @@ module QA ...@@ -6,8 +6,6 @@ module QA
RSpec.describe 'Package', :orchestrated, :packages do RSpec.describe 'Package', :orchestrated, :packages do
describe 'NuGet Repository' do describe 'NuGet Repository' do
include Runtime::Fixtures include Runtime::Fixtures
let(:package_name) { "dotnetcore-#{SecureRandom.hex(8)}" }
let(:project) do let(:project) do
Resource::Project.fabricate_via_api! do |project| Resource::Project.fabricate_via_api! do |project|
project.name = 'nuget-package-project' project.name = 'nuget-package-project'
...@@ -15,6 +13,13 @@ module QA ...@@ -15,6 +13,13 @@ module QA
end end
end end
let(:package) do
Resource::Package.new.tap do |package|
package.name = "dotnetcore-#{SecureRandom.hex(8)}"
package.project = project
end
end
let(:another_project) do let(:another_project) do
Resource::Project.fabricate_via_api! do |project| Resource::Project.fabricate_via_api! do |project|
project.name = 'nuget-package-install-project' project.name = 'nuget-package-install-project'
...@@ -43,6 +48,7 @@ module QA ...@@ -43,6 +48,7 @@ module QA
after do after do
runner.remove_via_api! runner.remove_via_api!
another_runner.remove_via_api! another_runner.remove_via_api!
package.remove_via_api!
end end
it 'publishes a nuget package at the project level, installs and deletes it at the group level', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1073' do it 'publishes a nuget package at the project level, installs and deletes it at the group level', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1073' do
...@@ -66,7 +72,7 @@ module QA ...@@ -66,7 +72,7 @@ module QA
script: script:
- dotnet restore -p:Configuration=Release - dotnet restore -p:Configuration=Release
- dotnet build -c Release - dotnet build -c Release
- dotnet pack -c Release -p:PackageID=#{package_name} - dotnet pack -c Release -p:PackageID=#{package.name}
- dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text - dotnet nuget add source "$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
- dotnet nuget push "bin/Release/*.nupkg" --source gitlab - dotnet nuget push "bin/Release/*.nupkg" --source gitlab
only: only:
...@@ -127,7 +133,7 @@ module QA ...@@ -127,7 +133,7 @@ module QA
script: script:
- dotnet nuget locals all --clear - dotnet nuget locals all --clear
- dotnet nuget add source "$CI_SERVER_URL/api/v4/groups/#{another_project.group.id}/-/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text - dotnet nuget add source "$CI_SERVER_URL/api/v4/groups/#{another_project.group.id}/-/packages/nuget/index.json" --name gitlab --username gitlab-ci-token --password $CI_JOB_TOKEN --store-password-in-clear-text
- "dotnet add otherdotnet.csproj package #{package_name} --version 1.0.0" - "dotnet add otherdotnet.csproj package #{package.name} --version 1.0.0"
only: only:
- "#{another_project.default_branch}" - "#{another_project.default_branch}"
tags: tags:
...@@ -153,15 +159,15 @@ module QA ...@@ -153,15 +159,15 @@ module QA
Page::Group::Menu.perform(&:go_to_group_packages) Page::Group::Menu.perform(&:go_to_group_packages)
Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package_name) expect(index).to have_package(package.name)
index.click_package(package_name) index.click_package(package.name)
end end
Page::Project::Packages::Show.perform(&:click_delete) Page::Project::Packages::Show.perform(&:click_delete)
Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
expect(index).to have_content("Package deleted successfully") expect(index).to have_content("Package deleted successfully")
expect(index).not_to have_package(package_name) expect(index).not_to have_package(package.name)
end end
end end
end end
......
...@@ -4,15 +4,19 @@ module QA ...@@ -4,15 +4,19 @@ module QA
RSpec.describe 'Package', :orchestrated, :packages do RSpec.describe 'Package', :orchestrated, :packages do
describe 'PyPI Repository' do describe 'PyPI Repository' do
include Runtime::Fixtures include Runtime::Fixtures
let(:package_name) { 'mypypipackage' }
let(:project) do let(:project) do
Resource::Project.fabricate_via_api! do |project| Resource::Project.fabricate_via_api! do |project|
project.name = 'pypi-package-project' project.name = 'pypi-package-project'
end end
end end
let(:package) do
Resource::Package.new.tap do |package|
package.name = 'mypypipackage'
package.project = project
end
end
let!(:runner) do let!(:runner) do
Resource::Runner.fabricate! do |runner| Resource::Runner.fabricate! do |runner|
runner.name = "qa-runner-#{Time.now.to_i}" runner.name = "qa-runner-#{Time.now.to_i}"
...@@ -87,6 +91,7 @@ module QA ...@@ -87,6 +91,7 @@ module QA
after do after do
runner.remove_via_api! runner.remove_via_api!
package.remove_via_api!
project&.remove_via_api! project&.remove_via_api!
end end
...@@ -94,8 +99,8 @@ module QA ...@@ -94,8 +99,8 @@ module QA
Page::Project::Menu.perform(&:click_packages_link) Page::Project::Menu.perform(&:click_packages_link)
Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
expect(index).to have_package(package_name) expect(index).to have_package(package.name)
index.click_package(package_name) index.click_package(package.name)
end end
Page::Project::Packages::Show.perform(&:click_delete) Page::Project::Packages::Show.perform(&:click_delete)
...@@ -103,7 +108,7 @@ module QA ...@@ -103,7 +108,7 @@ module QA
Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
aggregate_failures do aggregate_failures do
expect(index).to have_content("Package deleted successfully") expect(index).to have_content("Package deleted successfully")
expect(index).not_to have_package(package_name) expect(index).not_to have_package(package.name)
end end
end end
end end
...@@ -127,8 +132,8 @@ module QA ...@@ -127,8 +132,8 @@ module QA
Page::Project::Menu.perform(&:click_packages_link) Page::Project::Menu.perform(&:click_packages_link)
Page::Project::Packages::Index.perform do |index| Page::Project::Packages::Index.perform do |index|
index.wait_for_package_replication(package_name) index.wait_for_package_replication(package.name)
expect(index).to have_package(package_name) expect(index).to have_package(package.name)
end end
end end
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