Merge branch 'master' into per-project-pipeline-iid

This commit is contained in:
Shinya Maeda 2018-05-22 14:32:40 +09:00
commit f61666c0d7
396 changed files with 3605 additions and 2171 deletions

View File

@ -10,3 +10,7 @@ lib/gitlab/background_migration/*
app/models/project_services/kubernetes_service.rb
lib/gitlab/workhorse.rb
lib/gitlab/ci/trace/chunked_io.rb
lib/gitlab/gitaly_client/ref_service.rb
lib/gitlab/gitaly_client/commit_service.rb
lib/gitlab/git/commit.rb
lib/gitlab/git/tag.rb

View File

@ -126,6 +126,23 @@ stages:
<<: *dedicated-no-docs-pull-cache-job
<<: *except-docs-and-qa
.single-script-job: &single-script-job
image: ruby:2.4-alpine
before_script: []
stage: build
cache: {}
dependencies: []
variables: &single-script-job-variables
GIT_STRATEGY: none
before_script:
# We need to download the script rather than clone the repo since the
# package-and-qa job will not be able to run when the branch gets
# deleted (when merging the MR).
- export SCRIPT_NAME="${SCRIPT_NAME:-$CI_JOB_NAME}"
- apk add --update openssl
- wget $CI_PROJECT_URL/raw/$CI_COMMIT_SHA/scripts/$SCRIPT_NAME
- chmod 755 $SCRIPT_NAME
.rake-exec: &rake-exec
<<: *dedicated-no-docs-no-db-pull-cache-job
script:
@ -189,7 +206,7 @@ stages:
<<: *dedicated-no-docs-and-no-qa-pull-cache-job
<<: *use-pg
variables:
CREATE_DB_USER: "true"
SETUP_DB: "false"
script:
# Manually clone gitlab-test and only seed this project in
# db/fixtures/development/04_project.rb thanks to SIZE=1 below
@ -207,19 +224,10 @@ stages:
.review-docs: &review-docs
<<: *dedicated-runner
<<: *except-qa
image: ruby:2.4-alpine
before_script:
- gem install gitlab --no-doc
# We need to download the script rather than clone the repo since the
# review-docs-cleanup job will not be able to run when the branch gets
# deleted (when merging the MR).
- apk add --update openssl
- wget https://gitlab.com/gitlab-org/gitlab-ce/raw/master/scripts/trigger-build-docs
- chmod 755 trigger-build-docs
cache: {}
dependencies: []
<<: *single-script-job
variables:
GIT_STRATEGY: none
<<: *single-script-job-variables
SCRIPT_NAME: trigger-build-docs
when: manual
only:
- branches
@ -233,7 +241,7 @@ stages:
.migration-paths: &migration-paths
<<: *dedicated-no-docs-and-no-qa-pull-cache-job
variables:
CREATE_DB_USER: "true"
SETUP_DB: "false"
script:
- git fetch https://gitlab.com/gitlab-org/gitlab-ce.git v9.3.0
- git checkout -f FETCH_HEAD
@ -242,7 +250,7 @@ stages:
- cp config/gitlab.yml.example config/gitlab.yml
- bundle exec rake db:drop db:create db:schema:load db:seed_fu
- date
- git checkout $CI_COMMIT_SHA
- git checkout -f $CI_COMMIT_SHA
- bundle install $BUNDLE_INSTALL_FLAGS
- date
- . scripts/prepare_build.sh
@ -253,23 +261,14 @@ stages:
# Trigger a package build in omnibus-gitlab repository
#
package-and-qa:
image: ruby:2.4-alpine
before_script: []
stage: build
cache: {}
when: manual
<<: *single-script-job
variables:
GIT_STRATEGY: none
<<: *single-script-job-variables
SCRIPT_NAME: trigger-build-omnibus
retry: 0
before_script:
# We need to download the script rather than clone the repo since the
# package-and-qa job will not be able to run when the branch gets
# deleted (when merging the MR).
- apk add --update openssl
- wget https://gitlab.com/$CI_PROJECT_PATH/raw/$CI_COMMIT_SHA/scripts/trigger-build-omnibus
- chmod 755 trigger-build-omnibus
script:
- ./trigger-build-omnibus
- ./$SCRIPT_NAME
when: manual
only:
- //@gitlab-org/gitlab-ce
- //@gitlab-org/gitlab-ee
@ -286,7 +285,8 @@ review-docs-deploy:
url: http://$DOCS_GITLAB_REPO_SUFFIX-$CI_COMMIT_REF_SLUG.$DOCS_REVIEW_APPS_DOMAIN/$DOCS_GITLAB_REPO_SUFFIX
on_stop: review-docs-cleanup
script:
- ./trigger-build-docs deploy
- gem install gitlab --no-ri --no-rdoc
- ./$SCRIPT_NAME deploy
# Cleanup remote environment of gitlab-docs
review-docs-cleanup:
@ -296,7 +296,26 @@ review-docs-cleanup:
name: review-docs/$CI_COMMIT_REF_NAME
action: stop
script:
- ./trigger-build-docs cleanup
- gem install gitlab --no-ri --no-rdoc
- ./SCRIPT_NAME cleanup
##
# Trigger a docker image build in CNG (Cloud Native GitLab) repository
#
cloud-native-image:
image: ruby:2.4-alpine
before_script: []
stage: build
allow_failure: true
cache: {}
before_script:
- gem install gitlab --no-rdoc --no-ri
- chmod 755 ./scripts/trigger-build-cloud-native
script:
- ./scripts/trigger-build-cloud-native
only:
- tags@gitlab-org/gitlab-ce
- tags@gitlab-org/gitlab-ee
# Retrieve knapsack and rspec_flaky reports
retrieve-tests-metadata:
@ -325,7 +344,7 @@ update-tests-metadata:
- rspec_flaky/
policy: push
script:
- retry gem install fog-aws mime-types activesupport
- retry gem install fog-aws mime-types activesupport --no-ri --no-rdoc
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec-pg_node_*.json
- scripts/merge-reports ${FLAKY_RSPEC_SUITE_REPORT_PATH} rspec_flaky/all_*_*.json
- FLAKY_RSPEC_GENERATE_REPORT=1 scripts/prune-old-flaky-specs ${FLAKY_RSPEC_SUITE_REPORT_PATH}

View File

@ -2,6 +2,189 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 10.8.0 (2018-05-22)
### Security (3 changes, 1 of them is from the community)
- Update faraday_middlewar to 0.12.2. !18397 (Takuya Noguchi)
- Serve archive requests with the correct file in all cases.
- Sanitizes user name to avoid XSS attacks.
### Fixed (47 changes, 11 of them are from the community)
- Refactor CSS to eliminate vertical misalignment of login nav. !16275 (Takuya Noguchi)
- Fix pipeline status in branch/tag tree page. !17995
- Allow group owner to enable runners from subgroups (#41981). !18009
- Fix template selector menu visibility when toggling preview mode in file edit view. !18118 (Fabian Schneider)
- Fix confirmation modal for deleting a protected branch. !18176 (Paul Bonaud @PaulRbR)
- Triggering custom hooks by Wiki UI edit. !18251
- Now `rake cache:clear` will also clear pipeline status cache. !18257
- Fix `joined` information on project members page. !18290 (Fabian Schneider)
- Fix missing namespace for some internal users. !18357
- Show shared projects on group page. !18390
- Restore label underline color. !18407 (George Tsiolis)
- Fix undefined `html_escape` method during markdown rendering. !18418
- Fix unassign slash command preview. !18447
- Correct text and functionality for delete user / delete user and contributions modal. !18463 (Marc Schwede)
- Fix discussions API setting created_at for notable in a group or notable in a project in a group with owners. !18464
- Don't include lfs_file_locks data in export bundle. !18495
- Reset milestone filter when clicking "Any Milestone" in dashboard. !18531
- Ensure member notifications are sent after the member actual creation/update in the DB. !18538
- Update links to /ci/lint with ones to project ci/lint. !18539 (Takuya Noguchi)
- Fix tabs container styles to make RSS button clickable. !18559
- Raise NoRepository error for non-valid repositories when calculating repository checksum. !18594
- Don't automatically remove artifacts for pages jobs after pages:deploy has run. !18628
- Increase new issue metadata form margin. !18630 (George Tsiolis)
- Add loading icon padding for pipeline environments. !18631 (George Tsiolis)
- ShaAttribute no longer stops startup if database is missing. !18726
- Fix close keyboard shortcuts dialog using the keyboard shortcut. !18783 (Lars Greiss)
- Fixes database inconsistencies between Community and Enterprise Edition on import state. !18811
- Add database foreign key constraint between pipelines and build. !18822
- Fix finding wiki pages when they have invalidly-encoded content. !18856
- Fix outdated Web IDE welcome copy. !18861
- fixed copy to blipboard button in embed bar of snippets. !18923 (haseebeqx)
- Disables RBAC on nginx-ingress. !18947
- Correct skewed Kubernetes popover illustration. !18949
- Resolve Import/Export ci_cd_settings error updating the project. !46049
- Fix project creation for user endpoint when jobs_enabled parameter supplied.
- 46210 Display logo and user dropdown on mobile for terms page and fix styling.
- Adds illustration for when job log was erased.
- Ensure web hook 'blocked URL' errors are stored in web hook logs and properly surfaced to the user.
- Make toggle markdown preview shortcut only toggle selected field.
- Verifiy if pipeline has commit idetails and render information in MR widget when branch is deleted.
- Fixed inconsistent protected branch pill baseline.
- Fix setting Gitlab metrics content types.
- Display only generic message on merge error to avoid exposing any potentially sensitive or user unfriendly backend messages.
- Fix label links update on project transfer.
- Breaks commit not found message in pipelines table.
- Adjust issue boards list header label text color.
- Prevent pipeline actions in dropdown to redirct to a new page.
### Changed (35 changes, 15 of them are from the community)
- Improve tooltips in collapsed right sidebar. !17714
- Partition job_queue_duration_seconds with jobs_running_for_project. !17730
- For group dashboard, we no longer show groups which the visitor is not a member of (this applies to admins and auditors). !17884 (Roger Rüttimann)
- Use RFC 3676 mail signature delimiters. !17979 (Enrico Scholz)
- Add sha filter to pipelines list API. !18125
- New CI Job live-trace architecture. !18169
- Make project deploy keys table more clearly structured. !18279
- Remove green background from unlock button in admin area. !18288
- Renamed Overview to Project in the contextual navigation at a project level. !18295 (Constance Okoghenun)
- Load branches on new merge request page asynchronously. !18315
- Create settings section for autodevops. !18321
- Add a comma to the time estimate system notes. !18326
- Enable specifying variables when executing a manual pipeline. !18440
- Fix size and position for fork icon. !18449 (George Tsiolis)
- Refactored activity calendar. !18469 (Enrico Scholz)
- Small improvements to repository checks. !18484
- Add 2FA filter to users API for admins only. !18503
- Align project avatar on small viewports. !18513 (George Tsiolis)
- Show group and project LFS settings in the interface to Owners and Masters. !18562
- Update environment item action buttons icons. !18632 (George Tsiolis)
- Update timeline icon for description edit. !18633 (George Tsiolis)
- Revert discussion counter height. !18656 (George Tsiolis)
- Improve quick actions summary preview. !18659 (George Tsiolis)
- Change font for tables inside diff discussions. !18660 (George Tsiolis)
- Add padding to profile description. !18663 (George Tsiolis)
- Break issue title for board card title and issuable header text. !18674 (George Tsiolis)
- Adds push mirrors to GitLab Community Edition. !18715
- Inform the user when there are no project import options available. !18716 (George Tsiolis)
- Improve commit message body rendering and fix responsive compare panels. !18725 (Constance Okoghenun)
- Reconcile project templates with Auto DevOps. !18737
- Remove branch name from the status bar of WebIDE.
- Clean up WebIDE status bar and add useful info.
- Improve interaction on WebIDE commit panel.
- Keep current labels visible when editing them in the sidebar.
- Use VueJS for rendering pipeline stages.
### Performance (26 changes, 11 of them are from the community)
- Move WorkInProgress vue component. !17536 (George Tsiolis)
- Move ReadyToMerge vue component. !17545 (George Tsiolis)
- Move BoardBlankState vue component. !17666 (George Tsiolis)
- Improve DB performance of calculating total artifacts size. !17839
- Add i18n and update specs for UnresolvedDiscussions vue component. !17866 (George Tsiolis)
- Introduce new ProjectCiCdSetting model with group_runners_enabled. !18144
- Move PipelineFailed vue component. !18277 (George Tsiolis)
- Move TimeTrackingEstimateOnlyPane vue component. !18318 (George Tsiolis)
- Move TimeTrackingHelpState vue component. !18319 (George Tsiolis)
- Reduce queries on merge requests list page for merge requests from forks. !18561
- Destroy build_chunks efficiently with FastDestroyAll module. !18575
- Improve performance of a service responsible for creating a pipeline. !18582
- Replace time_ago_in_words with JS-based one. !18607 (Takuya Noguchi)
- Move TimeTrackingNoTrackingPane vue component. !18676 (George Tsiolis)
- Move SidebarTimeTracking vue component. !18677 (George Tsiolis)
- Move TimeTrackingSpentOnlyPane vue component. !18710 (George Tsiolis)
- Detecting tags containing a commit uses Gitaly by default.
- Increase cluster applications installer availability using alpine linux mirrors.
- Compute notification recipients in background jobs.
- Use persisted diff data instead fetching Git on discussions.
- Detecting branchnames containing a commit uses Gitaly by default.
- Detect repository license on Gitaly by default.
- Finish NamespaceService migration to Gitaly.
- Check if a ref exists is done by Gitaly by default.
- Compute Gitlab::Git::Repository#checksum on Gitaly by default.
- Repository#exists? is always executed through Gitaly.
### Added (22 changes, 10 of them are from the community)
- Allow group masters to configure runners for groups. !9646 (Alexis Reigel)
- Adds Embedded Snippets Support. !15695 (haseebeqx)
- Add Copy metadata quick action. !16473 (Mateusz Bajorski)
- Show Runner's description on job's page. !17321
- Add deprecation message to dynamic milestone pages. !17505
- Show new branch/mr button even when branch exists. !17712 (Jacopo Beschi @jacopo-beschi)
- API: add languages of project GET /projects/:id/languages. !17770 (Roger Rüttimann)
- Display active sessions and allow the user to revoke any of it. !17867 (Alexis Reigel)
- Add cron job to email users on issue due date. !17985 (Stuart Nelson)
- Rubocop rule to avoid returning from a block. !18000 (Jacopo Beschi @jacopo-beschi)
- Add the signature verfication badge to the compare view. !18245 (Marc Shaw)
- Expose Deploy Token data as environment varialbes on CI/CD jobs. !18414
- Show group id in group settings. !18482 (George Tsiolis)
- Allow admins to enforce accepting Terms of Service on an instance. !18570
- Add CI_COMMIT_MESSAGE, CI_COMMIT_TITLE and CI_COMMIT_DESCRIPTION predefined variables. !18672
- Add GCP signup offer to cluster index / create pages. !18684
- Output some useful information when running the rails console. !18697
- Display merge commit SHA in merge widget after merge. !18722
- git SHA is now displayed alongside the GitLab version on the Admin Dashboard.
- Expose the target commit ID through the tag API.
- Added fuzzy file finder to web IDE.
- Add discussion API for merge requests and commits.
### Other (22 changes, 8 of them are from the community)
- Replace the `project/issues/milestones.feature` spinach test with an rspec analog. !18300 (@blackst0ne)
- Replace the `project/commits/branches.feature` spinach test with an rspec analog. !18302 (@blackst0ne)
- Replacing gollum libraries for gitlab custom libs. !18343
- Replace the `project/commits/comments.feature` spinach test with an rspec analog. !18356 (@blackst0ne)
- Replace "Click" with "Select" to be more inclusive of people with accessibility requirements. !18386 (Mark Lapierre)
- Remove ahead/behind graphs on project branches on mobile. !18415 (Takuya Noguchi)
- Replace the `project/source/markdown_render.feature` spinach test with an rspec analog. !18525 (@blackst0ne)
- Add missing changelog type to docs. !18526 (@blackst0ne)
- Added Webhook SSRF prevention to documentation. !18532
- Upgrade underscore.js to 1.9.0. !18578
- Add documentation about how to use variables to define deploy policies for staging/production environments. !18675
- Replace the `project/builds/artifacts.feature` spinach test with an rspec analog. !18729 (@blackst0ne)
- Block access to the API & git for users that did not accept enforced Terms of Service. !18816
- Transition to atomic internal ids for all models. !44259
- Removes modal boards store and mixins from global scope.
- Replace GKE acronym with Google Kubernetes Engine.
- Replace vue resource with axios for pipelines details page.
- Enable prometheus monitoring by default.
- Replace vue resource with axios in pipelines table.
- Bump lograge to 0.10.0 and remove monkey patch.
- Improves wording in new pipeline page.
- Gitaly handles repository forks by default.
## 10.7.4 (2018-05-21)
### Fixed (1 change)
- Fix error when deleting an empty list of refs.
## 10.7.3 (2018-05-02)
### Fixed (8 changes)

View File

@ -168,7 +168,7 @@ hits. They are not always necessary, but very convenient.
If you are an expert in a particular area, it makes it easier to find issues to
work on. You can also subscribe to those labels to receive an email each time an
issue is labelled with a subject label corresponding to your expertise.
issue is labeled with a subject label corresponding to your expertise.
Examples of subject labels are ~wiki, ~"container registry", ~ldap, ~api,
~issues, ~"merge requests", ~labels, and ~"container registry".
@ -296,7 +296,24 @@ any potential community contributor to @-mention per above.
## Implement design & UI elements
Please see the [UX Guide for GitLab].
For guidance on UX implementation at GitLab, please refer to our [Design System](https://design.gitlab.com/).
The UX team uses labels to manage their workflow.
The ~"UX" label on an issue is a signal to the UX team that it will need UX attention.
To better understand the priority by which UX tackles issues, see the [UX section](https://about.gitlab.com/handbook/ux/) of the handbook.
Once an issue has been worked on and is ready for development, a UXer applies the ~"UX ready" label to that issue.
The UX team has a special type label called ~"design artifact". This label indicates that the final output
for an issue is a UX solution/design. The solution will be developed by frontend and/or backend in a subsequent milestone.
Any issue labeled ~"design artifact" should not also be labeled ~"frontend" or ~"backend" since no development is
needed until the solution has been decided.
~"design artifact" issues are like any other issue and should contain a milestone label, ~"Deliverable" or ~"Stretch", when scheduled in the current milestone.
Once the ~"design artifact" issue has been completed, the UXer removes the ~"design artifact" label and applies the ~"UX ready" label. The Product Manager can use the
existing issue or decide to create a whole new issue for the purpose of development.
## Issue tracker

View File

@ -1 +1 @@
0.100.0
0.102.0

View File

@ -174,6 +174,9 @@ gem 'httparty', '~> 0.13.3'
# Colored output to console
gem 'rainbow', '~> 2.2'
# Progress bar
gem 'ruby-progressbar'
# GitLab settings
gem 'settingslogic', '~> 2.0.9'

View File

@ -1150,6 +1150,7 @@ DEPENDENCIES
rubocop-rspec (~> 1.22.1)
ruby-fogbugz (~> 0.2.1)
ruby-prof (~> 0.17.0)
ruby-progressbar
ruby_parser (~> 3.8)
rufus-scheduler (~> 3.4)
rugged (~> 0.27)

View File

@ -1 +1 @@
10.8.0-pre
11.0.0-pre

View File

@ -68,8 +68,7 @@
this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', showLoader);
this.service.getFolderContent(folder.folder_path)
.then(resp => resp.json())
.then(response => this.store.setfolderContent(folder, response.environments))
.then(response => this.store.setfolderContent(folder, response.data.environments))
.then(() => this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', false))
.catch(() => {
Flash(s__('Environments|An error occurred while fetching the environments.'));

View File

@ -6,7 +6,6 @@ import Visibility from 'visibilityjs';
import Poll from '../../lib/utils/poll';
import {
getParameterByName,
parseQueryStringIntoObject,
} from '../../lib/utils/common_utils';
import { s__ } from '../../locale';
import Flash from '../../flash';
@ -46,17 +45,14 @@ export default {
methods: {
saveData(resp) {
const headers = resp.headers;
return resp.json().then((response) => {
this.isLoading = false;
this.isLoading = false;
if (_.isEqual(parseQueryStringIntoObject(resp.url.split('?')[1]), this.requestData)) {
this.store.storeAvailableCount(response.available_count);
this.store.storeStoppedCount(response.stopped_count);
this.store.storeEnvironments(response.environments);
this.store.setPagination(headers);
}
});
if (_.isEqual(resp.config.params, this.requestData)) {
this.store.storeAvailableCount(resp.data.available_count);
this.store.storeStoppedCount(resp.data.stopped_count);
this.store.storeEnvironments(resp.data.environments);
this.store.setPagination(resp.headers);
}
},
/**
@ -70,7 +66,7 @@ export default {
updateContent(parameters) {
this.updateInternalState(parameters);
// fetch new data
return this.service.get(this.requestData)
return this.service.fetchEnvironments(this.requestData)
.then(response => this.successCallback(response))
.then(() => {
// restart polling
@ -105,7 +101,7 @@ export default {
fetchEnvironments() {
this.isLoading = true;
return this.service.get(this.requestData)
return this.service.fetchEnvironments(this.requestData)
.then(this.successCallback)
.catch(this.errorCallback);
},
@ -141,7 +137,7 @@ export default {
this.poll = new Poll({
resource: this.service,
method: 'get',
method: 'fetchEnvironments',
data: this.requestData,
successCallback: this.successCallback,
errorCallback: this.errorCallback,

View File

@ -1,25 +1,22 @@
/* eslint-disable class-methods-use-this */
import Vue from 'vue';
import VueResource from 'vue-resource';
Vue.use(VueResource);
import axios from '~/lib/utils/axios_utils';
export default class EnvironmentsService {
constructor(endpoint) {
this.environments = Vue.resource(endpoint);
this.environmentsEndpoint = endpoint;
this.folderResults = 3;
}
get(options = {}) {
fetchEnvironments(options = {}) {
const { scope, page } = options;
return this.environments.get({ scope, page });
return axios.get(this.environmentsEndpoint, { params: { scope, page } });
}
// eslint-disable-next-line class-methods-use-this
postAction(endpoint) {
return Vue.http.post(endpoint, {}, { emulateJSON: true });
return axios.post(endpoint, {}, { emulateJSON: true });
}
getFolderContent(folderUrl) {
return Vue.http.get(`${folderUrl}.json?per_page=${this.folderResults}`);
return axios.get(`${folderUrl}.json?per_page=${this.folderResults}`);
}
}

View File

@ -5,7 +5,7 @@ import LoadingButton from '~/vue_shared/components/loading_button.vue';
import CommitMessageField from './message_field.vue';
import Actions from './actions.vue';
import SuccessMessage from './success_message.vue';
import { activityBarViews, MAX_WINDOW_HEIGHT_COMPACT, COMMIT_ITEM_PADDING } from '../../constants';
import { activityBarViews, MAX_WINDOW_HEIGHT_COMPACT } from '../../constants';
export default {
components: {
@ -70,7 +70,7 @@ export default {
? this.$refs.formEl && this.$refs.formEl.offsetHeight
: this.$refs.compactEl && this.$refs.compactEl.offsetHeight;
this.componentHeight = elHeight + COMMIT_ITEM_PADDING;
this.componentHeight = elHeight;
},
enterTransition() {
this.$nextTick(() => {
@ -78,7 +78,7 @@ export default {
? this.$refs.compactEl && this.$refs.compactEl.offsetHeight
: this.$refs.formEl && this.$refs.formEl.offsetHeight;
this.componentHeight = elHeight + COMMIT_ITEM_PADDING;
this.componentHeight = elHeight;
});
},
afterEndTransition() {

View File

@ -122,11 +122,11 @@ export default {
<div
class="file"
:class="fileClass"
@click="clickFile"
role="button"
>
<div
class="file-name"
@click="clickFile"
role="button"
>
<span
class="ide-file-name str-truncated"

View File

@ -5,8 +5,6 @@ export const FILE_FINDER_EMPTY_ROW_HEIGHT = 33;
export const MAX_WINDOW_HEIGHT_COMPACT = 750;
export const COMMIT_ITEM_PADDING = 32;
// Commit message textarea
export const MAX_TITLE_LENGTH = 50;
export const MAX_BODY_LENGTH = 72;

View File

@ -93,10 +93,13 @@ export default {
v-html="actionTextHtml"
class="system-note-message">
</span>
<span class="system-note-separator">
&middot;
</span>
<a
:href="noteTimestampLink"
@click="updateTargetNoteHash"
class="note-timestamp">
class="note-timestamp system-note-separator">
<time-ago-tooltip
:time="createdAt"
tooltip-placement="bottom"

View File

@ -1,11 +1,21 @@
<script>
import $ from 'jquery';
import tooltip from '../../../vue_shared/directives/tooltip';
import Icon from '../../../vue_shared/components/icon.vue';
import { dasherize } from '../../../lib/utils/text_utility';
import eventHub from '../../event_hub';
import axios from '~/lib/utils/axios_utils';
import { dasherize } from '~/lib/utils/text_utility';
import { __ } from '~/locale';
import createFlash from '~/flash';
import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
/**
* Renders either a cancel, retry or play icon pointing to the given path.
* Renders either a cancel, retry or play icon button and handles the post request
*
* Used in:
* - mr widget mini pipeline graph: `mr_widget_pipeline.vue`
* - pipelines table
* - pipelines table in merge request page
* - pipelines table in commit page
* - pipelines detail page in big graph
*/
export default {
components: {
@ -32,16 +42,10 @@ export default {
required: true,
},
requestFinishedFor: {
type: String,
required: false,
default: '',
},
},
data() {
return {
isDisabled: false,
linkRequested: '',
};
},
@ -51,19 +55,28 @@ export default {
return `${actionIconDash} js-icon-${actionIconDash}`;
},
},
watch: {
requestFinishedFor() {
if (this.requestFinishedFor === this.linkRequested) {
this.isDisabled = false;
}
},
},
methods: {
/**
* The request should not be handled here.
* However due to this component being used in several
* different apps it avoids repetition & complexity.
*
*/
onClickAction() {
$(this.$el).tooltip('hide');
eventHub.$emit('postAction', this.link);
this.linkRequested = this.link;
this.isDisabled = true;
axios.post(`${this.link}.json`)
.then(() => {
this.isDisabled = false;
this.$emit('pipelineActionRequestComplete');
})
.catch(() => {
this.isDisabled = false;
createFlash(__('An error occurred while making the request.'));
});
},
},
};
@ -80,6 +93,6 @@ btn-transparent ci-action-icon-container ci-action-icon-wrapper"
data-container="body"
:disabled="isDisabled"
>
<icon :name="actionIcon" />
<icon :name="actionIcon"/>
</button>
</template>

View File

@ -42,11 +42,6 @@ export default {
type: Object,
required: true,
},
requestFinishedFor: {
type: String,
required: false,
default: '',
},
},
computed: {
@ -76,11 +71,15 @@ export default {
e.stopPropagation();
});
},
pipelineActionRequestComplete() {
this.$emit('pipelineActionRequestComplete');
},
},
};
</script>
<template>
<div class="ci-job-dropdown-container">
<div class="ci-job-dropdown-container dropdown">
<button
v-tooltip
type="button"
@ -110,7 +109,7 @@ export default {
<job-component
:job="item"
css-class-job-name="mini-pipeline-graph-dropdown-item"
:request-finished-for="requestFinishedFor"
@pipelineActionRequestComplete="pipelineActionRequestComplete"
/>
</li>
</ul>

View File

@ -16,11 +16,6 @@ export default {
type: Object,
required: true,
},
requestFinishedFor: {
type: String,
required: false,
default: '',
},
},
computed: {
@ -51,6 +46,10 @@ export default {
return className;
},
refreshPipelineGraph() {
this.$emit('refreshPipelineGraph');
},
},
};
</script>
@ -74,7 +73,7 @@ export default {
:key="stage.name"
:stage-connector-class="stageConnectorClass(index, stage)"
:is-first-column="isFirstColumn(index)"
:request-finished-for="requestFinishedFor"
@refreshPipelineGraph="refreshPipelineGraph"
/>
</ul>
</div>

View File

@ -46,11 +46,6 @@ export default {
required: false,
default: '',
},
requestFinishedFor: {
type: String,
required: false,
default: '',
},
},
computed: {
status() {
@ -84,6 +79,11 @@ export default {
return this.job.status && this.job.status.action && this.job.status.action.path;
},
},
methods: {
pipelineActionRequestComplete() {
this.$emit('pipelineActionRequestComplete');
},
},
};
</script>
<template>
@ -126,7 +126,7 @@ export default {
:tooltip-text="status.action.title"
:link="status.action.path"
:action-icon="status.action.icon"
:request-finished-for="requestFinishedFor"
@pipelineActionRequestComplete="pipelineActionRequestComplete"
/>
</div>
</template>

View File

@ -29,12 +29,6 @@ export default {
required: false,
default: '',
},
requestFinishedFor: {
type: String,
required: false,
default: '',
},
},
methods: {
@ -49,6 +43,10 @@ export default {
buildConnnectorClass(index) {
return index === 0 && !this.isFirstColumn ? 'left-connector' : '';
},
pipelineActionRequestComplete() {
this.$emit('refreshPipelineGraph');
},
},
};
</script>
@ -75,12 +73,13 @@ export default {
v-if="job.size === 1"
:job="job"
css-class-job-name="build-content"
@pipelineActionRequestComplete="pipelineActionRequestComplete"
/>
<dropdown-job-component
v-if="job.size > 1"
:job="job"
:request-finished-for="requestFinishedFor"
@pipelineActionRequestComplete="pipelineActionRequestComplete"
/>
</li>

View File

@ -9,6 +9,7 @@
import CommitComponent from '../../vue_shared/components/commit.vue';
import LoadingButton from '../../vue_shared/components/loading_button.vue';
import Icon from '../../vue_shared/components/icon.vue';
import { PIPELINES_TABLE } from '../constants';
/**
* Pipeline table row.
@ -46,6 +47,7 @@
required: true,
},
},
pipelinesTable: PIPELINES_TABLE,
data() {
return {
isRetrying: false,
@ -297,6 +299,7 @@
v-for="(stage, index) in pipeline.details.stages"
:key="index">
<pipeline-stage
:type="$options.pipelinesTable"
:stage="stage"
:update-dropdown="updateGraphDropdown"
/>

View File

@ -21,6 +21,7 @@ import Icon from '../../vue_shared/components/icon.vue';
import LoadingIcon from '../../vue_shared/components/loading_icon.vue';
import JobComponent from './graph/job_component.vue';
import tooltip from '../../vue_shared/directives/tooltip';
import { PIPELINES_TABLE } from '../constants';
export default {
components: {
@ -44,6 +45,12 @@ export default {
required: false,
default: false,
},
type: {
type: String,
required: false,
default: '',
},
},
data() {
@ -133,6 +140,16 @@ export default {
isDropdownOpen() {
return this.$el.classList.contains('open');
},
pipelineActionRequestComplete() {
if (this.type === PIPELINES_TABLE) {
// warn the table to update
eventHub.$emit('refreshPipelinesTable');
} else {
// close the dropdown in mr widget
$(this.$refs.dropdown).dropdown('toggle');
}
},
},
};
</script>
@ -151,6 +168,7 @@ export default {
id="stageDropdown"
aria-haspopup="true"
aria-expanded="false"
ref="dropdown"
>
<span
@ -188,6 +206,7 @@ export default {
<job-component
:job="job"
css-class-job-name="mini-pipeline-graph-dropdown-item"
@pipelineActionRequestComplete="pipelineActionRequestComplete"
/>
</li>
</ul>

View File

@ -1,2 +1,2 @@
// eslint-disable-next-line import/prefer-default-export
export const CANCEL_REQUEST = 'CANCEL_REQUEST';
export const PIPELINES_TABLE = 'PIPELINES_TABLE';

View File

@ -55,11 +55,13 @@ export default {
eventHub.$on('postAction', this.postAction);
eventHub.$on('retryPipeline', this.postAction);
eventHub.$on('clickedDropdown', this.updateTable);
eventHub.$on('refreshPipelinesTable', this.fetchPipelines);
},
beforeDestroy() {
eventHub.$off('postAction', this.postAction);
eventHub.$off('retryPipeline', this.postAction);
eventHub.$off('clickedDropdown', this.updateTable);
eventHub.$off('refreshPipelinesTable', this.fetchPipelines);
},
destroyed() {
this.poll.stop();

View File

@ -25,30 +25,14 @@ export default () => {
data() {
return {
mediator,
requestFinishedFor: null,
};
},
created() {
eventHub.$on('postAction', this.postAction);
},
beforeDestroy() {
eventHub.$off('postAction', this.postAction);
},
methods: {
postAction(action) {
// Click was made, reset this variable
this.requestFinishedFor = null;
this.mediator.service
.postAction(action)
.then(() => {
this.mediator.refreshPipeline();
this.requestFinishedFor = action;
})
.catch(() => {
this.requestFinishedFor = action;
Flash(__('An error occurred while making the request.'));
});
requestRefreshPipelineGraph() {
// When an action is clicked
// (wether in the dropdown or in the main nodes, we refresh the big graph)
this.mediator.refreshPipeline()
.catch(() => Flash(__('An error occurred while making the request.')));
},
},
render(createElement) {
@ -56,7 +40,9 @@ export default () => {
props: {
isLoading: this.mediator.state.isLoading,
pipeline: this.mediator.store.state.pipeline,
requestFinishedFor: this.requestFinishedFor,
},
on: {
refreshPipelineGraph: this.requestRefreshPipelineGraph,
},
});
},

View File

@ -7,7 +7,7 @@ export default class ShortcutsNavigation extends Shortcuts {
super();
Mousetrap.bind('g p', () => findAndFollowLink('.shortcuts-project'));
Mousetrap.bind('g e', () => findAndFollowLink('.shortcuts-project-activity'));
Mousetrap.bind('g v', () => findAndFollowLink('.shortcuts-project-activity'));
Mousetrap.bind('g f', () => findAndFollowLink('.shortcuts-tree'));
Mousetrap.bind('g c', () => findAndFollowLink('.shortcuts-commits'));
Mousetrap.bind('g j', () => findAndFollowLink('.shortcuts-builds'));
@ -16,9 +16,10 @@ export default class ShortcutsNavigation extends Shortcuts {
Mousetrap.bind('g i', () => findAndFollowLink('.shortcuts-issues'));
Mousetrap.bind('g b', () => findAndFollowLink('.shortcuts-issue-boards'));
Mousetrap.bind('g m', () => findAndFollowLink('.shortcuts-merge_requests'));
Mousetrap.bind('g t', () => findAndFollowLink('.shortcuts-todos'));
Mousetrap.bind('g w', () => findAndFollowLink('.shortcuts-wiki'));
Mousetrap.bind('g s', () => findAndFollowLink('.shortcuts-snippets'));
Mousetrap.bind('g k', () => findAndFollowLink('.shortcuts-kubernetes'));
Mousetrap.bind('g e', () => findAndFollowLink('.shortcuts-environments'));
Mousetrap.bind('i', () => findAndFollowLink('.shortcuts-new-issue'));
this.enabledHelp.push('.hidden-shortcut.project');

View File

@ -40,7 +40,7 @@ export default {
:class="cssClass"
:title="tooltipTitle(time)"
:data-placement="tooltipPlacement"
data-container="body">
{{ timeFormated(time) }}
data-container="body"
v-text="timeFormated(time)">
</time>
</template>

View File

@ -279,251 +279,14 @@ ul.indent-list {
padding: 10px 0 0 30px;
}
// Specific styles for tree list
@keyframes spin-avatar {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.groups-list-tree-container {
.has-no-search-results {
text-align: center;
padding: $gl-padding;
font-style: italic;
color: $well-light-text-color;
}
> .group-list-tree > .group-row.has-children:first-child {
border-top: 0;
}
}
.group-list-tree {
.avatar-container.content-loading {
position: relative;
> a,
> a .avatar {
height: 100%;
border-radius: 50%;
}
> a {
padding: 2px;
.avatar {
border: 2px solid $white-normal;
&.identicon {
line-height: 15px;
}
}
}
&::after {
content: "";
position: absolute;
height: 100%;
width: 100%;
background-color: transparent;
border: 2px outset $kdb-border;
border-radius: 50%;
animation: spin-avatar 3s infinite linear;
}
}
.folder-toggle-wrap {
float: left;
line-height: $list-text-height;
font-size: 0;
span {
font-size: $gl-font-size;
}
}
.folder-caret,
.item-type-icon {
display: inline-block;
}
.folder-caret {
width: 15px;
svg {
margin-bottom: 2px;
}
}
.item-type-icon {
margin-top: 2px;
width: 20px;
}
> .group-row:not(.has-children) {
.folder-caret {
opacity: 0;
}
}
.content-list li:last-child {
padding-bottom: 0;
}
.group-list-tree {
margin-bottom: 0;
margin-left: 30px;
position: relative;
&::before {
content: '';
display: block;
width: 0;
position: absolute;
top: 5px;
bottom: 0;
left: -16px;
border-left: 2px solid $border-white-normal;
}
.group-row {
position: relative;
&::before {
content: "";
display: block;
width: 10px;
height: 0;
border-top: 2px solid $border-white-normal;
position: absolute;
top: 30px;
left: -16px;
}
&:last-child::before {
background: $white-light;
height: auto;
top: 30px;
bottom: 0;
}
&.being-removed {
opacity: 0.5;
}
}
}
.group-row {
padding: 0;
&.has-children {
border-top: 0;
}
&:first-child {
border-top: 1px solid $white-normal;
}
&:last-of-type {
.group-row-contents:not(:hover) {
border-bottom: 1px solid transparent;
}
}
}
.group-row-contents {
padding: 10px 10px 8px;
border-top: solid 1px transparent;
border-bottom: solid 1px $white-normal;
&:hover {
border-color: $row-hover-border;
background-color: $row-hover;
cursor: pointer;
}
.avatar-container > a {
width: 100%;
text-decoration: none;
}
&.has-more-items {
display: block;
padding: 20px 10px;
}
.stats {
position: relative;
line-height: 46px;
> span {
display: inline-flex;
align-items: center;
height: 16px;
min-width: 30px;
}
> span:last-child {
margin-right: 0;
}
.stat-value {
margin: 2px 0 0 5px;
}
}
.controls {
margin-left: 5px;
> .btn {
margin-right: $btn-xs-side-margin;
}
}
}
.project-row-contents .stats {
line-height: inherit;
> span:first-child {
margin-left: 25px;
}
.item-visibility {
margin-right: 0;
}
.last-updated {
position: absolute;
right: 12px;
min-width: 250px;
text-align: right;
color: $gl-text-color-secondary;
}
}
}
.namespace-title {
.tooltip-inner {
max-width: 350px;
}
}
ul.group-list-tree {
li.group-row {
> .group-row-contents .title {
line-height: $list-text-height;
}
&.has-description > .group-row-contents .title {
line-height: inherit;
}
}
}
.js-groups-list-holder {
.groups-list-loading {
font-size: 34px;
text-align: center;
}
}

View File

@ -1,5 +1,3 @@
@import './issues/issue_count_badge';
[v-cloak] {
display: none;
}

View File

@ -18,6 +18,10 @@
.group-row {
@include basic-list-stats;
.description p {
margin-bottom: 0;
}
}
.ldap-group-links {
@ -237,3 +241,231 @@
overflow-y: unset;
}
}
.groups-list-tree-container {
.has-no-search-results {
text-align: center;
padding: $gl-padding;
font-style: italic;
color: $well-light-text-color;
}
> .group-list-tree > .group-row.has-children:first-child {
border-top: 0;
}
}
.group-list-tree {
.avatar-container.content-loading {
position: relative;
> a,
> a .avatar {
height: 100%;
border-radius: 50%;
}
> a {
padding: 2px;
.avatar {
border: 2px solid $white-normal;
&.identicon {
line-height: 15px;
}
}
}
&::after {
content: "";
position: absolute;
height: 100%;
width: 100%;
background-color: transparent;
border: 2px outset $kdb-border;
border-radius: 50%;
animation: spin-avatar 3s infinite linear;
}
}
.folder-toggle-wrap {
float: left;
line-height: $list-text-height;
font-size: 0;
span {
font-size: $gl-font-size;
}
}
.folder-caret,
.item-type-icon {
display: inline-block;
}
.folder-caret {
width: 15px;
svg {
margin-bottom: 2px;
}
}
.item-type-icon {
margin-top: 2px;
width: 20px;
}
> .group-row:not(.has-children) {
.folder-caret {
opacity: 0;
}
}
.content-list li:last-child {
padding-bottom: 0;
}
.group-list-tree {
margin-bottom: 0;
margin-left: 30px;
position: relative;
&::before {
content: '';
display: block;
width: 0;
position: absolute;
top: 5px;
bottom: 0;
left: -16px;
border-left: 2px solid $border-white-normal;
}
.group-row {
position: relative;
&::before {
content: "";
display: block;
width: 10px;
height: 0;
border-top: 2px solid $border-white-normal;
position: absolute;
top: 30px;
left: -16px;
}
&:last-child::before {
background: $white-light;
height: auto;
top: 30px;
bottom: 0;
}
&.being-removed {
opacity: 0.5;
}
}
}
.group-row {
padding: 0;
&.has-children {
border-top: 0;
}
&:first-child {
border-top: 1px solid $white-normal;
}
}
.group-row-contents {
padding: $gl-padding-top;
&:hover {
border-color: $row-hover-border;
background-color: $row-hover;
cursor: pointer;
}
.avatar-container > a {
width: 100%;
text-decoration: none;
}
&.has-more-items {
display: block;
padding: 20px 10px;
}
.stats {
position: relative;
line-height: 46px;
> span {
display: inline-flex;
align-items: center;
height: 16px;
min-width: 30px;
}
> span:last-child {
margin-right: 0;
}
.stat-value {
margin: 2px 0 0 5px;
}
}
.controls {
margin-left: 5px;
> .btn {
margin-right: $btn-xs-side-margin;
}
}
}
.project-row-contents .stats {
line-height: inherit;
> span:first-child {
margin-left: 25px;
}
.item-visibility {
margin-right: 0;
}
.last-updated {
position: absolute;
right: 12px;
min-width: 250px;
text-align: right;
color: $gl-text-color-secondary;
}
}
}
ul.group-list-tree {
li.group-row {
> .group-row-contents .title {
line-height: $list-text-height;
}
&.has-description > .group-row-contents .title {
line-height: inherit;
}
}
}
.js-groups-list-holder {
.groups-list-loading {
font-size: 34px;
text-align: center;
}
}

View File

@ -197,9 +197,21 @@
}
&.assignee {
.author_link:hover {
.author {
text-decoration: underline;
.author_link {
display: block;
padding-left: 42px;
position: relative;
&:hover {
.author {
text-decoration: underline;
}
}
.avatar {
left: 0;
position: absolute;
top: 0;
}
}
}

View File

@ -1,5 +1,3 @@
@import "./issues/issue_count_badge";
.issues-list {
.issue {
padding: 10px 0 10px $gl-padding;

View File

@ -455,6 +455,10 @@ ul.notes {
white-space: normal;
}
.system-note-separator {
color: $gl-text-color-disabled;
}
a:hover {
text-decoration: underline;
}

View File

@ -66,13 +66,9 @@
}
}
.btn-group {
&.open {
.btn-default {
background-color: $white-normal;
border-color: $border-white-normal;
}
}
.btn-group.open .btn-default {
background-color: $white-normal;
border-color: $border-white-normal;
}
.btn .text-center {
@ -361,16 +357,14 @@
&:not(:first-child) {
margin-left: 44px;
.left-connector {
&::before {
content: '';
position: absolute;
top: 48%;
left: -44px;
border-top: 2px solid $border-color;
width: 44px;
height: 1px;
}
.left-connector::before {
content: '';
position: absolute;
top: 48%;
left: -44px;
border-top: 2px solid $border-color;
width: 44px;
height: 1px;
}
}
}
@ -386,22 +380,16 @@
&:last-child {
.build {
// Remove right connecting horizontal line from first build in last stage
&:first-child {
&::after {
border: 0;
}
&:first-child::after {
border: 0;
}
// Remove right curved connectors from all builds in last stage
&:not(:first-child) {
&::after {
border: 0;
}
&:not(:first-child)::after {
border: 0;
}
// Remove opposite curve
.curve {
&::before {
display: none;
}
.curve::before {
display: none;
}
}
}
@ -409,16 +397,12 @@
&:first-child {
.build {
// Remove left curved connectors from all builds in first stage
&:not(:first-child) {
&::before {
border: 0;
}
&:not(:first-child)::before {
border: 0;
}
// Remove opposite curve
.curve {
&::after {
display: none;
}
.curve::after {
display: none;
}
}
}

View File

@ -39,12 +39,15 @@
.ide-file-list {
flex: 1;
padding-left: $gl-padding;
padding-right: $gl-padding;
padding-bottom: $grid-size;
.file {
cursor: pointer;
&.file-open {
background: $link-active-background;
background: $white-normal;
}
&.file-active {
@ -84,12 +87,11 @@
.ide-new-btn {
display: none;
margin-right: -8px;
}
&:hover,
&:focus {
background: $link-active-background;
background: $white-normal;
.ide-new-btn {
display: block;
@ -111,12 +113,11 @@
}
}
.file-name,
.file-col-commit-message {
.file-name {
display: flex;
overflow: visible;
align-items: center;
padding: 6px 12px;
width: 100%;
}
.multi-file-loading-container {
@ -306,8 +307,18 @@
}
.preview-container {
height: 100%;
overflow: auto;
flex-grow: 1;
position: relative;
.md-previewer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: auto;
padding: $gl-padding;
}
.file-container {
background-color: $gray-darker;
@ -347,10 +358,6 @@
color: $diff-image-info-color;
}
}
.md-previewer {
padding: $gl-padding;
}
}
.ide-mode-tabs {
@ -501,7 +508,7 @@
align-items: center;
margin-bottom: 0;
border-bottom: 1px solid $white-dark;
padding: $gl-btn-padding $gl-padding;
padding: 12px 0;
}
.multi-file-commit-panel-header-title {
@ -523,32 +530,31 @@
.multi-file-commit-list {
flex: 1;
overflow: auto;
padding: $gl-padding;
padding: $grid-size 0;
margin-left: -$grid-size;
margin-right: -$grid-size;
min-height: 60px;
.multi-file-commit-list-item {
margin-left: 0;
margin-right: 0;
}
&.help-block {
margin-left: 0;
right: 0;
}
}
.multi-file-commit-list-item {
display: flex;
padding: 0;
align-items: center;
border-radius: $border-radius-default;
.multi-file-discard-btn {
display: none;
margin-top: -2px;
margin-left: auto;
margin-right: $grid-size;
color: $gl-link-color;
&:focus,
&:hover {
text-decoration: underline;
}
}
&:hover {
background: $white-normal;
.multi-file-discard-btn {
display: flex;
}
@ -584,25 +590,39 @@
}
}
.multi-file-commit-list-item,
.ide-file-list .file {
display: flex;
align-items: center;
margin-left: -$grid-size;
margin-right: -$grid-size;
padding: $grid-size / 2 $grid-size;
border-radius: $border-radius-default;
text-align: left;
&:hover,
&:focus {
background: $white-normal;
}
}
.multi-file-commit-list-path {
padding: $grid-size / 2;
padding-left: $grid-size;
padding: 0;
background: none;
border: 0;
text-align: left;
width: 100%;
min-width: 0;
&:hover,
&:focus {
outline: 0;
}
svg {
min-width: 16px;
vertical-align: middle;
display: inline-block;
}
&:hover,
&:focus {
outline: 0;
}
}
.multi-file-commit-list-file-path {
@ -619,12 +639,18 @@
.multi-file-commit-form {
position: relative;
padding: $gl-padding;
background-color: $white-light;
border-top: 1px solid $white-dark;
border-left: 1px solid $white-dark;
transition: all 0.3s ease;
> form,
> .commit-form-compact {
padding: $gl-padding 0;
margin-left: $gl-padding;
margin-right: $gl-padding;
border-top: 1px solid $white-dark;
}
.btn {
font-size: $gl-font-size;
}
@ -787,8 +813,9 @@
display: flex;
flex: 1;
flex-direction: column;
width: 100%;
min-height: 140px;
margin-left: $gl-padding;
margin-right: $gl-padding;
&.is-first {
border-bottom: 1px solid $white-dark;
@ -979,9 +1006,8 @@
.ide-tree-header {
display: flex;
align-items: center;
padding: 10px 0;
margin-left: 10px;
margin-right: 10px;
margin-bottom: 8px;
padding: 12px 0;
border-bottom: 1px solid $white-dark;
.ide-new-btn {
@ -1012,9 +1038,9 @@
.commit-form-slide-up-enter-active,
.commit-form-slide-up-leave-active {
position: absolute;
top: 16px;
left: 16px;
right: 16px;
top: 0;
left: 0;
right: 0;
transition: all 0.3s ease;
}

View File

@ -94,7 +94,7 @@ module Boards
def serialize_as_json(resource)
resource.as_json(
only: [:id, :iid, :project_id, :title, :confidential, :due_date, :relative_position],
only: [:id, :iid, :project_id, :title, :confidential, :due_date, :relative_position, :weight],
labels: true,
issue_endpoints: true,
include_full_project_path: board.group_board?,

View File

@ -0,0 +1,15 @@
module AcceptsPendingInvitations
extend ActiveSupport::Concern
def accept_pending_invitations
return unless resource.active_for_authentication?
clear_stored_location_for_resource if resource.accept_pending_invitations!.any?
end
def clear_stored_location_for_resource
session_key = stored_location_key_for(resource)
session.delete(session_key)
end
end

View File

@ -1,4 +1,6 @@
class ConfirmationsController < Devise::ConfirmationsController
include AcceptsPendingInvitations
def almost_there
flash[:notice] = nil
render layout: "devise_empty"
@ -11,6 +13,8 @@ class ConfirmationsController < Devise::ConfirmationsController
end
def after_confirmation_path_for(resource_name, resource)
accept_pending_invitations
# incoming resource can either be a :user or an :email
if signed_in?(:user)
after_sign_in(resource)

View File

@ -23,7 +23,7 @@ class Profiles::KeysController < Profiles::ApplicationController
def destroy
@key = current_user.keys.find(params[:id])
@key.destroy
Keys::DestroyService.new(current_user).execute(@key)
respond_to do |format|
format.html { redirect_to profile_keys_url, status: 302 }

View File

@ -23,8 +23,12 @@ class Projects::CommitController < Projects::ApplicationController
respond_to do |format|
format.html { render }
format.diff { render text: @commit.to_diff }
format.patch { render text: @commit.to_patch }
format.diff do
send_git_diff(@project.repository, @commit.diff_refs)
end
format.patch do
send_git_patch(@project.repository, @commit.diff_refs)
end
end
end

View File

@ -18,19 +18,12 @@ class Projects::PipelinesController < Projects::ApplicationController
.page(params[:page])
.per(30)
@running_count = PipelinesFinder
.new(project, scope: 'running').execute.count
@running_count = limited_pipelines_count(project, 'running')
@pending_count = limited_pipelines_count(project, 'pending')
@finished_count = limited_pipelines_count(project, 'finished')
@pipelines_count = limited_pipelines_count(project)
@pending_count = PipelinesFinder
.new(project, scope: 'pending').execute.count
@finished_count = PipelinesFinder
.new(project, scope: 'finished').execute.count
@pipelines_count = PipelinesFinder
.new(project).execute.count
@pipelines.map(&:commit) # List commits for batch loading
Gitlab::Ci::Pipeline::Preloader.preload(@pipelines)
respond_to do |format|
format.html
@ -41,7 +34,7 @@ class Projects::PipelinesController < Projects::ApplicationController
pipelines: PipelineSerializer
.new(project: @project, current_user: @current_user)
.with_pagination(request, response)
.represent(@pipelines),
.represent(@pipelines, disable_coverage: true),
count: {
all: @pipelines_count,
running: @running_count,
@ -185,4 +178,10 @@ class Projects::PipelinesController < Projects::ApplicationController
def authorize_update_pipeline!
return access_denied! unless can?(current_user, :update_pipeline, @pipeline)
end
def limited_pipelines_count(project, scope = nil)
finder = PipelinesFinder.new(project, scope: scope)
view_context.limited_counter_with_delimiter(finder.execute)
end
end

View File

@ -11,7 +11,14 @@ module Projects
@hook = ProjectHook.new
# Services
@services = @project.find_or_initialize_services
@services = @project.find_or_initialize_services(exceptions: service_exceptions)
end
private
# Returns a list of services that should be hidden from the list
def service_exceptions
@project.disabled_services.dup
end
end
end

View File

@ -1,5 +1,6 @@
class RegistrationsController < Devise::RegistrationsController
include Recaptcha::Verify
include AcceptsPendingInvitations
before_action :whitelist_query_limiting, only: [:destroy]
@ -16,6 +17,7 @@ class RegistrationsController < Devise::RegistrationsController
end
if !Gitlab::Recaptcha.load_configurations! || verify_recaptcha
accept_pending_invitations
super
else
flash[:alert] = 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'
@ -60,7 +62,7 @@ class RegistrationsController < Devise::RegistrationsController
def after_sign_up_path_for(user)
Gitlab::AppLogger.info("User Created: username=#{user.username} email=#{user.email} ip=#{request.remote_ip} confirmed:#{user.confirmed?}")
user.confirmed? ? dashboard_projects_path : users_almost_there_path
user.confirmed? ? stored_location_for(user) || dashboard_projects_path : users_almost_there_path
end
def after_inactive_sign_up_path_for(resource)

View File

@ -6,7 +6,7 @@
# klass - actual class like Issue or MergeRequest
# current_user - which user use
# params:
# scope: 'created-by-me' or 'assigned-to-me' or 'all'
# scope: 'created_by_me' or 'assigned_to_me' or 'all'
# state: 'opened' or 'closed' or 'all'
# group_id: integer
# project_id: integer
@ -282,9 +282,9 @@ class IssuableFinder
return items.none if current_user_related? && !current_user
case params[:scope]
when 'created-by-me', 'authored'
when 'created_by_me', 'authored'
items.where(author_id: current_user.id)
when 'assigned-to-me'
when 'assigned_to_me'
items.assigned_to(current_user)
else
items
@ -426,6 +426,7 @@ class IssuableFinder
end
def current_user_related?
params[:scope] == 'created-by-me' || params[:scope] == 'authored' || params[:scope] == 'assigned-to-me'
scope = params[:scope]
scope == 'created_by_me' || scope == 'authored' || scope == 'assigned_to_me'
end
end

View File

@ -5,7 +5,7 @@
# Arguments:
# current_user - which user use
# params:
# scope: 'created-by-me' or 'assigned-to-me' or 'all'
# scope: 'created_by_me' or 'assigned_to_me' or 'all'
# state: 'open' or 'closed' or 'all'
# group_id: integer
# project_id: integer

View File

@ -5,7 +5,7 @@
# Arguments:
# current_user - which user use
# params:
# scope: 'created-by-me' or 'assigned-to-me' or 'all'
# scope: 'created_by_me' or 'assigned_to_me' or 'all'
# state: 'open', 'closed', 'merged', or 'all'
# group_id: integer
# project_id: integer

View File

@ -13,7 +13,7 @@ class PersonalProjectsFinder < UnionFinder
def execute(current_user = nil)
segments = all_projects(current_user)
find_union(segments, Project).includes(:namespace).order_id_desc
find_union(segments, Project).includes(:namespace).order_updated_desc
end
private

View File

@ -184,7 +184,7 @@ module Ci
end
def playable?
action? && (manual? || complete?)
action? && (manual? || retryable?)
end
def action?
@ -599,6 +599,7 @@ module Ci
break variables unless persisted?
variables
.concat(pipeline.persisted_variables)
.append(key: 'CI_JOB_ID', value: id.to_s)
.append(key: 'CI_JOB_TOKEN', value: token, public: false)
.append(key: 'CI_BUILD_ID', value: id.to_s)
@ -661,7 +662,7 @@ module Ci
Gitlab::Ci::Variables::Collection.new.tap do |variables|
break variables unless gitlab_deploy_token
variables.append(key: 'CI_DEPLOY_USER', value: gitlab_deploy_token.name)
variables.append(key: 'CI_DEPLOY_USER', value: gitlab_deploy_token.username)
variables.append(key: 'CI_DEPLOY_PASSWORD', value: gitlab_deploy_token.token, public: false)
end
end

View File

@ -411,7 +411,18 @@ module Ci
end
def has_warnings?
builds.latest.failed_but_allowed.any?
number_of_warnings.positive?
end
def number_of_warnings
BatchLoader.for(id).batch(default_value: 0) do |pipeline_ids, loader|
Build.where(commit_id: pipeline_ids)
.latest
.failed_but_allowed
.group(:commit_id)
.count
.each { |id, amount| loader.call(id, amount) }
end
end
def set_config_source
@ -517,9 +528,14 @@ module Ci
strong_memoize(:legacy_trigger) { trigger_requests.first }
end
def persisted_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'CI_PIPELINE_ID', value: id.to_s) if persisted?
end
end
def predefined_variables
Gitlab::Ci::Variables::Collection.new
.append(key: 'CI_PIPELINE_ID', value: id.to_s)
.append(key: 'CI_PIPELINE_IID', value: iid.to_s)
.append(key: 'CI_CONFIG_PATH', value: ci_yaml_file_path)
.append(key: 'CI_PIPELINE_SOURCE', value: source.to_s)

View File

@ -75,7 +75,7 @@ module Ci
project_type: 3
}
cached_attr_reader :version, :revision, :platform, :architecture, :contacted_at, :ip_address
cached_attr_reader :version, :revision, :platform, :architecture, :ip_address, :contacted_at
chronic_duration_attr :maximum_timeout_human_readable, :maximum_timeout

View File

@ -49,6 +49,11 @@ module Clusters
# ensures headers containing auth data are appended to original k8s client options
options = kube_client.rest_client.options.merge(headers: kube_client.headers)
RestClient::Resource.new(proxy_url, options)
rescue Kubeclient::HttpError
# If users have mistakenly set parameters or removed the depended clusters,
# `proxy_url` could raise an exception because gitlab can not communicate with the cluster.
# Since `PrometheusAdapter#can_query?` is eargely loaded on environement pages in gitlab,
# we need to silence the exceptions
end
private

View File

@ -224,8 +224,34 @@ class Commit
Gitlab::ClosingIssueExtractor.new(project, current_user).closed_by_message(safe_message)
end
def lazy_author
BatchLoader.for(author_email.downcase).batch do |emails, loader|
# A Hash that maps user Emails to the corresponding User objects. The
# Emails at this point are the _primary_ Emails of the Users.
users_for_emails = User
.by_any_email(emails)
.each_with_object({}) { |user, hash| hash[user.email] = user }
users_for_ids = users_for_emails
.values
.each_with_object({}) { |user, hash| hash[user.id] = user }
# Some commits may have used an alternative Email address. In this case we
# need to query the "emails" table to map those addresses to User objects.
Email
.where(email: emails - users_for_emails.keys)
.pluck(:email, :user_id)
.each { |(email, id)| users_for_emails[email] = users_for_ids[id] }
users_for_emails.each { |email, user| loader.call(email, user) }
end
end
def author
User.find_by_any_email(author_email.downcase)
# We use __sync so that we get the actual objects back (including an actual
# nil), instead of a wrapper, as returning a wrapped nil breaks a lot of
# code.
lazy_author.__sync
end
request_cache(:author) { author_email.downcase }

View File

@ -2,6 +2,7 @@ class CommitStatus < ActiveRecord::Base
include HasStatus
include Importable
include AfterCommitQueue
include Presentable
self.table_name = 'ci_builds'

View File

@ -7,7 +7,11 @@ module RedisCacheable
class_methods do
def cached_attr_reader(*attributes)
attributes.each do |attribute|
define_method("#{attribute}") do
define_method(attribute) do
unless self.has_attribute?(attribute)
raise ArgumentError, "`cached_attr_reader` requires the #{self.class.name}\##{attribute} attribute to have a database column"
end
cached_attribute(attribute) || read_attribute(attribute)
end
end
@ -15,13 +19,16 @@ module RedisCacheable
end
def cached_attribute(attribute)
(cached_attributes || {})[attribute]
cached_value = (cached_attributes || {})[attribute]
cast_value_from_cache(attribute, cached_value) if cached_value
end
def cache_attributes(values)
Gitlab::Redis::SharedState.with do |redis|
redis.set(cache_attribute_key, values.to_json, ex: CACHED_ATTRIBUTES_EXPIRY_TIME)
end
clear_memoization(:cached_attributes)
end
private
@ -38,4 +45,12 @@ module RedisCacheable
end
end
end
def cast_value_from_cache(attribute, value)
if Gitlab.rails5?
self.class.type_for_attribute(attribute).cast(value)
else
self.class.column_for_attribute(attribute).type_cast_from_database(value)
end
end
end

View File

@ -12,8 +12,8 @@ module Sortable
scope :order_created_asc, -> { reorder(created_at: :asc) }
scope :order_updated_desc, -> { reorder(updated_at: :desc) }
scope :order_updated_asc, -> { reorder(updated_at: :asc) }
scope :order_name_asc, -> { reorder(name: :asc) }
scope :order_name_desc, -> { reorder(name: :desc) }
scope :order_name_asc, -> { reorder("lower(name) asc") }
scope :order_name_desc, -> { reorder("lower(name) desc") }
end
module ClassMethods

View File

@ -53,6 +53,10 @@ module TimeTrackable
Gitlab::TimeTrackingFormatter.output(time_estimate)
end
def time_estimate=(val)
val.is_a?(Integer) ? super([val, Gitlab::Database::MAX_INT_VALUE].min) : super(val)
end
private
def touchable?

View File

@ -997,7 +997,7 @@ class Project < ActiveRecord::Base
available_services_names = Service.available_services_names - exceptions
available_services_names.map do |service_name|
available_services = available_services_names.map do |service_name|
service = find_service(services, service_name)
if service
@ -1014,6 +1014,14 @@ class Project < ActiveRecord::Base
end
end
end
available_services.reject do |service|
disabled_services.include?(service.to_param)
end
end
def disabled_services
[]
end
def find_or_initialize_service(name)

View File

@ -860,6 +860,16 @@ class User < ActiveRecord::Base
confirmed? && !temp_oauth_email?
end
def accept_pending_invitations!
pending_invitations.select do |member|
member.accept_invite!(self)
end
end
def pending_invitations
Member.where(invite_email: verified_emails).invite
end
def all_emails
all_emails = []
all_emails << email unless temp_oauth_email?

View File

@ -1,16 +1,5 @@
module Ci
class BuildPresenter < Gitlab::View::Presenter::Delegated
CALLOUT_FAILURE_MESSAGES = {
unknown_failure: 'There is an unknown failure, please try again',
script_failure: 'There has been a script failure. Check the job log for more information',
api_failure: 'There has been an API failure, please try again',
stuck_or_timeout_failure: 'There has been a timeout failure or the job got stuck. Check your timeout limits or try again',
runner_system_failure: 'There has been a runner system failure, please try again',
missing_dependency_failure: 'There has been a missing dependency failure, check the job log for more information'
}.freeze
presents :build
class BuildPresenter < CommitStatusPresenter
def erased_by_user?
# Build can be erased through API, therefore it does not have
# `erased_by` user assigned in that case.
@ -44,14 +33,6 @@ module Ci
"#{subject.name} - #{detailed_status.status_tooltip}"
end
def callout_failure_message
CALLOUT_FAILURE_MESSAGES[failure_reason.to_sym]
end
def recoverable?
failed? && !unrecoverable?
end
private
def tooltip_for_badge
@ -61,9 +42,5 @@ module Ci
def detailed_status
@detailed_status ||= subject.detailed_status(user)
end
def unrecoverable?
script_failure? || missing_dependency_failure?
end
end
end

View File

@ -0,0 +1,24 @@
class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
CALLOUT_FAILURE_MESSAGES = {
unknown_failure: 'There is an unknown failure, please try again',
script_failure: 'There has been a script failure. Check the job log for more information',
api_failure: 'There has been an API failure, please try again',
stuck_or_timeout_failure: 'There has been a timeout failure or the job got stuck. Check your timeout limits or try again',
runner_system_failure: 'There has been a runner system failure, please try again',
missing_dependency_failure: 'There has been a missing dependency failure, check the job log for more information'
}.freeze
presents :build
def callout_failure_message
CALLOUT_FAILURE_MESSAGES[failure_reason.to_sym]
end
def recoverable?
failed? && !unrecoverable?
end
def unrecoverable?
script_failure? || missing_dependency_failure?
end
end

View File

@ -0,0 +1,2 @@
class GenericCommitStatusPresenter < CommitStatusPresenter
end

View File

@ -4,7 +4,11 @@ class PipelineEntity < Grape::Entity
expose :id
expose :user, using: UserEntity
expose :active?, as: :active
expose :coverage
# Coverage isn't always necessary (e.g. when displaying project pipelines in
# the UI). Instead of creating an entirely different entity we just allow the
# disabling of this specific field whenever necessary.
expose :coverage, unless: proc { options[:disable_coverage] }
expose :source
expose :created_at, :updated_at

View File

@ -2,7 +2,7 @@ module Keys
class BaseService
attr_accessor :user, :params
def initialize(user, params)
def initialize(user, params = {})
@user, @params = user, params
@ip_address = @params.delete(:ip_address)
end

View File

@ -0,0 +1,12 @@
module Keys
class DestroyService < ::Keys::BaseService
def execute(key)
key.destroy if destroy_possible?(key)
end
# overriden in EE::Keys::DestroyService
def destroy_possible?(key)
true
end
end
end

View File

@ -2,14 +2,14 @@ module Lfs
class UnlockFileService < BaseService
def execute
unless can?(current_user, :push_code, project)
raise Gitlab::GitAccess::UnauthorizedError, 'You have no permissions'
raise Gitlab::GitAccess::UnauthorizedError, _('You have no permissions')
end
unlock_file
rescue Gitlab::GitAccess::UnauthorizedError => ex
error(ex.message, 403)
rescue ActiveRecord::RecordNotFound
error('Lock not found', 404)
error(_('Lock not found'), 404)
rescue => ex
error(ex.message, 500)
end
@ -24,9 +24,9 @@ module Lfs
success(lock: lock, http_status: :ok)
elsif forced
error('You must have master access to force delete a lock', 403)
error(_('You must have master access to force delete a lock'), 403)
else
error("#{lock.path} is locked by GitLab User #{lock.user_id}", 403)
error(_("%{lock_path} is locked by GitLab User %{lock_user_id}") % { lock_path: lock.path, lock_user_id: lock.user_id }, 403)
end
end

View File

@ -5,6 +5,7 @@ module Milestones
def initialize(parent, user, params = {})
@parent, @current_user, @params = parent, user, params.dup
super
end
end
end

View File

@ -27,11 +27,11 @@
.col-sm-10
= f.color_field :font, class: "form-control"
.form-group
= f.label :starts_at, class: 'control-label'
= f.label :starts_at, _("Starts at (UTC)"), class: 'control-label'
.col-sm-10.datetime-controls
= f.datetime_select :starts_at, {}, class: 'form-control form-control-inline'
.form-group
= f.label :ends_at, class: 'control-label'
= f.label :ends_at, _("Ends at (UTC)"), class: 'control-label'
.col-sm-10.datetime-controls
= f.datetime_select :ends_at, {}, class: 'form-control form-control-inline'
.form-actions

View File

@ -33,7 +33,7 @@
= tag
%td
- if runner.contacted_at
#{time_ago_in_words(runner.contacted_at)} ago
= time_ago_with_tooltip runner.contacted_at
- else
Never
%td.admin-runner-btn-group-cell

View File

@ -121,7 +121,7 @@
%tr
%td.shortcut
.key g
.key e
.key v
%td
Go to the project's activity feed
%tr
@ -172,6 +172,18 @@
.key m
%td
Go to merge requests
%tr
%td.shortcut
.key g
.key e
%td
Go to environments
%tr
%td.shortcut
.key g
.key k
%td
Go to kubernetes
%tr
%td.shortcut
.key g
@ -219,6 +231,17 @@
%td.shortcut
.key y
%td Go to file permalink
%tbody
%tr
%th
%th Web IDE
%tr
%td.shortcut
- if browser.platform.mac?
.key &#8984; p
- else
.key ctrl p
%td Go to file
.col-lg-4
%table.shortcut-mappings
%tbody.hidden-shortcut.network{ style: 'display:none' }

View File

@ -19,7 +19,7 @@
= nav_link(path: 'projects#show', html_options: { class: "fly-out-top-item" } ) do
= link_to project_path(@project) do
%strong.fly-out-top-item-name
= _('Overview')
= _('Project')
%li.divider.fly-out-top-item
= nav_link(path: 'projects#show') do
= link_to project_path(@project), title: _('Project details'), class: 'shortcuts-project' do
@ -154,7 +154,7 @@
= nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :artifacts]) do
= link_to project_pipelines_path(@project), class: 'shortcuts-pipelines' do
.nav-icon-container
= sprite_icon('pipeline')
= sprite_icon('rocket')
%span.nav-item-name
= _('CI / CD')
@ -212,7 +212,7 @@
- if project_nav_tab? :clusters
- show_cluster_hint = show_gke_cluster_integration_callout?(@project)
= nav_link(controller: [:clusters, :user, :gcp]) do
= link_to project_clusters_path(@project), title: _('Kubernetes'), class: 'shortcuts-cluster' do
= link_to project_clusters_path(@project), title: _('Kubernetes'), class: 'shortcuts-kubernetes' do
%span
= _('Kubernetes')
- if show_cluster_hint

View File

@ -4,7 +4,7 @@
by
= link_to member.created_by.name, user_url(member.created_by)
to join the
= link_to member_source.human_name, member_source.web_url
= link_to member_source.human_name, member_source.public? ? member_source.web_url : invite_url(@token)
#{member_source.model_name.singular} as #{member.human_access}.
%p

0
app/views/projects/forks/new.html.haml Executable file → Normal file
View File

View File

@ -30,7 +30,7 @@
%br
%p
- deploy_token = link_to(_('deploy token'), help_page_path('user/project/deploy_tokens/index', anchor: 'read-container-registry-images'), target: '_blank')
= s_('ContainerRegistry|You can also %{deploy_token} for read-only access to the registry images.').html_safe % { deploy_token: deploy_token }
= s_('ContainerRegistry|You can also use a %{deploy_token} for read-only access to the registry images.').html_safe % { deploy_token: deploy_token }
%br
%p
= s_('ContainerRegistry|Once you log in, you&rsquo;re free to create and upload a container image using the common %{build} and %{push} commands').html_safe % { build: "<code>build</code>".html_safe, push: "<code>push</code>".html_safe }

View File

@ -41,8 +41,9 @@
- if note.system
%span.system-note-message
= markdown_field(note, :note)
%a{ href: "##{dom_id(note)}" }
= time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago')
%span.system-note-separator
&middot;
%a.system-note-separator{ href: "##{dom_id(note)}" }= time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago')
- unless note.system?
.note-actions
- if note.for_personal_snippet?

View File

@ -66,6 +66,6 @@
%td Last contact
%td
- if @runner.contacted_at
#{time_ago_in_words(@runner.contacted_at)} ago
= time_ago_with_tooltip @runner.contacted_at
- else
Never

View File

@ -1,5 +0,0 @@
---
title: Introduce new ProjectCiCdSetting model with group_runners_enabled
merge_request: 18144
author:
type: performance

View File

@ -1,5 +0,0 @@
---
title: Add cron job to email users on issue due date
merge_request: 17985
author: Stuart Nelson
type: added

View File

@ -0,0 +1,5 @@
---
title: Fix double-brackets being linkified in wiki markdown
merge_request: 18524
author: brewingcode
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Add API endpoint to render markdown text
merge_request: 18926
author: "@blackst0ne"
type: added

View File

@ -1,5 +0,0 @@
---
title: Improves wording in new pipeline page
merge_request:
author:
type: other

View File

@ -1,5 +0,0 @@
---
title: Improve tooltips in collapsed right sidebar
merge_request: 17714
author:
type: changed

View File

@ -1,5 +0,0 @@
---
title: Fix `joined` information on project members page
merge_request: 18290
author: Fabian Schneider
type: fixed

View File

@ -1,6 +0,0 @@
---
title: Fix template selector menu visibility when toggling preview mode in file edit
view
merge_request: 18118
author: Fabian Schneider
type: fixed

View File

@ -1,5 +0,0 @@
---
title: Use VueJS for rendering pipeline stages
merge_request:
author:
type: changed

View File

@ -1,5 +0,0 @@
---
title: Prevent pipeline actions in dropdown to redirct to a new page
merge_request:
author:
type: fixed

View File

@ -1,5 +0,0 @@
---
title: Keep current labels visible when editing them in the sidebar
merge_request:
author:
type: changed

View File

@ -1,5 +0,0 @@
---
title: Reconcile project templates with Auto DevOps
merge_request: 18737
author:
type: changed

View File

@ -1,5 +0,0 @@
---
title: Adjust issue boards list header label text color
merge_request:
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Apply NestingDepth (level 5) (pages/pipelines.scss)
merge_request: 18830
author: Takuya Noguchi
type: other

View File

@ -1,5 +0,0 @@
---
title: Add a comma to the time estimate system notes
merge_request: 18326
author:
type: changed

View File

@ -1,4 +0,0 @@
title: Replace vue resource with axios in pipelines table
merge_request:
author:
type: other

View File

@ -1,5 +0,0 @@
---
title: Improve DB performance of calculating total artifacts size
merge_request: 17839
author:
type: performance

View File

@ -1,5 +0,0 @@
---
title: Make project deploy keys table more clearly structured
merge_request: 18279
author:
type: changed

View File

@ -1,5 +0,0 @@
---
title: Refactor CSS to eliminate vertical misalignment of login nav
merge_request: 16275
author: Takuya Noguchi
type: fixed

View File

@ -1,5 +0,0 @@
---
title: 'Allow group owner to enable runners from subgroups (#41981)'
merge_request: 18009
author:
type: fixed

View File

@ -1,5 +0,0 @@
---
title: Adds push mirrors to GitLab Community Edition
merge_request: 18715
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Automatically accepts project/group invite by email after user signup
merge_request: 17634
author: Jacopo Beschi @jacopo-beschi
type: changed

View File

@ -1,5 +0,0 @@
---
title: Remove ahead/behind graphs on project branches on mobile
merge_request: 18415
author: Takuya Noguchi
type: other

View File

@ -1,5 +0,0 @@
---
title: Show new branch/mr button even when branch exists
merge_request: 17712
author: Jacopo Beschi @jacopo-beschi
type: added

View File

@ -1,5 +0,0 @@
---
title: Rubocop rule to avoid returning from a block
merge_request: 18000
author: Jacopo Beschi @jacopo-beschi
type: added

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