Commit e04c1ae7 authored by Lin Jen-Shin's avatar Lin Jen-Shin

Merge remote-tracking branch 'upstream/master' into 36089-handle-ref-failure-better

* upstream/master: (62 commits)
  Update gitlab.po: Missing 'r' in "Fouché" that comes from "Fourcher" verb.
  Docs: update user docs index
  Fix minor typos in views
  Fix Layout/SpaceBeforeBlockBraces violation in bin/changelog_spec
  Merge branch 'rs-alphanumeric-ssh-params' into 'security-9-4'
  Merge branch 'import-symlinks-9-3' into 'security-9-3'
  Fix wrong method call on prometheus histogram
  Document new all-in-one Helm chart - docs
  Fix 404 on link path
  Fix line numbers not matching up to code in code viewer.
  Hide overflow-x on collapsed sidebar
  removed global use of breakpoint checker
  Increase performance of the breakpoint size checker
  Filter sensitive query string parameters from NGINX access logs
  Added a template for database changes
  Render new issue link in failed job as a regular link instead of a UJS one
  Include RE2 in the upgrade docs
  Remove affix plugin from issuable sidebar with new navigation
  Fix linter error
  alternative route for download archive
  ...
parents ae7c52a0 539152bc
Remove this section and replace it with a description of your MR. Also follow the
checklist below and check off any tasks that are done. If a certain task can not
be done you should explain so in the MR body. You are free to remove any
sections that do not apply to your MR.
When gathering statistics (e.g. the output of `EXPLAIN ANALYZE`) you should make
sure your database has enough data. Having around 10 000 rows in the tables
being queries should provide a reasonable estimate of how a query will behave.
Also make sure that PostgreSQL uses the following settings:
* `random_page_cost`: `1`
* `work_mem`: `16MB`
* `maintenance_work_mem`: at least `64MB`
* `shared_buffers`: at least `256MB`
If you have access to GitLab.com's staging environment you should also run your
measurements there, and include the results in this MR.
## Database Checklist
When adding migrations:
- [ ] Updated `db/schema.rb`
- [ ] Added a `down` method so the migration can be reverted
- [ ] Added the output of the migration(s) to the MR body
- [ ] Added the execution time of the migration(s) to the MR body
- [ ] Added tests for the migration in `spec/migrations` if necessary (e.g. when
migrating data)
- [ ] Made sure the migration won't interfere with a running GitLab cluster,
for example by disabling transactions for long running migrations
When adding or modifying queries to improve performance:
- [ ] Included the raw SQL queries of the relevant queries
- [ ] Included the output of `EXPLAIN ANALYZE` and execution timings of the
relevant queries
- [ ] Added tests for the relevant changes
When adding indexes:
- [ ] Described the need for these indexes in the MR body
- [ ] Made sure existing indexes can not be reused instead
When adding foreign keys to existing tables:
- [ ] Included a migration to remove orphaned rows in the source table
- [ ] Removed any instances of `dependent: ...` that may no longer be necessary
When adding tables:
- [ ] Ordered columns based on their type sizes in descending order
- [ ] Added foreign keys if necessary
- [ ] Added indexes if necessary
When removing columns, tables, indexes or other structures:
- [ ] Removed these in a post-deployment migration
- [ ] Made sure the application no longer uses (or ignores) these structures
## General Checklist
- [ ] [Changelog entry](https://docs.gitlab.com/ce/development/changelog.html) added, if necessary
- [ ] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md)
- [ ] API support added
- [ ] Tests added for this feature/bug
- Review
- [ ] Has been reviewed by UX
- [ ] Has been reviewed by Frontend
- [ ] Has been reviewed by Backend
- [ ] Has been reviewed by Database
- [ ] Conform by the [merge request performance guides](http://docs.gitlab.com/ce/development/merge_request_performance_guidelines.html)
- [ ] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides)
- [ ] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
...@@ -207,6 +207,13 @@ Layout/SpaceAroundKeyword: ...@@ -207,6 +207,13 @@ Layout/SpaceAroundKeyword:
Layout/SpaceAroundOperators: Layout/SpaceAroundOperators:
Enabled: true Enabled: true
# Checks that block braces have or don't have a space before the opening
# brace depending on configuration.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: space, no_space
Layout/SpaceBeforeBlockBraces:
Enabled: true
# No spaces before commas. # No spaces before commas.
Layout/SpaceBeforeComma: Layout/SpaceBeforeComma:
Enabled: true Enabled: true
......
...@@ -26,13 +26,6 @@ Layout/IndentArray: ...@@ -26,13 +26,6 @@ Layout/IndentArray:
Layout/IndentHash: Layout/IndentHash:
Enabled: false Enabled: false
# Offense count: 174
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: space, no_space
Layout/SpaceBeforeBlockBraces:
Enabled: false
# Offense count: 8 # Offense count: 8
# Cop supports --auto-correct. # Cop supports --auto-correct.
# Configuration parameters: AllowForAlignment. # Configuration parameters: AllowForAlignment.
......
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
documentation](doc/development/changelog.md) for instructions on adding your own documentation](doc/development/changelog.md) for instructions on adding your own
entry. entry.
## 9.4.4 (2017-08-09)
- Remove hidden symlinks from project import files.
- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
## 9.4.3 (2017-07-31) ## 9.4.3 (2017-07-31)
- Fix Prometheus client PID reuse bug. !13130 - Fix Prometheus client PID reuse bug. !13130
...@@ -226,6 +231,11 @@ entry. ...@@ -226,6 +231,11 @@ entry.
- Log rescued exceptions to Sentry. - Log rescued exceptions to Sentry.
- Remove remaining N+1 queries in merge requests API with emojis and labels. - Remove remaining N+1 queries in merge requests API with emojis and labels.
## 9.3.10 (2017-08-09)
- Remove hidden symlinks from project import files.
- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
## 9.3.9 (2017-07-20) ## 9.3.9 (2017-07-20)
- Fix an infinite loop when handling user-supplied regular expressions. - Fix an infinite loop when handling user-supplied regular expressions.
...@@ -498,6 +508,11 @@ entry. ...@@ -498,6 +508,11 @@ entry.
- Remove foreigh key on ci_trigger_schedules only if it exists. - Remove foreigh key on ci_trigger_schedules only if it exists.
- Allow translation of Pipeline Schedules. - Allow translation of Pipeline Schedules.
## 9.2.10 (2017-08-09)
- Remove hidden symlinks from project import files.
- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
## 9.2.9 (2017-07-20) ## 9.2.9 (2017-07-20)
- Fix an infinite loop when handling user-supplied regular expressions. - Fix an infinite loop when handling user-supplied regular expressions.
...@@ -753,6 +768,11 @@ entry. ...@@ -753,6 +768,11 @@ entry.
- Fix preemptive scroll bar on user activity calendar. - Fix preemptive scroll bar on user activity calendar.
- Pipeline chat notifications convert seconds to minutes and hours. - Pipeline chat notifications convert seconds to minutes and hours.
## 9.1.10 (2017-08-09)
- Remove hidden symlinks from project import files.
- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
## 9.1.9 (2017-07-20) ## 9.1.9 (2017-07-20)
- Fix an infinite loop when handling user-supplied regular expressions. - Fix an infinite loop when handling user-supplied regular expressions.
...@@ -1076,6 +1096,11 @@ entry. ...@@ -1076,6 +1096,11 @@ entry.
- Only send chat notifications for the default branch. - Only send chat notifications for the default branch.
- Don't fill in the default kubernetes namespace. - Don't fill in the default kubernetes namespace.
## 9.0.13 (2017-08-09)
- Remove hidden symlinks from project import files.
- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
## 9.0.12 (2017-07-20) ## 9.0.12 (2017-07-20)
- Fix an infinite loop when handling user-supplied regular expressions. - Fix an infinite loop when handling user-supplied regular expressions.
...@@ -1456,6 +1481,11 @@ entry. ...@@ -1456,6 +1481,11 @@ entry.
- Change development tanuki favicon colors to match logo color order. - Change development tanuki favicon colors to match logo color order.
- API issues - support filtering by iids. - API issues - support filtering by iids.
## 8.17.8 (2017-08-09)
- Remove hidden symlinks from project import files.
- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
## 8.17.7 (2017-07-19) ## 8.17.7 (2017-07-19)
- Renders 404 if given project is not readable by the user on Todos dashboard. - Renders 404 if given project is not readable by the user on Todos dashboard.
......
...@@ -744,6 +744,7 @@ GEM ...@@ -744,6 +744,7 @@ GEM
rubocop-gitlab-security (0.0.6) rubocop-gitlab-security (0.0.6)
rubocop (>= 0.47.1) rubocop (>= 0.47.1)
rubocop-rspec (1.15.1) rubocop-rspec (1.15.1)
rubocop (>= 0.42.0)
ruby-fogbugz (0.2.1) ruby-fogbugz (0.2.1)
crack (~> 0.4) crack (~> 0.4)
ruby-prof (0.16.2) ruby-prof (0.16.2)
......
...@@ -119,6 +119,12 @@ only be left until after the freeze if: ...@@ -119,6 +119,12 @@ only be left until after the freeze if:
are aware of it. are aware of it.
* It is in the correct milestone, with the ~Deliverable label. * It is in the correct milestone, with the ~Deliverable label.
If a merge request is not ready, but the developers and Product Manager
responsible for the feature think it is essential that it is in the release,
they can [ask for an exception](#asking-for-an-exception) in advance. This is
preferable to merging something that we are not confident in, but should still
be a rare case: most features can be allowed to slip a release.
All Community Edition merge requests from GitLab team members merged on the All Community Edition merge requests from GitLab team members merged on the
freeze date (the 7th) should have a corresponding Enterprise Edition merge freeze date (the 7th) should have a corresponding Enterprise Edition merge
request, even if there are no conflicts. This is to reduce the size of the request, even if there are no conflicts. This is to reduce the size of the
...@@ -128,11 +134,26 @@ information, see ...@@ -128,11 +134,26 @@ information, see
### After the 7th ### After the 7th
Once the stable branch is frozen, only fixes for [regressions](#regressions) Once the stable branch is frozen, the only MRs that can be cherry-picked into
and security issues will be cherry-picked into the stable branch. the stable branch are:
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. * Fixes for [regressions](#regressions)
If the fixes are are completed on or after the 22nd, they will be shipped in a patch for that release. * Fixes for security issues
* 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
release should have the correct milestone assigned _and_ have the label
~"Pick into Stable" set, so that release managers can find and pick them.
Merge requests without a milestone and this label will
not be merged into any stable branches.
### 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,
you can ask for an exception to be made. Exceptions require sign-off from 3 people besides the developer: you can ask for an exception to be made. Exceptions require sign-off from 3 people besides the developer:
...@@ -152,11 +173,7 @@ When in doubt, we err on the side of _not_ cherry-picking. ...@@ -152,11 +173,7 @@ When in doubt, we err on the side of _not_ cherry-picking.
For example, it is likely that an exception will be made for a trivial 1-5 line performance improvement For example, it is likely that an exception will be made for a trivial 1-5 line performance improvement
(e.g. adding a database index or adding `includes` to a query), but not for a new feature, no matter how relatively small or thoroughly tested. (e.g. adding a database index or adding `includes` to a query), but not for a new feature, no matter how relatively small or thoroughly tested.
During the feature freeze all merge requests that are meant to go into the upcoming All MRs which have had exceptions granted must be merged by the 15th.
release should have the correct milestone assigned _and_ have the label
~"Pick into Stable" set, so that release managers can find and pick them.
Merge requests without a milestone and this label will
not be merged into any stable branches.
### Regressions ### Regressions
......
/* global ListIssue */ /* global ListIssue */
/* global bp */
import Vue from 'vue'; import Vue from 'vue';
import bp from '../../../breakpoints';
const ModalStore = gl.issueBoards.ModalStore; const ModalStore = gl.issueBoards.ModalStore;
......
/* eslint-disable func-names, space-before-function-paren, wrap-iife, one-var, no-var, one-var-declaration-per-line, quotes, no-shadow, prefer-arrow-callback, prefer-template, consistent-return, no-return-assign, new-parens, no-param-reassign, max-len */ export const breakpoints = {
lg: 1200,
md: 992,
sm: 768,
xs: 0,
};
var Breakpoints = (function() { const BreakpointInstance = {
var BreakpointInstance, instance; windowWidth: () => window.innerWidth,
getBreakpointSize() {
const windowWidth = this.windowWidth();
function Breakpoints() {} const breakpoint = Object.keys(breakpoints).find(key => windowWidth > breakpoints[key]);
instance = null; return breakpoint;
},
};
BreakpointInstance = (function() { export default BreakpointInstance;
var BREAKPOINTS;
BREAKPOINTS = ["xs", "sm", "md", "lg"];
function BreakpointInstance() {
this.setup();
}
BreakpointInstance.prototype.setup = function() {
var allDeviceSelector, els;
allDeviceSelector = BREAKPOINTS.map(function(breakpoint) {
return ".device-" + breakpoint;
});
if ($(allDeviceSelector.join(",")).length) {
return;
}
// Create all the elements
els = $.map(BREAKPOINTS, function(breakpoint) {
return "<div class='device-" + breakpoint + " visible-" + breakpoint + "'></div>";
});
return $("body").append(els.join(''));
};
BreakpointInstance.prototype.visibleDevice = function() {
var allDeviceSelector;
allDeviceSelector = BREAKPOINTS.map(function(breakpoint) {
return ".device-" + breakpoint;
});
return $(allDeviceSelector.join(",")).filter(":visible");
};
BreakpointInstance.prototype.getBreakpointSize = function() {
var $visibleDevice;
$visibleDevice = this.visibleDevice;
// TODO: Consider refactoring in light of turbolinks removal.
// the page refreshed via turbolinks
if (!$visibleDevice().length) {
this.setup();
}
$visibleDevice = this.visibleDevice();
return $visibleDevice.attr("class").split("visible-")[1];
};
return BreakpointInstance;
})();
Breakpoints.get = function() {
return instance != null ? instance : instance = new BreakpointInstance;
};
return Breakpoints;
})();
$(() => { window.bp = Breakpoints.get(); });
window.Breakpoints = Breakpoints;
/* eslint-disable func-names, wrap-iife, no-use-before-define, /* eslint-disable func-names, wrap-iife, no-use-before-define,
consistent-return, prefer-rest-params */ consistent-return, prefer-rest-params */
/* global Breakpoints */
import _ from 'underscore'; import _ from 'underscore';
import bp from './breakpoints';
import { bytesToKiB } from './lib/utils/number_utils'; import { bytesToKiB } from './lib/utils/number_utils';
window.Build = (function () { window.Build = (function () {
...@@ -34,8 +33,6 @@ window.Build = (function () { ...@@ -34,8 +33,6 @@ window.Build = (function () {
this.$scrollBottomBtn = $('.js-scroll-down'); this.$scrollBottomBtn = $('.js-scroll-down');
clearTimeout(Build.timeout); clearTimeout(Build.timeout);
// Init breakpoint checker
this.bp = Breakpoints.get();
this.initSidebar(); this.initSidebar();
this.populateJobs(this.buildStage); this.populateJobs(this.buildStage);
...@@ -230,7 +227,7 @@ window.Build = (function () { ...@@ -230,7 +227,7 @@ window.Build = (function () {
}; };
Build.prototype.shouldHideSidebarForViewport = function () { Build.prototype.shouldHideSidebarForViewport = function () {
const bootstrapBreakpoint = this.bp.getBreakpointSize(); const bootstrapBreakpoint = bp.getBreakpointSize();
return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm'; return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm';
}; };
......
...@@ -76,6 +76,7 @@ import initLegacyFilters from './init_legacy_filters'; ...@@ -76,6 +76,7 @@ import initLegacyFilters from './init_legacy_filters';
import initIssuableSidebar from './init_issuable_sidebar'; import initIssuableSidebar from './init_issuable_sidebar';
import GpgBadges from './gpg_badges'; import GpgBadges from './gpg_badges';
import UserFeatureHelper from './helpers/user_feature_helper'; import UserFeatureHelper from './helpers/user_feature_helper';
import initChangesDropdown from './init_changes_dropdown';
(function() { (function() {
var Dispatcher; var Dispatcher;
...@@ -228,6 +229,7 @@ import UserFeatureHelper from './helpers/user_feature_helper'; ...@@ -228,6 +229,7 @@ import UserFeatureHelper from './helpers/user_feature_helper';
break; break;
case 'projects:compare:show': case 'projects:compare:show':
new gl.Diff(); new gl.Diff();
initChangesDropdown();
break; break;
case 'projects:branches:new': case 'projects:branches:new':
case 'projects:branches:create': case 'projects:branches:create':
...@@ -320,6 +322,7 @@ import UserFeatureHelper from './helpers/user_feature_helper'; ...@@ -320,6 +322,7 @@ import UserFeatureHelper from './helpers/user_feature_helper';
container: '.js-commit-pipeline-graph', container: '.js-commit-pipeline-graph',
}).bindEvents(); }).bindEvents();
initNotes(); initNotes();
initChangesDropdown();
$('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath); $('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
break; break;
case 'projects:commit:pipelines': case 'projects:commit:pipelines':
......
/* eslint-disable wrap-iife, func-names, space-before-function-paren, comma-dangle, prefer-template, consistent-return, class-methods-use-this, arrow-body-style, no-unused-vars, no-underscore-dangle, no-new, max-len, no-sequences, no-unused-expressions, no-param-reassign */ /* eslint-disable wrap-iife, func-names, space-before-function-paren, comma-dangle, prefer-template, consistent-return, class-methods-use-this, arrow-body-style, no-unused-vars, no-underscore-dangle, no-new, max-len, no-sequences, no-unused-expressions, no-param-reassign */
/* global dateFormat */ /* global dateFormat */
/* global Pikaday */
import Pikaday from 'pikaday';
import DateFix from './lib/utils/datefix'; import DateFix from './lib/utils/datefix';
class DueDateSelect { class DueDateSelect {
......
/* global bp */
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import './breakpoints'; import bp from './breakpoints';
export const canShowActiveSubItems = (el) => { export const canShowActiveSubItems = (el) => {
const isHiddenByMedia = bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md'; const isHiddenByMedia = bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md';
...@@ -49,7 +48,8 @@ export const hideSubLevelItems = (el) => { ...@@ -49,7 +48,8 @@ export const hideSubLevelItems = (el) => {
el.classList.remove('is-showing-fly-out'); el.classList.remove('is-showing-fly-out');
el.classList.remove('is-over'); el.classList.remove('is-over');
subItems.style.display = 'none'; subItems.style.display = '';
subItems.style.transform = '';
subItems.classList.remove('is-above'); subItems.classList.remove('is-above');
}; };
......
import stickyMonitor from './lib/utils/sticky';
export default () => {
stickyMonitor(document.querySelector('.js-diff-files-changed'));
$('.js-diff-stats-dropdown').glDropdown({
filterable: true,
remoteFilter: false,
});
};
/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-new, comma-dangle, quotes, prefer-arrow-callback, consistent-return, one-var, no-var, one-var-declaration-per-line, no-underscore-dangle, max-len */ /* eslint-disable func-names, space-before-function-paren, wrap-iife, no-new, comma-dangle, quotes, prefer-arrow-callback, consistent-return, one-var, no-var, one-var-declaration-per-line, no-underscore-dangle, max-len */
/* global bp */
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import bp from './breakpoints';
import UsersSelect from './users_select'; import UsersSelect from './users_select';
const PARTICIPANTS_ROW_COUNT = 7; const PARTICIPANTS_ROW_COUNT = 7;
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
/* global GitLab */ /* global GitLab */
/* global Autosave */ /* global Autosave */
/* global dateFormat */ /* global dateFormat */
/* global Pikaday */
import Pikaday from 'pikaday';
import UsersSelect from './users_select'; import UsersSelect from './users_select';
import GfmAutoComplete from './gfm_auto_complete'; import GfmAutoComplete from './gfm_auto_complete';
import ZenMode from './zen_mode'; import ZenMode from './zen_mode';
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
label: 'New issue', label: 'New issue',
path: this.job.new_issue_path, path: this.job.new_issue_path,
cssClass: 'js-new-issue btn btn-new btn-inverted visible-md-block visible-lg-block', cssClass: 'js-new-issue btn btn-new btn-inverted visible-md-block visible-lg-block',
type: 'ujs-link', type: 'link',
}); });
} }
......
/* eslint-disable func-names, space-before-function-paren, no-var, quotes, consistent-return, prefer-arrow-callback, comma-dangle, object-shorthand, no-new, max-len, no-multi-spaces, import/newline-after-import, import/first */ /* eslint-disable func-names, space-before-function-paren, no-var, quotes, consistent-return, prefer-arrow-callback, comma-dangle, object-shorthand, no-new, max-len, no-multi-spaces, import/newline-after-import, import/first */
/* global bp */
/* global Flash */ /* global Flash */
/* global ConfirmDangerModal */ /* global ConfirmDangerModal */
/* global Aside */ /* global Aside */
...@@ -7,7 +6,6 @@ ...@@ -7,7 +6,6 @@
import jQuery from 'jquery'; import jQuery from 'jquery';
import _ from 'underscore'; import _ from 'underscore';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import Pikaday from 'pikaday';
import Dropzone from 'dropzone'; import Dropzone from 'dropzone';
import Sortable from 'vendor/Sortable'; import Sortable from 'vendor/Sortable';
...@@ -20,7 +18,6 @@ import 'vendor/fuzzaldrin-plus'; ...@@ -20,7 +18,6 @@ import 'vendor/fuzzaldrin-plus';
window.jQuery = jQuery; window.jQuery = jQuery;
window.$ = jQuery; window.$ = jQuery;
window._ = _; window._ = _;
window.Pikaday = Pikaday;
window.Dropzone = Dropzone; window.Dropzone = Dropzone;
window.Sortable = Sortable; window.Sortable = Sortable;
...@@ -68,7 +65,7 @@ import './api'; ...@@ -68,7 +65,7 @@ import './api';
import './aside'; import './aside';
import './autosave'; import './autosave';
import loadAwardsHandler from './awards_handler'; import loadAwardsHandler from './awards_handler';
import './breakpoints'; import bp from './breakpoints';
import './broadcast_message'; import './broadcast_message';
import './build'; import './build';
import './build_artifacts'; import './build_artifacts';
......
/* global Pikaday */
/* global dateFormat */ /* global dateFormat */
import Pikaday from 'pikaday';
(() => { (() => {
// Add datepickers to all `js-access-expiration-date` elements. If those elements are // Add datepickers to all `js-access-expiration-date` elements. If those elements are
// children of an element with the `clearable-input` class, and have a sibling // children of an element with the `clearable-input` class, and have a sibling
......
/* eslint-disable no-new, class-methods-use-this */ /* eslint-disable no-new, class-methods-use-this */
/* global Breakpoints */
/* global Flash */ /* global Flash */
/* global notes */ /* global notes */
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import './breakpoints';
import './flash'; import './flash';
import BlobForkSuggestion from './blob/blob_fork_suggestion'; import BlobForkSuggestion from './blob/blob_fork_suggestion';
import stickyMonitor from './lib/utils/sticky'; import initChangesDropdown from './init_changes_dropdown';
import bp from './breakpoints';
/* eslint-disable max-len */ /* eslint-disable max-len */
// MergeRequestTabs // MergeRequestTabs
...@@ -134,7 +133,7 @@ import stickyMonitor from './lib/utils/sticky'; ...@@ -134,7 +133,7 @@ import stickyMonitor from './lib/utils/sticky';
this.destroyPipelinesView(); this.destroyPipelinesView();
} else if (this.isDiffAction(action)) { } else if (this.isDiffAction(action)) {
this.loadDiff($target.attr('href')); this.loadDiff($target.attr('href'));
if (Breakpoints.get().getBreakpointSize() !== 'lg') { if (bp.getBreakpointSize() !== 'lg') {
this.shrinkView(); this.shrinkView();
} }
if (this.diffViewType() === 'parallel') { if (this.diffViewType() === 'parallel') {
...@@ -145,7 +144,7 @@ import stickyMonitor from './lib/utils/sticky'; ...@@ -145,7 +144,7 @@ import stickyMonitor from './lib/utils/sticky';
this.resetViewContainer(); this.resetViewContainer();
this.mountPipelinesView(); this.mountPipelinesView();
} else { } else {
if (Breakpoints.get().getBreakpointSize() !== 'xs') { if (bp.getBreakpointSize() !== 'xs') {
this.expandView(); this.expandView();
} }
this.resetViewContainer(); this.resetViewContainer();
...@@ -267,9 +266,7 @@ import stickyMonitor from './lib/utils/sticky'; ...@@ -267,9 +266,7 @@ import stickyMonitor from './lib/utils/sticky';
const $container = $('#diffs'); const $container = $('#diffs');
$container.html(data.html); $container.html(data.html);
this.initChangesDropdown(); initChangesDropdown();
stickyMonitor(document.querySelector('.js-diff-files-changed'));
if (typeof gl.diffNotesCompileComponents !== 'undefined') { if (typeof gl.diffNotesCompileComponents !== 'undefined') {
gl.diffNotesCompileComponents(); gl.diffNotesCompileComponents();
...@@ -319,13 +316,6 @@ import stickyMonitor from './lib/utils/sticky'; ...@@ -319,13 +316,6 @@ import stickyMonitor from './lib/utils/sticky';
}); });
} }
initChangesDropdown() {
$('.js-diff-stats-dropdown').glDropdown({
filterable: true,
remoteFilter: false,
});
}
// Show or hide the loading spinner // Show or hide the loading spinner
// //
// status - Boolean, true to show, false to hide // status - Boolean, true to show, false to hide
...@@ -401,7 +391,7 @@ import stickyMonitor from './lib/utils/sticky'; ...@@ -401,7 +391,7 @@ import stickyMonitor from './lib/utils/sticky';
// Screen space on small screens is usually very sparse // Screen space on small screens is usually very sparse
// So we dont affix the tabs on these // So we dont affix the tabs on these
if (Breakpoints.get().getBreakpointSize() === 'xs' || !$tabs.length) return; if (bp.getBreakpointSize() === 'xs' || !$tabs.length) return;
/** /**
If the browser does not support position sticky, it returns the position as static. If the browser does not support position sticky, it returns the position as static.
......
<script> <script>
/* global Breakpoints */
import d3 from 'd3'; import d3 from 'd3';
import monitoringLegends from './monitoring_legends.vue'; import monitoringLegends from './monitoring_legends.vue';
import monitoringFlag from './monitoring_flag.vue'; import monitoringFlag from './monitoring_flag.vue';
...@@ -8,6 +7,7 @@ ...@@ -8,6 +7,7 @@
import eventHub from '../event_hub'; import eventHub from '../event_hub';
import measurements from '../utils/measurements'; import measurements from '../utils/measurements';
import { formatRelevantDigits } from '../../lib/utils/number_utils'; import { formatRelevantDigits } from '../../lib/utils/number_utils';
import bp from '../../breakpoints';
const bisectDate = d3.bisector(d => d.time).left; const bisectDate = d3.bisector(d => d.time).left;
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
yScale: {}, yScale: {},
margin: {}, margin: {},
data: [], data: [],
breakpointHandler: Breakpoints.get(),
unitOfDisplay: '', unitOfDisplay: '',
areaColorRgb: '#8fbce8', areaColorRgb: '#8fbce8',
lineColorRgb: '#1f78d1', lineColorRgb: '#1f78d1',
...@@ -96,7 +95,7 @@ ...@@ -96,7 +95,7 @@
methods: { methods: {
draw() { draw() {
const breakpointSize = this.breakpointHandler.getBreakpointSize(); const breakpointSize = bp.getBreakpointSize();
const query = this.columnData.queries[0]; const query = this.columnData.queries[0];
this.margin = measurements.large.margin; this.margin = measurements.large.margin;
if (breakpointSize === 'xs' || breakpointSize === 'sm') { if (breakpointSize === 'xs' || breakpointSize === 'sm') {
......
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import _ from 'underscore'; import _ from 'underscore';
/* global bp */ import bp from './breakpoints';
import './breakpoints';
export default class NewNavSidebar { export default class NewNavSidebar {
constructor() { constructor() {
......
import _ from 'underscore'; import _ from 'underscore';
import Cookies from 'js-cookie';
export default { export default {
init() { init() {
if (!this.initialized) { if (!this.initialized) {
if (Cookies.get('new_nav') === 'true' && $('.js-issuable-sidebar').length) return;
this.$window = $(window); this.$window = $(window);
this.$rightSidebar = $('.js-right-sidebar'); this.$rightSidebar = $('.js-right-sidebar');
this.$navHeight = $('.navbar-gitlab').outerHeight() + this.$navHeight = $('.navbar-gitlab').outerHeight() +
......
...@@ -120,7 +120,7 @@ export default { ...@@ -120,7 +120,7 @@ export default {
</a> </a>
<a <a
v-if="action.type === 'ujs-link'" v-else-if="action.type === 'ujs-link'"
:href="action.path" :href="action.path"
data-method="post" data-method="post"
rel="nofollow" rel="nofollow"
...@@ -129,7 +129,7 @@ export default { ...@@ -129,7 +129,7 @@ export default {
</a> </a>
<button <button
v-else="action.type === 'button'" v-else-if="action.type === 'button'"
@click="onClickAction(action)" @click="onClickAction(action)"
:disabled="action.isLoading" :disabled="action.isLoading"
:class="action.cssClass" :class="action.cssClass"
......
/* global Breakpoints */ import bp from './breakpoints';
import './breakpoints';
export default class Wikis { export default class Wikis {
constructor() { constructor() {
this.bp = Breakpoints.get();
this.sidebarEl = document.querySelector('.js-wiki-sidebar'); this.sidebarEl = document.querySelector('.js-wiki-sidebar');
this.sidebarExpanded = false; this.sidebarExpanded = false;
...@@ -41,15 +38,15 @@ export default class Wikis { ...@@ -41,15 +38,15 @@ export default class Wikis {
this.renderSidebar(); this.renderSidebar();
} }
sidebarCanCollapse() { static sidebarCanCollapse() {
const bootstrapBreakpoint = this.bp.getBreakpointSize(); const bootstrapBreakpoint = bp.getBreakpointSize();
return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm'; return bootstrapBreakpoint === 'xs' || bootstrapBreakpoint === 'sm';
} }
renderSidebar() { renderSidebar() {
if (!this.sidebarEl) return; if (!this.sidebarEl) return;
const { classList } = this.sidebarEl; const { classList } = this.sidebarEl;
if (this.sidebarExpanded || !this.sidebarCanCollapse()) { if (this.sidebarExpanded || !Wikis.sidebarCanCollapse()) {
if (!classList.contains('right-sidebar-expanded')) { if (!classList.contains('right-sidebar-expanded')) {
classList.remove('right-sidebar-collapsed'); classList.remove('right-sidebar-collapsed');
classList.add('right-sidebar-expanded'); classList.add('right-sidebar-expanded');
......
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
font-family: $monospace_font; font-family: $monospace_font;
display: block; display: block;
font-size: $code_font_size !important; font-size: $code_font_size !important;
line-height: 19px; min-height: 19px;
white-space: nowrap; white-space: nowrap;
i { i {
......
...@@ -103,12 +103,16 @@ $new-sidebar-collapsed-width: 50px; ...@@ -103,12 +103,16 @@ $new-sidebar-collapsed-width: 50px;
&.sidebar-icons-only { &.sidebar-icons-only {
width: $new-sidebar-collapsed-width; width: $new-sidebar-collapsed-width;
overflow-x: hidden;
.nav-item-name,
.badge, .badge,
.project-title { .project-title {
display: none; display: none;
} }
.nav-item-name {
opacity: 0;
}
} }
&.nav-sidebar-expanded { &.nav-sidebar-expanded {
...@@ -182,7 +186,7 @@ $new-sidebar-collapsed-width: 50px; ...@@ -182,7 +186,7 @@ $new-sidebar-collapsed-width: 50px;
> li { > li {
a { a {
padding: 8px 16px 8px 50px; padding: 8px 16px 8px 40px;
&:hover, &:hover,
&:focus { &:focus {
...@@ -215,6 +219,10 @@ $new-sidebar-collapsed-width: 50px; ...@@ -215,6 +219,10 @@ $new-sidebar-collapsed-width: 50px;
&:hover { &:hover {
color: $gl-text-color; color: $gl-text-color;
svg {
fill: $gl-text-color;
}
} }
} }
...@@ -301,6 +309,7 @@ $new-sidebar-collapsed-width: 50px; ...@@ -301,6 +309,7 @@ $new-sidebar-collapsed-width: 50px;
> a { > a {
margin-left: 4px; margin-left: 4px;
padding-left: 12px;
} }
.badge { .badge {
...@@ -361,7 +370,7 @@ $new-sidebar-collapsed-width: 50px; ...@@ -361,7 +370,7 @@ $new-sidebar-collapsed-width: 50px;
.sidebar-icons-only { .sidebar-icons-only {
.context-header { .context-header {
height: 60px; height: 61px;
a { a {
padding: 10px 4px; padding: 10px 4px;
......
...@@ -574,10 +574,14 @@ ...@@ -574,10 +574,14 @@
@media (min-width: $screen-sm-min) { @media (min-width: $screen-sm-min) {
position: -webkit-sticky; position: -webkit-sticky;
position: sticky; position: sticky;
top: 84px; top: 34px;
background-color: $white-light; background-color: $white-light;
z-index: 190; z-index: 190;
&.diff-files-changed-merge-request {
top: 84px;
}
+ .files, + .files,
+ .alert { + .alert {
margin-top: 1px; margin-top: 1px;
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
.commit-box, .commit-box,
.info-well, .info-well,
.commit-ci-menu, .commit-ci-menu,
.files-changed, .files-changed-inner,
.limited-header-width, .limited-header-width,
.limited-width-notes { .limited-width-notes {
@extend .fixed-width-container; @extend .fixed-width-container;
......
...@@ -566,14 +566,14 @@ a.deploy-project-label { ...@@ -566,14 +566,14 @@ a.deploy-project-label {
&::before { &::before {
content: "OR"; content: "OR";
position: absolute; position: absolute;
left: 0; left: -10px;
top: 40%; top: 50%;
z-index: 10; z-index: 10;
padding: 8px 0; padding: 8px 0;
text-align: center; text-align: center;
background-color: $white-light; background-color: $white-light;
color: $gl-text-color-tertiary; color: $gl-text-color-tertiary;
transform: translateX(-50%); transform: translateY(-50%);
font-size: 12px; font-size: 12px;
font-weight: bold; font-weight: bold;
line-height: 20px; line-height: 20px;
...@@ -581,8 +581,8 @@ a.deploy-project-label { ...@@ -581,8 +581,8 @@ a.deploy-project-label {
// Mobile // Mobile
@media (max-width: $screen-xs-max) { @media (max-width: $screen-xs-max) {
left: 50%; left: 50%;
top: 10px; top: 0;
transform: translateY(-50%); transform: translateX(-50%);
padding: 0 8px; padding: 0 8px;
} }
} }
......
...@@ -117,7 +117,7 @@ class ApplicationController < ActionController::Base ...@@ -117,7 +117,7 @@ class ApplicationController < ActionController::Base
Raven.capture_exception(exception) if sentry_enabled? Raven.capture_exception(exception) if sentry_enabled?
application_trace = ActionDispatch::ExceptionWrapper.new(env, exception).application_trace application_trace = ActionDispatch::ExceptionWrapper.new(env, exception).application_trace
application_trace.map!{ |t| " #{t}\n" } application_trace.map! { |t| " #{t}\n" }
logger.error "\n#{exception.class.name} (#{exception.message}):\n#{application_trace.join}" logger.error "\n#{exception.class.name} (#{exception.message}):\n#{application_trace.join}"
end end
......
...@@ -15,7 +15,7 @@ class Import::GitlabController < Import::BaseController ...@@ -15,7 +15,7 @@ class Import::GitlabController < Import::BaseController
@already_added_projects = current_user.created_projects.where(import_type: "gitlab") @already_added_projects = current_user.created_projects.where(import_type: "gitlab")
already_added_projects_names = @already_added_projects.pluck(:import_source) already_added_projects_names = @already_added_projects.pluck(:import_source)
@repos = @repos.to_a.reject{ |repo| already_added_projects_names.include? repo["path_with_namespace"] } @repos = @repos.to_a.reject { |repo| already_added_projects_names.include? repo["path_with_namespace"] }
end end
def jobs def jobs
......
...@@ -257,18 +257,6 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -257,18 +257,6 @@ class Projects::IssuesController < Projects::ApplicationController
return render_404 unless @project.feature_available?(:issues, current_user) return render_404 unless @project.feature_available?(:issues, current_user)
end end
def redirect_to_external_issue_tracker
external = @project.external_issue_tracker
return unless external
if action_name == 'new'
redirect_to external.new_issue_path
else
redirect_to external.issue_tracker_path
end
end
def issue_params def issue_params
params.require(:issue).permit(*issue_params_attributes) params.require(:issue).permit(*issue_params_attributes)
end end
......
...@@ -3,7 +3,7 @@ module GraphHelper ...@@ -3,7 +3,7 @@ module GraphHelper
refs = "" refs = ""
# Commit::ref_names already strips the refs/XXX from important refs (e.g. refs/heads/XXX) # Commit::ref_names already strips the refs/XXX from important refs (e.g. refs/heads/XXX)
# so anything leftover is internally used by GitLab # so anything leftover is internally used by GitLab
commit_refs = commit.ref_names(repo).reject{ |name| name.starts_with?('refs/') } commit_refs = commit.ref_names(repo).reject { |name| name.starts_with?('refs/') }
refs << commit_refs.join(' ') refs << commit_refs.join(' ')
# append note count # append note count
......
...@@ -151,7 +151,7 @@ module IssuablesHelper ...@@ -151,7 +151,7 @@ module IssuablesHelper
end end
def issuable_labels_tooltip(labels, limit: 5) def issuable_labels_tooltip(labels, limit: 5)
first, last = labels.partition.with_index{ |_, i| i < limit } first, last = labels.partition.with_index { |_, i| i < limit }
label_names = first.collect(&:name) label_names = first.collect(&:name)
label_names << "and #{last.size} more" unless last.empty? label_names << "and #{last.size} more" unless last.empty?
...@@ -329,7 +329,7 @@ module IssuablesHelper ...@@ -329,7 +329,7 @@ module IssuablesHelper
end end
def selected_template(issuable) def selected_template(issuable)
params[:issuable_template] if issuable_templates(issuable).any?{ |template| template[:name] == params[:issuable_template] } params[:issuable_template] if issuable_templates(issuable).any? { |template| template[:name] == params[:issuable_template] }
end end
def issuable_todo_button_data(issuable, todo, is_collapsed) def issuable_todo_button_data(issuable, todo, is_collapsed)
......
...@@ -206,7 +206,7 @@ module Network ...@@ -206,7 +206,7 @@ module Network
# Visit branching chains # Visit branching chains
leaves.each do |l| leaves.each do |l|
parents = l.parents(@map).select{|p| p.space.zero?} parents = l.parents(@map).select {|p| p.space.zero?}
parents.each do |p| parents.each do |p|
place_chain(p, l.time) place_chain(p, l.time)
end end
......
...@@ -77,20 +77,20 @@ class Note < ActiveRecord::Base ...@@ -77,20 +77,20 @@ class Note < ActiveRecord::Base
# Scopes # Scopes
scope :for_commit_id, ->(commit_id) { where(noteable_type: "Commit", commit_id: commit_id) } scope :for_commit_id, ->(commit_id) { where(noteable_type: "Commit", commit_id: commit_id) }
scope :system, ->{ where(system: true) } scope :system, -> { where(system: true) }
scope :user, ->{ where(system: false) } scope :user, -> { where(system: false) }
scope :common, ->{ where(noteable_type: ["", nil]) } scope :common, -> { where(noteable_type: ["", nil]) }
scope :fresh, ->{ order(created_at: :asc, id: :asc) } scope :fresh, -> { order(created_at: :asc, id: :asc) }
scope :updated_after, ->(time){ where('updated_at > ?', time) } scope :updated_after, ->(time) { where('updated_at > ?', time) }
scope :inc_author_project, ->{ includes(:project, :author) } scope :inc_author_project, -> { includes(:project, :author) }
scope :inc_author, ->{ includes(:author) } scope :inc_author, -> { includes(:author) }
scope :inc_relations_for_view, -> do scope :inc_relations_for_view, -> do
includes(:project, :author, :updated_by, :resolved_by, :award_emoji, :system_note_metadata) includes(:project, :author, :updated_by, :resolved_by, :award_emoji, :system_note_metadata)
end end
scope :diff_notes, ->{ where(type: %w(LegacyDiffNote DiffNote)) } scope :diff_notes, -> { where(type: %w(LegacyDiffNote DiffNote)) }
scope :new_diff_notes, ->{ where(type: 'DiffNote') } scope :new_diff_notes, -> { where(type: 'DiffNote') }
scope :non_diff_notes, ->{ where(type: ['Note', 'DiscussionNote', nil]) } scope :non_diff_notes, -> { where(type: ['Note', 'DiscussionNote', nil]) }
scope :with_associations, -> do scope :with_associations, -> do
# FYI noteable cannot be loaded for LegacyDiffNote for commits # FYI noteable cannot be loaded for LegacyDiffNote for commits
......
...@@ -8,5 +8,13 @@ class RedirectRoute < ActiveRecord::Base ...@@ -8,5 +8,13 @@ class RedirectRoute < ActiveRecord::Base
presence: true, presence: true,
uniqueness: { case_sensitive: false } uniqueness: { case_sensitive: false }
scope :matching_path_and_descendants, -> (path) { where('redirect_routes.path = ? OR redirect_routes.path LIKE ?', path, "#{sanitize_sql_like(path)}/%") } scope :matching_path_and_descendants, -> (path) do
wheres = if Gitlab::Database.postgresql?
'LOWER(redirect_routes.path) = LOWER(?) OR LOWER(redirect_routes.path) LIKE LOWER(?)'
else
'redirect_routes.path = ? OR redirect_routes.path LIKE ?'
end
where(wheres, path, "#{sanitize_sql_like(path)}/%")
end
end end
...@@ -148,6 +148,8 @@ class User < ActiveRecord::Base ...@@ -148,6 +148,8 @@ class User < ActiveRecord::Base
uniqueness: { case_sensitive: false } uniqueness: { case_sensitive: false }
validate :namespace_uniq, if: :username_changed? validate :namespace_uniq, if: :username_changed?
validate :namespace_move_dir_allowed, if: :username_changed?
validate :avatar_type, if: ->(user) { user.avatar.present? && user.avatar_changed? } validate :avatar_type, if: ->(user) { user.avatar.present? && user.avatar_changed? }
validate :unique_email, if: :email_changed? validate :unique_email, if: :email_changed?
validate :owns_notification_email, if: :notification_email_changed? validate :owns_notification_email, if: :notification_email_changed?
...@@ -487,6 +489,12 @@ class User < ActiveRecord::Base ...@@ -487,6 +489,12 @@ class User < ActiveRecord::Base
end end
end end
def namespace_move_dir_allowed
if namespace&.any_project_has_container_registry_tags?
errors.add(:username, 'cannot be changed if a personal project has container registry tags.')
end
end
def avatar_type def avatar_type
unless avatar.image? unless avatar.image?
errors.add :avatar, "only images allowed" errors.add :avatar, "only images allowed"
......
...@@ -85,13 +85,13 @@ module Ci ...@@ -85,13 +85,13 @@ module Ci
end end
def register_failure def register_failure
failed_attempt_counter.increase failed_attempt_counter.increment
attempt_counter.increase attempt_counter.increment
end end
def register_success(job) def register_success(job)
job_queue_duration_seconds.observe({ shared_runner: @runner.shared? }, Time.now - job.created_at) job_queue_duration_seconds.observe({ shared_runner: @runner.shared? }, Time.now - job.created_at)
attempt_counter.increase attempt_counter.increment
end end
def failed_attempt_counter def failed_attempt_counter
......
...@@ -16,6 +16,7 @@ module Issues ...@@ -16,6 +16,7 @@ module Issues
spam_check(issue, current_user) spam_check(issue, current_user)
issue.move_to_end issue.move_to_end
# current_user (defined in BaseService) is not available within run_after_commit block
user = current_user user = current_user
issue.run_after_commit do issue.run_after_commit do
NewIssueWorker.perform_async(issue.id, user.id) NewIssueWorker.perform_async(issue.id, user.id)
......
...@@ -17,6 +17,7 @@ module MergeRequests ...@@ -17,6 +17,7 @@ module MergeRequests
end end
def before_create(merge_request) def before_create(merge_request)
# current_user (defined in BaseService) is not available within run_after_commit block
user = current_user user = current_user
merge_request.run_after_commit do merge_request.run_after_commit do
NewMergeRequestWorker.perform_async(merge_request.id, user.id) NewMergeRequestWorker.perform_async(merge_request.id, user.id)
......
...@@ -172,11 +172,11 @@ module Projects ...@@ -172,11 +172,11 @@ module Projects
end end
def register_attempt def register_attempt
pages_deployments_total_counter.increase pages_deployments_total_counter.increment
end end
def register_failure def register_failure
pages_deployments_failed_total_counter.increase pages_deployments_failed_total_counter.increment
end end
def pages_deployments_total_counter def pages_deployments_total_counter
......
...@@ -28,6 +28,6 @@ ...@@ -28,6 +28,6 @@
%h3.blank-state-title %h3.blank-state-title
Create a group Create a group
%p.blank-state-text %p.blank-state-text
Groups are a great way to organise projects and people. Groups are a great way to organize projects and people.
= link_to new_group_path, class: "btn btn-new" do = link_to new_group_path, class: "btn btn-new" do
New group New group
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
Customize how FogBugz email addresses and usernames are imported into GitLab. Customize how FogBugz email addresses and usernames are imported into GitLab.
In the next step, you'll be able to select the projects you want to import. In the next step, you'll be able to select the projects you want to import.
%p %p
The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames wil be imported into GitLab. You can change this by populating the table below. The user map is a mapping of the FogBugz users that participated on your projects to the way their email address and usernames will be imported into GitLab. You can change this by populating the table below.
%ul %ul
%li %li
%strong Default: Map a FogBugz account ID to a full name %strong Default: Map a FogBugz account ID to a full name
......
...@@ -2,22 +2,24 @@ ...@@ -2,22 +2,24 @@
- show_whitespace_toggle = local_assigns.fetch(:show_whitespace_toggle, true) - show_whitespace_toggle = local_assigns.fetch(:show_whitespace_toggle, true)
- can_create_note = !@diff_notes_disabled && can?(current_user, :create_note, diffs.project) - can_create_note = !@diff_notes_disabled && can?(current_user, :create_note, diffs.project)
- diff_files = diffs.diff_files - diff_files = diffs.diff_files
- merge_request = local_assigns.fetch(:merge_request, false)
.content-block.oneline-block.files-changed.diff-files-changed.js-diff-files-changed .content-block.oneline-block.files-changed.diff-files-changed.js-diff-files-changed{ class: ("diff-files-changed-merge-request" if merge_request) }
.inline-parallel-buttons .files-changed-inner
- if !diffs_expanded? && diff_files.any? { |diff_file| diff_file.collapsed? } .inline-parallel-buttons
= link_to 'Expand all', url_for(params.merge(expanded: 1, format: nil)), class: 'btn btn-default' - if !diffs_expanded? && diff_files.any? { |diff_file| diff_file.collapsed? }
- if show_whitespace_toggle = link_to 'Expand all', url_for(params.merge(expanded: 1, format: nil)), class: 'btn btn-default'
- if current_controller?(:commit) - if show_whitespace_toggle
= commit_diff_whitespace_link(diffs.project, @commit, class: 'hidden-xs') - if current_controller?(:commit)
- elsif current_controller?('projects/merge_requests/diffs') = commit_diff_whitespace_link(diffs.project, @commit, class: 'hidden-xs')
= diff_merge_request_whitespace_link(diffs.project, @merge_request, class: 'hidden-xs') - elsif current_controller?('projects/merge_requests/diffs')
- elsif current_controller?(:compare) = diff_merge_request_whitespace_link(diffs.project, @merge_request, class: 'hidden-xs')
= diff_compare_whitespace_link(diffs.project, params[:from], params[:to], class: 'hidden-xs') - elsif current_controller?(:compare)
.btn-group = diff_compare_whitespace_link(diffs.project, params[:from], params[:to], class: 'hidden-xs')
= inline_diff_btn .btn-group
= parallel_diff_btn = inline_diff_btn
= render 'projects/diffs/stats', diff_files: diff_files = parallel_diff_btn
= render 'projects/diffs/stats', diff_files: diff_files
- if render_overflow_warning?(diff_files) - if render_overflow_warning?(diff_files)
= render 'projects/diffs/warning', diff_files: diffs = render 'projects/diffs/warning', diff_files: diffs
......
...@@ -205,7 +205,7 @@ ...@@ -205,7 +205,7 @@
%button.btn.js-settings-toggle %button.btn.js-settings-toggle
= expanded ? 'Collapse' : 'Expand' = expanded ? 'Collapse' : 'Expand'
%p %p
Perform advanced options such as housekeeping, exporting, archiveing, renameing, transfering, or removeing your project. Perform advanced options such as housekeeping, exporting, archiving, renaming, transferring, or removing your project.
.settings-content.no-animate{ class: ('expanded' if expanded) } .settings-content.no-animate{ class: ('expanded' if expanded) }
.sub-section .sub-section
%h4 Housekeeping %h4 Housekeeping
...@@ -274,7 +274,7 @@ ...@@ -274,7 +274,7 @@
%li Be careful. Changing the project's namespace can have unintended side effects. %li Be careful. Changing the project's namespace can have unintended side effects.
%li You can only transfer the project to namespaces you manage. %li You can only transfer the project to namespaces you manage.
%li You will need to update your local repositories to point to the new location. %li You will need to update your local repositories to point to the new location.
%li Project visibility level will be changed to match namespace rules when transfering to a group. %li Project visibility level will be changed to match namespace rules when transferring to a group.
= f.submit 'Transfer project', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) } = f.submit 'Transfer project', class: "btn btn-remove js-confirm-danger", data: { "confirm-danger-message" => transfer_project_message(@project) }
- if @project.forked? && can?(current_user, :remove_fork_project, @project) - if @project.forked? && can?(current_user, :remove_fork_project, @project)
.sub-section .sub-section
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
Pipeline Pipeline
= link_to "##{@build.pipeline.id}", project_pipeline_path(@project, @build.pipeline), class: 'link-commit' = link_to "##{@build.pipeline.id}", project_pipeline_path(@project, @build.pipeline), class: 'link-commit'
from from
= link_to "#{@build.pipeline.ref}", project_branch_path(@project, @build.pipeline.ref), class: 'link-commit' = link_to "#{@build.pipeline.ref}", project_ref_path(@project, @build.pipeline.ref), class: 'link-commit ref-name'
%button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' } %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
%span.stage-selection More %span.stage-selection More
= icon('chevron-down') = icon('chevron-down')
......
- if @merge_request_diff.collected? || @merge_request_diff.overflow? - if @merge_request_diff.collected? || @merge_request_diff.overflow?
= render 'projects/merge_requests/diffs/versions' = render 'projects/merge_requests/diffs/versions'
= render "projects/diffs/diffs", diffs: @diffs, environment: @environment = render "projects/diffs/diffs", diffs: @diffs, environment: @environment, merge_request: true
- elsif @merge_request_diff.empty? - elsif @merge_request_diff.empty?
.nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch} .nothing-here-block Nothing to merge from #{@merge_request.source_branch} into #{@merge_request.target_branch}
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
= page_specific_javascript_bundle_tag('common_vue') = page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('sidebar') = page_specific_javascript_bundle_tag('sidebar')
%aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => "50", "spy" => "affix", signed: { in: current_user.present? } }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' } %aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { "offset-top" => ("50" unless show_new_nav?), "spy" => ("affix" unless show_new_nav?), signed: { in: current_user.present? } }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' }
.issuable-sidebar{ data: { endpoint: "#{issuable_json_path(issuable)}" } } .issuable-sidebar{ data: { endpoint: "#{issuable_json_path(issuable)}" } }
- can_edit_issuable = can?(current_user, :"admin_#{issuable.to_ability_name}", @project) - can_edit_issuable = can?(current_user, :"admin_#{issuable.to_ability_name}", @project)
.block.issuable-sidebar-header .block.issuable-sidebar-header
......
module NewIssuable module NewIssuable
attr_reader :issuable, :user attr_reader :issuable, :user
def ensure_objects_found(issuable_id, user_id) def objects_found?(issuable_id, user_id)
@issuable = issuable_class.find_by(id: issuable_id) set_user(user_id)
unless @issuable set_issuable(issuable_id)
log_error(issuable_class, issuable_id)
return false user && issuable
end end
def set_user(user_id)
@user = User.find_by(id: user_id) @user = User.find_by(id: user_id)
unless @user
log_error(User, user_id)
return false
end
true log_error(User, user_id) unless @user
end
def set_issuable(issuable_id)
@issuable = issuable_class.find_by(id: issuable_id)
log_error(issuable_class, issuable_id) unless @issuable
end end
def log_error(record_class, record_id) def log_error(record_class, record_id)
......
...@@ -4,7 +4,7 @@ class NewIssueWorker ...@@ -4,7 +4,7 @@ class NewIssueWorker
include NewIssuable include NewIssuable
def perform(issue_id, user_id) def perform(issue_id, user_id)
return unless ensure_objects_found(issue_id, user_id) return unless objects_found?(issue_id, user_id)
EventCreateService.new.open_issue(issuable, user) EventCreateService.new.open_issue(issuable, user)
NotificationService.new.new_issue(issuable, user) NotificationService.new.new_issue(issuable, user)
......
...@@ -4,7 +4,7 @@ class NewMergeRequestWorker ...@@ -4,7 +4,7 @@ class NewMergeRequestWorker
include NewIssuable include NewIssuable
def perform(merge_request_id, user_id) def perform(merge_request_id, user_id)
return unless ensure_objects_found(merge_request_id, user_id) return unless objects_found?(merge_request_id, user_id)
EventCreateService.new.open_mr(issuable, user) EventCreateService.new.open_mr(issuable, user)
NotificationService.new.new_merge_request(issuable, user) NotificationService.new.new_merge_request(issuable, user)
......
...@@ -14,54 +14,107 @@ Options = Struct.new( ...@@ -14,54 +14,107 @@ Options = Struct.new(
:dry_run, :dry_run,
:force, :force,
:merge_request, :merge_request,
:title :title,
:type
) )
INVALID_TYPE = -1
class ChangelogOptionParser class ChangelogOptionParser
def self.parse(argv) Type = Struct.new(:name, :description)
options = Options.new TYPES = [
Type.new('added', 'New feature'),
Type.new('fixed', 'Bug fix'),
Type.new('changed', 'Feature change'),
Type.new('deprecated', 'New deprecation'),
Type.new('removed', 'Feature removal'),
Type.new('security', 'Security fix'),
Type.new('other', 'Other')
].freeze
TYPES_OFFSET = 1
class << self
def parse(argv)
options = Options.new
parser = OptionParser.new do |opts|
opts.banner = "Usage: #{__FILE__} [options] [title]\n\n"
# Note: We do not provide a shorthand for this in order to match the `git
# commit` interface
opts.on('--amend', 'Amend the previous commit') do |value|
options.amend = value
end
opts.on('-f', '--force', 'Overwrite an existing entry') do |value|
options.force = value
end
opts.on('-m', '--merge-request [integer]', Integer, 'Merge Request ID') do |value|
options.merge_request = value
end
opts.on('-n', '--dry-run', "Don't actually write anything, just print") do |value|
options.dry_run = value
end
opts.on('-u', '--git-username', 'Use Git user.name configuration as the author') do |value|
options.author = git_user_name if value
end
opts.on('-t', '--type [string]', String, "The category of the change, valid options are: #{TYPES.map(&:name).join(', ')}") do |value|
options.type = parse_type(value)
end
opts.on('-h', '--help', 'Print help message') do
$stdout.puts opts
exit
end
end
parser = OptionParser.new do |opts| parser.parse!(argv)
opts.banner = "Usage: #{__FILE__} [options] [title]\n\n"
# Note: We do not provide a shorthand for this in order to match the `git # Title is everything that remains, but let's clean it up a bit
# commit` interface options.title = argv.join(' ').strip.squeeze(' ').tr("\r\n", '')
opts.on('--amend', 'Amend the previous commit') do |value|
options.amend = value
end
opts.on('-f', '--force', 'Overwrite an existing entry') do |value| options
options.force = value end
end
opts.on('-m', '--merge-request [integer]', Integer, 'Merge Request ID') do |value| def read_type
options.merge_request = value read_type_message
end
opts.on('-n', '--dry-run', "Don't actually write anything, just print") do |value| type = TYPES[$stdin.getc.to_i - TYPES_OFFSET]
options.dry_run = value assert_valid_type!(type)
end
opts.on('-u', '--git-username', 'Use Git user.name configuration as the author') do |value| type.name
options.author = git_user_name if value end
end
private
opts.on('-h', '--help', 'Print help message') do def parse_type(name)
$stdout.puts opts type_found = TYPES.find do |type|
exit type.name == name
end end
type_found ? type_found.name : INVALID_TYPE
end end
parser.parse!(argv) def read_type_message
$stdout.puts "\n>> Please specify the index for the category of your change:"
# Title is everything that remains, but let's clean it up a bit TYPES.each_with_index do |type, index|
options.title = argv.join(' ').strip.squeeze(' ').tr("\r\n", '') $stdout.puts "#{index + TYPES_OFFSET}. #{type.description}"
end
$stdout.print "\n?> "
end
options def assert_valid_type!(type)
end unless type
$stderr.puts "Invalid category index, please select an index between 1 and #{TYPES.length}"
exit 1
end
end
def self.git_user_name def git_user_name
%x{git config user.name}.strip %x{git config user.name}.strip
end
end end
end end
...@@ -72,8 +125,12 @@ class ChangelogEntry ...@@ -72,8 +125,12 @@ class ChangelogEntry
@options = options @options = options
assert_feature_branch! assert_feature_branch!
assert_new_file!
assert_title! assert_title!
assert_new_file!
# Read type from $stdin unless is already set
options.type ||= ChangelogOptionParser.read_type
assert_valid_type!
$stdout.puts "\e[32mcreate\e[0m #{file_path}" $stdout.puts "\e[32mcreate\e[0m #{file_path}"
$stdout.puts contents $stdout.puts contents
...@@ -90,7 +147,8 @@ class ChangelogEntry ...@@ -90,7 +147,8 @@ class ChangelogEntry
yaml_content = YAML.dump( yaml_content = YAML.dump(
'title' => title, 'title' => title,
'merge_request' => options.merge_request, 'merge_request' => options.merge_request,
'author' => options.author 'author' => options.author,
'type' => options.type
) )
remove_trailing_whitespace(yaml_content) remove_trailing_whitespace(yaml_content)
end end
...@@ -129,6 +187,12 @@ class ChangelogEntry ...@@ -129,6 +187,12 @@ class ChangelogEntry
" to use the title from the previous commit." " to use the title from the previous commit."
end end
def assert_valid_type!
return unless options.type && options.type == INVALID_TYPE
fail_with 'Invalid category given!'
end
def title def title
if options.title.empty? if options.title.empty?
last_commit_subject last_commit_subject
......
---
title: Added type to CHANGELOG entries
merge_request:
author: Jacopo Beschi @jacopo-beschi
---
title: Fix the alignment of line numbers to lines of code in code viewer
merge_request: 13403
author: Trevor Flynn
\ No newline at end of file
---
title: Simplify checking if objects exist code in new issaubles workers
merge_request:
author:
---
title: Fixes new issue button for failed job returning 404
merge_request:
author:
---
title: Align OR separator to center in new project page
merge_request:
author:
---
title: Remove hidden symlinks from project import files
merge_request:
author:
---
title: Fix destroy of case-insensitive conflicting redirects
merge_request: 13357
author:
---
title: Add missing validation error for username change with container registry tags
merge_request: 13356
author:
---
title: Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric
character
merge_request:
author:
---
title: Use project_ref_path to create the link to a branch to fix links that 404
merge_request:
author:
...@@ -71,7 +71,7 @@ class Settings < Settingslogic ...@@ -71,7 +71,7 @@ class Settings < Settingslogic
# check that `current` (string or integer) is a contant in `modul`. # check that `current` (string or integer) is a contant in `modul`.
def verify_constant(modul, current, default) def verify_constant(modul, current, default)
constant = modul.constants.find{ |name| modul.const_get(name) == current } constant = modul.constants.find { |name| modul.const_get(name) == current }
value = constant.nil? ? default : modul.const_get(constant) value = constant.nil? ? default : modul.const_get(constant)
if current.is_a? String if current.is_a? String
value = modul.const_get(current.upcase) rescue default value = modul.const_get(current.upcase) rescue default
......
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
resource :repository, only: [:create] do resource :repository, only: [:create] do
member do member do
get ':ref/archive', constraints: { format: Gitlab::PathRegex.archive_formats_regex, ref: /.+/ }, action: 'archive', as: 'archive' get ':ref/archive', constraints: { format: Gitlab::PathRegex.archive_formats_regex, ref: /.+/ }, action: 'archive', as: 'archive'
# deprecated since GitLab 9.5
get 'archive', constraints: { format: Gitlab::PathRegex.archive_formats_regex }, as: 'archive_alternative'
end end
end end
......
...@@ -10,7 +10,7 @@ class AddUniqueIndexToLabels < ActiveRecord::Migration ...@@ -10,7 +10,7 @@ class AddUniqueIndexToLabels < ActiveRecord::Migration
def up def up
select_all('SELECT title, project_id, COUNT(id) as cnt FROM labels GROUP BY project_id, title HAVING COUNT(id) > 1').each do |label| select_all('SELECT title, project_id, COUNT(id) as cnt FROM labels GROUP BY project_id, title HAVING COUNT(id) > 1').each do |label|
label_title = quote_string(label['title']) label_title = quote_string(label['title'])
duplicated_ids = select_all("SELECT id FROM labels WHERE project_id = #{label['project_id']} AND title = '#{label_title}' ORDER BY id ASC").map{ |label| label['id'] } duplicated_ids = select_all("SELECT id FROM labels WHERE project_id = #{label['project_id']} AND title = '#{label_title}' ORDER BY id ASC").map { |label| label['id'] }
label_id = duplicated_ids.first label_id = duplicated_ids.first
duplicated_ids.delete(label_id) duplicated_ids.delete(label_id)
......
...@@ -30,7 +30,7 @@ class CleanupNamespacelessPendingDeleteProjects < ActiveRecord::Migration ...@@ -30,7 +30,7 @@ class CleanupNamespacelessPendingDeleteProjects < ActiveRecord::Migration
private private
def pending_delete_batch def pending_delete_batch
connection.exec_query(find_batch).map{ |row| row['id'].to_i } connection.exec_query(find_batch).map { |row| row['id'].to_i }
end end
BATCH_SIZE = 5000 BATCH_SIZE = 5000
......
---
toc: false
---
# GitLab Documentation # GitLab Documentation
Welcome to [GitLab](https://about.gitlab.com/), a Git-based fully featured Welcome to [GitLab](https://about.gitlab.com/), a Git-based fully featured
...@@ -26,6 +30,9 @@ Shortcuts to GitLab's most visited docs: ...@@ -26,6 +30,9 @@ Shortcuts to GitLab's most visited docs:
| [Configuring `.gitlab-ci.yml`](ci/yaml/README.md) | [SSH authentication](ssh/README.md) | | [Configuring `.gitlab-ci.yml`](ci/yaml/README.md) | [SSH authentication](ssh/README.md) |
| [Using Docker images](ci/docker/using_docker_images.md) | [GitLab Pages](user/project/pages/index.md) | | [Using Docker images](ci/docker/using_docker_images.md) | [GitLab Pages](user/project/pages/index.md) |
- [User documentation](user/index.md)
- [Administrator documentation](#administrator-documentation)
## Getting started with GitLab ## Getting started with GitLab
- [GitLab Basics](gitlab-basics/README.md): Start working on your command line and on GitLab. - [GitLab Basics](gitlab-basics/README.md): Start working on your command line and on GitLab.
...@@ -36,7 +43,6 @@ Shortcuts to GitLab's most visited docs: ...@@ -36,7 +43,6 @@ Shortcuts to GitLab's most visited docs:
### User account ### User account
- [User documentation](user/index.md): Learn how to use GitLab and explore its features
- [User account](user/profile/index.md): Manage your account - [User account](user/profile/index.md): Manage your account
- [Authentication](topics/authentication/index.md): Account security with two-factor authentication, setup your ssh keys and deploy keys for secure access to your projects. - [Authentication](topics/authentication/index.md): Account security with two-factor authentication, setup your ssh keys and deploy keys for secure access to your projects.
- [Profile settings](user/profile/index.md#profile-settings): Manage your profile settings, two factor authentication and more. - [Profile settings](user/profile/index.md#profile-settings): Manage your profile settings, two factor authentication and more.
......
...@@ -42,6 +42,10 @@ GitLab does not recommend using EFS with GitLab. ...@@ -42,6 +42,10 @@ GitLab does not recommend using EFS with GitLab.
are allocated. For smaller volumes, users may experience decent performance are allocated. For smaller volumes, users may experience decent performance
for a period of time due to 'Burst Credits'. Over a period of weeks to months for a period of time due to 'Burst Credits'. Over a period of weeks to months
credits may run out and performance will bottom out. credits may run out and performance will bottom out.
- To keep "Burst Credits" available, it may be necessary to provision more space
with 'dummy data'. However, this may get expensive.
- Another option to maintain "Burst Credits" is to use FS Cache on the server so
that AWS doesn't always have to go into EFS to access files.
- For larger volumes, allocated IOPS may not be the problem. Workloads where - For larger volumes, allocated IOPS may not be the problem. Workloads where
many small files are written in a serialized manner are not well-suited for EFS. many small files are written in a serialized manner are not well-suited for EFS.
EBS with an NFS server on top will perform much better. EBS with an NFS server on top will perform much better.
......
...@@ -15,11 +15,14 @@ following format: ...@@ -15,11 +15,14 @@ following format:
title: "Going through change[log]s" title: "Going through change[log]s"
merge_request: 1972 merge_request: 1972
author: Ozzy Osbourne author: Ozzy Osbourne
type: added
``` ```
The `merge_request` value is a reference to a merge request that adds this The `merge_request` value is a reference to a merge request that adds this
entry, and the `author` key is used to give attribution to community entry, and the `author` key is used to give attribution to community
contributors. **Both are optional**. contributors. **Both are optional**.
The `type` field maps the category of the change,
valid options are: added, fixed, changed, deprecated, removed, security, other. **Type field is mandatory**.
Community contributors and core team members are encouraged to add their name to Community contributors and core team members are encouraged to add their name to
the `author` field. GitLab team members **should not**. the `author` field. GitLab team members **should not**.
...@@ -94,6 +97,19 @@ Its simplest usage is to provide the value for `title`: ...@@ -94,6 +97,19 @@ Its simplest usage is to provide the value for `title`:
$ bin/changelog 'Hey DZ, I added a feature to GitLab!' $ bin/changelog 'Hey DZ, I added a feature to GitLab!'
``` ```
At this point the script would ask you to select the category of the change (mapped to the `type` field in the entry):
```text
>> Please specify the category of your change:
1. New feature
2. Bug fix
3. Feature change
4. New deprecation
5. Feature removal
6. Security fix
7. Other
```
The entry filename is based on the name of the current Git branch. If you run The entry filename is based on the name of the current Git branch. If you run
the command above on a branch called `feature/hey-dz`, it will generate a the command above on a branch called `feature/hey-dz`, it will generate a
`changelogs/unreleased/feature-hey-dz.yml` file. `changelogs/unreleased/feature-hey-dz.yml` file.
...@@ -106,26 +122,29 @@ create changelogs/unreleased/my-feature.yml ...@@ -106,26 +122,29 @@ create changelogs/unreleased/my-feature.yml
title: Hey DZ, I added a feature to GitLab! title: Hey DZ, I added a feature to GitLab!
merge_request: merge_request:
author: author:
type:
``` ```
If you're working on the GitLab EE repository, the entry will be added to If you're working on the GitLab EE repository, the entry will be added to
`changelogs/unreleased-ee/` instead. `changelogs/unreleased-ee/` instead.
#### Arguments #### Arguments
| Argument | Shorthand | Purpose | | Argument | Shorthand | Purpose |
| ----------------- | --------- | --------------------------------------------- | | ----------------- | --------- | ---------------------------------------------------------------------------------------------------------- |
| [`--amend`] | | Amend the previous commit | | [`--amend`] | | Amend the previous commit |
| [`--force`] | `-f` | Overwrite an existing entry | | [`--force`] | `-f` | Overwrite an existing entry |
| [`--merge-request`] | `-m` | Set merge request ID | | [`--merge-request`] | `-m` | Set merge request ID |
| [`--dry-run`] | `-n` | Don't actually write anything, just print | | [`--dry-run`] | `-n` | Don't actually write anything, just print |
| [`--git-username`] | `-u` | Use Git user.name configuration as the author | | [`--git-username`] | `-u` | Use Git user.name configuration as the author |
| [`--help`] | `-h` | Print help message | | [`--type`] | `-t` | The category of the change, valid options are: added, fixed, changed, deprecated, removed, security, other |
| [`--help`] | `-h` | Print help message |
[`--amend`]: #-amend [`--amend`]: #-amend
[`--force`]: #-force-or-f [`--force`]: #-force-or-f
[`--merge-request`]: #-merge-request-or-m [`--merge-request`]: #-merge-request-or-m
[`--dry-run`]: #-dry-run-or-n [`--dry-run`]: #-dry-run-or-n
[`--git-username`]: #-git-username-or-u [`--git-username`]: #-git-username-or-u
[`--type`]: #-type-or-t
[`--help`]: #-help [`--help`]: #-help
##### `--amend` ##### `--amend`
...@@ -147,6 +166,7 @@ create changelogs/unreleased/feature-hey-dz.yml ...@@ -147,6 +166,7 @@ create changelogs/unreleased/feature-hey-dz.yml
title: Added an awesome new feature to GitLab title: Added an awesome new feature to GitLab
merge_request: merge_request:
author: author:
type:
``` ```
##### `--force` or `-f` ##### `--force` or `-f`
...@@ -164,6 +184,7 @@ create changelogs/unreleased/feature-hey-dz.yml ...@@ -164,6 +184,7 @@ create changelogs/unreleased/feature-hey-dz.yml
title: Hey DZ, I added a feature to GitLab! title: Hey DZ, I added a feature to GitLab!
merge_request: 1983 merge_request: 1983
author: author:
type:
``` ```
##### `--merge-request` or `-m` ##### `--merge-request` or `-m`
...@@ -178,6 +199,7 @@ create changelogs/unreleased/feature-hey-dz.yml ...@@ -178,6 +199,7 @@ create changelogs/unreleased/feature-hey-dz.yml
title: Hey DZ, I added a feature to GitLab! title: Hey DZ, I added a feature to GitLab!
merge_request: 1983 merge_request: 1983
author: author:
type:
``` ```
##### `--dry-run` or `-n` ##### `--dry-run` or `-n`
...@@ -192,6 +214,7 @@ create changelogs/unreleased/feature-hey-dz.yml ...@@ -192,6 +214,7 @@ create changelogs/unreleased/feature-hey-dz.yml
title: Added an awesome new feature to GitLab title: Added an awesome new feature to GitLab
merge_request: merge_request:
author: author:
type:
$ ls changelogs/unreleased/ $ ls changelogs/unreleased/
``` ```
...@@ -211,6 +234,21 @@ create changelogs/unreleased/feature-hey-dz.yml ...@@ -211,6 +234,21 @@ create changelogs/unreleased/feature-hey-dz.yml
title: Hey DZ, I added a feature to GitLab! title: Hey DZ, I added a feature to GitLab!
merge_request: merge_request:
author: Jane Doe author: Jane Doe
type:
```
##### `--type` or `-t`
Use the **`--type`** or **`-t`** argument to provide the `type` value:
```text
$ bin/changelog 'Hey DZ, I added a feature to GitLab!' -t added
create changelogs/unreleased/feature-hey-dz.yml
---
title: Hey DZ, I added a feature to GitLab!
merge_request:
author:
type: added
``` ```
### History and Reasoning ### History and Reasoning
......
...@@ -66,6 +66,9 @@ Install the required packages (needed to compile Ruby and native extensions to R ...@@ -66,6 +66,9 @@ Install the required packages (needed to compile Ruby and native extensions to R
sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libre2-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate python-docutils pkg-config cmake sudo apt-get install -y build-essential zlib1g-dev libyaml-dev libssl-dev libgdbm-dev libre2-dev libreadline-dev libncurses5-dev libffi-dev curl openssh-server checkinstall libxml2-dev libxslt-dev libcurl4-openssl-dev libicu-dev logrotate python-docutils pkg-config cmake
Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
you can [install re2 manually](https://github.com/google/re2/wiki/Install).
If you want to use Kerberos for user authentication, then install libkrb5-dev: If you want to use Kerberos for user authentication, then install libkrb5-dev:
sudo apt-get install libkrb5-dev sudo apt-get install libkrb5-dev
...@@ -296,9 +299,9 @@ sudo usermod -aG redis git ...@@ -296,9 +299,9 @@ sudo usermod -aG redis git
### Clone the Source ### Clone the Source
# Clone GitLab repository # Clone GitLab repository
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 9-4-stable gitlab sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 9-5-stable gitlab
**Note:** You can change `9-4-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! **Note:** You can change `9-5-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It ### Configure It
......
# GitLab Helm Chart # GitLab Helm Chart
> Officially supported cloud providers are Google Container Service and Azure Container Service. > These Helm charts are in beta. GitLab is working on a [cloud-native](http://docs.gitlab.com/omnibus/package-information/cloud_native.html) set of [Charts](https://gitlab.com/charts/helm.gitlab.io) which will replace these.
> Officially supported schedulers are Kubernetes and Terraform. > Officially supported cloud providers are Google Container Service and Azure Container Service.
The `gitlab` Helm chart deploys GitLab into your Kubernetes cluster. The `gitlab` Helm chart deploys GitLab into your Kubernetes cluster.
...@@ -207,7 +207,7 @@ its class in an annotation. ...@@ -207,7 +207,7 @@ its class in an annotation.
>**Note:** >**Note:**
The Ingress alone doesn't expose GitLab externally. You need to have a Ingress controller setup to do that. The Ingress alone doesn't expose GitLab externally. You need to have a Ingress controller setup to do that.
Setting up an Ingress controller can be done by installing the `nginx-ingress` helm chart. But be sure Setting up an Ingress controller can be done by installing the `nginx-ingress` helm chart. But be sure
to read the [documentation](https://github.com/kubernetes/charts/blob/master/stable/nginx-ingress/README.md). to read the [documentation](https://github.com/kubernetes/charts/blob/master/stable/nginx-ingress/README.md).
>**Note:** >**Note:**
If you would like to use the Registry, you will also need to ensure your Ingress supports a [sufficiently large request size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size). If you would like to use the Registry, you will also need to ensure your Ingress supports a [sufficiently large request size](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size).
......
# GitLab-Omnibus Helm Chart
> These Helm charts are in beta. GitLab is working on a [cloud-native](http://docs.gitlab.com/omnibus/package-information/cloud_native.html) set of [Charts](https://gitlab.com/charts/helm.gitlab.io) which will replace these.
> Officially supported cloud providers are Google Container Service and Azure Container Service.
This work is based partially on: https://github.com/lwolf/kubernetes-gitlab/. GitLab would like to thank Sergey Nuzhdin for his work.
## Introduction
This chart provides an easy way to get started with GitLab, provisioning an installation with nearly all functionality enabled. SSL is automatically provisioned as well via [Let's Encrypt](https://letsencrypt.org/).
The deployment includes:
- A [GitLab Omnibus](https://docs.gitlab.com/omnibus/) Pod, including Mattermost, Container Registry, and Prometheus
- An auto-scaling [GitLab Runner](https://docs.gitlab.com/runner/) using the Kubernetes executor
- [Redis](https://github.com/kubernetes/charts/tree/master/stable/redis)
- [PostgreSQL](https://github.com/kubernetes/charts/tree/master/stable/postgresql)
- [NGINX Ingress](https://github.com/kubernetes/charts/tree/master/stable/nginx-ingress)
- Persistent Volume Claims for Data, Registry, Postgres, and Redis
A video demonstration of GitLab utilizing this chart [is available](https://about.gitlab.com/handbook/sales/demo/).
Terms:
- Google Cloud Platform (**GCP**)
- Google Container Engine (**GKE**)
- Azure Container Service (**ACS**)
- Kubernetes (**k8s**)
## Prerequisites
- _At least_ 4 GB of RAM available on your cluster, in chunks of 1 GB. 41GB of storage and 2 CPU are also required.
- Kubernetes 1.4+ with Beta APIs enabled
- [Persistent Volume](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) provisioner support in the underlying infrastructure
- An [external IP address](#networking-prerequisites)
- A [wildcard DNS entry](#networking-prerequisites), which resolves to the external IP address
- The `kubectl` CLI installed locally and authenticated for the cluster
- The Helm Client installed locally
- The Helm Server (Tiller) already installed and running in the cluster, by running `helm init`
- The GitLab Helm Repo [added to your Helm Client](index.md#add-the-gitlab-helm-repository)
### Networking Prerequisites
This chart configures a GitLab server and Kubernetes cluster which can support dynamic [Review Apps](https://docs.gitlab.com/ee/ci/review_apps/index.html), as well as services like the integrated [Container Registry](https://docs.gitlab.com/ee/user/project/container_registry.html) and [Mattermost](https://docs.gitlab.com/omnibus/gitlab-mattermost/).
To support the GitLab services and dynamic environments, a wildcard DNS entry is required which resolves to the external Load Balancer IP.
To provision an external IP on GCP and Azure, simply request a new address from the Networking section. Ensure that the region matches the region your container cluster is created in. Note, it is important that the IP is not assigned at this point in time. It will be automatically assigned once the Helm chart is installed, and assigned to the Load Balancer.
Now that an external IP address has been allocated, ensure that the wildcard DNS entry you would like to use resolves to this IP. Please consult the documentation for your DNS service for more information on creating DNS records.
## Configuring and Installing GitLab
For most installations, only two parameters are required:
- `baseIP`: the desired [external IP address](#networking-prerequisites)
- `baseDomain`: the [base domain](#networking-prerequisites) with the wildcard host entry resolving to the `baseIP`. For example, `mycompany.io`.
Other common configuration options:
- `gitlab`: Choose the [desired edition](https://about.gitlab.com/products), either `ee` or `ce`. `ce` is the default.
- `gitlabEELicense`: For Enterprise Edition, the [license](https://docs.gitlab.com/ee/user/admin_area/license.html) can be installed directly via the Chart
- `provider`: Optimizes the deployment for a cloud provider. The default is `gke` for GCP, with `acs` also supported for Azure.
- `legoEmail`: Email address to use when requesting new SSL certificates from Let's Encrypt
For additional configuration options, consult the [values.yaml](https://gitlab.com/charts/charts.gitlab.io/blob/master/charts/gitlab-omnibus/values.yaml).
These settings can either be passed directly on the command line:
```bash
helm install --name gitlab --set baseDomain=gitlab.io,baseIP=1.1.1.1,gitlab=ee,gitlabEELicense=$LICENSE,legoEmail=email@gitlab.com gitlab/gitlab-omnibus
```
or within a YAML file:
```bash
helm install --name gitlab -f values.yaml gitlab/gitlab-omnibus
```
> **Note:**
If you are using a machine type with support for less than 4 attached disks, like an Azure trial, you should disable dedicated storage for [Postgres and Redis](#persistent-storage).
### Choosing a different GitLab release version
The version of GitLab installed is based on the `gitlab` setting (see [section](#choosing-gitlab-edition) above), and
the value of the corresponding helm setting: `gitlabCEImage` or `gitabEEImage`.
```yaml
gitlab: CE
gitlabCEImage: gitlab/gitlab-ce:9.1.2-ce.0
gitlabEEImage: gitlab/gitlab-ee:9.1.2-ee.0
```
The different images can be found in the [gitlab-ce](https://hub.docker.com/r/gitlab/gitlab-ce/tags/) and [gitlab-ee](https://hub.docker.com/r/gitlab/gitlab-ee/tags/)
repositories on Docker Hub.
> **Note:**
There is no guarantee that other release versions of GitLab, other than what are
used by default in the chart, will be supported by a chart install.
### Persistent storage
By default, persistent storage is enabled for GitLab and the charts it depends
on (Redis and PostgreSQL).
Components can have their claim size set from your `values.yaml`, along with whether to provision separate storage for Postgres and Redis.
Basic configuration:
```yaml
redisImage: redis:3.2.10
redisDedicatedStorage: true
redisStorageSize: 5Gi
postgresImage: postgres:9.6.3
# If you disable postgresDedicatedStorage, you should consider bumping up gitlabRailsStorageSize
postgresDedicatedStorage: true
postgresStorageSize: 30Gi
gitlabRailsStorageSize: 30Gi
gitlabRegistryStorageSize: 30Gi
gitlabConfigStorageSize: 1Gi
```
### Routing and SSL
Ingress routing and SSL are automatically configured within this Chart. An NGINX ingress is provisioned and configured, and will route traffic to any service. SSL certificates are automatically created and configured by [kube-lego](https://github.com/kubernetes/charts/tree/master/stable/kube-lego).
> **Note:**
Let's Encrypt limits a single TLD to five certificate requests within a single week. This means that common DNS wildcard services like [xip.io](http://xip.io) and [nip.io](http://nip.io) are unlikely to work.
## Installing GitLab using the Helm Chart
> You may see a temporary error message `SchedulerPredicates failed due to PersistentVolumeClaim is not bound` while storage provisions. Once the storage provisions, the pods will automatically restart. This may take a couple minutes depending on your cloud provider. If the error persists, please review the [prerequisites](#prerequisites) to ensure you have enough RAM, CPU, and storage.
Once you have reviewed the [configuration settings](#configuring-and-installing-gitlab), you can install the chart. We recommending saving your configuration options in a `values.yaml` file for easier upgrades in the future.
For example:
```bash
helm install --name gitlab -f values.yaml gitlab/gitlab-omnibus
```
or passing them on the command line:
```bash
helm install --name gitlab --set baseDomain=gitlab.io,baseIP=1.1.1.1,gitlab=ee,gitlabEELicense=$LICENSE,legoEmail=email@gitlab.com gitlab/gitlab-omnibus
```
## Updating GitLab using the Helm Chart
Once your GitLab Chart is installed, configuration changes and chart updates
should we done using `helm upgrade`
```bash
helm upgrade -f <CONFIG_VALUES_FILE> <RELEASE-NAME> gitlab/gitlab
```
where:
- `<CONFIG_VALUES_FILE>` is the path to values file containing your custom
[configuration] (#configuring-and-installing-gitlab).
- `<RELEASE-NAME>` is the name you gave the chart when installing it.
In the [Install section](#installing-gitlab-using-the-helm-chart) we called it `gitlab`.
## Uninstalling GitLab using the Helm Chart
To uninstall the GitLab Chart, run the following:
```bash
helm delete <RELEASE-NAME>
```
where:
- `<RELEASE-NAME>` is the name you gave the chart when installing it.
In the [Install section](#installing) we called it `gitlab`.
[kube-srv]: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types
[storageclass]: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#storageclasses
# GitLab Runner Helm Chart # GitLab Runner Helm Chart
> Officially supported cloud providers are Google Container Service and Azure Container Service. > These Helm charts are in beta. GitLab is working on a [cloud-native](http://docs.gitlab.com/omnibus/package-information/cloud_native.html) set of [Charts](https://gitlab.com/charts/helm.gitlab.io) which will replace these.
> Officially supported schedulers are Kubernetes and Terraform. > Officially supported cloud providers are Google Container Service and Azure Container Service.
The `gitlab-runner` Helm chart deploys a GitLab Runner instance into your The `gitlab-runner` Helm chart deploys a GitLab Runner instance into your
Kubernetes cluster. Kubernetes cluster.
......
# Installing GitLab on Kubernetes # Installing GitLab on Kubernetes
> Officially supported cloud providers are Google Container Service and Azure Container Service. > These Helm charts are in beta. GitLab is working on a [cloud-native](http://docs.gitlab.com/omnibus/package-information/cloud_native.html) set of [Charts](https://gitlab.com/charts/helm.gitlab.io) which will replace these.
> Officially supported schedulers are Kubernetes, Terraform and Tectonic. > Officially supported cloud providers are Google Container Service and Azure Container Service.
The easiest method to deploy GitLab in [Kubernetes](https://kubernetes.io/) is The easiest method to deploy GitLab in [Kubernetes](https://kubernetes.io/) is
to take advantage of the official GitLab Helm charts. [Helm] is a package to take advantage of the official GitLab Helm charts. [Helm] is a package
...@@ -35,12 +35,11 @@ helm init ...@@ -35,12 +35,11 @@ helm init
## Using the GitLab Helm Charts ## Using the GitLab Helm Charts
GitLab makes available two Helm Charts, one for the GitLab server and another GitLab makes available three Helm Charts: an easy to use bundled chart, and a specific chart for GitLab itself and the Runner.
for the Runner. More detailed information on installing and configuring each
Chart can be found below:
- [Install GitLab](gitlab_chart.md) - [gitlab-omnibus](gitlab_omnibus.md): The easiest way to get started. Includes everything needed to run GitLab, including: a Runner, Container Registry, automatic SSL, and an Ingress.
- [Install GitLab Runner](gitlab_runner_chart.md) - [gitlab](gitlab_chart.md): Just the GitLab service, with optional Postgres and Redis.
- [gitlab-runner](gitlab_runner_chart.md): GitLab Runner, to process CI jobs.
[chart]: https://github.com/kubernetes/charts [chart]: https://github.com/kubernetes/charts
[helm-quick]: https://github.com/kubernetes/helm/blob/master/docs/quickstart.md [helm-quick]: https://github.com/kubernetes/helm/blob/master/docs/quickstart.md
......
...@@ -264,6 +264,16 @@ sudo systemctl daemon-reload ...@@ -264,6 +264,16 @@ sudo systemctl daemon-reload
### 9. Install libs, migrations, etc. ### 9. Install libs, migrations, etc.
GitLab 9.0.11 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
a dependency on on the `re2` regular expression library. To install this dependency:
```bash
sudo apt-get install libre2-dev
```
Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
you can [install re2 manually](https://github.com/google/re2/wiki/Install).
```bash ```bash
cd /home/git/gitlab cd /home/git/gitlab
......
...@@ -264,6 +264,16 @@ sudo systemctl daemon-reload ...@@ -264,6 +264,16 @@ sudo systemctl daemon-reload
### 9. Install libs, migrations, etc. ### 9. Install libs, migrations, etc.
GitLab 9.1.8 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
a dependency on on the `re2` regular expression library. To install this dependency:
```bash
sudo apt-get install libre2-dev
```
Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
you can [install re2 manually](https://github.com/google/re2/wiki/Install).
```bash ```bash
cd /home/git/gitlab cd /home/git/gitlab
......
...@@ -222,6 +222,16 @@ sudo systemctl daemon-reload ...@@ -222,6 +222,16 @@ sudo systemctl daemon-reload
### 10. Install libs, migrations, etc. ### 10. Install libs, migrations, etc.
GitLab 9.2.8 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
a dependency on on the `re2` regular expression library. To install this dependency:
```bash
sudo apt-get install libre2-dev
```
Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
you can [install re2 manually](https://github.com/google/re2/wiki/Install).
```bash ```bash
cd /home/git/gitlab cd /home/git/gitlab
......
...@@ -258,6 +258,16 @@ sudo systemctl daemon-reload ...@@ -258,6 +258,16 @@ sudo systemctl daemon-reload
### 12. Install libs, migrations, etc. ### 12. Install libs, migrations, etc.
GitLab 9.3.8 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
a dependency on on the `re2` regular expression library. To install this dependency:
```bash
sudo apt-get install libre2-dev
```
Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
you can [install re2 manually](https://github.com/google/re2/wiki/Install).
```bash ```bash
cd /home/git/gitlab cd /home/git/gitlab
......
...@@ -271,6 +271,16 @@ sudo systemctl daemon-reload ...@@ -271,6 +271,16 @@ sudo systemctl daemon-reload
### 12. Install libs, migrations, etc. ### 12. Install libs, migrations, etc.
GitLab 9.4 [introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/24570)
a dependency on on the `re2` regular expression library. To install this dependency:
```bash
sudo apt-get install libre2-dev
```
Ubuntu 14.04 (Trusty Tahr) doesn't have the `libre2-dev` package available, but
you can [install re2 manually](https://github.com/google/re2/wiki/Install).
```bash ```bash
cd /home/git/gitlab cd /home/git/gitlab
......
...@@ -295,6 +295,10 @@ sudo -u git -H bundle clean ...@@ -295,6 +295,10 @@ sudo -u git -H bundle clean
# Run database migrations # Run database migrations
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
# Compile GetText PO files
sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production
# Update node dependencies and recompile assets # Update node dependencies and recompile assets
sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
......
...@@ -71,80 +71,44 @@ your code, use it as an issue tracker, collaborate on code, and continuously ...@@ -71,80 +71,44 @@ your code, use it as an issue tracker, collaborate on code, and continuously
build, test, and deploy your app with built-in GitLab CI/CD. Or, you can do build, test, and deploy your app with built-in GitLab CI/CD. Or, you can do
it all at once, from one single project. it all at once, from one single project.
### Repository - [Repositories](project/repository/index.md): Host your codebase in
repositories with version control and as part of a fully integrated platform.
Host your codebase in [GitLab repositories](project/repository/index.md) with version control - [Issues](project/issues/index.md): Explore the best of GitLab Issues' features.
and as part of a fully integrated platform. - [Merge Requests](project/merge_requests/index.md): Collaborate on code,
reviews, live preview changes per branch, and request approvals with Merge Requests.
### Issues - [Milestones](project/milestones/index.md): Work on multiple issues and merge
requests towards the same target date with Milestones.
Explore the best of GitLab [Issues](project/issues/index.md).
### Merge Requests
Collanorate on code, gather reviews, live preview changes per branch, and
request approvals with [Merge Requests](project/merge_requests/index.md).
### Milestones
Work on multiple issues and merge requests towards the same target date
with [Milestones](project/milestones/index.md).
### GitLab Pages
Publish your static site directly from GitLab with [GitLab Pages](project/pages/index.md). You
can [build, test, and deploy any Static Site Generator](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/) with Pages.
### Container Registry
Build and deploy Docker images with [GitLab Container Registry](project/container_registry.md).
## GitLab CI/CD ## GitLab CI/CD
Use built-in [GitLab CI/CD](../ci/README.md) to test, build, and deploy your applications Use built-in [GitLab CI/CD](../ci/README.md) to test, build, and deploy your applications
directly from GitLab. No third-party integrations needed. directly from GitLab. No third-party integrations needed.
### Auto Deploy - [GitLab Auto Deploy](../ci/autodeploy/index.md): Deploy your application out-of-the-box with GitLab Auto Deploy.
- [Review Apps](../ci/review_apps/index.md): Live-preview the changes introduced by a merge request with Review Apps.
Deploy your application out-of-the-box with [GitLab Auto Deploy](../ci/autodeploy/index.md). - [GitLab Pages](project/pages/index.md): Publish your static site directly from
GitLab with Gitlab Pages. You can build, test, and deploy any Static Site Generator with Pages.
### Review Apps - [GitLab Container Registry](project/container_registry.md): Build and deploy Docker
images with Container Registry.
Live-preview the changes introduced by a merge request with [Review Apps](../ci/review_apps/index.md).
## Groups
With GitLab [Groups](group/index.md) you can assemble related projects together
and grant members access to several projects at once.
### Subgroups
Groups can also be nested in [subgroups](group/subgroups/index.md).
## Account ## Account
There is a lot you can customize and configure There is a lot you can customize and configure
to enjoy the best of GitLab. to enjoy the best of GitLab.
[Manage your user settings](profile/index.md) to change your personal info, - [Settings](profile/index.md): Manage your user settings to change your personal info,
personal access tokens, authorized applications, etc. personal access tokens, authorized applications, etc.
- [Authentication](../topics/authentication/index.md): Read through the authentication
methods available in GitLab.
- [Permissions](permissions.md): Learn the different set of permissions levels for each
user type (guest, reporter, developer, master, owner).
### Authentication ## Groups
Read through the [authentication](../topics/authentication/index.md) methods available in GitLab.
### Permissions
Learn the different set of [permissions](permissions.md) for user type (guest, reporter, developer, master, owner).
## Integrations
[Integrate GitLab](../integration/README.md) with your preferred tool,
such as Trello, JIRA, etc.
## Git and GitLab With GitLab [Groups](group/index.md) you can assemble related projects together
and grant members access to several projects at once.
Learn what is [Git](../topics/git/index.md) and its best practices. Groups can also be nested in [subgroups](group/subgroups/index.md).
## Discussions ## Discussions
...@@ -168,6 +132,11 @@ requests you're assigned to. ...@@ -168,6 +132,11 @@ requests you're assigned to.
you have quick access to. You can also gather feedback on them through you have quick access to. You can also gather feedback on them through
[discussions](#discussions). [discussions](#discussions).
## Integrations
[Integrate GitLab](../integration/README.md) with your preferred tool,
such as Trello, JIRA, etc.
## Webhooks ## Webhooks
Configure [webhooks](project/integrations/webhooks.html) to listen for Configure [webhooks](project/integrations/webhooks.html) to listen for
...@@ -178,3 +147,6 @@ POST request with data to the webhook URL. ...@@ -178,3 +147,6 @@ POST request with data to the webhook URL.
Automate GitLab via [API](../api/README.html). Automate GitLab via [API](../api/README.html).
## Git and GitLab
Learn what is [Git](../topics/git/index.md) and its best practices.
...@@ -132,7 +132,7 @@ module API ...@@ -132,7 +132,7 @@ module API
expose :lfs_enabled?, as: :lfs_enabled expose :lfs_enabled?, as: :lfs_enabled
expose :creator_id expose :creator_id
expose :namespace, using: 'API::Entities::Namespace' expose :namespace, using: 'API::Entities::Namespace'
expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda{ |project, options| project.forked? } expose :forked_from_project, using: Entities::BasicProjectDetails, if: lambda { |project, options| project.forked? }
expose :import_status expose :import_status
expose :import_error, if: lambda { |_project, options| options[:user_can_admin_project] } expose :import_error, if: lambda { |_project, options| options[:user_can_admin_project] }
expose :avatar_url do |user, options| expose :avatar_url do |user, options|
......
...@@ -68,7 +68,7 @@ module API ...@@ -68,7 +68,7 @@ module API
expose :lfs_enabled?, as: :lfs_enabled expose :lfs_enabled?, as: :lfs_enabled
expose :creator_id expose :creator_id
expose :namespace, using: 'API::Entities::Namespace' expose :namespace, using: 'API::Entities::Namespace'
expose :forked_from_project, using: ::API::Entities::BasicProjectDetails, if: lambda{ |project, options| project.forked? } expose :forked_from_project, using: ::API::Entities::BasicProjectDetails, if: lambda { |project, options| project.forked? }
expose :avatar_url do |user, options| expose :avatar_url do |user, options|
user.avatar_url(only_path: false) user.avatar_url(only_path: false)
end end
......
...@@ -198,11 +198,11 @@ module Backup ...@@ -198,11 +198,11 @@ module Backup
end end
def archives_to_backup def archives_to_backup
ARCHIVES_TO_BACKUP.map{ |name| (name + ".tar.gz") unless skipped?(name) }.compact ARCHIVES_TO_BACKUP.map { |name| (name + ".tar.gz") unless skipped?(name) }.compact
end end
def folders_to_backup def folders_to_backup
FOLDERS_TO_BACKUP.reject{ |name| skipped?(name) } FOLDERS_TO_BACKUP.reject { |name| skipped?(name) }
end end
def disabled_features def disabled_features
......
...@@ -6,6 +6,8 @@ class ProjectUrlConstrainer ...@@ -6,6 +6,8 @@ class ProjectUrlConstrainer
return false unless DynamicPathValidator.valid_project_path?(full_path) return false unless DynamicPathValidator.valid_project_path?(full_path)
# We intentionally allow SELECT(*) here so result of this query can be used
# as cache for further Project.find_by_full_path calls within request
Project.find_by_full_path(full_path, follow_redirects: request.get?).present? Project.find_by_full_path(full_path, follow_redirects: request.get?).present?
end end
end end
...@@ -98,10 +98,11 @@ module Gitlab ...@@ -98,10 +98,11 @@ module Gitlab
if status.zero? if status.zero?
@ee_branch_found = ee_branch_prefix @ee_branch_found = ee_branch_prefix
else return
_, status = step("Fetching origin/#{ee_branch_suffix}", %W[git fetch origin #{ee_branch_suffix}])
end end
_, status = step("Fetching origin/#{ee_branch_suffix}", %W[git fetch origin #{ee_branch_suffix}])
if status.zero? if status.zero?
@ee_branch_found = ee_branch_suffix @ee_branch_found = ee_branch_suffix
else else
......
...@@ -324,6 +324,23 @@ module Gitlab ...@@ -324,6 +324,23 @@ module Gitlab
raw_log(options).map { |c| Commit.decorate(self, c) } raw_log(options).map { |c| Commit.decorate(self, c) }
end end
# Used in gitaly-ruby
def raw_log(options)
actual_ref = options[:ref] || root_ref
begin
sha = sha_from_ref(actual_ref)
rescue Rugged::OdbError, Rugged::InvalidError, Rugged::ReferenceError
# Return an empty array if the ref wasn't found
return []
end
if log_using_shell?(options)
log_by_shell(sha, options)
else
log_by_walk(sha, options)
end
end
def count_commits(options) def count_commits(options)
gitaly_migrate(:count_commits) do |is_enabled| gitaly_migrate(:count_commits) do |is_enabled|
if is_enabled if is_enabled
...@@ -733,22 +750,6 @@ module Gitlab ...@@ -733,22 +750,6 @@ module Gitlab
sort_branches(branches, sort_by) sort_branches(branches, sort_by)
end end
def raw_log(options)
actual_ref = options[:ref] || root_ref
begin
sha = sha_from_ref(actual_ref)
rescue Rugged::OdbError, Rugged::InvalidError, Rugged::ReferenceError
# Return an empty array if the ref wasn't found
return []
end
if log_using_shell?(options)
log_by_shell(sha, options)
else
log_by_walk(sha, options)
end
end
def log_using_shell?(options) def log_using_shell?(options)
options[:path].present? || options[:path].present? ||
options[:disable_walk] || options[:disable_walk] ||
......
...@@ -10,7 +10,7 @@ module Gitlab ...@@ -10,7 +10,7 @@ module Gitlab
def exists? def exists?
request = Gitaly::RepositoryExistsRequest.new(repository: @gitaly_repo) request = Gitaly::RepositoryExistsRequest.new(repository: @gitaly_repo)
GitalyClient.call(@storage, :repository_service, :exists, request).exists GitalyClient.call(@storage, :repository_service, :repository_exists, request).exists
end end
def garbage_collect(create_bitmap) def garbage_collect(create_bitmap)
......
...@@ -71,7 +71,7 @@ module Gitlab ...@@ -71,7 +71,7 @@ module Gitlab
end end
def config def config
Gitlab.config.omniauth.providers.find{|provider| provider.name == "gitlab"} Gitlab.config.omniauth.providers.find {|provider| provider.name == "gitlab"}
end end
def gitlab_options def gitlab_options
......
...@@ -47,12 +47,16 @@ module Gitlab ...@@ -47,12 +47,16 @@ module Gitlab
end end
def remove_symlinks! def remove_symlinks!
Dir["#{@shared.export_path}/**/*"].each do |path| extracted_files.each do |path|
FileUtils.rm(path) if File.lstat(path).symlink? FileUtils.rm(path) if File.lstat(path).symlink?
end end
true true
end end
def extracted_files
Dir.glob("#{@shared.export_path}/**/*", File::FNM_DOTMATCH).reject { |f| f =~ /.*\/\.{1,2}$/ }
end
end end
end end
end end
...@@ -19,6 +19,8 @@ module Gitlab ...@@ -19,6 +19,8 @@ module Gitlab
return false if internal?(uri) return false if internal?(uri)
return true if blocked_port?(uri.port) return true if blocked_port?(uri.port)
return true if blocked_user_or_hostname?(uri.user)
return true if blocked_user_or_hostname?(uri.hostname)
server_ips = Resolv.getaddresses(uri.hostname) server_ips = Resolv.getaddresses(uri.hostname)
return true if (blocked_ips & server_ips).any? return true if (blocked_ips & server_ips).any?
...@@ -37,6 +39,12 @@ module Gitlab ...@@ -37,6 +39,12 @@ module Gitlab
port < 1024 && !VALID_PORTS.include?(port) port < 1024 && !VALID_PORTS.include?(port)
end end
def blocked_user_or_hostname?(value)
return false if value.blank?
value !~ /\A\p{Alnum}/
end
def internal?(uri) def internal?(uri)
internal_web?(uri) || internal_shell?(uri) internal_web?(uri) || internal_shell?(uri)
end end
......
...@@ -25,6 +25,39 @@ map $http_upgrade $connection_upgrade_gitlab { ...@@ -25,6 +25,39 @@ map $http_upgrade $connection_upgrade_gitlab {
'' close; '' close;
} }
## NGINX 'combined' log format with filtered query strings
log_format gitlab_access $remote_addr - $remote_user [$time_local] "$request_method $gitlab_filtered_request_uri $server_protocol" $status $body_bytes_sent "$gitlab_filtered_http_referer" "$http_user_agent";
## Remove private_token from the request URI
# In: /foo?private_token=unfiltered&authenticity_token=unfiltered&rss_token=unfiltered&...
# Out: /foo?private_token=[FILTERED]&authenticity_token=unfiltered&rss_token=unfiltered&...
map $request_uri $gitlab_temp_request_uri_1 {
default $request_uri;
~(?i)^(?<start>.*)(?<temp>[\?&]private[\-_]token)=[^&]*(?<rest>.*)$ "$start$temp=[FILTERED]$rest";
}
## Remove authenticity_token from the request URI
# In: /foo?private_token=[FILTERED]&authenticity_token=unfiltered&rss_token=unfiltered&...
# Out: /foo?private_token=[FILTERED]&authenticity_token=[FILTERED]&rss_token=unfiltered&...
map $gitlab_temp_request_uri_1 $gitlab_temp_request_uri_2 {
default $gitlab_temp_request_uri_1;
~(?i)^(?<start>.*)(?<temp>[\?&]authenticity[\-_]token)=[^&]*(?<rest>.*)$ "$start$temp=[FILTERED]$rest";
}
## Remove rss_token from the request URI
# In: /foo?private_token=[FILTERED]&authenticity_token=[FILTERED]&rss_token=unfiltered&...
# Out: /foo?private_token=[FILTERED]&authenticity_token=[FILTERED]&rss_token=[FILTERED]&...
map $gitlab_temp_request_uri_2 $gitlab_filtered_request_uri {
default $gitlab_temp_request_uri_2;
~(?i)^(?<start>.*)(?<temp>[\?&]rss[\-_]token)=[^&]*(?<rest>.*)$ "$start$temp=[FILTERED]$rest";
}
## A version of the referer without the query string
map $http_referer $gitlab_filtered_http_referer {
default $http_referer;
~^(?<temp>.*)\? $temp;
}
## Normal HTTP host ## Normal HTTP host
server { server {
## Either remove "default_server" from the listen line below, ## Either remove "default_server" from the listen line below,
...@@ -46,7 +79,7 @@ server { ...@@ -46,7 +79,7 @@ server {
# set_real_ip_from YOUR_TRUSTED_ADDRESS; ## Replace this with something like 192.168.1.0/24 # set_real_ip_from YOUR_TRUSTED_ADDRESS; ## Replace this with something like 192.168.1.0/24
## Individual nginx logs for this GitLab vhost ## Individual nginx logs for this GitLab vhost
access_log /var/log/nginx/gitlab_access.log; access_log /var/log/nginx/gitlab_access.log gitlab_access;
error_log /var/log/nginx/gitlab_error.log; error_log /var/log/nginx/gitlab_error.log;
location / { location / {
......
...@@ -18,8 +18,11 @@ server { ...@@ -18,8 +18,11 @@ server {
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache off;
# The same address as passed to GitLab Pages: `-listen-proxy` # The same address as passed to GitLab Pages: `-listen-proxy`
proxy_pass http://localhost:8090/; proxy_pass http://localhost:8090/;
} }
# Define custom error pages # Define custom error pages
......
...@@ -67,8 +67,11 @@ server { ...@@ -67,8 +67,11 @@ server {
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache off;
# The same address as passed to GitLab Pages: `-listen-proxy` # The same address as passed to GitLab Pages: `-listen-proxy`
proxy_pass http://localhost:8090/; proxy_pass http://localhost:8090/;
} }
# Define custom error pages # Define custom error pages
......
...@@ -29,6 +29,41 @@ map $http_upgrade $connection_upgrade_gitlab_ssl { ...@@ -29,6 +29,41 @@ map $http_upgrade $connection_upgrade_gitlab_ssl {
'' close; '' close;
} }
## NGINX 'combined' log format with filtered query strings
log_format gitlab_ssl_access $remote_addr - $remote_user [$time_local] "$request_method $gitlab_ssl_filtered_request_uri $server_protocol" $status $body_bytes_sent "$gitlab_ssl_filtered_http_referer" "$http_user_agent";
## Remove private_token from the request URI
# In: /foo?private_token=unfiltered&authenticity_token=unfiltered&rss_token=unfiltered&...
# Out: /foo?private_token=[FILTERED]&authenticity_token=unfiltered&rss_token=unfiltered&...
map $request_uri $gitlab_ssl_temp_request_uri_1 {
default $request_uri;
~(?i)^(?<start>.*)(?<temp>[\?&]private[\-_]token)=[^&]*(?<rest>.*)$ "$start$temp=[FILTERED]$rest";
}
## Remove authenticity_token from the request URI
# In: /foo?private_token=[FILTERED]&authenticity_token=unfiltered&rss_token=unfiltered&...
# Out: /foo?private_token=[FILTERED]&authenticity_token=[FILTERED]&rss_token=unfiltered&...
map $gitlab_ssl_temp_request_uri_1 $gitlab_ssl_temp_request_uri_2 {
default $gitlab_ssl_temp_request_uri_1;
~(?i)^(?<start>.*)(?<temp>[\?&]authenticity[\-_]token)=[^&]*(?<rest>.*)$ "$start$temp=[FILTERED]$rest";
}
## Remove rss_token from the request URI
# In: /foo?private_token=[FILTERED]&authenticity_token=[FILTERED]&rss_token=unfiltered&...
# Out: /foo?private_token=[FILTERED]&authenticity_token=[FILTERED]&rss_token=[FILTERED]&...
map $gitlab_ssl_temp_request_uri_2 $gitlab_ssl_filtered_request_uri {
default $gitlab_ssl_temp_request_uri_2;
~(?i)^(?<start>.*)(?<temp>[\?&]rss[\-_]token)=[^&]*(?<rest>.*)$ "$start$temp=[FILTERED]$rest";
}
## A version of the referer without the query string
map $http_referer $gitlab_ssl_filtered_http_referer {
default $http_referer;
~^(?<temp>.*)\? $temp;
}
## Redirects all HTTP traffic to the HTTPS host ## Redirects all HTTP traffic to the HTTPS host
server { server {
## Either remove "default_server" from the listen line below, ## Either remove "default_server" from the listen line below,
...@@ -40,7 +75,7 @@ server { ...@@ -40,7 +75,7 @@ server {
server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com
server_tokens off; ## Don't show the nginx version number, a security best practice server_tokens off; ## Don't show the nginx version number, a security best practice
return 301 https://$http_host$request_uri; return 301 https://$http_host$request_uri;
access_log /var/log/nginx/gitlab_access.log; access_log /var/log/nginx/gitlab_access.log gitlab_ssl_access;
error_log /var/log/nginx/gitlab_error.log; error_log /var/log/nginx/gitlab_error.log;
} }
...@@ -93,7 +128,7 @@ server { ...@@ -93,7 +128,7 @@ server {
# set_real_ip_from YOUR_TRUSTED_ADDRESS; ## Replace this with something like 192.168.1.0/24 # set_real_ip_from YOUR_TRUSTED_ADDRESS; ## Replace this with something like 192.168.1.0/24
## Individual nginx logs for this GitLab vhost ## Individual nginx logs for this GitLab vhost
access_log /var/log/nginx/gitlab_access.log; access_log /var/log/nginx/gitlab_access.log gitlab_ssl_access;
error_log /var/log/nginx/gitlab_error.log; error_log /var/log/nginx/gitlab_error.log;
location / { location / {
......
...@@ -41,8 +41,6 @@ namespace :gitlab do ...@@ -41,8 +41,6 @@ namespace :gitlab do
end end
namespace :gitlab_shell do namespace :gitlab_shell do
include SystemCheck::Helpers
desc "GitLab | Check the configuration of GitLab Shell" desc "GitLab | Check the configuration of GitLab Shell"
task check: :environment do task check: :environment do
warn_user_is_not_gitlab warn_user_is_not_gitlab
...@@ -249,8 +247,6 @@ namespace :gitlab do ...@@ -249,8 +247,6 @@ namespace :gitlab do
end end
namespace :sidekiq do namespace :sidekiq do
include SystemCheck::Helpers
desc "GitLab | Check the configuration of Sidekiq" desc "GitLab | Check the configuration of Sidekiq"
task check: :environment do task check: :environment do
warn_user_is_not_gitlab warn_user_is_not_gitlab
...@@ -309,8 +305,6 @@ namespace :gitlab do ...@@ -309,8 +305,6 @@ namespace :gitlab do
end end
namespace :incoming_email do namespace :incoming_email do
include SystemCheck::Helpers
desc "GitLab | Check the configuration of Reply by email" desc "GitLab | Check the configuration of Reply by email"
task check: :environment do task check: :environment do
warn_user_is_not_gitlab warn_user_is_not_gitlab
...@@ -444,8 +438,6 @@ namespace :gitlab do ...@@ -444,8 +438,6 @@ namespace :gitlab do
end end
namespace :ldap do namespace :ldap do
include SystemCheck::Helpers
task :check, [:limit] => :environment do |_, args| task :check, [:limit] => :environment do |_, args|
# Only show up to 100 results because LDAP directories can be very big. # Only show up to 100 results because LDAP directories can be very big.
# This setting only affects the `rake gitlab:check` script. # This setting only affects the `rake gitlab:check` script.
...@@ -501,8 +493,6 @@ namespace :gitlab do ...@@ -501,8 +493,6 @@ namespace :gitlab do
end end
namespace :repo do namespace :repo do
include SystemCheck::Helpers
desc "GitLab | Check the integrity of the repositories managed by GitLab" desc "GitLab | Check the integrity of the repositories managed by GitLab"
task check: :environment do task check: :environment do
Gitlab.config.repositories.storages.each do |name, repository_storage| Gitlab.config.repositories.storages.each do |name, repository_storage|
...@@ -517,8 +507,6 @@ namespace :gitlab do ...@@ -517,8 +507,6 @@ namespace :gitlab do
end end
namespace :user do namespace :user do
include SystemCheck::Helpers
desc "GitLab | Check the integrity of a specific user's repositories" desc "GitLab | Check the integrity of a specific user's repositories"
task :check_repos, [:username] => :environment do |t, args| task :check_repos, [:username] => :environment do |t, args|
username = args[:username] || prompt("Check repository integrity for fsername? ".color(:blue)) username = args[:username] || prompt("Check repository integrity for fsername? ".color(:blue))
......
...@@ -4,5 +4,5 @@ require 'tasks/gitlab/task_helpers' ...@@ -4,5 +4,5 @@ require 'tasks/gitlab/task_helpers'
StateMachines::Machine.ignore_method_conflicts = true if ENV['CRON'] StateMachines::Machine.ignore_method_conflicts = true if ENV['CRON']
namespace :gitlab do namespace :gitlab do
include Gitlab::TaskHelpers extend SystemCheck::Helpers
end end
...@@ -5,6 +5,8 @@ module Gitlab ...@@ -5,6 +5,8 @@ module Gitlab
TaskAbortedByUserError = Class.new(StandardError) TaskAbortedByUserError = Class.new(StandardError)
module TaskHelpers module TaskHelpers
extend self
# Ask if the user wants to continue # Ask if the user wants to continue
# #
# Returns "yes" the user chose to continue # Returns "yes" the user chose to continue
......
...@@ -417,7 +417,7 @@ msgstr[0] "Fourche" ...@@ -417,7 +417,7 @@ msgstr[0] "Fourche"
msgstr[1] "Fourches" msgstr[1] "Fourches"
msgid "ForkedFromProjectPath|Forked from" msgid "ForkedFromProjectPath|Forked from"
msgstr "Fouché depuis" msgstr "Fourché depuis"
msgid "From issue creation until deploy to production" msgid "From issue creation until deploy to production"
msgstr "Depuis la création de l'incident jusqu'au déploiement en production" msgstr "Depuis la création de l'incident jusqu'au déploiement en production"
......
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