# HG changeset patch # User Balasankar 'Balu' C <balasankar@gitlab.com> # Date 1647571604 0 # Fri Mar 18 02:46:44 2022 +0000 # Node ID 6cf620bad9384163c45ed979f6e9972970fcd84d # Parent 2296db406e195efb692dd70d62c5fda3e78b7a1d Move specs testing non-chef components to own directory - Moves Build and Tasks rspecs into the lib directory Closes https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3217 Signed-off-by: Balasankar "Balu" C <balasankar@gitlab.com> diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ node_modules spec/examples.txt + +.projections.json diff --git a/.projections.json.example b/.projections.json.example new file mode 100644 --- /dev/null +++ b/.projections.json.example @@ -0,0 +1,11 @@ +{ + "lib/*.rb": { + "alternate": "spec/lib/{}_spec.rb", + "type": "source" + }, + "spec/lib/*_spec.rb": { + "alternate": "lib/{}.rb", + "type": "test", + "dispatch": "bundle exec rspec {file}" + } +} diff --git a/.rubocop.yml b/.rubocop.yml --- a/.rubocop.yml +++ b/.rubocop.yml @@ -70,7 +70,7 @@ - files/**/* - docker/**/* - lib/gitlab/util.rb - - spec/gitlab/util_spec.rb + - spec/lib/gitlab/util_spec.rb Style/MultilineIfModifier: Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -68,8 +68,8 @@ - 'files/gitlab-ctl-commands/upgrade.rb' - 'spec/chef/secrets_spec.rb' - 'spec/gitlab-ctl-commands/gitlab_ctl_spec.rb' - - 'spec/gitlab/build/image_spec.rb' - - 'spec/gitlab/tasks/qa_spec.rb' + - 'spec/lib/gitlab/build/image_spec.rb' + - 'spec/lib/gitlab/tasks/qa_spec.rb' - 'spec/support/shared_examples/geo_promotion_command_accepts_option_shared_examples.rb' - 'spec/support/shared_examples/gitlab_geo_promotion_commands_shared_examples.rb' diff --git a/spec/gitlab/build/check_spec.rb b/spec/gitlab/build/check_spec.rb deleted file mode 100644 --- a/spec/gitlab/build/check_spec.rb +++ /dev/null @@ -1,171 +0,0 @@ -require 'spec_helper' -require 'gitlab/build/check' - -RSpec.describe Build::Check do - before do - stub_default_package_version - end - - describe 'is_ee?' do - describe 'with environment variables' do - before do - stub_is_ee_version(false) - end - - describe 'ee variable' do - it 'when ee=true' do - stub_is_ee_env(true) - expect(described_class.is_ee?).to be_truthy - end - - it 'when ee=false' do - stub_is_ee(false) - expect(described_class.is_ee?).to be_falsy - end - - it 'when env variable is not set' do - stub_is_ee_version(false) - stub_is_auto_deploy(false) - expect(described_class.is_ee?).to be_falsy - end - end - - describe 'GITLAB_VERSION variable' do - it 'when GITLAB_VERSION ends with -ee' do - stub_env_var('GITLAB_VERSION', 'foo-ee') - expect(described_class.is_ee?).to be_truthy - end - - it 'when GITLAB_VERSION does not end with -ee' do - stub_env_var('GITLAB_VERSION', 'foo') - stub_is_auto_deploy(false) - expect(described_class.is_ee?).to be_falsy - end - - it 'ee variable wins over GITLAB_VERSION variable' do - stub_is_ee_env(true) - stub_env_var('GITLAB_VERSION', 'foo') - expect(described_class.is_ee?).to be_truthy - end - end - end - - describe 'without environment variables' do - it 'checks the VERSION file' do - stub_is_ee_version(false) - stub_env_var('GITLAB_VERSION', 'foo-ee') - expect(described_class.is_ee?).to be_truthy - end - - it 'GITLAB_VERSION variable wins over the file' do - stub_env_var('GITLAB_VERSION', 'foo-ee') - expect(described_class.is_ee?).to be_truthy - end - end - end - - describe 'include_ee?' do - it 'returns true when is_ee? is true' do - allow(described_class).to receive(:is_ee?).and_return(true) - expect(described_class.include_ee?).to be_truthy - end - - it 'returns false when we are building a ce package' do - allow(described_class).to receive(:is_ee?).and_return(false) - expect(described_class.include_ee?).to be_falsey - end - end - - describe 'add tag methods' do - describe 'is_nightly?' do - it 'returns true if it is a nightly build' do - stub_env_var('NIGHTLY', 'true') - expect(described_class.is_nightly?).to be_truthy - end - - it 'returns false if it is not a nightly build' do - expect(described_class.is_nightly?).to be_falsey - end - end - - describe 'is_latest_tag?' do - it 'returns true if it is an rc release' do - # This will be the case if latest_tag is eg. 9.3.0+rc6.ce.0 - # or 9.3.0+ce.0 - allow(Build::Info).to receive(:latest_tag).and_return('9.3.0+rc6.ce.0') # This line only is only an example, stubbing is not needed. - allow(described_class).to receive(:match_tag?).and_return(true) - expect(described_class.is_latest_tag?).to be_truthy - end - - it 'returns true if it is not an rc release' do - allow(Build::Info).to receive(:latest_tag).and_return('9.3.0+ce.0') # This line only is only an example, stubbing is not needed. - allow(described_class).to receive(:match_tag?).and_return(false) - expect(described_class.is_latest_tag?).to be_falsey - end - end - - describe 'is_latest_stable_tag?' do - it 'returns true if it is a stable release' do - # This will be the case if latest_tag is eg. 9.3.0+ce.0 - # It will not be the case if the tag is 9.3.0+rc6.ce.0 - allow(Build::Info).to receive(:latest_stable_tag).and_return('9.3.0+ce.0') # This line only is only an example, stubbing is not needed. - allow(described_class).to receive(:match_tag?).and_return(true) - expect(described_class.is_latest_stable_tag?).to be_truthy - end - - it 'returns true if it is not a stable release' do - allow(Build::Info).to receive(:latest_stable_tag).and_return('9.3.0+rc6.ce.0') # This line only is only an example, stubbing is not needed. - allow(described_class).to receive(:match_tag?).and_return(false) - expect(described_class.is_latest_stable_tag?).to be_falsey - end - end - end - - describe '.is_patch_release?' do - it 'returns true for patch release' do - allow(Build::Info).to receive(:semver_version).and_return("10.0.3") - expect(described_class.is_patch_release?).to be_truthy - end - - it 'returns false for major/minor release' do - allow(Build::Info).to receive(:semver_version).and_return("10.0.0") - expect(described_class.is_patch_release?).to be_falsey - end - end - - describe 'is_rc_tag?' do - it 'returns true if it looks like an rc tag' do - # It will be the case if the tag is 9.3.0+rc6.ce.0 - allow(Build::Info).to receive(:current_git_tag).and_return('9.3.0+rc6.ce.0') - expect(described_class.is_rc_tag?).to be_truthy - end - it 'returns false if it does not look like an rc tag' do - # This not be the case if tag is eg. 9.3.0+ce.0 - allow(Build::Info).to receive(:current_git_tag).and_return('9.3.0+ce.0') - expect(described_class.is_rc_tag?).to be_falsey - end - end - - describe 'is_auto_deploy?' do - it 'returns true if it looks like an auto-deploy tag' do - # This is the case if the tag is 11.10.12345+5159f2949cb.59c9fa631 - allow(Build::Info).to receive(:current_git_tag).and_return('11.10.12345+5159f2949cb.59c9fa631') - expect(described_class.is_auto_deploy?).to be_truthy - end - - it 'returns false if it does not look like an auto-deploy tag' do - # This not be the case if ag is eg. 9.3.0+ce.0 - allow(Gitlab::Util).to receive(:get_env).with('CI_COMMIT_REF_NAME').and_return('a-random-branch') - - allow(Build::Info).to receive(:current_git_tag).and_return('9.3.0+ce.0') - expect(described_class.is_auto_deploy?).to be_falsey - end - end - - describe 'ci_commit_tag?' do - it 'checks for the CI_COMMIT_TAG' do - allow(Gitlab::Util).to receive(:get_env).with('CI_COMMIT_TAG').and_return('11.10.12345+5159f2949cb.59c9fa631') - expect(described_class.ci_commit_tag?).to be_truthy - end - end -end diff --git a/spec/gitlab/build/facts_spec.rb b/spec/gitlab/build/facts_spec.rb deleted file mode 100644 --- a/spec/gitlab/build/facts_spec.rb +++ /dev/null @@ -1,96 +0,0 @@ -require 'spec_helper' -require 'gitlab/build/facts' -require 'gitlab/build/gitlab_image' - -RSpec.describe Build::Facts do - before do - allow(ENV).to receive(:[]).and_call_original - end - - describe '.generate' do - it 'calls necessary methods' do - expect(described_class).to receive(:generate_tag_files) - expect(described_class).to receive(:generate_env_file) - - described_class.generate - end - end - - describe '.generate_tag_files' do - before do - allow(Build::Info).to receive(:latest_stable_tag).and_return('14.6.2+ce.0') - allow(Build::Info).to receive(:latest_tag).and_return('14.7.0+rc42.ce.0') - end - - it 'writes tag details to file' do - expect(File).to receive(:write).with('build_facts/latest_stable_tag', '14.6.2+ce.0') - expect(File).to receive(:write).with('build_facts/latest_tag', '14.7.0+rc42.ce.0') - - described_class.generate_tag_files - end - end - - describe '.generate_env_file' do - before do - allow(described_class).to receive(:common_vars).and_return(%w[TOP_UPSTREAM_SOURCE_PROJECT=gitlab-org/gitlab]) - allow(described_class).to receive(:qa_trigger_vars).and_return(%w[QA_RELEASE=foobar]) - allow(described_class).to receive(:version_vars).and_return(%w[GITLAB_VERSION=randombranch]) - end - - it 'writes environment variables to file' do - expect(File).to receive(:write).with('build_facts/env_vars', "TOP_UPSTREAM_SOURCE_PROJECT=gitlab-org/gitlab\nQA_RELEASE=foobar\nGITLAB_VERSION=randombranch") - - described_class.generate_env_file - end - end - - describe '.common_vars' do - before do - stub_env_var('TOP_UPSTREAM_SOURCE_PROJECT', 'gitlab-org/gitlab') - stub_env_var('TOP_UPSTREAM_SOURCE_REF', 'master') - stub_env_var('TOP_UPSTREAM_SOURCE_JOB', '123456') - stub_env_var('TOP_UPSTREAM_SOURCE_SHA', 'aq2456fs') - stub_env_var('TOP_UPSTREAM_MERGE_REQUEST_PROJECT_ID', '55555') - stub_env_var('TOP_UPSTREAM_MERGE_REQUEST_IID', '7689') - end - - it 'returns correct variables' do - result = %w[ - TOP_UPSTREAM_SOURCE_PROJECT=gitlab-org/gitlab - TOP_UPSTREAM_SOURCE_REF=master - TOP_UPSTREAM_SOURCE_JOB=123456 - TOP_UPSTREAM_SOURCE_SHA=aq2456fs - TOP_UPSTREAM_MERGE_REQUEST_PROJECT_ID=55555 - TOP_UPSTREAM_MERGE_REQUEST_IID=7689 - ] - - expect(described_class.common_vars).to eq(result) - end - end - - describe '.qa_trigger_vars' do - before do - allow(described_class).to receive(:generate_knapsack_report?).and_return('true') - allow(Build::GitlabImage).to receive(:gitlab_registry_image_address).and_return('registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:14.6.2-rfbranch.450066356.c97110ad-0') - - stub_env_var('QA_IMAGE', 'gitlab/gitlab-ee-qa:nightly') - stub_env_var('QA_TESTS', '') - stub_env_var('ALLURE_JOB_NAME', '') - stub_env_var('GITLAB_QA_OPTIONS', '') - end - - it 'returns correct variables' do - result = %w[ - QA_BRANCH=master - QA_RELEASE=registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:14.6.2-rfbranch.450066356.c97110ad-0 - QA_IMAGE=gitlab/gitlab-ee-qa:nightly - QA_TESTS= - ALLURE_JOB_NAME= - GITLAB_QA_OPTIONS= - KNAPSACK_GENERATE_REPORT=true - ] - - expect(described_class.qa_trigger_vars).to eq(result) - end - end -end diff --git a/spec/gitlab/build/gitlab_image_spec.rb b/spec/gitlab/build/gitlab_image_spec.rb deleted file mode 100644 --- a/spec/gitlab/build/gitlab_image_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -require 'spec_helper' -require 'gitlab/build/gitlab_image' - -RSpec.describe Build::GitlabImage do - before do - allow(Build::Info).to receive(:package).and_return('gitlab-ce') - end - - describe '.dockerhub_image_name' do - it 'returns a correct image name' do - expect(described_class.dockerhub_image_name).to eq('gitlab/gitlab-ce') - end - end - - describe '.gitlab_registry_image_name' do - it 'returns a correct image name' do - expect(described_class.gitlab_registry_image_name).to eq('gitlab-ce') - end - end -end diff --git a/spec/gitlab/build/image_spec.rb b/spec/gitlab/build/image_spec.rb deleted file mode 100644 --- a/spec/gitlab/build/image_spec.rb +++ /dev/null @@ -1,163 +0,0 @@ -require 'spec_helper' -require 'gitlab/build/image' - -RSpec.describe Build::Image do - ComponentImage = Class.new do - extend Build::Image - - def self.gitlab_registry_image_name - 'my-project/my-image' - end - - def self.dockerhub_image_name - 'my-image' - end - end - - before do - allow(ENV).to receive(:[]).and_call_original - allow(ENV).to receive(:[]).with('CI_JOB_TOKEN').and_return('1234') - allow(ENV).to receive(:[]).with('CI_REGISTRY').and_return('registry.com') - allow(ENV).to receive(:[]).with('CI_REGISTRY_IMAGE').and_return('registry.com/group/repo') - allow(ENV).to receive(:[]).with('DOCKERHUB_USERNAME').and_return('john') - allow(ENV).to receive(:[]).with('DOCKERHUB_PASSWORD').and_return('secret') - allow(Build::Info).to receive(:docker_tag).and_return('9.0.0') - end - - describe '.pull' do - it 'creates an image from the local one' do - expect(Docker::Image).to receive(:create).with( - 'fromImage' => "#{ComponentImage.gitlab_registry_image_address}:9.0.0" - ) - - ComponentImage.pull - end - end - - describe '.gitlab_registry_image_address' do - it 'returns a correct image name' do - expect(ComponentImage.gitlab_registry_image_address).to eq('registry.com/group/repo/my-project/my-image') - end - - context 'with a tag given' do - it 'returns a correct image name' do - expect(ComponentImage.gitlab_registry_image_address(tag: 'mytag')).to eq('registry.com/group/repo/my-project/my-image:mytag') - end - end - end - - describe '.tag_and_push_to_gitlab_registry' do - it 'calls DockerOperations.authenticate and DockerOperations.tag_and_push' do - expect(DockerOperations).to receive(:authenticate).with('gitlab-ci-token', '1234', 'registry.com') - expect(DockerOperations).to receive(:tag_and_push).with( - ComponentImage.gitlab_registry_image_address, - ComponentImage.gitlab_registry_image_address, - 'latest', - 'foo' - ) - - ComponentImage.tag_and_push_to_gitlab_registry('foo') - end - end - - describe '.tag_and_push_to_dockerhub' do - it 'calls DockerOperations.authenticate and DockerOperations.tag_and_push' do - expect(DockerOperations).to receive(:authenticate).with('john', 'secret') - expect(DockerOperations).to receive(:tag_and_push).with( - ComponentImage.gitlab_registry_image_address, - ComponentImage.dockerhub_image_name, - '9.0.0', - 'foo' - ) - - ComponentImage.tag_and_push_to_dockerhub('foo') - end - - context 'with a initial_tag given' do - it 'calls DockerOperations.authenticate and DockerOperations.tag_and_push' do - expect(DockerOperations).to receive(:authenticate).with('john', 'secret') - expect(DockerOperations).to receive(:tag_and_push).with( - ComponentImage.gitlab_registry_image_address, - ComponentImage.dockerhub_image_name, - 'latest', - 'foo' - ) - - ComponentImage.tag_and_push_to_dockerhub('foo', initial_tag: 'latest') - end - end - end - - describe '.write_release_file' do - describe 'with triggered build' do - let(:release_file) do - [ - "PACKAGECLOUD_REPO=download-package", - "RELEASE_VERSION=12.121.12-ce.1", - "DOWNLOAD_URL=https://gitlab.com/api/v4/projects/1/jobs/1/artifacts/pkg/ubuntu-focal/gitlab.deb", - "TRIGGER_PRIVATE_TOKEN=NOT-PRIVATE-TOKEN\n" - ] - end - - before do - stub_env_var('PACKAGECLOUD_REPO', 'download-package') - stub_env_var('TRIGGER_PRIVATE_TOKEN', 'NOT-PRIVATE-TOKEN') - stub_env_var('CI_PROJECT_ID', '1') - stub_env_var('CI_PIPELINE_ID', '2') - allow(Build::Info).to receive(:release_version).and_return('12.121.12-ce.1') - allow(Build::Info).to receive(:fetch_artifact_url).with('1', '2').and_return('1') - end - - describe 'for CE' do - before do - allow(Build::Info).to receive(:package).and_return('gitlab-ce') - end - - it 'returns build version and iteration with env variable' do - release_file_content = release_file.insert(1, 'RELEASE_PACKAGE=gitlab-ce').join("\n") - - expect(ComponentImage.write_release_file).to eq(release_file_content) - end - end - - describe 'for EE' do - before do - allow(Build::Info).to receive(:package).and_return('gitlab-ee') - end - - it 'returns build version and iteration with env variable' do - release_file_content = release_file.insert(1, 'RELEASE_PACKAGE=gitlab-ee').join("\n") - - expect(ComponentImage.write_release_file).to eq(release_file_content) - end - end - - describe 'with regular build' do - let(:s3_download_link) { 'https://downloads-packages.s3.amazonaws.com/ubuntu-focal/gitlab-ee_12.121.12-ce.1_amd64.deb' } - - let(:release_file) do - [ - "RELEASE_VERSION=12.121.12-ce.1", - "DOWNLOAD_URL=#{s3_download_link}\n", - ] - end - - before do - stub_env_var('PACKAGECLOUD_REPO', '') - stub_env_var('TRIGGER_PRIVATE_TOKEN', '') - stub_env_var('CI_PROJECT_ID', '') - stub_env_var('CI_PIPELINE_ID', '') - allow(Build::Check).to receive(:on_tag?).and_return(true) - allow(Build::Info).to receive(:package).and_return('gitlab-ee') - allow(ComponentImage).to receive(:release_version).and_return('12.121.12-ce.1') - end - - it 'returns build version and iteration with env variable' do - release_file_content = release_file.insert(0, 'RELEASE_PACKAGE=gitlab-ee').join("\n") - - expect(ComponentImage.write_release_file).to eq(release_file_content) - end - end - end - end -end diff --git a/spec/gitlab/build/info_spec.rb b/spec/gitlab/build/info_spec.rb deleted file mode 100644 --- a/spec/gitlab/build/info_spec.rb +++ /dev/null @@ -1,277 +0,0 @@ -require 'spec_helper' -require 'gitlab/build/info' -require 'gitlab/build/gitlab_image' - -RSpec.describe Build::Info do - before do - stub_default_package_version - stub_env_var('GITLAB_ALTERNATIVE_REPO', nil) - stub_env_var('ALTERNATIVE_PRIVATE_TOKEN', nil) - end - - describe '.package' do - describe 'shows EE' do - it 'when ee=true' do - stub_is_ee_env(true) - expect(described_class.package).to eq('gitlab-ee') - end - - it 'when env var is not present, checks VERSION file' do - stub_is_ee_version(true) - expect(described_class.package).to eq('gitlab-ee') - end - end - - describe 'shows CE' do - it 'by default' do - stub_is_ee(false) - expect(described_class.package).to eq('gitlab-ce') - end - end - end - - describe '.release_version' do - before do - allow(Build::Check).to receive(:on_tag?).and_return(true) - allow_any_instance_of(Omnibus::BuildVersion).to receive(:semver).and_return('12.121.12') - allow_any_instance_of(Gitlab::BuildIteration).to receive(:build_iteration).and_return('ce.1') - end - - it 'returns build version and iteration' do - expect(described_class.release_version).to eq('12.121.12-ce.1') - end - - it 'defaults to an initial build version when there are no matching tags' do - allow(Build::Check).to receive(:on_tag?).and_return(false) - allow(Build::Check).to receive(:is_nightly?).and_return(false) - allow(Build::Info).to receive(:latest_tag).and_return('') - allow(Build::Info).to receive(:commit_sha).and_return('ffffffff') - stub_env_var('CI_PIPELINE_ID', '5555') - - expect(described_class.release_version).to eq('0.0.1+rfbranch.5555.ffffffff-ce.1') - end - - describe 'with env variables' do - it 'returns build version and iteration with env variable' do - stub_env_var('USE_S3_CACHE', 'false') - stub_env_var('CACHE_AWS_ACCESS_KEY_ID', 'NOT-KEY') - stub_env_var('CACHE_AWS_SECRET_ACCESS_KEY', 'NOT-SECRET-KEY') - stub_env_var('CACHE_AWS_BUCKET', 'bucket') - stub_env_var('CACHE_AWS_S3_REGION', 'moon-west1') - stub_env_var('CACHE_AWS_S3_ENDPOINT', 'endpoint') - stub_env_var('CACHE_S3_ACCELERATE', 'sure') - - stub_env_var('NIGHTLY', 'true') - stub_env_var('CI_PIPELINE_ID', '5555') - - expect(described_class.release_version).to eq('12.121.12-ce.1') - end - end - end - - describe '.docker_tag' do - before do - allow(Build::Check).to receive(:on_tag?).and_return(true) - allow_any_instance_of(Omnibus::BuildVersion).to receive(:semver).and_return('12.121.12') - allow_any_instance_of(Gitlab::BuildIteration).to receive(:build_iteration).and_return('ce.1') - end - - it 'returns package version when regular build' do - expect(described_class.docker_tag).to eq('12.121.12-ce.1') - end - - it 'respects IMAGE_TAG if set' do - allow(ENV).to receive(:[]).with('IMAGE_TAG').and_return('foobar') - expect(described_class.docker_tag).to eq('foobar') - end - end - - # Specs for latest_tag and for latest_stable_tag are really useful since we - # are stubbing out shell out to git. - # However, they are showing what we expect to see. - describe '.latest_tag' do - describe 'for CE' do - before do - stub_is_ee(false) - allow(described_class).to receive(:`).with("git describe --exact-match 2>/dev/null").and_return('12.121.12+rc7.ce.0') - allow(described_class).to receive(:`).with("git -c versionsort.prereleaseSuffix=rc tag -l '*[+.]ce.*' --sort=-v:refname | head -1").and_return('12.121.12+rc7.ce.0') - end - - it 'returns the version of correct edition' do - expect(described_class.latest_tag).to eq('12.121.12+rc7.ce.0') - end - end - - describe 'for EE' do - before do - stub_is_ee(true) - allow(described_class).to receive(:`).with("git -c versionsort.prereleaseSuffix=rc tag -l '*[+.]ee.*' --sort=-v:refname | head -1").and_return('12.121.12+rc7.ee.0') - end - - it 'returns the version of correct edition' do - expect(described_class.latest_tag).to eq('12.121.12+rc7.ee.0') - end - end - end - - describe '.latest_stable_tag' do - describe 'for CE' do - before do - stub_is_ee(nil) - allow(described_class).to receive(:`).with("git describe --exact-match 2>/dev/null").and_return('12.121.12+ce.0') - allow(described_class).to receive(:`).with("git -c versionsort.prereleaseSuffix=rc tag -l '*[+.]ce.*' --sort=-v:refname | awk '!/rc/' | head -1").and_return('12.121.12+ce.0') - end - - it 'returns the version of correct edition' do - expect(described_class.latest_stable_tag).to eq('12.121.12+ce.0') - end - end - - describe 'for EE' do - before do - stub_is_ee(true) - allow(described_class).to receive(:`).with("git -c versionsort.prereleaseSuffix=rc tag -l '*[+.]ee.*' --sort=-v:refname | awk '!/rc/' | head -1").and_return('12.121.12+ee.0') - end - - it 'returns the version of correct edition' do - expect(described_class.latest_stable_tag).to eq('12.121.12+ee.0') - end - end - end - - describe '.gitlab_version' do - describe 'GITLAB_VERSION variable specified' do - it 'returns passed value' do - allow(ENV).to receive(:[]).with("GITLAB_VERSION").and_return("9.0.0") - expect(described_class.gitlab_version).to eq('9.0.0') - end - end - - describe 'GITLAB_VERSION variable not specified' do - it 'returns content of VERSION' do - allow(File).to receive(:read).with("VERSION").and_return("8.5.6") - expect(described_class.gitlab_version).to eq('8.5.6') - end - end - end - - describe '.previous_version' do - it 'detects previous version correctly' do - allow(described_class).to receive(:`).with("git describe --exact-match 2>/dev/null").and_return('10.4.0+ee.0') - allow(Build::Info).to receive(:`).with(/git -c versionsort/).and_return("10.4.0+ee.0\n10.3.5+ee.0") - - expect(described_class.previous_version).to eq("10.3.5-ee.0") - end - end - - describe '.gitlab_rails repo' do - describe 'with alternative sources channel selected' do - before do - allow(::Gitlab::Version).to receive(:sources_channel).and_return('alternative') - end - - it 'returns public mirror for GitLab CE' do - allow(Build::Info).to receive(:package).and_return("gitlab-ce") - expect(described_class.gitlab_rails_repo).to eq("https://gitlab.com/gitlab-org/gitlab-foss.git") - end - it 'returns public mirror for GitLab EE' do - allow(Build::Info).to receive(:package).and_return("gitlab-ee") - expect(described_class.gitlab_rails_repo).to eq("https://gitlab.com/gitlab-org/gitlab.git") - end - end - - describe 'with default sources channel' do - before do - allow(::Gitlab::Version).to receive(:sources_channel).and_return('remote') - end - - it 'returns dev repo for GitLab CE' do - allow(Build::Info).to receive(:package).and_return("gitlab-ce") - expect(described_class.gitlab_rails_repo).to eq("git@dev.gitlab.org:gitlab/gitlabhq.git") - end - it 'returns dev repo for GitLab EE' do - allow(Build::Info).to receive(:package).and_return("gitlab-ee") - expect(described_class.gitlab_rails_repo).to eq("git@dev.gitlab.org:gitlab/gitlab-ee.git") - end - end - - describe 'with security sources channel selected' do - before do - allow(::Gitlab::Version).to receive(:sources_channel).and_return('security') - stub_env_var('CI_JOB_TOKEN', 'CJT') - end - - it 'returns security mirror for GitLab CE with attached credential' do - allow(Build::Info).to receive(:package).and_return("gitlab-ce") - expect(described_class.gitlab_rails_repo).to eq("https://gitlab-ci-token:CJT@gitlab.com/gitlab-org/security/gitlab-foss.git") - end - it 'returns security mirror for GitLab EE with attached credential' do - allow(Build::Info).to receive(:package).and_return("gitlab-ee") - expect(described_class.gitlab_rails_repo).to eq("https://gitlab-ci-token:CJT@gitlab.com/gitlab-org/security/gitlab.git") - end - end - end - - describe '.major_minor_version_and_rails_ref' do - it 'return minor and major version components plus the rails ref' do - allow(ENV).to receive(:[]).with('CI_COMMIT_TAG').and_return('12.0.12345+5159f2949cb.59c9fa631') - - expect(described_class.major_minor_version_and_rails_ref).to eq('12.0-5159f2949cb') - end - - it 'raises an error if the commit tag is invalid' do - allow(ENV).to receive(:[]).with('CI_COMMIT_TAG').and_return('xyz') - - expect { described_class.major_minor_version_and_rails_ref }.to raise_error(RuntimeError, /Invalid auto-deploy version 'xyz'/) - end - end - - describe '.deploy_env' do - before do - allow(ENV).to receive(:[]).with('AUTO_DEPLOY_ENVIRONMENT').and_return('ad') - allow(ENV).to receive(:[]).with('PATCH_DEPLOY_ENVIRONMENT').and_return('patch') - allow(ENV).to receive(:[]).with('RELEASE_DEPLOY_ENVIRONMENT').and_return('r') - end - - context 'on auto-deploy tag' do - before do - allow(Build::Check).to receive(:is_auto_deploy_tag?).and_return(true) - end - it 'returns the auto-deploy environment' do - expect(described_class.deploy_env).to eq('ad') - end - end - - context 'on RC tag' do - before do - allow(Build::Check).to receive(:is_auto_deploy_tag?).and_return(false) - allow(Build::Check).to receive(:is_rc_tag?).and_return(true) - end - it 'returns the auto-deploy environment' do - expect(described_class.deploy_env).to eq('patch') - end - end - - context 'on latest tag' do - before do - allow(Build::Check).to receive(:is_auto_deploy_tag?).and_return(false) - allow(Build::Check).to receive(:is_rc_tag?).and_return(false) - allow(Build::Check).to receive(:is_latest_stable_tag?).and_return(true) - end - it 'returns the auto-deploy environment' do - expect(described_class.deploy_env).to eq('r') - end - end - - context 'when unable to determine the desired env' do - before do - allow(Build::Check).to receive(:is_auto_deploy_tag?).and_return(false) - allow(Build::Check).to receive(:is_rc_tag?).and_return(false) - allow(Build::Check).to receive(:is_latest_stable_tag?).and_return(false) - end - it 'it returns nil' do - expect(described_class.deploy_env).to eq(nil) - end - end - end -end diff --git a/spec/gitlab/build/qa_image_spec.rb b/spec/gitlab/build/qa_image_spec.rb deleted file mode 100644 --- a/spec/gitlab/build/qa_image_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -require 'spec_helper' -require 'gitlab/build/qa_image' - -RSpec.describe Build::QAImage do - before do - allow(Build::GitlabImage).to receive(:dockerhub_image_name).and_return('gitlab/gitlab-ce') - allow(Build::GitlabImage).to receive(:gitlab_registry_image_name).and_return('gitlab-ce') - end - - describe '.dockerhub_image_name' do - it 'returns a correct image name' do - expect(described_class.dockerhub_image_name).to eq('gitlab/gitlab-ce-qa') - end - end - - describe '.gitlab_registry_image_name' do - it 'returns a correct image name' do - expect(described_class.gitlab_registry_image_name).to eq('gitlab-ce-qa') - end - end -end diff --git a/spec/gitlab/build/qa_spec.rb b/spec/gitlab/build/qa_spec.rb deleted file mode 100644 --- a/spec/gitlab/build/qa_spec.rb +++ /dev/null @@ -1,68 +0,0 @@ -require 'spec_helper' -require 'gitlab/build/qa' - -RSpec.describe Build::QA do - before do - allow(ENV).to receive(:[]).and_call_original - stub_env_var('GITLAB_ALTERNATIVE_REPO', nil) - stub_env_var('ALTERNATIVE_PRIVATE_TOKEN', nil) - end - - describe '.repo_path' do - it 'returns correct location' do - expect(described_class.repo_path).to eq("/tmp/gitlab") - end - end - - describe '.get_gitlab_repo' do - it 'returns correct location' do - allow(Build::QA).to receive(:clone_gitlab_rails).and_return(true) - allow(Build::QA).to receive(:checkout_gitlab_rails).and_return(true) - - expect(described_class.get_gitlab_repo).to eq("/tmp/gitlab") - end - end - - describe '.clone_gitlab_rails' do - it 'calls the git command' do - allow(Build::Info).to receive(:package).and_return("gitlab-ee") - allow(::Gitlab::Version).to receive(:sources_channel).and_return('remote') - - expect(described_class).to receive(:system).with(*%w[rm -rf /tmp/gitlab]) - expect(described_class).to receive(:system).with(*%w[git clone git@dev.gitlab.org:gitlab/gitlab-ee.git /tmp/gitlab]) - - Build::QA.clone_gitlab_rails - end - end - - describe '.checkout_gitlab_rails' do - it 'calls the git command' do - allow(Build::Info).to receive(:package).and_return("gitlab-ee") - allow(Build::Info).to receive(:gitlab_version).and_return("9.0.0") - allow(Build::Check).to receive(:on_tag?).and_return(true) - stub_is_auto_deploy(false) - - expect(described_class).to receive(:system).with(*%w[git --git-dir=/tmp/gitlab/.git --work-tree=/tmp/gitlab checkout --quiet v9.0.0]) - - Build::QA.checkout_gitlab_rails - end - end - - describe '.get_gitlab_rails_sha' do - it 'returns the correct stable tag' do - allow(Build::Info).to receive(:gitlab_version).and_return("9.0.0") - allow(Build::Check).to receive(:on_tag?).and_return(true) - stub_is_auto_deploy(false) - - expect(Build::QA.get_gitlab_rails_sha).to eq("v9.0.0") - end - - it 'returns the correct auto-deploy commit sha' do - allow(Build::Info).to receive(:gitlab_version).and_return("bebc7c1e290074863e0d2621b3a4c4c7bdb072ae") - allow(Build::Check).to receive(:on_tag?).and_return(true) - stub_is_auto_deploy(true) - - expect(Build::QA.get_gitlab_rails_sha).to eq("bebc7c1e290074863e0d2621b3a4c4c7bdb072ae") - end - end -end diff --git a/spec/gitlab/build_iteration_spec.rb b/spec/gitlab/build_iteration_spec.rb deleted file mode 100644 --- a/spec/gitlab/build_iteration_spec.rb +++ /dev/null @@ -1,71 +0,0 @@ -require 'spec_helper' -require 'gitlab/build_iteration' - -RSpec.describe Gitlab::BuildIteration do - describe :build_iteration do - subject { Gitlab::BuildIteration.new(git_describe) } - - context 'with an invalid git_describe' do - let(:git_describe) { '1.2.3-foo.3' } - - it 'returns 0' do - allow(Build::Check).to receive(:on_tag?).and_return(true) - expect(subject.build_iteration).to eq('0') - end - end - - context 'with a git_describe from master' do - let(:git_describe) { '1.2.3+rc1.ce.2-6-ge5626d5' } - - it 'returns rc1.ce.2' do - allow(Build::Check).to receive(:on_tag?).and_return(true) - expect(subject.build_iteration).to eq('rc1.ce.2') - end - end - - context 'with a proper git_describe' do - let(:git_describe) { '1.2.3+foo.4' } - - it 'returns foo.4' do - allow(Build::Check).to receive(:on_tag?).and_return(true) - expect(subject.build_iteration).to eq('foo.4') - end - end - - context 'with a git_describe with new line char' do - let(:git_describe) { "1.2.3+foo.4\n" } - - it 'returns foo.4' do - allow(Build::Check).to receive(:on_tag?).and_return(true) - expect(subject.build_iteration).to eq('foo.4') - end - end - - context 'with multiple plus signs' do - let(:git_describe) { '1.2.3+foo.4+bar' } - - it 'returns everything after the first plus' do - allow(Build::Check).to receive(:on_tag?).and_return(true) - expect(subject.build_iteration).to eq('foo.4+bar') - end - end - - context 'with an invalid git tag' do - let(:git_describe) { '1.2.3+' } - - it 'returns an empty string' do - allow(Build::Check).to receive(:on_tag?).and_return(true) - expect(subject.build_iteration).to eq('0') - end - end - - context 'not on a git tag' do - subject { Gitlab::BuildIteration.new } - - it 'returns 0' do - allow(Build::Check).to receive(:system).with('git describe --exact-match > /dev/null 2>&1').and_return(false) - expect(subject.build_iteration).to eq('0') - end - end - end -end diff --git a/spec/gitlab/build_spec.rb b/spec/gitlab/build_spec.rb deleted file mode 100644 --- a/spec/gitlab/build_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -require 'spec_helper' -require 'gitlab/build' - -RSpec.describe Build do - describe 'cmd' do - describe 'by default' do - it 'runs build command with log level info' do - expect(described_class.cmd('gitlab')).to eq %w[bundle exec omnibus build gitlab --log-level info] - end - end - - describe 'with different log level' do - it 'runs build command with custom log level' do - stub_env_var('BUILD_LOG_LEVEL', 'debug') - expect(described_class.cmd('gitlab')).to eq %w[bundle exec omnibus build gitlab --log-level debug] - end - end - end -end diff --git a/spec/gitlab/deployer_helper_spec.rb b/spec/gitlab/deployer_helper_spec.rb deleted file mode 100644 --- a/spec/gitlab/deployer_helper_spec.rb +++ /dev/null @@ -1,46 +0,0 @@ -require 'spec_helper' -require 'gitlab/build' -require 'gitlab/deployer_helper' - -RSpec.describe DeployerHelper do - subject(:service) { described_class.new('some-token', 'some-env', 'some-branch') } - describe '#trigger_deploy' do - it 'triggers an auto deploy' do - response = instance_double('response', body: JSON.dump(web_url: 'http://example.com'), status: 201) - allow(Build::Info).to receive(:docker_tag).and_return('some-version') - expect(HTTP) - .to receive(:post) - .with( - "https://ops.gitlab.net/api/v4/projects/135/trigger/pipeline", - form: { - "token" => "some-token", - "ref" => "some-branch", - "variables[DEPLOY_ENVIRONMENT]" => "some-env", - "variables[DEPLOY_VERSION]" => "some-version", - "variables[DEPLOY_USER]" => "deployer" - } - ).and_return(response) - expect(service.trigger_deploy).to eq('http://example.com') - end - - it 'triggers an auto deploy with retries' do - # Set this to zero so there we don't have delays during tests - stub_const('DeployerHelper::TRIGGER_RETRY_INTERVAL', 0) - response = instance_double('response', body: JSON.dump(web_url: 'http://example.com'), status: 401) - allow(Build::Info).to receive(:docker_tag).and_return('some-version') - expect(HTTP) - .to receive(:post) - .with( - "https://ops.gitlab.net/api/v4/projects/135/trigger/pipeline", - form: { - "token" => "some-token", - "ref" => "some-branch", - "variables[DEPLOY_ENVIRONMENT]" => "some-env", - "variables[DEPLOY_VERSION]" => "some-version", - "variables[DEPLOY_USER]" => "deployer" - } - ).and_return(response).exactly(3).times - expect { service.trigger_deploy }.to raise_error(RuntimeError, "Unable to trigger pipeline after 3 retries") - end - end -end diff --git a/spec/gitlab/docker_operations_spec.rb b/spec/gitlab/docker_operations_spec.rb deleted file mode 100644 --- a/spec/gitlab/docker_operations_spec.rb +++ /dev/null @@ -1,105 +0,0 @@ -require 'spec_helper' -require 'gitlab/docker_operations' - -RSpec.describe DockerOperations do - describe '.set_timeout' do - context 'when ENV["DOCKER_TIMEOUT"] is not set' do - it 'uses a default timeout value' do - expect(Docker).to receive(:options=).with(read_timeout: 1200, write_timeout: 1200) - - described_class.set_timeout - end - end - - context 'when ENV["DOCKER_TIMEOUT"] is not set' do - before do - expect(ENV).to receive(:[]).with('DOCKER_TIMEOUT').and_return("42") - end - - it 'uses the given timeout value' do - expect(Docker).to receive(:options=).with(read_timeout: "42", write_timeout: "42") - - described_class.set_timeout - end - end - end - - describe '.build' do - let(:location) { '/tmp/foo' } - let(:image) { 'gitlab-ce' } - let(:tag) { 'latest' } - - it 'uses a default timeout value' do - expect(described_class).to receive(:set_timeout) - expect(Docker::Image).to receive(:build_from_dir).with(location, { t: "#{image}:#{tag}", pull: true }).and_yield(JSON.dump(stream: 'Hello!')) - expect(described_class).to receive(:puts).with('Hello!') - - described_class.build(location.to_sym, image, tag) - end - end - - describe '.authenticate' do - context 'with no arguments' do - it 'calls Docker.authenticate!' do - expect(ENV).to receive(:[]).with('DOCKERHUB_USERNAME').and_return('user') - expect(ENV).to receive(:[]).with('DOCKERHUB_PASSWORD').and_return('pass') - expect(Docker).to receive(:authenticate!).with(username: 'user', password: 'pass', serveraddress: '') - - described_class.authenticate - end - end - - context 'with arguments' do - it 'uses a default timeout value' do - expect(Docker).to receive(:authenticate!).with(username: 'john', password: 'secret', serveraddress: 'registry.com') - - described_class.authenticate('john', 'secret', 'registry.com') - end - end - end - - describe '.get' do - it 'calls Docker::Image.get' do - expect(described_class).to receive(:set_timeout) - expect(Docker::Image).to receive(:get).with('namespace:tag') - - described_class.get('namespace', 'tag') - end - end - - describe '.push' do - it 'calls Docker::Image.push' do - image = double - creds = double - - expect(described_class).to receive(:set_timeout) - expect(described_class).to receive(:get).with('namespace', 'tag').and_return(image) - expect(Docker).to receive(:creds).and_return(creds) - expect(image).to receive(:push).with(creds, repo_tag: 'namespace:tag').and_yield('Hello!') - expect(described_class).to receive(:puts).and_return('Hello!') - - described_class.push('namespace', 'tag') - end - end - - describe '.tag' do - it 'calls Docker::Image.tag' do - image = double - - expect(described_class).to receive(:set_timeout) - expect(described_class).to receive(:get).with('namespace1', 'tag1').and_return(image) - expect(image).to receive(:tag).with(repo: 'namespace2', tag: 'tag2', force: true) - - described_class.tag('namespace1', 'namespace2', 'tag1', 'tag2') - end - end - - describe '.tag_and_push' do - it 'delegates to tag_and_push' do - expect(described_class).to receive(:tag).with('namespace1', 'namespace2', 'tag1', 'tag2') - expect(described_class).to receive(:push).with('namespace2', 'tag2') - - described_class.tag_and_push('namespace1', 'namespace2', 'tag1', 'tag2') - end - end -end diff --git a/spec/gitlab/linker_helper_spec.rb b/spec/gitlab/linker_helper_spec.rb deleted file mode 100644 --- a/spec/gitlab/linker_helper_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -require 'spec_helper' -require 'gitlab/linker_helper' - -RSpec.describe LinkerHelper do - subject(:service) { described_class } - before do - allow(IO).to receive(:popen).and_call_original - allow(IO).to receive(:popen).with(%w[ldconfig -p]).and_return("1 library found\nlibssl.so (libc6,x86-64) => /lib64/libssl.so") - end - - describe "#ldconfig" do - it "should should update linker cache" do - expect(service).to receive(:system).with("ldconfig") - - service.ldconfig - end - - it "should return discovered libraries" do - expect(service.ldconfig).to have_key("libssl.so") - end - end -end diff --git a/spec/gitlab/package_repository_spec.rb b/spec/gitlab/package_repository_spec.rb deleted file mode 100644 --- a/spec/gitlab/package_repository_spec.rb +++ /dev/null @@ -1,265 +0,0 @@ -require 'spec_helper' -require 'gitlab/package_repository' -require 'gitlab/util' - -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 - 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 - 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).to receive(:package_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).to receive(:package_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 - it 'prints a message and aborts' do - expect { repo.upload('my-staging-repository', true) }.to output(%r{User for uploading to package server not specified!\n}).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).to receive(:package_list).and_return(['pkg/el-6/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/scientific/6 pkg/el-6/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/ol/6 pkg/el-6/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/6 pkg/el-6/gitlab-ce.rpm --url=https://packages.gitlab.com\n}).to_stdout - 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 - 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 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 diff --git a/spec/gitlab/tasks/aws_spec.rb b/spec/gitlab/tasks/aws_spec.rb deleted file mode 100644 --- a/spec/gitlab/tasks/aws_spec.rb +++ /dev/null @@ -1,154 +0,0 @@ -require 'spec_helper' - -Struct.new("Image", :image_id, :name, :tags) -Struct.new("Region", :region_name) -Struct.new("Response", :images) -Struct.new("Tag", :key, :value) -Struct.new("DescribeRegionResult", :regions) - -class AwsDummyClass - # Dummy class which mimicks AWS::EC2::Client class from aws-sdk and stubs - # necessary methods - - def describe_images(parameters) - images = if parameters['filters'.to_sym][1][:values] == ["GitLab Community Edition"] - [ - Struct::Image.new("ami-422", "GitLab Community Edition 8.13.2", [Struct::Tag.new("Version", "8.13.2")]) - ] - else - [ - Struct::Image.new("ami-322", "GitLab Enterprise Edition 10.5.4", [Struct::Tag.new("Version", "10.5.4")]) - ] - end - @response = Struct::Response.new(images) - end - - def describe_regions - Struct::DescribeRegionResult.new([Struct::Region.new('us-east-1')]) - end - - def deregister_image(parameters) - true - end -end - -RSpec.describe 'aws:ami:create', type: :rake do - before :all do - Rake.application.rake_require 'gitlab/tasks/aws' - end - - before do - Rake::Task['aws:ami:create'].reenable - allow_any_instance_of(Kernel).to receive(:system).and_return(true) - end - - describe 'on a regular tag' do - before do - allow(Build::Check).to receive(:on_tag?).and_return(true) - allow(Build::Check).to receive(:is_auto_deploy?).and_return(false) - allow(Build::Check).to receive(:is_rc_tag?).and_return(false) - allow(Build::Info).to receive(:deb_package_download_url).and_return('http://example.com') - end - - it 'should identify ce category correctly, if specified' do - allow(Build::Info).to receive(:edition).and_return('ce') - allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') - - expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ce", "http://example.com", ""]) - - Rake::Task['aws:ami:create'].invoke - end - - it 'should identify ce category correctly if nothing is specified' do - allow(Build::Info).to receive(:edition).and_return(nil) - allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') - - expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ce", "http://example.com", ""]) - - Rake::Task['aws:ami:create'].invoke - end - - it 'should identify ee category correctly' do - allow(Build::Info).to receive(:edition).and_return('ee') - allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') - - expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ee", "http://example.com", ""]) - - Rake::Task['aws:ami:create'].invoke - end - - it 'should identify ce arm64 correctly' do - allow(Gitlab::Util).to receive(:get_env).and_call_original - allow(Gitlab::Util).to receive(:get_env).with('AWS_ARCHITECTURE').and_return('arm64') - allow(Build::Info).to receive(:edition).and_return(nil) - allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') - - expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ce-arm64", "http://example.com", ""]) - - Rake::Task['aws:ami:create'].invoke - end - - it 'should identify ee arm64 correctly' do - allow(Gitlab::Util).to receive(:get_env).and_call_original - allow(Gitlab::Util).to receive(:get_env).with('AWS_ARCHITECTURE').and_return('arm64') - allow(Build::Info).to receive(:edition).and_return('ee') - allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') - - expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ee-arm64", "http://example.com", ""]) - - Rake::Task['aws:ami:create'].invoke - end - - it 'should identify ee ultimate category correctly' do - allow(Build::Info).to receive(:edition).and_return('ee') - allow(Gitlab::Util).to receive(:get_env).and_call_original - allow(Gitlab::Util).to receive(:get_env).with("AWS_RELEASE_TYPE").and_return('ultimate') - allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') - - expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ee-ultimate", "http://example.com", "AWS_ULTIMATE_LICENSE_FILE"]) - - Rake::Task['aws:ami:create'].invoke - end - - it 'should identify ee premium category correctly' do - allow(Build::Info).to receive(:edition).and_return('ee') - allow(Gitlab::Util).to receive(:get_env).and_call_original - allow(Gitlab::Util).to receive(:get_env).with("AWS_RELEASE_TYPE").and_return('premium') - allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') - - expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ee-premium", "http://example.com", "AWS_PREMIUM_LICENSE_FILE"]) - - Rake::Task['aws:ami:create'].invoke - end - end - - describe 'on an rc tag' do - before do - allow(Build::Check).to receive(:on_tag?).and_return(true) - allow(Build::Check).to receive(:is_auto_deploy?).and_return(false) - allow(Build::Check).to receive(:is_rc_tag?).and_return(true) - allow(Build::Info).to receive(:deb_package_download_url).and_return('http://example.com') - end - - it 'does not do anything' do - expect(AWSHelper).not_to receive(:new) - - Rake::Task['aws:ami:create'].invoke - end - end - - describe 'on an auto-deploy tag' do - before do - allow(Build::Check).to receive(:on_tag?).and_return(true) - allow(Build::Check).to receive(:is_auto_deploy?).and_return(true) - allow(Build::Check).to receive(:is_rc_tag?).and_return(false) - allow(Build::Info).to receive(:deb_package_download_url).and_return('http://example.com') - end - - it 'does not do anything' do - expect(AWSHelper).not_to receive(:new) - - Rake::Task['aws:ami:create'].invoke - end - end -end diff --git a/spec/gitlab/tasks/docker_tasks_spec.rb b/spec/gitlab/tasks/docker_tasks_spec.rb deleted file mode 100644 --- a/spec/gitlab/tasks/docker_tasks_spec.rb +++ /dev/null @@ -1,119 +0,0 @@ -require 'spec_helper' -require_relative '../../../lib/gitlab/docker_operations.rb' - -RSpec.describe 'docker', type: :rake do - before :all do - Rake.application.rake_require 'gitlab/tasks/docker_tasks' - end - - describe 'docker:build:image' do - before do - Rake::Task['docker:build:image'].reenable - allow(ENV).to receive(:[]).and_call_original - end - - it 'calls build command with correct parameters' do - allow(ENV).to receive(:[]).with('CI_REGISTRY_IMAGE').and_return('dev.gitlab.org:5005/gitlab/omnibus-gitlab') - allow(Build::Info).to receive(:package).and_return('gitlab-ce') - allow(Build::GitlabImage).to receive(:write_release_file).and_return(true) - allow(File).to receive(:expand_path).and_return('/tmp/omnibus-gitlab/lib/gitlab/tasks/docker_tasks.rake') - allow(DockerOperations).to receive(:build).and_call_original - - expect(DockerOperations).to receive(:build).with("/tmp/omnibus-gitlab/docker", "dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ce", "latest") - expect(Docker::Image).to receive(:build_from_dir).with("/tmp/omnibus-gitlab/docker", { t: "dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ce:latest", pull: true }) - Rake::Task['docker:build:image'].invoke - end - end - - describe 'docker:pull:staging' do - before do - Rake::Task['docker:pull:staging'].reenable - allow(ENV).to receive(:[]).and_call_original - end - - it 'pulls in correct image' do - allow(ENV).to receive(:[]).with('CI_REGISTRY_IMAGE').and_return('dev.gitlab.org:5005/gitlab/omnibus-gitlab') - allow(Build::Info).to receive(:package).and_return('gitlab-ce') - allow(Build::Info).to receive(:docker_tag).and_return('9.0.0') - allow(DockerOperations).to receive(:authenticate).and_return(true) - - expect(Docker::Image).to receive(:create).with('fromImage' => 'dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ce:9.0.0') - Rake::Task['docker:pull:staging'].invoke - end - end - - describe 'docker:push' do - let(:dummy_image) { Docker::Image.new(Docker::Connection.new("test", {}), "id" => "test") } - let(:dummy_creds) { { username: "test", password: "test" } } - - before do - Rake::Task['docker:push:staging'].reenable - Rake::Task['docker:push:stable'].reenable - Rake::Task['docker:push:nightly'].reenable - Rake::Task['docker:push:rc'].reenable - Rake::Task['docker:push:latest'].reenable - - allow(ENV).to receive(:[]).and_call_original - allow(ENV).to receive(:[]).with('CI_REGISTRY_IMAGE').and_return('dev.gitlab.org:5005/gitlab/omnibus-gitlab') - allow(Build::Info).to receive(:package).and_return('gitlab-ce') - allow(Build::Info).to receive(:docker_tag).and_return('9.0.0') - allow(DockerOperations).to receive(:authenticate).and_return(true) - allow(Docker::Image).to receive(:get).and_return(dummy_image) - allow(Docker).to receive(:creds).and_return(dummy_creds) - allow(dummy_image).to receive(:tag).and_return(true) - end - - it 'pushes to staging correctly' do - expect(dummy_image).to receive(:push).with(dummy_creds, repo_tag: 'dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ce:9.0.0') - Rake::Task['docker:push:staging'].invoke - end - - it 'pushes nightly images correctly' do - allow(Build::Check).to receive(:is_nightly?).and_return(true) - - expect(dummy_image).to receive(:push).with(dummy_creds, repo_tag: 'gitlab/gitlab-ce:nightly') - Rake::Task['docker:push:nightly'].invoke - end - - it 'pushes latest images correctly' do - allow(Build::Check).to receive(:is_latest_stable_tag?).and_return(true) - - expect(dummy_image).to receive(:push).with(dummy_creds, repo_tag: 'gitlab/gitlab-ce:latest') - Rake::Task['docker:push:latest'].invoke - end - - it 'pushes rc images correctly' do - allow(Build::Check).to receive(:is_latest_tag?).and_return(true) - - expect(dummy_image).to receive(:push).with(dummy_creds, repo_tag: 'gitlab/gitlab-ce:rc') - Rake::Task['docker:push:rc'].invoke - end - - it 'pushes triggered images correctly' do - allow(ENV).to receive(:[]).with('CI_REGISTRY_IMAGE').and_return('registry.gitlab.com/gitlab-org/omnibus-gitlab') - allow(ENV).to receive(:[]).with("IMAGE_TAG").and_return("omnibus-12345") - allow(Build::Info).to receive(:docker_tag).and_call_original - - expect(dummy_image).to receive(:push).with(dummy_creds, repo_tag: 'registry.gitlab.com/gitlab-org/omnibus-gitlab/gitlab-ce:omnibus-12345') - Rake::Task['docker:push:triggered'].invoke - end - end -end - -RSpec.describe 'docker_operations' do - describe 'without docker operations timeout variable' do - it 'sets default value as timeout' do - DockerOperations.set_timeout - expect(Docker.options[:read_timeout]).to eq(1200) - end - end - - describe 'with docker operations timeout variable specified' do - it 'sets provided value as timeout' do - allow(ENV).to receive(:[]).and_call_original - allow(ENV).to receive(:[]).with('DOCKER_TIMEOUT').and_return("500") - DockerOperations.set_timeout - expect(Docker.options[:read_timeout]).to eq("500") - end - end -end diff --git a/spec/gitlab/tasks/license_spec.rb b/spec/gitlab/tasks/license_spec.rb deleted file mode 100644 --- a/spec/gitlab/tasks/license_spec.rb +++ /dev/null @@ -1,151 +0,0 @@ -require 'spec_helper' - -RSpec.describe 'license:check', type: :rake do - let(:f) { double("Mocked file object") } - - before :all do - Rake.application.rake_require 'gitlab/tasks/license' - end - - before do - Rake::Task['license:check'].reenable - allow(File).to receive(:exist?).and_return(true) - allow(File).to receive(:open).and_call_original - allow(File).to receive(:open).with(/pkg.*license-status.json/, "w").and_return(f) - allow(f).to receive(:write).and_return(true) - allow(f).to receive(:close).and_return(true) - allow(Build::Info).to receive(:release_version).and_return("11.5.1+ce.0") - end - - it 'detects good licenses correctly' do - license_info = '[ - { - "name": "chef-zero", - "version": "4.8.0", - "license": "Apache-2.0", - "dependencies": [ - { - "name": "sample", - "version": "1.0.0", - "license": "MIT" - } - ] - } - ]' - allow(File).to receive(:read).and_return(license_info) - - expect { Rake::Task['license:check'].invoke }.to output(/✓.*chef-zero - 4.8.0.*Apache-2.0/).to_stdout - end - - it 'detects blacklisted softwares with good licenses correctly' do - license_info = '[ - { - "name": "readline", - "version": "4.8.0", - "license": "Apache-2.0", - "dependencies": [ - { - "name": "sample", - "version": "1.0.0", - "license": "MIT" - } - ] - } - ]' - allow(File).to receive(:read).and_return(license_info) - - expect { Rake::Task['license:check'].invoke }.to output(/readline.*Blacklisted software/).to_stdout.and raise_error(RuntimeError, "Build Aborted due to license violations") - end - - it 'detects bad licenses correctly' do - license_info = '[ - { - "name": "foo", - "version": "4.8.0", - "license": "GPL-3.0", - "dependencies": [ - { - "name": "sample", - "version": "1.0.0", - "license": "GPL-3.0" - } - ] - } - ]' - - allow(File).to receive(:read).and_return(license_info) - expect { Rake::Task['license:check'].invoke }.to output(/foo.*Unacceptable license/).to_stdout.and raise_error(RuntimeError, "Build Aborted due to license violations") - end - - it 'detects whitelisted softwares with bad licenses correctly' do - license_info = '[ - { - "name": "git", - "version": "4.8.0", - "license": "GPL-3.0", - "dependencies": [ - { - "name": "sample", - "version": "1.0.0", - "license": "LGPL" - } - ] - } - ]' - allow(File).to receive(:read).and_return(license_info) - - expect { Rake::Task['license:check'].invoke }.to output(/git.*Whitelisted software/).to_stdout - end - - it 'detects blacklisted softwares with unknown licenses correctly' do - license_info = '[ - { - "name": "readline", - "version": "4.8.0", - "license": "jargon", - "dependencies": [ - { - "name": "sample", - "version": "1.0.0", - "license": "MIT" - } - ] - } - ]' - allow(File).to receive(:read).and_return(license_info) - - expect { Rake::Task['license:check'].invoke }.to output(/readline.*Blacklisted software/).to_stdout.and raise_error(RuntimeError, "Build Aborted due to license violations") - end - - it 'detects whitelisted software with unknown licenses correctly' do - license_info = '[ - { - "name": "git", - "version": "4.8.0", - "license": "jargon", - "dependencies": [ - { - "name": "sample", - "version": "1.0.0", - "license": "MIT" - } - ] - } - ]' - allow(File).to receive(:read).and_return(license_info) - expect { Rake::Task['license:check'].invoke }.to output(/git.*Whitelisted software/).to_stdout - end - - it 'should detect if install directory not found' do - allow(File).to receive(:read).and_return('install_dir /opt/gitlab') - allow(File).to receive(:exist?).with('/opt/gitlab').and_return(false) - expect { Rake::Task['license:check'].invoke }.to raise_error(StandardError, "Unable to retrieve install_dir, thus unable to check /opt/gitlab/dependency_licenses.json") - end - - it 'should detect if dependency_license.json file not found' do - allow(File).to receive(:read).and_return('install_dir /opt/gitlab') - allow(File).to receive(:exist?).with('/opt/gitlab').and_return(true) - allow(File).to receive(:exist?).with('/opt/gitlab/dependency_licenses.json').and_return(false) - expect { Rake::Task['license:check'].invoke }.to raise_error(StandardError, "Unable to open /opt/gitlab/dependency_licenses.json") - end -end diff --git a/spec/gitlab/tasks/qa_spec.rb b/spec/gitlab/tasks/qa_spec.rb deleted file mode 100644 --- a/spec/gitlab/tasks/qa_spec.rb +++ /dev/null @@ -1,110 +0,0 @@ -require 'spec_helper' - -RSpec.describe 'qa', type: :rake do - let(:gitlab_registry_image_address) { 'dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ce-qa' } - let(:gitlab_version) { '10.2.0' } - let(:commit_sha) { 'abcd1234' } - let(:image_tag) { 'omnibus-12345' } - let(:version_manifest) { { "software": { "gitlab-rails": { "locked_version": "123445" } } } } - - before(:all) do - Rake.application.rake_require 'gitlab/tasks/qa' - end - - describe 'qa:build' do - let(:repo_path) { "/tmp/gitlab" } - before do - Rake::Task['qa:build'].reenable - - allow(Build::QA).to receive(:get_gitlab_repo).and_return(repo_path) - allow(Build::QA).to receive(:gitlab_repo).and_return(repo_path) - allow(Build::QAImage).to receive(:gitlab_registry_image_address).and_return(gitlab_registry_image_address) - allow(JSON).to receive(:parse).and_return(version_manifest) - end - - it 'calls build method with correct parameters' do - expect(DockerOperations).to receive(:build).with(repo_path, 'dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ce-qa', 'latest', dockerfile: "qa/Dockerfile") - - Rake::Task['qa:build'].invoke - end - end - - describe 'qa:push' do - before do - Rake::Task['qa:push:stable'].reenable - Rake::Task['qa:push:nightly'].reenable - Rake::Task['qa:push:rc'].reenable - Rake::Task['qa:push:latest'].reenable - - allow(Build::Info).to receive(:gitlab_version).and_return(gitlab_version) - end - - it 'pushes stable images correctly' do - expect(Build::QAImage).to receive(:tag_and_push_to_gitlab_registry).with(gitlab_version) - expect(Build::QAImage).to receive(:tag_and_push_to_dockerhub).with(gitlab_version, initial_tag: 'latest') - - Rake::Task['qa:push:stable'].invoke - end - - it 'pushes nightly images correctly' do - expect(Build::Check).to receive(:is_nightly?).and_return(true) - - expect(Build::QAImage).to receive(:tag_and_push_to_dockerhub).with('nightly', initial_tag: 'latest') - - Rake::Task['qa:push:nightly'].invoke - end - - it 'pushes latest images correctly' do - expect(Build::Check).to receive(:is_latest_stable_tag?).and_return(true) - - expect(Build::QAImage).to receive(:tag_and_push_to_dockerhub).with('latest', initial_tag: 'latest') - - Rake::Task['qa:push:latest'].invoke - end - - it 'pushes rc images correctly' do - expect(Build::Check).to receive(:is_latest_tag?).and_return(true) - - expect(Build::QAImage).to receive(:tag_and_push_to_dockerhub).with('rc', initial_tag: 'latest') - - Rake::Task['qa:push:rc'].invoke - end - - it 'pushes triggered images correctly' do - allow(ENV).to receive(:[]).with('CI').and_return('true') - expect(ENV).to receive(:[]).with('IMAGE_TAG').and_return(image_tag) - - expect(Build::QAImage).to receive(:tag_and_push_to_gitlab_registry).with(image_tag) - - Rake::Task['qa:push:triggered'].invoke - end - - describe ':staging' do - before do - Rake::Task['qa:push:staging'].reenable - - allow(Build::Info).to receive(:gitlab_version).and_return(gitlab_version) - allow(Build::Info).to receive(:commit_sha).and_return(commit_sha) - end - - it 'pushes staging images correctly' do - stub_is_auto_deploy(false) - expect(Build::QAImage).to receive(:tag_and_push_to_gitlab_registry).with(gitlab_version) - expect(Build::QAImage).to receive(:tag_and_push_to_gitlab_registry).with(commit_sha) - - Rake::Task['qa:push:staging'].invoke - end - - it 'pushes staging auto-deploy images correctly' do - allow(ENV).to receive(:[]).with('CI').and_return('true') - allow(ENV).to receive(:[]).with('CI_COMMIT_TAG').and_return('12.0.12345+5159f2949cb.59c9fa631') - allow(Build::Info).to receive(:current_git_tag).and_return('12.0.12345+5159f2949cb.59c9fa631') - - expect(Build::QAImage).to receive(:tag_and_push_to_gitlab_registry).with('12.0-5159f2949cb') - expect(Build::QAImage).to receive(:tag_and_push_to_gitlab_registry).with(commit_sha) - - Rake::Task['qa:push:staging'].invoke - end - end - end -end diff --git a/spec/gitlab/util_spec.rb b/spec/gitlab/util_spec.rb deleted file mode 100644 --- a/spec/gitlab/util_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -require 'spec_helper' -require 'gitlab/util' - -RSpec.describe Gitlab::Util do - describe :get_env do - it 'strips value of env variable correctly' do - allow(ENV).to receive(:[]).with('foo').and_return(' bar ') - - expect(Gitlab::Util.get_env('foo')).to eq('bar') - end - - it 'does not fail if env variable is nil' do - allow(ENV).to receive(:[]).with('foo').and_return(nil) - - expect { Gitlab::Util.get_env('foo') }.not_to raise_error - expect(Gitlab::Util.get_env('foo')).to eq(nil) - end - end - - describe :set_env do - it 'strips value before setting env variable' do - Gitlab::Util.set_env('foo', ' blahblah ') - expect(ENV['foo']).to eq('blahblah') - end - - it 'does not fail if value is nil' do - expect { Gitlab::Util.set_env('foo', nil) }.not_to raise_error - expect(ENV['foo']).to eq(nil) - end - end - - describe :set_env_if_missing do - it 'does not override existing value' do - allow(ENV).to receive(:[]).with('foo').and_return('lorem') - - Gitlab::Util.set_env_if_missing('foo', 'ipsum') - expect(ENV['foo']).to eq('lorem') - end - - it 'sets value if env variable is mising' do - Gitlab::Util.set_env_if_missing('foo', 'ipsum') - expect(ENV['foo']).to eq('ipsum') - end - - it 'does not fail if value is nil' do - expect { Gitlab::Util.set_env_if_missing('bar', nil) }.not_to raise_error - expect(ENV['bar']).to eq(nil) - end - end -end diff --git a/spec/gitlab/version_spec.rb b/spec/gitlab/version_spec.rb deleted file mode 100644 --- a/spec/gitlab/version_spec.rb +++ /dev/null @@ -1,318 +0,0 @@ -require 'spec_helper' -require 'gitlab/version' - -RSpec.describe Gitlab::Version do - before do - allow(ENV).to receive(:[]).and_call_original - stub_env_var('GITLAB_ALTERNATIVE_REPO', nil) - stub_env_var('ALTERNATIVE_PRIVATE_TOKEN', nil) - end - - describe '.sources_channel' do - subject { described_class } - using RSpec::Parameterized::TableSyntax - where(:alternative_sources, :security_sources, :source_channel) do - nil | nil | "alternative" - nil | 'true' | "security" - nil | 'false' | "alternative" - 'true' | nil | "alternative" - 'true' | 'true' | "security" - 'true' | 'false' | "alternative" - 'false' | nil | "remote" - 'false' | 'true' | "security" - 'false' | 'false' | "remote" - end - - with_them do - before do - stub_env_var('ALTERNATIVE_SOURCES', alternative_sources) - stub_env_var('SECURITY_SOURCES', security_sources) - end - - context 'when checking the source channel environment variables' do - it 'uses the correct source channel' do - expect(subject.sources_channel).to eq(source_channel) - end - end - end - end - - describe '.fallback_sources_channel' do - subject { described_class } - - context 'with ALTERNATIVE_SOURCES=true' do - it 'returns "alternative"' do - stub_env_var('ALTERNATIVE_SOURCES', 'true') - - expect(subject.fallback_sources_channel).to eq('alternative') - end - end - - context 'with ALTERNATIVE_SOURCES not set true' do - it 'returns "remote"' do - stub_env_var('ALTERNATIVE_SOURCES', 'false') - - expect(subject.fallback_sources_channel).to eq('remote') - end - end - end - - describe '.security_channel?' do - subject { described_class } - - it 'returns true when sources_channel is set for security' do - mock_sources_channel('security') - - expect(subject.security_channel?).to be_truthy - end - - it 'returns false when sources_channel is not set for security' do - mock_sources_channel - - expect(subject.security_channel?).to be_falsey - end - end - - describe :remote do - subject { Gitlab::Version.new(software) } - - context 'with a valid software name' do - let(:software) { 'gitlab-rails-ee' } - - it 'returns a link from custom_sources yml' do - mock_sources_channel - - expect(subject.remote).to eq('git@dev.gitlab.org:gitlab/gitlab-ee.git') - end - end - - context 'with an invalid software name' do - let(:software) { 'not a valid software' } - - it 'outputs an empty string' do - expect(subject.remote).to eq('') - end - end - - context 'with default fallback' do - let(:software) { 'gitlab-rails-ee' } - - it 'returns "remote" link from custom_sources yml' do - mock_sources_channel - - expect(subject.remote).to eq('git@dev.gitlab.org:gitlab/gitlab-ee.git') - end - end - - context 'with alternative fallback' do - let(:software) { 'gitlab-rails-ee' } - - it 'returns "alternative" link from custom_sources yml' do - mock_sources_channel('alternative') - - expect(subject.remote).to eq('https://gitlab.com/gitlab-org/gitlab.git') - end - end - - context 'with alternative env override' do - let(:software) { 'gitlab-rails-ee' } - - it 'returns "alternative" link from the environment whenever present' do - stub_env_var('GITLAB_ALTERNATIVE_REPO', 'https://gitlab.example.com/gitlab.git') - - expect(subject.remote).to eq('https://gitlab.example.com/gitlab.git') - end - - it 'attaches credentials to alternative env links when present' do - stub_env_var('GITLAB_ALTERNATIVE_REPO', 'https://gitlab.example.com/gitlab.git') - stub_env_var('ALTERNATIVE_PRIVATE_TOKEN', 'APT') - - expect(subject.remote).to eq('https://gitlab-ci-token:APT@gitlab.example.com/gitlab.git') - end - end - - context 'with security source channel selected' do - before do - stub_env_var('CI_JOB_TOKEN', 'CJT') - mock_sources_channel('security') - end - - context 'when security source is defined for the software' do - let(:software) { 'gitlab-rails-ee' } - - it 'returns "security" link attached with credential from custom_sources yml' do - expect(subject.remote).to eq('https://gitlab-ci-token:CJT@gitlab.com/gitlab-org/security/gitlab.git') - end - - context 'when "security" link is in not URI compliant' do - before do - allow(YAML).to receive(:load_file) - .and_return(software => { "security" => "git@dev.gitlab.org:gitlab/gitlab-ee.git" }) - end - - it 'returns "security" link without attaching credential' do - expect(subject.remote).to eq("git@dev.gitlab.org:gitlab/gitlab-ee.git") - end - end - end - - context 'when security source is not defined for the software' do - let(:software) { 'prometheus' } - - it 'returns "remote" link from custom_sources yml' do - mock_fallback_channel - - expect(subject.remote).to eq('git@dev.gitlab.org:omnibus-mirror/prometheus.git') - end - - it 'returns expected link from custom_sources yml when asked for a specific remote' do - mock_fallback_channel - - expect(subject.remote('alternative')).to eq('https://gitlab.com/gitlab-org/build/omnibus-mirror/prometheus.git') - end - - context 'with alternative fallback' do - it 'returns "alternative" link from custom_sources yml' do - mock_fallback_channel('alternative') - - expect(subject.remote).to eq('https://gitlab.com/gitlab-org/build/omnibus-mirror/prometheus.git') - end - end - end - end - end - - describe :print do - subject { Gitlab::Version.new(software, version) } - - context 'with a valid software name and version' do - let(:software) { 'gitlab-rails' } - let(:version) { '12.34.567' } - - it 'returns correct version with v appended' do - expect(subject.print).to eq('v12.34.567') - end - end - - context 'with a valid software name and version' do - let(:software) { 'gitlab-rails-ee' } - let(:version) { '12.34.567-ee' } - - it 'returns correct version with v appended' do - expect(subject.print).to eq('v12.34.567-ee') - end - end - - context 'with a valid software name and no version' do - let(:software) { 'ruby' } - let(:version) { nil } - - it 'outputs an empty string' do - expect(subject.print).to eq(nil) - end - end - - context 'with a valid software name and a version' do - let(:software) { 'ruby' } - let(:version) { '2.3.1' } - - it 'adds a v prefix' do - expect(subject.print).to eq("v2.3.1") - end - - it 'does not add a v prefix if explicitly set' do - expect(subject.print(false)).to eq("2.3.1") - end - end - - context 'with a valid software name and a branch name' do - let(:software) { 'gitlab-rails' } - let(:version) { '9-0-stable' } - - it 'does not add a v prefix' do - expect(subject.print).to eq("9-0-stable") - end - end - - context 'with a valid software name and a branch name' do - let(:software) { 'gitlab-rails' } - let(:version) { 'master' } - - it 'does not add a v prefix' do - expect(subject.print).to eq("master") - end - end - - context 'with a valid software name and an rc tag ' do - let(:software) { 'gitlab-rails' } - let(:version) { '9.1.0-rc1' } - - it 'add a v prefix' do - expect(subject.print).to eq("v9.1.0-rc1") - end - end - - context 'with a valid software name and an rc tag ' do - let(:software) { 'gitlab-rails' } - let(:version) { '9.1.0-rc2-ee' } - - it 'add a v prefix' do - expect(subject.print).to eq("v9.1.0-rc2-ee") - end - end - - context 'with a valid software name and a branch name' do - let(:software) { 'gitlab-rails' } - let(:version) { '9.1.0-fix' } - - it 'does not add a v prefix' do - expect(subject.print).to eq("9.1.0-fix") - end - end - - context 'with a valid software name and a branch name' do - let(:software) { 'gitlab-rails' } - let(:version) { 'fix-9.1.0' } - - it 'does not add a v prefix' do - expect(subject.print).to eq("fix-9.1.0") - end - end - - context 'with a valid software name and a commit sha' do - let(:software) { 'gitlab-rails' } - let(:version) { '1076385cb57a03fa254be5604f6c6ceb6e39987f' } - - it 'does not add a v prefix' do - expect(subject.print).to eq("1076385cb57a03fa254be5604f6c6ceb6e39987f") - end - end - end - - describe :version do - subject { Gitlab::Version.new(software) } - - context 'env variable for setting version' do - let(:software) { 'gitlab-rails' } - - it 'identifies correct version from env variable' do - stub_env_var('GITLAB_VERSION', '5.6.7') - allow(File).to receive(:read).and_return("1.2.3") - expect(subject.print).to eq("v5.6.7") - end - - it 'falls back to VERSION file if env variable not found' do - allow(File).to receive(:read).and_return("1.2.3") - expect(subject.print).to eq("v1.2.3") - end - end - end - - def mock_sources_channel(channel = 'remote') - allow(::Gitlab::Version).to receive(:sources_channel).and_return(channel) - end - - def mock_fallback_channel(channel = 'remote') - allow(::Gitlab::Version).to receive(:fallback_sources_channel).and_return(channel) - end -end diff --git a/spec/lib/gitlab/build/check_spec.rb b/spec/lib/gitlab/build/check_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/build/check_spec.rb @@ -0,0 +1,171 @@ +require 'spec_helper' +require 'gitlab/build/check' + +RSpec.describe Build::Check do + before do + stub_default_package_version + end + + describe 'is_ee?' do + describe 'with environment variables' do + before do + stub_is_ee_version(false) + end + + describe 'ee variable' do + it 'when ee=true' do + stub_is_ee_env(true) + expect(described_class.is_ee?).to be_truthy + end + + it 'when ee=false' do + stub_is_ee(false) + expect(described_class.is_ee?).to be_falsy + end + + it 'when env variable is not set' do + stub_is_ee_version(false) + stub_is_auto_deploy(false) + expect(described_class.is_ee?).to be_falsy + end + end + + describe 'GITLAB_VERSION variable' do + it 'when GITLAB_VERSION ends with -ee' do + stub_env_var('GITLAB_VERSION', 'foo-ee') + expect(described_class.is_ee?).to be_truthy + end + + it 'when GITLAB_VERSION does not end with -ee' do + stub_env_var('GITLAB_VERSION', 'foo') + stub_is_auto_deploy(false) + expect(described_class.is_ee?).to be_falsy + end + + it 'ee variable wins over GITLAB_VERSION variable' do + stub_is_ee_env(true) + stub_env_var('GITLAB_VERSION', 'foo') + expect(described_class.is_ee?).to be_truthy + end + end + end + + describe 'without environment variables' do + it 'checks the VERSION file' do + stub_is_ee_version(false) + stub_env_var('GITLAB_VERSION', 'foo-ee') + expect(described_class.is_ee?).to be_truthy + end + + it 'GITLAB_VERSION variable wins over the file' do + stub_env_var('GITLAB_VERSION', 'foo-ee') + expect(described_class.is_ee?).to be_truthy + end + end + end + + describe 'include_ee?' do + it 'returns true when is_ee? is true' do + allow(described_class).to receive(:is_ee?).and_return(true) + expect(described_class.include_ee?).to be_truthy + end + + it 'returns false when we are building a ce package' do + allow(described_class).to receive(:is_ee?).and_return(false) + expect(described_class.include_ee?).to be_falsey + end + end + + describe 'add tag methods' do + describe 'is_nightly?' do + it 'returns true if it is a nightly build' do + stub_env_var('NIGHTLY', 'true') + expect(described_class.is_nightly?).to be_truthy + end + + it 'returns false if it is not a nightly build' do + expect(described_class.is_nightly?).to be_falsey + end + end + + describe 'is_latest_tag?' do + it 'returns true if it is an rc release' do + # This will be the case if latest_tag is eg. 9.3.0+rc6.ce.0 + # or 9.3.0+ce.0 + allow(Build::Info).to receive(:latest_tag).and_return('9.3.0+rc6.ce.0') # This line only is only an example, stubbing is not needed. + allow(described_class).to receive(:match_tag?).and_return(true) + expect(described_class.is_latest_tag?).to be_truthy + end + + it 'returns true if it is not an rc release' do + allow(Build::Info).to receive(:latest_tag).and_return('9.3.0+ce.0') # This line only is only an example, stubbing is not needed. + allow(described_class).to receive(:match_tag?).and_return(false) + expect(described_class.is_latest_tag?).to be_falsey + end + end + + describe 'is_latest_stable_tag?' do + it 'returns true if it is a stable release' do + # This will be the case if latest_tag is eg. 9.3.0+ce.0 + # It will not be the case if the tag is 9.3.0+rc6.ce.0 + allow(Build::Info).to receive(:latest_stable_tag).and_return('9.3.0+ce.0') # This line only is only an example, stubbing is not needed. + allow(described_class).to receive(:match_tag?).and_return(true) + expect(described_class.is_latest_stable_tag?).to be_truthy + end + + it 'returns true if it is not a stable release' do + allow(Build::Info).to receive(:latest_stable_tag).and_return('9.3.0+rc6.ce.0') # This line only is only an example, stubbing is not needed. + allow(described_class).to receive(:match_tag?).and_return(false) + expect(described_class.is_latest_stable_tag?).to be_falsey + end + end + end + + describe '.is_patch_release?' do + it 'returns true for patch release' do + allow(Build::Info).to receive(:semver_version).and_return("10.0.3") + expect(described_class.is_patch_release?).to be_truthy + end + + it 'returns false for major/minor release' do + allow(Build::Info).to receive(:semver_version).and_return("10.0.0") + expect(described_class.is_patch_release?).to be_falsey + end + end + + describe 'is_rc_tag?' do + it 'returns true if it looks like an rc tag' do + # It will be the case if the tag is 9.3.0+rc6.ce.0 + allow(Build::Info).to receive(:current_git_tag).and_return('9.3.0+rc6.ce.0') + expect(described_class.is_rc_tag?).to be_truthy + end + it 'returns false if it does not look like an rc tag' do + # This not be the case if tag is eg. 9.3.0+ce.0 + allow(Build::Info).to receive(:current_git_tag).and_return('9.3.0+ce.0') + expect(described_class.is_rc_tag?).to be_falsey + end + end + + describe 'is_auto_deploy?' do + it 'returns true if it looks like an auto-deploy tag' do + # This is the case if the tag is 11.10.12345+5159f2949cb.59c9fa631 + allow(Build::Info).to receive(:current_git_tag).and_return('11.10.12345+5159f2949cb.59c9fa631') + expect(described_class.is_auto_deploy?).to be_truthy + end + + it 'returns false if it does not look like an auto-deploy tag' do + # This not be the case if ag is eg. 9.3.0+ce.0 + allow(Gitlab::Util).to receive(:get_env).with('CI_COMMIT_REF_NAME').and_return('a-random-branch') + + allow(Build::Info).to receive(:current_git_tag).and_return('9.3.0+ce.0') + expect(described_class.is_auto_deploy?).to be_falsey + end + end + + describe 'ci_commit_tag?' do + it 'checks for the CI_COMMIT_TAG' do + allow(Gitlab::Util).to receive(:get_env).with('CI_COMMIT_TAG').and_return('11.10.12345+5159f2949cb.59c9fa631') + expect(described_class.ci_commit_tag?).to be_truthy + end + end +end diff --git a/spec/lib/gitlab/build/facts_spec.rb b/spec/lib/gitlab/build/facts_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/build/facts_spec.rb @@ -0,0 +1,96 @@ +require 'spec_helper' +require 'gitlab/build/facts' +require 'gitlab/build/gitlab_image' + +RSpec.describe Build::Facts do + before do + allow(ENV).to receive(:[]).and_call_original + end + + describe '.generate' do + it 'calls necessary methods' do + expect(described_class).to receive(:generate_tag_files) + expect(described_class).to receive(:generate_env_file) + + described_class.generate + end + end + + describe '.generate_tag_files' do + before do + allow(Build::Info).to receive(:latest_stable_tag).and_return('14.6.2+ce.0') + allow(Build::Info).to receive(:latest_tag).and_return('14.7.0+rc42.ce.0') + end + + it 'writes tag details to file' do + expect(File).to receive(:write).with('build_facts/latest_stable_tag', '14.6.2+ce.0') + expect(File).to receive(:write).with('build_facts/latest_tag', '14.7.0+rc42.ce.0') + + described_class.generate_tag_files + end + end + + describe '.generate_env_file' do + before do + allow(described_class).to receive(:common_vars).and_return(%w[TOP_UPSTREAM_SOURCE_PROJECT=gitlab-org/gitlab]) + allow(described_class).to receive(:qa_trigger_vars).and_return(%w[QA_RELEASE=foobar]) + allow(described_class).to receive(:version_vars).and_return(%w[GITLAB_VERSION=randombranch]) + end + + it 'writes environment variables to file' do + expect(File).to receive(:write).with('build_facts/env_vars', "TOP_UPSTREAM_SOURCE_PROJECT=gitlab-org/gitlab\nQA_RELEASE=foobar\nGITLAB_VERSION=randombranch") + + described_class.generate_env_file + end + end + + describe '.common_vars' do + before do + stub_env_var('TOP_UPSTREAM_SOURCE_PROJECT', 'gitlab-org/gitlab') + stub_env_var('TOP_UPSTREAM_SOURCE_REF', 'master') + stub_env_var('TOP_UPSTREAM_SOURCE_JOB', '123456') + stub_env_var('TOP_UPSTREAM_SOURCE_SHA', 'aq2456fs') + stub_env_var('TOP_UPSTREAM_MERGE_REQUEST_PROJECT_ID', '55555') + stub_env_var('TOP_UPSTREAM_MERGE_REQUEST_IID', '7689') + end + + it 'returns correct variables' do + result = %w[ + TOP_UPSTREAM_SOURCE_PROJECT=gitlab-org/gitlab + TOP_UPSTREAM_SOURCE_REF=master + TOP_UPSTREAM_SOURCE_JOB=123456 + TOP_UPSTREAM_SOURCE_SHA=aq2456fs + TOP_UPSTREAM_MERGE_REQUEST_PROJECT_ID=55555 + TOP_UPSTREAM_MERGE_REQUEST_IID=7689 + ] + + expect(described_class.common_vars).to eq(result) + end + end + + describe '.qa_trigger_vars' do + before do + allow(described_class).to receive(:generate_knapsack_report?).and_return('true') + allow(Build::GitlabImage).to receive(:gitlab_registry_image_address).and_return('registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:14.6.2-rfbranch.450066356.c97110ad-0') + + stub_env_var('QA_IMAGE', 'gitlab/gitlab-ee-qa:nightly') + stub_env_var('QA_TESTS', '') + stub_env_var('ALLURE_JOB_NAME', '') + stub_env_var('GITLAB_QA_OPTIONS', '') + end + + it 'returns correct variables' do + result = %w[ + QA_BRANCH=master + QA_RELEASE=registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:14.6.2-rfbranch.450066356.c97110ad-0 + QA_IMAGE=gitlab/gitlab-ee-qa:nightly + QA_TESTS= + ALLURE_JOB_NAME= + GITLAB_QA_OPTIONS= + KNAPSACK_GENERATE_REPORT=true + ] + + expect(described_class.qa_trigger_vars).to eq(result) + end + end +end diff --git a/spec/lib/gitlab/build/gitlab_image_spec.rb b/spec/lib/gitlab/build/gitlab_image_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/build/gitlab_image_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' +require 'gitlab/build/gitlab_image' + +RSpec.describe Build::GitlabImage do + before do + allow(Build::Info).to receive(:package).and_return('gitlab-ce') + end + + describe '.dockerhub_image_name' do + it 'returns a correct image name' do + expect(described_class.dockerhub_image_name).to eq('gitlab/gitlab-ce') + end + end + + describe '.gitlab_registry_image_name' do + it 'returns a correct image name' do + expect(described_class.gitlab_registry_image_name).to eq('gitlab-ce') + end + end +end diff --git a/spec/lib/gitlab/build/image_spec.rb b/spec/lib/gitlab/build/image_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/build/image_spec.rb @@ -0,0 +1,163 @@ +require 'spec_helper' +require 'gitlab/build/image' + +RSpec.describe Build::Image do + ComponentImage = Class.new do + extend Build::Image + + def self.gitlab_registry_image_name + 'my-project/my-image' + end + + def self.dockerhub_image_name + 'my-image' + end + end + + before do + allow(ENV).to receive(:[]).and_call_original + allow(ENV).to receive(:[]).with('CI_JOB_TOKEN').and_return('1234') + allow(ENV).to receive(:[]).with('CI_REGISTRY').and_return('registry.com') + allow(ENV).to receive(:[]).with('CI_REGISTRY_IMAGE').and_return('registry.com/group/repo') + allow(ENV).to receive(:[]).with('DOCKERHUB_USERNAME').and_return('john') + allow(ENV).to receive(:[]).with('DOCKERHUB_PASSWORD').and_return('secret') + allow(Build::Info).to receive(:docker_tag).and_return('9.0.0') + end + + describe '.pull' do + it 'creates an image from the local one' do + expect(Docker::Image).to receive(:create).with( + 'fromImage' => "#{ComponentImage.gitlab_registry_image_address}:9.0.0" + ) + + ComponentImage.pull + end + end + + describe '.gitlab_registry_image_address' do + it 'returns a correct image name' do + expect(ComponentImage.gitlab_registry_image_address).to eq('registry.com/group/repo/my-project/my-image') + end + + context 'with a tag given' do + it 'returns a correct image name' do + expect(ComponentImage.gitlab_registry_image_address(tag: 'mytag')).to eq('registry.com/group/repo/my-project/my-image:mytag') + end + end + end + + describe '.tag_and_push_to_gitlab_registry' do + it 'calls DockerOperations.authenticate and DockerOperations.tag_and_push' do + expect(DockerOperations).to receive(:authenticate).with('gitlab-ci-token', '1234', 'registry.com') + expect(DockerOperations).to receive(:tag_and_push).with( + ComponentImage.gitlab_registry_image_address, + ComponentImage.gitlab_registry_image_address, + 'latest', + 'foo' + ) + + ComponentImage.tag_and_push_to_gitlab_registry('foo') + end + end + + describe '.tag_and_push_to_dockerhub' do + it 'calls DockerOperations.authenticate and DockerOperations.tag_and_push' do + expect(DockerOperations).to receive(:authenticate).with('john', 'secret') + expect(DockerOperations).to receive(:tag_and_push).with( + ComponentImage.gitlab_registry_image_address, + ComponentImage.dockerhub_image_name, + '9.0.0', + 'foo' + ) + + ComponentImage.tag_and_push_to_dockerhub('foo') + end + + context 'with a initial_tag given' do + it 'calls DockerOperations.authenticate and DockerOperations.tag_and_push' do + expect(DockerOperations).to receive(:authenticate).with('john', 'secret') + expect(DockerOperations).to receive(:tag_and_push).with( + ComponentImage.gitlab_registry_image_address, + ComponentImage.dockerhub_image_name, + 'latest', + 'foo' + ) + + ComponentImage.tag_and_push_to_dockerhub('foo', initial_tag: 'latest') + end + end + end + + describe '.write_release_file' do + describe 'with triggered build' do + let(:release_file) do + [ + "PACKAGECLOUD_REPO=download-package", + "RELEASE_VERSION=12.121.12-ce.1", + "DOWNLOAD_URL=https://gitlab.com/api/v4/projects/1/jobs/1/artifacts/pkg/ubuntu-focal/gitlab.deb", + "TRIGGER_PRIVATE_TOKEN=NOT-PRIVATE-TOKEN\n" + ] + end + + before do + stub_env_var('PACKAGECLOUD_REPO', 'download-package') + stub_env_var('TRIGGER_PRIVATE_TOKEN', 'NOT-PRIVATE-TOKEN') + stub_env_var('CI_PROJECT_ID', '1') + stub_env_var('CI_PIPELINE_ID', '2') + allow(Build::Info).to receive(:release_version).and_return('12.121.12-ce.1') + allow(Build::Info).to receive(:fetch_artifact_url).with('1', '2').and_return('1') + end + + describe 'for CE' do + before do + allow(Build::Info).to receive(:package).and_return('gitlab-ce') + end + + it 'returns build version and iteration with env variable' do + release_file_content = release_file.insert(1, 'RELEASE_PACKAGE=gitlab-ce').join("\n") + + expect(ComponentImage.write_release_file).to eq(release_file_content) + end + end + + describe 'for EE' do + before do + allow(Build::Info).to receive(:package).and_return('gitlab-ee') + end + + it 'returns build version and iteration with env variable' do + release_file_content = release_file.insert(1, 'RELEASE_PACKAGE=gitlab-ee').join("\n") + + expect(ComponentImage.write_release_file).to eq(release_file_content) + end + end + + describe 'with regular build' do + let(:s3_download_link) { 'https://downloads-packages.s3.amazonaws.com/ubuntu-focal/gitlab-ee_12.121.12-ce.1_amd64.deb' } + + let(:release_file) do + [ + "RELEASE_VERSION=12.121.12-ce.1", + "DOWNLOAD_URL=#{s3_download_link}\n", + ] + end + + before do + stub_env_var('PACKAGECLOUD_REPO', '') + stub_env_var('TRIGGER_PRIVATE_TOKEN', '') + stub_env_var('CI_PROJECT_ID', '') + stub_env_var('CI_PIPELINE_ID', '') + allow(Build::Check).to receive(:on_tag?).and_return(true) + allow(Build::Info).to receive(:package).and_return('gitlab-ee') + allow(ComponentImage).to receive(:release_version).and_return('12.121.12-ce.1') + end + + it 'returns build version and iteration with env variable' do + release_file_content = release_file.insert(0, 'RELEASE_PACKAGE=gitlab-ee').join("\n") + + expect(ComponentImage.write_release_file).to eq(release_file_content) + end + end + end + end +end diff --git a/spec/lib/gitlab/build/info_spec.rb b/spec/lib/gitlab/build/info_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/build/info_spec.rb @@ -0,0 +1,277 @@ +require 'spec_helper' +require 'gitlab/build/info' +require 'gitlab/build/gitlab_image' + +RSpec.describe Build::Info do + before do + stub_default_package_version + stub_env_var('GITLAB_ALTERNATIVE_REPO', nil) + stub_env_var('ALTERNATIVE_PRIVATE_TOKEN', nil) + end + + describe '.package' do + describe 'shows EE' do + it 'when ee=true' do + stub_is_ee_env(true) + expect(described_class.package).to eq('gitlab-ee') + end + + it 'when env var is not present, checks VERSION file' do + stub_is_ee_version(true) + expect(described_class.package).to eq('gitlab-ee') + end + end + + describe 'shows CE' do + it 'by default' do + stub_is_ee(false) + expect(described_class.package).to eq('gitlab-ce') + end + end + end + + describe '.release_version' do + before do + allow(Build::Check).to receive(:on_tag?).and_return(true) + allow_any_instance_of(Omnibus::BuildVersion).to receive(:semver).and_return('12.121.12') + allow_any_instance_of(Gitlab::BuildIteration).to receive(:build_iteration).and_return('ce.1') + end + + it 'returns build version and iteration' do + expect(described_class.release_version).to eq('12.121.12-ce.1') + end + + it 'defaults to an initial build version when there are no matching tags' do + allow(Build::Check).to receive(:on_tag?).and_return(false) + allow(Build::Check).to receive(:is_nightly?).and_return(false) + allow(Build::Info).to receive(:latest_tag).and_return('') + allow(Build::Info).to receive(:commit_sha).and_return('ffffffff') + stub_env_var('CI_PIPELINE_ID', '5555') + + expect(described_class.release_version).to eq('0.0.1+rfbranch.5555.ffffffff-ce.1') + end + + describe 'with env variables' do + it 'returns build version and iteration with env variable' do + stub_env_var('USE_S3_CACHE', 'false') + stub_env_var('CACHE_AWS_ACCESS_KEY_ID', 'NOT-KEY') + stub_env_var('CACHE_AWS_SECRET_ACCESS_KEY', 'NOT-SECRET-KEY') + stub_env_var('CACHE_AWS_BUCKET', 'bucket') + stub_env_var('CACHE_AWS_S3_REGION', 'moon-west1') + stub_env_var('CACHE_AWS_S3_ENDPOINT', 'endpoint') + stub_env_var('CACHE_S3_ACCELERATE', 'sure') + + stub_env_var('NIGHTLY', 'true') + stub_env_var('CI_PIPELINE_ID', '5555') + + expect(described_class.release_version).to eq('12.121.12-ce.1') + end + end + end + + describe '.docker_tag' do + before do + allow(Build::Check).to receive(:on_tag?).and_return(true) + allow_any_instance_of(Omnibus::BuildVersion).to receive(:semver).and_return('12.121.12') + allow_any_instance_of(Gitlab::BuildIteration).to receive(:build_iteration).and_return('ce.1') + end + + it 'returns package version when regular build' do + expect(described_class.docker_tag).to eq('12.121.12-ce.1') + end + + it 'respects IMAGE_TAG if set' do + allow(ENV).to receive(:[]).with('IMAGE_TAG').and_return('foobar') + expect(described_class.docker_tag).to eq('foobar') + end + end + + # Specs for latest_tag and for latest_stable_tag are really useful since we + # are stubbing out shell out to git. + # However, they are showing what we expect to see. + describe '.latest_tag' do + describe 'for CE' do + before do + stub_is_ee(false) + allow(described_class).to receive(:`).with("git describe --exact-match 2>/dev/null").and_return('12.121.12+rc7.ce.0') + allow(described_class).to receive(:`).with("git -c versionsort.prereleaseSuffix=rc tag -l '*[+.]ce.*' --sort=-v:refname | head -1").and_return('12.121.12+rc7.ce.0') + end + + it 'returns the version of correct edition' do + expect(described_class.latest_tag).to eq('12.121.12+rc7.ce.0') + end + end + + describe 'for EE' do + before do + stub_is_ee(true) + allow(described_class).to receive(:`).with("git -c versionsort.prereleaseSuffix=rc tag -l '*[+.]ee.*' --sort=-v:refname | head -1").and_return('12.121.12+rc7.ee.0') + end + + it 'returns the version of correct edition' do + expect(described_class.latest_tag).to eq('12.121.12+rc7.ee.0') + end + end + end + + describe '.latest_stable_tag' do + describe 'for CE' do + before do + stub_is_ee(nil) + allow(described_class).to receive(:`).with("git describe --exact-match 2>/dev/null").and_return('12.121.12+ce.0') + allow(described_class).to receive(:`).with("git -c versionsort.prereleaseSuffix=rc tag -l '*[+.]ce.*' --sort=-v:refname | awk '!/rc/' | head -1").and_return('12.121.12+ce.0') + end + + it 'returns the version of correct edition' do + expect(described_class.latest_stable_tag).to eq('12.121.12+ce.0') + end + end + + describe 'for EE' do + before do + stub_is_ee(true) + allow(described_class).to receive(:`).with("git -c versionsort.prereleaseSuffix=rc tag -l '*[+.]ee.*' --sort=-v:refname | awk '!/rc/' | head -1").and_return('12.121.12+ee.0') + end + + it 'returns the version of correct edition' do + expect(described_class.latest_stable_tag).to eq('12.121.12+ee.0') + end + end + end + + describe '.gitlab_version' do + describe 'GITLAB_VERSION variable specified' do + it 'returns passed value' do + allow(ENV).to receive(:[]).with("GITLAB_VERSION").and_return("9.0.0") + expect(described_class.gitlab_version).to eq('9.0.0') + end + end + + describe 'GITLAB_VERSION variable not specified' do + it 'returns content of VERSION' do + allow(File).to receive(:read).with("VERSION").and_return("8.5.6") + expect(described_class.gitlab_version).to eq('8.5.6') + end + end + end + + describe '.previous_version' do + it 'detects previous version correctly' do + allow(described_class).to receive(:`).with("git describe --exact-match 2>/dev/null").and_return('10.4.0+ee.0') + allow(Build::Info).to receive(:`).with(/git -c versionsort/).and_return("10.4.0+ee.0\n10.3.5+ee.0") + + expect(described_class.previous_version).to eq("10.3.5-ee.0") + end + end + + describe '.gitlab_rails repo' do + describe 'with alternative sources channel selected' do + before do + allow(::Gitlab::Version).to receive(:sources_channel).and_return('alternative') + end + + it 'returns public mirror for GitLab CE' do + allow(Build::Info).to receive(:package).and_return("gitlab-ce") + expect(described_class.gitlab_rails_repo).to eq("https://gitlab.com/gitlab-org/gitlab-foss.git") + end + it 'returns public mirror for GitLab EE' do + allow(Build::Info).to receive(:package).and_return("gitlab-ee") + expect(described_class.gitlab_rails_repo).to eq("https://gitlab.com/gitlab-org/gitlab.git") + end + end + + describe 'with default sources channel' do + before do + allow(::Gitlab::Version).to receive(:sources_channel).and_return('remote') + end + + it 'returns dev repo for GitLab CE' do + allow(Build::Info).to receive(:package).and_return("gitlab-ce") + expect(described_class.gitlab_rails_repo).to eq("git@dev.gitlab.org:gitlab/gitlabhq.git") + end + it 'returns dev repo for GitLab EE' do + allow(Build::Info).to receive(:package).and_return("gitlab-ee") + expect(described_class.gitlab_rails_repo).to eq("git@dev.gitlab.org:gitlab/gitlab-ee.git") + end + end + + describe 'with security sources channel selected' do + before do + allow(::Gitlab::Version).to receive(:sources_channel).and_return('security') + stub_env_var('CI_JOB_TOKEN', 'CJT') + end + + it 'returns security mirror for GitLab CE with attached credential' do + allow(Build::Info).to receive(:package).and_return("gitlab-ce") + expect(described_class.gitlab_rails_repo).to eq("https://gitlab-ci-token:CJT@gitlab.com/gitlab-org/security/gitlab-foss.git") + end + it 'returns security mirror for GitLab EE with attached credential' do + allow(Build::Info).to receive(:package).and_return("gitlab-ee") + expect(described_class.gitlab_rails_repo).to eq("https://gitlab-ci-token:CJT@gitlab.com/gitlab-org/security/gitlab.git") + end + end + end + + describe '.major_minor_version_and_rails_ref' do + it 'return minor and major version components plus the rails ref' do + allow(ENV).to receive(:[]).with('CI_COMMIT_TAG').and_return('12.0.12345+5159f2949cb.59c9fa631') + + expect(described_class.major_minor_version_and_rails_ref).to eq('12.0-5159f2949cb') + end + + it 'raises an error if the commit tag is invalid' do + allow(ENV).to receive(:[]).with('CI_COMMIT_TAG').and_return('xyz') + + expect { described_class.major_minor_version_and_rails_ref }.to raise_error(RuntimeError, /Invalid auto-deploy version 'xyz'/) + end + end + + describe '.deploy_env' do + before do + allow(ENV).to receive(:[]).with('AUTO_DEPLOY_ENVIRONMENT').and_return('ad') + allow(ENV).to receive(:[]).with('PATCH_DEPLOY_ENVIRONMENT').and_return('patch') + allow(ENV).to receive(:[]).with('RELEASE_DEPLOY_ENVIRONMENT').and_return('r') + end + + context 'on auto-deploy tag' do + before do + allow(Build::Check).to receive(:is_auto_deploy_tag?).and_return(true) + end + it 'returns the auto-deploy environment' do + expect(described_class.deploy_env).to eq('ad') + end + end + + context 'on RC tag' do + before do + allow(Build::Check).to receive(:is_auto_deploy_tag?).and_return(false) + allow(Build::Check).to receive(:is_rc_tag?).and_return(true) + end + it 'returns the auto-deploy environment' do + expect(described_class.deploy_env).to eq('patch') + end + end + + context 'on latest tag' do + before do + allow(Build::Check).to receive(:is_auto_deploy_tag?).and_return(false) + allow(Build::Check).to receive(:is_rc_tag?).and_return(false) + allow(Build::Check).to receive(:is_latest_stable_tag?).and_return(true) + end + it 'returns the auto-deploy environment' do + expect(described_class.deploy_env).to eq('r') + end + end + + context 'when unable to determine the desired env' do + before do + allow(Build::Check).to receive(:is_auto_deploy_tag?).and_return(false) + allow(Build::Check).to receive(:is_rc_tag?).and_return(false) + allow(Build::Check).to receive(:is_latest_stable_tag?).and_return(false) + end + it 'it returns nil' do + expect(described_class.deploy_env).to eq(nil) + end + end + end +end diff --git a/spec/lib/gitlab/build/qa_image_spec.rb b/spec/lib/gitlab/build/qa_image_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/build/qa_image_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' +require 'gitlab/build/qa_image' + +RSpec.describe Build::QAImage do + before do + allow(Build::GitlabImage).to receive(:dockerhub_image_name).and_return('gitlab/gitlab-ce') + allow(Build::GitlabImage).to receive(:gitlab_registry_image_name).and_return('gitlab-ce') + end + + describe '.dockerhub_image_name' do + it 'returns a correct image name' do + expect(described_class.dockerhub_image_name).to eq('gitlab/gitlab-ce-qa') + end + end + + describe '.gitlab_registry_image_name' do + it 'returns a correct image name' do + expect(described_class.gitlab_registry_image_name).to eq('gitlab-ce-qa') + end + end +end diff --git a/spec/lib/gitlab/build/qa_spec.rb b/spec/lib/gitlab/build/qa_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/build/qa_spec.rb @@ -0,0 +1,68 @@ +require 'spec_helper' +require 'gitlab/build/qa' + +RSpec.describe Build::QA do + before do + allow(ENV).to receive(:[]).and_call_original + stub_env_var('GITLAB_ALTERNATIVE_REPO', nil) + stub_env_var('ALTERNATIVE_PRIVATE_TOKEN', nil) + end + + describe '.repo_path' do + it 'returns correct location' do + expect(described_class.repo_path).to eq("/tmp/gitlab") + end + end + + describe '.get_gitlab_repo' do + it 'returns correct location' do + allow(Build::QA).to receive(:clone_gitlab_rails).and_return(true) + allow(Build::QA).to receive(:checkout_gitlab_rails).and_return(true) + + expect(described_class.get_gitlab_repo).to eq("/tmp/gitlab") + end + end + + describe '.clone_gitlab_rails' do + it 'calls the git command' do + allow(Build::Info).to receive(:package).and_return("gitlab-ee") + allow(::Gitlab::Version).to receive(:sources_channel).and_return('remote') + + expect(described_class).to receive(:system).with(*%w[rm -rf /tmp/gitlab]) + expect(described_class).to receive(:system).with(*%w[git clone git@dev.gitlab.org:gitlab/gitlab-ee.git /tmp/gitlab]) + + Build::QA.clone_gitlab_rails + end + end + + describe '.checkout_gitlab_rails' do + it 'calls the git command' do + allow(Build::Info).to receive(:package).and_return("gitlab-ee") + allow(Build::Info).to receive(:gitlab_version).and_return("9.0.0") + allow(Build::Check).to receive(:on_tag?).and_return(true) + stub_is_auto_deploy(false) + + expect(described_class).to receive(:system).with(*%w[git --git-dir=/tmp/gitlab/.git --work-tree=/tmp/gitlab checkout --quiet v9.0.0]) + + Build::QA.checkout_gitlab_rails + end + end + + describe '.get_gitlab_rails_sha' do + it 'returns the correct stable tag' do + allow(Build::Info).to receive(:gitlab_version).and_return("9.0.0") + allow(Build::Check).to receive(:on_tag?).and_return(true) + stub_is_auto_deploy(false) + + expect(Build::QA.get_gitlab_rails_sha).to eq("v9.0.0") + end + + it 'returns the correct auto-deploy commit sha' do + allow(Build::Info).to receive(:gitlab_version).and_return("bebc7c1e290074863e0d2621b3a4c4c7bdb072ae") + allow(Build::Check).to receive(:on_tag?).and_return(true) + stub_is_auto_deploy(true) + + expect(Build::QA.get_gitlab_rails_sha).to eq("bebc7c1e290074863e0d2621b3a4c4c7bdb072ae") + end + end +end diff --git a/spec/lib/gitlab/build_iteration_spec.rb b/spec/lib/gitlab/build_iteration_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/build_iteration_spec.rb @@ -0,0 +1,71 @@ +require 'spec_helper' +require 'gitlab/build_iteration' + +RSpec.describe Gitlab::BuildIteration do + describe :build_iteration do + subject { Gitlab::BuildIteration.new(git_describe) } + + context 'with an invalid git_describe' do + let(:git_describe) { '1.2.3-foo.3' } + + it 'returns 0' do + allow(Build::Check).to receive(:on_tag?).and_return(true) + expect(subject.build_iteration).to eq('0') + end + end + + context 'with a git_describe from master' do + let(:git_describe) { '1.2.3+rc1.ce.2-6-ge5626d5' } + + it 'returns rc1.ce.2' do + allow(Build::Check).to receive(:on_tag?).and_return(true) + expect(subject.build_iteration).to eq('rc1.ce.2') + end + end + + context 'with a proper git_describe' do + let(:git_describe) { '1.2.3+foo.4' } + + it 'returns foo.4' do + allow(Build::Check).to receive(:on_tag?).and_return(true) + expect(subject.build_iteration).to eq('foo.4') + end + end + + context 'with a git_describe with new line char' do + let(:git_describe) { "1.2.3+foo.4\n" } + + it 'returns foo.4' do + allow(Build::Check).to receive(:on_tag?).and_return(true) + expect(subject.build_iteration).to eq('foo.4') + end + end + + context 'with multiple plus signs' do + let(:git_describe) { '1.2.3+foo.4+bar' } + + it 'returns everything after the first plus' do + allow(Build::Check).to receive(:on_tag?).and_return(true) + expect(subject.build_iteration).to eq('foo.4+bar') + end + end + + context 'with an invalid git tag' do + let(:git_describe) { '1.2.3+' } + + it 'returns an empty string' do + allow(Build::Check).to receive(:on_tag?).and_return(true) + expect(subject.build_iteration).to eq('0') + end + end + + context 'not on a git tag' do + subject { Gitlab::BuildIteration.new } + + it 'returns 0' do + allow(Build::Check).to receive(:system).with('git describe --exact-match > /dev/null 2>&1').and_return(false) + expect(subject.build_iteration).to eq('0') + end + end + end +end diff --git a/spec/lib/gitlab/build_spec.rb b/spec/lib/gitlab/build_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/build_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' +require 'gitlab/build' + +RSpec.describe Build do + describe 'cmd' do + describe 'by default' do + it 'runs build command with log level info' do + expect(described_class.cmd('gitlab')).to eq %w[bundle exec omnibus build gitlab --log-level info] + end + end + + describe 'with different log level' do + it 'runs build command with custom log level' do + stub_env_var('BUILD_LOG_LEVEL', 'debug') + expect(described_class.cmd('gitlab')).to eq %w[bundle exec omnibus build gitlab --log-level debug] + end + end + end +end diff --git a/spec/lib/gitlab/deployer_helper_spec.rb b/spec/lib/gitlab/deployer_helper_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/deployer_helper_spec.rb @@ -0,0 +1,46 @@ +require 'spec_helper' +require 'gitlab/build' +require 'gitlab/deployer_helper' + +RSpec.describe DeployerHelper do + subject(:service) { described_class.new('some-token', 'some-env', 'some-branch') } + describe '#trigger_deploy' do + it 'triggers an auto deploy' do + response = instance_double('response', body: JSON.dump(web_url: 'http://example.com'), status: 201) + allow(Build::Info).to receive(:docker_tag).and_return('some-version') + expect(HTTP) + .to receive(:post) + .with( + "https://ops.gitlab.net/api/v4/projects/135/trigger/pipeline", + form: { + "token" => "some-token", + "ref" => "some-branch", + "variables[DEPLOY_ENVIRONMENT]" => "some-env", + "variables[DEPLOY_VERSION]" => "some-version", + "variables[DEPLOY_USER]" => "deployer" + } + ).and_return(response) + expect(service.trigger_deploy).to eq('http://example.com') + end + + it 'triggers an auto deploy with retries' do + # Set this to zero so there we don't have delays during tests + stub_const('DeployerHelper::TRIGGER_RETRY_INTERVAL', 0) + response = instance_double('response', body: JSON.dump(web_url: 'http://example.com'), status: 401) + allow(Build::Info).to receive(:docker_tag).and_return('some-version') + expect(HTTP) + .to receive(:post) + .with( + "https://ops.gitlab.net/api/v4/projects/135/trigger/pipeline", + form: { + "token" => "some-token", + "ref" => "some-branch", + "variables[DEPLOY_ENVIRONMENT]" => "some-env", + "variables[DEPLOY_VERSION]" => "some-version", + "variables[DEPLOY_USER]" => "deployer" + } + ).and_return(response).exactly(3).times + expect { service.trigger_deploy }.to raise_error(RuntimeError, "Unable to trigger pipeline after 3 retries") + end + end +end diff --git a/spec/lib/gitlab/docker_operations_spec.rb b/spec/lib/gitlab/docker_operations_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/docker_operations_spec.rb @@ -0,0 +1,105 @@ +require 'spec_helper' +require 'gitlab/docker_operations' + +RSpec.describe DockerOperations do + describe '.set_timeout' do + context 'when ENV["DOCKER_TIMEOUT"] is not set' do + it 'uses a default timeout value' do + expect(Docker).to receive(:options=).with(read_timeout: 1200, write_timeout: 1200) + + described_class.set_timeout + end + end + + context 'when ENV["DOCKER_TIMEOUT"] is not set' do + before do + expect(ENV).to receive(:[]).with('DOCKER_TIMEOUT').and_return("42") + end + + it 'uses the given timeout value' do + expect(Docker).to receive(:options=).with(read_timeout: "42", write_timeout: "42") + + described_class.set_timeout + end + end + end + + describe '.build' do + let(:location) { '/tmp/foo' } + let(:image) { 'gitlab-ce' } + let(:tag) { 'latest' } + + it 'uses a default timeout value' do + expect(described_class).to receive(:set_timeout) + expect(Docker::Image).to receive(:build_from_dir).with(location, { t: "#{image}:#{tag}", pull: true }).and_yield(JSON.dump(stream: 'Hello!')) + expect(described_class).to receive(:puts).with('Hello!') + + described_class.build(location.to_sym, image, tag) + end + end + + describe '.authenticate' do + context 'with no arguments' do + it 'calls Docker.authenticate!' do + expect(ENV).to receive(:[]).with('DOCKERHUB_USERNAME').and_return('user') + expect(ENV).to receive(:[]).with('DOCKERHUB_PASSWORD').and_return('pass') + expect(Docker).to receive(:authenticate!).with(username: 'user', password: 'pass', serveraddress: '') + + described_class.authenticate + end + end + + context 'with arguments' do + it 'uses a default timeout value' do + expect(Docker).to receive(:authenticate!).with(username: 'john', password: 'secret', serveraddress: 'registry.com') + + described_class.authenticate('john', 'secret', 'registry.com') + end + end + end + + describe '.get' do + it 'calls Docker::Image.get' do + expect(described_class).to receive(:set_timeout) + expect(Docker::Image).to receive(:get).with('namespace:tag') + + described_class.get('namespace', 'tag') + end + end + + describe '.push' do + it 'calls Docker::Image.push' do + image = double + creds = double + + expect(described_class).to receive(:set_timeout) + expect(described_class).to receive(:get).with('namespace', 'tag').and_return(image) + expect(Docker).to receive(:creds).and_return(creds) + expect(image).to receive(:push).with(creds, repo_tag: 'namespace:tag').and_yield('Hello!') + expect(described_class).to receive(:puts).and_return('Hello!') + + described_class.push('namespace', 'tag') + end + end + + describe '.tag' do + it 'calls Docker::Image.tag' do + image = double + + expect(described_class).to receive(:set_timeout) + expect(described_class).to receive(:get).with('namespace1', 'tag1').and_return(image) + expect(image).to receive(:tag).with(repo: 'namespace2', tag: 'tag2', force: true) + + described_class.tag('namespace1', 'namespace2', 'tag1', 'tag2') + end + end + + describe '.tag_and_push' do + it 'delegates to tag_and_push' do + expect(described_class).to receive(:tag).with('namespace1', 'namespace2', 'tag1', 'tag2') + expect(described_class).to receive(:push).with('namespace2', 'tag2') + + described_class.tag_and_push('namespace1', 'namespace2', 'tag1', 'tag2') + end + end +end diff --git a/spec/lib/gitlab/linker_helper_spec.rb b/spec/lib/gitlab/linker_helper_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/linker_helper_spec.rb @@ -0,0 +1,22 @@ +require 'spec_helper' +require 'gitlab/linker_helper' + +RSpec.describe LinkerHelper do + subject(:service) { described_class } + before do + allow(IO).to receive(:popen).and_call_original + allow(IO).to receive(:popen).with(%w[ldconfig -p]).and_return("1 library found\nlibssl.so (libc6,x86-64) => /lib64/libssl.so") + end + + describe "#ldconfig" do + it "should should update linker cache" do + expect(service).to receive(:system).with("ldconfig") + + service.ldconfig + end + + it "should return discovered libraries" do + expect(service.ldconfig).to have_key("libssl.so") + end + end +end diff --git a/spec/lib/gitlab/package_repository_spec.rb b/spec/lib/gitlab/package_repository_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/package_repository_spec.rb @@ -0,0 +1,265 @@ +require 'spec_helper' +require 'gitlab/package_repository' +require 'gitlab/util' + +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 + 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 + 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).to receive(:package_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).to receive(:package_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 + it 'prints a message and aborts' do + expect { repo.upload('my-staging-repository', true) }.to output(%r{User for uploading to package server not specified!\n}).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).to receive(:package_list).and_return(['pkg/el-6/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/scientific/6 pkg/el-6/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/ol/6 pkg/el-6/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/6 pkg/el-6/gitlab-ce.rpm --url=https://packages.gitlab.com\n}).to_stdout + 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 + 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 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 diff --git a/spec/lib/gitlab/tasks/aws_spec.rb b/spec/lib/gitlab/tasks/aws_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/tasks/aws_spec.rb @@ -0,0 +1,154 @@ +require 'spec_helper' + +Struct.new("Image", :image_id, :name, :tags) +Struct.new("Region", :region_name) +Struct.new("Response", :images) +Struct.new("Tag", :key, :value) +Struct.new("DescribeRegionResult", :regions) + +class AwsDummyClass + # Dummy class which mimicks AWS::EC2::Client class from aws-sdk and stubs + # necessary methods + + def describe_images(parameters) + images = if parameters['filters'.to_sym][1][:values] == ["GitLab Community Edition"] + [ + Struct::Image.new("ami-422", "GitLab Community Edition 8.13.2", [Struct::Tag.new("Version", "8.13.2")]) + ] + else + [ + Struct::Image.new("ami-322", "GitLab Enterprise Edition 10.5.4", [Struct::Tag.new("Version", "10.5.4")]) + ] + end + @response = Struct::Response.new(images) + end + + def describe_regions + Struct::DescribeRegionResult.new([Struct::Region.new('us-east-1')]) + end + + def deregister_image(parameters) + true + end +end + +RSpec.describe 'aws:ami:create', type: :rake do + before :all do + Rake.application.rake_require 'gitlab/tasks/aws' + end + + before do + Rake::Task['aws:ami:create'].reenable + allow_any_instance_of(Kernel).to receive(:system).and_return(true) + end + + describe 'on a regular tag' do + before do + allow(Build::Check).to receive(:on_tag?).and_return(true) + allow(Build::Check).to receive(:is_auto_deploy?).and_return(false) + allow(Build::Check).to receive(:is_rc_tag?).and_return(false) + allow(Build::Info).to receive(:deb_package_download_url).and_return('http://example.com') + end + + it 'should identify ce category correctly, if specified' do + allow(Build::Info).to receive(:edition).and_return('ce') + allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') + + expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ce", "http://example.com", ""]) + + Rake::Task['aws:ami:create'].invoke + end + + it 'should identify ce category correctly if nothing is specified' do + allow(Build::Info).to receive(:edition).and_return(nil) + allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') + + expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ce", "http://example.com", ""]) + + Rake::Task['aws:ami:create'].invoke + end + + it 'should identify ee category correctly' do + allow(Build::Info).to receive(:edition).and_return('ee') + allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') + + expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ee", "http://example.com", ""]) + + Rake::Task['aws:ami:create'].invoke + end + + it 'should identify ce arm64 correctly' do + allow(Gitlab::Util).to receive(:get_env).and_call_original + allow(Gitlab::Util).to receive(:get_env).with('AWS_ARCHITECTURE').and_return('arm64') + allow(Build::Info).to receive(:edition).and_return(nil) + allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') + + expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ce-arm64", "http://example.com", ""]) + + Rake::Task['aws:ami:create'].invoke + end + + it 'should identify ee arm64 correctly' do + allow(Gitlab::Util).to receive(:get_env).and_call_original + allow(Gitlab::Util).to receive(:get_env).with('AWS_ARCHITECTURE').and_return('arm64') + allow(Build::Info).to receive(:edition).and_return('ee') + allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') + + expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ee-arm64", "http://example.com", ""]) + + Rake::Task['aws:ami:create'].invoke + end + + it 'should identify ee ultimate category correctly' do + allow(Build::Info).to receive(:edition).and_return('ee') + allow(Gitlab::Util).to receive(:get_env).and_call_original + allow(Gitlab::Util).to receive(:get_env).with("AWS_RELEASE_TYPE").and_return('ultimate') + allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') + + expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ee-ultimate", "http://example.com", "AWS_ULTIMATE_LICENSE_FILE"]) + + Rake::Task['aws:ami:create'].invoke + end + + it 'should identify ee premium category correctly' do + allow(Build::Info).to receive(:edition).and_return('ee') + allow(Gitlab::Util).to receive(:get_env).and_call_original + allow(Gitlab::Util).to receive(:get_env).with("AWS_RELEASE_TYPE").and_return('premium') + allow(Omnibus::BuildVersion).to receive(:semver).and_return('9.3.0') + + expect_any_instance_of(Kernel).to receive(:system).with(*["support/packer/packer_ami.sh", "9.3.0", "ee-premium", "http://example.com", "AWS_PREMIUM_LICENSE_FILE"]) + + Rake::Task['aws:ami:create'].invoke + end + end + + describe 'on an rc tag' do + before do + allow(Build::Check).to receive(:on_tag?).and_return(true) + allow(Build::Check).to receive(:is_auto_deploy?).and_return(false) + allow(Build::Check).to receive(:is_rc_tag?).and_return(true) + allow(Build::Info).to receive(:deb_package_download_url).and_return('http://example.com') + end + + it 'does not do anything' do + expect(AWSHelper).not_to receive(:new) + + Rake::Task['aws:ami:create'].invoke + end + end + + describe 'on an auto-deploy tag' do + before do + allow(Build::Check).to receive(:on_tag?).and_return(true) + allow(Build::Check).to receive(:is_auto_deploy?).and_return(true) + allow(Build::Check).to receive(:is_rc_tag?).and_return(false) + allow(Build::Info).to receive(:deb_package_download_url).and_return('http://example.com') + end + + it 'does not do anything' do + expect(AWSHelper).not_to receive(:new) + + Rake::Task['aws:ami:create'].invoke + end + end +end diff --git a/spec/lib/gitlab/tasks/docker_tasks_spec.rb b/spec/lib/gitlab/tasks/docker_tasks_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/tasks/docker_tasks_spec.rb @@ -0,0 +1,119 @@ +require 'spec_helper' +require 'gitlab/docker_operations' + +RSpec.describe 'docker', type: :rake do + before :all do + Rake.application.rake_require 'gitlab/tasks/docker_tasks' + end + + describe 'docker:build:image' do + before do + Rake::Task['docker:build:image'].reenable + allow(ENV).to receive(:[]).and_call_original + end + + it 'calls build command with correct parameters' do + allow(ENV).to receive(:[]).with('CI_REGISTRY_IMAGE').and_return('dev.gitlab.org:5005/gitlab/omnibus-gitlab') + allow(Build::Info).to receive(:package).and_return('gitlab-ce') + allow(Build::GitlabImage).to receive(:write_release_file).and_return(true) + allow(File).to receive(:expand_path).and_return('/tmp/omnibus-gitlab/lib/gitlab/tasks/docker_tasks.rake') + allow(DockerOperations).to receive(:build).and_call_original + + expect(DockerOperations).to receive(:build).with("/tmp/omnibus-gitlab/docker", "dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ce", "latest") + expect(Docker::Image).to receive(:build_from_dir).with("/tmp/omnibus-gitlab/docker", { t: "dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ce:latest", pull: true }) + Rake::Task['docker:build:image'].invoke + end + end + + describe 'docker:pull:staging' do + before do + Rake::Task['docker:pull:staging'].reenable + allow(ENV).to receive(:[]).and_call_original + end + + it 'pulls in correct image' do + allow(ENV).to receive(:[]).with('CI_REGISTRY_IMAGE').and_return('dev.gitlab.org:5005/gitlab/omnibus-gitlab') + allow(Build::Info).to receive(:package).and_return('gitlab-ce') + allow(Build::Info).to receive(:docker_tag).and_return('9.0.0') + allow(DockerOperations).to receive(:authenticate).and_return(true) + + expect(Docker::Image).to receive(:create).with('fromImage' => 'dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ce:9.0.0') + Rake::Task['docker:pull:staging'].invoke + end + end + + describe 'docker:push' do + let(:dummy_image) { Docker::Image.new(Docker::Connection.new("test", {}), "id" => "test") } + let(:dummy_creds) { { username: "test", password: "test" } } + + before do + Rake::Task['docker:push:staging'].reenable + Rake::Task['docker:push:stable'].reenable + Rake::Task['docker:push:nightly'].reenable + Rake::Task['docker:push:rc'].reenable + Rake::Task['docker:push:latest'].reenable + + allow(ENV).to receive(:[]).and_call_original + allow(ENV).to receive(:[]).with('CI_REGISTRY_IMAGE').and_return('dev.gitlab.org:5005/gitlab/omnibus-gitlab') + allow(Build::Info).to receive(:package).and_return('gitlab-ce') + allow(Build::Info).to receive(:docker_tag).and_return('9.0.0') + allow(DockerOperations).to receive(:authenticate).and_return(true) + allow(Docker::Image).to receive(:get).and_return(dummy_image) + allow(Docker).to receive(:creds).and_return(dummy_creds) + allow(dummy_image).to receive(:tag).and_return(true) + end + + it 'pushes to staging correctly' do + expect(dummy_image).to receive(:push).with(dummy_creds, repo_tag: 'dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ce:9.0.0') + Rake::Task['docker:push:staging'].invoke + end + + it 'pushes nightly images correctly' do + allow(Build::Check).to receive(:is_nightly?).and_return(true) + + expect(dummy_image).to receive(:push).with(dummy_creds, repo_tag: 'gitlab/gitlab-ce:nightly') + Rake::Task['docker:push:nightly'].invoke + end + + it 'pushes latest images correctly' do + allow(Build::Check).to receive(:is_latest_stable_tag?).and_return(true) + + expect(dummy_image).to receive(:push).with(dummy_creds, repo_tag: 'gitlab/gitlab-ce:latest') + Rake::Task['docker:push:latest'].invoke + end + + it 'pushes rc images correctly' do + allow(Build::Check).to receive(:is_latest_tag?).and_return(true) + + expect(dummy_image).to receive(:push).with(dummy_creds, repo_tag: 'gitlab/gitlab-ce:rc') + Rake::Task['docker:push:rc'].invoke + end + + it 'pushes triggered images correctly' do + allow(ENV).to receive(:[]).with('CI_REGISTRY_IMAGE').and_return('registry.gitlab.com/gitlab-org/omnibus-gitlab') + allow(ENV).to receive(:[]).with("IMAGE_TAG").and_return("omnibus-12345") + allow(Build::Info).to receive(:docker_tag).and_call_original + + expect(dummy_image).to receive(:push).with(dummy_creds, repo_tag: 'registry.gitlab.com/gitlab-org/omnibus-gitlab/gitlab-ce:omnibus-12345') + Rake::Task['docker:push:triggered'].invoke + end + end +end + +RSpec.describe 'docker_operations' do + describe 'without docker operations timeout variable' do + it 'sets default value as timeout' do + DockerOperations.set_timeout + expect(Docker.options[:read_timeout]).to eq(1200) + end + end + + describe 'with docker operations timeout variable specified' do + it 'sets provided value as timeout' do + allow(ENV).to receive(:[]).and_call_original + allow(ENV).to receive(:[]).with('DOCKER_TIMEOUT').and_return("500") + DockerOperations.set_timeout + expect(Docker.options[:read_timeout]).to eq("500") + end + end +end diff --git a/spec/lib/gitlab/tasks/license_spec.rb b/spec/lib/gitlab/tasks/license_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/tasks/license_spec.rb @@ -0,0 +1,151 @@ +require 'spec_helper' + +RSpec.describe 'license:check', type: :rake do + let(:f) { double("Mocked file object") } + + before :all do + Rake.application.rake_require 'gitlab/tasks/license' + end + + before do + Rake::Task['license:check'].reenable + allow(File).to receive(:exist?).and_return(true) + allow(File).to receive(:open).and_call_original + allow(File).to receive(:open).with(/pkg.*license-status.json/, "w").and_return(f) + allow(f).to receive(:write).and_return(true) + allow(f).to receive(:close).and_return(true) + allow(Build::Info).to receive(:release_version).and_return("11.5.1+ce.0") + end + + it 'detects good licenses correctly' do + license_info = '[ + { + "name": "chef-zero", + "version": "4.8.0", + "license": "Apache-2.0", + "dependencies": [ + { + "name": "sample", + "version": "1.0.0", + "license": "MIT" + } + ] + } + ]' + allow(File).to receive(:read).and_return(license_info) + + expect { Rake::Task['license:check'].invoke }.to output(/✓.*chef-zero - 4.8.0.*Apache-2.0/).to_stdout + end + + it 'detects blacklisted softwares with good licenses correctly' do + license_info = '[ + { + "name": "readline", + "version": "4.8.0", + "license": "Apache-2.0", + "dependencies": [ + { + "name": "sample", + "version": "1.0.0", + "license": "MIT" + } + ] + } + ]' + allow(File).to receive(:read).and_return(license_info) + + expect { Rake::Task['license:check'].invoke }.to output(/readline.*Blacklisted software/).to_stdout.and raise_error(RuntimeError, "Build Aborted due to license violations") + end + + it 'detects bad licenses correctly' do + license_info = '[ + { + "name": "foo", + "version": "4.8.0", + "license": "GPL-3.0", + "dependencies": [ + { + "name": "sample", + "version": "1.0.0", + "license": "GPL-3.0" + } + ] + } + ]' + + allow(File).to receive(:read).and_return(license_info) + expect { Rake::Task['license:check'].invoke }.to output(/foo.*Unacceptable license/).to_stdout.and raise_error(RuntimeError, "Build Aborted due to license violations") + end + + it 'detects whitelisted softwares with bad licenses correctly' do + license_info = '[ + { + "name": "git", + "version": "4.8.0", + "license": "GPL-3.0", + "dependencies": [ + { + "name": "sample", + "version": "1.0.0", + "license": "LGPL" + } + ] + } + ]' + allow(File).to receive(:read).and_return(license_info) + + expect { Rake::Task['license:check'].invoke }.to output(/git.*Whitelisted software/).to_stdout + end + + it 'detects blacklisted softwares with unknown licenses correctly' do + license_info = '[ + { + "name": "readline", + "version": "4.8.0", + "license": "jargon", + "dependencies": [ + { + "name": "sample", + "version": "1.0.0", + "license": "MIT" + } + ] + } + ]' + allow(File).to receive(:read).and_return(license_info) + + expect { Rake::Task['license:check'].invoke }.to output(/readline.*Blacklisted software/).to_stdout.and raise_error(RuntimeError, "Build Aborted due to license violations") + end + + it 'detects whitelisted software with unknown licenses correctly' do + license_info = '[ + { + "name": "git", + "version": "4.8.0", + "license": "jargon", + "dependencies": [ + { + "name": "sample", + "version": "1.0.0", + "license": "MIT" + } + ] + } + ]' + allow(File).to receive(:read).and_return(license_info) + expect { Rake::Task['license:check'].invoke }.to output(/git.*Whitelisted software/).to_stdout + end + + it 'should detect if install directory not found' do + allow(File).to receive(:read).and_return('install_dir /opt/gitlab') + allow(File).to receive(:exist?).with('/opt/gitlab').and_return(false) + expect { Rake::Task['license:check'].invoke }.to raise_error(StandardError, "Unable to retrieve install_dir, thus unable to check /opt/gitlab/dependency_licenses.json") + end + + it 'should detect if dependency_license.json file not found' do + allow(File).to receive(:read).and_return('install_dir /opt/gitlab') + allow(File).to receive(:exist?).with('/opt/gitlab').and_return(true) + allow(File).to receive(:exist?).with('/opt/gitlab/dependency_licenses.json').and_return(false) + expect { Rake::Task['license:check'].invoke }.to raise_error(StandardError, "Unable to open /opt/gitlab/dependency_licenses.json") + end +end diff --git a/spec/lib/gitlab/tasks/qa_spec.rb b/spec/lib/gitlab/tasks/qa_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/tasks/qa_spec.rb @@ -0,0 +1,110 @@ +require 'spec_helper' + +RSpec.describe 'qa', type: :rake do + let(:gitlab_registry_image_address) { 'dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ce-qa' } + let(:gitlab_version) { '10.2.0' } + let(:commit_sha) { 'abcd1234' } + let(:image_tag) { 'omnibus-12345' } + let(:version_manifest) { { "software": { "gitlab-rails": { "locked_version": "123445" } } } } + + before(:all) do + Rake.application.rake_require 'gitlab/tasks/qa' + end + + describe 'qa:build' do + let(:repo_path) { "/tmp/gitlab" } + before do + Rake::Task['qa:build'].reenable + + allow(Build::QA).to receive(:get_gitlab_repo).and_return(repo_path) + allow(Build::QA).to receive(:gitlab_repo).and_return(repo_path) + allow(Build::QAImage).to receive(:gitlab_registry_image_address).and_return(gitlab_registry_image_address) + allow(JSON).to receive(:parse).and_return(version_manifest) + end + + it 'calls build method with correct parameters' do + expect(DockerOperations).to receive(:build).with(repo_path, 'dev.gitlab.org:5005/gitlab/omnibus-gitlab/gitlab-ce-qa', 'latest', dockerfile: "qa/Dockerfile") + + Rake::Task['qa:build'].invoke + end + end + + describe 'qa:push' do + before do + Rake::Task['qa:push:stable'].reenable + Rake::Task['qa:push:nightly'].reenable + Rake::Task['qa:push:rc'].reenable + Rake::Task['qa:push:latest'].reenable + + allow(Build::Info).to receive(:gitlab_version).and_return(gitlab_version) + end + + it 'pushes stable images correctly' do + expect(Build::QAImage).to receive(:tag_and_push_to_gitlab_registry).with(gitlab_version) + expect(Build::QAImage).to receive(:tag_and_push_to_dockerhub).with(gitlab_version, initial_tag: 'latest') + + Rake::Task['qa:push:stable'].invoke + end + + it 'pushes nightly images correctly' do + expect(Build::Check).to receive(:is_nightly?).and_return(true) + + expect(Build::QAImage).to receive(:tag_and_push_to_dockerhub).with('nightly', initial_tag: 'latest') + + Rake::Task['qa:push:nightly'].invoke + end + + it 'pushes latest images correctly' do + expect(Build::Check).to receive(:is_latest_stable_tag?).and_return(true) + + expect(Build::QAImage).to receive(:tag_and_push_to_dockerhub).with('latest', initial_tag: 'latest') + + Rake::Task['qa:push:latest'].invoke + end + + it 'pushes rc images correctly' do + expect(Build::Check).to receive(:is_latest_tag?).and_return(true) + + expect(Build::QAImage).to receive(:tag_and_push_to_dockerhub).with('rc', initial_tag: 'latest') + + Rake::Task['qa:push:rc'].invoke + end + + it 'pushes triggered images correctly' do + allow(ENV).to receive(:[]).with('CI').and_return('true') + expect(ENV).to receive(:[]).with('IMAGE_TAG').and_return(image_tag) + + expect(Build::QAImage).to receive(:tag_and_push_to_gitlab_registry).with(image_tag) + + Rake::Task['qa:push:triggered'].invoke + end + + describe ':staging' do + before do + Rake::Task['qa:push:staging'].reenable + + allow(Build::Info).to receive(:gitlab_version).and_return(gitlab_version) + allow(Build::Info).to receive(:commit_sha).and_return(commit_sha) + end + + it 'pushes staging images correctly' do + stub_is_auto_deploy(false) + expect(Build::QAImage).to receive(:tag_and_push_to_gitlab_registry).with(gitlab_version) + expect(Build::QAImage).to receive(:tag_and_push_to_gitlab_registry).with(commit_sha) + + Rake::Task['qa:push:staging'].invoke + end + + it 'pushes staging auto-deploy images correctly' do + allow(ENV).to receive(:[]).with('CI').and_return('true') + allow(ENV).to receive(:[]).with('CI_COMMIT_TAG').and_return('12.0.12345+5159f2949cb.59c9fa631') + allow(Build::Info).to receive(:current_git_tag).and_return('12.0.12345+5159f2949cb.59c9fa631') + + expect(Build::QAImage).to receive(:tag_and_push_to_gitlab_registry).with('12.0-5159f2949cb') + expect(Build::QAImage).to receive(:tag_and_push_to_gitlab_registry).with(commit_sha) + + Rake::Task['qa:push:staging'].invoke + end + end + end +end diff --git a/spec/lib/gitlab/util_spec.rb b/spec/lib/gitlab/util_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/util_spec.rb @@ -0,0 +1,50 @@ +require 'spec_helper' +require 'gitlab/util' + +RSpec.describe Gitlab::Util do + describe :get_env do + it 'strips value of env variable correctly' do + allow(ENV).to receive(:[]).with('foo').and_return(' bar ') + + expect(Gitlab::Util.get_env('foo')).to eq('bar') + end + + it 'does not fail if env variable is nil' do + allow(ENV).to receive(:[]).with('foo').and_return(nil) + + expect { Gitlab::Util.get_env('foo') }.not_to raise_error + expect(Gitlab::Util.get_env('foo')).to eq(nil) + end + end + + describe :set_env do + it 'strips value before setting env variable' do + Gitlab::Util.set_env('foo', ' blahblah ') + expect(ENV['foo']).to eq('blahblah') + end + + it 'does not fail if value is nil' do + expect { Gitlab::Util.set_env('foo', nil) }.not_to raise_error + expect(ENV['foo']).to eq(nil) + end + end + + describe :set_env_if_missing do + it 'does not override existing value' do + allow(ENV).to receive(:[]).with('foo').and_return('lorem') + + Gitlab::Util.set_env_if_missing('foo', 'ipsum') + expect(ENV['foo']).to eq('lorem') + end + + it 'sets value if env variable is mising' do + Gitlab::Util.set_env_if_missing('foo', 'ipsum') + expect(ENV['foo']).to eq('ipsum') + end + + it 'does not fail if value is nil' do + expect { Gitlab::Util.set_env_if_missing('bar', nil) }.not_to raise_error + expect(ENV['bar']).to eq(nil) + end + end +end diff --git a/spec/lib/gitlab/version_spec.rb b/spec/lib/gitlab/version_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/gitlab/version_spec.rb @@ -0,0 +1,318 @@ +require 'spec_helper' +require 'gitlab/version' + +RSpec.describe Gitlab::Version do + before do + allow(ENV).to receive(:[]).and_call_original + stub_env_var('GITLAB_ALTERNATIVE_REPO', nil) + stub_env_var('ALTERNATIVE_PRIVATE_TOKEN', nil) + end + + describe '.sources_channel' do + subject { described_class } + using RSpec::Parameterized::TableSyntax + where(:alternative_sources, :security_sources, :source_channel) do + nil | nil | "alternative" + nil | 'true' | "security" + nil | 'false' | "alternative" + 'true' | nil | "alternative" + 'true' | 'true' | "security" + 'true' | 'false' | "alternative" + 'false' | nil | "remote" + 'false' | 'true' | "security" + 'false' | 'false' | "remote" + end + + with_them do + before do + stub_env_var('ALTERNATIVE_SOURCES', alternative_sources) + stub_env_var('SECURITY_SOURCES', security_sources) + end + + context 'when checking the source channel environment variables' do + it 'uses the correct source channel' do + expect(subject.sources_channel).to eq(source_channel) + end + end + end + end + + describe '.fallback_sources_channel' do + subject { described_class } + + context 'with ALTERNATIVE_SOURCES=true' do + it 'returns "alternative"' do + stub_env_var('ALTERNATIVE_SOURCES', 'true') + + expect(subject.fallback_sources_channel).to eq('alternative') + end + end + + context 'with ALTERNATIVE_SOURCES not set true' do + it 'returns "remote"' do + stub_env_var('ALTERNATIVE_SOURCES', 'false') + + expect(subject.fallback_sources_channel).to eq('remote') + end + end + end + + describe '.security_channel?' do + subject { described_class } + + it 'returns true when sources_channel is set for security' do + mock_sources_channel('security') + + expect(subject.security_channel?).to be_truthy + end + + it 'returns false when sources_channel is not set for security' do + mock_sources_channel + + expect(subject.security_channel?).to be_falsey + end + end + + describe :remote do + subject { Gitlab::Version.new(software) } + + context 'with a valid software name' do + let(:software) { 'gitlab-rails-ee' } + + it 'returns a link from custom_sources yml' do + mock_sources_channel + + expect(subject.remote).to eq('git@dev.gitlab.org:gitlab/gitlab-ee.git') + end + end + + context 'with an invalid software name' do + let(:software) { 'not a valid software' } + + it 'outputs an empty string' do + expect(subject.remote).to eq('') + end + end + + context 'with default fallback' do + let(:software) { 'gitlab-rails-ee' } + + it 'returns "remote" link from custom_sources yml' do + mock_sources_channel + + expect(subject.remote).to eq('git@dev.gitlab.org:gitlab/gitlab-ee.git') + end + end + + context 'with alternative fallback' do + let(:software) { 'gitlab-rails-ee' } + + it 'returns "alternative" link from custom_sources yml' do + mock_sources_channel('alternative') + + expect(subject.remote).to eq('https://gitlab.com/gitlab-org/gitlab.git') + end + end + + context 'with alternative env override' do + let(:software) { 'gitlab-rails-ee' } + + it 'returns "alternative" link from the environment whenever present' do + stub_env_var('GITLAB_ALTERNATIVE_REPO', 'https://gitlab.example.com/gitlab.git') + + expect(subject.remote).to eq('https://gitlab.example.com/gitlab.git') + end + + it 'attaches credentials to alternative env links when present' do + stub_env_var('GITLAB_ALTERNATIVE_REPO', 'https://gitlab.example.com/gitlab.git') + stub_env_var('ALTERNATIVE_PRIVATE_TOKEN', 'APT') + + expect(subject.remote).to eq('https://gitlab-ci-token:APT@gitlab.example.com/gitlab.git') + end + end + + context 'with security source channel selected' do + before do + stub_env_var('CI_JOB_TOKEN', 'CJT') + mock_sources_channel('security') + end + + context 'when security source is defined for the software' do + let(:software) { 'gitlab-rails-ee' } + + it 'returns "security" link attached with credential from custom_sources yml' do + expect(subject.remote).to eq('https://gitlab-ci-token:CJT@gitlab.com/gitlab-org/security/gitlab.git') + end + + context 'when "security" link is in not URI compliant' do + before do + allow(YAML).to receive(:load_file) + .and_return(software => { "security" => "git@dev.gitlab.org:gitlab/gitlab-ee.git" }) + end + + it 'returns "security" link without attaching credential' do + expect(subject.remote).to eq("git@dev.gitlab.org:gitlab/gitlab-ee.git") + end + end + end + + context 'when security source is not defined for the software' do + let(:software) { 'prometheus' } + + it 'returns "remote" link from custom_sources yml' do + mock_fallback_channel + + expect(subject.remote).to eq('git@dev.gitlab.org:omnibus-mirror/prometheus.git') + end + + it 'returns expected link from custom_sources yml when asked for a specific remote' do + mock_fallback_channel + + expect(subject.remote('alternative')).to eq('https://gitlab.com/gitlab-org/build/omnibus-mirror/prometheus.git') + end + + context 'with alternative fallback' do + it 'returns "alternative" link from custom_sources yml' do + mock_fallback_channel('alternative') + + expect(subject.remote).to eq('https://gitlab.com/gitlab-org/build/omnibus-mirror/prometheus.git') + end + end + end + end + end + + describe :print do + subject { Gitlab::Version.new(software, version) } + + context 'with a valid software name and version' do + let(:software) { 'gitlab-rails' } + let(:version) { '12.34.567' } + + it 'returns correct version with v appended' do + expect(subject.print).to eq('v12.34.567') + end + end + + context 'with a valid software name and version' do + let(:software) { 'gitlab-rails-ee' } + let(:version) { '12.34.567-ee' } + + it 'returns correct version with v appended' do + expect(subject.print).to eq('v12.34.567-ee') + end + end + + context 'with a valid software name and no version' do + let(:software) { 'ruby' } + let(:version) { nil } + + it 'outputs an empty string' do + expect(subject.print).to eq(nil) + end + end + + context 'with a valid software name and a version' do + let(:software) { 'ruby' } + let(:version) { '2.3.1' } + + it 'adds a v prefix' do + expect(subject.print).to eq("v2.3.1") + end + + it 'does not add a v prefix if explicitly set' do + expect(subject.print(false)).to eq("2.3.1") + end + end + + context 'with a valid software name and a branch name' do + let(:software) { 'gitlab-rails' } + let(:version) { '9-0-stable' } + + it 'does not add a v prefix' do + expect(subject.print).to eq("9-0-stable") + end + end + + context 'with a valid software name and a branch name' do + let(:software) { 'gitlab-rails' } + let(:version) { 'master' } + + it 'does not add a v prefix' do + expect(subject.print).to eq("master") + end + end + + context 'with a valid software name and an rc tag ' do + let(:software) { 'gitlab-rails' } + let(:version) { '9.1.0-rc1' } + + it 'add a v prefix' do + expect(subject.print).to eq("v9.1.0-rc1") + end + end + + context 'with a valid software name and an rc tag ' do + let(:software) { 'gitlab-rails' } + let(:version) { '9.1.0-rc2-ee' } + + it 'add a v prefix' do + expect(subject.print).to eq("v9.1.0-rc2-ee") + end + end + + context 'with a valid software name and a branch name' do + let(:software) { 'gitlab-rails' } + let(:version) { '9.1.0-fix' } + + it 'does not add a v prefix' do + expect(subject.print).to eq("9.1.0-fix") + end + end + + context 'with a valid software name and a branch name' do + let(:software) { 'gitlab-rails' } + let(:version) { 'fix-9.1.0' } + + it 'does not add a v prefix' do + expect(subject.print).to eq("fix-9.1.0") + end + end + + context 'with a valid software name and a commit sha' do + let(:software) { 'gitlab-rails' } + let(:version) { '1076385cb57a03fa254be5604f6c6ceb6e39987f' } + + it 'does not add a v prefix' do + expect(subject.print).to eq("1076385cb57a03fa254be5604f6c6ceb6e39987f") + end + end + end + + describe :version do + subject { Gitlab::Version.new(software) } + + context 'env variable for setting version' do + let(:software) { 'gitlab-rails' } + + it 'identifies correct version from env variable' do + stub_env_var('GITLAB_VERSION', '5.6.7') + allow(File).to receive(:read).and_return("1.2.3") + expect(subject.print).to eq("v5.6.7") + end + + it 'falls back to VERSION file if env variable not found' do + allow(File).to receive(:read).and_return("1.2.3") + expect(subject.print).to eq("v1.2.3") + end + end + end + + def mock_sources_channel(channel = 'remote') + allow(::Gitlab::Version).to receive(:sources_channel).and_return(channel) + end + + def mock_fallback_channel(channel = 'remote') + allow(::Gitlab::Version).to receive(:fallback_sources_channel).and_return(channel) + end +end diff --git a/spec/lib/rubocop/cop/avoid_using_env_spec.rb b/spec/lib/rubocop/cop/avoid_using_env_spec.rb new file mode 100644 --- /dev/null +++ b/spec/lib/rubocop/cop/avoid_using_env_spec.rb @@ -0,0 +1,50 @@ +require 'spec_helper' +require 'rubocop/rspec/cop_helper' +require 'rubocop/rspec/expect_offense' + +require 'rubocop/cop/avoid_using_env' + +RSpec.describe Rubocop::Cop::AvoidUsingEnv do + include CopHelper + include RuboCop::RSpec::ExpectOffense + + subject(:cop) { described_class.new } + + it 'flags violation for setting env vars directly' do + expect_offense(<<~RUBY) + call do + ENV['foo'] = 'blah' + ^^^^^^^^^^^^^^^^^^^ Do not use ENV directly to set environment variables, use Gitlab::Util.set_env or Gitlab::Util.set_env_if_missing methods instead. + end + RUBY + end + + it 'flags violation for getting env vars directly ENV' do + expect_offense(<<~RUBY) + call do + value = ENV['foo'] + ^^^^^^^^^^ Do not use ENV directly to retrieve environment variables. Use Gitlab::Util.get_env method instead. + end + RUBY + end + + it 'flags violation for using ||= with ENV' do + expect_offense(<<~RUBY) + call do + ENV['bar'] ||= ENV['foo'] + ^^^^^^^^^^ Do not use ENV directly to retrieve environment variables. Use Gitlab::Util.get_env method instead. + ^^^^^^^^^^ Do not use ENV directly to retrieve environment variables. Use Gitlab::Util.get_env method instead. + ^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use ENV directly to set environment variables, use Gitlab::Util.set_env or Gitlab::Util.set_env_if_missing methods instead. + end + RUBY + end + + it 'does not flag violation for comments' do + expect_no_offenses(<<~RUBY) + call do + # ENV['bar'] ||= ENV['foo'] + puts valu + end + RUBY + end +end diff --git a/spec/rubocop/cop/avoid_using_env_spec.rb b/spec/rubocop/cop/avoid_using_env_spec.rb deleted file mode 100644 --- a/spec/rubocop/cop/avoid_using_env_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -require 'spec_helper' -require 'rubocop/rspec/cop_helper' -require 'rubocop/rspec/expect_offense' - -require_relative '../../../lib/rubocop/cop/avoid_using_env' - -RSpec.describe Rubocop::Cop::AvoidUsingEnv do - include CopHelper - include RuboCop::RSpec::ExpectOffense - - subject(:cop) { described_class.new } - - it 'flags violation for setting env vars directly' do - expect_offense(<<~RUBY) - call do - ENV['foo'] = 'blah' - ^^^^^^^^^^^^^^^^^^^ Do not use ENV directly to set environment variables, use Gitlab::Util.set_env or Gitlab::Util.set_env_if_missing methods instead. - end - RUBY - end - - it 'flags violation for getting env vars directly ENV' do - expect_offense(<<~RUBY) - call do - value = ENV['foo'] - ^^^^^^^^^^ Do not use ENV directly to retrieve environment variables. Use Gitlab::Util.get_env method instead. - end - RUBY - end - - it 'flags violation for using ||= with ENV' do - expect_offense(<<~RUBY) - call do - ENV['bar'] ||= ENV['foo'] - ^^^^^^^^^^ Do not use ENV directly to retrieve environment variables. Use Gitlab::Util.get_env method instead. - ^^^^^^^^^^ Do not use ENV directly to retrieve environment variables. Use Gitlab::Util.get_env method instead. - ^^^^^^^^^^^^^^^^^^^^^^^^^ Do not use ENV directly to set environment variables, use Gitlab::Util.set_env or Gitlab::Util.set_env_if_missing methods instead. - end - RUBY - end - - it 'does not flag violation for comments' do - expect_no_offenses(<<~RUBY) - call do - # ENV['bar'] ||= ENV['foo'] - puts valu - end - RUBY - end -end