diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-15 00:09:08 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-02-15 00:09:08 +0300 |
commit | 866ca4e49ff74ffadf8e6f6ff663a168489c2aba (patch) | |
tree | cc3135b1bae11dbd1cb3a30cb547473ad89a5551 | |
parent | 26a50872e9da9509c52c70f74dc21698fec906db (diff) |
Add latest changes from gitlab-org/gitlab@master
107 files changed, 688 insertions, 252 deletions
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml index c18453b778c..7171f94decc 100644 --- a/.gitlab/ci/global.gitlab-ci.yml +++ b/.gitlab/ci/global.gitlab-ci.yml @@ -203,6 +203,8 @@ - name: postgres:9.6 command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] - name: redis:alpine + variables: + POSTGRES_HOST_AUTH_METHOD: trust .use-pg10: image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.6.5-golang-1.12-git-2.24-lfs-2.9-chrome-73.0-node-12.x-yarn-1.21-postgresql-10-graphicsmagick-1.3.34" @@ -210,6 +212,8 @@ - name: postgres:10.9 command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] - name: redis:alpine + variables: + POSTGRES_HOST_AUTH_METHOD: trust .use-pg9-ee: services: @@ -217,6 +221,8 @@ command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] - name: redis:alpine - name: elasticsearch:6.4.2 + variables: + POSTGRES_HOST_AUTH_METHOD: trust .use-pg10-ee: image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.6.5-golang-1.12-git-2.24-lfs-2.9-chrome-73.0-node-12.x-yarn-1.21-postgresql-10-graphicsmagick-1.3.34" @@ -225,6 +231,8 @@ command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] - name: redis:alpine - name: elasticsearch:6.4.2 + variables: + POSTGRES_HOST_AUTH_METHOD: trust .only-ee: only: diff --git a/app/assets/javascripts/monitoring/stores/actions.js b/app/assets/javascripts/monitoring/stores/actions.js index 3a052200ab9..8bb5047ef04 100644 --- a/app/assets/javascripts/monitoring/stores/actions.js +++ b/app/assets/javascripts/monitoring/stores/actions.js @@ -6,7 +6,7 @@ import { gqClient, parseEnvironmentsResponse, removeLeadingSlash } from './utils import trackDashboardLoad from '../monitoring_tracking_helper'; import getEnvironments from '../queries/getEnvironments.query.graphql'; import statusCodes from '../../lib/utils/http_status'; -import { backOff } from '../../lib/utils/common_utils'; +import { backOff, convertObjectPropsToCamelCase } from '../../lib/utils/common_utils'; import { s__, sprintf } from '../../locale'; import { PROMETHEUS_TIMEOUT } from '../constants'; @@ -52,6 +52,8 @@ export const requestMetricsDashboard = ({ commit }) => { export const receiveMetricsDashboardSuccess = ({ commit, dispatch }, { response, params }) => { commit(types.SET_ALL_DASHBOARDS, response.all_dashboards); commit(types.RECEIVE_METRICS_DATA_SUCCESS, response.dashboard); + commit(types.SET_ENDPOINTS, convertObjectPropsToCamelCase(response.metrics_data)); + return dispatch('fetchPrometheusMetrics', params); }; export const receiveMetricsDashboardFailure = ({ commit }, error) => { diff --git a/app/assets/javascripts/monitoring/stores/mutations.js b/app/assets/javascripts/monitoring/stores/mutations.js index 5f559290ff7..8bd53a24b61 100644 --- a/app/assets/javascripts/monitoring/stores/mutations.js +++ b/app/assets/javascripts/monitoring/stores/mutations.js @@ -1,4 +1,5 @@ import Vue from 'vue'; +import pick from 'lodash/pick'; import { slugify } from '~/lib/utils/text_utility'; import * as types from './mutation_types'; import { normalizeMetric, normalizeQueryResult } from './utils'; @@ -174,15 +175,19 @@ export default { state: emptyStateFromError(error), }); }, - - [types.SET_ENDPOINTS](state, endpoints) { - state.metricsEndpoint = endpoints.metricsEndpoint; - state.deploymentsEndpoint = endpoints.deploymentsEndpoint; - state.dashboardEndpoint = endpoints.dashboardEndpoint; - state.dashboardsEndpoint = endpoints.dashboardsEndpoint; - state.currentDashboard = endpoints.currentDashboard; - state.projectPath = endpoints.projectPath; - state.logsPath = endpoints.logsPath || state.logsPath; + [types.SET_ENDPOINTS](state, endpoints = {}) { + const endpointKeys = [ + 'metricsEndpoint', + 'deploymentsEndpoint', + 'dashboardEndpoint', + 'dashboardsEndpoint', + 'currentDashboard', + 'projectPath', + 'logsPath', + ]; + Object.entries(pick(endpoints, endpointKeys)).forEach(([key, value]) => { + state[key] = value; + }); }, [types.SET_TIME_RANGE](state, timeRange) { state.timeRange = timeRange; diff --git a/app/assets/javascripts/pages/projects/releases/edit/index.js b/app/assets/javascripts/pages/projects/releases/edit/index.js index 98ec196fc37..efa059dcd6d 100644 --- a/app/assets/javascripts/pages/projects/releases/edit/index.js +++ b/app/assets/javascripts/pages/projects/releases/edit/index.js @@ -1,5 +1,5 @@ import ZenMode from '~/zen_mode'; -import initEditRelease from '~/releases/detail'; +import initEditRelease from '~/releases/mount_edit'; document.addEventListener('DOMContentLoaded', () => { new ZenMode(); // eslint-disable-line no-new diff --git a/app/assets/javascripts/pages/projects/releases/index/index.js b/app/assets/javascripts/pages/projects/releases/index/index.js index 6402023149f..24c9cd528b3 100644 --- a/app/assets/javascripts/pages/projects/releases/index/index.js +++ b/app/assets/javascripts/pages/projects/releases/index/index.js @@ -1,3 +1,3 @@ -import initReleases from '~/releases/list'; +import initReleases from '~/releases/mount_index'; document.addEventListener('DOMContentLoaded', initReleases); diff --git a/app/assets/javascripts/releases/detail/components/app.vue b/app/assets/javascripts/releases/components/app_edit.vue index 073cfcd7694..bdc2b3abb8c 100644 --- a/app/assets/javascripts/releases/detail/components/app.vue +++ b/app/assets/javascripts/releases/components/app_edit.vue @@ -7,7 +7,7 @@ import MarkdownField from '~/vue_shared/components/markdown/field.vue'; import autofocusonshow from '~/vue_shared/directives/autofocusonshow'; export default { - name: 'ReleaseDetailApp', + name: 'ReleaseEditApp', components: { GlFormInput, GlFormGroup, @@ -18,7 +18,7 @@ export default { autofocusonshow, }, computed: { - ...mapState([ + ...mapState('detail', [ 'isFetchingRelease', 'fetchError', 'markdownDocsPath', @@ -42,7 +42,7 @@ export default { ); }, tagName() { - return this.$store.state.release.tagName; + return this.$store.state.detail.release.tagName; }, tagNameHintText() { return sprintf( @@ -60,7 +60,7 @@ export default { }, releaseTitle: { get() { - return this.$store.state.release.name; + return this.$store.state.detail.release.name; }, set(title) { this.updateReleaseTitle(title); @@ -68,7 +68,7 @@ export default { }, releaseNotes: { get() { - return this.$store.state.release.description; + return this.$store.state.detail.release.description; }, set(notes) { this.updateReleaseNotes(notes); @@ -79,7 +79,7 @@ export default { this.fetchRelease(); }, methods: { - ...mapActions([ + ...mapActions('detail', [ 'fetchRelease', 'updateRelease', 'updateReleaseTitle', diff --git a/app/assets/javascripts/releases/list/components/app.vue b/app/assets/javascripts/releases/components/app_index.vue index eb63e709ebd..f602c9fdda2 100644 --- a/app/assets/javascripts/releases/list/components/app.vue +++ b/app/assets/javascripts/releases/components/app_index.vue @@ -32,7 +32,7 @@ export default { }, }, computed: { - ...mapState(['isLoading', 'releases', 'hasError', 'pageInfo']), + ...mapState('list', ['isLoading', 'releases', 'hasError', 'pageInfo']), shouldRenderEmptyState() { return !this.releases.length && !this.hasError && !this.isLoading; }, @@ -47,7 +47,7 @@ export default { }); }, methods: { - ...mapActions(['fetchReleases']), + ...mapActions('list', ['fetchReleases']), onChangePage(page) { historyPushState(buildUrlWithCurrentLocation(`?page=${page}`)); this.fetchReleases({ page, projectId: this.projectId }); diff --git a/app/assets/javascripts/releases/list/components/evidence_block.vue b/app/assets/javascripts/releases/components/evidence_block.vue index d9abd195fee..d9abd195fee 100644 --- a/app/assets/javascripts/releases/list/components/evidence_block.vue +++ b/app/assets/javascripts/releases/components/evidence_block.vue diff --git a/app/assets/javascripts/releases/list/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue index e6bb5325120..e6bb5325120 100644 --- a/app/assets/javascripts/releases/list/components/release_block.vue +++ b/app/assets/javascripts/releases/components/release_block.vue diff --git a/app/assets/javascripts/releases/list/components/release_block_assets.vue b/app/assets/javascripts/releases/components/release_block_assets.vue index 06b7f97a8de..06b7f97a8de 100644 --- a/app/assets/javascripts/releases/list/components/release_block_assets.vue +++ b/app/assets/javascripts/releases/components/release_block_assets.vue diff --git a/app/assets/javascripts/releases/list/components/release_block_author.vue b/app/assets/javascripts/releases/components/release_block_author.vue index e7075d4d67a..e7075d4d67a 100644 --- a/app/assets/javascripts/releases/list/components/release_block_author.vue +++ b/app/assets/javascripts/releases/components/release_block_author.vue diff --git a/app/assets/javascripts/releases/list/components/release_block_footer.vue b/app/assets/javascripts/releases/components/release_block_footer.vue index 8533fc17ffd..8533fc17ffd 100644 --- a/app/assets/javascripts/releases/list/components/release_block_footer.vue +++ b/app/assets/javascripts/releases/components/release_block_footer.vue diff --git a/app/assets/javascripts/releases/list/components/release_block_header.vue b/app/assets/javascripts/releases/components/release_block_header.vue index b459418aef2..b459418aef2 100644 --- a/app/assets/javascripts/releases/list/components/release_block_header.vue +++ b/app/assets/javascripts/releases/components/release_block_header.vue diff --git a/app/assets/javascripts/releases/list/components/release_block_metadata.vue b/app/assets/javascripts/releases/components/release_block_metadata.vue index f0aad594062..f0aad594062 100644 --- a/app/assets/javascripts/releases/list/components/release_block_metadata.vue +++ b/app/assets/javascripts/releases/components/release_block_metadata.vue diff --git a/app/assets/javascripts/releases/list/components/release_block_milestone_info.vue b/app/assets/javascripts/releases/components/release_block_milestone_info.vue index d3e354d6157..d3e354d6157 100644 --- a/app/assets/javascripts/releases/list/components/release_block_milestone_info.vue +++ b/app/assets/javascripts/releases/components/release_block_milestone_info.vue diff --git a/app/assets/javascripts/releases/list/components/release_block_milestones.vue b/app/assets/javascripts/releases/components/release_block_milestones.vue index a3dff75b828..a3dff75b828 100644 --- a/app/assets/javascripts/releases/list/components/release_block_milestones.vue +++ b/app/assets/javascripts/releases/components/release_block_milestones.vue diff --git a/app/assets/javascripts/releases/list/constants.js b/app/assets/javascripts/releases/constants.js index defcd917465..defcd917465 100644 --- a/app/assets/javascripts/releases/list/constants.js +++ b/app/assets/javascripts/releases/constants.js diff --git a/app/assets/javascripts/releases/detail/index.js b/app/assets/javascripts/releases/detail/index.js deleted file mode 100644 index 0dab90a1ede..00000000000 --- a/app/assets/javascripts/releases/detail/index.js +++ /dev/null @@ -1,19 +0,0 @@ -import Vue from 'vue'; -import ReleaseDetailApp from './components/app.vue'; -import createStore from './store'; - -export default () => { - const el = document.getElementById('js-edit-release-page'); - - const store = createStore(); - store.dispatch('setInitialState', el.dataset); - - return new Vue({ - el, - store, - components: { ReleaseDetailApp }, - render(createElement) { - return createElement('release-detail-app'); - }, - }); -}; diff --git a/app/assets/javascripts/releases/detail/store/index.js b/app/assets/javascripts/releases/detail/store/index.js deleted file mode 100644 index e8623a49356..00000000000 --- a/app/assets/javascripts/releases/detail/store/index.js +++ /dev/null @@ -1,14 +0,0 @@ -import Vue from 'vue'; -import Vuex from 'vuex'; -import * as actions from './actions'; -import mutations from './mutations'; -import state from './state'; - -Vue.use(Vuex); - -export default () => - new Vuex.Store({ - actions, - mutations, - state, - }); diff --git a/app/assets/javascripts/releases/list/index.js b/app/assets/javascripts/releases/list/index.js deleted file mode 100644 index adbed3cb8e2..00000000000 --- a/app/assets/javascripts/releases/list/index.js +++ /dev/null @@ -1,24 +0,0 @@ -import Vue from 'vue'; -import App from './components/app.vue'; -import createStore from './store'; - -export default () => { - const element = document.getElementById('js-releases-page'); - - return new Vue({ - el: element, - store: createStore(), - components: { - App, - }, - render(createElement) { - return createElement('app', { - props: { - projectId: element.dataset.projectId, - documentationLink: element.dataset.documentationPath, - illustrationPath: element.dataset.illustrationPath, - }, - }); - }, - }); -}; diff --git a/app/assets/javascripts/releases/list/store/index.js b/app/assets/javascripts/releases/list/store/index.js deleted file mode 100644 index 968b94f0e0d..00000000000 --- a/app/assets/javascripts/releases/list/store/index.js +++ /dev/null @@ -1,14 +0,0 @@ -import Vue from 'vue'; -import Vuex from 'vuex'; -import state from './state'; -import * as actions from './actions'; -import mutations from './mutations'; - -Vue.use(Vuex); - -export default () => - new Vuex.Store({ - actions, - mutations, - state: state(), - }); diff --git a/app/assets/javascripts/releases/mount_edit.js b/app/assets/javascripts/releases/mount_edit.js new file mode 100644 index 00000000000..343de8c56d3 --- /dev/null +++ b/app/assets/javascripts/releases/mount_edit.js @@ -0,0 +1,17 @@ +import Vue from 'vue'; +import ReleaseEditApp from './components/app_edit.vue'; +import createStore from './stores'; +import detailModule from './stores/modules/detail'; + +export default () => { + const el = document.getElementById('js-edit-release-page'); + + const store = createStore({ detail: detailModule }); + store.dispatch('setInitialState', el.dataset); + + return new Vue({ + el, + store, + render: h => h(ReleaseEditApp), + }); +}; diff --git a/app/assets/javascripts/releases/mount_index.js b/app/assets/javascripts/releases/mount_index.js new file mode 100644 index 00000000000..6fcb6d802e4 --- /dev/null +++ b/app/assets/javascripts/releases/mount_index.js @@ -0,0 +1,21 @@ +import Vue from 'vue'; +import ReleaseListApp from './components/app_index.vue'; +import createStore from './stores'; +import listModule from './stores/modules/list'; + +export default () => { + const el = document.getElementById('js-releases-page'); + + return new Vue({ + el, + store: createStore({ list: listModule }), + render: h => + h(ReleaseListApp, { + props: { + projectId: el.dataset.projectId, + documentationLink: el.dataset.documentationPath, + illustrationPath: el.dataset.illustrationPath, + }, + }), + }); +}; diff --git a/app/assets/javascripts/releases/stores/index.js b/app/assets/javascripts/releases/stores/index.js new file mode 100644 index 00000000000..aa607906a0e --- /dev/null +++ b/app/assets/javascripts/releases/stores/index.js @@ -0,0 +1,6 @@ +import Vue from 'vue'; +import Vuex from 'vuex'; + +Vue.use(Vuex); + +export default modules => new Vuex.Store({ modules }); diff --git a/app/assets/javascripts/releases/detail/store/actions.js b/app/assets/javascripts/releases/stores/modules/detail/actions.js index c9749582f5c..c9749582f5c 100644 --- a/app/assets/javascripts/releases/detail/store/actions.js +++ b/app/assets/javascripts/releases/stores/modules/detail/actions.js diff --git a/app/assets/javascripts/releases/stores/modules/detail/index.js b/app/assets/javascripts/releases/stores/modules/detail/index.js new file mode 100644 index 00000000000..243c2389d8c --- /dev/null +++ b/app/assets/javascripts/releases/stores/modules/detail/index.js @@ -0,0 +1,10 @@ +import * as actions from './actions'; +import mutations from './mutations'; +import state from './state'; + +export default { + namespaced: true, + actions, + mutations, + state, +}; diff --git a/app/assets/javascripts/releases/detail/store/mutation_types.js b/app/assets/javascripts/releases/stores/modules/detail/mutation_types.js index 75e1d78a645..75e1d78a645 100644 --- a/app/assets/javascripts/releases/detail/store/mutation_types.js +++ b/app/assets/javascripts/releases/stores/modules/detail/mutation_types.js diff --git a/app/assets/javascripts/releases/detail/store/mutations.js b/app/assets/javascripts/releases/stores/modules/detail/mutations.js index d739978d755..d739978d755 100644 --- a/app/assets/javascripts/releases/detail/store/mutations.js +++ b/app/assets/javascripts/releases/stores/modules/detail/mutations.js diff --git a/app/assets/javascripts/releases/detail/store/state.js b/app/assets/javascripts/releases/stores/modules/detail/state.js index 7e3d975f1ae..7e3d975f1ae 100644 --- a/app/assets/javascripts/releases/detail/store/state.js +++ b/app/assets/javascripts/releases/stores/modules/detail/state.js diff --git a/app/assets/javascripts/releases/list/store/actions.js b/app/assets/javascripts/releases/stores/modules/list/actions.js index b15fb69226f..b15fb69226f 100644 --- a/app/assets/javascripts/releases/list/store/actions.js +++ b/app/assets/javascripts/releases/stores/modules/list/actions.js diff --git a/app/assets/javascripts/releases/stores/modules/list/index.js b/app/assets/javascripts/releases/stores/modules/list/index.js new file mode 100644 index 00000000000..e4633b15a0c --- /dev/null +++ b/app/assets/javascripts/releases/stores/modules/list/index.js @@ -0,0 +1,10 @@ +import state from './state'; +import * as actions from './actions'; +import mutations from './mutations'; + +export default { + namespaced: true, + actions, + mutations, + state, +}; diff --git a/app/assets/javascripts/releases/list/store/mutation_types.js b/app/assets/javascripts/releases/stores/modules/list/mutation_types.js index a74bf15c515..a74bf15c515 100644 --- a/app/assets/javascripts/releases/list/store/mutation_types.js +++ b/app/assets/javascripts/releases/stores/modules/list/mutation_types.js diff --git a/app/assets/javascripts/releases/list/store/mutations.js b/app/assets/javascripts/releases/stores/modules/list/mutations.js index 99fc096264a..99fc096264a 100644 --- a/app/assets/javascripts/releases/list/store/mutations.js +++ b/app/assets/javascripts/releases/stores/modules/list/mutations.js diff --git a/app/assets/javascripts/releases/list/store/state.js b/app/assets/javascripts/releases/stores/modules/list/state.js index c251f56c9c5..c251f56c9c5 100644 --- a/app/assets/javascripts/releases/list/store/state.js +++ b/app/assets/javascripts/releases/stores/modules/list/state.js diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 8a583e16c0b..54c9bde067d 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -56,7 +56,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController end def clear_repository_check_states - RepositoryCheck::ClearWorker.perform_async + RepositoryCheck::ClearWorker.perform_async # rubocop:disable CodeReuse/Worker redirect_to( general_admin_application_settings_path, @@ -73,7 +73,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController # Specs are in spec/requests/self_monitoring_project_spec.rb def create_self_monitoring_project - job_id = SelfMonitoringProjectCreateWorker.perform_async + job_id = SelfMonitoringProjectCreateWorker.perform_async # rubocop:disable CodeReuse/Worker render status: :accepted, json: { job_id: job_id, @@ -92,7 +92,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController } end - if SelfMonitoringProjectCreateWorker.in_progress?(job_id) + if SelfMonitoringProjectCreateWorker.in_progress?(job_id) # rubocop:disable CodeReuse/Worker ::Gitlab::PollingInterval.set_header(response, interval: 3_000) return render status: :accepted, json: { @@ -112,7 +112,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController # Specs are in spec/requests/self_monitoring_project_spec.rb def delete_self_monitoring_project - job_id = SelfMonitoringProjectDeleteWorker.perform_async + job_id = SelfMonitoringProjectDeleteWorker.perform_async # rubocop:disable CodeReuse/Worker render status: :accepted, json: { job_id: job_id, @@ -131,7 +131,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController } end - if SelfMonitoringProjectDeleteWorker.in_progress?(job_id) + if SelfMonitoringProjectDeleteWorker.in_progress?(job_id) # rubocop:disable CodeReuse/Worker ::Gitlab::PollingInterval.set_header(response, interval: 3_000) return render status: :accepted, json: { diff --git a/app/controllers/admin/projects_controller.rb b/app/controllers/admin/projects_controller.rb index cdedc34e634..7015da8bd50 100644 --- a/app/controllers/admin/projects_controller.rb +++ b/app/controllers/admin/projects_controller.rb @@ -55,7 +55,7 @@ class Admin::ProjectsController < Admin::ApplicationController # rubocop: enable CodeReuse/ActiveRecord def repository_check - RepositoryCheck::SingleRepositoryWorker.perform_async(@project.id) + RepositoryCheck::SingleRepositoryWorker.perform_async(@project.id) # rubocop:disable CodeReuse/Worker redirect_to( admin_project_path(@project), diff --git a/app/controllers/admin/services_controller.rb b/app/controllers/admin/services_controller.rb index e31e0e09978..50b79cde5c5 100644 --- a/app/controllers/admin/services_controller.rb +++ b/app/controllers/admin/services_controller.rb @@ -19,7 +19,7 @@ class Admin::ServicesController < Admin::ApplicationController def update if service.update(service_params[:service]) - PropagateServiceTemplateWorker.perform_async(service.id) if service.active? + PropagateServiceTemplateWorker.perform_async(service.id) if service.active? # rubocop:disable CodeReuse/Worker redirect_to admin_application_settings_services_path, notice: 'Application settings saved successfully' diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 0944d7b47bf..35f803302eb 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -188,7 +188,7 @@ class Projects::IssuesController < Projects::ApplicationController def import_csv if uploader = UploadService.new(project, params[:file]).execute - ImportIssuesCsvWorker.perform_async(current_user.id, project.id, uploader.upload.id) + ImportIssuesCsvWorker.perform_async(current_user.id, project.id, uploader.upload.id) # rubocop:disable CodeReuse/Worker flash[:notice] = _("Your issues are being imported. Once finished, you'll get a confirmation email.") else diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb index 6a7e2b69652..ead839e8441 100644 --- a/app/controllers/projects/pipeline_schedules_controller.rb +++ b/app/controllers/projects/pipeline_schedules_controller.rb @@ -47,7 +47,7 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController end def play - job_id = RunPipelineScheduleWorker.perform_async(schedule.id, current_user.id) + job_id = RunPipelineScheduleWorker.perform_async(schedule.id, current_user.id) # rubocop:disable CodeReuse/Worker if job_id pipelines_link_start = "<a href=\"#{project_pipelines_path(@project)}\">" diff --git a/app/controllers/projects/registry/repositories_controller.rb b/app/controllers/projects/registry/repositories_controller.rb index b31a74540e2..e524d1c29a2 100644 --- a/app/controllers/projects/registry/repositories_controller.rb +++ b/app/controllers/projects/registry/repositories_controller.rb @@ -32,7 +32,7 @@ module Projects end def destroy - DeleteContainerRepositoryWorker.perform_async(current_user.id, image.id) + DeleteContainerRepositoryWorker.perform_async(current_user.id, image.id) # rubocop:disable CodeReuse/Worker track_event(:delete_repository) respond_to do |format| diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb index 6af815b8daa..bf0c2d885f8 100644 --- a/app/controllers/projects/settings/ci_cd_controller.rb +++ b/app/controllers/projects/settings/ci_cd_controller.rb @@ -69,7 +69,9 @@ module Projects return end + # rubocop:disable CodeReuse/Worker CreatePipelineWorker.perform_async(project.id, current_user.id, project.default_branch, :web, ignore_skip_ci: true, save_on_errors: false) + # rubocop:enable CodeReuse/Worker pipelines_link_start = '<a href="%{url}">'.html_safe % { url: project_pipelines_path(@project) } flash[:toast] = _("A new Auto DevOps pipeline has been created, go to %{pipelines_link_start}Pipelines page%{pipelines_link_end} for details") % { pipelines_link_start: pipelines_link_start, pipelines_link_end: "</a>".html_safe } diff --git a/app/controllers/projects/settings/repository_controller.rb b/app/controllers/projects/settings/repository_controller.rb index 0c634bbea03..63f5d5073a7 100644 --- a/app/controllers/projects/settings/repository_controller.rb +++ b/app/controllers/projects/settings/repository_controller.rb @@ -25,7 +25,7 @@ module Projects result = Projects::UpdateService.new(project, current_user, cleanup_params).execute if result[:status] == :success - RepositoryCleanupWorker.perform_async(project.id, current_user.id) + RepositoryCleanupWorker.perform_async(project.id, current_user.id) # rubocop:disable CodeReuse/Worker flash[:notice] = _('Repository cleanup has started. You will receive an email once the cleanup operation is complete.') else flash[:alert] = _('Failed to upload object map file') diff --git a/app/controllers/repositories/git_http_controller.rb b/app/controllers/repositories/git_http_controller.rb index 82431ae286a..75c79881264 100644 --- a/app/controllers/repositories/git_http_controller.rb +++ b/app/controllers/repositories/git_http_controller.rb @@ -80,7 +80,7 @@ module Repositories return unless repo_type.project? return unless project&.daily_statistics_enabled? - ProjectDailyStatisticsWorker.perform_async(project.id) + ProjectDailyStatisticsWorker.perform_async(project.id) # rubocop:disable CodeReuse/Worker end def access diff --git a/app/helpers/analytics_navbar_helper.rb b/app/helpers/analytics_navbar_helper.rb index bbb7470d1fd..021b9bb10cd 100644 --- a/app/helpers/analytics_navbar_helper.rb +++ b/app/helpers/analytics_navbar_helper.rb @@ -31,7 +31,7 @@ module AnalyticsNavbarHelper end def cycle_analytics_navbar_link(project, current_user) - return unless Feature.enabled?(:analytics_pages_under_project_analytics_sidebar, project) + return unless Feature.enabled?(:analytics_pages_under_project_analytics_sidebar, project, default_enabled: true) return unless project_nav_tab?(:cycle_analytics) navbar_sub_item( @@ -43,7 +43,7 @@ module AnalyticsNavbarHelper end def repository_analytics_navbar_link(project, current_user) - return if Feature.disabled?(:analytics_pages_under_project_analytics_sidebar, project) + return if Feature.disabled?(:analytics_pages_under_project_analytics_sidebar, project, default_enabled: true) return if project.empty_repo? navbar_sub_item( @@ -55,7 +55,7 @@ module AnalyticsNavbarHelper end def ci_cd_analytics_navbar_link(project, current_user) - return unless Feature.enabled?(:analytics_pages_under_project_analytics_sidebar, project) + return unless Feature.enabled?(:analytics_pages_under_project_analytics_sidebar, project, default_enabled: true) return unless project_nav_tab?(:pipelines) return unless project.feature_available?(:builds, current_user) || !project.empty_repo? diff --git a/app/services/ci/process_build_service.rb b/app/services/ci/process_build_service.rb index eb92c7d1a27..12cdca24066 100644 --- a/app/services/ci/process_build_service.rb +++ b/app/services/ci/process_build_service.rb @@ -3,7 +3,7 @@ module Ci class ProcessBuildService < BaseService def execute(build, current_status) - if valid_statuses_for_when(build.when).include?(current_status) + if valid_statuses_for_build(build).include?(current_status) if build.schedulable? build.schedule elsif build.action? @@ -25,10 +25,10 @@ module Ci build.enqueue end - def valid_statuses_for_when(value) - case value + def valid_statuses_for_build(build) + case build.when when 'on_success' - %w[success skipped] + build.scheduling_type_dag? ? %w[success] : %w[success skipped] when 'on_failure' %w[failed] when 'always' diff --git a/app/views/layouts/nav/sidebar/_analytics_links.html.haml b/app/views/layouts/nav/sidebar/_analytics_links.html.haml index b859a1ade66..e87cf92374a 100644 --- a/app/views/layouts/nav/sidebar/_analytics_links.html.haml +++ b/app/views/layouts/nav/sidebar/_analytics_links.html.haml @@ -6,10 +6,10 @@ = link_to navbar_links.first.link do .nav-icon-container = sprite_icon('chart') - %span.nav-item-name + %span.nav-item-name{ data: { qa_selector: 'analytics_link' } } = _('Analytics') - %ul.sidebar-sub-level-items + %ul.sidebar-sub-level-items{ data: { qa_selector: 'analytics_sidebar_submenu' } } - navbar_links.each do |menu_item| = nav_link(path: menu_item.path) do = link_to(menu_item.link, menu_item.link_to_options) do diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml index 60c5ef3877f..c00c48b623c 100644 --- a/app/views/layouts/nav/sidebar/_group.html.haml +++ b/app/views/layouts/nav/sidebar/_group.html.haml @@ -1,4 +1,4 @@ -- should_display_analytics_pages_in_sidebar = Feature.enabled?(:analytics_pages_under_group_analytics_sidebar, @group) +- should_display_analytics_pages_in_sidebar = Feature.enabled?(:analytics_pages_under_group_analytics_sidebar, @group, default_enabled: true) - issues_count = group_issues_count(state: 'opened') - merge_requests_count = group_merge_requests_count(state: 'opened') diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml index c587d0ca053..b9324f0596c 100644 --- a/app/views/layouts/nav/sidebar/_project.html.haml +++ b/app/views/layouts/nav/sidebar/_project.html.haml @@ -1,4 +1,4 @@ -- should_display_analytics_pages_in_sidebar = Feature.enabled?(:analytics_pages_under_project_analytics_sidebar, @project) +- should_display_analytics_pages_in_sidebar = Feature.enabled?(:analytics_pages_under_project_analytics_sidebar, @project, default_enabled: true) .nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?) } .nav-sidebar-inner-scroll @@ -9,7 +9,7 @@ = project_icon(@project, alt: @project.name, class: 'avatar s40 avatar-tile', width: 40, height: 40) .sidebar-context-title = @project.name - %ul.sidebar-top-level-items + %ul.sidebar-top-level-items.qa-project-sidebar - paths = sidebar_projects_paths - paths << 'cycle_analytics#show' unless should_display_analytics_pages_in_sidebar = nav_link(path: paths, html_options: { class: 'home' }) do diff --git a/changelogs/unreleased/31526-skip-if-needed-job-skipped.yml b/changelogs/unreleased/31526-skip-if-needed-job-skipped.yml new file mode 100644 index 00000000000..27b2e5f9b8e --- /dev/null +++ b/changelogs/unreleased/31526-skip-if-needed-job-skipped.yml @@ -0,0 +1,5 @@ +--- +title: Prevent DAG builds to run after skipped need build +merge_request: 23405 +author: +type: fixed diff --git a/changelogs/unreleased/55487-backfill-lfs-objects-projects-sql.yml b/changelogs/unreleased/55487-backfill-lfs-objects-projects-sql.yml new file mode 100644 index 00000000000..45dd3c6e9f5 --- /dev/null +++ b/changelogs/unreleased/55487-backfill-lfs-objects-projects-sql.yml @@ -0,0 +1,5 @@ +--- +title: Backfill LfsObjectsProject records of forks +merge_request: 24767 +author: +type: other diff --git a/changelogs/unreleased/georgekoltsov-object_builder_convert_empty_strings.yml b/changelogs/unreleased/georgekoltsov-object_builder_convert_empty_strings.yml new file mode 100644 index 00000000000..31eca8a2653 --- /dev/null +++ b/changelogs/unreleased/georgekoltsov-object_builder_convert_empty_strings.yml @@ -0,0 +1,6 @@ +--- +title: Fix Group Import existing objects lookup when description attribute is an empty + string +merge_request: 25187 +author: +type: fixed diff --git a/changelogs/unreleased/jcunha-update-managed-apps-template.yml b/changelogs/unreleased/jcunha-update-managed-apps-template.yml new file mode 100644 index 00000000000..145a15c6ae0 --- /dev/null +++ b/changelogs/unreleased/jcunha-update-managed-apps-template.yml @@ -0,0 +1,5 @@ +--- +title: Update cluster-applications to v0.8.0 +merge_request: 25138 +author: +type: changed diff --git a/changelogs/unreleased/toggle-analytics-navbar-feature-flags.yml b/changelogs/unreleased/toggle-analytics-navbar-feature-flags.yml new file mode 100644 index 00000000000..506e4fffdbb --- /dev/null +++ b/changelogs/unreleased/toggle-analytics-navbar-feature-flags.yml @@ -0,0 +1,5 @@ +--- +title: Move analytics pages under the sidebar for projects and groups +merge_request: 24470 +author: +type: changed diff --git a/db/post_migrate/20200210062432_schedule_link_lfs_objects.rb b/db/post_migrate/20200210062432_schedule_link_lfs_objects.rb new file mode 100644 index 00000000000..c955639c259 --- /dev/null +++ b/db/post_migrate/20200210062432_schedule_link_lfs_objects.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +class ScheduleLinkLfsObjects < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + MIGRATION = 'LinkLfsObjects' + BATCH_SIZE = 1_000 + + disable_ddl_transaction! + + class Project < ActiveRecord::Base + include EachBatch + + self.table_name = 'projects' + end + + def up + fork_network_members = + Gitlab::BackgroundMigration::LinkLfsObjects::ForkNetworkMember + .select(1) + .with_non_existing_lfs_objects + .where('fork_network_members.project_id = projects.id') + + forks = Project.where('EXISTS (?)', fork_network_members) + + queue_background_migration_jobs_by_range_at_intervals( + forks, + MIGRATION, + BackgroundMigrationWorker.minimum_interval, + batch_size: BATCH_SIZE + ) + end + + def down + # no-op + end +end diff --git a/doc/user/group/contribution_analytics/index.md b/doc/user/group/contribution_analytics/index.md index 4411c7834a4..1bbc40a14a4 100644 --- a/doc/user/group/contribution_analytics/index.md +++ b/doc/user/group/contribution_analytics/index.md @@ -16,7 +16,7 @@ group: - Merge requests - Push events -To view the Contribution Analytics, go to your group's **Overview > Contribution Analytics** +To view the Contribution Analytics, go to your group's **Analytics > Contribution Analytics** page. ## Use cases diff --git a/doc/user/group/insights/img/insights_sidebar_link.png b/doc/user/group/insights/img/insights_sidebar_link.png Binary files differdeleted file mode 100644 index f7b0c2daae3..00000000000 --- a/doc/user/group/insights/img/insights_sidebar_link.png +++ /dev/null diff --git a/doc/user/group/insights/img/insights_sidebar_link_v12_8.png b/doc/user/group/insights/img/insights_sidebar_link_v12_8.png Binary files differnew file mode 100644 index 00000000000..9a6d6bae766 --- /dev/null +++ b/doc/user/group/insights/img/insights_sidebar_link_v12_8.png diff --git a/doc/user/group/insights/index.md b/doc/user/group/insights/index.md index 7e933c66789..edbb85962ed 100644 --- a/doc/user/group/insights/index.md +++ b/doc/user/group/insights/index.md @@ -14,10 +14,10 @@ requests to be merged and much more. ## View your group's Insights -You can access your group's Insights by clicking the **Overview > Insights** +You can access your group's Insights by clicking the **Analytics > Insights** link in the left sidebar: -![Insights sidebar link](img/insights_sidebar_link.png) +![Insights sidebar link](img/insights_sidebar_link_v12_8.png) ## Configure your Insights diff --git a/doc/user/group/issues_analytics/img/issues_created_per_month.png b/doc/user/group/issues_analytics/img/issues_created_per_month.png Binary files differdeleted file mode 100644 index 96f0d36c917..00000000000 --- a/doc/user/group/issues_analytics/img/issues_created_per_month.png +++ /dev/null diff --git a/doc/user/group/issues_analytics/img/issues_created_per_month_v12_8.png b/doc/user/group/issues_analytics/img/issues_created_per_month_v12_8.png Binary files differnew file mode 100644 index 00000000000..b7dc2d3da8d --- /dev/null +++ b/doc/user/group/issues_analytics/img/issues_created_per_month_v12_8.png diff --git a/doc/user/group/issues_analytics/index.md b/doc/user/group/issues_analytics/index.md index f84a3a3c286..6c710885b98 100644 --- a/doc/user/group/issues_analytics/index.md +++ b/doc/user/group/issues_analytics/index.md @@ -10,7 +10,7 @@ Issues Analytics is a bar graph which illustrates the number of issues created e The default timespan is 13 months, which includes the current month, and the 12 months prior. -To access the chart, navigate to a group's sidebar and select **Issues > Analytics**. +To access the chart, navigate to a group's sidebar and select **Analytics > Issues Analytics**. Hover over each bar to see the total number of issues. @@ -28,7 +28,7 @@ You can change the total number of months displayed by setting a URL parameter. For example, `https://gitlab.com/groups/gitlab-org/-/issues_analytics?months_back=15` shows a total of 15 months for the chart in the GitLab.org group. -![Issues created per month](img/issues_created_per_month.png) +![Issues created per month](img/issues_created_per_month_v12_8.png) <!-- ## Troubleshooting diff --git a/doc/user/project/insights/img/insights_sidebar_link.png b/doc/user/project/insights/img/insights_sidebar_link.png Binary files differdeleted file mode 100644 index 9fc449baf68..00000000000 --- a/doc/user/project/insights/img/insights_sidebar_link.png +++ /dev/null diff --git a/doc/user/project/insights/img/insights_sidebar_link_v12_8.png b/doc/user/project/insights/img/insights_sidebar_link_v12_8.png Binary files differnew file mode 100644 index 00000000000..b07ecc5286a --- /dev/null +++ b/doc/user/project/insights/img/insights_sidebar_link_v12_8.png diff --git a/doc/user/project/insights/index.md b/doc/user/project/insights/index.md index 3fb661f9349..4af6f47ce7b 100644 --- a/doc/user/project/insights/index.md +++ b/doc/user/project/insights/index.md @@ -13,10 +13,10 @@ This feature is [also available at the group level](../../group/insights/index.m ## View your project's Insights -You can access your project's Insights by clicking the **Project > Insights** +You can access your project's Insights by clicking the **Analytics > Insights** link in the left sidebar: -![Insights sidebar link](img/insights_sidebar_link.png) +![Insights sidebar link](img/insights_sidebar_link_v12_8.png) ## Configure your Insights diff --git a/doc/user/project/integrations/img/prometheus_dashboard_area_panel_type.png b/doc/user/project/integrations/img/prometheus_dashboard_area_panel_type.png Binary files differdeleted file mode 100644 index 9fdb6dfddac..00000000000 --- a/doc/user/project/integrations/img/prometheus_dashboard_area_panel_type.png +++ /dev/null diff --git a/doc/user/project/integrations/img/prometheus_dashboard_area_panel_type_v12_8.png b/doc/user/project/integrations/img/prometheus_dashboard_area_panel_type_v12_8.png Binary files differnew file mode 100644 index 00000000000..8c5663fef12 --- /dev/null +++ b/doc/user/project/integrations/img/prometheus_dashboard_area_panel_type_v12_8.png diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md index cf98c002331..210ce4ffe56 100644 --- a/doc/user/project/integrations/prometheus.md +++ b/doc/user/project/integrations/prometheus.md @@ -285,7 +285,9 @@ Note the following properties: | type | string | no | Type of panel to be rendered. Optional for area panel types | | query_range | string | required | For area panel types, you must use a [range query](https://prometheus.io/docs/prometheus/latest/querying/api/#range-queries) | -![area panel type](img/prometheus_dashboard_area_panel_type.png) +![area panel chart](img/prometheus_dashboard_area_panel_type_v12_8.png) + +Starting in [version 12.8](https://gitlab.com/gitlab-org/gitlab/issues/202696), the y-axis values will automatically scale according to the data. Previously, it always started from 0. ##### Anomaly chart @@ -329,7 +331,7 @@ Note the following properties: ![anomaly panel type](img/prometheus_dashboard_anomaly_panel_type.png) -#### Column +##### Column chart To add a column panel type to a dashboard, look at the following sample dashboard file: diff --git a/doc/user/shortcuts.md b/doc/user/shortcuts.md index 54e7938d8f7..e7cb5e59be8 100644 --- a/doc/user/shortcuts.md +++ b/doc/user/shortcuts.md @@ -52,7 +52,7 @@ relatively quickly to work, and they will take you to another page in the projec | <kbd>t</kbd> | Go to the project file search page. (**Repository > Files**, click **Find Files**). | | <kbd>g</kbd> + <kbd>c</kbd> | Go to the project commits list (**Repository > Commits**). | | <kbd>g</kbd> + <kbd>n</kbd> | Go to the [repository graph](#repository-graph) page (**Repository > Graph**). | -| <kbd>g</kbd> + <kbd>d</kbd> | Go to repository charts (**Repository > Charts**). | +| <kbd>g</kbd> + <kbd>d</kbd> | Go to repository charts (**Analytics > Repository Analytics**). | | <kbd>g</kbd> + <kbd>i</kbd> | Go to the project issues list (**Issues > List**). | | <kbd>i</kbd> | Go to the New Issue page (**Issues**, click **New Issue** ). | | <kbd>g</kbd> + <kbd>b</kbd> | Go to the project issue boards list (**Issues > Boards**). | diff --git a/lib/api/group_export.rb b/lib/api/group_export.rb index 4d32212b8eb..6fe72458da2 100644 --- a/lib/api/group_export.rb +++ b/lib/api/group_export.rb @@ -27,7 +27,7 @@ module API detail 'This feature was introduced in GitLab 12.5.' end post ':id/export' do - GroupExportWorker.perform_async(current_user.id, user_group.id, params) + GroupExportWorker.perform_async(current_user.id, user_group.id, params) # rubocop:disable CodeReuse/Worker accepted! end diff --git a/lib/api/group_import.rb b/lib/api/group_import.rb index 3531abb2604..ed52506de14 100644 --- a/lib/api/group_import.rb +++ b/lib/api/group_import.rb @@ -76,7 +76,7 @@ module API group = ::Groups::CreateService.new(current_user, group_params).execute if group.persisted? - GroupImportWorker.perform_async(current_user.id, group.id) + GroupImportWorker.perform_async(current_user.id, group.id) # rubocop:disable CodeReuse/Worker accepted! else diff --git a/lib/api/pipeline_schedules.rb b/lib/api/pipeline_schedules.rb index 61c40c54d69..445a37a70c0 100644 --- a/lib/api/pipeline_schedules.rb +++ b/lib/api/pipeline_schedules.rb @@ -120,7 +120,7 @@ module API post ':id/pipeline_schedules/:pipeline_schedule_id/play' do authorize! :play_pipeline_schedule, pipeline_schedule - job_id = RunPipelineScheduleWorker + job_id = RunPipelineScheduleWorker # rubocop:disable CodeReuse/Worker .perform_async(pipeline_schedule.id, current_user.id) if job_id diff --git a/lib/api/project_container_repositories.rb b/lib/api/project_container_repositories.rb index e2963c0de22..70c913bea98 100644 --- a/lib/api/project_container_repositories.rb +++ b/lib/api/project_container_repositories.rb @@ -41,7 +41,7 @@ module API delete ':id/registry/repositories/:repository_id', requirements: REPOSITORY_ENDPOINT_REQUIREMENTS do authorize_admin_container_image! - DeleteContainerRepositoryWorker.perform_async(current_user.id, repository.id) + DeleteContainerRepositoryWorker.perform_async(current_user.id, repository.id) # rubocop:disable CodeReuse/Worker track_event('delete_repository') status :accepted @@ -79,8 +79,10 @@ module API message = 'This request has already been made. You can run this at most once an hour for a given container repository' render_api_error!(message, 400) unless obtain_new_cleanup_container_lease + # rubocop:disable CodeReuse/Worker CleanupContainerRepositoryWorker.perform_async(current_user.id, repository.id, declared_params.except(:repository_id).merge(container_expiration_policy: false)) + # rubocop:enable CodeReuse/Worker track_event('delete_tag_bulk') diff --git a/lib/api/releases.rb b/lib/api/releases.rb index b1f23d9837f..6e7a99bf0bb 100644 --- a/lib/api/releases.rb +++ b/lib/api/releases.rb @@ -170,9 +170,9 @@ module API return if release.historical_release? if release.upcoming_release? - CreateEvidenceWorker.perform_at(release.released_at, release.id) + CreateEvidenceWorker.perform_at(release.released_at, release.id) # rubocop:disable CodeReuse/Worker else - CreateEvidenceWorker.perform_async(release.id) + CreateEvidenceWorker.perform_async(release.id) # rubocop:disable CodeReuse/Worker end end end diff --git a/lib/gitlab/background_migration/link_lfs_objects.rb b/lib/gitlab/background_migration/link_lfs_objects.rb new file mode 100644 index 00000000000..014bebc4258 --- /dev/null +++ b/lib/gitlab/background_migration/link_lfs_objects.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +module Gitlab + module BackgroundMigration + # Create missing LfsObjectsProject records for forks + class LinkLfsObjects + # Model definition used for migration + class ForkNetworkMember < ActiveRecord::Base + self.table_name = 'fork_network_members' + + def self.with_non_existing_lfs_objects + joins('JOIN lfs_objects_projects lop ON fork_network_members.forked_from_project_id = lop.project_id') + .where( + <<~SQL + NOT EXISTS ( + SELECT 1 + FROM lfs_objects_projects + WHERE lfs_objects_projects.project_id = fork_network_members.project_id + AND lfs_objects_projects.lfs_object_id = lop.lfs_object_id + ) + SQL + ) + end + end + + def perform(start_id, end_id) + select_query = + ForkNetworkMember + .select('lop.lfs_object_id, fork_network_members.project_id') + .with_non_existing_lfs_objects + .where(project_id: start_id..end_id) + + return if select_query.empty? + + execute <<-SQL + INSERT INTO lfs_objects_projects (lfs_object_id, project_id) + #{select_query.to_sql} + SQL + end + + private + + def execute(sql) + ::ActiveRecord::Base.connection.execute(sql) + end + end + end +end diff --git a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml index a133c5e0485..73ae63c3092 100644 --- a/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml +++ b/lib/gitlab/ci/templates/Managed-Cluster-Applications.gitlab-ci.yml @@ -1,6 +1,6 @@ apply: stage: deploy - image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.7.0" + image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.8.0" environment: name: production variables: @@ -12,6 +12,8 @@ apply: GITLAB_RUNNER_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/gitlab-runner/values.yaml CILIUM_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/cilium/values.yaml JUPYTERHUB_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/jupyterhub/values.yaml + PROMETHEUS_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/prometheus/values.yaml + ELASTIC_STACK_VALUES_FILE: $CI_PROJECT_DIR/.gitlab/managed-apps/elastic-stack/values.yaml script: - gitlab-managed-apps /usr/local/share/gitlab-managed-apps/helmfile.yaml only: diff --git a/lib/gitlab/import_export/group_object_builder.rb b/lib/gitlab/import_export/group_object_builder.rb index fa426e32b60..9796bfa07d4 100644 --- a/lib/gitlab/import_export/group_object_builder.rb +++ b/lib/gitlab/import_export/group_object_builder.rb @@ -18,12 +18,21 @@ module Gitlab super @group = @attributes['group'] + + update_description end private attr_reader :group + # Convert description empty string to nil + # due to existing object being saved with description: nil + # Which makes object lookup to fail since nil != '' + def update_description + attributes['description'] = nil if attributes['description'] == '' + end + def where_clauses [ where_clause_base, @@ -159,6 +159,10 @@ module QA autoload :Validator, 'qa/page/validator' autoload :Validatable, 'qa/page/validatable' + module SubMenus + autoload :Common, 'qa/page/sub_menus/common' + end + module Main autoload :Login, 'qa/page/main/login' autoload :Menu, 'qa/page/main/menu' diff --git a/qa/qa/page/group/menu.rb b/qa/qa/page/group/menu.rb index 2b3b872aff4..230511ce6f6 100644 --- a/qa/qa/page/group/menu.rb +++ b/qa/qa/page/group/menu.rb @@ -13,15 +13,22 @@ module QA element :contribution_analytics_link end + view 'app/views/layouts/nav/sidebar/_analytics_links.html.haml' do + element :analytics_link + element :analytics_sidebar_submenu + end + def click_group_members_item within_sidebar do click_element(:group_members_item) end end - def click_group_analytics_item - within_sidebar do - click_element(:contribution_analytics_link) + def click_contribution_analytics_item + hover_element(:analytics_link) do + within_submenu(:analytics_sidebar_submenu) do + click_element(:contribution_analytics_link) + end end end diff --git a/qa/qa/page/group/sub_menus/common.rb b/qa/qa/page/group/sub_menus/common.rb index a378db80e4b..96efc8da98d 100644 --- a/qa/qa/page/group/sub_menus/common.rb +++ b/qa/qa/page/group/sub_menus/common.rb @@ -5,6 +5,8 @@ module QA module Group module SubMenus module Common + include QA::Page::SubMenus::Common + def self.included(base) base.class_eval do view 'app/views/layouts/nav/sidebar/_group.html.haml' do @@ -13,23 +15,10 @@ module QA end end - def hover_element(element) - within_sidebar do - find_element(element).hover - yield - end - end + private - def within_sidebar - within_element(:group_sidebar) do - yield - end - end - - def within_submenu(element) - within_element(element) do - yield - end + def sidebar_element + :group_sidebar end end end diff --git a/qa/qa/page/project/sub_menus/common.rb b/qa/qa/page/project/sub_menus/common.rb index 3c9e8085748..da759398cff 100644 --- a/qa/qa/page/project/sub_menus/common.rb +++ b/qa/qa/page/project/sub_menus/common.rb @@ -5,20 +5,12 @@ module QA module Project module SubMenus module Common - def within_sidebar - within('.sidebar-top-level-items') do - yield - end - end + include QA::Page::SubMenus::Common + + private - def within_submenu - if has_css?('.fly-out-list') - within('.fly-out-list') do - yield - end - else - yield - end + def sidebar_element + :project_sidebar end end end diff --git a/qa/qa/page/sub_menus/common.rb b/qa/qa/page/sub_menus/common.rb new file mode 100644 index 00000000000..0eb1b100bd7 --- /dev/null +++ b/qa/qa/page/sub_menus/common.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +module QA + module Page + module SubMenus + module Common + def hover_element(element) + within_sidebar do + find_element(element).hover + yield + end + end + + def within_sidebar + within_element(sidebar_element) do + yield + end + end + + def within_submenu(element = nil) + if element + within_element(element) do + yield + end + else + within_submenu_without_element do + yield + end + end + end + + private + + def within_submenu_without_element + if has_css?('.fly-out-list') + within('.fly-out-list') do + yield + end + else + yield + end + end + + def sidebar_element + raise NotImplementedError + end + end + end + end +end diff --git a/rubocop/rubocop.rb b/rubocop/rubocop.rb index 9305153dc7d..1c314976b4e 100644 --- a/rubocop/rubocop.rb +++ b/rubocop/rubocop.rb @@ -55,6 +55,7 @@ require_relative 'cop/code_reuse/service_class' require_relative 'cop/code_reuse/presenter' require_relative 'cop/code_reuse/serializer' require_relative 'cop/code_reuse/active_record' +require_relative 'cop/code_reuse/worker' require_relative 'cop/group_public_or_visible_to_user' require_relative 'cop/inject_enterprise_edition_module' require_relative 'cop/graphql/authorize_types' diff --git a/spec/features/security/group/internal_access_spec.rb b/spec/features/security/group/internal_access_spec.rb index 8dd15789cd1..114bc1a1f0c 100644 --- a/spec/features/security/group/internal_access_spec.rb +++ b/spec/features/security/group/internal_access_spec.rb @@ -36,7 +36,7 @@ describe 'Internal Group access' do it { is_expected.to be_denied_for(:visitor) } end - describe 'GET /groups/:path/issues' do + describe 'GET /groups/:path/-/issues' do subject { issues_group_path(group) } it { is_expected.to be_allowed_for(:admin) } @@ -51,7 +51,7 @@ describe 'Internal Group access' do it { is_expected.to be_denied_for(:visitor) } end - describe 'GET /groups/:path/merge_requests' do + describe 'GET /groups/:path/-/merge_requests' do let(:project) { create(:project, :internal, :repository, group: group) } subject { merge_requests_group_path(group) } @@ -68,7 +68,7 @@ describe 'Internal Group access' do it { is_expected.to be_denied_for(:visitor) } end - describe 'GET /groups/:path/group_members' do + describe 'GET /groups/:path/-/group_members' do subject { group_group_members_path(group) } it { is_expected.to be_allowed_for(:admin) } @@ -83,7 +83,7 @@ describe 'Internal Group access' do it { is_expected.to be_denied_for(:visitor) } end - describe 'GET /groups/:path/edit' do + describe 'GET /groups/:path/-/edit' do subject { edit_group_path(group) } it { is_expected.to be_allowed_for(:admin) } diff --git a/spec/features/security/group/private_access_spec.rb b/spec/features/security/group/private_access_spec.rb index 0720302b03b..3362b9a9e9e 100644 --- a/spec/features/security/group/private_access_spec.rb +++ b/spec/features/security/group/private_access_spec.rb @@ -36,7 +36,7 @@ describe 'Private Group access' do it { is_expected.to be_denied_for(:visitor) } end - describe 'GET /groups/:path/issues' do + describe 'GET /groups/:path/-/issues' do subject { issues_group_path(group) } it { is_expected.to be_allowed_for(:admin) } @@ -51,7 +51,7 @@ describe 'Private Group access' do it { is_expected.to be_denied_for(:visitor) } end - describe 'GET /groups/:path/merge_requests' do + describe 'GET /groups/:path/-/merge_requests' do let(:project) { create(:project, :private, :repository, group: group) } subject { merge_requests_group_path(group) } @@ -68,7 +68,7 @@ describe 'Private Group access' do it { is_expected.to be_denied_for(:visitor) } end - describe 'GET /groups/:path/group_members' do + describe 'GET /groups/:path/-/group_members' do subject { group_group_members_path(group) } it { is_expected.to be_allowed_for(:admin) } @@ -83,7 +83,7 @@ describe 'Private Group access' do it { is_expected.to be_denied_for(:visitor) } end - describe 'GET /groups/:path/edit' do + describe 'GET /groups/:path/-/edit' do subject { edit_group_path(group) } it { is_expected.to be_allowed_for(:admin) } diff --git a/spec/features/security/group/public_access_spec.rb b/spec/features/security/group/public_access_spec.rb index 0a18a0ff812..bf05f276cc6 100644 --- a/spec/features/security/group/public_access_spec.rb +++ b/spec/features/security/group/public_access_spec.rb @@ -36,7 +36,7 @@ describe 'Public Group access' do it { is_expected.to be_allowed_for(:visitor) } end - describe 'GET /groups/:path/issues' do + describe 'GET /groups/:path/-/issues' do subject { issues_group_path(group) } it { is_expected.to be_allowed_for(:admin) } @@ -51,7 +51,7 @@ describe 'Public Group access' do it { is_expected.to be_allowed_for(:visitor) } end - describe 'GET /groups/:path/merge_requests' do + describe 'GET /groups/:path/-/merge_requests' do let(:project) { create(:project, :public, :repository, group: group) } subject { merge_requests_group_path(group) } @@ -68,7 +68,7 @@ describe 'Public Group access' do it { is_expected.to be_allowed_for(:visitor) } end - describe 'GET /groups/:path/group_members' do + describe 'GET /groups/:path/-/group_members' do subject { group_group_members_path(group) } it { is_expected.to be_allowed_for(:admin) } @@ -83,7 +83,7 @@ describe 'Public Group access' do it { is_expected.to be_allowed_for(:visitor) } end - describe 'GET /groups/:path/edit' do + describe 'GET /groups/:path/-/edit' do subject { edit_group_path(group) } it { is_expected.to be_allowed_for(:admin) } diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb index 5c74b566ef0..ed1dbe15d65 100644 --- a/spec/features/security/project/internal_access_spec.rb +++ b/spec/features/security/project/internal_access_spec.rb @@ -29,7 +29,7 @@ describe "Internal Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/tree/master" do + describe "GET /:project_path/-/tree/master" do subject { project_tree_path(project, project.repository.root_ref) } it { is_expected.to be_allowed_for(:admin) } @@ -43,7 +43,7 @@ describe "Internal Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/commits/master" do + describe "GET /:project_path/-/commits/master" do subject { project_commits_path(project, project.repository.root_ref, limit: 1) } it { is_expected.to be_allowed_for(:admin) } @@ -57,7 +57,7 @@ describe "Internal Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/commit/:sha" do + describe "GET /:project_path/-/commit/:sha" do subject { project_commit_path(project, project.repository.commit) } it { is_expected.to be_allowed_for(:admin) } @@ -71,7 +71,7 @@ describe "Internal Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/compare" do + describe "GET /:project_path/-/compare" do subject { project_compare_index_path(project) } it { is_expected.to be_allowed_for(:admin) } @@ -127,7 +127,7 @@ describe "Internal Project Access" do it { is_expected.to be_denied_for(:external) } end - describe "GET /:project_path/blob" do + describe "GET /:project_path/-/blob" do let(:commit) { project.repository.commit } subject { project_blob_path(project, File.join(commit.id, '.gitignore')) } @@ -229,7 +229,7 @@ describe "Internal Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/merge_requests" do + describe "GET /:project_path/-/merge_requests" do subject { project_merge_requests_path(project) } it { is_expected.to be_allowed_for(:admin) } @@ -243,7 +243,7 @@ describe "Internal Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/merge_requests/new" do + describe "GET /:project_path/-/merge_requests/new" do subject { project_new_merge_request_path(project) } it { is_expected.to be_allowed_for(:admin) } @@ -257,7 +257,7 @@ describe "Internal Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/branches" do + describe "GET /:project_path/-/branches" do subject { project_branches_path(project) } before do @@ -278,7 +278,7 @@ describe "Internal Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/tags" do + describe "GET /:project_path/-/tags" do subject { project_tags_path(project) } before do diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb index 2404b7cc69d..97e6b3bd4ff 100644 --- a/spec/features/security/project/private_access_spec.rb +++ b/spec/features/security/project/private_access_spec.rb @@ -29,7 +29,7 @@ describe "Private Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/tree/master" do + describe "GET /:project_path/-/tree/master" do subject { project_tree_path(project, project.repository.root_ref) } it { is_expected.to be_allowed_for(:admin) } @@ -43,7 +43,7 @@ describe "Private Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/commits/master" do + describe "GET /:project_path/-/commits/master" do subject { project_commits_path(project, project.repository.root_ref, limit: 1) } it { is_expected.to be_allowed_for(:admin) } @@ -57,7 +57,7 @@ describe "Private Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/commit/:sha" do + describe "GET /:project_path/-/commit/:sha" do subject { project_commit_path(project, project.repository.commit) } it { is_expected.to be_allowed_for(:admin) } @@ -71,7 +71,7 @@ describe "Private Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/compare" do + describe "GET /:project_path/-/compare" do subject { project_compare_index_path(project) } it { is_expected.to be_allowed_for(:admin) } @@ -127,7 +127,7 @@ describe "Private Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/blob" do + describe "GET /:project_path/-/blob" do let(:commit) { project.repository.commit } subject { project_blob_path(project, File.join(commit.id, '.gitignore')) } @@ -215,7 +215,7 @@ describe "Private Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/merge_requests" do + describe "GET /:project_path/-/merge_requests" do subject { project_merge_requests_path(project) } it { is_expected.to be_allowed_for(:admin) } @@ -229,7 +229,7 @@ describe "Private Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/branches" do + describe "GET /:project_path/-/branches" do subject { project_branches_path(project) } before do @@ -250,7 +250,7 @@ describe "Private Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/tags" do + describe "GET /:project_path/-/tags" do subject { project_tags_path(project) } before do diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb index 8e07af61c8b..24bbb8d9b9e 100644 --- a/spec/features/security/project/public_access_spec.rb +++ b/spec/features/security/project/public_access_spec.rb @@ -29,7 +29,7 @@ describe "Public Project Access" do it { is_expected.to be_allowed_for(:visitor) } end - describe "GET /:project_path/tree/master" do + describe "GET /:project_path/-/tree/master" do subject { project_tree_path(project, project.repository.root_ref) } it { is_expected.to be_allowed_for(:admin) } @@ -43,7 +43,7 @@ describe "Public Project Access" do it { is_expected.to be_allowed_for(:visitor) } end - describe "GET /:project_path/commits/master" do + describe "GET /:project_path/-/commits/master" do subject { project_commits_path(project, project.repository.root_ref, limit: 1) } it { is_expected.to be_allowed_for(:admin) } @@ -57,7 +57,7 @@ describe "Public Project Access" do it { is_expected.to be_allowed_for(:visitor) } end - describe "GET /:project_path/commit/:sha" do + describe "GET /:project_path/-/commit/:sha" do subject { project_commit_path(project, project.repository.commit) } it { is_expected.to be_allowed_for(:admin) } @@ -71,7 +71,7 @@ describe "Public Project Access" do it { is_expected.to be_allowed_for(:visitor) } end - describe "GET /:project_path/compare" do + describe "GET /:project_path/-/compare" do subject { project_compare_index_path(project) } it { is_expected.to be_allowed_for(:admin) } @@ -345,7 +345,7 @@ describe "Public Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/blob" do + describe "GET /:project_path/-/blob" do let(:commit) { project.repository.commit } subject { project_blob_path(project, File.join(commit.id, '.gitignore')) } @@ -446,7 +446,7 @@ describe "Public Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/merge_requests" do + describe "GET /:project_path/-/merge_requests" do subject { project_merge_requests_path(project) } it { is_expected.to be_allowed_for(:admin) } @@ -460,7 +460,7 @@ describe "Public Project Access" do it { is_expected.to be_allowed_for(:visitor) } end - describe "GET /:project_path/merge_requests/new" do + describe "GET /:project_path/-/merge_requests/new" do subject { project_new_merge_request_path(project) } it { is_expected.to be_allowed_for(:admin) } @@ -474,7 +474,7 @@ describe "Public Project Access" do it { is_expected.to be_denied_for(:visitor) } end - describe "GET /:project_path/branches" do + describe "GET /:project_path/-/branches" do subject { project_branches_path(project) } before do @@ -495,7 +495,7 @@ describe "Public Project Access" do it { is_expected.to be_allowed_for(:visitor) } end - describe "GET /:project_path/tags" do + describe "GET /:project_path/-/tags" do subject { project_tags_path(project) } before do diff --git a/spec/frontend/monitoring/store/mutations_spec.js b/spec/frontend/monitoring/store/mutations_spec.js index b0ac42e0e5f..d9aebafb9ec 100644 --- a/spec/frontend/monitoring/store/mutations_spec.js +++ b/spec/frontend/monitoring/store/mutations_spec.js @@ -91,16 +91,37 @@ describe('Monitoring mutations', () => { expect(stateCopy.projectPath).toEqual('/gitlab-org/gitlab-foss'); }); - it('should not remove default value of logsPath', () => { + it('should not remove previously set properties', () => { const defaultLogsPath = stateCopy.logsPath; mutations[types.SET_ENDPOINTS](stateCopy, { + logsPath: defaultLogsPath, + }); + mutations[types.SET_ENDPOINTS](stateCopy, { dashboardEndpoint: 'dashboard.json', }); + mutations[types.SET_ENDPOINTS](stateCopy, { + projectPath: '/gitlab-org/gitlab-foss', + }); - expect(stateCopy.logsPath).toBe(defaultLogsPath); + expect(stateCopy).toMatchObject({ + logsPath: defaultLogsPath, + dashboardEndpoint: 'dashboard.json', + projectPath: '/gitlab-org/gitlab-foss', + }); + }); + + it('should not update unknown properties', () => { + mutations[types.SET_ENDPOINTS](stateCopy, { + dashboardEndpoint: 'dashboard.json', + someOtherProperty: 'some invalid value', // someOtherProperty is not allowed + }); + + expect(stateCopy.dashboardEndpoint).toBe('dashboard.json'); + expect(stateCopy.someOtherProperty).toBeUndefined(); }); }); + describe('Individual panel/metric results', () => { const metricId = '12_system_metrics_kubernetes_container_memory_total'; const result = [ diff --git a/spec/frontend/releases/detail/components/app_spec.js b/spec/frontend/releases/components/app_edit_spec.js index 894cd3a8f14..cb940facbd6 100644 --- a/spec/frontend/releases/detail/components/app_spec.js +++ b/spec/frontend/releases/components/app_edit_spec.js @@ -1,10 +1,10 @@ import Vuex from 'vuex'; import { mount } from '@vue/test-utils'; -import ReleaseDetailApp from '~/releases/detail/components/app.vue'; -import { release } from '../../mock_data'; +import ReleaseEditApp from '~/releases/components/app_edit.vue'; +import { release } from '../mock_data'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; -describe('Release detail component', () => { +describe('Release edit component', () => { let wrapper; let releaseClone; let actions; @@ -27,9 +27,17 @@ describe('Release detail component', () => { navigateToReleasesPage: jest.fn(), }; - const store = new Vuex.Store({ actions, state }); + const store = new Vuex.Store({ + modules: { + detail: { + namespaced: true, + actions, + state, + }, + }, + }); - wrapper = mount(ReleaseDetailApp, { + wrapper = mount(ReleaseEditApp, { store, }); diff --git a/spec/frontend/releases/list/components/evidence_block_spec.js b/spec/frontend/releases/components/evidence_block_spec.js index 39f3975f665..7b896575965 100644 --- a/spec/frontend/releases/list/components/evidence_block_spec.js +++ b/spec/frontend/releases/components/evidence_block_spec.js @@ -2,8 +2,8 @@ import { mount } from '@vue/test-utils'; import { GlLink } from '@gitlab/ui'; import { truncateSha } from '~/lib/utils/text_utility'; import Icon from '~/vue_shared/components/icon.vue'; -import { release } from '../../mock_data'; -import EvidenceBlock from '~/releases/list/components/evidence_block.vue'; +import { release } from '../mock_data'; +import EvidenceBlock from '~/releases/components/evidence_block.vue'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; describe('Evidence Block', () => { diff --git a/spec/frontend/releases/list/components/release_block_footer_spec.js b/spec/frontend/releases/components/release_block_footer_spec.js index 07f61303e33..4125d5c7e74 100644 --- a/spec/frontend/releases/list/components/release_block_footer_spec.js +++ b/spec/frontend/releases/components/release_block_footer_spec.js @@ -1,9 +1,9 @@ import { mount } from '@vue/test-utils'; import { GlLink } from '@gitlab/ui'; import { trimText } from 'helpers/text_helper'; -import ReleaseBlockFooter from '~/releases/list/components/release_block_footer.vue'; +import ReleaseBlockFooter from '~/releases/components/release_block_footer.vue'; import Icon from '~/vue_shared/components/icon.vue'; -import { release } from '../../mock_data'; +import { release } from '../mock_data'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; jest.mock('~/vue_shared/mixins/timeago', () => ({ diff --git a/spec/frontend/releases/list/components/release_block_header_spec.js b/spec/frontend/releases/components/release_block_header_spec.js index 1f2331635d6..157df15ff3c 100644 --- a/spec/frontend/releases/list/components/release_block_header_spec.js +++ b/spec/frontend/releases/components/release_block_header_spec.js @@ -1,9 +1,9 @@ import { shallowMount } from '@vue/test-utils'; import { cloneDeep, merge } from 'lodash'; import { GlLink } from '@gitlab/ui'; -import ReleaseBlockHeader from '~/releases/list/components/release_block_header.vue'; +import ReleaseBlockHeader from '~/releases/components/release_block_header.vue'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; -import { release as originalRelease } from '../../mock_data'; +import { release as originalRelease } from '../mock_data'; describe('Release block header', () => { let wrapper; diff --git a/spec/frontend/releases/list/components/release_block_milestone_info_spec.js b/spec/frontend/releases/components/release_block_milestone_info_spec.js index 8a63dbbdca7..5a3204a4ce2 100644 --- a/spec/frontend/releases/list/components/release_block_milestone_info_spec.js +++ b/spec/frontend/releases/components/release_block_milestone_info_spec.js @@ -1,9 +1,9 @@ import { mount } from '@vue/test-utils'; import { GlProgressBar, GlLink, GlBadge, GlButton } from '@gitlab/ui'; import { trimText } from 'helpers/text_helper'; -import ReleaseBlockMilestoneInfo from '~/releases/list/components/release_block_milestone_info.vue'; -import { milestones } from '../../mock_data'; -import { MAX_MILESTONES_TO_DISPLAY } from '~/releases/list/constants'; +import ReleaseBlockMilestoneInfo from '~/releases/components/release_block_milestone_info.vue'; +import { milestones } from '../mock_data'; +import { MAX_MILESTONES_TO_DISPLAY } from '~/releases/constants'; describe('Release block milestone info', () => { let wrapper; diff --git a/spec/frontend/releases/list/components/release_block_spec.js b/spec/frontend/releases/components/release_block_spec.js index 0e8d569f326..aba1b8aff41 100644 --- a/spec/frontend/releases/list/components/release_block_spec.js +++ b/spec/frontend/releases/components/release_block_spec.js @@ -1,11 +1,11 @@ import $ from 'jquery'; import { mount } from '@vue/test-utils'; import { first } from 'underscore'; -import EvidenceBlock from '~/releases/list/components/evidence_block.vue'; -import ReleaseBlock from '~/releases/list/components/release_block.vue'; -import ReleaseBlockFooter from '~/releases/list/components/release_block_footer.vue'; +import EvidenceBlock from '~/releases/components/evidence_block.vue'; +import ReleaseBlock from '~/releases/components/release_block.vue'; +import ReleaseBlockFooter from '~/releases/components/release_block_footer.vue'; import timeagoMixin from '~/vue_shared/mixins/timeago'; -import { release } from '../../mock_data'; +import { release } from '../mock_data'; import Icon from '~/vue_shared/components/icon.vue'; import { scrollToElement } from '~/lib/utils/common_utils'; diff --git a/spec/frontend/releases/detail/store/actions_spec.js b/spec/frontend/releases/stores/modules/detail/actions_spec.js index 5a1447aa4fc..0c2763822c9 100644 --- a/spec/frontend/releases/detail/store/actions_spec.js +++ b/spec/frontend/releases/stores/modules/detail/actions_spec.js @@ -1,10 +1,10 @@ import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; import testAction from 'helpers/vuex_action_helper'; -import * as actions from '~/releases/detail/store/actions'; -import * as types from '~/releases/detail/store/mutation_types'; -import { release } from '../../mock_data'; -import state from '~/releases/detail/store/state'; +import * as actions from '~/releases/stores/modules/detail/actions'; +import * as types from '~/releases/stores/modules/detail/mutation_types'; +import { release } from '../../../mock_data'; +import state from '~/releases/stores/modules/detail/state'; import createFlash from '~/flash'; import { redirectTo } from '~/lib/utils/url_utility'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; diff --git a/spec/frontend/releases/detail/store/mutations_spec.js b/spec/frontend/releases/stores/modules/detail/mutations_spec.js index 106a40c812e..81b2dde75ab 100644 --- a/spec/frontend/releases/detail/store/mutations_spec.js +++ b/spec/frontend/releases/stores/modules/detail/mutations_spec.js @@ -5,10 +5,10 @@ * is resolved */ -import state from '~/releases/detail/store/state'; -import mutations from '~/releases/detail/store/mutations'; -import * as types from '~/releases/detail/store/mutation_types'; -import { release } from '../../mock_data'; +import state from '~/releases/stores/modules/detail/state'; +import mutations from '~/releases/stores/modules/detail/mutations'; +import * as types from '~/releases/stores/modules/detail/mutation_types'; +import { release } from '../../../mock_data'; describe('Release detail mutations', () => { let stateClone; diff --git a/spec/javascripts/releases/list/components/app_spec.js b/spec/javascripts/releases/components/app_index_spec.js index de6208ab1fd..bcf062f357a 100644 --- a/spec/javascripts/releases/list/components/app_spec.js +++ b/spec/javascripts/releases/components/app_index_spec.js @@ -1,16 +1,17 @@ import _ from 'underscore'; import Vue from 'vue'; import { mountComponentWithStore } from 'spec/helpers/vue_mount_component_helper'; -import app from '~/releases/list/components/app.vue'; -import createStore from '~/releases/list/store'; +import app from '~/releases/components/app_index.vue'; +import createStore from '~/releases/stores'; +import listModule from '~/releases/stores/modules/list'; import api from '~/api'; -import { resetStore } from '../store/helpers'; +import { resetStore } from '../stores/modules/list/helpers'; import { pageInfoHeadersWithoutPagination, pageInfoHeadersWithPagination, release, releases, -} from '../../mock_data'; +} from '../mock_data'; describe('Releases App ', () => { const Component = Vue.extend(app); @@ -25,7 +26,7 @@ describe('Releases App ', () => { }; beforeEach(() => { - store = createStore(); + store = createStore({ list: listModule }); releasesPagination = _.range(21).map(index => ({ ...release, tag_name: `${index}.00` })); }); diff --git a/spec/javascripts/releases/list/store/actions_spec.js b/spec/javascripts/releases/stores/modules/list/actions_spec.js index f03e019b95c..037c9d8d54a 100644 --- a/spec/javascripts/releases/list/store/actions_spec.js +++ b/spec/javascripts/releases/stores/modules/list/actions_spec.js @@ -4,12 +4,12 @@ import { fetchReleases, receiveReleasesSuccess, receiveReleasesError, -} from '~/releases/list/store/actions'; -import state from '~/releases/list/store/state'; -import * as types from '~/releases/list/store/mutation_types'; +} from '~/releases/stores/modules/list/actions'; +import state from '~/releases/stores/modules/list/state'; +import * as types from '~/releases/stores/modules/list/mutation_types'; import api from '~/api'; import { parseIntPagination } from '~/lib/utils/common_utils'; -import { pageInfoHeadersWithoutPagination, releases } from '../../mock_data'; +import { pageInfoHeadersWithoutPagination, releases } from '../../../mock_data'; describe('Releases State actions', () => { let mockedState; diff --git a/spec/javascripts/releases/list/store/helpers.js b/spec/javascripts/releases/stores/modules/list/helpers.js index fbc89ec2148..435ca36047e 100644 --- a/spec/javascripts/releases/list/store/helpers.js +++ b/spec/javascripts/releases/stores/modules/list/helpers.js @@ -1,4 +1,4 @@ -import state from '~/releases/list/store/state'; +import state from '~/releases/stores/modules/list/state'; // eslint-disable-next-line import/prefer-default-export export const resetStore = store => { diff --git a/spec/javascripts/releases/list/store/mutations_spec.js b/spec/javascripts/releases/stores/modules/list/mutations_spec.js index d756c69d53b..3035b916ff6 100644 --- a/spec/javascripts/releases/list/store/mutations_spec.js +++ b/spec/javascripts/releases/stores/modules/list/mutations_spec.js @@ -1,8 +1,8 @@ -import state from '~/releases/list/store/state'; -import mutations from '~/releases/list/store/mutations'; -import * as types from '~/releases/list/store/mutation_types'; +import state from '~/releases/stores/modules/list/state'; +import mutations from '~/releases/stores/modules/list/mutations'; +import * as types from '~/releases/stores/modules/list/mutation_types'; import { parseIntPagination } from '~/lib/utils/common_utils'; -import { pageInfoHeadersWithoutPagination, releases } from '../../mock_data'; +import { pageInfoHeadersWithoutPagination, releases } from '../../../mock_data'; describe('Releases Store Mutations', () => { let stateCopy; diff --git a/spec/lib/gitlab/background_migration/link_lfs_objects_spec.rb b/spec/lib/gitlab/background_migration/link_lfs_objects_spec.rb new file mode 100644 index 00000000000..2a33af2c644 --- /dev/null +++ b/spec/lib/gitlab/background_migration/link_lfs_objects_spec.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::BackgroundMigration::LinkLfsObjects, :migration, schema: 2020_02_10_062432 do + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:fork_networks) { table(:fork_networks) } + let(:fork_network_members) { table(:fork_network_members) } + let(:lfs_objects) { table(:lfs_objects) } + let(:lfs_objects_projects) { table(:lfs_objects_projects) } + let(:namespace) { namespaces.create(name: 'GitLab', path: 'gitlab') } + let(:source_project) { projects.create(namespace_id: namespace.id) } + let(:another_source_project) { projects.create(namespace_id: namespace.id) } + let(:project) { projects.create(namespace_id: namespace.id) } + let(:another_project) { projects.create(namespace_id: namespace.id) } + let(:other_project) { projects.create(namespace_id: namespace.id) } + let(:linked_project) { projects.create(namespace_id: namespace.id) } + let(:fork_network) { fork_networks.create(root_project_id: source_project.id) } + let(:another_fork_network) { fork_networks.create(root_project_id: another_source_project.id) } + let(:lfs_object) { lfs_objects.create(oid: 'abc123', size: 100) } + let(:another_lfs_object) { lfs_objects.create(oid: 'def456', size: 200) } + + before do + # Create links between projects + fork_network_members.create(fork_network_id: fork_network.id, project_id: source_project.id, forked_from_project_id: nil) + + [project, another_project, linked_project].each do |p| + fork_network_members.create( + fork_network_id: fork_network.id, + project_id: p.id, + forked_from_project_id: fork_network.root_project_id + ) + end + + fork_network_members.create(fork_network_id: another_fork_network.id, project_id: another_source_project.id, forked_from_project_id: nil) + fork_network_members.create(fork_network_id: another_fork_network.id, project_id: other_project.id, forked_from_project_id: another_fork_network.root_project_id) + + # Links LFS objects to some projects + [source_project, another_source_project, linked_project].each do |p| + lfs_objects_projects.create(lfs_object_id: lfs_object.id, project_id: p.id) + lfs_objects_projects.create(lfs_object_id: another_lfs_object.id, project_id: p.id) + end + end + + it 'creates LfsObjectsProject records for forks within the specified range of project IDs' do + expect { subject.perform(project.id, other_project.id) }.to change { lfs_objects_projects.count }.by(6) + + expect(lfs_object_ids_for(project)).to match_array(lfs_object_ids_for(source_project)) + expect(lfs_object_ids_for(another_project)).to match_array(lfs_object_ids_for(source_project)) + expect(lfs_object_ids_for(other_project)).to match_array(lfs_object_ids_for(another_source_project)) + + expect { subject.perform(project.id, other_project.id) }.not_to change { lfs_objects_projects.count } + end + + context 'when it is not necessary to create LfsObjectProject records' do + it 'does not create LfsObjectProject records' do + expect { subject.perform(linked_project.id, linked_project.id) } + .not_to change { lfs_objects_projects.count } + end + end + + def lfs_object_ids_for(project) + lfs_objects_projects.where(project_id: project.id).pluck(:lfs_object_id) + end +end diff --git a/spec/lib/gitlab/import_export/group_object_builder_spec.rb b/spec/lib/gitlab/import_export/group_object_builder_spec.rb index 7950a937608..08b2dae1147 100644 --- a/spec/lib/gitlab/import_export/group_object_builder_spec.rb +++ b/spec/lib/gitlab/import_export/group_object_builder_spec.rb @@ -26,6 +26,16 @@ describe Gitlab::ImportExport::GroupObjectBuilder do expect(label.persisted?).to be true end + + context 'when description is an empty string' do + let(:label_attributes) { base_attributes.merge('type' => 'GroupLabel', 'description' => '') } + + it 'finds the existing group label' do + group_label = create(:group_label, label_attributes) + + expect(described_class.build(Label, label_attributes)).to eq(group_label) + end + end end context 'milestones' do @@ -41,4 +51,16 @@ describe Gitlab::ImportExport::GroupObjectBuilder do expect(milestone.persisted?).to be true end end + + describe '#initialize' do + context 'when attributes contain description as empty string' do + let(:attributes) { base_attributes.merge('description' => '') } + + it 'converts empty string to nil' do + builder = described_class.new(Label, attributes) + + expect(builder.send(:attributes)).to include({ 'description' => nil }) + end + end + end end diff --git a/spec/migrations/schedule_link_lfs_objects_spec.rb b/spec/migrations/schedule_link_lfs_objects_spec.rb new file mode 100644 index 00000000000..87632bc7648 --- /dev/null +++ b/spec/migrations/schedule_link_lfs_objects_spec.rb @@ -0,0 +1,82 @@ +# frozen_string_literal: true + +require 'spec_helper' +require Rails.root.join('db', 'post_migrate', '20200210062432_schedule_link_lfs_objects.rb') + +describe ScheduleLinkLfsObjects, :migration, :sidekiq do + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:fork_networks) { table(:fork_networks) } + let(:fork_network_members) { table(:fork_network_members) } + let(:lfs_objects) { table(:lfs_objects) } + let(:lfs_objects_projects) { table(:lfs_objects_projects) } + let(:namespace) { namespaces.create(name: 'GitLab', path: 'gitlab') } + let(:fork_network) { fork_networks.create(root_project_id: source_project.id) } + let(:another_fork_network) { fork_networks.create(root_project_id: another_source_project.id) } + let(:source_project) { projects.create(namespace_id: namespace.id) } + let(:another_source_project) { projects.create(namespace_id: namespace.id) } + let(:project) { projects.create(namespace_id: namespace.id) } + let(:another_project) { projects.create(namespace_id: namespace.id) } + let(:other_project) { projects.create(namespace_id: namespace.id) } + let(:linked_project) { projects.create(namespace_id: namespace.id) } + let(:lfs_object) { lfs_objects.create(oid: 'abc123', size: 100) } + let(:another_lfs_object) { lfs_objects.create(oid: 'def456', size: 200) } + + before do + # Create links between projects + fork_network_members.create(fork_network_id: fork_network.id, project_id: source_project.id, forked_from_project_id: nil) + + [project, another_project, linked_project].each do |p| + fork_network_members.create( + fork_network_id: fork_network.id, + project_id: p.id, + forked_from_project_id: fork_network.root_project_id + ) + end + + fork_network_members.create(fork_network_id: another_fork_network.id, project_id: another_source_project.id, forked_from_project_id: nil) + fork_network_members.create(fork_network_id: another_fork_network.id, project_id: other_project.id, forked_from_project_id: another_fork_network.root_project_id) + end + + context 'when there are forks to be backfilled' do + before do + stub_const("#{described_class.name}::BATCH_SIZE", 2) + + # Links LFS objects to some projects + [source_project, another_source_project, linked_project].each do |p| + lfs_objects_projects.create(lfs_object_id: lfs_object.id, project_id: p.id) + lfs_objects_projects.create(lfs_object_id: another_lfs_object.id, project_id: p.id) + end + end + + it 'schedules background migration to link LFS objects' do + Sidekiq::Testing.fake! do + migrate! + + expect(BackgroundMigrationWorker.jobs.size).to eq(2) + expect(described_class::MIGRATION) + .to be_scheduled_delayed_migration(2.minutes, project.id, another_project.id) + expect(described_class::MIGRATION) + .to be_scheduled_delayed_migration(4.minutes, other_project.id, other_project.id) + end + end + end + + context 'when there are no forks to be backfilled' do + before do + # Links LFS objects to all projects + projects.all.each do |p| + lfs_objects_projects.create(lfs_object_id: lfs_object.id, project_id: p.id) + lfs_objects_projects.create(lfs_object_id: another_lfs_object.id, project_id: p.id) + end + end + + it 'does not schedule any job' do + Sidekiq::Testing.fake! do + migrate! + + expect(BackgroundMigrationWorker.jobs.size).to eq(0) + end + end + end +end diff --git a/spec/routing/project_routing_spec.rb b/spec/routing/project_routing_spec.rb index 40c9dd565ff..e503f1a4231 100644 --- a/spec/routing/project_routing_spec.rb +++ b/spec/routing/project_routing_spec.rb @@ -577,7 +577,7 @@ describe 'project routing' do end end - # project_blob GET /:project_id/blob/:id(.:format) blob#show {id: /[^\0]+/, project_id: /[^\/]+/} + # project_blob GET /:project_id/-/blob/:id(.:format) blob#show {id: /[^\0]+/, project_id: /[^\/]+/} describe Projects::BlobController, 'routing' do it 'to #show' do expect(get('/gitlab/gitlabhq/-/blob/master/app/models/project.rb')).to route_to('projects/blob#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb') @@ -600,7 +600,7 @@ describe 'project routing' do end end - # project_tree GET /:project_id/tree/:id(.:format) tree#show {id: /[^\0]+/, project_id: /[^\/]+/} + # project_tree GET /:project_id/-/tree/:id(.:format) tree#show {id: /[^\0]+/, project_id: /[^\/]+/} describe Projects::TreeController, 'routing' do it 'to #show' do expect(get('/gitlab/gitlabhq/-/tree/master/app/models/project.rb')).to route_to('projects/tree#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master/app/models/project.rb') @@ -621,8 +621,8 @@ describe 'project routing' do end end - # project_find_file GET /:namespace_id/:project_id/find_file/*id(.:format) projects/find_file#show {:id=>/[^\0]+/, :namespace_id=>/[a-zA-Z.0-9_\-]+/, :project_id=>/[a-zA-Z.0-9_\-]+(?<!\.atom)/, :format=>/html/} - # project_files GET /:namespace_id/:project_id/files/*id(.:format) projects/find_file#list {:id=>/(?:[^.]|\.(?!json$))+/, :namespace_id=>/[a-zA-Z.0-9_\-]+/, :project_id=>/[a-zA-Z.0-9_\-]+(?<!\.atom)/, :format=>/json/} + # project_find_file GET /:namespace_id/:project_id/-/find_file/*id(.:format) projects/find_file#show {:id=>/[^\0]+/, :namespace_id=>/[a-zA-Z.0-9_\-]+/, :project_id=>/[a-zA-Z.0-9_\-]+(?<!\.atom)/, :format=>/html/} + # project_files GET /:namespace_id/:project_id/-/files/*id(.:format) projects/find_file#list {:id=>/(?:[^.]|\.(?!json$))+/, :namespace_id=>/[a-zA-Z.0-9_\-]+/, :project_id=>/[a-zA-Z.0-9_\-]+(?<!\.atom)/, :format=>/json/} describe Projects::FindFileController, 'routing' do it 'to #show' do expect(get('/gitlab/gitlabhq/-/find_file/master')).to route_to('projects/find_file#show', namespace_id: 'gitlab', project_id: 'gitlabhq', id: 'master') @@ -677,7 +677,7 @@ describe 'project routing' do end end - # project_raw GET /:project_id/raw/:id(.:format) raw#show {id: /[^\0]+/, project_id: /[^\/]+/} + # project_raw GET /:project_id/-/raw/:id(.:format) raw#show {id: /[^\0]+/, project_id: /[^\/]+/} describe Projects::RawController, 'routing' do it 'to #show' do newline_file = "new\n\nline.txt" @@ -694,9 +694,9 @@ describe 'project routing' do end end - # project_compare_index GET /:project_id/compare(.:format) compare#index {id: /[^\/]+/, project_id: /[^\/]+/} - # POST /:project_id/compare(.:format) compare#create {id: /[^\/]+/, project_id: /[^\/]+/} - # project_compare /:project_id/compare/:from...:to(.:format) compare#show {from: /.+/, to: /.+/, id: /[^\/]+/, project_id: /[^\/]+/} + # project_compare_index GET /:project_id/-/compare(.:format) compare#index {id: /[^\/]+/, project_id: /[^\/]+/} + # POST /:project_id/-/compare(.:format) compare#create {id: /[^\/]+/, project_id: /[^\/]+/} + # project_compare /:project_id/-/compare/:from...:to(.:format) compare#show {from: /.+/, to: /.+/, id: /[^\/]+/, project_id: /[^\/]+/} describe Projects::CompareController, 'routing' do it 'to #index' do expect(get('/gitlab/gitlabhq/-/compare')).to route_to('projects/compare#index', namespace_id: 'gitlab', project_id: 'gitlabhq') diff --git a/spec/services/ci/pipeline_processing/shared_processing_service.rb b/spec/services/ci/pipeline_processing/shared_processing_service.rb index 2349dedf370..ca003299535 100644 --- a/spec/services/ci/pipeline_processing/shared_processing_service.rb +++ b/spec/services/ci/pipeline_processing/shared_processing_service.rb @@ -880,6 +880,31 @@ shared_examples 'Pipeline Processing Service' do end end + context 'when a needed job is skipped', :sidekiq_inline do + let!(:linux_build) { create_build('linux:build', stage: 'build', stage_idx: 0) } + let!(:linux_rspec) { create_build('linux:rspec', stage: 'test', stage_idx: 1) } + let!(:deploy) do + create_build('deploy', stage: 'deploy', stage_idx: 2, scheduling_type: :dag, needs: [ + create(:ci_build_need, name: 'linux:rspec') + ]) + end + + it 'skips the jobs depending on it' do + expect(process_pipeline).to be_truthy + + expect(stages).to eq(%w(pending created created)) + expect(all_builds.pending).to contain_exactly(linux_build) + + linux_build.reset.drop! + + expect(stages).to eq(%w(failed skipped skipped)) + expect(all_builds.failed).to contain_exactly(linux_build) + expect(all_builds.skipped).to contain_exactly(linux_rspec, deploy) + end + end + + private + def all_builds pipeline.builds.order(:stage_idx, :id) end diff --git a/spec/services/ci/process_build_service_spec.rb b/spec/services/ci/process_build_service_spec.rb index 704685417bb..abc5c18a523 100644 --- a/spec/services/ci/process_build_service_spec.rb +++ b/spec/services/ci/process_build_service_spec.rb @@ -22,6 +22,14 @@ describe Ci::ProcessBuildService, '#execute' do end end + context 'when current status is skipped' do + let(:current_status) { 'skipped' } + + it 'changes the build status' do + expect { subject }.to change { build.status }.to('pending') + end + end + context 'when current status is failed' do let(:current_status) { 'failed' } @@ -114,4 +122,27 @@ describe Ci::ProcessBuildService, '#execute' do end end end + + context 'when build is scheduled with DAG' do + let(:pipeline) { create(:ci_pipeline, ref: 'master', project: project) } + let!(:build) { create(:ci_build, :created, when: :on_success, pipeline: pipeline, scheduling_type: :dag) } + let!(:other_build) { create(:ci_build, :created, when: :on_success, pipeline: pipeline) } + let!(:build_on_other_build) { create(:ci_build_need, build: build, name: other_build.name) } + + context 'when current status is success' do + let(:current_status) { 'success' } + + it 'enqueues the build' do + expect { subject }.to change { build.status }.to('pending') + end + end + + context 'when current status is skipped' do + let(:current_status) { 'skipped' } + + it 'skips the build' do + expect { subject }.to change { build.status }.to('skipped') + end + end + end end |