merge master and fix application.rb conflict

This commit is contained in:
Regis 2016-12-23 16:34:56 -07:00
commit 71d731a21b
358 changed files with 2695 additions and 1461 deletions

View File

@ -2,6 +2,223 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 8.15.1 (2016-12-23)
- Push payloads schedule at most 100 commits, instead of all commits.
- Fix Mattermost command creation by specifying username.
- Do not override incoming webhook for mattermost and slack.
- Adds background color for disabled state to merge when succeeds dropdown. !8222
- Standardises font-size for titles in Issues, Merge Requests and Merge Request widget. !8235
- Fix Pipeline builds list blank on MR. !8255
- Do not show retried builds in pipeline stage dropdown. !8260
## 8.15.0 (2016-12-22)
- Whitelist next project names: notes, services.
- Use Grape's new Route methods.
- Fixed issue boards scrolling with a lot of lists & issues.
- Remove unnecessary sentences for status codes in the API documentation. (Luis Alonso Chavez Armendariz)
- Allow unauthenticated access to Repositories Files API GET endpoints.
- Add note to the invite page when the logged in user email is not the same as the invitation.
- Don't accidentally mark unsafe diff lines as HTML safe.
- Add git diff context to notifications of new notes on merge requests. (Heidi Hoopes)
- Shows group members in project members list.
- Gem update: Update grape to 0.18.0. (Robert Schilling)
- API: Expose merge status for branch API. (Robert Schilling)
- Displays milestone remaining days only when it's present.
- API: Expose committer details for commits. (Robert Schilling)
- API: Ability to set 'should_remove_source_branch' on merge requests. (Robert Schilling)
- Fix project import label priorities error.
- Fix Import/Export merge requests error while importing.
- Refactor Bitbucket importer to use BitBucket API Version 2.
- Fix Import/Export duplicated builds error.
- Ci::Builds have same ref as Ci::Pipeline in dev fixtures. (twonegatives)
- For single line git commit messages, the close quote should be on the same line as the open quote.
- Use authorized projects in ProjectTeam.
- Destroy a user's session when they delete their own account.
- Edit help text to clarify annotated tag creation. (Liz Lam)
- Fixed file template dropdown for the "New File" editor for smaller/zoomed screens.
- Fix Route#rename_children behavior.
- Add nested groups support on data level.
- Allow projects with 'dashboard' as path.
- Disabled emoji buttons when user is not logged in.
- Remove unused and void services from the database.
- Add issue search slash command.
- Accept issue new as command to create an issue.
- Non members cannot create labels through the API.
- API: expose pipeline coverage.
- Validate state param when filtering issuables.
- Username exists check respects relative root path.
- Bump Git version requirement to 2.8.4.
- Updates the font weight of button styles because of the change to system fonts.
- Update API spec files to describe the correct class. (Livier)
- Fixed timeago re-rendering every timeago.
- Enable ColorVariable in scss-lint. (Sam Rose)
- Various small emoji positioning adjustments.
- Add shortcuts for adding users to a project team with a specific role. (Nikolay Ponomarev and Dino M)
- Additional rounded label fixes.
- Remove unnecessary database indices.
- 24726 Remove Across GitLab from side navigation.
- Changed cursor icon to pointer when mousing over stages on the Cycle Analytics pages. (Ryan Harris)
- Add focus state to dropdown items.
- Fixes Environments displaying incorrect date since 8.14 upgrade.
- Improve bulk assignment for issuables.
- Stop supporting Google and Azure as backup strategies.
- Fix broken README.md UX guide link.
- Allow public access to some Tag API endpoints.
- Encode input when migrating ProcessCommitWorker jobs to prevent migration errors.
- Adjust the width of project avatars to fix alignment within their container. (Ryan Harris)
- Sentence cased the nav tab headers on the project dashboard page. (Ryan Harris)
- Adds hoverstates for collapsed Issue/Merge Request sidebar.
- Make CI badge hitboxes match parent.
- Add a starting date to milestones.
- Adjusted margins for Build Status and Coverage Report rows to match those of the CI/CD Pipeline row. (Ryan Harris)
- Updated members dropdowns.
- Move all action buttons to project header.
- Replace issue access checks with use of IssuableFinder.
- Fix missing Note access checks by moving Note#search to updated NoteFinder.
- Centered Accept Merge Request button within MR widget and added padding for viewports smaller than 768px. (Ryan Harris)
- Fix missing access checks on issue lookup using IssuableFinder.
- Added top margin to Build status page header for mobile views. (Ryan Harris)
- Fixes "ActionView::Template::Error: undefined method `text?` for nil:NilClass" on MR pages.
- Issue#visible_to_user moved to IssuesFinder to prevent accidental use.
- Replace MR access checks with use of MergeRequestsFinder.
- Fix information disclosure in `Projects::BlobController#update`.
- Allow branch names with dots on API endpoint.
- Changed Housekeeping button on project settings page to default styling. (Ryan Harris)
- Ensure issuable state changes only fire webhooks once.
- Fix bad selection on dropdown menu for tags filter. (Luis Alonso Chavez Armendariz)
- Fix title case to sentence case. (Luis Alonso Chavez Armendariz)
- Fix appearance in error pages. (Luis Alonso Chavez Armendariz)
- Create mattermost service.
- 25617 Fix placeholder color of todo filters.
- Made the padding on the plus button in the breadcrumb menu even. (Ryan Harris)
- Allow to delete tag release note.
- Ensure nil User-Agent doesn't break the CI API.
- Replace Rack::Multipart with GitLab-Workhorse based solution. !5867
- Add scopes for personal access tokens and OAuth tokens. !5951
- API: Endpoint to expose personal snippets as /snippets. !6373 (Bernard Guyzmo Pratz)
- New `gitlab:workhorse:install` rake task. !6574
- Filter protocol-relative URLs in ExternalLinkFilter. Fixes issue #22742. !6635 (Makoto Scott-Hinkle)
- Add support for setting the GitLab Runners Registration Token during initial database seeding. !6642
- Guests can read builds when public. !6842
- Made comment autocomplete more performant and removed some loading bugs. !6856
- Add GitLab host to 2FA QR code and manual info. !6941
- Add sorting functionality for group/project members. !7032
- Rename Merge When Build Succeeds to Merge When Pipeline Succeeds. !7135
- Resolve all discussions in a merge request by creating an issue collecting them. !7180 (Bob Van Landuyt)
- Add Human Readable format for rake backup. !7188 (David Gerő)
- post_receive: accept any user email from last commit. !7225 (Elan Ruusamäe)
- Add support for Dockerfile templates. !7247
- Add shorthand support to gitlab markdown references. !7255 (Oswaldo Ferreira)
- Display error code for U2F errors. !7305 (winniehell)
- Fix wrong tab selected when loggin fails and multiple login tabs exists. !7314 (Jacopo Beschi @jacopo-beschi)
- Clean up common_utils.js. !7318 (winniehell)
- Show commit status from latest pipeline. !7333
- Remove the help text under the sidebar subscribe button and style it inline. !7389
- Update wiki page design. !7429
- Add nested groups support to the routing. !7459
- Changed eslint airbnb config to the base airbnb config and corrected eslintrc plugins and envs. !7470 (Luke "Jared" Bennett)
- Fix cancelling created or external pipelines. !7508
- Allow admins to stop impersonating users without e-mail addresses. !7550 (Oren Kanner)
- Remove unnecessary self from user model. !7551 (Semyon Pupkov)
- Homogenize filter and sort dropdown look'n'feel. !7583 (David Wagner)
- Create dynamic fixture for build_spec. !7589 (winniehell)
- Moved Leave Project and Leave Group buttons to access_request_buttons from the settings dropdown. !7600
- Remove unnecessary require_relative calls from service classes. !7601 (Semyon Pupkov)
- Simplify copy on "Create a new list" dropdown in Issue Boards. !7605 (Victor Rodrigues)
- Refactor create service spec. !7609 (Semyon Pupkov)
- Shows unconfirmed email status in profile. !7611
- The admin user projects view now has a clickable group link. !7620 (James Gregory)
- Prevent DOM ID collisions resulting from user-generated content anchors. !7631
- Replace static fixture for abuse_reports_spec. !7644 (winniehell)
- Define common helper for describe pagination params in api. !7646 (Semyon Pupkov)
- Move abuse report spinach test to rspec. !7659 (Semyon Pupkov)
- Replace static fixture for awards_handler_spec. !7661 (winniehell)
- API: Add ability to unshare a project from a group. !7662 (Robert Schilling)
- Replace references to MergeRequestDiff#commits with st_commits when we care only about the number of commits. !7668
- Add issue events filter and make all really show all events. !7673 (Oxan van Leeuwen)
- Replace static fixture for notes_spec. !7683 (winniehell)
- Replace static fixture for shortcuts_issuable_spec. !7685 (winniehell)
- Replace static fixture for zen_mode_spec. !7686 (winniehell)
- Replace static fixture for right_sidebar_spec. !7687 (winniehell)
- Add online terminal support for Kubernetes. !7690
- Move admin abuse report spinach test to rspec. !7691 (Semyon Pupkov)
- Move admin spam spinach test to Rspec. !7708 (Semyon Pupkov)
- Make API::Helpers find a project with only one query. !7714
- Create builds in transaction to avoid empty pipelines. !7742
- Render SVG images in diffs and notes. !7747 (andrebsguedes)
- Add setting to enable/disable HTML emails. !7749
- Use SmartInterval for MR widget and improve visibilitychange functionality. !7762
- Resolve "Remove Builds tab from Merge Requests and Commits". !7763
- Moved new projects button below new group button on the welcome screen. !7770
- fix display hook error message. !7775 (basyura)
- Refactor issuable_filters_present to reduce duplications. !7776 (Semyon Pupkov)
- Redirect to sign-in page when unauthenticated user tries to create a snippet. !7786
- Fix Archived project merge requests add to group's Merge Requests. !7790 (Jacopo Beschi @jacopo-beschi)
- Update generic/external build status to match normal build status template. !7811
- Enable AsciiDoctor admonition icons. !7812 (Horacio Sanson)
- Do not raise error in AutocompleteController#users when not authorized. !7817 (Semyon Pupkov)
- fix: 24982- Remove'Signed in successfully' message After this change the sign-in-success flash message will not be shown. !7837 (jnoortheen)
- Fix Latest deployment link is broken. !7839
- Don't display prompt to add SSH keys if SSH protocol is disabled. !7840 (Andrew Smith (EspadaV8))
- Allow unauthenticated access to some Project API GET endpoints. !7843
- Refactor presenters ChatCommands. !7846
- Improve help message for issue create slash command. !7850
- change text around timestamps to make it clear which timestamp is displayed. !7860 (BM5k)
- Improve Build Log scrolling experience. !7895
- Change ref property to commitRef in vue commit component. !7901
- Prevent user creating issue or MR without signing in for a group. !7902
- Provides a sensible default message when adding a README to a project. !7903
- Bump ruby version to 2.3.3. !7904
- Fix comments activity tab visibility condition. !7913 (Rydkin Maxim)
- Remove unnecessary target branch link from MR page in case of deleted target branch. !7916 (Rydkin Maxim)
- Add image controls to MR diffs. !7919
- Remove wrong '.builds-feature' class from the MR settings fieldset. !7930
- Resolve "Manual actions on pipeline graph". !7931
- Avoid escaping relative links in Markdown twice. !7940 (winniehell)
- Move admin hooks spinach to rspec. !7942 (Semyon Pupkov)
- Move admin logs spinach test to rspec. !7945 (Semyon Pupkov)
- fix: removed signed_out notification. !7958 (jnoortheen)
- Accept environment variables from the `pre-receive` script. !7967
- Do not reload diff for merge request made from fork when target branch in fork is updated. !7973
- Fixes left align issue for long system notes. !7982
- Add a slug to environments. !7983
- Fix lookup of project by unknown ref when caching is enabled. !7988
- Resolve "Provide SVG as a prop instead of hiding and copy them in environments table". !7992
- Introduce deployment services, starting with a KubernetesService. !7994
- Adds tests for custom event polyfill. !7996
- Allow all alphanumeric characters in file names. !8002 (winniehell)
- Added support for math rendering, using KaTeX, in Markdown and asciidoc. !8003 (Munken)
- Remove unnecessary commits order message. !8004
- API: Memoize the current_user so that sudo can work properly. !8017
- group authors in contribution graph with case insensitive email handle comparison. !8021
- Move admin active tab spinach tests to rspec. !8037 (Semyon Pupkov)
- Add Authentiq as Oauth provider. !8038 (Alexandros Keramidas)
- API: Ability to cherry pick a commit. !8047 (Robert Schilling)
- Fix Slack pipeline message from pipelines made by API. !8059
- API: Simple representation of group's projects. !8060 (Robert Schilling)
- Prevent overflow with vertical scroll when we have space to show content. !8061
- Allow to auto-configure Mattermost. !8070
- Introduce $CI_BUILD_REF_SLUG. !8072
- Added go back anchor on error pages. !8087
- Convert CI YAML variables keys into strings. !8088
- Adds Direct link from pipeline list to builds. !8097
- Cache last commit id for path. !8098 (Hiroyuki Sato)
- Pass variables from deployment project services to CI runner. !8107
- New Gitea importer. !8116
- Introduce "Set up autodeploy" button to help configure GitLab CI for deployment. !8135
- Prevent enviroment table to overflow when name has underscores. !8142
- Fix missing service error importing from EE to CE. !8144
- Milestoneish SQL performance partially improved and memoized. !8146
- Allow unauthenticated access to Repositories API GET endpoints. !8148
- fix colors and margins for adjacent alert banners. !8151
- Hides new issue button for non loggedin user. !8175
- Fix N+1 queries on milestone show pages. !8185
- Rename groups with .git in the end of the path. !8199
- Whitelist next project names: help, ci, admin, search. !8227
- Adds back CSS for progress-bars. !8237
## 8.14.5 (2016-12-14)
- Moved Leave Project and Leave Group buttons to access_request_buttons from the settings dropdown. !7600

