Commit 4bdc02e5 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'master' into 'ee-gitaly-commit-patch'

# Conflicts:
#   Gemfile
#   Gemfile.lock
parents 0c135fb2 a240dbab
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.7-phantomjs-2.1-node-7.1-postgresql-9.6" image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.13-phantomjs-2.1-node-7.1-postgresql-9.6"
.default-cache: &default-cache .default-cache: &default-cache
key: "ruby-233-with-yarn" key: "ruby-233-with-yarn"
...@@ -266,7 +266,7 @@ setup-test-env: ...@@ -266,7 +266,7 @@ setup-test-env:
<<: *default-cache <<: *default-cache
script: script:
- node --version - node --version
- yarn install --pure-lockfile --cache-folder .yarn-cache - yarn install --frozen-lockfile --cache-folder .yarn-cache
- bundle exec rake gettext:po_to_json - bundle exec rake gettext:po_to_json
- bundle exec rake gitlab:assets:compile - bundle exec rake gitlab:assets:compile
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init' - bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
...@@ -461,7 +461,6 @@ db:rollback-mysql: ...@@ -461,7 +461,6 @@ db:rollback-mysql:
variables: variables:
SIZE: "1" SIZE: "1"
SETUP_DB: "false" SETUP_DB: "false"
RAILS_ENV: "development"
script: script:
- git clone https://gitlab.com/gitlab-org/gitlab-test.git - git clone https://gitlab.com/gitlab-org/gitlab-test.git
/home/git/repositories/gitlab-org/gitlab-test.git /home/git/repositories/gitlab-org/gitlab-test.git
...@@ -496,7 +495,7 @@ gitlab:assets:compile: ...@@ -496,7 +495,7 @@ gitlab:assets:compile:
WEBPACK_REPORT: "true" WEBPACK_REPORT: "true"
NO_COMPRESSION: "true" NO_COMPRESSION: "true"
script: script:
- yarn install --pure-lockfile --production --cache-folder .yarn-cache - yarn install --frozen-lockfile --production --cache-folder .yarn-cache
- bundle exec rake gettext:po_to_json - bundle exec rake gettext:po_to_json
- bundle exec rake gitlab:assets:compile - bundle exec rake gitlab:assets:compile
artifacts: artifacts:
...@@ -510,7 +509,7 @@ karma: ...@@ -510,7 +509,7 @@ karma:
<<: *dedicated-runner <<: *dedicated-runner
<<: *except-docs <<: *except-docs
<<: *pull-cache <<: *pull-cache
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.7-chrome-59.0-node-7.1-postgresql-9.6" image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.13-chrome-60.0-node-7.1-postgresql-9.6"
stage: test stage: test
variables: variables:
BABEL_ENV: "coverage" BABEL_ENV: "coverage"
......
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
## 9.5.0 (2017-08-22)
- [FIXED] Fix Copy to Clipboard for SSH Public Key on Pull Repository settings. !2692
- [FIXED] Enable mirror repository button.
- [FIXED] Create system notes only if issue was successfully related.
- [FIXED] Fix issue boards focus button not being visible to guest users.
- Namespace license checks Audit Events & Admin Audit Log. !2326
- Namespace license checks for Repository Mirrors. !2328
- Automatically link kerberos users to LDAP people. !2405
- Implement SSH public-key support for repository mirroring. !2423
- Shows project names for commits in elasticsearch global search. !2434
- Add admin application setting to allow group owners to manage LDAP. !2529
- Geo - Selectively choose which namespaces to replicate in DR. !2533
- Support variables on Trigger API for Cross-project pipeline. !2557
- Allow excluding sidekiq queues from execution in sidekiq-cluster. !2571
- Ensure artifacts are moved locally within the filesystem to prevent timeouts. !2572
- Audit failed login events. !2587
- Spread load across all nodes in an elasticsearch cluster. !2625
- Improves handling of stuck imports. !2628
- Improves handling of the mirror threshold. !2671
- Allow artifacts access with job_token parameter or CI_JOB_TOKEN header.
- Add initial Groups/Billing and Profile/Billing routing and template.
- Fix rebase from fork when upstream has protected branches.
- Present Related Issues add badge only when user can manage related issues (previously when user could edit issue).
- clean up merge request widget UI.
- Make contextual sidebar collapsible.
- Fix accessing individual files on Object Storage.
- Fix rebase button when merge request is created from a fork.
- Skip oAuth authorization for trusted applications.
## 9.4.5 (2017-08-14) ## 9.4.5 (2017-08-14)
- Ensure artifacts are moved locally within the filesystem to prevent timeouts. !2572 - Ensure artifacts are moved locally within the filesystem to prevent timeouts. !2572
......
This diff is collapsed.
...@@ -16,7 +16,7 @@ gem 'mysql2', '~> 0.4.5', group: :mysql ...@@ -16,7 +16,7 @@ gem 'mysql2', '~> 0.4.5', group: :mysql
gem 'pg', '~> 0.18.2', group: :postgres gem 'pg', '~> 0.18.2', group: :postgres
gem 'rugged', '~> 0.26.0' gem 'rugged', '~> 0.26.0'
gem 'grape-route-helpers', '~> 2.0.0' gem 'grape-route-helpers', '~> 2.1.0'
gem 'faraday', '~> 0.12' gem 'faraday', '~> 0.12'
...@@ -79,7 +79,7 @@ gem 'gollum-rugged_adapter', '~> 0.4.4', require: false ...@@ -79,7 +79,7 @@ gem 'gollum-rugged_adapter', '~> 0.4.4', require: false
gem 'github-linguist', '~> 4.7.0', require: 'linguist' gem 'github-linguist', '~> 4.7.0', require: 'linguist'
# API # API
gem 'grape', '~> 0.19.2' gem 'grape', '~> 1.0'
gem 'grape-entity', '~> 0.6.0' gem 'grape-entity', '~> 0.6.0'
gem 'rack-cors', '~> 0.4.0', require: 'rack/cors' gem 'rack-cors', '~> 0.4.0', require: 'rack/cors'
...@@ -162,7 +162,7 @@ gem 'acts-as-taggable-on', '~> 4.0' ...@@ -162,7 +162,7 @@ gem 'acts-as-taggable-on', '~> 4.0'
gem 'sidekiq', '~> 5.0' gem 'sidekiq', '~> 5.0'
gem 'sidekiq-cron', '~> 0.6.0' gem 'sidekiq-cron', '~> 0.6.0'
gem 'redis-namespace', '~> 1.5.2' gem 'redis-namespace', '~> 1.5.2'
gem 'sidekiq-limit_fetch', '~> 3.4' gem 'sidekiq-limit_fetch', '~> 3.4', require: false
# Cron Parser # Cron Parser
gem 'rufus-scheduler', '~> 3.4' gem 'rufus-scheduler', '~> 3.4'
...@@ -240,7 +240,7 @@ gem 'ace-rails-ap', '~> 4.1.0' ...@@ -240,7 +240,7 @@ gem 'ace-rails-ap', '~> 4.1.0'
gem 'mousetrap-rails', '~> 1.4.6' gem 'mousetrap-rails', '~> 1.4.6'
# Detect and convert string character encoding # Detect and convert string character encoding
gem 'charlock_holmes', '~> 0.7.3' gem 'charlock_holmes', '~> 0.7.5'
# Faster JSON # Faster JSON
gem 'oj', '~> 2.17.4' gem 'oj', '~> 2.17.4'
...@@ -299,7 +299,7 @@ group :metrics do ...@@ -299,7 +299,7 @@ group :metrics do
gem 'influxdb', '~> 0.2', require: false gem 'influxdb', '~> 0.2', require: false
# Prometheus # Prometheus
gem 'prometheus-client-mmap', '~>0.7.0.beta11' gem 'prometheus-client-mmap', '~>0.7.0.beta12'
gem 'raindrops', '~> 0.18' gem 'raindrops', '~> 0.18'
end end
......
...@@ -123,7 +123,7 @@ GEM ...@@ -123,7 +123,7 @@ GEM
activesupport (>= 4.0.0) activesupport (>= 4.0.0)
mime-types (>= 1.16) mime-types (>= 1.16)
cause (0.1) cause (0.1)
charlock_holmes (0.7.3) charlock_holmes (0.7.5)
chronic (0.10.2) chronic (0.10.2)
chronic_duration (0.10.6) chronic_duration (0.10.6)
numerizer (~> 0.1.1) numerizer (~> 0.1.1)
...@@ -365,12 +365,9 @@ GEM ...@@ -365,12 +365,9 @@ GEM
signet (~> 0.7) signet (~> 0.7)
gpgme (2.0.13) gpgme (2.0.13)
mini_portile2 (~> 2.1) mini_portile2 (~> 2.1)
grape (0.19.2) grape (1.0.0)
activesupport activesupport
builder builder
hashie (>= 2.1.0)
multi_json (>= 1.3.2)
multi_xml (>= 0.5.2)
mustermann-grape (~> 1.0.0) mustermann-grape (~> 1.0.0)
rack (>= 1.3.0) rack (>= 1.3.0)
rack-accept rack-accept
...@@ -378,11 +375,11 @@ GEM ...@@ -378,11 +375,11 @@ GEM
grape-entity (0.6.0) grape-entity (0.6.0)
activesupport activesupport
multi_json (>= 1.3.2) multi_json (>= 1.3.2)
grape-route-helpers (2.0.0) grape-route-helpers (2.1.0)
activesupport activesupport
grape (~> 0.16, >= 0.16.0) grape (>= 0.16.0)
rake rake
grpc (1.4.0) grpc (1.4.5)
google-protobuf (~> 3.1) google-protobuf (~> 3.1)
googleauth (~> 0.5.1) googleauth (~> 0.5.1)
gssapi (1.2.0) gssapi (1.2.0)
...@@ -400,7 +397,7 @@ GEM ...@@ -400,7 +397,7 @@ GEM
thor thor
tilt tilt
hashdiff (0.3.4) hashdiff (0.3.4)
hashie (3.5.5) hashie (3.5.6)
hashie-forbidden_attributes (0.1.1) hashie-forbidden_attributes (0.1.1)
hashie (>= 3.0) hashie (>= 3.0)
health_check (2.6.0) health_check (2.6.0)
...@@ -651,7 +648,7 @@ GEM ...@@ -651,7 +648,7 @@ GEM
parser parser
unparser unparser
procto (0.0.3) procto (0.0.3)
prometheus-client-mmap (0.7.0.beta11) prometheus-client-mmap (0.7.0.beta12)
mmap2 (~> 2.2, >= 2.2.7) mmap2 (~> 2.2, >= 2.2.7)
pry (0.10.4) pry (0.10.4)
coderay (~> 1.1.0) coderay (~> 1.1.0)
...@@ -754,7 +751,7 @@ GEM ...@@ -754,7 +751,7 @@ GEM
retriable (1.4.1) retriable (1.4.1)
rinku (2.0.0) rinku (2.0.0)
rotp (2.1.2) rotp (2.1.2)
rouge (2.1.0) rouge (2.2.0)
rqrcode (0.7.0) rqrcode (0.7.0)
chunky_png chunky_png
rqrcode-rails3 (0.1.7) rqrcode-rails3 (0.1.7)
...@@ -1014,7 +1011,7 @@ DEPENDENCIES ...@@ -1014,7 +1011,7 @@ DEPENDENCIES
capybara (~> 2.6.2) capybara (~> 2.6.2)
capybara-screenshot (~> 1.0.0) capybara-screenshot (~> 1.0.0)
carrierwave (~> 1.1) carrierwave (~> 1.1)
charlock_holmes (~> 0.7.3) charlock_holmes (~> 0.7.5)
chronic (~> 0.10.2) chronic (~> 0.10.2)
chronic_duration (~> 0.10.6) chronic_duration (~> 0.10.6)
concurrent-ruby (~> 1.0.5) concurrent-ruby (~> 1.0.5)
...@@ -1068,9 +1065,9 @@ DEPENDENCIES ...@@ -1068,9 +1065,9 @@ DEPENDENCIES
gon (~> 6.1.0) gon (~> 6.1.0)
google-api-client (~> 0.8.6) google-api-client (~> 0.8.6)
gpgme gpgme
grape (~> 0.19.2) grape (~> 1.0)
grape-entity (~> 0.6.0) grape-entity (~> 0.6.0)
grape-route-helpers (~> 2.0.0) grape-route-helpers (~> 2.1.0)
gssapi gssapi
haml_lint (~> 0.26.0) haml_lint (~> 0.26.0)
hamlit (~> 2.6.1) hamlit (~> 2.6.1)
...@@ -1135,7 +1132,7 @@ DEPENDENCIES ...@@ -1135,7 +1132,7 @@ DEPENDENCIES
pg (~> 0.18.2) pg (~> 0.18.2)
poltergeist (~> 1.9.0) poltergeist (~> 1.9.0)
premailer-rails (~> 1.9.7) premailer-rails (~> 1.9.7)
prometheus-client-mmap (~> 0.7.0.beta11) prometheus-client-mmap (~> 0.7.0.beta12)
pry-byebug (~> 3.4.1) pry-byebug (~> 3.4.1)
pry-rails (~> 0.3.4) pry-rails (~> 0.3.4)
rack-attack (~> 4.4.1) rack-attack (~> 4.4.1)
......
...@@ -141,18 +141,22 @@ the stable branch are: ...@@ -141,18 +141,22 @@ the stable branch are:
* Fixes for security issues * Fixes for security issues
* New or updated translations (as long as they do not touch application code) * New or updated translations (as long as they do not touch application code)
Any merge requests cherry-picked into the stable branch for a previous release
will also be picked into the latest stable branch. These fixes will be shipped
in the next RC for that release if it is before the 22nd. If the fixes are are
completed on or after the 22nd, they will be shipped in a patch for that
release.
During the feature freeze all merge requests that are meant to go into the upcoming During the feature freeze all merge requests that are meant to go into the upcoming
release should have the correct milestone assigned _and_ have the label release should have the correct milestone assigned _and_ have the label
~"Pick into Stable" set, so that release managers can find and pick them. ~"Pick into Stable" set, so that release managers can find and pick them.
Merge requests without a milestone and this label will Merge requests without a milestone and this label will
not be merged into any stable branches. not be merged into any stable branches.
Fixes marked like this will be shipped in the next RC for that release. Once
the final RC has been prepared ready for release on the 22nd, further fixes
marked ~"Pick into Stable" will go into a patch for that release.
If a merge request is to be picked into more than one release it will also need
the ~"Pick into Backports" label set to remind the release manager to change
the milestone after cherry-picking. As before, it should still have the
~"Pick into Stable" label and the milestone of the highest release it will be
picked into.
### Asking for an exception ### Asking for an exception
If you think a merge request should go into an RC or patch even though it does not meet these requirements, If you think a merge request should go into an RC or patch even though it does not meet these requirements,
......
...@@ -97,7 +97,7 @@ gl.issueBoards.IssueCardInner = Vue.extend({ ...@@ -97,7 +97,7 @@ gl.issueBoards.IssueCardInner = Vue.extend({
return `Avatar for ${assignee.name}`; return `Avatar for ${assignee.name}`;
}, },
showLabel(label) { showLabel(label) {
if (!this.list || !label) return true; if (!label.id) return false;
return true; return true;
}, },
filterByLabel(label, e) { filterByLabel(label, e) {
......
...@@ -17,7 +17,7 @@ window.CommitsList = (function() { ...@@ -17,7 +17,7 @@ window.CommitsList = (function() {
} }
}); });
Pager.init(limit, false, false, this.processCommits); Pager.init(parseInt(limit, 10), false, false, this.processCommits);
this.content = $("#commits-list"); this.content = $("#commits-list");
this.searchField = $("#commits-search"); this.searchField = $("#commits-search");
......
...@@ -451,7 +451,7 @@ import initGroupAnalytics from './init_group_analytics'; ...@@ -451,7 +451,7 @@ import initGroupAnalytics from './init_group_analytics';
case 'projects:tree:show': case 'projects:tree:show':
shortcut_handler = new ShortcutsNavigation(); shortcut_handler = new ShortcutsNavigation();
if (UserFeatureHelper.isNewRepo()) break; if (UserFeatureHelper.isNewRepoEnabled()) break;
new TreeView(); new TreeView();
new BlobViewer(); new BlobViewer();
...@@ -479,7 +479,7 @@ import initGroupAnalytics from './init_group_analytics'; ...@@ -479,7 +479,7 @@ import initGroupAnalytics from './init_group_analytics';
shortcut_handler = true; shortcut_handler = true;
break; break;
case 'projects:blob:show': case 'projects:blob:show':
if (UserFeatureHelper.isNewRepo()) break; if (UserFeatureHelper.isNewRepoEnabled()) break;
new BlobViewer(); new BlobViewer();
initBlob(); initBlob();
break; break;
......
...@@ -15,6 +15,10 @@ export const setOpenMenu = (menu = null) => { currentOpenMenu = menu; }; ...@@ -15,6 +15,10 @@ export const setOpenMenu = (menu = null) => { currentOpenMenu = menu; };
export const slope = (a, b) => (b.y - a.y) / (b.x - a.x); export const slope = (a, b) => (b.y - a.y) / (b.x - a.x);
let headerHeight = 50;
export const getHeaderHeight = () => headerHeight;
export const canShowActiveSubItems = (el) => { export const canShowActiveSubItems = (el) => {
const isHiddenByMedia = bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md'; const isHiddenByMedia = bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md';
...@@ -74,7 +78,7 @@ export const moveSubItemsToPosition = (el, subItems) => { ...@@ -74,7 +78,7 @@ export const moveSubItemsToPosition = (el, subItems) => {
const isAbove = top < boundingRect.top; const isAbove = top < boundingRect.top;
subItems.classList.add('fly-out-list'); subItems.classList.add('fly-out-list');
subItems.style.transform = `translate3d(0, ${Math.floor(top)}px, 0)`; // eslint-disable-line no-param-reassign subItems.style.transform = `translate3d(0, ${Math.floor(top) - headerHeight}px, 0)`; // eslint-disable-line no-param-reassign
const subItemsRect = subItems.getBoundingClientRect(); const subItemsRect = subItems.getBoundingClientRect();
...@@ -153,6 +157,8 @@ export default () => { ...@@ -153,6 +157,8 @@ export default () => {
}, getHideSubItemsInterval()); }, getHideSubItemsInterval());
}); });
headerHeight = document.querySelector('.nav-sidebar').offsetTop;
items.forEach((el) => { items.forEach((el) => {
const subItems = el.querySelector('.sidebar-sub-level-items'); const subItems = el.querySelector('.sidebar-sub-level-items');
......
...@@ -111,8 +111,7 @@ window.GroupsSelect = (function() { ...@@ -111,8 +111,7 @@ window.GroupsSelect = (function() {
}; };
GroupsSelect.prototype.forceOverflow = function (e) { GroupsSelect.prototype.forceOverflow = function (e) {
const itemHeight = this.dropdown.querySelector('.select2-result:first-child').clientHeight; this.dropdown.style.height = `${Math.floor(this.dropdown.scrollHeight)}px`;
this.dropdown.style.height = `${Math.floor(this.dropdown.scrollHeight - (itemHeight * 0.9))}px`;
}; };
GroupsSelect.PER_PAGE = 20; GroupsSelect.PER_PAGE = 20;
......
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
function isNewRepo() { export default {
return Cookies.get('new_repo') === 'true'; isNewRepoEnabled() {
} return Cookies.get('new_repo') === 'true';
},
const UserFeatureHelper = {
isNewRepo,
}; };
export default UserFeatureHelper;
...@@ -378,15 +378,15 @@ ...@@ -378,15 +378,15 @@
w.gl.utils.backOff = (fn, timeout = 60000) => { w.gl.utils.backOff = (fn, timeout = 60000) => {
const maxInterval = 32000; const maxInterval = 32000;
let nextInterval = 2000; let nextInterval = 2000;
let timeElapsed = 0;
const startTime = Date.now();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const stop = arg => ((arg instanceof Error) ? reject(arg) : resolve(arg)); const stop = arg => ((arg instanceof Error) ? reject(arg) : resolve(arg));
const next = () => { const next = () => {
if (Date.now() - startTime < timeout) { if (timeElapsed < timeout) {
setTimeout(fn.bind(null, next, stop), nextInterval); setTimeout(() => fn(next, stop), nextInterval);
timeElapsed += nextInterval;
nextInterval = Math.min(nextInterval + nextInterval, maxInterval); nextInterval = Math.min(nextInterval + nextInterval, maxInterval);
} else { } else {
reject(new Error('BACKOFF_TIMEOUT')); reject(new Error('BACKOFF_TIMEOUT'));
......
export const isSticky = (el, scrollY, stickyTop) => { export const isSticky = (el, scrollY, stickyTop) => {
const top = el.offsetTop - scrollY; const top = el.offsetTop - scrollY;
if (top === stickyTop) { if (top <= stickyTop) {
el.classList.add('is-stuck'); el.classList.add('is-stuck');
} else { } else {
el.classList.remove('is-stuck'); el.classList.remove('is-stuck');
......
...@@ -43,10 +43,12 @@ export default class NewNavSidebar { ...@@ -43,10 +43,12 @@ export default class NewNavSidebar {
} }
toggleCollapsedSidebar(collapsed) { toggleCollapsedSidebar(collapsed) {
this.$sidebar.toggleClass('sidebar-icons-only', collapsed); const breakpoint = bp.getBreakpointSize();
if (this.$sidebar.length) { if (this.$sidebar.length) {
this.$sidebar.toggleClass('sidebar-icons-only', collapsed);
this.$page.toggleClass('page-with-new-sidebar', !collapsed); this.$page.toggleClass('page-with-new-sidebar', !collapsed);
this.$page.toggleClass('page-with-icon-sidebar', collapsed); this.$page.toggleClass('page-with-icon-sidebar', breakpoint === 'sm' ? true : collapsed);
} }
NewNavSidebar.setCollapsedCookie(collapsed); NewNavSidebar.setCollapsedCookie(collapsed);
} }
......
...@@ -4,10 +4,10 @@ export default class ProjectSelectComboButton { ...@@ -4,10 +4,10 @@ export default class ProjectSelectComboButton {
constructor(select) { constructor(select) {
this.projectSelectInput = $(select); this.projectSelectInput = $(select);
this.newItemBtn = $('.new-project-item-link'); this.newItemBtn = $('.new-project-item-link');
this.newItemBtnBaseText = this.newItemBtn.data('label'); this.resourceType = this.newItemBtn.data('type');
this.itemType = this.deriveItemTypeFromLabel(); this.resourceLabel = this.newItemBtn.data('label');
this.formattedText = this.deriveTextVariants();
this.groupId = this.projectSelectInput.data('groupId'); this.groupId = this.projectSelectInput.data('groupId');
this.bindEvents(); this.bindEvents();
this.initLocalStorage(); this.initLocalStorage();
} }
...@@ -23,9 +23,7 @@ export default class ProjectSelectComboButton { ...@@ -23,9 +23,7 @@ export default class ProjectSelectComboButton {
const localStorageIsSafe = AccessorUtilities.isLocalStorageAccessSafe(); const localStorageIsSafe = AccessorUtilities.isLocalStorageAccessSafe();
if (localStorageIsSafe) { if (localStorageIsSafe) {
const itemTypeKebabed = this.newItemBtnBaseText.toLowerCase().split(' ').join('-'); this.localStorageKey = ['group', this.groupId, this.formattedText.localStorageItemType, 'recent-project'].join('-');
this.localStorageKey = ['group', this.groupId, itemTypeKebabed, 'recent-project'].join('-');
this.setBtnTextFromLocalStorage(); this.setBtnTextFromLocalStorage();
} }
} }
...@@ -57,19 +55,14 @@ export default class ProjectSelectComboButton { ...@@ -57,19 +55,14 @@ export default class ProjectSelectComboButton {
setNewItemBtnAttributes(project) { setNewItemBtnAttributes(project) {
if (project) { if (project) {
this.newItemBtn.attr('href', project.url); this.newItemBtn.attr('href', project.url);
this.newItemBtn.text(`${this.newItemBtnBaseText} in ${project.name}`); this.newItemBtn.text(`${this.formattedText.defaultTextPrefix} in ${project.name}`);
this.newItemBtn.enable(); this.newItemBtn.enable();
} else { } else {
this.newItemBtn.text(`Select project to create ${this.itemType}`); this.newItemBtn.text(`Select project to create ${this.formattedText.presetTextSuffix}`);
this.newItemBtn.disable(); this.newItemBtn.disable();
} }
} }
deriveItemTypeFromLabel() {
// label is either 'New issue' or 'New merge request'
return this.newItemBtnBaseText.split(' ').slice(1).join(' ');
}
getProjectFromLocalStorage() { getProjectFromLocalStorage() {
const projectString = localStorage.getItem(this.localStorageKey); const projectString = localStorage.getItem(this.localStorageKey);
...@@ -81,5 +74,19 @@ export default class ProjectSelectComboButton { ...@@ -81,5 +74,19 @@ export default class ProjectSelectComboButton {
localStorage.setItem(this.localStorageKey, projectString); localStorage.setItem(this.localStorageKey, projectString);
} }
deriveTextVariants() {
const defaultTextPrefix = this.resourceLabel;
// the trailing slice call depluralizes each of these strings (e.g. new-issues -> new-issue)
const localStorageItemType = `new-${this.resourceType.split('_').join('-').slice(0, -1)}`;
const presetTextSuffix = this.resourceType.split('_').join(' ').slice(0, -1);
return {
localStorageItemType, // new-issue / new-merge-request
defaultTextPrefix, // New issue / New merge request
presetTextSuffix, // issue / merge request
};
}
} }
...@@ -74,7 +74,8 @@ export default { ...@@ -74,7 +74,8 @@ export default {
<tbody> <tbody>
<repo-file-options <repo-file-options
:is-mini="isMini" :is-mini="isMini"
:project-name="projectName"/> :project-name="projectName"
/>
<repo-previous-directory <repo-previous-directory
v-if="isRoot" v-if="isRoot"
:prev-url="prevURL" :prev-url="prevURL"
...@@ -84,7 +85,8 @@ export default { ...@@ -84,7 +85,8 @@ export default {
:key="n" :key="n"
:loading="loading" :loading="loading"
:has-files="!!files.length" :has-files="!!files.length"
:is-mini="isMini"/> :is-mini="isMini"
/>
<repo-file <repo-file
v-for="file in files" v-for="file in files"
:key="file.id" :key="file.id"
...@@ -93,7 +95,8 @@ export default { ...@@ -93,7 +95,8 @@ export default {
@linkclicked="fileClicked(file)" @linkclicked="fileClicked(file)"
:is-tree="isTree" :is-tree="isTree"
:has-files="!!files.length" :has-files="!!files.length"
:active-file="activeFile"/> :active-file="activeFile"
/>
</tbody> </tbody>
</table> </table>
</div> </div>
......
...@@ -71,7 +71,7 @@ export default { ...@@ -71,7 +71,7 @@ export default {
/> />
<div v-if="!isConfidential" class="no-value confidential-value"> <div v-if="!isConfidential" class="no-value confidential-value">
<i class="fa fa-eye is-not-confidential"></i> <i class="fa fa-eye is-not-confidential"></i>
None Not confidential
</div> </div>
<div v-else class="value confidential-value hide-collapsed"> <div v-else class="value confidential-value hide-collapsed">
<i aria-hidden="true" data-hidden="true" class="fa fa-eye-slash is-confidential"></i> <i aria-hidden="true" data-hidden="true" class="fa fa-eye-slash is-confidential"></i>
......
...@@ -283,15 +283,14 @@ export default { ...@@ -283,15 +283,14 @@ export default {
<span v-if="mr.ffOnlyEnabled"> <span v-if="mr.ffOnlyEnabled">
Fast-forward merge without a merge commit Fast-forward merge without a merge commit
</span> </span>
<span v-else> <button
<button v-else
@click="toggleCommitMessageEditor" @click="toggleCommitMessageEditor"
:disabled="isMergeButtonDisabled" :disabled="isMergeButtonDisabled"
class="btn btn-default btn-xs" class="btn btn-default btn-xs"
type="button"> type="button">
Modify commit message Modify commit message
</button> </button>
</span>
</template> </template>
<template v-else> <template v-else>
<span class="bold"> <span class="bold">
......
...@@ -51,9 +51,7 @@ export default { ...@@ -51,9 +51,7 @@ export default {
class="modal popup-dialog" class="modal popup-dialog"
role="dialog" role="dialog"
tabindex="-1"> tabindex="-1">
<div <div class="modal-dialog" role="document">
class="modal-dialog"
role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" <button type="button"
...@@ -74,8 +72,7 @@ export default { ...@@ -74,8 +72,7 @@ export default {
@click="emitSubmit(false)"> @click="emitSubmit(false)">
{{closeButtonLabel}} {{closeButtonLabel}}
</button> </button>
<button <button type="button"
type="button"
class="btn" class="btn"
:class="btnKindClass" :class="btnKindClass"
@click="emitSubmit(true)"> @click="emitSubmit(true)">
......
...@@ -752,11 +752,16 @@ ...@@ -752,11 +752,16 @@
border-radius: 0; border-radius: 0;
padding: 8px 16px; padding: 8px 16px;
// make sure the text color is not overriden
&.text-danger {
@extend .text-danger;
}
&.is-focused, &.is-focused,
&:hover, &:hover,
&:active, &:active,
&:focus { &:focus {
background-color: $gray-darker; background-color: $dropdown-item-hover-bg;
color: $gl-text-color; color: $gl-text-color;
} }
......
...@@ -132,6 +132,8 @@ ul.content-list { ...@@ -132,6 +132,8 @@ ul.content-list {
} }
.controls { .controls {
@include new-style-dropdown;
float: right; float: right;
> .control-text { > .control-text {
......
...@@ -204,6 +204,16 @@ ...@@ -204,6 +204,16 @@
} }
} }
div.avatar {
display: inline-flex;
justify-content: center;
align-items: center;
.center {
line-height: 14px;
}
}
strong { strong {
color: $gl-text-color; color: $gl-text-color;
} }
......
...@@ -161,6 +161,8 @@ ...@@ -161,6 +161,8 @@
} }
.nav-controls { .nav-controls {
@include new-style-dropdown;
display: inline-block; display: inline-block;
float: right; float: right;
text-align: right; text-align: right;
......
...@@ -276,3 +276,41 @@ ...@@ -276,3 +276,41 @@
.ajax-users-dropdown { .ajax-users-dropdown {
min-width: 250px !important; min-width: 250px !important;
} }
// TODO: change global style
.ajax-project-dropdown {
&.select2-drop {
color: $gl-text-color;
}
.select2-results {
.select2-no-results,
.select2-searching,
.select2-ajax-error,
.select2-selection-limit {
background: transparent;
}
.select2-result {
padding: 0 1px;
.select2-match {
font-weight: bold;
text-decoration: none;
}
.select2-result-label {
padding: #{$gl-padding / 2} $gl-padding;
}
&.select2-highlighted {
background-color: transparent !important;
color: $gl-text-color;
.select2-result-label {
background-color: $dropdown-item-hover-bg;
}
}
}
}
}
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
background-color: $gray-lightest; background-color: $gray-lightest;
} }
img.js-lazy-loaded { img.js-lazy-loaded,
img.emoji {
min-width: inherit; min-width: inherit;
min-height: inherit; min-height: inherit;
background-color: inherit; background-color: inherit;
......
...@@ -300,7 +300,7 @@ $dropdown-input-focus-shadow: rgba($dropdown-input-focus-border, .4); ...@@ -300,7 +300,7 @@ $dropdown-input-focus-shadow: rgba($dropdown-input-focus-border, .4);
$dropdown-loading-bg: rgba(#fff, .6); $dropdown-loading-bg: rgba(#fff, .6);
$dropdown-chevron-size: 10px; $dropdown-chevron-size: 10px;
$dropdown-toggle-active-border-color: darken($border-color, 14%); $dropdown-toggle-active-border-color: darken($border-color, 14%);
$dropdown-item-hover-bg: $gray-darker;
/* /*
* Filtered Search * Filtered Search
......
...@@ -403,6 +403,7 @@ header.navbar-gitlab-new { ...@@ -403,6 +403,7 @@ header.navbar-gitlab-new {
} }
.breadcrumbs-extra { .breadcrumbs-extra {
display: flex;
flex: 0 0 auto; flex: 0 0 auto;
margin-left: auto; margin-left: auto;
} }
......
...@@ -97,13 +97,16 @@ $new-sidebar-collapsed-width: 50px; ...@@ -97,13 +97,16 @@ $new-sidebar-collapsed-width: 50px;
top: $header-height; top: $header-height;
bottom: 0; bottom: 0;
left: 0; left: 0;
overflow: auto;
background-color: $gray-normal; background-color: $gray-normal;
box-shadow: inset -2px 0 0 $border-color; box-shadow: inset -2px 0 0 $border-color;
transform: translate3d(0, 0, 0);
&.sidebar-icons-only { &.sidebar-icons-only {
width: $new-sidebar-collapsed-width; width: $new-sidebar-collapsed-width;
overflow-x: hidden;
.nav-sidebar-inner-scroll {
overflow-x: hidden;
}
.badge, .badge,
.project-title { .project-title {
...@@ -111,7 +114,11 @@ $new-sidebar-collapsed-width: 50px; ...@@ -111,7 +114,11 @@ $new-sidebar-collapsed-width: 50px;
} }
.nav-item-name { .nav-item-name {
opacity: 0; display: none;
}
.sidebar-top-level-items > li > a {
min-height: 44px;
} }
} }
...@@ -176,6 +183,12 @@ $new-sidebar-collapsed-width: 50px; ...@@ -176,6 +183,12 @@ $new-sidebar-collapsed-width: 50px;
} }
} }
.nav-sidebar-inner-scroll {
height: 100%;
width: 100%;
overflow: auto;
}
.with-performance-bar .nav-sidebar { .with-performance-bar .nav-sidebar {
top: $header-height + $performance-bar-height; top: $header-height + $performance-bar-height;
} }
......
...@@ -560,9 +560,13 @@ ...@@ -560,9 +560,13 @@
} }
.diff-files-changed { .diff-files-changed {
.inline-parallel-buttons {
position: relative;
z-index: 1;
}
.commit-stat-summary { .commit-stat-summary {
@include new-style-dropdown; @include new-style-dropdown;
z-index: -1;
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
margin-left: -$gl-padding; margin-left: -$gl-padding;
......
...@@ -81,6 +81,7 @@ ...@@ -81,6 +81,7 @@
border: 1px solid $white-normal; border: 1px solid $white-normal;
padding: 5px; padding: 5px;
max-height: calc(100vh - 100px); max-height: calc(100vh - 100px);
max-width: 100%;
} }
.emoji-block { .emoji-block {
...@@ -259,7 +260,7 @@ ...@@ -259,7 +260,7 @@
padding-top: 10px; padding-top: 10px;
} }
&:not(.issue-boards-sidebar):not([data-signed-in]) { &:not(.issue-boards-sidebar):not([data-signed-in]):not([data-always-show-toggle]) {
.issuable-sidebar-header { .issuable-sidebar-header {
display: none; display: none;
} }
......
...@@ -35,18 +35,18 @@ module EventsHelper ...@@ -35,18 +35,18 @@ module EventsHelper
[event.action_name, target].join(" ") [event.action_name, target].join(" ")
end end
def event_filter_link(key, tooltip) def event_filter_link(key, text, tooltip)
key = key.to_s key = key.to_s
active = 'active' if @event_filter.active?(key) active = 'active' if @event_filter.active?(key)
link_opts = { link_opts = {
class: "event-filter-link", class: "event-filter-link has-tooltip",
id: "#{key}_event_filter", id: "#{key}_event_filter",
title: "Filter by #{tooltip.downcase}" title: tooltip
} }
content_tag :li, class: active do content_tag :li, class: active do
link_to request.path, link_opts do link_to request.path, link_opts do
content_tag(:span, ' ' + tooltip) content_tag(:span, ' ' + text)
end end
end end
end end
...@@ -176,7 +176,7 @@ module EventsHelper ...@@ -176,7 +176,7 @@ module EventsHelper
sanitize( sanitize(
text, text,
tags: %w(a img gl-emoji b pre code p span), tags: %w(a img gl-emoji b pre code p span),
attributes: Rails::Html::WhiteListSanitizer.allowed_attributes + ['style', 'data-name', 'data-unicode-version'] attributes: Rails::Html::WhiteListSanitizer.allowed_attributes + ['style', 'data-src', 'data-name', 'data-unicode-version']
) )
end end
......
...@@ -235,6 +235,8 @@ module ProjectsHelper ...@@ -235,6 +235,8 @@ module ProjectsHelper
# If no limit is applied we'll just issue a COUNT since the result set could # If no limit is applied we'll just issue a COUNT since the result set could
# be too large to load into memory. # be too large to load into memory.
def any_projects?(projects) def any_projects?(projects)
return projects.any? if projects.is_a?(Array)
if projects.limit_value if projects.limit_value
projects.to_a.any? projects.to_a.any?
else else
......
...@@ -9,7 +9,7 @@ module BlobViewer ...@@ -9,7 +9,7 @@ module BlobViewer
end end
def manager_url def manager_url
'https://getcomposer.com/' 'https://getcomposer.org/'
end end
def package_name def package_name
......
...@@ -198,10 +198,7 @@ module Ci ...@@ -198,10 +198,7 @@ module Ci
# * Maximum length is 63 bytes # * Maximum length is 63 bytes
# * First/Last Character is not a hyphen # * First/Last Character is not a hyphen
def ref_slug def ref_slug
ref.to_s Gitlab::Utils.slugify(ref.to_s)
.downcase
.gsub(/[^a-z0-9]/, '-')[0..62]
.gsub(/(\A-+|-+\z)/, '')
end end
# Variables whose value does not depend on environment # Variables whose value does not depend on environment
......
...@@ -9,7 +9,7 @@ module Ci ...@@ -9,7 +9,7 @@ module Ci
belongs_to :owner, class_name: 'User' belongs_to :owner, class_name: 'User'
has_one :last_pipeline, -> { order(id: :desc) }, class_name: 'Ci::Pipeline' has_one :last_pipeline, -> { order(id: :desc) }, class_name: 'Ci::Pipeline'
has_many :pipelines has_many :pipelines
has_many :variables, class_name: 'Ci::PipelineScheduleVariable' has_many :variables, class_name: 'Ci::PipelineScheduleVariable', validate: false
validates :cron, unless: :importing?, cron: true, presence: { unless: :importing? } validates :cron, unless: :importing?, cron: true, presence: { unless: :importing? }
validates :cron_timezone, cron_timezone: true, presence: { unless: :importing? } validates :cron_timezone, cron_timezone: true, presence: { unless: :importing? }
......
...@@ -4,5 +4,7 @@ module Ci ...@@ -4,5 +4,7 @@ module Ci
include HasVariable include HasVariable
belongs_to :pipeline_schedule belongs_to :pipeline_schedule
validates :key, uniqueness: { scope: :pipeline_schedule_id }
end end
end end
module Ci module Ci
class Stage < ActiveRecord::Base class Stage < ActiveRecord::Base
extend Ci::Model extend Ci::Model
include Importable
include HasStatus
include Gitlab::OptimisticLocking
enum status: HasStatus::STATUSES_ENUM
belongs_to :project belongs_to :project
belongs_to :pipeline belongs_to :pipeline
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id has_many :statuses, class_name: 'CommitStatus', foreign_key: :stage_id
has_many :builds, foreign_key: :commit_id has_many :builds, foreign_key: :stage_id
validates :project, presence: true, unless: :importing?
validates :pipeline, presence: true, unless: :importing?
validates :name, presence: true, unless: :importing?
state_machine :status, initial: :created do
event :enqueue do
transition created: :pending
transition [:success, :failed, :canceled, :skipped] => :running
end
event :run do
transition any - [:running] => :running
end
event :skip do
transition any - [:skipped] => :skipped
end
event :drop do
transition any - [:failed] => :failed
end
event :succeed do
transition any - [:success] => :success
end
event :cancel do
transition any - [:canceled] => :canceled
end
event :block do
transition any - [:manual] => :manual
end
end
def update_status
retry_optimistic_lock(self) do
case statuses.latest.status
when 'pending' then enqueue
when 'running' then run
when 'success' then succeed
when 'failed' then drop
when 'canceled' then cancel
when 'manual' then block
when 'skipped' then skip
else skip
end
end
end
end end
end end
...@@ -383,6 +383,6 @@ class Commit ...@@ -383,6 +383,6 @@ class Commit
end end
def gpg_commit def gpg_commit
@gpg_commit ||= Gitlab::Gpg::Commit.new(self) @gpg_commit ||= Gitlab::Gpg::Commit.for_commit(self)
end end
end end
...@@ -39,14 +39,14 @@ class CommitStatus < ActiveRecord::Base ...@@ -39,14 +39,14 @@ class CommitStatus < ActiveRecord::Base
scope :after_stage, -> (index) { where('stage_idx > ?', index) } scope :after_stage, -> (index) { where('stage_idx > ?', index) }
state_machine :status do state_machine :status do
event :enqueue do
transition [:created, :skipped, :manual] => :pending
end
event :process do event :process do
transition [:skipped, :manual] => :created transition [:skipped, :manual] => :created
end end
event :enqueue do
transition [:created, :skipped, :manual] => :pending
end
event :run do event :run do
transition pending: :running transition pending: :running
end end
...@@ -91,6 +91,7 @@ class CommitStatus < ActiveRecord::Base ...@@ -91,6 +91,7 @@ class CommitStatus < ActiveRecord::Base
end end
end end
StageUpdateWorker.perform_async(commit_status.stage_id)
ExpireJobCacheWorker.perform_async(commit_status.id) ExpireJobCacheWorker.perform_async(commit_status.id)
end end
end end
......
...@@ -8,6 +8,8 @@ module HasStatus ...@@ -8,6 +8,8 @@ module HasStatus
ACTIVE_STATUSES = %w[pending running].freeze ACTIVE_STATUSES = %w[pending running].freeze
COMPLETED_STATUSES = %w[success failed canceled skipped].freeze COMPLETED_STATUSES = %w[success failed canceled skipped].freeze
ORDERED_STATUSES = %w[failed pending running manual canceled success skipped created].freeze ORDERED_STATUSES = %w[failed pending running manual canceled success skipped created].freeze
STATUSES_ENUM = { created: 0, pending: 1, running: 2, success: 3,
failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze
class_methods do class_methods do
def status_sql def status_sql
......
...@@ -25,6 +25,11 @@ module Referable ...@@ -25,6 +25,11 @@ module Referable
to_reference(from_project) to_reference(from_project)
end end
included do
alias_method :non_referable_inspect, :inspect
alias_method :inspect, :referable_inspect
end
def referable_inspect def referable_inspect
if respond_to?(:id) if respond_to?(:id)
"#<#{self.class.name} id:#{id} #{to_reference(full: true)}>" "#<#{self.class.name} id:#{id} #{to_reference(full: true)}>"
...@@ -33,10 +38,6 @@ module Referable ...@@ -33,10 +38,6 @@ module Referable
end end
end end
def inspect
referable_inspect
end
module ClassMethods module ClassMethods
# The character that prefixes the actual reference identifier # The character that prefixes the actual reference identifier
# #
......
...@@ -89,6 +89,10 @@ class Event < ActiveRecord::Base ...@@ -89,6 +89,10 @@ class Event < ActiveRecord::Base
self.inheritance_column = 'action' self.inheritance_column = 'action'
class << self class << self
def model_name
ActiveModel::Name.new(self, nil, 'event')
end
def find_sti_class(action) def find_sti_class(action)
if action.to_i == PUSHED if action.to_i == PUSHED
PushEvent PushEvent
...@@ -444,6 +448,12 @@ class Event < ActiveRecord::Base ...@@ -444,6 +448,12 @@ class Event < ActiveRecord::Base
EventForMigration.create!(new_attributes) EventForMigration.create!(new_attributes)
end end
def to_partial_path
# We are intentionally using `Event` rather than `self.class` so that
# subclasses also use the `Event` implementation.
Event._to_partial_path
end
private private
def recent_update? def recent_update?
......
...@@ -18,4 +18,8 @@ class GpgSignature < ActiveRecord::Base ...@@ -18,4 +18,8 @@ class GpgSignature < ActiveRecord::Base
def commit def commit
project.commit(commit_sha) project.commit(commit_sha)
end end
def gpg_commit
Gitlab::Gpg::Commit.new(project, commit_sha)
end
end end
...@@ -12,11 +12,8 @@ class Issue < ActiveRecord::Base ...@@ -12,11 +12,8 @@ class Issue < ActiveRecord::Base
include Elastic::IssuesSearch include Elastic::IssuesSearch
include FasterCacheKeys include FasterCacheKeys
include RelativePositioning include RelativePositioning
include IgnorableColumn
include CreatedAtFilterable include CreatedAtFilterable
ignore_column :position
WEIGHT_RANGE = 1..9 WEIGHT_RANGE = 1..9
WEIGHT_ALL = 'Everything'.freeze WEIGHT_ALL = 'Everything'.freeze
WEIGHT_ANY = 'Any Weight'.freeze WEIGHT_ANY = 'Any Weight'.freeze
......
...@@ -8,7 +8,6 @@ class MergeRequest < ActiveRecord::Base ...@@ -8,7 +8,6 @@ class MergeRequest < ActiveRecord::Base
include IgnorableColumn include IgnorableColumn
include CreatedAtFilterable include CreatedAtFilterable
ignore_column :position
ignore_column :locked_at ignore_column :locked_at
include ::EE::MergeRequest include ::EE::MergeRequest
......
...@@ -63,7 +63,7 @@ class Project < ActiveRecord::Base ...@@ -63,7 +63,7 @@ class Project < ActiveRecord::Base
end end
before_destroy :remove_private_deploy_keys before_destroy :remove_private_deploy_keys
after_destroy :remove_pages after_destroy -> { run_after_commit { remove_pages } }
# update visibility_level of forks # update visibility_level of forks
after_update :update_forks_visibility_level after_update :update_forks_visibility_level
...@@ -1237,6 +1237,9 @@ class Project < ActiveRecord::Base ...@@ -1237,6 +1237,9 @@ class Project < ActiveRecord::Base
# TODO: what to do here when not using Legacy Storage? Do we still need to rename and delay removal? # TODO: what to do here when not using Legacy Storage? Do we still need to rename and delay removal?
def remove_pages def remove_pages
# Projects with a missing namespace cannot have their pages removed
return unless namespace
::Projects::UpdatePagesConfigurationService.new(self).execute ::Projects::UpdatePagesConfigurationService.new(self).execute
# 1. We rename pages to temporary directory # 1. We rename pages to temporary directory
...@@ -1295,12 +1298,16 @@ class Project < ActiveRecord::Base ...@@ -1295,12 +1298,16 @@ class Project < ActiveRecord::Base
status.zero? status.zero?
end end
def full_path_slug
Gitlab::Utils.slugify(full_path.to_s)
end
def predefined_variables def predefined_variables
[ [
{ key: 'CI_PROJECT_ID', value: id.to_s, public: true }, { key: 'CI_PROJECT_ID', value: id.to_s, public: true },
{ key: 'CI_PROJECT_NAME', value: path, public: true }, { key: 'CI_PROJECT_NAME', value: path, public: true },
{ key: 'CI_PROJECT_PATH', value: full_path, public: true }, { key: 'CI_PROJECT_PATH', value: full_path, public: true },
{ key: 'CI_PROJECT_PATH_SLUG', value: full_path.parameterize, public: true }, { key: 'CI_PROJECT_PATH_SLUG', value: full_path_slug, public: true },
{ key: 'CI_PROJECT_NAMESPACE', value: namespace.full_path, public: true }, { key: 'CI_PROJECT_NAMESPACE', value: namespace.full_path, public: true },
{ key: 'CI_PROJECT_URL', value: web_url, public: true } { key: 'CI_PROJECT_URL', value: web_url, public: true }
] ]
......
...@@ -50,11 +50,6 @@ class User < ActiveRecord::Base ...@@ -50,11 +50,6 @@ class User < ActiveRecord::Base
devise :lockable, :recoverable, :rememberable, :trackable, devise :lockable, :recoverable, :rememberable, :trackable,
:validatable, :omniauthable, :confirmable, :registerable :validatable, :omniauthable, :confirmable, :registerable
# devise overrides #inspect, so we manually use the Referable one
def inspect
referable_inspect
end
# 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)
...@@ -861,7 +856,12 @@ class User < ActiveRecord::Base ...@@ -861,7 +856,12 @@ class User < ActiveRecord::Base
create_namespace!(path: username, name: username) unless namespace create_namespace!(path: username, name: username) unless namespace
if username_changed? if username_changed?
namespace.update_attributes(path: username, name: username) unless namespace.update_attributes(path: username, name: username)
namespace.errors.each do |attribute, message|
self.errors.add(:"namespace_#{attribute}", message)
end
raise ActiveRecord::RecordInvalid.new(namespace)
end
end end
end end
......
...@@ -181,9 +181,14 @@ module Ci ...@@ -181,9 +181,14 @@ module Ci
end end
def error(message, save: false) def error(message, save: false)
pipeline.errors.add(:base, message) pipeline.tap do
pipeline.drop if save pipeline.errors.add(:base, message)
pipeline
if save
pipeline.drop
update_merge_requests_head_pipeline
end
end
end end
def pipeline_created_counter def pipeline_created_counter
......
...@@ -65,7 +65,7 @@ module Geo ...@@ -65,7 +65,7 @@ module Geo
Gitlab::ExclusiveLease.cancel(lease_key, repository_lease) Gitlab::ExclusiveLease.cancel(lease_key, repository_lease)
end end
def update_registry(type, started_at: nil, finished_at: nil) def update_registry(started_at: nil, finished_at: nil)
return unless started_at || finished_at return unless started_at || finished_at
log_info("Updating #{type} sync information") log_info("Updating #{type} sync information")
......
...@@ -4,8 +4,13 @@ module Geo ...@@ -4,8 +4,13 @@ module Geo
def execute def execute
try_obtain_lease do |lease| try_obtain_lease do |lease|
start_time = Time.now
bytes_downloaded = downloader.execute bytes_downloaded = downloader.execute
success = bytes_downloaded && bytes_downloaded >= 0 success = bytes_downloaded && bytes_downloaded >= 0
log_info("File download",
success: success,
bytes_downloaded: bytes_downloaded,
download_time_s: (Time.now - start_time).to_f.round(3))
update_registry(bytes_downloaded) if success update_registry(bytes_downloaded) if success
end end
end end
......
...@@ -27,8 +27,9 @@ module Geo ...@@ -27,8 +27,9 @@ module Geo
klass_name.camelize klass_name.camelize
end end
def log_info(message) def log_info(message, details = {})
data = log_base_data(message) data = log_base_data(message)
data.merge!(details) if details
Gitlab::Geo::Logger.info(data) Gitlab::Geo::Logger.info(data)
end end
......
...@@ -11,17 +11,17 @@ module Geo ...@@ -11,17 +11,17 @@ module Geo
def fetch_project_repository def fetch_project_repository
log_info('Fetching project repository') log_info('Fetching project repository')
update_registry(:repository, started_at: DateTime.now) update_registry(started_at: DateTime.now)
begin begin
project.ensure_repository project.ensure_repository
project.repository.fetch_geo_mirror(ssh_url_to_repo) project.repository.fetch_geo_mirror(ssh_url_to_repo)
update_registry(:repository, finished_at: DateTime.now) update_registry(finished_at: DateTime.now)
rescue Gitlab::Shell::Error, Geo::EmptyCloneUrlPrefixError => e rescue Gitlab::Shell::Error, Geo::EmptyCloneUrlPrefixError => e
log_error("Error syncing repository", e) log_error('Error syncing repository', e)
rescue Gitlab::Git::Repository::NoRepository => e rescue Gitlab::Git::Repository::NoRepository => e
log_error("Invalid repository", e) log_error('Invalid repository', e)
log_info('Expiring caches') log_info('Expiring caches')
project.repository.after_create project.repository.after_create
end end
......
...@@ -10,18 +10,18 @@ module Geo ...@@ -10,18 +10,18 @@ module Geo
def fetch_wiki_repository def fetch_wiki_repository
log_info('Fetching wiki repository') log_info('Fetching wiki repository')
update_registry(:wiki, started_at: DateTime.now) update_registry(started_at: DateTime.now)
begin begin
project.wiki.ensure_repository project.wiki.ensure_repository
project.wiki.repository.fetch_geo_mirror(ssh_url_to_wiki) project.wiki.repository.fetch_geo_mirror(ssh_url_to_wiki)
update_registry(:wiki, finished_at: DateTime.now) update_registry(finished_at: DateTime.now)
rescue Gitlab::Git::Repository::NoRepository, rescue Gitlab::Git::Repository::NoRepository,
Gitlab::Shell::Error, Gitlab::Shell::Error,
ProjectWiki::CouldNotCreateWikiError, ProjectWiki::CouldNotCreateWikiError,
Geo::EmptyCloneUrlPrefixError => e Geo::EmptyCloneUrlPrefixError => e
log_error("Error syncing wiki repository", e) log_error('Error syncing wiki repository', e)
end end
end end
......
...@@ -95,8 +95,19 @@ class GitPushService < BaseService ...@@ -95,8 +95,19 @@ class GitPushService < BaseService
end end
def update_signatures def update_signatures
@push_commits.each do |commit| commit_shas = @push_commits.last(PROCESS_COMMIT_LIMIT).map(&:sha)
CreateGpgSignatureWorker.perform_async(commit.sha, @project.id)
return if commit_shas.empty?
shas_with_cached_signatures = GpgSignature.where(commit_sha: commit_shas).pluck(:commit_sha)
commit_shas -= shas_with_cached_signatures
return if commit_shas.empty?
commit_shas = Gitlab::Git::Commit.shas_with_signatures(project.repository, commit_shas)
commit_shas.each do |sha|
CreateGpgSignatureWorker.perform_async(sha, project.id)
end end
end end
......
...@@ -3,6 +3,8 @@ module MergeRequests ...@@ -3,6 +3,8 @@ module MergeRequests
def execute def execute
return error('Invalid issue iid') unless issue_iid.present? && issue.present? return error('Invalid issue iid') unless issue_iid.present? && issue.present?
params[:label_ids] = issue.label_ids if issue.label_ids.any?
result = CreateBranchService.new(project, current_user).execute(branch_name, ref) result = CreateBranchService.new(project, current_user).execute(branch_name, ref)
return result if result[:status] == :error return result if result[:status] == :error
...@@ -43,7 +45,8 @@ module MergeRequests ...@@ -43,7 +45,8 @@ module MergeRequests
{ {
source_project_id: project.id, source_project_id: project.id,
source_branch: branch_name, source_branch: branch_name,
target_project_id: project.id target_project_id: project.id,
milestone_id: issue.milestone_id
} }
end end
......
...@@ -25,7 +25,6 @@ module MergeRequests ...@@ -25,7 +25,6 @@ module MergeRequests
end end
def after_create(issuable) def after_create(issuable)
event_service.open_mr(issuable, current_user)
todo_service.new_merge_request(issuable, current_user) todo_service.new_merge_request(issuable, current_user)
issuable.cache_merge_request_closes_issues!(current_user) issuable.cache_merge_request_closes_issues!(current_user)
update_merge_requests_head_pipeline(issuable) update_merge_requests_head_pipeline(issuable)
......
...@@ -20,6 +20,14 @@ class ObjectStoreUploader < CarrierWave::Uploader::Base ...@@ -20,6 +20,14 @@ class ObjectStoreUploader < CarrierWave::Uploader::Base
def object_store_enabled? def object_store_enabled?
object_store_options&.enabled object_store_options&.enabled
end end
def object_store_credentials
@object_store_credentials ||= object_store_options&.connection&.to_hash&.deep_symbolize_keys
end
def object_store_directory
object_store_options&.remote_directory
end
end end
attr_reader :subject, :field attr_reader :subject, :field
...@@ -98,11 +106,11 @@ class ObjectStoreUploader < CarrierWave::Uploader::Base ...@@ -98,11 +106,11 @@ class ObjectStoreUploader < CarrierWave::Uploader::Base
end end
def fog_directory def fog_directory
self.class.object_store_options.remote_directory self.class.object_store_directory
end end
def fog_credentials def fog_credentials
self.class.object_store_options.connection self.class.object_store_credentials
end end
def fog_public def fog_public
......
...@@ -397,7 +397,9 @@ ...@@ -397,7 +397,9 @@
%fieldset %fieldset
%legend Background Jobs %legend Background Jobs
%p %p
These settings require a restart to take effect. These settings require a
= link_to 'restart', help_page_path('administration/restart_gitlab')
to take effect.
.form-group .form-group
.col-sm-offset-2.col-sm-10 .col-sm-offset-2.col-sm-10
.checkbox .checkbox
......
...@@ -46,9 +46,10 @@ ...@@ -46,9 +46,10 @@
%li %li
= link_to 'Remove user', admin_user_path(user), = link_to 'Remove user', admin_user_path(user),
data: { confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?" }, data: { confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?" },
class: 'text-danger',
method: :delete method: :delete
%li %li
= link_to 'Remove user and contributions', admin_user_path(user, hard_delete: true), = link_to 'Remove user and contributions', admin_user_path(user, hard_delete: true),
data: { confirm: "USER #{user.name} WILL BE REMOVED! All issues, merge requests and comments authored by this user, and groups owned solely by them, will also be removed! Are you sure?" }, data: { confirm: "USER #{user.name} WILL BE REMOVED! All issues, merge requests and comments authored by this user, and groups owned solely by them, will also be removed! Are you sure?" },
class: 'btn btn-remove btn-block', class: 'text-danger',
method: :delete method: :delete
...@@ -8,14 +8,14 @@ ...@@ -8,14 +8,14 @@
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= link_to params.merge(rss_url_options), class: 'btn has-tooltip append-right-10', title: 'Subscribe' do = link_to params.merge(rss_url_options), class: 'btn has-tooltip append-right-10', title: 'Subscribe' do
= icon('rss') = icon('rss')
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues' = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues
.top-area .top-area
= render 'shared/issuable/nav', type: :issues = render 'shared/issuable/nav', type: :issues
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls{ class: ("visible-xs" if show_new_nav?) }
= link_to params.merge(rss_url_options), class: 'btn has-tooltip', title: 'Subscribe' do = link_to params.merge(rss_url_options), class: 'btn has-tooltip', title: 'Subscribe' do
= icon('rss') = icon('rss')
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues' = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues
= render 'shared/issuable/filter', type: :issues = render 'shared/issuable/filter', type: :issues
= render 'shared/issues' = render 'shared/issues'
...@@ -4,12 +4,12 @@ ...@@ -4,12 +4,12 @@
- if show_new_nav? - if show_new_nav?
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests' = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests
.top-area .top-area
= render 'shared/issuable/nav', type: :merge_requests = render 'shared/issuable/nav', type: :merge_requests
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls{ class: ("visible-xs" if show_new_nav?) }
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests' = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests
= render 'shared/issuable/filter', type: :merge_requests = render 'shared/issuable/filter', type: :merge_requests
= render 'shared/merge_requests' = render 'shared/merge_requests'
...@@ -4,13 +4,13 @@ ...@@ -4,13 +4,13 @@
- if show_new_nav? - if show_new_nav?
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true = render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true, type: :milestones
.top-area .top-area
= render 'shared/milestones_filter', counts: @milestone_states = render 'shared/milestones_filter', counts: @milestone_states
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls{ class: ("visible-xs" if show_new_nav?) }
= render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true = render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true, type: :milestones
.milestones .milestones
%ul.content-list %ul.content-list
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= link_to params.merge(rss_url_options), class: 'btn btn-default append-right-10' do = link_to params.merge(rss_url_options), class: 'btn btn-default append-right-10' do
= icon('rss') = icon('rss')
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue" = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues
- if group_issues_exists - if group_issues_exists
.top-area .top-area
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
= icon('rss') = icon('rss')
%span.icon-label %span.icon-label
Subscribe Subscribe
= render 'shared/new_project_item_select', path: 'issues/new', label: "New issue" = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues
= render 'shared/issuable/search_bar', type: :issues = render 'shared/issuable/search_bar', type: :issues
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
- if show_new_nav? && current_user - if show_new_nav? && current_user
- content_for :breadcrumbs_extra do - content_for :breadcrumbs_extra do
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request" = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests
- if @group_merge_requests.empty? - if @group_merge_requests.empty?
= render 'shared/empty_states/merge_requests', project_select_button: true = render 'shared/empty_states/merge_requests', project_select_button: true
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
= render 'shared/issuable/nav', type: :merge_requests = render 'shared/issuable/nav', type: :merge_requests
- if current_user - if current_user
.nav-controls{ class: ("visible-xs" if show_new_nav?) } .nav-controls{ class: ("visible-xs" if show_new_nav?) }
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request" = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests
= render 'shared/issuable/filter', type: :merge_requests = render 'shared/issuable/filter', type: :merge_requests
......
...@@ -189,7 +189,7 @@ ...@@ -189,7 +189,7 @@
= icon('chevron-down') = icon('chevron-down')
%ul.dropdown-menu %ul.dropdown-menu
%li %li
%a Sort by date = link_to 'Sort by date', '#'
= link_to 'New issue', '#', class: 'btn btn-new btn-inverted' = link_to 'New issue', '#', class: 'btn btn-new btn-inverted'
......
.page-with-sidebar.js-page-with-sidebar{ class: [('page-with-new-sidebar' if @new_sidebar), page_gutter_class] } .page-with-sidebar.js-page-with-sidebar{ class: page_with_sidebar_class }
- if show_new_nav? - if show_new_nav?
- if defined?(nav) && nav - if defined?(nav) && nav
= render "layouts/nav/#{nav}" = render "layouts/nav/#{nav}"
......
...@@ -74,10 +74,7 @@ ...@@ -74,10 +74,7 @@
= link_to admin_requests_profiles_path, title: 'Requests Profiles' do = link_to admin_requests_profiles_path, title: 'Requests Profiles' do
%span %span
Requests Profiles Requests Profiles
= nav_link path: 'audit_logs#index' do = render 'layouts/nav/ee/new_admin_monitoring_sidebar'
= link_to admin_audit_logs_path, title: 'Audit Log' do
%span
Audit Log
= nav_link(controller: :broadcast_messages) do = nav_link(controller: :broadcast_messages) do
= link_to admin_broadcast_messages_path, title: 'Messages' do = link_to admin_broadcast_messages_path, title: 'Messages' do
...@@ -118,58 +115,168 @@ ...@@ -118,58 +115,168 @@
= nav_link(controller: :spam_logs) do = nav_link(controller: :spam_logs) do
= link_to admin_spam_logs_path, title: "Spam Logs" do = link_to admin_spam_logs_path, title: "Spam Logs" do
.nav-icon-container .nav-icon-container
= custom_icon('spam_logs') = custom_icon('overview')
%span.nav-item-name %span.nav-item-name
Spam Logs Overview
= nav_link(controller: :push_rules) do %ul.sidebar-sub-level-items
= link_to admin_push_rule_path, title: 'Push Rules' do = nav_link(controller: :dashboard, html_options: {class: 'home'}) do
.nav-icon-container = link_to admin_root_path, title: 'Overview' do
= custom_icon('push_rules') %span
%span.nav-item-name Dashboard
Push Rules = nav_link(controller: [:admin, :projects]) do
= link_to admin_projects_path, title: 'Projects' do
%span
Projects
= nav_link(controller: :users) do
= link_to admin_users_path, title: 'Users' do
%span
Users
= nav_link(controller: :groups) do
= link_to admin_groups_path, title: 'Groups' do
%span
Groups
= nav_link path: 'jobs#index' do
= link_to admin_jobs_path, title: 'Jobs' do
%span
Jobs
= nav_link path: ['runners#index', 'runners#show'] do
= link_to admin_runners_path, title: 'Runners' do
%span
Runners
= nav_link path: 'cohorts#index' do
= link_to admin_cohorts_path, title: 'Cohorts' do
%span
Cohorts
= nav_link(controller: :geo_nodes) do = nav_link(controller: %w(conversational_development_index system_info background_jobs logs health_check requests_profiles audit_logs)) do
= link_to admin_geo_nodes_path, title: 'Geo Nodes' do = link_to admin_conversational_development_index_path, title: 'Monitoring' do
.nav-icon-container .nav-icon-container
= custom_icon('geo_nodes') = custom_icon('monitoring')
%span.nav-item-name %span.nav-item-name
Geo Nodes Monitoring
= nav_link(controller: :deploy_keys) do %ul.sidebar-sub-level-items
= link_to admin_deploy_keys_path, title: 'Deploy Keys' do = nav_link(controller: :conversational_development_index) do
.nav-icon-container = link_to admin_conversational_development_index_path, title: 'ConvDev Index' do
= custom_icon('key') %span
%span.nav-item-name ConvDev Index
Deploy Keys = nav_link(controller: :system_info) do
= link_to admin_system_info_path, title: 'System Info' do
%span
System Info
= nav_link(controller: :background_jobs) do
= link_to admin_background_jobs_path, title: 'Background Jobs' do
%span
Background Jobs
= nav_link(controller: :logs) do
= link_to admin_logs_path, title: 'Logs' do
%span
Logs
= nav_link(controller: :health_check) do
= link_to admin_health_check_path, title: 'Health Check' do
%span
Health Check
= nav_link(controller: :requests_profiles) do
= link_to admin_requests_profiles_path, title: 'Requests Profiles' do
%span
Requests Profiles
= nav_link(path: 'audit_logs#index') do
= link_to admin_audit_logs_path, title: 'Audit Log' do
%span
Audit Log
= nav_link(controller: :services) do = nav_link(controller: :broadcast_messages) do
= link_to admin_application_settings_services_path, title: 'Service Templates' do = link_to admin_broadcast_messages_path, title: 'Messages' do
.nav-icon-container .nav-icon-container
= custom_icon('service_templates') = custom_icon('messages')
%span.nav-item-name %span.nav-item-name
Service Templates Messages
= nav_link(controller: [:hooks, :hook_logs]) do
= link_to admin_hooks_path, title: 'Hooks' do
.nav-icon-container
= custom_icon('system_hooks')
%span.nav-item-name
System Hooks
= nav_link(controller: :labels) do = nav_link(controller: :applications) do
= link_to admin_labels_path, title: 'Labels' do = link_to admin_applications_path, title: 'Applications' do
.nav-icon-container .nav-icon-container
= custom_icon('labels') = custom_icon('applications')
%span.nav-item-name %span.nav-item-name
Labels Applications
= nav_link(controller: :appearances) do = nav_link(controller: :abuse_reports) do
= link_to admin_appearances_path, title: 'Appearances' do = link_to admin_abuse_reports_path, title: "Abuse Reports" do
.nav-icon-container .nav-icon-container
= custom_icon('appearance') = custom_icon('abuse_reports')
%span.nav-item-name %span.nav-item-name
Appearance Abuse Reports
%span.badge.count= number_with_delimiter(AbuseReport.count(:all))
%li.divider = nav_link(controller: :licenses) do
= nav_link(controller: :application_settings) do = link_to admin_license_path, title: 'License' do
= link_to admin_application_settings_path, title: 'Settings' do .nav-icon-container
.nav-icon-container = custom_icon('license')
= custom_icon('settings') %span.nav-item-name
%span.nav-item-name License
Settings
- if akismet_enabled?
= nav_link(controller: :spam_logs) do
= link_to admin_spam_logs_path, title: "Spam Logs" do
.nav-icon-container
= custom_icon('spam_logs')
%span.nav-item-name
Spam Logs
= nav_link(controller: :push_rules) do
= link_to admin_push_rule_path, title: 'Push Rules' do
.nav-icon-container
= custom_icon('push_rules')
%span.nav-item-name
Push Rules
= nav_link(controller: :geo_nodes) do
= link_to admin_geo_nodes_path, title: 'Geo Nodes' do
.nav-icon-container
= custom_icon('geo_nodes')
%span.nav-item-name
Geo Nodes
= nav_link(controller: :deploy_keys) do
= link_to admin_deploy_keys_path, title: 'Deploy Keys' do
.nav-icon-container
= custom_icon('key')
%span.nav-item-name
Deploy Keys
= nav_link(controller: :services) do
= link_to admin_application_settings_services_path, title: 'Service Templates' do
.nav-icon-container
= custom_icon('service_templates')
%span.nav-item-name
Service Templates
= nav_link(controller: :labels) do
= link_to admin_labels_path, title: 'Labels' do
.nav-icon-container
= custom_icon('labels')
%span.nav-item-name
Labels
= nav_link(controller: :appearances) do
= link_to admin_appearances_path, title: 'Appearances' do
.nav-icon-container
= custom_icon('appearance')
%span.nav-item-name
Appearance
%li.divider
= nav_link(controller: :application_settings) do
= link_to admin_application_settings_path, title: 'Settings' do
.nav-icon-container
= custom_icon('settings')
%span.nav-item-name
Settings
= render 'shared/sidebar_toggle_button' = render 'shared/sidebar_toggle_button'
.nav-sidebar{ class: ("sidebar-icons-only" if collapsed_sidebar?) } .nav-sidebar{ class: ("sidebar-icons-only" if collapsed_sidebar?) }
.context-header .nav-sidebar-inner-scroll
= link_to group_path(@group), title: @group.name do .context-header
.avatar-container.s40.group-avatar = link_to group_path(@group), title: @group.name do
= image_tag group_icon(@group), class: "avatar s40 avatar-tile" .avatar-container.s40.group-avatar
.group-title = image_tag group_icon(@group), class: "avatar s40 avatar-tile"
= @group.name .group-title
%ul.sidebar-top-level-items = @group.name
= nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups', 'analytics#show'], html_options: { class: 'home' }) do %ul.sidebar-top-level-items
= link_to group_path(@group), title: 'Group overview' do = nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups', 'analytics#show'], html_options: { class: 'home' }) do
.nav-icon-container = link_to group_path(@group), title: 'Group overview' do
= custom_icon('project') .nav-icon-container
%span.nav-item-name = custom_icon('project')
Overview %span.nav-item-name
Overview
%ul.sidebar-sub-level-items
= nav_link(path: ['groups#show', 'groups#subgroups'], html_options: { class: 'home' }) do
= link_to group_path(@group), title: 'Group details' do
%span
Details
= nav_link(path: 'groups#activity') do
= link_to activity_group_path(@group), title: 'Activity' do
%span
Activity
- if @group.feature_available?(:contribution_analytics) %ul.sidebar-sub-level-items
= nav_link(path: 'analytics#show') do = nav_link(path: ['groups#show', 'groups#subgroups'], html_options: { class: 'home' }) do
= link_to group_analytics_path(@group), title: 'Contribution Analytics', data: {placement: 'right'} do = link_to group_path(@group), title: 'Group details' do
%span %span
Contribution Analytics Details
= nav_link(path: ['groups#issues', 'labels#index', 'milestones#index']) do
= link_to issues_group_path(@group), title: 'Issues' do
.nav-icon-container
= custom_icon('issues')
%span.nav-item-name
- issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
Issues
%span.badge.count= number_with_delimiter(issues.count)
%ul.sidebar-sub-level-items = nav_link(path: 'groups#activity') do
= nav_link(path: 'groups#issues', html_options: { class: 'home' }) do = link_to activity_group_path(@group), title: 'Activity' do
= link_to issues_group_path(@group), title: 'List' do %span
%span Activity
List
= nav_link(path: 'labels#index') do
= link_to group_labels_path(@group), title: 'Labels' do
%span
Labels
= nav_link(path: 'milestones#index') do - if @group.feature_available?(:contribution_analytics)
= link_to group_milestones_path(@group), title: 'Milestones' do = nav_link(path: 'analytics#show') do
%span = link_to group_analytics_path(@group), title: 'Contribution Analytics', data: {placement: 'right'} do
Milestones %span
Contribution Analytics
= nav_link(path: 'groups#merge_requests') do = nav_link(path: ['groups#issues', 'labels#index', 'milestones#index']) do
= link_to merge_requests_group_path(@group), title: 'Merge Requests' do = link_to issues_group_path(@group), title: 'Issues' do
.nav-icon-container
= custom_icon('mr_bold')
%span.nav-item-name
- merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened', non_archived: true).execute
Merge Requests
%span.badge.count= number_with_delimiter(merge_requests.count)
= nav_link(path: 'group_members#index') do
= link_to group_group_members_path(@group), title: 'Members' do
.nav-icon-container
= custom_icon('members')
%span.nav-item-name
Members
- if current_user && can?(current_user, :admin_group, @group)
= nav_link(path: %w[groups#projects groups#edit ci_cd#show ldap_group_links#index hooks#index audit_events#index pipeline_quota#index]) do
= link_to edit_group_path(@group), title: 'Settings' do
.nav-icon-container .nav-icon-container
= custom_icon('settings') = custom_icon('issues')
%span.nav-item-name %span.nav-item-name
Settings - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
Issues
%span.badge.count= number_with_delimiter(issues.count)
%ul.sidebar-sub-level-items %ul.sidebar-sub-level-items
= nav_link(path: 'groups#edit') do = nav_link(path: 'groups#issues', html_options: { class: 'home' }) do
= link_to edit_group_path(@group), title: 'General' do = link_to issues_group_path(@group), title: 'List' do
%span %span
General List
= nav_link(path: 'groups#projects') do = nav_link(path: 'labels#index') do
= link_to projects_group_path(@group), title: 'Projects' do = link_to group_labels_path(@group), title: 'Labels' do
%span %span
Projects Labels
= nav_link(controller: :ci_cd) do = nav_link(path: 'milestones#index') do
= link_to group_settings_ci_cd_path(@group), title: 'CI / CD' do = link_to group_milestones_path(@group), title: 'Milestones' do
%span %span
CI / CD Milestones
= nav_link(path: 'groups#merge_requests') do
= link_to merge_requests_group_path(@group), title: 'Merge Requests' do
.nav-icon-container
= custom_icon('mr_bold')
%span.nav-item-name
- merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened', non_archived: true).execute
Merge Requests
%span.badge.count= number_with_delimiter(merge_requests.count)
= nav_link(path: 'group_members#index') do
= link_to group_group_members_path(@group), title: 'Members' do
.nav-icon-container
= custom_icon('members')
%span.nav-item-name
Members
- if current_user && can?(current_user, :admin_group, @group)
= nav_link(path: %w[groups#projects groups#edit ci_cd#show ldap_group_links#index hooks#index audit_events#index pipeline_quota#index]) do
= link_to edit_group_path(@group), title: 'Settings' do
.nav-icon-container
= custom_icon('settings')
%span.nav-item-name
Settings
%ul.sidebar-sub-level-items
= nav_link(path: 'groups#edit') do
= link_to edit_group_path(@group), title: 'General' do
%span
General
= nav_link(path: 'groups#projects') do
= link_to projects_group_path(@group), title: 'Projects' do
%span
Projects
= nav_link(controller: :ci_cd) do
= link_to group_settings_ci_cd_path(@group), title: 'CI / CD' do
%span
CI / CD
= render "groups/ee/settings_nav" = render "groups/ee/settings_nav"
= render 'shared/sidebar_toggle_button' = render 'shared/sidebar_toggle_button'
.nav-sidebar{ class: ("sidebar-icons-only" if collapsed_sidebar?) } .nav-sidebar{ class: ("sidebar-icons-only" if collapsed_sidebar?) }
.context-header .nav-sidebar-inner-scroll
= link_to profile_path, title: 'Profile Settings' do .context-header
.avatar-container.s40.settings-avatar
= icon('user')
.project-title User Settings
%ul.sidebar-top-level-items
= nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to profile_path, title: 'Profile Settings' do = link_to profile_path, title: 'Profile Settings' do
.nav-icon-container .avatar-container.s40.settings-avatar
= custom_icon('profile') = icon('user')
%span.nav-item-name .project-title User Settings
Profile %ul.sidebar-top-level-items
= nav_link(controller: [:accounts, :two_factor_auths]) do = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
= link_to profile_account_path, title: 'Account' do = link_to profile_path, title: 'Profile Settings' do
.nav-icon-container
= custom_icon('account')
%span.nav-item-name
Account
- if current_application_settings.should_check_namespace_plan?
= nav_link(controller: :billings) do
= link_to profile_billings_path, title: 'Billing' do
%span
Billing
- if current_application_settings.user_oauth_applications?
= nav_link(controller: 'oauth/applications') do
= link_to applications_profile_path, title: 'Applications' do
.nav-icon-container .nav-icon-container
= custom_icon('applications') = custom_icon('profile')
%span.nav-item-name %span.nav-item-name
Applications Profile
= nav_link(controller: :chat_names) do = nav_link(controller: [:accounts, :two_factor_auths]) do
= link_to profile_chat_names_path, title: 'Chat' do = link_to profile_account_path, title: 'Account' do
.nav-icon-container
= custom_icon('chat')
%span.nav-item-name
Chat
= nav_link(controller: :personal_access_tokens) do
= link_to profile_personal_access_tokens_path, title: 'Access Tokens' do
.nav-icon-container
= custom_icon('access_tokens')
%span.nav-item-name
Access Tokens
= nav_link(controller: :emails) do
= link_to profile_emails_path, title: 'Emails' do
.nav-icon-container
= custom_icon('emails')
%span.nav-item-name
Emails
- unless current_user.ldap_user?
= nav_link(controller: :passwords) do
= link_to edit_profile_password_path, title: 'Password' do
.nav-icon-container .nav-icon-container
= custom_icon('lock') = custom_icon('account')
%span.nav-item-name %span.nav-item-name
Password Account
= nav_link(controller: :notifications) do - if current_application_settings.should_check_namespace_plan?
= link_to profile_notifications_path, title: 'Notifications' do = nav_link(controller: :billings) do
.nav-icon-container = link_to profile_billings_path, title: 'Billing' do
= custom_icon('notifications') %span
%span.nav-item-name Billing
Notifications - if current_application_settings.user_oauth_applications?
= nav_link(controller: 'oauth/applications') do
= nav_link(controller: :keys) do = link_to applications_profile_path, title: 'Applications' do
= link_to profile_keys_path, title: 'SSH Keys' do .nav-icon-container
.nav-icon-container = custom_icon('applications')
= custom_icon('key') %span.nav-item-name
%span.nav-item-name Applications
SSH Keys = nav_link(controller: :chat_names) do
= nav_link(controller: :gpg_keys) do = link_to profile_chat_names_path, title: 'Chat' do
= link_to profile_gpg_keys_path, title: 'GPG Keys' do .nav-icon-container
.nav-icon-container = custom_icon('chat')
= custom_icon('key_2') %span.nav-item-name
%span.nav-item-name Chat
GPG Keys = nav_link(controller: :personal_access_tokens) do
= nav_link(controller: :preferences) do = link_to profile_personal_access_tokens_path, title: 'Access Tokens' do
= link_to profile_preferences_path, title: 'Preferences' do .nav-icon-container
.nav-icon-container = custom_icon('access_tokens')
= custom_icon('preferences') %span.nav-item-name
%span.nav-item-name Access Tokens
Preferences = nav_link(controller: :emails) do
= nav_link(path: 'profiles#audit_log') do = link_to profile_emails_path, title: 'Emails' do
= link_to audit_log_profile_path, title: 'Authentication log' do .nav-icon-container
.nav-icon-container = custom_icon('emails')
= custom_icon('authentication_log') %span.nav-item-name
%span.nav-item-name Emails
Authentication log - unless current_user.ldap_user?
= nav_link(path: 'profiles#pipeline_quota') do = nav_link(controller: :passwords) do
= link_to profile_pipeline_quota_path, title: 'Pipeline quota' do = link_to edit_profile_password_path, title: 'Password' do
.nav-icon-container .nav-icon-container
= custom_icon('pipeline') = custom_icon('lock')
%span.nav-item-name %span.nav-item-name
Pipeline quota Password
= nav_link(controller: :notifications) do
= link_to profile_notifications_path, title: 'Notifications' do
.nav-icon-container
= custom_icon('notifications')
%span.nav-item-name
Notifications
= nav_link(controller: :keys) do
= link_to profile_keys_path, title: 'SSH Keys' do
.nav-icon-container
= custom_icon('key')
%span.nav-item-name
SSH Keys
= nav_link(controller: :gpg_keys) do
= link_to profile_gpg_keys_path, title: 'GPG Keys' do
.nav-icon-container
= custom_icon('key_2')
%span.nav-item-name
GPG Keys
= nav_link(controller: :preferences) do
= link_to profile_preferences_path, title: 'Preferences' do
.nav-icon-container
= custom_icon('preferences')
%span.nav-item-name
Preferences
= nav_link(path: 'profiles#audit_log') do
= link_to audit_log_profile_path, title: 'Authentication log' do
.nav-icon-container
= custom_icon('authentication_log')
%span.nav-item-name
Authentication log
= nav_link(path: 'profiles#pipeline_quota') do
= link_to profile_pipeline_quota_path, title: 'Pipeline quota' do
.nav-icon-container
= custom_icon('pipeline')
%span.nav-item-name
Pipeline quota
= render 'shared/sidebar_toggle_button' = render 'shared/sidebar_toggle_button'
...@@ -92,25 +92,24 @@ ...@@ -92,25 +92,24 @@
Update username Update username
%hr %hr
- if signup_enabled? .row.prepend-top-default
.row.prepend-top-default .col-lg-4.profile-settings-sidebar
.col-lg-4.profile-settings-sidebar %h4.prepend-top-0.danger-title
%h4.prepend-top-0.danger-title Remove account
Remove account .col-lg-8
.col-lg-8 - if @user.can_be_removed? && can?(current_user, :destroy_user, @user)
- if @user.can_be_removed? && can?(current_user, :destroy_user, @user) %p
Deleting an account has the following effects:
= render 'users/deletion_guidance', user: current_user
= link_to 'Delete account', user_registration_path, data: { confirm: "REMOVE #{current_user.name}? Are you sure?" }, method: :delete, class: "btn btn-remove"
- else
- if @user.solo_owned_groups.present?
%p %p
Deleting an account has the following effects: Your account is currently an owner in these groups:
= render 'users/deletion_guidance', user: current_user %strong= @user.solo_owned_groups.map(&:name).join(', ')
= link_to 'Delete account', user_registration_path, data: { confirm: "REMOVE #{current_user.name}? Are you sure?" }, method: :delete, class: "btn btn-remove" %p
You must transfer ownership or delete these groups before you can delete your account.
- else - else
- if @user.solo_owned_groups.present? %p
%p You don't have access to delete this user.
Your account is currently an owner in these groups:
%strong= @user.solo_owned_groups.map(&:name).join(', ')
%p
You must transfer ownership or delete these groups before you can delete your account.
- else
%p
You don't have access to delete this user.
.append-bottom-default .append-bottom-default
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
Add a GPG key Add a GPG key
%p.profile-settings-content %p.profile-settings-content
Before you can add a GPG key you need to Before you can add a GPG key you need to
= link_to 'generate it.', help_page_path('workflow/gpg_signed_commits/index.md') = link_to 'generate it.', help_page_path('user/project/gpg_signed_commits/index.md')
= render 'form' = render 'form'
%hr %hr
%h5 %h5
......
%div{ class: container_class } %div{ class: container_class }
.nav-block.activity-filter-block.activities .nav-block.activity-filter-block.activities
.controls .controls
= link_to project_path(@project, rss_url_options), title: "Subscribe", class: 'btn rss-btn has-tooltip' do = link_to project_path(@project, rss_url_options), title: s_("ProjectActivityRSS|Subscribe"), class: 'btn rss-btn has-tooltip' do
= icon('rss') = icon('rss')
= render 'shared/event_filter' = render 'shared/event_filter'
......
...@@ -3,16 +3,16 @@ ...@@ -3,16 +3,16 @@
.row-content-block.top-block.hidden-xs.white .row-content-block.top-block.hidden-xs.white
.event-last-push .event-last-push
.event-last-push-text .event-last-push-text
%span You pushed to %span= s_("LastPushEvent|You pushed to")
%strong %strong
= link_to event.ref_name, project_commits_path(event.project, event.ref_name), class: 'ref-name' = link_to event.ref_name, project_commits_path(event.project, event.ref_name), class: 'ref-name'
- if event.project != @project - if event.project != @project
%span at %span= s_("LastPushEvent|at")
%strong= link_to_project event.project %strong= link_to_project event.project
#{time_ago_with_tooltip(event.created_at)} #{time_ago_with_tooltip(event.created_at)}
.pull-right .pull-right
= link_to new_mr_path_from_push_event(event), title: "New merge request", class: "btn btn-info btn-sm" do = link_to new_mr_path_from_push_event(event), title: _("New merge request"), class: "btn btn-info btn-sm" do
#{ _('Create merge request') } #{ _('Create merge request') }
...@@ -5,6 +5,6 @@ ...@@ -5,6 +5,6 @@
Blank Blank
- Gitlab::ProjectTemplate.all.each do |template| - Gitlab::ProjectTemplate.all.each do |template|
.btn .btn
%input{ type: "radio", autocomplete: "off", name: "project_templates", id: template.name } %input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name }
= custom_icon(template.logo) = custom_icon(template.logo)
= template.title = template.title
- @no_container = true - @no_container = true
- if show_new_nav? - if show_new_nav?
- add_to_breadcrumbs("Project", project_path(@project)) - add_to_breadcrumbs(_("Project"), project_path(@project))
- page_title "Activity" - page_title _("Activity")
= render "projects/head" = render "projects/head"
= render 'projects/last_push' = render 'projects/last_push'
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
%span.monospace= signature.gpg_key_primary_keyid %span.monospace= signature.gpg_key_primary_keyid
= link_to('Learn more about signing commits', help_page_path('workflow/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link') = link_to('Learn more about signing commits', help_page_path('user/project/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link')
%button{ class: css_classes, data: { toggle: 'popover', html: 'true', placement: 'auto top', title: title, content: content } } %button{ class: css_classes, data: { toggle: 'popover', html: 'true', placement: 'auto top', title: title, content: content } }
= label = label
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
- notes = commit.notes - notes = commit.notes
- note_count = notes.user.count - note_count = notes.user.count
- cache_key = [project.full_path, commit.id, current_application_settings, note_count, @path.presence, current_controller?(:commits)] - cache_key = [project.full_path, commit.id, current_application_settings, note_count, @path.presence, current_controller?(:commits), I18n.locale]
- cache_key.push(commit.status(ref)) if commit.status(ref) - cache_key.push(commit.status(ref)) if commit.status(ref)
= cache(cache_key, expires_in: 1.day) do = cache(cache_key, expires_in: 1.day) do
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
.content-block.oneline-block.files-changed.diff-files-changed.js-diff-files-changed{ class: ("diff-files-changed-merge-request" if merge_request) } .content-block.oneline-block.files-changed.diff-files-changed.js-diff-files-changed{ class: ("diff-files-changed-merge-request" if merge_request) }
.files-changed-inner .files-changed-inner
.inline-parallel-buttons .inline-parallel-buttons.hidden-xs.hidden-sm
- if !diffs_expanded? && diff_files.any? { |diff_file| diff_file.collapsed? } - if !diffs_expanded? && diff_files.any? { |diff_file| diff_file.collapsed? }
= link_to 'Expand all', url_for(params.merge(expanded: 1, format: nil)), class: 'btn btn-default' = link_to 'Expand all', url_for(params.merge(expanded: 1, format: nil)), class: 'btn btn-default'
- if show_whitespace_toggle - if show_whitespace_toggle
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
%strong.cgreen #{sum_added_lines} additions %strong.cgreen #{sum_added_lines} additions
and and
%strong.cred #{sum_removed_lines} deletions %strong.cred #{sum_removed_lines} deletions
.diff-stats-additions-deletions-collapsed.pull-right{ "aria-hidden": "true", "aria-describedby": "diff-stats" } .diff-stats-additions-deletions-collapsed.pull-right.hidden-xs.hidden-sm{ "aria-hidden": "true", "aria-describedby": "diff-stats" }
%strong.cgreen< %strong.cgreen<
+#{sum_added_lines} +#{sum_added_lines}
%strong.cred< %strong.cred<
......
- if @can_bulk_update - if @can_bulk_update
= button_tag "Edit merge requests", class: "btn js-bulk-update-toggle" = button_tag "Edit merge requests", class: "btn append-right-10 js-bulk-update-toggle"
- if merge_project - if merge_project
= link_to new_merge_request_path, class: "btn btn-new", title: "New merge request" do = link_to new_merge_request_path, class: "btn btn-new", title: "New merge request" do
New merge request New merge request
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
.form-group .form-group
= f.label :template_project, class: 'label-light' do = f.label :template_project, class: 'label-light' do
Create from template Create from template
= link_to icon('question-circle'), help_page_path("public_access/public_access"), aria: { label: "What’s included in a template?" }, title: "What’s included in a template?", class: 'has-tooltip', data: { placement: 'top'} = link_to icon('question-circle'), help_page_path("gitlab-basics/create-project"), target: '_blank', aria: { label: "What’s included in a template?" }, title: "What’s included in a template?", class: 'has-tooltip', data: { placement: 'top'}
%div %div
= render 'project_templates', f: f = render 'project_templates', f: f
.second-column .second-column
......
%ul.nav-links.event-filter.scrolling-tabs %ul.nav-links.event-filter.scrolling-tabs
= event_filter_link EventFilter.all, 'All' = event_filter_link EventFilter.all, _('All'), s_('EventFilterBy|Filter by all')
- if event_filter_visible(:repository) - if event_filter_visible(:repository)
= event_filter_link EventFilter.push, 'Push events' = event_filter_link EventFilter.push, _('Push events'), s_('EventFilterBy|Filter by push events')
- if event_filter_visible(:merge_requests) - if event_filter_visible(:merge_requests)
= event_filter_link EventFilter.merged, 'Merge events' = event_filter_link EventFilter.merged, _('Merge events'), s_('EventFilterBy|Filter by merge events')
- if event_filter_visible(:issues) - if event_filter_visible(:issues)
= event_filter_link EventFilter.issue, 'Issue events' = event_filter_link EventFilter.issue, _('Issue events'), s_('EventFilterBy|Filter by issue events')
- if comments_visible? - if comments_visible?
= event_filter_link EventFilter.comments, 'Comments' = event_filter_link EventFilter.comments, _('Comments'), s_('EventFilterBy|Filter by comments')
= event_filter_link EventFilter.team, 'Team' = event_filter_link EventFilter.team, _('Team'), s_('EventFilterBy|Filter by team')
- if any_projects?(@projects) - if any_projects?(@projects)
.project-item-select-holder.btn-group.pull-right .project-item-select-holder.btn-group.pull-right
%a.btn.btn-new.new-project-item-link{ href: '', data: { label: local_assigns[:label] } } %a.btn.btn-new.new-project-item-link{ href: '', data: { label: local_assigns[:label], type: local_assigns[:type] } }
= icon('spinner spin') = icon('spinner spin')
= project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at', relative_path: local_assigns[:path] }, with_feature_enabled: local_assigns[:with_feature_enabled] = project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at', relative_path: local_assigns[:path] }, with_feature_enabled: local_assigns[:with_feature_enabled]
%button.btn.btn-new.new-project-item-select-button %button.btn.btn-new.new-project-item-select-button
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
Issues can be bugs, tasks or ideas to be discussed. Issues can be bugs, tasks or ideas to be discussed.
Also, issues are searchable and filterable. Also, issues are searchable and filterable.
- if project_select_button - if project_select_button
= render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue' = render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue', type: :issues
- else - else
= link_to 'New issue', button_path, class: 'btn btn-new', title: 'New issue', id: 'new_issue_link' = link_to 'New issue', button_path, class: 'btn btn-new', title: 'New issue', id: 'new_issue_link'
- else - else
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
%p %p
Interested parties can even contribute by pushing commits if they want to. Interested parties can even contribute by pushing commits if they want to.
- if project_select_button - if project_select_button
= render 'shared/new_project_item_select', path: 'merge_requests/new', label: 'New merge request' = render 'shared/new_project_item_select', path: 'merge_requests/new', label: 'New merge request', type: :merge_requests
- else - else
= link_to 'New merge request', button_path, class: 'btn btn-new', title: 'New merge request', id: 'new_merge_request_link' = link_to 'New merge request', button_path, class: 'btn btn-new', title: 'New merge request', id: 'new_merge_request_link'
- else - else
......
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" d="m8.419 7.99l-.002.002c-.023-.026-.046-.051-.071-.075-.642-.642-1.678-.651-2.312-.018l-2.432 2.432c-.635.635-.626 1.668.018 2.312.642.642 1.678.651 2.312.018l1.028-1.028c.719.366 1.481.518 2.176.444l-1.753 1.753c-1.344 1.344-3.542 1.326-4.909-.041-1.367-1.367-1.383-3.566-.041-4.909l2.292-2.292c1.344-1.344 3.542-1.326 4.909.041.016.016.032.032.048.049.009.008.017.016.025.024.362.362.367.944.011 1.3-.356.356-.938.351-1.3-.011m-.575.284l.002-.002c.023.026.046.051.071.075.642.642 1.678.651 2.312.018l2.432-2.432c.635-.635.626-1.668-.018-2.312-.642-.642-1.678-.651-2.312-.018l-1.028 1.028c-.719-.366-1.481-.518-2.176-.444l1.753-1.753c1.344-1.344 3.542-1.326 4.909.041 1.367 1.367 1.383 3.566.041 4.909l-2.292 2.292c-1.344 1.344-3.542 1.326-4.909-.041-.016-.016-.032-.032-.048-.049-.009-.008-.017-.016-.025-.024-.362-.362-.367-.944-.011-1.3.356-.356.938-.351 1.3.011"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M6.986 3.35l2.12-2.122a4 4 0 0 1 5.657 5.657l-2.828 2.829a4 4 0 0 1-5.657 0 1 1 0 0 1 1.414-1.415 2 2 0 0 0 2.829 0l2.828-2.828a2 2 0 1 0-2.828-2.828l-1.001 1a5.018 5.018 0 0 0-2.534-.294zm2.12 9.192l-2.12 2.121a4 4 0 1 1-5.658-5.656l2.829-2.829a4 4 0 0 1 5.657 0 1 1 0 1 1-1.415 1.414 2 2 0 0 0-2.828 0l-2.828 2.829a2 2 0 1 0 2.828 2.828l1.001-1.001a5.018 5.018 0 0 0 2.534.294z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g fill-rule="evenodd"><path fill-rule="nonzero" d="M11.3 8.85c.2-.15.4-.3.6-.5l1.4-1.4c1.37-1.38 1.53-3.44.36-4.6-1.17-1.18-3.23-1.02-4.6.35l-1.4 1.4c-.2.2-.36.4-.5.6l1.66.66.04-.04 1.4-1.4c.6-.6 1.48-.66 1.98-.16s.44 1.38-.15 1.97l-1.44 1.4-.04.05.66 1.67zM8.85 11.3c-.15.2-.3.4-.5.6l-1.4 1.4c-1.38 1.37-3.44 1.53-4.6.36-1.18-1.17-1.02-3.23.35-4.6l1.4-1.4c.2-.2.4-.36.6-.5l.66 1.66-.04.04-1.4 1.4c-.6.6-.66 1.48-.16 1.98s1.38.44 1.97-.15l1.4-1.44.05-.04 1.67.66z"/><path d="M12.66 9.2h2c.27 0 .5.23.5.5v.06c0 .27-.23.5-.5.5h-2c-.28 0-.5-.23-.5-.5V9.7c0-.27.22-.5.5-.5zm-.4 2.12l1.43 1.42c.16.2.16.5 0 .7l-.07.04c-.2.2-.5.2-.7 0l-1.42-1.4c-.2-.2-.2-.53 0-.72l.05-.04c.2-.2.5-.2.7 0zm-2.8 1.1c0-.28.2-.5.5-.5H10c.28 0 .5.22.5.5v2c0 .27-.22.5-.5.5h-.05c-.28 0-.5-.23-.5-.5v-2zM6.7 3.24v-2c0-.27-.22-.5-.5-.5h-.05c-.27 0-.5.23-.5.5v2c0 .28.23.5.5.5h.05c.28 0 .5-.22.5-.5zm-2.1.4L3.16 2.2c-.2-.2-.5-.2-.7 0l-.04.04c-.2.2-.2.5 0 .7l1.4 1.42c.2.2.52.2.72 0l.04-.04c.18-.2.18-.5 0-.7zm-1.1 2.8c.27 0 .5-.2.5-.5V5.9c0-.27-.23-.5-.5-.5h-2c-.28 0-.5.23-.5.5v.06c0 .28.22.5.5.5h2z"/></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M11.295 8.845l-.659-1.664a1.78 1.78 0 0 0 .04-.04l1.415-1.414c.586-.586.654-1.468.152-1.97s-1.384-.434-1.97.152L8.859 5.323a1.781 1.781 0 0 0-.04.04l-1.664-.658c.141-.208.305-.408.491-.594l1.415-1.414c1.366-1.367 3.424-1.525 4.596-.354 1.171 1.172 1.013 3.23-.354 4.596L11.89 8.354c-.186.186-.386.35-.594.491zm-2.45 2.45a4.075 4.075 0 0 1-.491.594l-1.415 1.414c-1.366 1.367-3.424 1.525-4.596.354-1.171-1.172-1.013-3.23.354-4.596L4.11 7.646c.186-.186.386-.35.594-.491l.659 1.664a1.781 1.781 0 0 0-.04.04l-1.415 1.414c-.586.586-.654 1.468-.152 1.97s1.384.434 1.97-.152l1.414-1.414a1.78 1.78 0 0 0 .04-.04l1.664.658zm3.812-2.088h2a.5.5 0 0 1 .5.5v.05a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-.05a.5.5 0 0 1 .5-.5zm-.384 2.116l1.415 1.414a.5.5 0 0 1 0 .708l-.037.036a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 0-.707l.036-.037a.5.5 0 0 1 .707 0zm-2.823 1.09a.5.5 0 0 1 .5-.5h.052a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-.5.5H9.95a.5.5 0 0 1-.5-.5v-2zm-2.748-9.16a.5.5 0 0 1-.5.5h-.05a.5.5 0 0 1-.5-.5v-2a.5.5 0 0 1 .5-.5h.05a.5.5 0 0 1 .5.5v2zm-2.116.383a.5.5 0 0 1 0 .707l-.036.036a.5.5 0 0 1-.707 0L2.428 2.965a.5.5 0 0 1 0-.707l.037-.036a.5.5 0 0 1 .707 0l1.414 1.414zm-1.09 2.823h-2a.5.5 0 0 1-.5-.5v-.051a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 .5.5v.05a.5.5 0 0 1-.5.5z"/></svg>
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M10.536 10.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 1 1 9.12 9.243l1.415 1.414zM7.632 8.109A2 2 0 0 0 7 11.364l2.121 2.121a1.996 1.996 0 0 0 2.807.021C11.686 14.554 10.627 15 6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8c.6 0 1.142.038 1.632.109zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></svg>
<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1490 1322q0 40-28 68l-136 136q-28 28-68 28t-68-28l-294-294-294 294q-28 28-68 28t-68-28l-136-136q-28-28-28-68t28-68l294-294-294-294q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 294 294-294q28-28 68-28t68 28l136 136q28 28 28 68t-28 68l-294 294 294 294q28 28 28 68z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M11.95 8.536l1.06-1.061a1 1 0 0 1 1.415 1.414l-1.061 1.06 1.06 1.061a1 1 0 0 1-1.414 1.415l-1.06-1.061-1.06 1.06a1 1 0 1 1-1.415-1.414l1.06-1.06-1.06-1.06a1 1 0 0 1 1.414-1.414l1.06 1.06zm-3.768-.33c.006.503.201 1.006.586 1.39l.353.354-.353.353a2 2 0 1 0 2.828 2.829l.354-.354.047.048C11.964 14.363 11.527 15 6 15c-5.924 0-6-.78-6-2.52S.964 8 6 8c.834 0 1.557.074 2.182.205zM5.976 7a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/></svg>
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
.col-sm-6.milestone-actions .col-sm-6.milestone-actions
- if can?(current_user, :admin_milestones, @group) - if can?(current_user, :admin_milestones, @group)
- if milestone.is_group_milestone? - if milestone.is_group_milestone?
= link_to edit_group_milestone_path(@group, milestone.id), class: "btn btn-xs btn-grouped" do = link_to edit_group_milestone_path(@group, milestone), class: "btn btn-xs btn-grouped" do
Edit Edit
\ \
- if milestone.closed? - if milestone.closed?
......
- affix_offset = local_assigns.fetch(:affix_offset, "50") - affix_offset = local_assigns.fetch(:affix_offset, "50")
- project = local_assigns[:project] - project = local_assigns[:project]
%aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => affix_offset, "spy" => "affix" }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' } %aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => affix_offset, "spy" => "affix", "always-show-toggle" => true }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' }
.issuable-sidebar.milestone-sidebar .issuable-sidebar.milestone-sidebar
.block.milestone-progress.issuable-sidebar-header .block.milestone-progress.issuable-sidebar-header
%a.gutter-toggle.pull-right.js-sidebar-toggle{ role: "button", href: "#", "aria-label" => "Toggle sidebar" } %a.gutter-toggle.pull-right.js-sidebar-toggle{ role: "button", href: "#", "aria-label" => "Toggle sidebar" }
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
.pull-right .pull-right
- if can?(current_user, :admin_milestones, group) - if can?(current_user, :admin_milestones, group)
- if milestone.is_group_milestone? - if milestone.is_group_milestone?
= link_to edit_group_milestone_path(group, milestone.iid), class: "btn btn btn-grouped" do = link_to edit_group_milestone_path(group, milestone), class: "btn btn btn-grouped" do
Edit Edit
- if milestone.active? - if milestone.active?
= link_to 'Close Milestone', group_milestone_route(milestone, {state_event: :close }), method: :put, class: "btn btn-grouped btn-close" = link_to 'Close Milestone', group_milestone_route(milestone, {state_event: :close }), method: :put, class: "btn btn-grouped btn-close"
......
...@@ -4,13 +4,9 @@ class CreateGpgSignatureWorker ...@@ -4,13 +4,9 @@ class CreateGpgSignatureWorker
def perform(commit_sha, project_id) def perform(commit_sha, project_id)
project = Project.find_by(id: project_id) project = Project.find_by(id: project_id)
return unless project return unless project
commit = project.commit(commit_sha) # This calculates and caches the signature in the database
Gitlab::Gpg::Commit.new(project, commit_sha).signature
return unless commit
commit.signature
end end
end end
...@@ -24,10 +24,6 @@ class NamespacelessProjectDestroyWorker ...@@ -24,10 +24,6 @@ class NamespacelessProjectDestroyWorker
unlink_fork(project) if project.forked? unlink_fork(project) if project.forked?
# Override Project#remove_pages for this instance so it doesn't do anything
def project.remove_pages
end
project.destroy! project.destroy!
end end
......
class StageUpdateWorker
include Sidekiq::Worker
include PipelineQueue
def perform(stage_id)
Ci::Stage.find_by(id: stage_id).try do |stage|
stage.update_status
end
end
end
...@@ -5,12 +5,12 @@ class StuckImportJobsWorker ...@@ -5,12 +5,12 @@ class StuckImportJobsWorker
IMPORT_JOBS_EXPIRATION = 15.hours.to_i IMPORT_JOBS_EXPIRATION = 15.hours.to_i
def perform def perform
projects_without_jid_count = mark_projects_without_jid_as_failed! values = {
projects_with_jid_count = mark_projects_with_jid_as_failed! projects_without_jid_count: mark_projects_without_jid_as_failed!,
projects_with_jid_count: mark_projects_with_jid_as_failed!
}
Gitlab::Metrics.add_event(:stuck_import_jobs, Gitlab::Metrics.add_event_with_values(:stuck_import_jobs, values)
projects_without_jid_count: projects_without_jid_count,
projects_with_jid_count: projects_with_jid_count)
end end
private private
......
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.
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.
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.
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.
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.
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.
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.
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