spec/lib/gitlab/package_repository_spec.rb (257 lines of code) (raw):
require 'spec_helper'
require 'gitlab/package_repository'
RSpec.describe PackageRepository do
let(:repo) { PackageRepository.new }
before do
allow(ENV).to receive(:[]).and_call_original
end
describe :repository_for_rc do
context 'on master' do
# Example:
# on non stable branch: 8.1.0+rc1.ce.0-1685-gd2a2c51
# on tag: 8.12.0+rc1.ee.0
before do
allow(IO).to receive(:popen).with(%w[git describe]).and_return("8.12.0+rc1.ee.0\n")
end
it { expect(repo.repository_for_rc).to eq 'unstable' }
end
context 'on stable branch' do
# Example:
# on non stable branch: 8.12.8+ce.0-1-gdac92d4
# on tag: 8.12.8+ce.0
before do
allow(IO).to receive(:popen).with(%w[git describe]).and_return("8.12.8+ce.0\n")
end
it { expect(repo.repository_for_rc).to eq nil }
end
end
describe :target do
shared_examples 'with an override repository' do
context 'with repository override' do
before do
set_all_env_variables
end
it 'uses the override repository' do
expect(repo.target).to eq('super-stable-1234')
end
end
end
shared_examples 'with raspberry pi repo' do
context 'with raspberry pi repo' do
before do
set_raspi_env_variable
end
it 'uses the raspberry pi repository' do
expect(repo.target).to eq('raspi')
end
end
end
context 'on non-stable branch' do
before do
unset_all_env_variables
allow(IO).to receive(:popen).with(%w[git describe]).and_return("8.1.0+rc1.ce.0-1685-gd2a2c51\n")
end
it 'prints unstable' do
expect(repo.target).to eq('unstable')
end
it_behaves_like 'with an override repository'
it_behaves_like 'with raspberry pi repo'
end
context 'on a stable branch' do
before do
unset_all_env_variables
allow(IO).to receive(:popen).with(%w[git describe]).and_return("8.12.8+ce.0-1-gdac92d4\n")
end
context 'when EE' do
before do
allow(File).to receive(:read).with('VERSION').and_return("1.2.3-ee\n")
end
it 'prints gitlab-ee' do
expect(repo.target).to eq('gitlab-ee')
end
it_behaves_like 'with an override repository'
it_behaves_like 'with raspberry pi repo'
end
context 'when CE' do
before do
stub_is_ee(false)
allow(File).to receive(:read).with('VERSION').and_return("1.2.3\n")
end
it 'prints gitlab-ce' do
expect(repo.target).to eq('gitlab-ce')
end
it_behaves_like 'with an override repository'
it_behaves_like 'with raspberry pi repo'
end
end
end
describe :validate do
context 'with artifacts available' do
before do
allow(Build::Info::Package).to receive(:file_list).and_return(['pkg/el-6/gitlab-ce.rpm'])
end
it 'in dry run mode prints the checksum commands' do
expect { repo.validate(true) }.to output("sha256sum -c pkg/el-6/gitlab-ce.rpm.sha256\n").to_stdout
end
it 'raises an exception when there is a mismatch' do
expect(repo).to receive(:verify_checksum).with('pkg/el-6/gitlab-ce.rpm.sha256', true).and_return(false)
expect { repo.validate(true) }.to raise_error(%r{Aborting, package .* has an invalid checksum!})
end
end
context 'with artifacts unavailable' do
before do
allow(Build::Info::Package).to receive(:file_list).and_return([])
end
it 'prints nothing' do
expect { repo.validate(true) }.to output('').to_stdout
end
end
end
describe '#upload' do
describe 'with staging repository' do
context 'when upload user is not specified' do
before do
unset_all_env_variables
end
it 'prints a message and aborts' do
expect { repo.upload('my-staging-repository', true) }.to output(%r{Owner of the repository to which packages are being uploaded not specified}).to_stdout
end
end
context 'with specified upload user' do
before do
stub_env_var('PACKAGECLOUD_USER', "gitlab")
end
context 'with artifacts available' do
before do
allow(Build::Info::Package).to receive(:file_list).and_return(['pkg/el-9/gitlab-ce.rpm'])
end
it 'in dry run mode prints the upload commands' do
expect { repo.upload('my-staging-repository', true) }.to output(%r{Uploading...\n}).to_stdout
expect { repo.upload('my-staging-repository', true) }.to output(%r{bin/package_cloud push gitlab/my-staging-repository/ol/9 pkg/el-9/gitlab-ce.rpm --url=https://packages.gitlab.com\n}).to_stdout
expect { repo.upload('my-staging-repository', true) }.to output(%r{bin/package_cloud push gitlab/my-staging-repository/el/9 pkg/el-9/gitlab-ce.rpm --url=https://packages.gitlab.com\n}).to_stdout
end
it 'retries upload if it fails' do
allow(repo).to receive(:`).and_return('504 Gateway Timeout')
allow(repo).to receive(:child_process_status).and_return(1)
allow(repo).to receive(:validate).and_return(nil)
expect(repo).to receive(:`).exactly(10).times
expect { repo.upload('my-staging-repository', false) }.to raise_error(described_class::PackageUploadError)
end
context 'with OpenSUSE Leap 15.6 artifact' do
before do
allow(Build::Info::Package).to receive(:file_list).and_return(['pkg/opensuse-15.6_aarch64/gitlab-ce.rpm'])
end
it 'uploads the package to SLES and Leap repositories' do
expect { repo.upload('my-staging-repository', true) }.to output(%r{Uploading...\n}).to_stdout
expect { repo.upload('my-staging-repository', true) }.to output(%r{bin/package_cloud push gitlab/my-staging-repository/opensuse/15.6 pkg/opensuse-15.6_aarch64/gitlab-ce.rpm --url=https://packages.gitlab.com\n}).to_stdout
expect { repo.upload('my-staging-repository', true) }.to output(%r{bin/package_cloud push gitlab/my-staging-repository/sles/15.6 pkg/opensuse-15.6_aarch64/gitlab-ce.rpm --url=https://packages.gitlab.com\n}).to_stdout
end
end
end
context 'with artifacts unavailable' do
before do
allow(Dir).to receive(:glob).with("pkg/**/*.{deb,rpm}").and_return([])
end
it 'prints a message and aborts' do
expect { repo.upload('my-staging-repository', true) }.to raise_exception(%r{No packages found for upload. Are artifacts available?})
end
end
end
end
describe "with production repository" do
context 'with artifacts available' do
before do
stub_env_var('PACKAGECLOUD_USER', "gitlab")
allow(Dir).to receive(:glob).with("pkg/**/*.{deb,rpm}").and_return(['pkg/ubuntu-focal/gitlab.deb'])
end
context 'for stable release' do
before do
stub_env_var('PACKAGECLOUD_REPO', nil)
stub_env_var('RASPBERRY_REPO', nil)
allow_any_instance_of(PackageRepository).to receive(:repository_for_rc).and_return(nil)
end
context 'of EE' do
before do
stub_is_ee(true)
end
it 'in dry run mode prints the upload commands' do
expect { repo.upload(nil, true) }.to output(%r{Uploading...\n}).to_stdout
expect { repo.upload(nil, true) }.to output(%r{bin/package_cloud push gitlab/gitlab-ee/ubuntu/focal pkg/ubuntu-focal/gitlab.deb --url=https://packages.gitlab.com\n}).to_stdout
end
context 'for arm64 packages' do
before do
allow(Dir).to receive(:glob).with("pkg/**/*.{deb,rpm}").and_return(['pkg/ubuntu-focal_aarch64/gitlab.deb'])
end
it 'drops the architecture suffix from repo path' do
expect { repo.upload(nil, true) }.to output(%r{Uploading...\n}).to_stdout
expect { repo.upload(nil, true) }.to output(%r{bin/package_cloud push gitlab/gitlab-ee/ubuntu/focal pkg/ubuntu-focal_aarch64/gitlab.deb --url=https://packages.gitlab.com\n}).to_stdout
end
end
context 'for fips packages' do
before do
allow(Dir).to receive(:glob).with("pkg/**/*.{deb,rpm}").and_return(['pkg/ubuntu-focal_fips/gitlab.deb'])
end
it 'drops the fips suffix from repo path' do
expect { repo.upload(nil, true) }.to output(%r{Uploading...\n}).to_stdout
expect { repo.upload(nil, true) }.to output(%r{bin/package_cloud push gitlab/gitlab-ee/ubuntu/focal pkg/ubuntu-focal_fips/gitlab.deb --url=https://packages.gitlab.com\n}).to_stdout
end
end
end
context 'of CE' do
before do
stub_is_ee(nil)
end
it 'in dry run mode prints the upload commands' do
expect { repo.upload(nil, true) }.to output(%r{Uploading...\n}).to_stdout
expect { repo.upload(nil, true) }.to output(%r{bin/package_cloud push gitlab/gitlab-ce/ubuntu/focal pkg/ubuntu-focal/gitlab.deb --url=https://packages.gitlab.com\n}).to_stdout
end
end
end
context 'for nightly release' do
before do
set_nightly_env_variable
allow_any_instance_of(PackageRepository).to receive(:repository_for_rc).and_return(nil)
end
it 'in dry run mode prints the upload commands' do
expect { repo.upload(Gitlab::Util.get_env('STAGING_REPO'), true) }.to output(%r{Uploading...\n}).to_stdout
expect { repo.upload(Gitlab::Util.get_env('STAGING_REPO'), true) }.to output(%r{bin/package_cloud push gitlab/nightly-builds/ubuntu/focal pkg/ubuntu-focal/gitlab.deb --url=https://packages.gitlab.com\n}).to_stdout
end
end
context 'for raspbian release' do
before do
set_raspi_env_variable
allow_any_instance_of(PackageRepository).to receive(:repository_for_rc).and_return(nil)
end
it 'in dry run mode prints the upload commands' do
expect { repo.upload(nil, true) }.to output(%r{Uploading...\n}).to_stdout
expect { repo.upload(nil, true) }.to output(%r{bin/package_cloud push gitlab/raspi/ubuntu/focal pkg/ubuntu-focal/gitlab.deb --url=https://packages.gitlab.com\n}).to_stdout
end
end
end
end
describe 'when artifacts contain unexpected files' do
before do
stub_env_var('PACKAGECLOUD_USER', "gitlab")
set_all_env_variables
allow(Dir).to receive(:glob).with("pkg/**/*.{deb,rpm}").and_return(['pkg/ubuntu-focal/gitlab.deb', 'pkg/ubuntu-focal/testing/gitlab.deb'])
end
it 'raises an exception' do
expect { repo.upload(nil, true) }.to raise_exception(%r{Found unexpected contents in the directory:})
end
end
end
def unset_all_env_variables
stub_env_var('PACKAGECLOUD_TOKEN', nil)
stub_env_var('PACKAGECLOUD_USER', nil)
stub_env_var('PACKAGECLOUD_REPO', nil)
stub_env_var('RASPBERRY_REPO', nil)
stub_env_var('STAGING_REPO', nil)
end
def set_all_env_variables
stub_env_var("PACKAGECLOUD_REPO", "super-stable-1234")
stub_env_var("RASPBERRY_REPO", "raspi")
end
def set_nightly_env_variable
stub_env_var("PACKAGECLOUD_REPO", "")
stub_env_var("RASPBERRY_REPO", "")
stub_env_var("STAGING_REPO", "nightly-builds")
end
def set_raspi_env_variable
stub_env_var("PACKAGECLOUD_REPO", "")
stub_env_var("RASPBERRY_REPO", "raspi")
end
end