View File

@ -32,6 +32,7 @@ gem 'omniauth-saml', '~> 1.7.0'
gem 'omniauth-shibboleth', '~> 1.2.0'
gem 'omniauth-twitter', '~> 1.2.0'
gem 'omniauth_crowd', '~> 2.2.0'
gem 'omniauth-authentiq', '~> 0.2.0'
gem 'rack-oauth2', '~> 1.2.1'
gem 'jwt'

View File

@ -428,6 +428,8 @@ GEM
rack (>= 1.0, < 3)
omniauth-auth0 (1.4.1)
omniauth-oauth2 (~> 1.1)
omniauth-authentiq (0.2.2)
omniauth-oauth2 (~> 1.3, >= 1.3.1)
omniauth-azure-oauth2 (0.0.6)
jwt (~> 1.0)
omniauth (~> 1.0)
@ -897,6 +899,7 @@ DEPENDENCIES
oj (~> 2.17.4)
omniauth (~> 1.3.1)
omniauth-auth0 (~> 1.4.1)
omniauth-authentiq (~> 0.2.0)
omniauth-azure-oauth2 (~> 0.0.6)
omniauth-cas3 (~> 1.1.2)
omniauth-facebook (~> 4.0.0)

View File

@ -1 +1 @@
8.15.0-pre
8.16.0-pre

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -4,6 +4,7 @@
(function() {
var bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
var AUTO_SCROLL_OFFSET = 75;
this.Build = (function() {
Build.interval = null;
@ -19,6 +20,17 @@
this.buildStage = options.buildStage;
this.updateDropdown = bind(this.updateDropdown, this);
this.$document = $(document);
this.$body = $('body');
this.$buildTrace = $('#build-trace');
this.$autoScrollContainer = $('.autoscroll-container');
this.$autoScrollStatus = $('#autoscroll-status');
this.$autoScrollStatusText = this.$autoScrollStatus.find('.status-text');
this.$upBuildTrace = $('#up-build-trace');
this.$downBuildTrace = $('#down-build-trace');
this.$scrollTopBtn = $('#scroll-top');
this.$scrollBottomBtn = $('#scroll-bottom');
this.$buildRefreshAnimation = $('.js-build-refresh');
clearInterval(Build.interval);
// Init breakpoint checker
this.bp = Breakpoints.get();
@ -32,6 +44,7 @@
this.$document.off('click', '.js-sidebar-build-toggle').on('click', '.js-sidebar-build-toggle', this.sidebarOnClick.bind(this));
this.$document.off('click', '.stage-item').on('click', '.stage-item', this.updateDropdown);
this.$document.on('scroll', this.initScrollMonitor.bind(this));
$(window).off('resize.build').on('resize.build', this.sidebarOnResize.bind(this));
$('a', this.$buildScroll).off('click.stepTrace').on('click.stepTrace', this.stepTrace);
this.updateArtifactRemoveDate();
@ -40,18 +53,6 @@
this.initScrollButtonAffix();
}
if (this.buildStatus === "running" || this.buildStatus === "pending") {
// Bind autoscroll button to follow build output
$('#autoscroll-button').on('click', function() {
var state;
state = $(this).data("state");
if ("enabled" === state) {
$(this).data("state", "disabled");
return $(this).text("Enable autoscroll");
} else {
$(this).data("state", "enabled");
return $(this).text("Disable autoscroll");
}
});
Build.interval = setInterval((function(_this) {
// Check for new build output if user still watching build page
// Only valid for runnig build when output changes during time
@ -91,9 +92,10 @@
success: function(buildData) {
$('.js-build-output').html(buildData.trace_html);
if (removeRefreshStatuses.indexOf(buildData.status) >= 0) {
return $('.js-build-refresh').remove();
this.initScrollMonitor();
return this.$buildRefreshAnimation.remove();
}
}
}.bind(this)
});
};
@ -122,22 +124,95 @@
};
Build.prototype.checkAutoscroll = function() {
if ("enabled" === $("#autoscroll-button").data("state")) {
return $("html,body").scrollTop($("#build-trace").height());
if (this.$autoScrollStatus.data("state") === "enabled") {
return $("html,body").scrollTop(this.$buildTrace.height());
}
// Handle a situation where user started new build
// but never scrolled a page
if (!this.$scrollTopBtn.is(':visible') &&
!this.$scrollBottomBtn.is(':visible') &&
!gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
this.$scrollBottomBtn.show();
}
};
Build.prototype.initScrollButtonAffix = function() {
var $body, $buildTrace;
$body = $('body');
$buildTrace = $('#build-trace');
return this.$buildScroll.affix({
offset: {
bottom: function() {
return $body.outerHeight() - ($buildTrace.outerHeight() + $buildTrace.offset().top);
}
// Hide everything initially
this.$scrollTopBtn.hide();
this.$scrollBottomBtn.hide();
this.$autoScrollContainer.hide();
}
// Page scroll listener to detect if user has scrolling page
// and handle following cases
// 1) User is at Top of Build Log;
// - Hide Top Arrow button
// - Show Bottom Arrow button
// - Disable Autoscroll and hide indicator (when build is running)
// 2) User is at Bottom of Build Log;
// - Show Top Arrow button
// - Hide Bottom Arrow button
// - Enable Autoscroll and show indicator (when build is running)
// 3) User is somewhere in middle of Build Log;
// - Show Top Arrow button
// - Show Bottom Arrow button
// - Disable Autoscroll and hide indicator (when build is running)
Build.prototype.initScrollMonitor = function() {
if (!gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
// User is somewhere in middle of Build Log
this.$scrollTopBtn.show();
if (this.buildStatus === 'success' || this.buildStatus === 'failed') { // Check if Build is completed
this.$scrollBottomBtn.show();
} else if (this.$buildRefreshAnimation.is(':visible') && !gl.utils.isInViewport(this.$buildRefreshAnimation.get(0))) {
this.$scrollBottomBtn.show();
} else {
this.$scrollBottomBtn.hide();
}
});
// Hide Autoscroll Status Indicator
if (this.$scrollBottomBtn.is(':visible')) {
this.$autoScrollContainer.hide();
this.$autoScrollStatusText.removeClass('animate');
} else {
this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).show();
this.$autoScrollStatusText.addClass('animate');
}
} else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && !gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
// User is at Top of Build Log
this.$scrollTopBtn.hide();
this.$scrollBottomBtn.show();
this.$autoScrollContainer.hide();
this.$autoScrollStatusText.removeClass('animate');
} else if ((!gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) ||
(this.$buildRefreshAnimation.is(':visible') && gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)))) {
// User is at Bottom of Build Log
this.$scrollTopBtn.show();
this.$scrollBottomBtn.hide();
// Show and Reposition Autoscroll Status Indicator
this.$autoScrollContainer.css({ top: this.$body.outerHeight() - AUTO_SCROLL_OFFSET }).show();
this.$autoScrollStatusText.addClass('animate');
} else if (gl.utils.isInViewport(this.$upBuildTrace.get(0)) && gl.utils.isInViewport(this.$downBuildTrace.get(0))) {
// Build Log height is small
this.$scrollTopBtn.hide();
this.$scrollBottomBtn.hide();
// Hide Autoscroll Status Indicator
this.$autoScrollContainer.hide();
this.$autoScrollStatusText.removeClass('animate');
}
if (this.buildStatus === "running" || this.buildStatus === "pending") {
// Check if Refresh Animation is in Viewport and enable Autoscroll, disable otherwise.
this.$autoScrollStatus.data("state", gl.utils.isInViewport(this.$buildRefreshAnimation.get(0)) ? 'enabled' : 'disabled');
}
};
Build.prototype.shouldHideSidebarForViewport = function() {

View File

@ -138,14 +138,8 @@
new MergedButtons();
break;
case 'projects:merge_requests:commits':
case 'projects:merge_requests:builds':
new MergedButtons();
break;
case 'projects:merge_requests:pipelines':
new gl.MiniPipelineGraph({
container: '.js-pipeline-table',
});
break;
case "projects:merge_requests:diffs":
new gl.Diff();
new ZenMode();
@ -168,9 +162,6 @@
container: '.js-pipeline-table',
});
break;
case 'projects:commit:builds':
new gl.Pipelines();
break;
case 'projects:commits:show':
case 'projects:activity':
shortcut_handler = new ShortcutsNavigation();

View File

@ -74,15 +74,16 @@
// The below is taken from At.js source
// Tweaked to commands to start without a space only if char before is a non-word character
// https://github.com/ichord/At.js
var _a, _y, regexp, match, atSymbols;
atSymbols = Object.keys(this.app.controllers).join('|');
var _a, _y, regexp, match, atSymbolsWithBar, atSymbolsWithoutBar;
atSymbolsWithBar = Object.keys(this.app.controllers).join('|');
atSymbolsWithoutBar = Object.keys(this.app.controllers).join('');
subtext = subtext.split(' ').pop();
flag = flag.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
_a = decodeURI("%C3%80");
_y = decodeURI("%C3%BF");
regexp = new RegExp("(?:\\B|\\W|\\s)" + flag + "(?![" + atSymbols + "])([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)$", 'gi');
regexp = new RegExp("^(?:\\B|[^a-zA-Z0-9_" + atSymbolsWithoutBar + "]|\\s)" + flag + "(?![" + atSymbolsWithBar + "])([A-Za-z" + _a + "-" + _y + "0-9_\'\.\+\-]*)$", 'gi');
match = regexp.exec(subtext);
@ -112,7 +113,6 @@
return value.path != null ? this.Emoji.template : this.Loading.template;
}.bind(this),
insertTpl: ':${name}:',
startWithSpace: false,
skipSpecialCharacterTest: true,
data: this.defaultLoadingData,
callbacks: {
@ -129,7 +129,6 @@
}.bind(this),
insertTpl: '${atwho-at}${username}',
searchKey: 'search',
startWithSpace: false,
alwaysHighlightFirst: true,
skipSpecialCharacterTest: true,
data: this.defaultLoadingData,
@ -172,7 +171,6 @@
}.bind(this),
data: this.defaultLoadingData,
insertTpl: '${atwho-at}${id}',
startWithSpace: false,
callbacks: {
sorter: this.DefaultOptions.sorter,
filter: this.DefaultOptions.filter,
@ -200,7 +198,6 @@
displayTpl: function(value) {
return value.title != null ? this.Milestones.template : this.Loading.template;
}.bind(this),
startWithSpace: false,
data: this.defaultLoadingData,
callbacks: {
matcher: this.DefaultOptions.matcher,
@ -225,7 +222,6 @@
at: '!',
alias: 'mergerequests',
searchKey: 'search',
startWithSpace: false,
displayTpl: function(value) {
return value.title != null ? this.Issues.template : this.Loading.template;
}.bind(this),
@ -259,7 +255,6 @@
return this.isLoading(value) ? this.Loading.template : this.Labels.template;
}.bind(this),
insertTpl: '${atwho-at}${title}',
startWithSpace: false,
callbacks: {
matcher: this.DefaultOptions.matcher,
sorter: this.DefaultOptions.sorter,
@ -379,14 +374,7 @@
togglePreventSelection(isPrevented = !!this.setting.tabSelectsMatch) {
this.setting.tabSelectsMatch = !isPrevented;
this.setting.spaceSelectsMatch = !isPrevented;
const eventListenerAction = `${isPrevented ? 'add' : 'remove'}EventListener`;
this.$inputor[0][eventListenerAction]('keydown', gl.GfmAutoComplete.preventSpaceTabEnter);
},
preventSpaceTabEnter(e) {
const key = e.which || e.keyCode;
const preventables = [9, 13, 32];
if (preventables.indexOf(key) > -1) e.preventDefault();
}
};
}).call(this);

View File

@ -1,13 +1,13 @@
/* eslint-disable func-names, no-var, camelcase, no-unused-vars, object-shorthand, space-before-function-paren, no-return-assign, comma-dangle, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, prefer-arrow-callback, prefer-const, padded-blocks, wrap-iife, max-len */
/* eslint-disable no-param-reassign, func-names, no-var, camelcase, no-unused-vars, object-shorthand, space-before-function-paren, no-return-assign, comma-dangle, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, prefer-arrow-callback, prefer-const, padded-blocks, wrap-iife, max-len */
/* global Issuable */
/* global Turbolinks */
(function() {
((global) => {
var issuable_created;
issuable_created = false;
this.Issuable = {
global.Issuable = {
init: function() {
Issuable.initTemplates();
Issuable.initSearch();
@ -111,7 +111,11 @@
filterResults: (function(_this) {
return function(form) {
var formAction, formData, issuesUrl;
formData = form.serialize();
formData = form.serializeArray();
formData = formData.filter(function(data) {
return data.value !== '';
});
formData = $.param(formData);
formAction = form.attr('action');
issuesUrl = formAction;
issuesUrl += "" + (formAction.indexOf('?') < 0 ? '?' : '&');
@ -184,4 +188,4 @@
}
};
}).call(this);
})(window);

View File

@ -93,6 +93,19 @@
}
};
// Check if element scrolled into viewport from above or below
// Courtesy http://stackoverflow.com/a/7557433/414749
w.gl.utils.isInViewport = function(el) {
var rect = el.getBoundingClientRect();
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= window.innerHeight &&
rect.right <= window.innerWidth
);
};
gl.utils.getPagePath = function() {
return $('body').data('page').split(':')[0];
};

View File

@ -59,16 +59,13 @@
class MergeRequestTabs {
constructor({ action, setUrl, buildsLoaded, stubLocation } = {}) {
constructor({ action, setUrl, stubLocation } = {}) {
this.diffsLoaded = false;
this.buildsLoaded = false;
this.pipelinesLoaded = false;
this.commitsLoaded = false;
this.fixedLayoutPref = null;
this.setUrl = setUrl !== undefined ? setUrl : true;
this.buildsLoaded = buildsLoaded || false;
this.setCurrentAction = this.setCurrentAction.bind(this);
this.tabShown = this.tabShown.bind(this);
this.showTab = this.showTab.bind(this);
@ -119,10 +116,6 @@
$.scrollTo('.merge-request-details .merge-request-tabs', {
offset: -navBarHeight,
});
} else if (action === 'builds') {
this.loadBuilds($target.attr('href'));
this.expandView();
this.resetViewContainer();
} else if (action === 'pipelines') {
this.loadPipelines($target.attr('href'));
this.expandView();
@ -180,8 +173,8 @@
setCurrentAction(action) {
this.currentAction = action === 'show' ? 'notes' : action;
// Remove a trailing '/commits' '/diffs' '/builds' '/pipelines' '/new' '/new/diffs'
let newState = location.pathname.replace(/\/(commits|diffs|builds|pipelines|new|new\/diffs)(\.html)?\/?$/, '');
// Remove a trailing '/commits' '/diffs' '/pipelines' '/new' '/new/diffs'
let newState = location.pathname.replace(/\/(commits|diffs|pipelines|new|new\/diffs)(\.html)?\/?$/, '');
// Append the new action if we're on a tab other than 'notes'
if (this.currentAction !== 'notes') {
@ -255,22 +248,6 @@
});
}
loadBuilds(source) {
if (this.buildsLoaded) {
return;
}
this.ajaxGet({
url: `${source}.json`,
success: (data) => {
document.querySelector('div#builds').innerHTML = data.html;
gl.utils.localTimeAgo($('.js-timeago', 'div#builds'));
this.buildsLoaded = true;
new gl.Pipelines();
this.scrollToElement('#builds');
},
});
}
loadPipelines(source) {
if (this.pipelinesLoaded) {
return;
@ -282,6 +259,10 @@
gl.utils.localTimeAgo($('.js-timeago', '#pipelines'));
this.pipelinesLoaded = true;
this.scrollToElement('#pipelines');
new gl.MiniPipelineGraph({
container: '.js-pipeline-table',
});
},
});
}

View File

@ -74,7 +74,7 @@
MergeRequestWidget.prototype.addEventListeners = function() {
var allowedPages;
allowedPages = ['show', 'commits', 'builds', 'pipelines', 'changes'];
allowedPages = ['show', 'commits', 'pipelines', 'changes'];
$(document).on('page:change.merge_request', (function(_this) {
return function() {
var page;
@ -173,7 +173,6 @@
message = message.replace('{{title}}', data.title);
notify(title, message, _this.opts.gitlab_icon, function() {
this.close();
return Turbolinks.visit(_this.opts.builds_path);
});
}
}

View File

@ -0,0 +1,42 @@
/* global merge_request_widget */
(() => {
$(() => {
/* TODO: This needs a better home, or should be refactored. It was previously contained
* in a script tag in app/views/projects/merge_requests/widget/open/_accept.html.haml,
* but Vue chokes on script tags and prevents their execution. So it was moved here
* temporarily.
* */
if ($('.accept-mr-form').length) {
$('.accept-mr-form').on('ajax:send', () => {
$('.accept-mr-form :input').disable();
});
$('.accept_merge_request').on('click', () => {
$('.js-merge-button').html('<i class="fa fa-spinner fa-spin"></i> Merge in progress');
});
$('.merge_when_build_succeeds').on('click', () => {
$('#merge_when_build_succeeds').val('1');
});
$('.js-merge-dropdown a').on('click', (e) => {
e.preventDefault();
$(this).closest('form').submit();
});
} else if ($('.rebase-in-progress').length) {
merge_request_widget.rebaseInProgress();
} else if ($('.rebase-mr-form').length) {
$('.rebase-mr-form').on('ajax:send', () => {
$('.rebase-mr-form :input').disable();
});
$('.js-rebase-button').on('click', () => {
$('.js-rebase-button').html("<i class='fa fa-spinner fa-spin'></i> Rebase in progress");
});
} else {
merge_request_widget.getMergeStatus();
}
});
})();

View File

@ -9,6 +9,7 @@
@import "framework/asciidoctor.scss";
@import "framework/blocks.scss";
@import "framework/buttons.scss";
@import "framework/badges.scss";
@import "framework/calendar.scss";
@import "framework/callout.scss";
@import "framework/common.scss";

View File

@ -0,0 +1,11 @@
.badge {
font-weight: normal;
background-color: $badge-bg;
color: $badge-color;
vertical-align: baseline;
}
.badge-dark {
background-color: $badge-bg-dark;
color: $badge-color-dark;
}

View File

@ -9,7 +9,7 @@
padding: 20px;
color: $gl-gray;
font-weight: normal;
font-size: 16px;
font-size: 14px;
line-height: 36px;
&.diff-collapsed {

View File

@ -76,13 +76,6 @@
color: $black;
}
}
.badge {
font-weight: normal;
background-color: $nav-badge-bg;
color: $gl-gray-light;
vertical-align: baseline;
}
}
&.sub-nav {
@ -434,4 +427,4 @@
border-bottom: none;
}
}
}
}

View File

@ -33,7 +33,7 @@
@import "bootstrap/labels";
@import "bootstrap/badges";
@import "bootstrap/alerts";
// @import "bootstrap/progress-bars";
@import "bootstrap/progress-bars";
@import "bootstrap/list-group";
@import "bootstrap/wells";
@import "bootstrap/close";

View File

@ -134,8 +134,8 @@ $md-area-border: #ddd;
/*
* Code
*/
$code_font_size: 13px;
$code_line_height: 1.5;
$code_font_size: 12px;
$code_line_height: 1.6;
/*
* Padding
@ -279,6 +279,14 @@ $dropdown-toggle-active-border-color: darken($border-color, 14%);
$btn-active-gray: #ececec;
$btn-active-gray-light: e4e7ed;
/*
* Badges
*/
$badge-bg: #f3f3f3;
$badge-bg-dark: #eee;
$badge-color: #929292;
$badge-color-dark: #8f8f8f;
/*
* Award emoji
*/

View File

@ -1,3 +1,34 @@
@keyframes fade-out-status {
0%, 50% { opacity: 1; }
100% { opacity: 0; }
}
@keyframes blinking-dots {
0% {
background-color: rgba($white-light, 1);
box-shadow: 12px 0 0 0 rgba($white-light,0.2),
24px 0 0 0 rgba($white-light,0.2);
}
25% {
background-color: rgba($white-light, 0.4);
box-shadow: 12px 0 0 0 rgba($white-light,2),
24px 0 0 0 rgba($white-light,0.2);
}
75% {
background-color: rgba($white-light, 0.4);
box-shadow: 12px 0 0 0 rgba($white-light,0.2),
24px 0 0 0 rgba($white-light,1);
}
100% {
background-color: rgba($white-light, 1);
box-shadow: 12px 0 0 0 rgba($white-light,0.2),
24px 0 0 0 rgba($white-light,0.2);
}
}
.build-page {
pre.trace {
background: $builds-trace-bg;
@ -14,33 +45,6 @@
}
}
.scroll-controls {
.scroll-step {
width: 31px;
margin: 0 0 0 auto;
}
&.affix-bottom {
position: absolute;
right: 25px;
}
&.affix {
right: 25px;
bottom: 15px;
z-index: 1;
}
&.sidebar-expanded {
right: #{$gutter_width + ($gl-padding * 2)};
}
a {
display: block;
margin-bottom: 10px;
}
}
.environment-information {
background-color: $gray-light;
border: 1px solid $border-color;
@ -55,6 +59,87 @@
}
}
.scroll-controls {
height: 100%;
.scroll-step {
width: 31px;
margin: 0 0 0 auto;
}
.scroll-link,
.autoscroll-container {
right: 25px;
z-index: 1;
}
.scroll-link {
position: fixed;
display: block;
margin-bottom: 10px;
&.scroll-top .gitlab-icon-scroll-up-hover,
&.scroll-top:hover .gitlab-icon-scroll-up,
&.scroll-bottom .gitlab-icon-scroll-down-hover,
&.scroll-bottom:hover .gitlab-icon-scroll-down {
display: none;
}
&.scroll-top:hover .gitlab-icon-scroll-up-hover,
&.scroll-bottom:hover .gitlab-icon-scroll-down-hover {
display: inline-block;
}
&.scroll-top {
top: 110px;
}
&.scroll-bottom {
bottom: -2px;
}
}
.autoscroll-container {
position: absolute;
}
&.sidebar-expanded {
.scroll-link,
.autoscroll-container {
right: ($gutter_width + ($gl-padding * 2));
}
}
}
.status-message {
display: inline-block;
color: $white-light;
.status-icon {
display: inline-block;
width: 16px;
height: 33px;
}
.status-text {
float: left;
opacity: 0;
margin-right: 10px;
font-weight: normal;
line-height: 1.8;
transition: opacity 1s ease-out;
&.animate {
animation: fade-out-status 2s ease;
}
}
&:hover .status-text {
opacity: 1;
}
}
.build-header {
position: relative;
padding: 0;
@ -109,6 +194,15 @@
.bash {
display: block;
}
.build-loader-animation {
position: relative;
width: 6px;
height: 6px;
margin: auto auto 12px 2px;
border-radius: 50%;
animation: blinking-dots 1s linear infinite;
}
}
.right-sidebar.build-sidebar {
@ -248,6 +342,12 @@
}
}
.build-sidebar {
.container-fluid.container-limited {
max-width: 100%;
}
}
.build-detail-row {
margin-bottom: 5px;

View File

@ -121,13 +121,6 @@
.folder-name {
cursor: pointer;
.badge {
font-weight: normal;
background-color: $gray-darker;
color: $gl-gray-light;
vertical-align: baseline;
}
}
}
@ -142,4 +135,4 @@
margin-right: 0;
}
}
}
}

View File

@ -434,6 +434,7 @@
.issuable-meta {
display: inline-block;
line-height: 18px;
font-size: 14px;
}
.js-issuable-selector-wrap {

View File

@ -98,7 +98,7 @@
}
.label {
padding: 8px 9px 9px;
padding: 8px 9px 9px $gl-padding;
font-size: 14px;
}
}

View File

@ -21,6 +21,14 @@
display: inline-block;
float: left;
.btn-success.dropdown-toggle .fa {
color: inherit;
}
.btn-success.dropdown-toggle:disabled {
background-color: $gl-success;
}
.accept_merge_request {
&.ci-pending,
&.ci-running {
@ -96,7 +104,7 @@
.mr-widget-body {
h4 {
font-weight: 600;
font-size: 17px;
font-size: 16px;
margin: 5px 0;
color: $gl-gray-dark;

View File

@ -25,12 +25,6 @@
}
.issuable-row {
.color-label {
border-radius: 2px;
padding: 3px !important;
margin-right: 7px;
}
span a {
color: $gl-text-color;
word-wrap: break-word;

View File

@ -448,11 +448,6 @@ ul.notes {
border-radius: $border-radius-base;
}
.diff-file .note .note-actions {
right: 0;
top: 0;
}
/**
* Line note button on the side of diffs
@ -586,3 +581,19 @@ ul.notes {
}
}
}
// Merge request notes in diffs
.diff-file {
// Diff is side by side
.notes_content.parallel .note-header .note-headline-light {
display: block;
position: relative;
}
// Diff is inline
.notes_content .note-header .note-headline-light {
display: inline-block;
position: relative;
}
}

View File

@ -63,6 +63,10 @@
}
}
.content-list.pipelines .table-holder {
min-height: 300px;
}
.pipeline-holder {
width: 100%;
overflow: auto;
@ -91,6 +95,10 @@
td {
padding: 10px 8px;
}
.commit-link {
padding: 9px 8px 10px;
}
}
tbody {
@ -203,7 +211,7 @@
width: 8px;
position: absolute;
right: -7px;
bottom: 9px;
top: 10px;
border-bottom: 2px solid $border-color;
}
}
@ -509,15 +517,10 @@
> .ci-action-icon-container {
position: absolute;
right: 4px;
right: 5px;
top: 5px;
}
.ci-status-icon {
position: relative;
top: 1px;
}
.ci-status-icon svg {
height: 20px;
width: 20px;
@ -604,6 +607,27 @@
}
}
}
.grouped-pipeline-dropdown {
.dropdown-build {
.build-content {
width: 100%;
&:hover {
background-color: $stage-hover-bg;
color: $gl-text-color;
}
}
.ci-action-icon-container {
padding: 0;
font-size: 11px;
position: absolute;
top: 1px;
right: 8px;
}
}
}
}
.dropdown-counter-badge {
@ -614,9 +638,11 @@
margin-right: 2px;
}
.grouped-pipeline-dropdown {
padding: 0;
width: 191px;
min-width: 191px;
left: auto;
right: -195px;
top: -4px;
@ -624,28 +650,55 @@
a {
display: inline-block;
}
&:hover {
background-color: $stage-hover-bg;
.dropdown-build {
.build-content {
width: 100%;
&:hover {
background-color: $stage-hover-bg;
color: $gl-text-color;
}
}
.ci-action-icon-container {
padding: 0;
font-size: 11px;
position: absolute;
margin-top: 3px;
right: 7px;
}
}
ul {
max-height: 245px;
overflow: auto;
margin: 5px 0;
margin: 3px 0;
li {
padding-top: 2px;
margin: 0 5px;
padding-left: 0;
padding-bottom: 0;
margin-bottom: 0;
line-height: 1.2;
margin: 4px 8px 4px 9px;
padding: 0;
line-height: 1.1;
position: relative;
.ci-action-icon-container:hover {
background-color: transparent;
}
.ci-status-icon {
position: relative;
top: 2px;
}
}
}
}
.pipeline-graph .dropdown-build .ci-status-icon svg {
width: 18px;
height: 18px;
}
.ci-status-text {
max-width: 110px;
white-space: nowrap;
@ -654,7 +707,7 @@
vertical-align: bottom;
display: inline-block;
position: relative;
font-weight: 100;
font-weight: 200;
}
// Action Icons
@ -690,11 +743,15 @@
.dropdown-build {
color: $gl-text-color-light;
.build-content {
padding: 4px 7px 8px;
}
.ci-action-icon-container {
padding: 0;
font-size: 11px;
float: right;
margin-top: 4px;
margin-top: 3px;
display: inline-block;
position: relative;
@ -704,16 +761,10 @@
}
}
&:hover {
background-color: $stage-hover-bg;
border-radius: 3px;
color: $gl-text-color;
}
.ci-action-icon-container {
i {
width: 25px;
height: 25px;
width: 24px;
height: 24px;
&::before {
top: 1px;
@ -743,11 +794,76 @@
.mini-pipeline-graph {
.builds-dropdown {
background-color: transparent;
border: none;
padding: 0;
color: $gl-text-color-light;
border: none;
margin: 0;
&:focus,
&:hover {
outline: none;
margin-right: -8px;
.ci-status-icon {
width: 32px;
padding: 0 8px 0 0;
transition: width 0.1s cubic-bezier(0.25, 0, 1, 1);
+ .dropdown-caret {
visibility: visible;
opacity: 1;
}
}
}
&:focus,
&:active {
.ci-status-icon-success {
background-color: rgba($gl-success, .1);
}
.ci-status-icon-failed {
background-color: rgba($gl-danger, .1);
}
.ci-status-icon-pending,
.ci-status-icon-success_with_warnings {
background-color: rgba($gl-warning, .1);
}
.ci-status-icon-running {
background-color: rgba($blue-normal, .1);
}
.ci-status-icon-canceled,
.ci-status-icon-disabled,
.ci-status-icon-not-found {
background-color: rgba($gl-gray, .1);
}
.ci-status-icon-created,
.ci-status-icon-skipped {
background-color: rgba($gray-darkest, .1);
}
}
.mini-pipeline-graph-icon-container {
.dropdown-caret {
font-size: 11px;
position: absolute;
top: 6px;
left: 20px;
margin-right: -6px;
z-index: 2;
visibility: hidden;
opacity: 0;
transition: visibility 0.1s, opacity 0.1s linear;
}
}
}
.dropdown-build .build-content {
padding: 3px 7px 7px;
}
.builds-dropdown-loading {
@ -798,89 +914,26 @@
.mini-pipeline-graph-icon-container .ci-status-icon {
display: inline-block;
border: 1px solid;
border-radius: 20px;
border-radius: 22px;
margin-right: 1px;
width: 20px;
height: 20px;
width: 22px;
height: 22px;
position: relative;
z-index: 2;
transition: all 0.2s cubic-bezier(0.25, 0, 1, 1);
transition: all 0.1s cubic-bezier(0.25, 0, 1, 1);
svg {
top: -1px;
left: -1px;
}
}
.builds-dropdown {
&:focus {
outline: none;
margin-right: -8px;
.ci-status-icon {
width: 28px;
padding: 0 8px 0 0;
transition: width 0.2s cubic-bezier(0.25, 0, 1, 1);
+ .dropdown-caret {
display: inline-block;
}
}
}
&:focus,
&:active {
.ci-status-icon-success {
background-color: rgba($gl-success, .1);
}
.ci-status-icon-failed {
background-color: rgba($gl-danger, .1);
}
.ci-status-icon-pending,
.ci-status-icon-success_with_warnings {
background-color: rgba($gl-warning, .1);
}
.ci-status-icon-running {
background-color: rgba($blue-normal, .1);
}
.ci-status-icon-canceled,
.ci-status-icon-disabled,
.ci-status-icon-not-found {
background-color: rgba($gl-gray, .1);
}
.ci-status-icon-created,
.ci-status-icon-skipped {
background-color: rgba($gray-darkest, .1);
}
}
.mini-pipeline-graph-icon-container {
.ci-status-icon:hover,
.ci-status-icon:focus {
width: 28px;
padding: 0 8px 0 0;
+ .dropdown-caret {
display: inline-block;
}
}
.dropdown-caret {
font-size: 11px;
position: relative;
top: 3px;
left: -11px;
margin-right: -6px;
display: none;
z-index: 2;
}
}
.stage-cell .mini-pipeline-graph-icon-container .ci-status-icon svg {
width: 22px;
height: 22px;
}
.terminal-icon {
margin-left: 3px;
}

View File

@ -880,3 +880,23 @@ pre.light-well {
width: 30%;
}
}
.services-installation-info .row {
margin-bottom: 10px;
}
.service-installation {
padding: 32px;
margin: 32px;
border-radius: 3px;
background-color: $white-light;
h3 {
margin-top: 0;
}
hr {
margin: 32px 0;
border-color: $border-color;
}
}

View File

@ -1,6 +1,6 @@
.container-fluid {
.ci-status {
padding: 2px 7px;
padding: 2px 7px 4px;
margin-right: 10px;
border: 1px solid $gray-darker;
white-space: nowrap;

View File

@ -82,6 +82,8 @@ class GroupsController < Groups::ApplicationController
if Groups::UpdateService.new(@group, current_user, group_params).execute
redirect_to edit_group_path(@group), notice: "Group '#{@group.name}' was successfully updated."
else
@group.reset_path!
render action: "edit"
end
end

View File

@ -8,13 +8,11 @@ class Projects::CommitController < Projects::ApplicationController
# Authorize
before_action :require_non_empty_project
before_action :authorize_download_code!, except: [:cancel_builds, :retry_builds]
before_action :authorize_update_build!, only: [:cancel_builds, :retry_builds]
before_action :authorize_download_code!
before_action :authorize_read_pipeline!, only: [:pipelines]
before_action :authorize_read_commit_status!, only: [:builds]
before_action :commit
before_action :define_commit_vars, only: [:show, :diff_for_path, :builds, :pipelines]
before_action :define_status_vars, only: [:show, :builds, :pipelines]
before_action :define_commit_vars, only: [:show, :diff_for_path, :pipelines]
before_action :define_status_vars, only: [:show, :pipelines]
before_action :define_note_vars, only: [:show, :diff_for_path]
before_action :authorize_edit_tree!, only: [:revert, :cherry_pick]
@ -35,25 +33,6 @@ class Projects::CommitController < Projects::ApplicationController
def pipelines
end
def builds
end
def cancel_builds
ci_builds.running_or_pending.each(&:cancel)
redirect_back_or_default default: builds_namespace_project_commit_path(project.namespace, project, commit.sha)
end
def retry_builds
ci_builds.latest.failed.each do |build|
if build.retryable?
Ci::Build.retry(build, current_user)
end
end
redirect_back_or_default default: builds_namespace_project_commit_path(project.namespace, project, commit.sha)
end
def branches
@branches = @project.repository.branch_names_contains(commit.id)
@tags = @project.repository.tag_names_contains(commit.id)
@ -98,10 +77,6 @@ class Projects::CommitController < Projects::ApplicationController
@noteable = @commit ||= @project.commit(params[:id])
end
def ci_builds
@ci_builds ||= Ci::Build.where(pipeline: pipelines)
end
def define_commit_vars
return git_not_found! unless commit
@ -133,8 +108,6 @@ class Projects::CommitController < Projects::ApplicationController
def define_status_vars
@ci_pipelines = project.pipelines.where(sha: commit.sha)
@statuses = CommitStatus.where(pipeline: @ci_pipelines).relevant
@builds = Ci::Build.where(pipeline: @ci_pipelines).relevant
end
def assign_change_commit_vars(mr_source_branch)

View File

@ -0,0 +1,43 @@
class Projects::MattermostsController < Projects::ApplicationController
include TriggersHelper
include ActionView::Helpers::AssetUrlHelper
layout 'project_settings'
before_action :authorize_admin_project!
before_action :service
before_action :teams, only: [:new]
def new
end
def create
result, message = @service.configure(current_user, configure_params)
if result
flash[:notice] = 'This service is now configured'
redirect_to edit_namespace_project_service_path(
@project.namespace, @project, service)
else
flash[:alert] = message || 'Failed to configure service'
redirect_to new_namespace_project_mattermost_path(
@project.namespace, @project)
end
end
private
def configure_params
params.require(:mattermost).permit(:trigger, :team_id).merge(
url: service_trigger_url(@service),
icon_url: asset_url('gitlab_logo.png'))
end
def teams
@teams ||= @service.list_teams(current_user)
end
def service
@service ||= @project.find_or_initialize_service('mattermost_slash_commands')
end
end

View File

@ -9,10 +9,10 @@ class Projects::MergeRequestsController < Projects::ApplicationController
before_action :module_enabled
before_action :merge_request, only: [
:edit, :update, :show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines, :merge, :merge_check,
:edit, :update, :show, :diffs, :commits, :conflicts, :conflict_for_path, :pipelines, :merge, :merge_check,
:ci_status, :ci_environments_status, :toggle_subscription, :cancel_merge_when_build_succeeds, :remove_wip, :resolve_conflicts, :assign_related_issues
]
before_action :validates_merge_request, only: [:show, :diffs, :commits, :builds, :pipelines]
before_action :validates_merge_request, only: [:show, :diffs, :commits, :pipelines]
before_action :define_show_vars, only: [:show, :diffs, :commits, :conflicts, :conflict_for_path, :builds, :pipelines]
before_action :define_widget_vars, only: [:merge, :cancel_merge_when_build_succeeds, :merge_check]
before_action :define_commit_vars, only: [:diffs]
@ -201,17 +201,6 @@ class Projects::MergeRequestsController < Projects::ApplicationController
end
end
def builds
respond_to do |format|
format.html do
define_discussion_vars
render 'show'
end
format.json { render json: { html: view_to_html_string('projects/merge_requests/show/_builds') } }
end
end
def pipelines
@pipelines = @merge_request.all_pipelines

View File

@ -1,5 +1,5 @@
module AuthHelper
PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2).freeze
PROVIDERS_WITH_ICONS = %w(twitter github gitlab bitbucket google_oauth2 facebook azure_oauth2 authentiq).freeze
FORM_BASED_PROVIDERS = [/\Aldap/, 'crowd'].freeze
def ldap_enabled?

View File

@ -188,7 +188,7 @@ module BlobHelper
end
def gitlab_ci_ymls
@gitlab_ci_ymls ||= Gitlab::Template::GitlabCiYmlTemplate.dropdown_names
@gitlab_ci_ymls ||= Gitlab::Template::GitlabCiYmlTemplate.dropdown_names(params[:context])
end
def dockerfile_names

View File

@ -1,7 +1,7 @@
module CiStatusHelper
def ci_status_path(pipeline)
project = pipeline.project
builds_namespace_project_commit_path(project.namespace, project, pipeline.sha)
namespace_project_pipeline_path(project.namespace, project, pipeline)
end
# Is used by Commit and Merge Request Widget

View File

@ -96,8 +96,8 @@ module IssuablesHelper
if issuable.tasks?
output << "&ensp;".html_safe
output << content_tag(:span, issuable.task_status, id: "task_status", class: "hidden-xs")
output << content_tag(:span, issuable.task_status_short, id: "task_status_short", class: "hidden-sm hidden-md hidden-lg")
output << content_tag(:span, issuable.task_status, id: "task_status", class: "hidden-xs hidden-sm")
output << content_tag(:span, issuable.task_status_short, id: "task_status_short", class: "hidden-md hidden-lg")
end
output

View File

@ -0,0 +1,9 @@
module MattermostHelper
def mattermost_teams_options(teams)
teams_options = teams.map do |id, options|
[options['display_name'] || options['name'], id]
end
teams_options.compact.unshift(['Select team...', '0'])
end
end

View File

@ -280,13 +280,15 @@ module ProjectsHelper
end
end
def add_special_file_path(project, file_name:, commit_message: nil)
def add_special_file_path(project, file_name:, commit_message: nil, target_branch: nil, context: nil)
namespace_project_new_blob_path(
project.namespace,
project,
project.default_branch || 'master',
file_name: file_name,
commit_message: commit_message || "Add #{file_name.downcase}"
commit_message: commit_message || "Add #{file_name.downcase}",
target_branch: target_branch,
context: context
)
end

View File

@ -35,7 +35,7 @@ module TodosHelper
else
path = [todo.project.namespace.becomes(Namespace), todo.project, todo.target]
path.unshift(:builds) if todo.build_failed?
path.unshift(:pipelines) if todo.build_failed?
polymorphic_path(path, anchor: anchor)
end

View File

@ -93,11 +93,8 @@ module Ci
.select("max(#{quoted_table_name}.id)")
.group(:ref, :sha)
if ref
where(id: max_id, ref: ref)
else
where(id: max_id)
end
relation = ref ? where(ref: ref) : self
relation.where(id: max_id).order(id: :desc)
end
def self.latest_status(ref = nil)

View File

@ -98,7 +98,7 @@ class Namespace < ActiveRecord::Base
def move_dir
if any_project_has_container_registry_tags?
raise Exception.new('Namespace cannot be moved, because at least one project has tags in container registry')
raise Gitlab::UpdatePathError.new('Namespace cannot be moved, because at least one project has tags in container registry')
end
# Move the namespace directory in all storages paths used by member projects
@ -111,7 +111,7 @@ class Namespace < ActiveRecord::Base
# if we cannot move namespace directory we should rollback
# db changes in order to prevent out of sync between db and fs
raise Exception.new('namespace directory cannot be moved')
raise Gitlab::UpdatePathError.new('namespace directory cannot be moved')
end
end

View File

@ -418,7 +418,7 @@ class Project < ActiveRecord::Base
repository.commit(ref)
end
# ref can't be HEAD, can only be branch/tag name or SHA
# ref can't be HEAD or SHA, can only be branch/tag name
def latest_successful_builds_for(ref = default_branch)
latest_pipeline = pipelines.latest_successful_for(ref)

View File

@ -49,11 +49,13 @@ class ChatNotificationService < Service
return false unless message
opt = {}
channel_name = get_channel_field(object_kind).presence || channel
opt[:channel] = get_channel_field(object_kind).presence || channel || default_channel
opt[:username] = username if username
notifier = Slack::Notifier.new(webhook, opt)
opts = {}
opts[:channel] = channel_name if channel_name
opts[:username] = username if username
notifier = Slack::Notifier.new(webhook, opts)
notifier.ping(message.pretext, attachments: message.attachments, fallback: message.fallback)
true
@ -71,7 +73,7 @@ class ChatNotificationService < Service
fields.reject { |field| field[:name].end_with?('channel') }
end
def default_channel
def default_channel_placeholder
raise NotImplementedError
end
@ -103,7 +105,7 @@ class ChatNotificationService < Service
def build_event_channels
supported_events.reduce([]) do |channels, event|
channels << { type: 'text', name: event_channel_name(event), placeholder: default_channel }
channels << { type: 'text', name: event_channel_name(event), placeholder: default_channel_placeholder }
end
end

View File

@ -35,7 +35,7 @@ class MattermostService < ChatNotificationService
]
end
def default_channel
def default_channel_placeholder
"#town-square"
end
end

View File

@ -18,4 +18,34 @@ class MattermostSlashCommandsService < ChatSlashCommandsService
def to_param
'mattermost_slash_commands'
end
def configure(user, params)
token = Mattermost::Command.new(user).
create(command(params))
update(active: true, token: token) if token
rescue Mattermost::Error => e
[false, e.message]
end
def list_teams(user)
Mattermost::Team.new(user).all
rescue Mattermost::Error => e
[[], e.message]
end
private
def command(params)
pretty_project_name = project.name_with_namespace
params.merge(
auto_complete: true,
auto_complete_desc: "Perform common operations on: #{pretty_project_name}",
auto_complete_hint: '[help]',
description: "Perform common operations on: #{pretty_project_name}",
display_name: "GitLab / #{pretty_project_name}",
method: 'P',
username: 'GitLab')
end
end

View File

@ -34,7 +34,7 @@ class SlackService < ChatNotificationService
]
end
def default_channel
def default_channel_placeholder
"#general"
end
end

View File

@ -16,7 +16,7 @@ class SlackSlashCommandsService < ChatSlashCommandsService
def trigger(params)
# Format messages to be Slack-compatible
super.tap do |result|
result[:text] = format(result[:text])
result[:text] = format(result[:text]) if result.is_a?(Hash)
end
end

View File

@ -654,11 +654,19 @@ class Repository
end
def last_commit_for_path(sha, path)
args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path})
sha = Gitlab::Popen.popen(args, path_to_repo).first.strip
sha = last_commit_id_for_path(sha, path)
commit(sha)
end
def last_commit_id_for_path(sha, path)
key = path.blank? ? "last_commit_id_for_path:#{sha}" : "last_commit_id_for_path:#{sha}:#{Digest::SHA1.hexdigest(path)}"
cache.fetch(key) do
args = %W(#{Gitlab.config.git.bin_path} rev-list --max-count=1 #{sha} -- #{path})
Gitlab::Popen.popen(args, path_to_repo).first.strip
end
end
def next_branch(name, opts = {})
branch_ids = self.branch_names.map do |n|
next 1 if n == name

View File

@ -3,6 +3,9 @@ class GitPushService < BaseService
include Gitlab::CurrentSettings
include Gitlab::Access
# The N most recent commits to process in a single push payload.
PROCESS_COMMIT_LIMIT = 100
# This method will be called after each git update
# and only if the provided user and project are present in GitLab.
#
@ -77,6 +80,16 @@ class GitPushService < BaseService
ProjectCacheWorker.perform_async(@project.id, types)
end
# Schedules processing of commit messages.
def process_commit_messages
default = is_default_branch?
push_commits.last(PROCESS_COMMIT_LIMIT).each do |commit|
ProcessCommitWorker.
perform_async(project.id, current_user.id, commit.to_hash, default)
end
end
protected
def execute_related_hooks
@ -128,17 +141,6 @@ class GitPushService < BaseService
end
end
# Extract any GFM references from the pushed commit messages. If the configured issue-closing regex is matched,
# close the referenced Issue. Create cross-reference Notes corresponding to any other referenced Mentionables.
def process_commit_messages
default = is_default_branch?
@push_commits.each do |commit|
ProcessCommitWorker.
perform_async(project.id, current_user.id, commit.to_hash, default)
end
end
def build_push_data
@push_data ||= Gitlab::DataBuilder::Push.build(
@project,

View File

@ -14,7 +14,13 @@ module Groups
group.assign_attributes(params)
group.save
begin
group.save
rescue Gitlab::UpdatePathError => e
group.errors.add(:base, e.message)
false
end
end
end
end

View File

@ -14,7 +14,8 @@ class ProjectPathValidator < ActiveModel::EachValidator
# without tree as reserved name routing can match 'group/project' as group name,
# 'tree' as project name and 'deploy_keys' as route.
#
RESERVED = (NamespaceValidator::RESERVED +
RESERVED = (NamespaceValidator::RESERVED -
%w[dashboard help ci admin search notes services] +
%w[tree commits wikis new edit create update logs_tree
preview blob blame raw files create_dir find_file]).freeze

View File

@ -31,7 +31,7 @@
= link_to admin_abuse_reports_path, title: "Abuse Reports" do
%span
Abuse Reports
%span.badge.count= number_with_delimiter(AbuseReport.count(:all))
%span.badge.badge-dark.count= number_with_delimiter(AbuseReport.count(:all))
- if askimet_enabled?
= nav_link(controller: :spam_logs) do

View File

@ -26,13 +26,13 @@
%span
Issues
- issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
%span.badge.count= number_with_delimiter(issues.count)
%span.badge.badge-dark.count= number_with_delimiter(issues.count)
= nav_link(path: 'groups#merge_requests') do
= link_to merge_requests_group_path(@group), title: 'Merge Requests' do
%span
Merge Requests
- merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened', non_archived: true).execute
%span.badge.count= number_with_delimiter(merge_requests.count)
%span.badge.badge-dark.count= number_with_delimiter(merge_requests.count)
= nav_link(controller: [:group_members]) do
= link_to group_group_members_path(@group), title: 'Members' do
%span

View File

@ -61,14 +61,14 @@
%span
Issues
- if @project.default_issues_tracker?
%span.badge.count.issue_counter= number_with_delimiter(IssuesFinder.new(current_user, project_id: @project.id).execute.opened.count)
%span.badge.badge-dark.count.issue_counter= number_with_delimiter(IssuesFinder.new(current_user, project_id: @project.id).execute.opened.count)
- if project_nav_tab? :merge_requests
= nav_link(controller: :merge_requests) do
= link_to namespace_project_merge_requests_path(@project.namespace, @project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
%span
Merge Requests
%span.badge.count.merge_counter= number_with_delimiter(MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.count)
%span.badge.badge-dark.count.merge_counter= number_with_delimiter(MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.count)
- if project_nav_tab? :wiki
= nav_link(controller: :wikis) do

View File

@ -1,7 +1,8 @@
- ref = local_assigns.fetch(:ref)
- status = commit.status(ref)
- if status
= link_to builds_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{status}" do
= link_to pipelines_namespace_project_commit_path(commit.project.namespace, commit.project, commit), class: "ci-status ci-#{status}" do
= ci_icon_for_status(status)
= ci_label_for_status(status)

View File

@ -7,7 +7,7 @@
= link_to pipeline_path(@build.pipeline) do
%strong ##{@build.pipeline.id}
for commit
= link_to ci_status_path(@build.pipeline) do
= link_to namespace_project_commit_path(@project.namespace, @project, @build.pipeline.sha) do
%strong= @build.pipeline.short_sha
from
= link_to namespace_project_commits_path(@project.namespace, @project, @build.ref) do

View File

@ -56,17 +56,22 @@
- else
#js-build-scroll.scroll-controls
.scroll-step
= link_to '#build-trace', class: 'btn' do
%i.fa.fa-angle-up
= link_to '#down-build-trace', class: 'btn' do
%i.fa.fa-angle-down
%a{ href: '#up-build-trace', id: 'scroll-top', class: 'scroll-link scroll-top', title: 'Scroll to top' }
= custom_icon('scroll_up')
= custom_icon('scroll_up_hover_active')
%a{ href: '#down-build-trace', id: 'scroll-bottom', class: 'scroll-link scroll-bottom', title: 'Scroll to bottom' }
= custom_icon('scroll_down')
= custom_icon('scroll_down_hover_active')
- if @build.active?
.autoscroll-container
%button.btn.btn-sm#autoscroll-button{:type => "button", :data => {:state => 'disabled'}}
Enable autoscroll
%span.status-message#autoscroll-status{ data: { state: 'disabled' } }
%span.status-text Autoscroll active
%i.status-icon
= custom_icon('scroll_down_hover_active')
#up-build-trace
%pre.build-trace#build-trace
%code.bash.js-build-output
= icon("refresh spin", class: "js-build-refresh")
.build-loader-animation.js-build-refresh
#down-build-trace

View File

@ -1,2 +0,0 @@
- @ci_pipelines.each do |pipeline|
= render "pipeline", pipeline: pipeline, pipeline_details: true

View File

@ -8,7 +8,3 @@
= link_to pipelines_namespace_project_commit_path(@project.namespace, @project, @commit.id) do
Pipelines
%span.badge= @ci_pipelines.count
= nav_link(path: 'commit#builds') do
= link_to builds_namespace_project_commit_path(@project.namespace, @project, @commit.id) do
Builds
%span.badge= @statuses.count

View File

@ -1,9 +0,0 @@
- @no_container = true
- page_title "Builds", "#{@commit.title} (#{@commit.short_id})", "Commits"
= render "projects/commits/head"
%div{ class: container_class }
= render "commit_box"
= render "ci_menu"
= render "builds"

View File

@ -0,0 +1,12 @@
%p
You arent a member of any team on the Mattermost instance at
%strong= Gitlab.config.mattermost.host
%p
To install this service,
= link_to "#{Gitlab.config.mattermost.host}/select_team", target: '__blank' do
join a team
= icon('external-link')
and try again.
%hr
.clearfix
= link_to 'Go back', edit_namespace_project_service_path(@project.namespace, @project, @service), class: 'btn btn-lg pull-right'

View File

@ -0,0 +1,44 @@
%p
This service will be installed on the Mattermost instance at
%strong= link_to Gitlab.config.mattermost.host, Gitlab.config.mattermost.host
%hr
= form_for(:mattermost, method: :post, url: namespace_project_mattermost_path(@project.namespace, @project)) do |f|
%h4 Team
%p
= @teams.one? ? 'The team' : 'Select the team'
where the slash commands will be used in
- selected_id = @teams.keys.first if @teams.one?
= f.select(:team_id, mattermost_teams_options(@teams), {}, { class: 'form-control', selected: "#{selected_id}", disabled: @teams.one? })
.help-block
- if @teams.one?
This is the only team where you are an administrator.
- else
The list shows teams where you are administrator
To create a team, ask your Mattermost system administrator.
To create a team,
= link_to "#{Gitlab.config.mattermost.host}/create_team" do
use Mattermost's interface
= icon('external-link')
%hr
%h4 Command trigger word
%p Choose the word that will trigger commands
= f.text_field(:trigger, value: @project.path, class: 'form-control')
.help-block
%p
Trigger word must be unique, and can't begin with a slash or contain any spaces.
Use the word that works best for your team.
%p
Suggestions:
%code= 'gitlab'
%code= @project.path # Path contains no spaces, but dashes
%code= @project.path_with_namespace
%p
Reserved:
= link_to 'https://docs.mattermost.com/help/messaging/executing-commands.html#built-in-commands', target: '__blank' do
see list of built-in slash commands
= icon('external-link')
%hr
.clearfix
.pull-right
= link_to 'Cancel', edit_namespace_project_service_path(@project.namespace, @project, @service), class: 'btn btn-lg'
= f.submit 'Install', class: 'btn btn-save btn-lg'

View File

@ -0,0 +1,8 @@
.service-installation
.inline.pull-right
= custom_icon('mattermost_logo', size: 48)
%h3 Install Mattermost Command
- if @teams.empty?
= render 'no_teams'
- else
= render 'team_selection'

View File

@ -34,11 +34,6 @@
= link_to url_for(params), data: {target: 'div#pipelines', action: 'pipelines', toggle: 'tab'} do
Pipelines
%span.badge= @pipelines.size
- if @pipeline.present?
%li.builds-tab
= link_to url_for(params), data: {target: 'div#builds', action: 'builds', toggle: 'tab'} do
Builds
%span.badge= @statuses_count
%li.diffs-tab
= link_to url_for(params.merge(action: 'new_diffs')), data: {target: 'div#diffs', action: 'new/diffs', toggle: 'tab'} do
Changes
@ -49,9 +44,6 @@
= render "projects/merge_requests/show/commits"
#diffs.diffs.tab-pane
- # This tab is always loaded via AJAX
- if @pipeline.present?
#builds.builds.tab-pane
= render "projects/merge_requests/show/builds"
- if @pipelines.any?
#pipelines.pipelines.tab-pane
= render "projects/merge_requests/show/pipelines"
@ -66,6 +58,5 @@
});
:javascript
var merge_request = new MergeRequest({
action: "#{(@show_changes_tab ? 'new/diffs' : 'new')}",
buildsLoaded: "#{@pipeline.present? ? 'true' : 'false'}"
action: "#{(@show_changes_tab ? 'new/diffs' : 'new')}"
});

View File

@ -65,11 +65,6 @@
= link_to pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#pipelines', action: 'pipelines', toggle: 'tab' } do
Pipelines
%span.badge= @pipelines.size
- if @pipeline.present?
%li.builds-tab
= link_to builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: '#builds', action: 'builds', toggle: 'tab' } do
Builds
%span.badge= @statuses_count
%li.diffs-tab
= link_to diffs_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), data: { target: 'div#diffs', action: 'diffs', toggle: 'tab' } do
Changes
@ -98,8 +93,6 @@
#commits.commits.tab-pane
- # This tab is always loaded via AJAX
#builds.builds.tab-pane
- # This tab is always loaded via AJAX
#pipelines.pipelines.tab-pane
- # This tab is always loaded via AJAX
#diffs.diffs.tab-pane

View File

@ -1 +0,0 @@
= render "projects/commit/pipeline", pipeline: @pipeline, link_to_commit: true

View File

@ -17,7 +17,7 @@
- # TODO, remove in later versions when services like Jenkins will set CI status via Commit status API
.mr-widget-heading
- %w[success skipped canceled failed running pending].each do |status|
.ci_widget{class: "ci-#{status}", style: "display:none"}
.ci_widget{class: "ci-#{status} ci-status-icon-#{status}", style: "display:none"}
= ci_icon_for_status(status)
%span
CI build

View File

@ -24,12 +24,10 @@
preparing: "{{status}} build",
normal: "Build {{status}}"
},
builds_path: "#{builds_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}",
pipelines_path: "#{pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request)}"
};
if (typeof merge_request_widget !== 'undefined') {
clearInterval(merge_request_widget.fetchBuildStatusInterval);
merge_request_widget.cancelPolling();
merge_request_widget.clearEventListeners();
}

View File

@ -1,3 +1,6 @@
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('merge_request_widget/ci_bundle.js')
- status_class = @pipeline ? " ci-#{@pipeline.status}" : nil
= form_for [:merge, @project.namespace.becomes(Namespace), @project, @merge_request], remote: true, method: :post, html: { class: 'accept-mr-form js-quick-submit js-requires-input' } do |f|
@ -47,21 +50,3 @@
rows: 14, hint: true
= hidden_field_tag :merge_when_build_succeeds, "", autocomplete: "off"
:javascript
$('.accept-mr-form').on('ajax:send', function() {
$(".accept-mr-form :input").disable();
});
$('.accept_merge_request').on('click', function() {
$('.js-merge-button').html("<i class='fa fa-spinner fa-spin'></i> Merge in progress");
});
$('.merge_when_build_succeeds').on('click', function() {
$("#merge_when_build_succeeds").val("1");
});
$('.js-merge-dropdown a').on('click', function(e) {
e.preventDefault();
$(this).closest("form").submit();
});

View File

@ -1,9 +1,6 @@
- content_for :page_specific_javascripts do
= page_specific_javascript_tag('merge_request_widget/ci_bundle.js')
%strong
= icon("spinner spin")
Checking ability to merge automatically&hellip;
:javascript
$(function() {
merge_request_widget.getMergeStatus();
});

View File

@ -10,7 +10,7 @@
.timeline-content
.note-header
= link_to_member(note.project, note.author, avatar: false)
.inline.note-headline-light
.note-headline-light
= note.author.to_reference
- unless note.system
commented

View File

@ -1,4 +1,4 @@
%ul
- @stage.statuses.each do |status|
- @stage.statuses.latest.each do |status|
%li.dropdown-build
= render 'ci/status/graph_badge', subject: status

View File

@ -8,7 +8,6 @@
.col-lg-9
= form_for(@service, as: :service, url: namespace_project_service_path(@project.namespace, @project, @service.to_param), method: :put, html: { class: 'form-horizontal' }) do |form|
= render 'shared/service_settings', form: form, subject: @service
.footer-block.row-content-block
= form.submit 'Save changes', class: 'btn btn-save'
&nbsp;

View File

@ -0,0 +1,91 @@
- run_actions_text = "Perform common operations on this project: #{@project.name_with_namespace}"
To setup this service:
%ul.list-unstyled
%li
1.
= link_to 'Enable custom slash commands', 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands'
on your Mattermost installation
%li
2.
= link_to 'Add a slash command', 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command'
in Mattermost with these options:
%hr
.help-form
.form-group
= label_tag :display_name, 'Display name', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :display_name, "GitLab / #{@project.name_with_namespace}", class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#display_name')
.form-group
= label_tag :description, 'Description', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#description')
.form-group
= label_tag nil, 'Command trigger word', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.text-block
%p Fill in the word that works best for your team.
%p
Suggestions:
%code= 'gitlab'
%code= @project.path # Path contains no spaces, but dashes
%code= @project.path_with_namespace
.form-group
= label_tag :request_url, 'Request URL', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :request_url, service_trigger_url(subject), class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#request_url')
.form-group
= label_tag nil, 'Request method', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.text-block POST
.form-group
= label_tag :response_username, 'Response username', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :response_username, 'GitLab', class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#response_username')
.form-group
= label_tag :response_icon, 'Response icon', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :response_icon, asset_url('gitlab_logo.png'), class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#response_icon')
.form-group
= label_tag nil, 'Autocomplete', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.text-block Yes
.form-group
= label_tag :autocomplete_hint, 'Autocomplete hint', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :autocomplete_hint, '[help]', class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#autocomplete_hint')
.form-group
= label_tag :autocomplete_description, 'Autocomplete description', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :autocomplete_description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#autocomplete_description')
%hr
%ul.list-unstyled
%li
3. After adding the slash command, paste the
%strong token
into the field below

View File

@ -1,4 +1,4 @@
- run_actions_text = "Perform common operations on this project: #{@project.name_with_namespace}"
- enabled = Gitlab.config.mattermost.enabled
.well
This service allows GitLab users to perform common operations on this
@ -7,93 +7,9 @@
See list of available commands in Mattermost after setting up this service,
by entering
%code /&lt;command_trigger_word&gt; help
%br
%br
To setup this service:
%ul.list-unstyled
%li
1.
= link_to 'Enable custom slash commands', 'https://docs.mattermost.com/developer/slash-commands.html#enabling-custom-commands'
on your Mattermost installation
%li
2.
= link_to 'Add a slash command', 'https://docs.mattermost.com/developer/slash-commands.html#set-up-a-custom-command'
in Mattermost with these options:
%hr
- unless enabled
= render 'projects/services/mattermost_slash_commands/detailed_help', subject: @service
.help-form
.form-group
= label_tag :display_name, 'Display name', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :display_name, "GitLab / #{@project.name_with_namespace}", class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#display_name')
.form-group
= label_tag :description, 'Description', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#description')
.form-group
= label_tag nil, 'Command trigger word', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.text-block
%p Fill in the word that works best for your team.
%p
Suggestions:
%code= 'gitlab'
%code= @project.path # Path contains no spaces, but dashes
%code= @project.path_with_namespace
.form-group
= label_tag :request_url, 'Request URL', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :request_url, service_trigger_url(subject), class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#request_url')
.form-group
= label_tag nil, 'Request method', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.text-block POST
.form-group
= label_tag :response_username, 'Response username', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :response_username, 'GitLab', class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#response_username')
.form-group
= label_tag :response_icon, 'Response icon', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :response_icon, asset_url('gitlab_logo.png'), class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#response_icon')
.form-group
= label_tag nil, 'Autocomplete', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.text-block Yes
.form-group
= label_tag :autocomplete_hint, 'Autocomplete hint', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :autocomplete_hint, '[help]', class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#autocomplete_hint')
.form-group
= label_tag :autocomplete_description, 'Autocomplete description', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :autocomplete_description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#autocomplete_description')
%hr
%ul.list-unstyled
%li
3. After adding the slash command, paste the
%strong token
into the field below
- if enabled
= render 'projects/services/mattermost_slash_commands/installation_info', subject: @service

View File

@ -0,0 +1,7 @@
.services-installation-info
- unless @service.activated?
.row
.col-sm-9.col-sm-offset-3
= link_to new_namespace_project_mattermost_path(@project.namespace, @project), class: 'btn btn-lg' do
= custom_icon('mattermost_logo', size: 15)
= 'Add to Mattermost'

View File

@ -68,6 +68,10 @@
- if koding_enabled? && @repository.koding_yml.blank?
%li.missing
= link_to 'Set up Koding', add_koding_stack_path(@project)
- if @repository.gitlab_ci_yml.blank? && @project.deployment_service.present?
%li.missing
= link_to add_special_file_path(@project, file_name: '.gitlab-ci.yml', commit_message: 'Set up autodeploy', target_branch: 'autodeploy', context: 'autodeploy') do
Set up autodeploy
- if @repository.commit
.project-last-commit{ class: container_class }

View File

@ -1,8 +1,8 @@
- group_status = CommitStatus.where(id: subject).status
%button.dropdown-menu-toggle.build-content.has-tooltip{ type: 'button', data: { toggle: 'dropdown'} }
%button.dropdown-menu-toggle.build-content.has-tooltip{ type: 'button', data: { toggle: 'dropdown', title: "#{name} - #{group_status}" } }
%span{class: "ci-status-icon ci-status-icon-#{group_status}"}
= ci_icon_for_status(group_status)
%span.ci-status-text{ 'data-toggle' => 'tooltip', 'data-title' => "#{name} - #{group_status}" }
%span.ci-status-text
= name
%span.dropdown-counter-badge= subject.size
.dropdown-menu.grouped-pipeline-dropdown

View File

@ -10,10 +10,10 @@
.text-content
- if has_button && current_user
%h4
The Issue Tracker is a good place to add things that need to be improved or solved in a project!
The Issue Tracker is the place to add things that need to be improved or solved in a project
%p
An issue can be a bug, a todo or a feature request that needs to be discussed in a project.
Besides, issues are searchable and filterable.
Issues can be bugs, tasks or ideas to be discussed.
Also, issues are searchable and filterable.
- if project_select_button
= render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue'
- else

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="<%= size %>" height="<%= size %>" version="1" viewBox="0 0 501 501"><path d="M236 .7C137.7 7.5 54 68.2 18.2 158.5c-32 81-19.6 172.8 33 242.5 39.8 53 97.2 87 164.3 97 16.5 2.7 48 3.2 63.5 1.2 48.7-6.3 92.2-24.6 129-54.2 13-10.5 33-31.2 42.2-43.7 26.4-35.5 42.8-75.8 49-120.3 1.6-12.3 1.6-48.7 0-61-4-28.3-12-54.8-24.2-79.5-12.8-26-26.5-45.3-46.8-65.8C417.8 64 400.2 49 398.4 49c-.6 0-.4 10.5.3 26l1.3 26 7 8.7c19 23.7 32.8 53.5 38.2 83 2.5 14 3 43 1 55.8-4.5 27.8-15.2 54-31 76.5-8.6 12.2-28 31.6-40.2 40.2-24 17-50 27.6-80 33-10 1.8-49 1.8-59 0-43-7.7-78.8-26-107.2-54.8-29.3-29.7-46.5-64-52.4-104.4-2-14-1.5-42 1-55C90 121.4 132 72 192 49.7c8-3 18.4-5.8 29.5-8.2 1.7-.4 34.4-38 35.3-40.6.3-1-10.2-1-20.8-.4z"/><path d="M322.2 24.6c-1.3.8-8.4 9.3-16 18.7-7.4 9.5-22.4 28-33.2 41.2-51 62.2-66 81.6-70.6 91-6 12-8.4 21-9 33-1.2 19.8 5 36 19 50C222 268 230 273 243 277.2c9 3 10.4 3.2 24 3.2 13.8 0 15 0 22.6-3 23.2-9 39-28.4 45-55.7 2-8.2 2-28.7.4-79.7l-2-72c-1-36.8-1.4-41.8-3-44-2-3-4.8-3.6-7.8-1.4z"/></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -0,0 +1,3 @@
<svg width="16" height="33" class="gitlab-icon-scroll-down" viewBox="0 0 16 33" xmlns="http://www.w3.org/2000/svg">
<path fill="#ffffff" d="M1.385 5.534v12.47a4.145 4.145 0 0 0 4.144 4.15h4.942a4.151 4.151 0 0 0 4.144-4.15V5.535a4.145 4.145 0 0 0-4.144-4.15H5.53a4.151 4.151 0 0 0-4.144 4.15zM8.88 30.27v-4.351a.688.688 0 0 0-.69-.688.687.687 0 0 0-.69.688v4.334l-1.345-1.346a.69.69 0 0 0-.976.976l2.526 2.526a.685.685 0 0 0 .494.2.685.685 0 0 0 .493-.2l2.526-2.526a.69.69 0 1 0-.976-.976L8.88 30.27zM0 5.534A5.536 5.536 0 0 1 5.529 0h4.942A5.53 5.53 0 0 1 16 5.534v12.47a5.536 5.536 0 0 1-5.529 5.534H5.53A5.53 5.53 0 0 1 0 18.005V5.534zm7 1.01a1 1 0 1 1 2 0v2.143a1 1 0 1 1-2 0V6.544z" fill-rule="evenodd"/>
</svg>

After

Width:  |  Height:  |  Size: 719 B

View File

@ -0,0 +1,3 @@
<svg width="16" height="33" class="gitlab-icon-scroll-down-hover" viewBox="0 0 16 33" xmlns="http://www.w3.org/2000/svg">
<path fill="#ffffff" d="M8.88 30.27v-4.351a.688.688 0 0 0-.69-.688.687.687 0 0 0-.69.688v4.334l-1.345-1.346a.69.69 0 0 0-.976.976l2.526 2.526a.685.685 0 0 0 .494.2.685.685 0 0 0 .493-.2l2.526-2.526a.69.69 0 1 0-.976-.976L8.88 30.27zM0 5.534A5.536 5.536 0 0 1 5.529 0h4.942A5.53 5.53 0 0 1 16 5.534v12.47a5.536 5.536 0 0 1-5.529 5.534H5.53A5.53 5.53 0 0 1 0 18.005V5.534zm7 1.01a1 1 0 1 1 2 0v2.143a1 1 0 1 1-2 0V6.544z" fill-rule="evenodd"/>
</svg>

After

Width:  |  Height:  |  Size: 573 B

View File

@ -0,0 +1,3 @@
<svg width="16" height="33" class="gitlab-icon-scroll-up" viewBox="0 0 16 33" xmlns="http://www.w3.org/2000/svg">
<path fill="#ffffff" d="M1.385 14.534v12.47a4.145 4.145 0 0 0 4.144 4.15h4.942a4.151 4.151 0 0 0 4.144-4.15v-12.47a4.145 4.145 0 0 0-4.144-4.15H5.53a4.151 4.151 0 0 0-4.144 4.15zM8.88 2.609V6.96a.688.688 0 0 1-.69.688.687.687 0 0 1-.69-.688V2.627L6.155 3.972a.69.69 0 0 1-.976-.976L7.705.47a.685.685 0 0 1 .494-.2.685.685 0 0 1 .493.2l2.526 2.526a.69.69 0 1 1-.976.976L8.88 2.609zM0 14.534A5.536 5.536 0 0 1 5.529 9h4.942A5.53 5.53 0 0 1 16 14.534v12.47a5.536 5.536 0 0 1-5.529 5.534H5.53A5.53 5.53 0 0 1 0 27.005V14.534zm7 1.01a1 1 0 1 1 2 0v2.143a1 1 0 1 1-2 0v-2.143z" fill-rule="evenodd"/>
</svg>

After

Width:  |  Height:  |  Size: 717 B

View File

@ -0,0 +1,3 @@
<svg width="16" height="33" class="gitlab-icon-scroll-up-hover" viewBox="0 0 16 33" xmlns="http://www.w3.org/2000/svg">
<path fill="#ffffff" d="M8.88 2.646l1.362 1.362a.69.69 0 0 0 .976-.976L8.692.507A.685.685 0 0 0 8.2.306a.685.685 0 0 0-.494.2L5.179 3.033a.69.69 0 1 0 .976.976L7.5 2.663v4.179c0 .38.306.688.69.688.381 0 .69-.306.69-.688V2.646zM0 14.534A5.536 5.536 0 0 1 5.529 9h4.942A5.53 5.53 0 0 1 16 14.534v12.47a5.536 5.536 0 0 1-5.529 5.534H5.53A5.53 5.53 0 0 1 0 27.005V14.534zm7 1.01a1 1 0 1 1 2 0v2.143a1 1 0 1 1-2 0v-2.143z" fill-rule="evenodd"/>
</svg>

After

Width:  |  Height:  |  Size: 569 B

View File

@ -3,7 +3,7 @@
- show_menu_above = show_menu_above || false
- selected_text = selected.try(:title) || params[:milestone_title]
- dropdown_title = local_assigns.fetch(:dropdown_title, "Filter by milestone")
- if selected.present?
- if selected.present? || params[:milestone_title].present?
= hidden_field_tag(name, name == :milestone_title ? selected_text : selected.id)
= dropdown_tag(milestone_dropdown_label(selected_text), options: { title: dropdown_title, toggle_class: "js-milestone-select js-filter-submit #{extra_class}", filter: true, dropdown_class: "dropdown-menu-selectable dropdown-menu-milestone",
placeholder: "Search milestones", footer_content: project.present?, data: { show_no: true, show_menu_above: show_menu_above, show_any: show_any, show_upcoming: show_upcoming, field_name: name, selected: selected.try(:title), project_id: project.try(:id), milestones: milestones_filter_dropdown_path, default_label: "Milestone" } }) do

View File

@ -1,4 +0,0 @@
---
title: Fix wrong tab selected when loggin fails and multiple login tabs exists
merge_request: 7314
author: Jacopo Beschi @jacopo-beschi

View File

@ -1,4 +0,0 @@
---
title: Made comment autocomplete more performant and removed some loading bugs
merge_request: 6856
author:

View File

@ -1,4 +0,0 @@
---
title: Update wiki page design
merge_request: 7429
author:

View File

@ -1,4 +0,0 @@
---
title: group authors in contribution graph with case insensitive email handle comparison
merge_request: 8021
author:

View File

@ -1,4 +0,0 @@
---
title: Adds Direct link from pipeline list to builds
merge_request: 8097
author:

View File

@ -1,4 +0,0 @@
---
title: Prevent overflow with vertical scroll when we have space to show content
merge_request: 8061
author:

View File

@ -1,4 +0,0 @@
---
title: Add scopes for personal access tokens and OAuth tokens
merge_request: 5951
author:

View File

@ -1,4 +0,0 @@
---
title: New Gitea importer
merge_request: 8116
author:

View File

@ -1,4 +0,0 @@
---
title: 'Make API::Helpers find a project with only one query'
merge_request: 7714
author:

View File

@ -1,4 +0,0 @@
---
title: Resolve "Manual actions on pipeline graph"
merge_request: 7931
author:

View File

@ -1,4 +0,0 @@
---
title: New `gitlab:workhorse:install` rake task
merge_request: 6574
author:

View File

@ -1,4 +0,0 @@
---
title: Prevent DOM ID collisions resulting from user-generated content anchors
merge_request: 7631
author:

View File

@ -1,4 +0,0 @@
---
title: Introduce $CI_BUILD_REF_SLUG
merge_request: 8072
author:

View File

@ -1,4 +0,0 @@
---
title: Add a slug to environments
merge_request: 7983
author:

Some files were not shown because too many files have changed in this diff Show More