Commit b84cd8bd authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-11-06

# Conflicts:
#	app/assets/javascripts/reports/components/report_item.vue

[ci skip]
parents d9260cc3 d19a6f68
......@@ -31,7 +31,7 @@ class DirtySubmitForm {
updateDirtyInput(event) {
const input = event.target;
if (!input.dataset.dirtySubmitOriginalValue) return;
if (!input.dataset.isDirtySubmitInput) return;
this.updateDirtyInputs(input);
this.toggleSubmission();
......@@ -65,6 +65,7 @@ class DirtySubmitForm {
}
static initInput(element) {
element.dataset.isDirtySubmitInput = true;
element.dataset.dirtySubmitOriginalValue = DirtySubmitForm.inputCurrentValue(element);
}
......
<script>
import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
import { components, componentNames } from 'ee/vue_shared/components/reports/issue_body';
import { components, componentNames } from '~/reports/components/issue_body';
export default {
name: 'ReportItem',
......
......@@ -73,6 +73,7 @@ export default {
linkStart: `<a href="${this.troubleshootingDocsPath}">`,
linkEnd: '</a>',
},
false,
);
},
/* We typically set defaults ([]) in the store or prop declarations, but because triggered
......
......@@ -251,6 +251,10 @@ module Ci
end
end
def self.latest_successful_ids_per_project
success.group(:project_id).select('max(id) as id')
end
def self.truncate_sha(sha)
sha[0...8]
end
......
......@@ -233,6 +233,12 @@ class Namespace < ActiveRecord::Base
Project.inside_path(full_path)
end
# Includes pipelines from this namespace and pipelines from all subgroups
# that belongs to this namespace
def all_pipelines
Ci::Pipeline.where(project: all_projects)
end
def has_parent?
parent.present?
end
......
---
title: Make index.* render like README.* when it's present in a repository
merge_request: 22639
author: Jakub Jirutka
type: added
---
title: Render unescaped link for failed pipeline status
merge_request: 22807
author:
type: fixed
......@@ -23,6 +23,9 @@ one of the [Merge request coaches][team].
Depending on the areas your merge request touches, it must be **approved** by one
or more [maintainers](https://about.gitlab.com/handbook/engineering/#maintainer):
For approvals, we use the approval functionality found in the merge request
widget. Reviewers can add their approval by [approving additionally](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html#adding-or-removing-an-approval).
1. If your merge request includes backend changes [^1], it must be
**approved by a [backend maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce_maintainers_backend)**.
1. If your merge request includes frontend changes [^1], it must be
......@@ -97,6 +100,9 @@ If a developer who happens to also be a maintainer was involved in a merge reque
as a domain expert and/or reviewer, it is recommended that they are not also picked
as the maintainer to ultimately approve and merge it.
Maintainers should check before merging if the merge request is approved by the
required approvers.
## Best practices
### Everyone
......
......@@ -53,6 +53,32 @@ To get started with the command line, please read through the
Use GitLab's [file finder](../../../workflow/file_finder.md) to search for files in a repository.
### Repository README and index files
When a `README` or `index` file is present in a repository, its contents will be
automatically pre-rendered by GitLab without opening it.
They can either be plain text or have an extension of a supported markup language:
- Asciidoc: `README.adoc` or `index.adoc`
- Markdown: `README.md` or `index.md`
- reStructuredText: `README.rst` or `index.rst`
- Text: `README.txt` or `index.txt`
Some things to note about precedence:
1. When both a `README` and an `index` file are present, the `README` will always
take precedence.
1. When more than one file is present with different extensions, they are
ordered alphabetically, with the exception of a file without an extension
which will always be last in precedence. For example, `README.adoc` will take
precedence over `README.md`, and `README.rst` will take precedence over
`README`.
NOTE: **Note:**
`index` files without an extension will not automatically pre-render. You'll
have to explicitly open them to see their contents.
### Jupyter Notebook files
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/2508) in GitLab 9.1
......@@ -165,7 +191,7 @@ minutes.
![Repository Languages bar](img/repository_languages.png)
Not all files are detected, among others; documentation,
Not all files are detected, among others; documentation,
vendored code, and most markup languages are excluded. This behaviour can be
adjusted by overriding the default. For example, to enable `.proto` files to be
detected, add the following to `.gitattributes` in the root of your repository.
......
......@@ -8,7 +8,7 @@ module Gitlab
module FileDetector
PATTERNS = {
# Project files
readme: %r{\Areadme[^/]*\z}i,
readme: %r{\A(readme|index)[^/]*\z}i,
changelog: %r{\A(changelog|history|changes|news)[^/]*\z}i,
license: %r{\A((un)?licen[sc]e|copying)(\.[^/]+)?\z}i,
contributing: %r{\Acontributing[^/]*\z}i,
......
......@@ -4,10 +4,11 @@ module Gitlab
module MarkupHelper
extend self
MARKDOWN_EXTENSIONS = %w(mdown mkd mkdn md markdown).freeze
ASCIIDOC_EXTENSIONS = %w(adoc ad asciidoc).freeze
OTHER_EXTENSIONS = %w(textile rdoc org creole wiki mediawiki rst).freeze
MARKDOWN_EXTENSIONS = %w[mdown mkd mkdn md markdown].freeze
ASCIIDOC_EXTENSIONS = %w[adoc ad asciidoc].freeze
OTHER_EXTENSIONS = %w[textile rdoc org creole wiki mediawiki rst].freeze
EXTENSIONS = MARKDOWN_EXTENSIONS + ASCIIDOC_EXTENSIONS + OTHER_EXTENSIONS
PLAIN_FILENAMES = %w[readme index].freeze
# Public: Determines if a given filename is compatible with GitHub::Markup.
#
......@@ -43,7 +44,7 @@ module Gitlab
#
# Returns boolean
def plain?(filename)
extension(filename) == 'txt' || filename.casecmp('readme').zero?
extension(filename) == 'txt' || plain_filename?(filename)
end
def previewable?(filename)
......@@ -55,5 +56,9 @@ module Gitlab
def extension(filename)
File.extname(filename).downcase.delete('.')
end
def plain_filename?(filename)
PLAIN_FILENAMES.include?(filename.downcase)
end
end
end
......@@ -179,7 +179,7 @@ describe 'Merge request > User sees merge widget', :js do
# Wait for the `ci_status` and `merge_check` requests
wait_for_requests
expect(page).to have_text(%r{Could not retrieve the pipeline status\. For troubleshooting steps, read the <a href=\".+\">documentation\.</a>})
expect(page).to have_text("Could not retrieve the pipeline status. For troubleshooting steps, read the documentation.")
end
end
......
......@@ -41,8 +41,7 @@ describe 'Merge request > User sees pipelines', :js do
visit project_merge_request_path(project, merge_request)
wait_for_requests
expect(page.find('.ci-widget')).to have_text(
%r{Could not retrieve the pipeline status\. For troubleshooting steps, read the <a href=\".+\">documentation\.</a>})
expect(page.find('.ci-widget')).to have_text("Could not retrieve the pipeline status. For troubleshooting steps, read the documentation.")
end
end
......
import DirtySubmitForm from '~/dirty_submit/dirty_submit_form';
import { setInput, createForm } from './helper';
function expectToToggleDisableOnDirtyUpdate(submit, input) {
const originalValue = input.value;
expect(submit.disabled).toBe(true);
return setInput(input, `${originalValue} changes`)
.then(() => expect(submit.disabled).toBe(false))
.then(() => setInput(input, originalValue))
.then(() => expect(submit.disabled).toBe(true));
}
describe('DirtySubmitForm', () => {
it('disables submit until there are changes', done => {
const { form, input, submit } = createForm();
const originalValue = input.value;
new DirtySubmitForm(form); // eslint-disable-line no-new
expect(submit.disabled).toBe(true);
return expectToToggleDisableOnDirtyUpdate(submit, input)
.then(done)
.catch(done.fail);
});
it('disables submit until there are changes when initializing with a falsy value', done => {
const { form, input, submit } = createForm();
input.value = '';
new DirtySubmitForm(form); // eslint-disable-line no-new
return setInput(input, `${originalValue} changes`)
.then(() => {
expect(submit.disabled).toBe(false);
})
.then(() => setInput(input, originalValue))
.then(() => {
expect(submit.disabled).toBe(true);
})
return expectToToggleDisableOnDirtyUpdate(submit, input)
.then(done)
.catch(done.fail);
});
......
......@@ -74,7 +74,7 @@ describe('MRWidgetPipeline', () => {
});
expect(vm.$el.querySelector('.media-body').textContent.trim()).toContain(
'Could not retrieve the pipeline status. For troubleshooting steps, read the <a href="help">documentation.</a>',
'Could not retrieve the pipeline status. For troubleshooting steps, read the documentation.',
);
});
......
......@@ -15,7 +15,12 @@ describe Gitlab::FileDetector do
describe '.type_of' do
it 'returns the type of a README file' do
expect(described_class.type_of('README.md')).to eq(:readme)
%w[README readme INDEX index].each do |filename|
expect(described_class.type_of(filename)).to eq(:readme)
%w[.md .adoc .rst].each do |extname|
expect(described_class.type_of(filename + extname)).to eq(:readme)
end
end
end
it 'returns nil for a README file in a directory' do
......
......@@ -1157,6 +1157,19 @@ describe Ci::Pipeline, :mailer do
end
end
describe '.latest_successful_ids_per_project' do
let(:projects) { create_list(:project, 2) }
let!(:pipeline1) { create(:ci_pipeline, :success, project: projects[0]) }
let!(:pipeline2) { create(:ci_pipeline, :success, project: projects[0]) }
let!(:pipeline3) { create(:ci_pipeline, :failed, project: projects[0]) }
let!(:pipeline4) { create(:ci_pipeline, :success, project: projects[1]) }
it 'returns expected pipeline ids' do
expect(described_class.latest_successful_ids_per_project)
.to contain_exactly(pipeline2, pipeline4)
end
end
describe '.internal_sources' do
subject { described_class.internal_sources }
......
......@@ -37,8 +37,8 @@ describe Awardable do
create(:award_emoji, awardable: issue3, name: "star", user: award_emoji.user)
create(:award_emoji, awardable: issue3, name: "star", user: award_emoji2.user)
expect(Issue.awarded(award_emoji.user)).to eq [issue, issue3]
expect(Issue.awarded(award_emoji2.user)).to eq [issue2, issue3]
expect(Issue.awarded(award_emoji.user)).to contain_exactly(issue, issue3)
expect(Issue.awarded(award_emoji2.user)).to contain_exactly(issue2, issue3)
end
end
......
......@@ -574,6 +574,17 @@ describe Namespace do
it { expect(group.all_projects.to_a).to match_array([project2, project1]) }
end
describe '#all_pipelines' do
let(:group) { create(:group) }
let(:child) { create(:group, parent: group) }
let!(:project1) { create(:project_empty_repo, namespace: group) }
let!(:project2) { create(:project_empty_repo, namespace: child) }
let!(:pipeline1) { create(:ci_empty_pipeline, project: project1) }
let!(:pipeline2) { create(:ci_empty_pipeline, project: project2) }
it { expect(group.all_pipelines.to_a).to match_array([pipeline1, pipeline2]) }
end
describe '#share_with_group_lock with subgroups', :nested_groups do
context 'when creating a subgroup' do
let(:subgroup) { create(:group, parent: root_group )}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment