Commit 84016f83 authored by Constance Okoghenun's avatar Constance Okoghenun

Resolved conflicts with master

parents 6b63e11d b44b4d4d
...@@ -401,6 +401,7 @@ gem 'sys-filesystem', '~> 1.1.6' ...@@ -401,6 +401,7 @@ gem 'sys-filesystem', '~> 1.1.6'
# SSH host key support # SSH host key support
gem 'net-ssh', '~> 4.1.0' gem 'net-ssh', '~> 4.1.0'
gem 'sshkey', '~> 1.9.0'
# Required for ED25519 SSH host key support # Required for ED25519 SSH host key support
group :ed25519 do group :ed25519 do
......
...@@ -895,6 +895,7 @@ GEM ...@@ -895,6 +895,7 @@ GEM
activesupport (>= 4.0) activesupport (>= 4.0)
sprockets (>= 3.0.0) sprockets (>= 3.0.0)
sqlite3 (1.3.13) sqlite3 (1.3.13)
sshkey (1.9.0)
stackprof (0.2.10) stackprof (0.2.10)
state_machines (0.4.0) state_machines (0.4.0)
state_machines-activemodel (0.4.0) state_machines-activemodel (0.4.0)
...@@ -1192,6 +1193,7 @@ DEPENDENCIES ...@@ -1192,6 +1193,7 @@ DEPENDENCIES
spring-commands-rspec (~> 1.0.4) spring-commands-rspec (~> 1.0.4)
spring-commands-spinach (~> 1.1.0) spring-commands-spinach (~> 1.1.0)
sprockets (~> 3.7.0) sprockets (~> 3.7.0)
sshkey (~> 1.9.0)
stackprof (~> 0.2.10) stackprof (~> 0.2.10)
state_machines-activerecord (~> 0.4.0) state_machines-activerecord (~> 0.4.0)
sys-filesystem (~> 1.1.6) sys-filesystem (~> 1.1.6)
......
...@@ -43,175 +43,14 @@ var Dispatcher; ...@@ -43,175 +43,14 @@ var Dispatcher;
}); });
switch (page) { switch (page) {
case 'projects:environments:metrics':
import('./pages/projects/environments/metrics')
.then(callDefault)
.catch(fail);
break;
case 'projects:merge_requests:index': case 'projects:merge_requests:index':
case 'projects:issues:index': case 'projects:issues:index':
case 'projects:issues:show': case 'projects:issues:show':
shortcut_handler = true;
break;
case 'projects:milestones:index':
import('./pages/projects/milestones/index')
.then(callDefault)
.catch(fail);
break;
case 'projects:milestones:show':
import('./pages/projects/milestones/show')
.then(callDefault)
.catch(fail);
break;
case 'groups:milestones:show':
import('./pages/groups/milestones/show')
.then(callDefault)
.catch(fail);
break;
case 'dashboard:milestones:show':
import('./pages/dashboard/milestones/show')
.then(callDefault)
.catch(fail);
break;
case 'dashboard:issues':
import('./pages/dashboard/issues')
.then(callDefault)
.catch(fail);
break;
case 'dashboard:merge_requests':
import('./pages/dashboard/merge_requests')
.then(callDefault)
.catch(fail);
break;
case 'groups:issues':
import('./pages/groups/issues')
.then(callDefault)
.catch(fail);
break;
case 'groups:merge_requests':
import('./pages/groups/merge_requests')
.then(callDefault)
.catch(fail);
break;
case 'dashboard:todos:index':
import('./pages/dashboard/todos/index')
.then(callDefault)
.catch(fail);
break;
case 'admin:jobs:index':
import('./pages/admin/jobs/index')
.then(callDefault)
.catch(fail);
break;
case 'admin:projects:index':
import('./pages/admin/projects/index/index')
.then(callDefault)
.catch(fail);
break;
case 'admin:users:index':
import('./pages/admin/users/shared')
.then(callDefault)
.catch(fail);
break;
case 'admin:users:show':
import('./pages/admin/users/shared')
.then(callDefault)
.catch(fail);
break;
case 'dashboard:projects:index':
case 'dashboard:projects:starred':
import('./pages/dashboard/projects')
.then(callDefault)
.catch(fail);
break;
case 'explore:projects:index':
case 'explore:projects:trending':
case 'explore:projects:starred':
import('./pages/explore/projects')
.then(callDefault)
.catch(fail);
break;
case 'explore:groups:index':
import('./pages/explore/groups')
.then(callDefault)
.catch(fail);
break;
case 'projects:milestones:new':
case 'projects:milestones:create':
import('./pages/projects/milestones/new')
.then(callDefault)
.catch(fail);
break;
case 'projects:milestones:edit':
case 'projects:milestones:update':
import('./pages/projects/milestones/edit')
.then(callDefault)
.catch(fail);
break;
case 'groups:milestones:new':
case 'groups:milestones:create':
import('./pages/groups/milestones/new')
.then(callDefault)
.catch(fail);
break;
case 'groups:milestones:edit':
case 'groups:milestones:update':
import('./pages/groups/milestones/edit')
.then(callDefault)
.catch(fail);
break;
case 'projects:compare:show':
import('./pages/projects/compare/show')
.then(callDefault)
.catch(fail);
break;
case 'projects:branches:new':
import('./pages/projects/branches/new')
.then(callDefault)
.catch(fail);
break;
case 'projects:branches:create':
import('./pages/projects/branches/new')
.then(callDefault)
.catch(fail);
break;
case 'projects:branches:index':
import('./pages/projects/branches/index')
.then(callDefault)
.catch(fail);
break;
case 'projects:boards:show':
case 'projects:boards:index':
import('./pages/projects/boards')
.then(callDefault)
.catch(fail);
break;
case 'projects:issues:new': case 'projects:issues:new':
import('./pages/projects/issues/new')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'projects:issues:edit': case 'projects:issues:edit':
import('./pages/projects/issues/edit')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'projects:merge_requests:creations:new': case 'projects:merge_requests:creations:new':
import('./pages/projects/merge_requests/creations/new')
.then(callDefault)
.catch(fail);
case 'projects:merge_requests:creations:diffs': case 'projects:merge_requests:creations:diffs':
import('./pages/projects/merge_requests/creations/diffs')
.then(callDefault)
.catch(fail);
shortcut_handler = true;
break;
case 'projects:merge_requests:edit': case 'projects:merge_requests:edit':
import('./pages/projects/merge_requests/edit')
.then(callDefault)
.catch(fail);
shortcut_handler = true; shortcut_handler = true;
break; break;
case 'projects:tags:new': case 'projects:tags:new':
......
import Chart from 'vendor/Chart';
// export to global scope
window.Chart = Chart;
...@@ -6,6 +6,11 @@ monacoContext.require.config({ ...@@ -6,6 +6,11 @@ monacoContext.require.config({
}, },
}); });
// ignore CDN config and use local assets path for service worker which cannot be cross-domain
const relativeRootPath = (gon && gon.relative_url_root) || '';
const monacoPath = `${relativeRootPath}/assets/webpack/monaco-editor/vs`;
window.MonacoEnvironment = { getWorkerUrl: () => `${monacoPath}/base/worker/workerMain.js` };
// eslint-disable-next-line no-underscore-dangle // eslint-disable-next-line no-underscore-dangle
window.__monaco_context__ = monacoContext; window.__monaco_context__ = monacoContext;
export default monacoContext.require; export default monacoContext.require;
import Vue from 'vue'; import Vue from 'vue';
import Translate from '~/vue_shared/translate'; import Translate from '~/vue_shared/translate';
import stopJobsModal from './components/stop_jobs_modal.vue'; import stopJobsModal from './components/stop_jobs_modal.vue';
Vue.use(Translate); Vue.use(Translate);
export default () => { document.addEventListener('DOMContentLoaded', () => {
const stopJobsButton = document.getElementById('stop-jobs-button'); const stopJobsButton = document.getElementById('stop-jobs-button');
if (stopJobsButton) { if (stopJobsButton) {
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
...@@ -27,4 +25,4 @@ export default () => { ...@@ -27,4 +25,4 @@ export default () => {
}, },
}); });
} }
}; });
...@@ -5,7 +5,7 @@ import csrf from '~/lib/utils/csrf'; ...@@ -5,7 +5,7 @@ import csrf from '~/lib/utils/csrf';
import deleteProjectModal from './components/delete_project_modal.vue'; import deleteProjectModal from './components/delete_project_modal.vue';
export default () => { document.addEventListener('DOMContentLoaded', () => {
Vue.use(Translate); Vue.use(Translate);
const deleteProjectModalEl = document.getElementById('delete-project-modal'); const deleteProjectModalEl = document.getElementById('delete-project-modal');
...@@ -34,4 +34,4 @@ export default () => { ...@@ -34,4 +34,4 @@ export default () => {
deleteModal.projectName = buttonProps.projectName; deleteModal.projectName = buttonProps.projectName;
} }
}); });
}; });
...@@ -5,7 +5,7 @@ import csrf from '~/lib/utils/csrf'; ...@@ -5,7 +5,7 @@ import csrf from '~/lib/utils/csrf';
import deleteUserModal from './components/delete_user_modal.vue'; import deleteUserModal from './components/delete_user_modal.vue';
export default () => { document.addEventListener('DOMContentLoaded', () => {
Vue.use(Translate); Vue.use(Translate);
const deleteUserModalEl = document.getElementById('delete-user-modal'); const deleteUserModalEl = document.getElementById('delete-user-modal');
...@@ -40,4 +40,4 @@ export default () => { ...@@ -40,4 +40,4 @@ export default () => {
deleteModal.username = buttonProps.username; deleteModal.username = buttonProps.username;
} }
}); });
}; });
import projectSelect from '~/project_select'; import projectSelect from '~/project_select';
import initLegacyFilters from '~/init_legacy_filters'; import initLegacyFilters from '~/init_legacy_filters';
export default () => { document.addEventListener('DOMContentLoaded', () => {
projectSelect(); projectSelect();
initLegacyFilters(); initLegacyFilters();
}; });
import projectSelect from '~/project_select'; import projectSelect from '~/project_select';
import initLegacyFilters from '~/init_legacy_filters'; import initLegacyFilters from '~/init_legacy_filters';
export default () => { document.addEventListener('DOMContentLoaded', () => {
projectSelect(); projectSelect();
initLegacyFilters(); initLegacyFilters();
}; });
import Milestone from '~/milestone'; import Milestone from '~/milestone';
import Sidebar from '~/right_sidebar'; import Sidebar from '~/right_sidebar';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new Milestone(); // eslint-disable-line no-new new Milestone(); // eslint-disable-line no-new
new Sidebar(); // eslint-disable-line no-new new Sidebar(); // eslint-disable-line no-new
}; });
import ProjectsList from '~/projects_list'; import ProjectsList from '~/projects_list';
export default () => new ProjectsList(); document.addEventListener('DOMContentLoaded', () => new ProjectsList());
import Todos from './todos'; import Todos from './todos';
export default () => new Todos(); document.addEventListener('DOMContentLoaded', () => new Todos());
...@@ -2,7 +2,7 @@ import GroupsList from '~/groups_list'; ...@@ -2,7 +2,7 @@ import GroupsList from '~/groups_list';
import Landing from '~/landing'; import Landing from '~/landing';
import initGroupsList from '../../../groups'; import initGroupsList from '../../../groups';
export default function () { document.addEventListener('DOMContentLoaded', () => {
new GroupsList(); // eslint-disable-line no-new new GroupsList(); // eslint-disable-line no-new
initGroupsList(); initGroupsList();
const landingElement = document.querySelector('.js-explore-groups-landing'); const landingElement = document.querySelector('.js-explore-groups-landing');
...@@ -13,4 +13,4 @@ export default function () { ...@@ -13,4 +13,4 @@ export default function () {
'explore_groups_landing_dismissed', 'explore_groups_landing_dismissed',
); );
exploreGroupsLanding.toggle(); exploreGroupsLanding.toggle();
} });
import ProjectsList from '~/projects_list'; import ProjectsList from '~/projects_list';
export default () => new ProjectsList(); document.addEventListener('DOMContentLoaded', () => new ProjectsList());
...@@ -2,9 +2,9 @@ import projectSelect from '~/project_select'; ...@@ -2,9 +2,9 @@ import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search'; import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants'; import { FILTERED_SEARCH } from '~/pages/constants';
export default () => { document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({ initFilteredSearch({
page: FILTERED_SEARCH.ISSUES, page: FILTERED_SEARCH.ISSUES,
}); });
projectSelect(); projectSelect();
}; });
...@@ -2,9 +2,9 @@ import projectSelect from '~/project_select'; ...@@ -2,9 +2,9 @@ import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search'; import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants'; import { FILTERED_SEARCH } from '~/pages/constants';
export default () => { document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({ initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS, page: FILTERED_SEARCH.MERGE_REQUESTS,
}); });
projectSelect(); projectSelect();
}; });
import initForm from '../../../../shared/milestones/form'; import initForm from '../../../../shared/milestones/form';
export default () => initForm(false); document.addEventListener('DOMContentLoaded', () => initForm(false));
import initForm from '../../../../shared/milestones/form'; import initForm from '../../../../shared/milestones/form';
export default () => initForm(false); document.addEventListener('DOMContentLoaded', () => initForm(false));
import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show'; import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
export default initMilestonesShow; document.addEventListener('DOMContentLoaded', initMilestonesShow);
...@@ -2,8 +2,8 @@ import UsersSelect from '~/users_select'; ...@@ -2,8 +2,8 @@ import UsersSelect from '~/users_select';
import ShortcutsNavigation from '~/shortcuts_navigation'; import ShortcutsNavigation from '~/shortcuts_navigation';
import initBoards from '~/boards'; import initBoards from '~/boards';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new UsersSelect(); // eslint-disable-line no-new new UsersSelect(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new new ShortcutsNavigation(); // eslint-disable-line no-new
initBoards(); initBoards();
}; });
import AjaxLoadingSpinner from '~/ajax_loading_spinner'; import AjaxLoadingSpinner from '~/ajax_loading_spinner';
import DeleteModal from '~/branches/branches_delete_modal'; import DeleteModal from '~/branches/branches_delete_modal';
export default () => { document.addEventListener('DOMContentLoaded', () => {
AjaxLoadingSpinner.init(); AjaxLoadingSpinner.init();
new DeleteModal(); // eslint-disable-line no-new new DeleteModal(); // eslint-disable-line no-new
}; });
import NewBranchForm from '~/new_branch_form'; import NewBranchForm from '~/new_branch_form';
export default () => new NewBranchForm($('.js-create-branch-form'), JSON.parse(document.getElementById('availableRefs').innerHTML)); document.addEventListener('DOMContentLoaded', () => (
new NewBranchForm($('.js-create-branch-form'), JSON.parse(document.getElementById('availableRefs').innerHTML))
));
import Diff from '~/diff'; import Diff from '~/diff';
import initChangesDropdown from '~/init_changes_dropdown'; import initChangesDropdown from '~/init_changes_dropdown';
export default () => { document.addEventListener('DOMContentLoaded', () => {
new Diff(); // eslint-disable-line no-new new Diff(); // eslint-disable-line no-new
const paddingTop = 16; const paddingTop = 16;
initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight - paddingTop); initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight - paddingTop);
}; });
import monitoringBundle from '~/monitoring/monitoring_bundle'; import monitoringBundle from '~/monitoring/monitoring_bundle';
export default monitoringBundle; document.addEventListener('DOMContentLoaded', monitoringBundle);
import Chart from 'vendor/Chart'; import Chart from 'chart.js';
import _ from 'underscore'; import _ from 'underscore';
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
......
import initForm from '../form'; import initForm from '../form';
export default () => { document.addEventListener('DOMContentLoaded', initForm);
initForm();
};
import initForm from '../form'; import initForm from '../form';
export default () => { document.addEventListener('DOMContentLoaded', initForm);
initForm();
};
import initMergeRequest from '~/pages/projects/merge_requests/init_merge_request'; import initMergeRequest from '~/pages/projects/merge_requests/init_merge_request';
export default initMergeRequest; document.addEventListener('DOMContentLoaded', initMergeRequest);
import Compare from '~/compare'; import Compare from '~/compare';
import MergeRequest from '~/merge_request'; import MergeRequest from '~/merge_request';
export default () => { document.addEventListener('DOMContentLoaded', () => {
const mrNewCompareNode = document.querySelector('.js-merge-request-new-compare'); const mrNewCompareNode = document.querySelector('.js-merge-request-new-compare');
if (mrNewCompareNode) { if (mrNewCompareNode) {
new Compare({ // eslint-disable-line no-new new Compare({ // eslint-disable-line no-new
...@@ -15,4 +15,4 @@ export default () => { ...@@ -15,4 +15,4 @@ export default () => {
action: mrNewSubmitNode.dataset.mrSubmitAction, action: mrNewSubmitNode.dataset.mrSubmitAction,
}); });
} }
}; });
import initMergeRequest from '~/pages/projects/merge_requests/init_merge_request'; import initMergeRequest from '~/pages/projects/merge_requests/init_merge_request';
export default initMergeRequest; document.addEventListener('DOMContentLoaded', initMergeRequest);
import initForm from '../../../../shared/milestones/form'; import initForm from '../../../../shared/milestones/form';
export default () => initForm(); document.addEventListener('DOMContentLoaded', () => initForm());
import milestones from '~/pages/milestones/shared'; import milestones from '~/pages/milestones/shared';
export default milestones; document.addEventListener('DOMContentLoaded', milestones);
import initForm from '../../../../shared/milestones/form'; import initForm from '../../../../shared/milestones/form';
export default () => initForm(); document.addEventListener('DOMContentLoaded', () => initForm());
import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show'; import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
import milestones from '~/pages/milestones/shared'; import milestones from '~/pages/milestones/shared';
export default () => { document.addEventListener('DOMContentLoaded', () => {
initMilestonesShow(); initMilestonesShow();
milestones(); milestones();
}; });
import Chart from 'vendor/Chart'; import Chart from 'chart.js';
const options = { const options = {
scaleOverlay: true, scaleOverlay: true,
......
...@@ -44,7 +44,10 @@ ...@@ -44,7 +44,10 @@
type="button" type="button"
class="btn btn-xs btn-default" class="btn btn-xs btn-default"
> >
<loading-icon v-if="isRefreshing" /> <loading-icon
v-if="isRefreshing"
:inline="true"
/>
{{ s__("mrWidget|Refresh") }} {{ s__("mrWidget|Refresh") }}
</button> </button>
</div> </div>
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
.status-neutral, .status-neutral,
.status-red, { .status-red, {
height: 100%; height: 100%;
min-width: 25px; min-width: 30px;
padding: 0 5px; padding: 0 5px;
font-size: $tooltip-font-size; font-size: $tooltip-font-size;
font-weight: normal; font-weight: normal;
......
...@@ -7,17 +7,24 @@ module WebpackHelper ...@@ -7,17 +7,24 @@ module WebpackHelper
def webpack_controller_bundle_tags def webpack_controller_bundle_tags
bundles = [] bundles = []
segments = [*controller.controller_path.split('/'), controller.action_name].compact
until segments.empty? action = case controller.action_name
when 'create' then 'new'
when 'update' then 'edit'
else controller.action_name
end
route = [*controller.controller_path.split('/'), action].compact
until route.empty?
begin begin
asset_paths = gitlab_webpack_asset_paths("pages.#{segments.join('.')}", extension: 'js') asset_paths = gitlab_webpack_asset_paths("pages.#{route.join('.')}", extension: 'js')
bundles.unshift(*asset_paths) bundles.unshift(*asset_paths)
rescue Webpack::Rails::Manifest::EntryPointMissingError rescue Webpack::Rails::Manifest::EntryPointMissingError
# no bundle exists for this path # no bundle exists for this path
end end
segments.pop route.pop
end end
javascript_include_tag(*bundles) javascript_include_tag(*bundles)
......
...@@ -7,18 +7,11 @@ module Emails ...@@ -7,18 +7,11 @@ module Emails
helper_method :member_source, :member helper_method :member_source, :member
end end
def member_access_requested_email(member_source_type, member_id) def member_access_requested_email(member_source_type, member_id, recipient_notification_email)
@member_source_type = member_source_type @member_source_type = member_source_type
@member_id = member_id @member_id = member_id
admins = member_source.members.owners_and_masters.pluck(:notification_email) mail(to: recipient_notification_email,
# A project in a group can have no explicit owners/masters, in that case
# we fallbacks to the group's owners/masters.
if admins.empty? && member_source.respond_to?(:group) && member_source.group
admins = member_source.group.members.owners_and_masters.pluck(:notification_email)
end
mail(to: admins,
subject: subject("Request to join the #{member_source.human_name} #{member_source.model_name.singular}")) subject: subject("Request to join the #{member_source.human_name} #{member_source.model_name.singular}"))
end end
......
...@@ -41,41 +41,12 @@ module Ci ...@@ -41,41 +41,12 @@ module Ci
scope :unstarted, ->() { where(runner_id: nil) } scope :unstarted, ->() { where(runner_id: nil) }
scope :ignore_failures, ->() { where(allow_failure: false) } scope :ignore_failures, ->() { where(allow_failure: false) }
# This convoluted mess is because we need to handle two cases of
# artifact files during the migration. And a simple OR clause
# makes it impossible to optimize.
# Instead we want to use UNION ALL and do two carefully
# constructed disjoint queries. But Rails cannot handle UNION or
# UNION ALL queries so we do the query in a subquery and wrap it
# in an otherwise redundant WHERE IN query (IN is fine for
# non-null columns).
# This should all be ripped out when the migration is finished and
# replaced with just the new storage to avoid the extra work.
scope :with_artifacts, ->() do scope :with_artifacts, ->() do
old = Ci::Build.select(:id).where(%q[artifacts_file <> '']) where('(artifacts_file IS NOT NULL AND artifacts_file <> ?) OR EXISTS (?)',
new = Ci::Build.select(:id).where(%q[(artifacts_file IS NULL OR artifacts_file = '') AND EXISTS (?)], '', Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id'))
Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id'))
where('ci_builds.id IN (? UNION ALL ?)', old, new)
end end
scope :with_artifacts_not_expired, ->() { with_artifacts.where('artifacts_expire_at IS NULL OR artifacts_expire_at > ?', Time.now) }
scope :with_artifacts_not_expired, ->() do scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) }
old = Ci::Build.select(:id).where(%q[artifacts_file <> '' AND (artifacts_expire_at IS NULL OR artifacts_expire_at > ?)], Time.now)
new = Ci::Build.select(:id).where(%q[(artifacts_file IS NULL OR artifacts_file = '') AND EXISTS (?)],
Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id AND (expire_at IS NULL OR expire_at > ?)', Time.now))
where('ci_builds.id IN (? UNION ALL ?)', old, new)
end
scope :with_expired_artifacts, ->() do
old = Ci::Build.select(:id).where(%q[artifacts_file <> '' AND artifacts_expire_at < ?], Time.now)
new = Ci::Build.select(:id).where(%q[(artifacts_file IS NULL OR artifacts_file = '') AND EXISTS (?)],
Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id AND expire_at < ?', Time.now))
where('ci_builds.id IN (? UNION ALL ?)', old, new)
end
scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) } scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) }
scope :manual_actions, ->() { where(when: :manual, status: COMPLETED_STATUSES + [:manual]) } scope :manual_actions, ->() { where(when: :manual, status: COMPLETED_STATUSES + [:manual]) }
scope :ref_protected, -> { where(protected: true) } scope :ref_protected, -> { where(protected: true) }
......
...@@ -417,6 +417,10 @@ class Commit ...@@ -417,6 +417,10 @@ class Commit
!!(title =~ WIP_REGEX) !!(title =~ WIP_REGEX)
end end
def merged_merge_request?(user)
!!merged_merge_request(user)
end
private private
def commit_reference(from, referable_commit_id, full: false) def commit_reference(from, referable_commit_id, full: false)
...@@ -445,10 +449,6 @@ class Commit ...@@ -445,10 +449,6 @@ class Commit
changes changes
end end
def merged_merge_request?(user)
!!merged_merge_request(user)
end
def merged_merge_request_no_cache(user) def merged_merge_request_no_cache(user)
MergeRequestsFinder.new(user, project_id: project.id).find_by(merge_commit_sha: id) if merge_commit? MergeRequestsFinder.new(user, project_id: project.id).find_by(merge_commit_sha: id) if merge_commit?
end end
......
...@@ -33,9 +33,8 @@ class Key < ActiveRecord::Base ...@@ -33,9 +33,8 @@ class Key < ActiveRecord::Base
after_destroy :refresh_user_cache after_destroy :refresh_user_cache
def key=(value) def key=(value)
value&.delete!("\n\r") write_attribute(:key, value.present? ? Gitlab::SSHPublicKey.sanitize(value) : nil)
value.strip! unless value.blank?
write_attribute(:key, value)
@public_key = nil @public_key = nil
end end
...@@ -97,7 +96,7 @@ class Key < ActiveRecord::Base ...@@ -97,7 +96,7 @@ class Key < ActiveRecord::Base
def generate_fingerprint def generate_fingerprint
self.fingerprint = nil self.fingerprint = nil
return unless self.key.present? return unless public_key.valid?
self.fingerprint = public_key.fingerprint self.fingerprint = public_key.fingerprint
end end
......
...@@ -492,12 +492,8 @@ class Repository ...@@ -492,12 +492,8 @@ class Repository
end end
def root_ref def root_ref
if raw_repository # When the repo does not exist, or there is no root ref, we raise this error so no data is cached.
raw_repository.root_ref raw_repository&.root_ref or raise Gitlab::Git::Repository::NoRepository # rubocop:disable Style/AndOr
else
# When the repo does not exist we raise this error so no data is cached.
raise Gitlab::Git::Repository::NoRepository
end
end end
cache_method :root_ref cache_method :root_ref
......
...@@ -59,6 +59,8 @@ class User < ActiveRecord::Base ...@@ -59,6 +59,8 @@ class User < ActiveRecord::Base
# Override Devise::Models::Trackable#update_tracked_fields! # Override Devise::Models::Trackable#update_tracked_fields!
# to limit database writes to at most once every hour # to limit database writes to at most once every hour
def update_tracked_fields!(request) def update_tracked_fields!(request)
return if Gitlab::Database.read_only?
update_tracked_fields(request) update_tracked_fields(request)
lease = Gitlab::ExclusiveLease.new("user_update_tracked_fields:#{id}", timeout: 1.hour.to_i) lease = Gitlab::ExclusiveLease.new("user_update_tracked_fields:#{id}", timeout: 1.hour.to_i)
......
...@@ -48,7 +48,8 @@ module Issues ...@@ -48,7 +48,8 @@ module Issues
new_params = { id: nil, iid: nil, label_ids: cloneable_label_ids, new_params = { id: nil, iid: nil, label_ids: cloneable_label_ids,
milestone_id: cloneable_milestone_id, milestone_id: cloneable_milestone_id,
project: @new_project, author: @old_issue.author, project: @new_project, author: @old_issue.author,
description: rewrite_content(@old_issue.description) } description: rewrite_content(@old_issue.description),
assignee_ids: @old_issue.assignee_ids }
new_params = @old_issue.serializable_hash.symbolize_keys.merge(new_params) new_params = @old_issue.serializable_hash.symbolize_keys.merge(new_params)
CreateService.new(@new_project, @current_user, new_params).execute CreateService.new(@new_project, @current_user, new_params).execute
......
...@@ -208,7 +208,12 @@ class NotificationService ...@@ -208,7 +208,12 @@ class NotificationService
def new_access_request(member) def new_access_request(member)
return true unless member.notifiable?(:subscription) return true unless member.notifiable?(:subscription)
mailer.member_access_requested_email(member.real_source_type, member.id).deliver_later recipients = member.source.members.owners_and_masters
if fallback_to_group_owners_masters?(recipients, member)
recipients = member.source.group.members.owners_and_masters
end
recipients.each { |recipient| deliver_access_request_email(recipient, member) }
end end
def decline_access_request(member) def decline_access_request(member)
...@@ -435,4 +440,14 @@ class NotificationService ...@@ -435,4 +440,14 @@ class NotificationService
def notifiable_users(*args) def notifiable_users(*args)
NotificationRecipientService.notifiable_users(*args) NotificationRecipientService.notifiable_users(*args)
end end
def deliver_access_request_email(recipient, member)
mailer.member_access_requested_email(member.real_source_type, member.id, recipient.user.notification_email).deliver_later
end
def fallback_to_group_owners_masters?(recipients, member)
return false if recipients.present?
member.source.respond_to?(:group) && member.source.group
end
end end
- if inject_u2f_api? - if inject_u2f_api?
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('u2f') = webpack_bundle_tag('u2f')
%div %div
= render 'devise/shared/tab_single', tab_title: 'Two-Factor Authentication' = render 'devise/shared/tab_single', tab_title: 'Two-Factor Authentication'
......
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('profile') = webpack_bundle_tag('profile')
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
- if inject_u2f_api? - if inject_u2f_api?
= page_specific_javascript_bundle_tag('u2f') = webpack_bundle_tag('u2f')
= page_specific_javascript_bundle_tag('two_factor_auth') = webpack_bundle_tag('two_factor_auth')
.js-two-factor-auth{ 'data-two-factor-skippable' => "#{two_factor_skippable?}", 'data-two_factor_skip_url' => skip_profile_two_factor_auth_path } .js-two-factor-auth{ 'data-two-factor-skippable' => "#{two_factor_skippable?}", 'data-two_factor_skip_url' => skip_profile_two_factor_auth_path }
.row.prepend-top-default .row.prepend-top-default
......
...@@ -29,4 +29,4 @@ ...@@ -29,4 +29,4 @@
= commit_in_fork_help = commit_in_fork_help
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('blob') = webpack_bundle_tag('blob')
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
- page_title "Edit", @blob.path, @ref - page_title "Edit", @blob.path, @ref
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/ace.js') = page_specific_javascript_tag('lib/ace.js')
= page_specific_javascript_bundle_tag('blob') = webpack_bundle_tag('blob')
%div{ class: container_class } %div{ class: container_class }
- if @conflict - if @conflict
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
- page_title "New File", @path.presence, @ref - page_title "New File", @path.presence, @ref
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/ace.js') = page_specific_javascript_tag('lib/ace.js')
= page_specific_javascript_bundle_tag('blob') = webpack_bundle_tag('blob')
.editor-title-row .editor-title-row
%h3.page-title.blob-new-page-title %h3.page-title.blob-new-page-title
New file New file
......
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('balsamiq_viewer') = webpack_bundle_tag('balsamiq_viewer')
.file-content.balsamiq-viewer#js-balsamiq-viewer{ data: { endpoint: blob_raw_path } } .file-content.balsamiq-viewer#js-balsamiq-viewer{ data: { endpoint: blob_raw_path } }
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('notebook_viewer') = webpack_bundle_tag('notebook_viewer')
.file-content#js-notebook-viewer{ data: { endpoint: blob_raw_path } } .file-content#js-notebook-viewer{ data: { endpoint: blob_raw_path } }
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('pdf_viewer') = webpack_bundle_tag('pdf_viewer')
.file-content#js-pdf-viewer{ data: { endpoint: blob_raw_path } } .file-content#js-pdf-viewer{ data: { endpoint: blob_raw_path } }
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('sketch_viewer') = webpack_bundle_tag('sketch_viewer')
.file-content#js-sketch-viewer{ data: { endpoint: blob_raw_path } } .file-content#js-sketch-viewer{ data: { endpoint: blob_raw_path } }
.js-loading-icon.text-center.prepend-top-default.append-bottom-default.js-loading-icon{ 'aria-label' => 'Loading Sketch preview' } .js-loading-icon.text-center.prepend-top-default.append-bottom-default.js-loading-icon{ 'aria-label' => 'Loading Sketch preview' }
......
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('stl_viewer') = webpack_bundle_tag('stl_viewer')
.file-content.is-stl-loading .file-content.is-stl-loading
.text-center#js-stl-viewer{ data: { endpoint: blob_raw_path } } .text-center#js-stl-viewer{ data: { endpoint: blob_raw_path } }
......
...@@ -8,5 +8,5 @@ ...@@ -8,5 +8,5 @@
} } } }
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('commit_pipelines') = webpack_bundle_tag('commit_pipelines')
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
- page_title "#{@commit.title} (#{@commit.short_id})", "Commits" - page_title "#{@commit.title} (#{@commit.short_id})", "Commits"
- page_description @commit.description - page_description @commit.description
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('diff_notes') = webpack_bundle_tag('diff_notes')
.container-fluid{ class: [limited_container_width, container_class] } .container-fluid{ class: [limited_container_width, container_class] }
= render "commit_box" = render "commit_box"
......
- @no_container = true - @no_container = true
- page_title "Cycle Analytics" - page_title "Cycle Analytics"
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('cycle_analytics') = webpack_bundle_tag('cycle_analytics')
#cycle-analytics{ class: container_class, "v-cloak" => "true", data: { request_path: project_cycle_analytics_path(@project) } } #cycle-analytics{ class: container_class, "v-cloak" => "true", data: { request_path: project_cycle_analytics_path(@project) } }
- if @cycle_analytics_no_data - if @cycle_analytics_no_data
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
- page_title "Environments" - page_title "Environments"
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag("environments_folder") = webpack_bundle_tag("environments_folder")
#environments-folder-list-view{ data: { endpoint: folder_project_environments_path(@project, @folder, format: :json), #environments-folder-list-view{ data: { endpoint: folder_project_environments_path(@project, @folder, format: :json),
"folder-name" => @folder, "folder-name" => @folder,
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project)) - add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag("common_vue") = webpack_bundle_tag("common_vue")
= page_specific_javascript_bundle_tag("environments") = webpack_bundle_tag("environments")
#environments-list-view{ data: { environments_data: environments_list_data, #environments-list-view{ data: { environments_data: environments_list_data,
"can-create-deployment" => can?(current_user, :create_deployment, @project).to_s, "can-create-deployment" => can?(current_user, :create_deployment, @project).to_s,
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= stylesheet_link_tag "xterm/xterm" = stylesheet_link_tag "xterm/xterm"
= page_specific_javascript_bundle_tag("terminal") = webpack_bundle_tag("terminal")
%div{ class: container_class } %div{ class: container_class }
.top-area .top-area
......
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
- page_title "Charts" - page_title "Charts"
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= webpack_bundle_tag('common_d3') = webpack_bundle_tag('common_d3')
= webpack_bundle_tag('graphs')
= webpack_bundle_tag('graphs_charts')
.repo-charts{ class: container_class } .repo-charts{ class: container_class }
%h4.sub-header %h4.sub-header
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
- page_title _('Contributors') - page_title _('Contributors')
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= webpack_bundle_tag('common_d3') = webpack_bundle_tag('common_d3')
= webpack_bundle_tag('graphs')
= webpack_bundle_tag('graphs_show') = webpack_bundle_tag('graphs_show')
.js-graphs-show{ class: container_class, 'data-project-graph-path': project_graph_path(@project, current_ref, format: :json) } .js-graphs-show{ class: container_class, 'data-project-graph-path': project_graph_path(@project, current_ref, format: :json) }
......
...@@ -87,5 +87,5 @@ ...@@ -87,5 +87,5 @@
= render 'shared/issuable/sidebar', issuable: @issue = render 'shared/issuable/sidebar', issuable: @issue
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('issue_show') = webpack_bundle_tag('issue_show')
- page_title "Merge Conflicts", "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests" - page_title "Merge Conflicts", "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests"
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('merge_conflicts') = webpack_bundle_tag('merge_conflicts')
= page_specific_javascript_tag('lib/ace.js') = page_specific_javascript_tag('lib/ace.js')
= render "projects/merge_requests/mr_title" = render "projects/merge_requests/mr_title"
......
- page_title "Merge Conflicts", "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests" - page_title "Merge Conflicts", "#{@merge_request.title} (#{@merge_request.to_reference}", "Merge Requests"
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('merge_conflicts') = webpack_bundle_tag('merge_conflicts')
= page_specific_javascript_tag('lib/ace.js') = page_specific_javascript_tag('lib/ace.js')
= render "projects/merge_requests/mr_title" = render "projects/merge_requests/mr_title"
......
- breadcrumb_title "Graph" - breadcrumb_title "Graph"
- page_title "Graph", @ref - page_title "Graph", @ref
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('network') = webpack_bundle_tag('network')
= render "head" = render "head"
%div{ class: container_class } %div{ class: container_class }
.project-network .project-network
......
...@@ -13,5 +13,5 @@ ...@@ -13,5 +13,5 @@
"ci-lint-path" => ci_lint_path, "ci-lint-path" => ci_lint_path,
"reset-cache-path" => reset_cache_project_settings_ci_cd_path(@project) } } "reset-cache-path" => reset_cache_project_settings_ci_cd_path(@project) } }
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('pipelines') = webpack_bundle_tag('pipelines')
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('protected_branches') = webpack_bundle_tag('protected_branches')
- content_for :create_protected_branch do - content_for :create_protected_branch do
= render 'projects/protected_branches/create_protected_branch' = render 'projects/protected_branches/create_protected_branch'
......
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('protected_tags') = webpack_bundle_tag('protected_tags')
- content_for :create_protected_tag do - content_for :create_protected_tag do
= render 'projects/protected_tags/create_protected_tag' = render 'projects/protected_tags/create_protected_tag'
......
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
.col-lg-12 .col-lg-12
#js-vue-registry-images{ data: { endpoint: project_container_registry_index_path(@project, format: :json) } } #js-vue-registry-images{ data: { endpoint: project_container_registry_index_path(@project, format: :json) } }
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('registry_list') = webpack_bundle_tag('registry_list')
.row.prepend-top-10 .row.prepend-top-10
.col-lg-12 .col-lg-12
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
- @content_class = "limit-container-width" unless fluid_layout - @content_class = "limit-container-width" unless fluid_layout
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('deploy_keys') = webpack_bundle_tag('deploy_keys')
-# Protected branches & tags use a lot of nested partials. -# Protected branches & tags use a lot of nested partials.
-# The shared parts of the views can be found in the `shared` directory. -# The shared parts of the views can be found in the `shared` directory.
......
- todo = issuable_todo(issuable) - todo = issuable_todo(issuable)
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('common_vue') = webpack_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('sidebar') = webpack_bundle_tag('sidebar')
%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: current_user.present? } }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' } %aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { signed: { in: current_user.present? } }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' }
.issuable-sidebar{ data: { endpoint: "#{issuable_json_path(issuable)}" } } .issuable-sidebar{ data: { endpoint: "#{issuable_json_path(issuable)}" } }
......
- content_for :page_specific_javascripts do - content_for :page_specific_javascripts do
= page_specific_javascript_tag('lib/ace.js') = page_specific_javascript_tag('lib/ace.js')
= page_specific_javascript_bundle_tag('snippet') = webpack_bundle_tag('snippet')
.snippet-form-holder .snippet-form-holder
= form_for @snippet, url: url, html: { class: "form-horizontal snippet-form js-requires-input js-quick-submit common-note-form" } do |f| = form_for @snippet, url: url, html: { class: "form-horizontal snippet-form js-requires-input js-quick-submit common-note-form" } do |f|
......
...@@ -23,27 +23,25 @@ class ProcessCommitWorker ...@@ -23,27 +23,25 @@ class ProcessCommitWorker
return unless user return unless user
commit = build_commit(project, commit_hash) commit = build_commit(project, commit_hash)
author = commit.author || user author = commit.author || user
process_commit_message(project, commit, user, author, default) process_commit_message(project, commit, user, author, default)
update_issue_metrics(commit, author) update_issue_metrics(commit, author)
end end
def process_commit_message(project, commit, user, author, default = false) def process_commit_message(project, commit, user, author, default = false)
closed_issues = default ? commit.closes_issues(user) : [] # this is a GitLab generated commit message, ignore it.
return if commit.merged_merge_request?(user)
unless closed_issues.empty? closed_issues = default ? commit.closes_issues(user) : []
close_issues(project, user, author, commit, closed_issues)
end
close_issues(project, user, author, commit, closed_issues) if closed_issues.any?
commit.create_cross_references!(author, closed_issues) commit.create_cross_references!(author, closed_issues)
end end
def close_issues(project, user, author, commit, issues) def close_issues(project, user, author, commit, issues)
# We don't want to run permission related queries for every single issue, # We don't want to run permission related queries for every single issue,
# therefor we use IssueCollection here and skip the authorization check in # therefore we use IssueCollection here and skip the authorization check in
# Issues::CloseService#execute. # Issues::CloseService#execute.
IssueCollection.new(issues).updatable_by_user(user).each do |issue| IssueCollection.new(issues).updatable_by_user(user).each do |issue|
Issues::CloseService.new(project, author) Issues::CloseService.new(project, author)
......
---
title: Update issue closing pattern to allow variations in punctuation
merge_request: 17198
author: Vicky Chijwani
type: changed
---
title: Fix duplicate system notes when merging a merge request.
merge_request: 17035
author:
type: fixed
---
title: Sanitize extra blank spaces used when uploading a SSH key
merge_request: 40552
author:
type: fixed
---
title: Remember assignee when moving an issue
merge_request:
author:
type: fixed
---
title: Fix long list of recipients on group request membership email
merge_request: 17121
author: Jacopo Beschi @jacopo-beschi
type: fixed
---
title: Fix monaco editor features which were incompatable with GitLab CDN settings
merge_request: 17021
author:
type: fixed
---
title: "[GitHub Import] Create an empty wiki if wiki import failed"
merge_request:
author:
type: fixed
---
title: Don't cache a nil repository root ref to prevent caching issues
merge_request:
author:
type: fixed
---
title: Change SQL for expired artifacts to use new ci_job_artifacts.expire_at
merge_request: 16578
author:
type: performance
---
title: Show loading button inline in refresh button in MR widget
merge_request:
author:
type: fixed
---
title: Increase feature flag cache TTL to one hour
merge_request:
author:
type: performance
---
title: Fix single digit value clipping for stacked progress bar
merge_request: 17217
author:
type: fixed
---
title: Fix Error 500 when viewing a commit with a GPG signature in Geo
merge_request:
author:
type: fixed
---
title: Fix squash not working when diff contained non-ASCII data
merge_request:
author:
type: fixed
---
title: Don't attempt to update user tracked fields if database is in read-only
merge_request:
author:
type: fixed
...@@ -262,7 +262,7 @@ Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled']. ...@@ -262,7 +262,7 @@ Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].
Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil? Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil?
Settings.gitlab['restricted_visibility_levels'] = Settings.__send__(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], []) Settings.gitlab['restricted_visibility_levels'] = Settings.__send__(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], [])
Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil? Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)|[Ii]mplement(?:s|ed|ing)?)(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?)|([A-Z][A-Z0-9_]+-\d+))+)' if Settings.gitlab['issue_closing_pattern'].nil? Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)|[Ii]mplement(?:s|ed|ing)?)(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?: *,? +and +| *, *)?)|([A-Z][A-Z0-9_]+-\d+))+)' if Settings.gitlab['issue_closing_pattern'].nil?
Settings.gitlab['default_projects_features'] ||= {} Settings.gitlab['default_projects_features'] ||= {}
Settings.gitlab['webhook_timeout'] ||= 10 Settings.gitlab['webhook_timeout'] ||= 10
Settings.gitlab['max_attachment_size'] ||= 10 Settings.gitlab['max_attachment_size'] ||= 10
......
...@@ -8,7 +8,7 @@ Flipper.configure do |config| ...@@ -8,7 +8,7 @@ Flipper.configure do |config|
cached_adapter = Flipper::Adapters::ActiveSupportCacheStore.new( cached_adapter = Flipper::Adapters::ActiveSupportCacheStore.new(
adapter, adapter,
Rails.cache, Rails.cache,
expires_in: 10.seconds) expires_in: 1.hour)
Flipper.new(cached_adapter) Flipper.new(cached_adapter)
end end
......
...@@ -27,11 +27,11 @@ var pageEntries = glob.sync('pages/**/index.js', { cwd: path.join(ROOT_PATH, 'ap ...@@ -27,11 +27,11 @@ var pageEntries = glob.sync('pages/**/index.js', { cwd: path.join(ROOT_PATH, 'ap
// filter out entries currently imported dynamically in dispatcher.js // filter out entries currently imported dynamically in dispatcher.js
var dispatcher = fs.readFileSync(path.join(ROOT_PATH, 'app/assets/javascripts/dispatcher.js')).toString(); var dispatcher = fs.readFileSync(path.join(ROOT_PATH, 'app/assets/javascripts/dispatcher.js')).toString();
var dispatcherChunks = dispatcher.match(/(?!import\('.\/)pages\/[^']+/g); var dispatcherChunks = dispatcher.match(/(?!import\(')\.\/pages\/[^']+/g);
pageEntries.forEach(( path ) => { pageEntries.forEach(( path ) => {
let chunkPath = path.replace(/\/index\.js$/, ''); let chunkPath = path.replace(/\/index\.js$/, '');
if (!dispatcherChunks.includes(chunkPath)) { if (!dispatcherChunks.includes('./' + chunkPath)) {
let chunkName = chunkPath.replace(/\//g, '.'); let chunkName = chunkPath.replace(/\//g, '.');
autoEntries[chunkName] = './' + path; autoEntries[chunkName] = './' + path;
} }
...@@ -61,8 +61,6 @@ var config = { ...@@ -61,8 +61,6 @@ var config = {
environments: './environments/environments_bundle.js', environments: './environments/environments_bundle.js',
environments_folder: './environments/folder/environments_folder_bundle.js', environments_folder: './environments/folder/environments_folder_bundle.js',
filtered_search: './filtered_search/filtered_search_bundle.js', filtered_search: './filtered_search/filtered_search_bundle.js',
graphs: './graphs/graphs_bundle.js',
graphs_charts: './graphs/graphs_charts.js',
graphs_show: './graphs/graphs_show.js', graphs_show: './graphs/graphs_show.js',
help: './help/help.js', help: './help/help.js',
how_to_merge: './how_to_merge.js', how_to_merge: './how_to_merge.js',
...@@ -282,7 +280,6 @@ var config = { ...@@ -282,7 +280,6 @@ var config = {
new webpack.optimize.CommonsChunkPlugin({ new webpack.optimize.CommonsChunkPlugin({
name: 'common_d3', name: 'common_d3',
chunks: [ chunks: [
'graphs',
'graphs_show', 'graphs_show',
'monitoring', 'monitoring',
'users', 'users',
......
# How to configure LDAP with GitLab CE ---
author: Chris Wilson
author_gitlab: MrChrisW
level: intermediary
article_type: admin guide
date: 2017-05-03
---
> **[Article Type](../../../development/writing_documentation.html#types-of-technical-articles):** admin guide || # How to configure LDAP with GitLab CE
> **Level:** intermediary ||
> **Author:** [Chris Wilson](https://gitlab.com/MrChrisW) ||
> **Publication date:** 2017-05-03
## Introduction ## Introduction
......
--- ---
redirect_from: 'https://docs.gitlab.com/ee/articles/artifactory_and_gitlab/index.html' redirect_from: 'https://docs.gitlab.com/ee/articles/artifactory_and_gitlab/index.html'
author: Fabio Busatto
author_gitlab: bikebilly
level: intermediary
article_type: tutorial
date: 2017-08-15
--- ---
# How to deploy Maven projects to Artifactory with GitLab CI/CD # How to deploy Maven projects to Artifactory with GitLab CI/CD
> **[Article Type](../../../development/writing_documentation.md#types-of-technical-articles):** tutorial ||
> **Level:** intermediary ||
> **Author:** [Fabio Busatto](https://gitlab.com/bikebilly) ||
> **Publication date:** 2017-08-15
## Introduction ## Introduction
In this article, we will show how you can leverage the power of [GitLab CI/CD](https://about.gitlab.com/features/gitlab-ci-cd/) In this article, we will show how you can leverage the power of [GitLab CI/CD](https://about.gitlab.com/features/gitlab-ci-cd/)
......
--- ---
redirect_from: 'https://docs.gitlab.com/ee/articles/laravel_with_gitlab_and_envoy/index.html' redirect_from: 'https://docs.gitlab.com/ee/articles/laravel_with_gitlab_and_envoy/index.html'
author: Mehran Rasulian
author_gitlab: mehranrasulian
level: intermediary
article_type: tutorial
date: 2017-08-31
--- ---
# Test and deploy Laravel applications with GitLab CI/CD and Envoy # Test and deploy Laravel applications with GitLab CI/CD and Envoy
> **[Article Type](../../../development/writing_documentation.md#types-of-technical-articles):** tutorial ||
> **Level:** intermediary ||
> **Author:** [Mehran Rasulian](https://gitlab.com/mehranrasulian) ||
> **Publication date:** 2017-08-31
## Introduction ## Introduction
GitLab features our applications with Continuous Integration, and it is possible to easily deploy the new code changes to the production server whenever we want. GitLab features our applications with Continuous Integration, and it is possible to easily deploy the new code changes to the production server whenever we want.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment