Commit 0a73bfba authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 76b43d8a 00112e67
<script> <script>
import { mapActions, mapGetters, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import { GlButton, GlLoadingIcon } from '@gitlab/ui';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { import {
WEBIDE_MARK_APP_START, WEBIDE_MARK_APP_START,
...@@ -29,15 +30,17 @@ export default { ...@@ -29,15 +30,17 @@ export default {
components: { components: {
IdeSidebar, IdeSidebar,
RepoEditor, RepoEditor,
'error-message': () => import('./error_message.vue'), GlButton,
'gl-button': () => import('@gitlab/ui/src/components/base/button/button.vue'), GlLoadingIcon,
'gl-loading-icon': () => import('@gitlab/ui/src/components/base/loading_icon/loading_icon.vue'), ErrorMessage: () => import(/* webpackChunkName: 'ide_runtime' */ './error_message.vue'),
'commit-editor-header': () => import('./commit_sidebar/editor_header.vue'), CommitEditorHeader: () =>
'repo-tabs': () => import('./repo_tabs.vue'), import(/* webpackChunkName: 'ide_runtime' */ './commit_sidebar/editor_header.vue'),
'ide-status-bar': () => import('./ide_status_bar.vue'), RepoTabs: () => import(/* webpackChunkName: 'ide_runtime' */ './repo_tabs.vue'),
'find-file': () => import('~/vue_shared/components/file_finder/index.vue'), IdeStatusBar: () => import(/* webpackChunkName: 'ide_runtime' */ './ide_status_bar.vue'),
'right-pane': () => import('./panes/right.vue'), FindFile: () =>
'new-modal': () => import('./new_dropdown/modal.vue'), import(/* webpackChunkName: 'ide_runtime' */ '~/vue_shared/components/file_finder/index.vue'),
RightPane: () => import(/* webpackChunkName: 'ide_runtime' */ './panes/right.vue'),
NewModal: () => import(/* webpackChunkName: 'ide_runtime' */ './new_dropdown/modal.vue'),
}, },
mixins: [glFeatureFlagsMixin()], mixins: [glFeatureFlagsMixin()],
data() { data() {
......
...@@ -14,8 +14,10 @@ export default { ...@@ -14,8 +14,10 @@ export default {
ResizablePanel, ResizablePanel,
ActivityBar, ActivityBar,
IdeTree, IdeTree,
[leftSidebarViews.review.name]: () => import('./ide_review.vue'), [leftSidebarViews.review.name]: () =>
[leftSidebarViews.commit.name]: () => import('./repo_commit_section.vue'), import(/* webpackChunkName: 'ide_runtime' */ './ide_review.vue'),
[leftSidebarViews.commit.name]: () =>
import(/* webpackChunkName: 'ide_runtime' */ './repo_commit_section.vue'),
CommitForm, CommitForm,
IdeProjectHeader, IdeProjectHeader,
}, },
......
<script> <script>
import { mapActions, mapGetters, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import EmptyState from './empty_state.vue'; import EmptyState from './empty_state.vue';
import TerminalSession from './session.vue';
export default { export default {
components: { components: {
EmptyState, EmptyState,
TerminalSession, TerminalSession: () => import(/* webpackChunkName: 'ide_terminal' */ './session.vue'),
}, },
computed: { computed: {
...mapState('terminal', ['isShowSplash', 'paths']), ...mapState('terminal', ['isShowSplash', 'paths']),
......
...@@ -52,7 +52,7 @@ class ProjectRepositoryStorageMove < ApplicationRecord ...@@ -52,7 +52,7 @@ class ProjectRepositoryStorageMove < ApplicationRecord
begin begin
storage_move.project.set_repository_read_only!(skip_git_transfer_check: true) storage_move.project.set_repository_read_only!(skip_git_transfer_check: true)
rescue => err rescue => err
errors.add(:project, err.message) storage_move.errors.add(:project, err.message)
next false next false
end end
......
...@@ -16,6 +16,8 @@ module Packages ...@@ -16,6 +16,8 @@ module Packages
composer_json: composer_json composer_json: composer_json
}) })
end end
created_package
end end
private private
......
...@@ -12,7 +12,7 @@ module Packages ...@@ -12,7 +12,7 @@ module Packages
end end
def execute def execute
package.package_files.create!( package_file = package.package_files.build(
file: file, file: file,
size: params['file.size'], size: params['file.size'],
file_name: params[:file_name], file_name: params[:file_name],
...@@ -25,6 +25,13 @@ module Packages ...@@ -25,6 +25,13 @@ module Packages
conan_file_type: params[:conan_file_type] conan_file_type: params[:conan_file_type]
} }
) )
if params[:build].present?
package_file.package_file_build_infos << package_file.package_file_build_infos.build(pipeline: params[:build].pipeline)
end
package_file.save!
package_file
end end
end end
end end
......
...@@ -8,9 +8,9 @@ module Packages ...@@ -8,9 +8,9 @@ module Packages
project project
.packages .packages
.with_package_type(package_type) .with_package_type(package_type)
.safe_find_or_create_by!(name: name, version: version) do |pkg| .safe_find_or_create_by!(name: name, version: version) do |package|
pkg.creator = package_creator package.creator = package_creator
yield pkg if block_given? add_build_info(package)
end end
end end
...@@ -18,7 +18,9 @@ module Packages ...@@ -18,7 +18,9 @@ module Packages
project project
.packages .packages
.with_package_type(package_type) .with_package_type(package_type)
.create!(package_attrs(attrs)) .create!(package_attrs(attrs)) do |package|
add_build_info(package)
end
end end
private private
...@@ -34,5 +36,11 @@ module Packages ...@@ -34,5 +36,11 @@ module Packages
def package_creator def package_creator
current_user if current_user.is_a?(User) current_user if current_user.is_a?(User)
end end
def add_build_info(package)
if params[:build].present?
package.build_infos.new(pipeline: params[:build].pipeline)
end
end
end end
end end
...@@ -18,9 +18,12 @@ module Packages ...@@ -18,9 +18,12 @@ module Packages
build: params[:build] build: params[:build]
} }
::Packages::Generic::FindOrCreatePackageService package = ::Packages::Generic::FindOrCreatePackageService
.new(project, current_user, package_params) .new(project, current_user, package_params)
.execute .execute
package.build_infos.safe_find_or_create_by!(pipeline: params[:build].pipeline) if params[:build].present?
package
end end
def create_package_file(package) def create_package_file(package)
......
...@@ -4,11 +4,7 @@ module Packages ...@@ -4,11 +4,7 @@ module Packages
module Generic module Generic
class FindOrCreatePackageService < ::Packages::CreatePackageService class FindOrCreatePackageService < ::Packages::CreatePackageService
def execute def execute
find_or_create_package!(::Packages::Package.package_types['generic']) do |package| find_or_create_package!(::Packages::Package.package_types['generic'])
if params[:build].present?
package.build_infos.new(pipeline: params[:build].pipeline)
end
end
end end
end end
end end
......
...@@ -46,7 +46,7 @@ module Packages ...@@ -46,7 +46,7 @@ module Packages
.execute .execute
end end
package.build_infos.create!(pipeline: params[:build].pipeline) if params[:build].present? package.build_infos.safe_find_or_create_by!(pipeline: params[:build].pipeline) if params[:build].present?
package package
end end
......
...@@ -17,10 +17,6 @@ module Packages ...@@ -17,10 +17,6 @@ module Packages
def create_npm_package! def create_npm_package!
package = create_package!(:npm, name: name, version: version) package = create_package!(:npm, name: name, version: version)
if build.present?
package.build_infos.create!(pipeline: build.pipeline)
end
::Packages::CreatePackageFileService.new(package, file_params).execute ::Packages::CreatePackageFileService.new(package, file_params).execute
::Packages::CreateDependencyService.new(package, package_dependencies).execute ::Packages::CreateDependencyService.new(package, package_dependencies).execute
::Packages::Npm::CreateTagService.new(package, dist_tag).execute ::Packages::Npm::CreateTagService.new(package, dist_tag).execute
...@@ -50,10 +46,6 @@ module Packages ...@@ -50,10 +46,6 @@ module Packages
params[:versions][version] params[:versions][version]
end end
def build
params[:build]
end
def dist_tag def dist_tag
params['dist-tags'].each_key.first params['dist-tags'].each_key.first
end end
......
...@@ -19,6 +19,8 @@ module Packages ...@@ -19,6 +19,8 @@ module Packages
Packages::Pypi::Metadatum.upsert(meta.attributes) Packages::Pypi::Metadatum.upsert(meta.attributes)
::Packages::CreatePackageFileService.new(created_package, file_params).execute ::Packages::CreatePackageFileService.new(created_package, file_params).execute
created_package
end end
end end
...@@ -32,6 +34,7 @@ module Packages ...@@ -32,6 +34,7 @@ module Packages
def file_params def file_params
{ {
build: params[:build],
file: params[:content], file: params[:content],
file_name: params[:content].original_filename, file_name: params[:content].original_filename,
file_md5: params[:md5_digest], file_md5: params[:md5_digest],
......
---
title: Create package build_info records for Conan, NuGet, PyPI, and Composer packages
and package files
merge_request: 48811
author:
type: added
---
title: Fix bug in ProjectRepositoryStorageMove transition to scheduled
merge_request: 49105
author:
type: fixed
...@@ -498,6 +498,7 @@ To configure Praefect with TLS: ...@@ -498,6 +498,7 @@ To configure Praefect with TLS:
**For Omnibus GitLab** **For Omnibus GitLab**
1. Create certificates for Praefect servers. 1. Create certificates for Praefect servers.
1. On the Praefect servers, create the `/etc/gitlab/ssl` directory and copy your key 1. On the Praefect servers, create the `/etc/gitlab/ssl` directory and copy your key
and certificate there: and certificate there:
...@@ -516,7 +517,8 @@ To configure Praefect with TLS: ...@@ -516,7 +517,8 @@ To configure Praefect with TLS:
praefect['key_path'] = "/etc/gitlab/ssl/key.pem" praefect['key_path'] = "/etc/gitlab/ssl/key.pem"
``` ```
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). 1. Save the file and [reconfigure](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. On the Praefect clients (including each Gitaly server), copy the certificates, 1. On the Praefect clients (including each Gitaly server), copy the certificates,
or their certificate authority, into `/etc/gitlab/trusted-certs`: or their certificate authority, into `/etc/gitlab/trusted-certs`:
...@@ -529,8 +531,10 @@ To configure Praefect with TLS: ...@@ -529,8 +531,10 @@ To configure Praefect with TLS:
```ruby ```ruby
git_data_dirs({ git_data_dirs({
'default' => { 'gitaly_address' => 'tls://praefect1.internal:3305' }, "default" => {
'storage1' => { 'gitaly_address' => 'tls://praefect2.internal:3305' }, "gitaly_address" => 'tls://LOAD_BALANCER_SERVER_ADDRESS:2305',
"gitaly_token" => 'PRAEFECT_EXTERNAL_TOKEN'
}
}) })
``` ```
...@@ -565,10 +569,7 @@ To configure Praefect with TLS: ...@@ -565,10 +569,7 @@ To configure Praefect with TLS:
repositories: repositories:
storages: storages:
default: default:
gitaly_address: tls://praefect1.internal:3305 gitaly_address: tls://LOAD_BALANCER_SERVER_ADDRESS:3305
path: /some/local/path
storage1:
gitaly_address: tls://praefect2.internal:3305
path: /some/local/path path: /some/local/path
``` ```
...@@ -834,6 +835,8 @@ Particular attention should be shown to: ...@@ -834,6 +835,8 @@ Particular attention should be shown to:
balancer. balancer.
- `PRAEFECT_EXTERNAL_TOKEN` with the real secret - `PRAEFECT_EXTERNAL_TOKEN` with the real secret
If you are using TLS, the `gitaly_address` should begin with `tls://`.
```ruby ```ruby
git_data_dirs({ git_data_dirs({
"default" => { "default" => {
......
...@@ -104,37 +104,6 @@ describe('Component', () => { ...@@ -104,37 +104,6 @@ describe('Component', () => {
Remember that the performance of each test depends on the environment. Remember that the performance of each test depends on the environment.
### Timout error due to async components
If your component is fetching some other components asynchroneously based on some conditions, it might happen so that your Jest suite for this component will become flaky timing out from time to time.
```javascript
// ide.vue
export default {
components: {
'error-message': () => import('./error_message.vue'),
'gl-button': () => import('@gitlab/ui/src/components/base/button/button.vue'),
...
};
```
To address this issue, you can "help" Jest by stubbing the async components so that Jest would not need to fetch those asynchroneously at the run-time.
```javascript
// ide_spec.js
import { GlButton } from '@gitlab/ui';
import ErrorMessage from '~/ide/components/error_message.vue';
...
return shallowMount(ide, {
...
stubs: {
ErrorMessage,
GlButton,
...
},
})
```
## What and how to test ## What and how to test
Before jumping into more gritty details about Jest-specific workflows like mocks and spies, we should briefly cover what to test with Jest. Before jumping into more gritty details about Jest-specific workflows like mocks and spies, we should briefly cover what to test with Jest.
......
...@@ -160,6 +160,9 @@ Configure the GitLab integration with Jenkins. ...@@ -160,6 +160,9 @@ Configure the GitLab integration with Jenkins.
### Option 2: Webhook ### Option 2: Webhook
If you are unable to provide GitLab with your Jenkins server login, you can use this option
to integrate GitLab and Jenkins.
1. In the configuration of your Jenkins job, in the GitLab configuration section, click **Advanced**. 1. In the configuration of your Jenkins job, in the GitLab configuration section, click **Advanced**.
1. Click the **Generate** button under the **Secret Token** field. 1. Click the **Generate** button under the **Secret Token** field.
1. Copy the resulting token, and save the job configuration. 1. Copy the resulting token, and save the job configuration.
......
...@@ -132,7 +132,7 @@ module API ...@@ -132,7 +132,7 @@ module API
track_package_event('push_package', :composer) track_package_event('push_package', :composer)
::Packages::Composer::CreatePackageService ::Packages::Composer::CreatePackageService
.new(authorized_user_project, current_user, declared_params) .new(authorized_user_project, current_user, declared_params.merge(build: current_authenticated_job))
.execute .execute
created! created!
......
...@@ -164,7 +164,11 @@ module API ...@@ -164,7 +164,11 @@ module API
end end
def find_or_create_package def find_or_create_package
package || ::Packages::Conan::CreatePackageService.new(project, current_user, params).execute package || ::Packages::Conan::CreatePackageService.new(
project,
current_user,
params.merge(build: current_authenticated_job)
).execute
end end
def track_push_package_event def track_push_package_event
...@@ -184,7 +188,11 @@ module API ...@@ -184,7 +188,11 @@ module API
def create_package_file_with_type(file_type, current_package) def create_package_file_with_type(file_type, current_package)
unless params[:file].size == 0 # rubocop: disable Style/ZeroLengthPredicate unless params[:file].size == 0 # rubocop: disable Style/ZeroLengthPredicate
# conan sends two upload requests, the first has no file, so we skip record creation if file.size == 0 # conan sends two upload requests, the first has no file, so we skip record creation if file.size == 0
::Packages::Conan::CreatePackageFileService.new(current_package, params[:file], params.merge(conan_file_type: file_type)).execute ::Packages::Conan::CreatePackageFileService.new(
current_package,
params[:file],
params.merge(conan_file_type: file_type, build: current_authenticated_job)
).execute
end end
end end
......
...@@ -101,11 +101,16 @@ module API ...@@ -101,11 +101,16 @@ module API
file_name: PACKAGE_FILENAME file_name: PACKAGE_FILENAME
) )
package = ::Packages::Nuget::CreatePackageService.new(authorized_user_project, current_user) package = ::Packages::Nuget::CreatePackageService.new(
.execute authorized_user_project,
current_user,
package_file = ::Packages::CreatePackageFileService.new(package, file_params) declared_params.merge(build: current_authenticated_job)
.execute ).execute
package_file = ::Packages::CreatePackageFileService.new(
package,
file_params.merge(build: current_authenticated_job)
).execute
track_package_event('push_package', :nuget) track_package_event('push_package', :nuget)
......
...@@ -127,7 +127,7 @@ module API ...@@ -127,7 +127,7 @@ module API
track_package_event('push_package', :pypi) track_package_event('push_package', :pypi)
::Packages::Pypi::CreatePackageService ::Packages::Pypi::CreatePackageService
.new(authorized_user_project, current_user, declared_params) .new(authorized_user_project, current_user, declared_params.merge(build: current_authenticated_job))
.execute .execute
created! created!
......
import Vuex from 'vuex'; import Vuex from 'vuex';
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import { GlButton, GlLoadingIcon } from '@gitlab/ui'; import waitForPromises from 'helpers/wait_for_promises';
import { createStore } from '~/ide/stores'; import { createStore } from '~/ide/stores';
import ErrorMessage from '~/ide/components/error_message.vue'; import ErrorMessage from '~/ide/components/error_message.vue';
import FindFile from '~/vue_shared/components/file_finder/index.vue';
import CommitEditorHeader from '~/ide/components/commit_sidebar/editor_header.vue';
import RepoTabs from '~/ide/components/repo_tabs.vue';
import IdeStatusBar from '~/ide/components/ide_status_bar.vue';
import RightPane from '~/ide/components/panes/right.vue';
import NewModal from '~/ide/components/new_dropdown/modal.vue';
import ide from '~/ide/components/ide.vue'; import ide from '~/ide/components/ide.vue';
import { file } from '../helpers'; import { file } from '../helpers';
import { projectData } from '../mock_data'; import { projectData } from '../mock_data';
...@@ -39,17 +32,6 @@ describe('WebIDE', () => { ...@@ -39,17 +32,6 @@ describe('WebIDE', () => {
return shallowMount(ide, { return shallowMount(ide, {
store, store,
localVue, localVue,
stubs: {
ErrorMessage,
GlButton,
GlLoadingIcon,
CommitEditorHeader,
RepoTabs,
IdeStatusBar,
FindFile,
RightPane,
NewModal,
},
}); });
} }
...@@ -74,27 +56,24 @@ describe('WebIDE', () => { ...@@ -74,27 +56,24 @@ describe('WebIDE', () => {
describe('ide component, non-empty repo', () => { describe('ide component, non-empty repo', () => {
describe('error message', () => { describe('error message', () => {
it('does not show error message when it is not set', () => { it.each`
errorMessage | exists
${null} | ${false}
${{ text: 'error' }} | ${true}
`(
'should error message exists=$exists when errorMessage=$errorMessage',
async ({ errorMessage, exists }) => {
wrapper = createComponent({ wrapper = createComponent({
state: { state: {
errorMessage: null, errorMessage,
}, },
}); });
expect(wrapper.find(ErrorMessage).exists()).toBe(false); await waitForPromises();
});
it('shows error message when set', () => { expect(wrapper.find(ErrorMessage).exists()).toBe(exists);
wrapper = createComponent({
state: {
errorMessage: {
text: 'error',
}, },
}, );
});
expect(wrapper.find(ErrorMessage).exists()).toBe(true);
});
}); });
describe('onBeforeUnload', () => { describe('onBeforeUnload', () => {
......
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex'; import Vuex from 'vuex';
import { TEST_HOST } from 'spec/test_constants'; import { TEST_HOST } from 'spec/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
import TerminalEmptyState from '~/ide/components/terminal/empty_state.vue'; import TerminalEmptyState from '~/ide/components/terminal/empty_state.vue';
import TerminalView from '~/ide/components/terminal/view.vue'; import TerminalView from '~/ide/components/terminal/view.vue';
import TerminalSession from '~/ide/components/terminal/session.vue'; import TerminalSession from '~/ide/components/terminal/session.vue';
...@@ -17,7 +18,7 @@ describe('IDE TerminalView', () => { ...@@ -17,7 +18,7 @@ describe('IDE TerminalView', () => {
let getters; let getters;
let wrapper; let wrapper;
const factory = () => { const factory = async () => {
const store = new Vuex.Store({ const store = new Vuex.Store({
modules: { modules: {
terminal: { terminal: {
...@@ -30,6 +31,9 @@ describe('IDE TerminalView', () => { ...@@ -30,6 +31,9 @@ describe('IDE TerminalView', () => {
}); });
wrapper = shallowMount(TerminalView, { localVue, store }); wrapper = shallowMount(TerminalView, { localVue, store });
// Uses deferred components, so wait for those to load...
await waitForPromises();
}; };
beforeEach(() => { beforeEach(() => {
...@@ -59,8 +63,8 @@ describe('IDE TerminalView', () => { ...@@ -59,8 +63,8 @@ describe('IDE TerminalView', () => {
wrapper.destroy(); wrapper.destroy();
}); });
it('renders empty state', () => { it('renders empty state', async () => {
factory(); await factory();
expect(wrapper.find(TerminalEmptyState).props()).toEqual({ expect(wrapper.find(TerminalEmptyState).props()).toEqual({
helpPath: TEST_HELP_PATH, helpPath: TEST_HELP_PATH,
...@@ -69,8 +73,8 @@ describe('IDE TerminalView', () => { ...@@ -69,8 +73,8 @@ describe('IDE TerminalView', () => {
}); });
}); });
it('hides splash and starts, when started', () => { it('hides splash and starts, when started', async () => {
factory(); await factory();
expect(actions.startSession).not.toHaveBeenCalled(); expect(actions.startSession).not.toHaveBeenCalled();
expect(actions.hideSplash).not.toHaveBeenCalled(); expect(actions.hideSplash).not.toHaveBeenCalled();
...@@ -81,9 +85,9 @@ describe('IDE TerminalView', () => { ...@@ -81,9 +85,9 @@ describe('IDE TerminalView', () => {
expect(actions.hideSplash).toHaveBeenCalled(); expect(actions.hideSplash).toHaveBeenCalled();
}); });
it('shows Web Terminal when started', () => { it('shows Web Terminal when started', async () => {
state.isShowSplash = false; state.isShowSplash = false;
factory(); await factory();
expect(wrapper.find(TerminalEmptyState).exists()).toBe(false); expect(wrapper.find(TerminalEmptyState).exists()).toBe(false);
expect(wrapper.find(TerminalSession).exists()).toBe(true); expect(wrapper.find(TerminalSession).exists()).toBe(true);
......
...@@ -73,6 +73,17 @@ RSpec.describe ProjectRepositoryStorageMove, type: :model do ...@@ -73,6 +73,17 @@ RSpec.describe ProjectRepositoryStorageMove, type: :model do
expect(project).to be_repository_read_only expect(project).to be_repository_read_only
end end
context 'when the transition fails' do
it 'does not trigger ProjectUpdateRepositoryStorageWorker and adds an error' do
allow(storage_move.project).to receive(:set_repository_read_only!).and_raise(StandardError, 'foobar')
expect(ProjectUpdateRepositoryStorageWorker).not_to receive(:perform_async)
storage_move.schedule!
expect(storage_move.errors[:project]).to include('foobar')
end
end
end end
context 'and transits to started' do context 'and transits to started' do
......
...@@ -41,6 +41,8 @@ RSpec.describe Packages::Composer::CreatePackageService do ...@@ -41,6 +41,8 @@ RSpec.describe Packages::Composer::CreatePackageService do
it_behaves_like 'assigns the package creator' do it_behaves_like 'assigns the package creator' do
let(:package) { created_package } let(:package) { created_package }
end end
it_behaves_like 'assigns build to package'
end end
context 'with a tag' do context 'with a tag' do
...@@ -62,6 +64,8 @@ RSpec.describe Packages::Composer::CreatePackageService do ...@@ -62,6 +64,8 @@ RSpec.describe Packages::Composer::CreatePackageService do
it_behaves_like 'assigns the package creator' do it_behaves_like 'assigns the package creator' do
let(:package) { created_package } let(:package) { created_package }
end end
it_behaves_like 'assigns build to package'
end end
end end
......
...@@ -5,11 +5,12 @@ RSpec.describe Packages::Conan::CreatePackageFileService do ...@@ -5,11 +5,12 @@ RSpec.describe Packages::Conan::CreatePackageFileService do
include WorkhorseHelpers include WorkhorseHelpers
let_it_be(:package) { create(:conan_package) } let_it_be(:package) { create(:conan_package) }
let_it_be(:user) { create(:user) }
describe '#execute' do describe '#execute' do
let(:file_name) { 'foo.tgz' } let(:file_name) { 'foo.tgz' }
subject { described_class.new(package, file, params) } subject { described_class.new(package, file, params).execute }
shared_examples 'a valid package_file' do shared_examples 'a valid package_file' do
let(:params) do let(:params) do
...@@ -27,7 +28,7 @@ RSpec.describe Packages::Conan::CreatePackageFileService do ...@@ -27,7 +28,7 @@ RSpec.describe Packages::Conan::CreatePackageFileService do
end end
it 'creates a new package file' do it 'creates a new package file' do
package_file = subject.execute package_file = subject
expect(package_file).to be_valid expect(package_file).to be_valid
expect(package_file.file_name).to eq(file_name) expect(package_file.file_name).to eq(file_name)
...@@ -40,6 +41,8 @@ RSpec.describe Packages::Conan::CreatePackageFileService do ...@@ -40,6 +41,8 @@ RSpec.describe Packages::Conan::CreatePackageFileService do
expect(package_file.conan_file_metadatum.conan_file_type).to eq('package_file') expect(package_file.conan_file_metadatum.conan_file_type).to eq('package_file')
expect(package_file.file.read).to eq('content') expect(package_file.file.read).to eq('content')
end end
it_behaves_like 'assigns build to package file'
end end
shared_examples 'a valid recipe_file' do shared_examples 'a valid recipe_file' do
...@@ -56,7 +59,7 @@ RSpec.describe Packages::Conan::CreatePackageFileService do ...@@ -56,7 +59,7 @@ RSpec.describe Packages::Conan::CreatePackageFileService do
end end
it 'creates a new recipe file' do it 'creates a new recipe file' do
package_file = subject.execute package_file = subject
expect(package_file).to be_valid expect(package_file).to be_valid
expect(package_file.file_name).to eq(file_name) expect(package_file.file_name).to eq(file_name)
...@@ -69,6 +72,8 @@ RSpec.describe Packages::Conan::CreatePackageFileService do ...@@ -69,6 +72,8 @@ RSpec.describe Packages::Conan::CreatePackageFileService do
expect(package_file.conan_file_metadatum.conan_file_type).to eq('recipe_file') expect(package_file.conan_file_metadatum.conan_file_type).to eq('recipe_file')
expect(package_file.file.read).to eq('content') expect(package_file.file.read).to eq('content')
end end
it_behaves_like 'assigns build to package file'
end end
context 'with temp file' do context 'with temp file' do
...@@ -123,7 +128,7 @@ RSpec.describe Packages::Conan::CreatePackageFileService do ...@@ -123,7 +128,7 @@ RSpec.describe Packages::Conan::CreatePackageFileService do
end end
it 'raises an error' do it 'raises an error' do
expect { subject.execute }.to raise_error(ActiveRecord::RecordInvalid) expect { subject }.to raise_error(ActiveRecord::RecordInvalid)
end end
end end
end end
......
...@@ -30,6 +30,7 @@ RSpec.describe Packages::Conan::CreatePackageService do ...@@ -30,6 +30,7 @@ RSpec.describe Packages::Conan::CreatePackageService do
end end
it_behaves_like 'assigns the package creator' it_behaves_like 'assigns the package creator'
it_behaves_like 'assigns build to package'
end end
context 'invalid params' do context 'invalid params' do
......
...@@ -4,10 +4,11 @@ require 'spec_helper' ...@@ -4,10 +4,11 @@ require 'spec_helper'
RSpec.describe Packages::CreatePackageFileService do RSpec.describe Packages::CreatePackageFileService do
let_it_be(:package) { create(:maven_package) } let_it_be(:package) { create(:maven_package) }
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
let(:service) { described_class.new(package, params) }
subject { described_class.new(package, params) }
describe '#execute' do describe '#execute' do
subject { service.execute }
context 'with valid params' do context 'with valid params' do
let(:params) do let(:params) do
{ {
...@@ -17,11 +18,13 @@ RSpec.describe Packages::CreatePackageFileService do ...@@ -17,11 +18,13 @@ RSpec.describe Packages::CreatePackageFileService do
end end
it 'creates a new package file' do it 'creates a new package file' do
package_file = subject.execute package_file = subject
expect(package_file).to be_valid expect(package_file).to be_valid
expect(package_file.file_name).to eq('foo.jar') expect(package_file.file_name).to eq('foo.jar')
end end
it_behaves_like 'assigns build to package file'
end end
context 'file is missing' do context 'file is missing' do
...@@ -32,17 +35,7 @@ RSpec.describe Packages::CreatePackageFileService do ...@@ -32,17 +35,7 @@ RSpec.describe Packages::CreatePackageFileService do
end end
it 'raises an error' do it 'raises an error' do
expect { subject.execute }.to raise_error(ActiveRecord::RecordInvalid) expect { subject }.to raise_error(ActiveRecord::RecordInvalid)
end
end
context 'with a build' do
let_it_be(:pipeline) { create(:ci_pipeline, user: user) }
let(:build) { double('build', pipeline: pipeline) }
let(:params) { { file: Tempfile.new, file_name: 'foo.jar', build: build } }
it 'creates a build_info' do
expect { subject.execute }.to change { Packages::PackageFileBuildInfo.count }.by(1)
end end
end end
end end
......
...@@ -23,6 +23,8 @@ RSpec.describe Packages::Generic::CreatePackageFileService do ...@@ -23,6 +23,8 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
} }
end end
subject { described_class.new(project, user, params).execute }
before do before do
FileUtils.touch(temp_file) FileUtils.touch(temp_file)
end end
...@@ -41,9 +43,7 @@ RSpec.describe Packages::Generic::CreatePackageFileService do ...@@ -41,9 +43,7 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
expect(::Packages::Generic::FindOrCreatePackageService).to receive(:new).with(project, user, package_params).and_return(package_service) expect(::Packages::Generic::FindOrCreatePackageService).to receive(:new).with(project, user, package_params).and_return(package_service)
expect(package_service).to receive(:execute).and_return(package) expect(package_service).to receive(:execute).and_return(package)
service = described_class.new(project, user, params) expect { subject }.to change { package.package_files.count }.by(1)
expect { service.execute }.to change { package.package_files.count }.by(1)
.and change { Packages::PackageFileBuildInfo.count }.by(1) .and change { Packages::PackageFileBuildInfo.count }.by(1)
package_file = package.package_files.last package_file = package.package_files.last
...@@ -54,5 +54,7 @@ RSpec.describe Packages::Generic::CreatePackageFileService do ...@@ -54,5 +54,7 @@ RSpec.describe Packages::Generic::CreatePackageFileService do
expect(package_file.file_sha256).to eq(sha256) expect(package_file.file_sha256).to eq(sha256)
end end
end end
it_behaves_like 'assigns build to package file'
end end
end end
...@@ -31,5 +31,6 @@ RSpec.describe Packages::Nuget::CreatePackageService do ...@@ -31,5 +31,6 @@ RSpec.describe Packages::Nuget::CreatePackageService do
end end
it_behaves_like 'assigns the package creator' it_behaves_like 'assigns the package creator'
it_behaves_like 'assigns build to package'
end end
end end
...@@ -51,6 +51,8 @@ RSpec.describe Packages::Pypi::CreatePackageService do ...@@ -51,6 +51,8 @@ RSpec.describe Packages::Pypi::CreatePackageService do
let(:package) { created_package } let(:package) { created_package }
end end
it_behaves_like 'assigns build to package'
context 'with an existing package' do context 'with an existing package' do
before do before do
described_class.new(project, user, params).execute described_class.new(project, user, params).execute
......
...@@ -14,6 +14,24 @@ RSpec.shared_examples 'assigns build to package' do ...@@ -14,6 +14,24 @@ RSpec.shared_examples 'assigns build to package' do
end end
end end
RSpec.shared_examples 'assigns build to package file' do
context 'with build info' do
let(:job) { create(:ci_build, user: user) }
let(:params) { super().merge(build: job) }
it 'assigns the pipeline to the package' do
package_file = subject
expect(package_file.package_file_build_infos).to be_present
expect(package_file.pipelines.first).to eq job.pipeline
end
it 'creates a new PackageFileBuildInfo record' do
expect { subject }.to change { Packages::PackageFileBuildInfo.count }.by(1)
end
end
end
RSpec.shared_examples 'assigns the package creator' do RSpec.shared_examples 'assigns the package creator' do
it 'assigns the package creator' do it 'assigns the package creator' do
subject subject
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment