diff options
11 files changed, 235 insertions, 113 deletions
diff --git a/.vale.ini b/.vale.ini new file mode 100644 index 00000000000..25353f97023 --- /dev/null +++ b/.vale.ini @@ -0,0 +1,49 @@ +# Vale configuration file, taken from https://errata-ai.github.io/vale/config/ + +# The relative path to the folder containing linting rules (styles) +# ----------------------------------------------------------------- +StylesPath = doc/.linting/vale/styles + +# Minimum alert level +# ------------------- +# The minimum alert level to display (suggestion, warning, or error). +# If integrated into CI, builds fail by default on error-level alerts, +# unless you execute Vale with the --no-exit flag +MinAlertLevel = suggestion + +# Should Vale parse any file formats other than .md files as Markdown? +# -------------------------------------------------------------------- +[formats] +mdx = md + +# What file types should Vale test? +# ---------------------------------- +[*.md] + +# Styles to load +# -------------- +# What styles, located in the StylesPath folder, should Vale load? +# Vale also currently includes write-good, proselint, joblint, and vale +BasedOnStyles = gitlab + +# Enabling or disabling specific rules in a style +# ----------------------------------------------- +# To disable a rule in an enabled style, use the following format: +# {style}.{filename} = NO +# To enable a single rule in a disabled style, use the following format: +# vale.Editorializing = YES + +# Altering the severity of a rule in a style +# ------------------------------------------ +# To change the reporting level (suggestion, warning, error) of a rule, +# use the following format: {style}.{filename} = {level} +# vale.Hedging = error + +# Syntax-specific settings +# ------------------------ +# You can configure specific tests to be enabled, disabled, or report at a +# different level for specific file types. File-type-specific settings added +# here will overwrite any conflicting global settings. +[*.{md,txt}] +# vale.Editorializing = NO + diff --git a/app/assets/javascripts/manual_ordering.js b/app/assets/javascripts/manual_ordering.js index f93dbcd4c47..683fe8b0b14 100644 --- a/app/assets/javascripts/manual_ordering.js +++ b/app/assets/javascripts/manual_ordering.js @@ -29,6 +29,7 @@ const initManualOrdering = (draggableSelector = 'li.issue') => { issueList, getBoardSortableDefaultOptions({ scroll: true, + fallbackTolerance: 1, dataIdAttr: 'data-id', fallbackOnBody: false, group: { diff --git a/app/assets/javascripts/monitoring/components/dashboard.vue b/app/assets/javascripts/monitoring/components/dashboard.vue index 14f39c50a2d..9b9c380c9af 100644 --- a/app/assets/javascripts/monitoring/components/dashboard.vue +++ b/app/assets/javascripts/monitoring/components/dashboard.vue @@ -69,6 +69,11 @@ export default { required: false, default: true, }, + showHeader: { + type: Boolean, + required: false, + default: true, + }, showPanels: { type: Boolean, required: false, @@ -129,7 +134,8 @@ export default { }, environmentsEndpoint: { type: String, - required: true, + required: false, + default: '', }, currentEnvironmentName: { type: String, @@ -356,86 +362,88 @@ export default { <template> <div class="prometheus-graphs"> - <div class="prometheus-graphs-header gl-p-3 pb-0 border-bottom bg-gray-light"> + <div + v-if="showHeader" + ref="prometheusGraphsHeader" + class="prometheus-graphs-header gl-p-3 pb-0 border-bottom bg-gray-light" + > <div class="row"> - <template v-if="environmentsEndpoint"> - <gl-form-group - :label="__('Dashboard')" - label-size="sm" - label-for="monitor-dashboards-dropdown" - class="col-sm-12 col-md-6 col-lg-2" - > - <dashboards-dropdown - id="monitor-dashboards-dropdown" - class="mb-0 d-flex" - toggle-class="dropdown-menu-toggle" - :default-branch="defaultBranch" - :selected-dashboard="selectedDashboard" - @selectDashboard="selectDashboard($event)" - /> - </gl-form-group> + <gl-form-group + :label="__('Dashboard')" + label-size="sm" + label-for="monitor-dashboards-dropdown" + class="col-sm-12 col-md-6 col-lg-2" + > + <dashboards-dropdown + id="monitor-dashboards-dropdown" + class="mb-0 d-flex" + toggle-class="dropdown-menu-toggle" + :default-branch="defaultBranch" + :selected-dashboard="selectedDashboard" + @selectDashboard="selectDashboard($event)" + /> + </gl-form-group> - <gl-form-group - :label="s__('Metrics|Environment')" - label-size="sm" - label-for="monitor-environments-dropdown" - class="col-sm-6 col-md-6 col-lg-2" + <gl-form-group + :label="s__('Metrics|Environment')" + label-size="sm" + label-for="monitor-environments-dropdown" + class="col-sm-6 col-md-6 col-lg-2" + > + <gl-dropdown + id="monitor-environments-dropdown" + ref="monitorEnvironmentsDropdown" + data-qa-selector="environments_dropdown" + class="mb-0 d-flex" + toggle-class="dropdown-menu-toggle" + menu-class="monitor-environment-dropdown-menu" + :text="currentEnvironmentName" + :disabled="filteredEnvironments.length === 0" > - <gl-dropdown - id="monitor-environments-dropdown" - ref="monitorEnvironmentsDropdown" - data-qa-selector="environments_dropdown" - class="mb-0 d-flex" - toggle-class="dropdown-menu-toggle" - menu-class="monitor-environment-dropdown-menu" - :text="currentEnvironmentName" - :disabled="filteredEnvironments.length === 0" - > - <div class="d-flex flex-column overflow-hidden"> - <gl-search-box-by-type - v-if="shouldRenderSearchableEnvironmentsDropdown" - ref="monitorEnvironmentsDropdownSearch" - class="m-2" - @input="debouncedEnvironmentsSearch" - /> - <div class="flex-fill overflow-auto"> - <gl-dropdown-item - v-for="environment in filteredEnvironments" - :key="environment.id" - :active="environment.name === currentEnvironmentName" - active-class="is-active" - :href="environment.metrics_path" - >{{ environment.name }}</gl-dropdown-item - > - </div> - <div - v-if="shouldRenderSearchableEnvironmentsDropdown" - v-show="filteredEnvironments.length === 0" - ref="monitorEnvironmentsDropdownMsg" - class="text-secondary no-matches-message" + <div class="d-flex flex-column overflow-hidden"> + <gl-search-box-by-type + v-if="shouldRenderSearchableEnvironmentsDropdown" + ref="monitorEnvironmentsDropdownSearch" + class="m-2" + @input="debouncedEnvironmentsSearch" + /> + <div class="flex-fill overflow-auto"> + <gl-dropdown-item + v-for="environment in filteredEnvironments" + :key="environment.id" + :active="environment.name === currentEnvironmentName" + active-class="is-active" + :href="environment.metrics_path" + >{{ environment.name }}</gl-dropdown-item > - {{ s__('No matching results') }} - </div> </div> - </gl-dropdown> - </gl-form-group> + <div + v-if="shouldRenderSearchableEnvironmentsDropdown" + v-show="filteredEnvironments.length === 0" + ref="monitorEnvironmentsDropdownMsg" + class="text-secondary no-matches-message" + > + {{ s__('No matching results') }} + </div> + </div> + </gl-dropdown> + </gl-form-group> - <gl-form-group - :label="s__('Metrics|Show last')" - label-size="sm" - label-for="monitor-time-window-dropdown" - class="col-sm-6 col-md-6 col-lg-4" - > - <date-time-picker - ref="dateTimePicker" - :start="startDate" - :end="endDate" - :time-windows="datePickerTimeWindows" - @apply="onDateTimePickerApply" - @invalid="onDateTimePickerInvalid" - /> - </gl-form-group> - </template> + <gl-form-group + :label="s__('Metrics|Show last')" + label-size="sm" + label-for="monitor-time-window-dropdown" + class="col-sm-6 col-md-6 col-lg-4" + > + <date-time-picker + ref="dateTimePicker" + :start="startDate" + :end="endDate" + :time-windows="datePickerTimeWindows" + @apply="onDateTimePickerApply" + @invalid="onDateTimePickerInvalid" + /> + </gl-form-group> <gl-form-group v-if="hasHeaderButtons" diff --git a/app/views/notify/links/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/notify/links/projects/generic_commit_statuses/_generic_commit_status.html.haml new file mode 100644 index 00000000000..b6563b185b3 --- /dev/null +++ b/app/views/notify/links/projects/generic_commit_statuses/_generic_commit_status.html.haml @@ -0,0 +1 @@ += build.name diff --git a/app/views/notify/links/projects/generic_commit_statuses/_generic_commit_status.text.erb b/app/views/notify/links/projects/generic_commit_statuses/_generic_commit_status.text.erb new file mode 100644 index 00000000000..af8924bad57 --- /dev/null +++ b/app/views/notify/links/projects/generic_commit_statuses/_generic_commit_status.text.erb @@ -0,0 +1 @@ +Job #<%= build.id %> diff --git a/changelogs/unreleased/198621-actionview-template-error-missing-partial-notify-links-projects-ge.yml b/changelogs/unreleased/198621-actionview-template-error-missing-partial-notify-links-projects-ge.yml new file mode 100644 index 00000000000..c99267c1449 --- /dev/null +++ b/changelogs/unreleased/198621-actionview-template-error-missing-partial-notify-links-projects-ge.yml @@ -0,0 +1,6 @@ +--- +title: Fix Pipeline failed notification email not being delivered if the failed job + is a bridge job +merge_request: 23668 +author: +type: fixed diff --git a/doc/.linting/vale/styles/gitlab/OxfordComma.yml b/doc/.linting/vale/styles/gitlab/OxfordComma.yml new file mode 100644 index 00000000000..76a8d5c3f3e --- /dev/null +++ b/doc/.linting/vale/styles/gitlab/OxfordComma.yml @@ -0,0 +1,6 @@ +extends: existence +message: Use a comma before the last "and" in a list of three or more items. +link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#punctuation +level: warning +tokens: + - '(?:[^,]+,){1,}\s\w+\sand' diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md index acba09986fb..34cf50f61d9 100644 --- a/doc/development/documentation/index.md +++ b/doc/development/documentation/index.md @@ -420,6 +420,7 @@ The following are some suggested linters you can install locally and sample conf - [`proselint`](#proselint) - [markdownlint](#markdownlint), which is the same as the test run in [`docs-lint`](#testing) +- [Vale](#vale), for English language grammar and syntax suggestions NOTE: **Note:** This list does not limit what other linters you can add to your local documentation writing toolchain. @@ -519,6 +520,23 @@ also check [the issue](https://gitlab.com/gitlab-org/gitlab-foss/issues/64352) t tracked the changes required to implement these rules, and details which rules were on or off when markdownlint was enabled on the docs. +#### `Vale` + +[Vale](https://errata-ai.github.io/vale/) is a grammar, style, and word usage linter +for the English language. Vale's configuration is stored in the +[`.vale.ini`](https://gitlab.com/gitlab-org/gitlab/blob/master/.vale.ini) file +located in the root directory of the [GitLab repository](https://gitlab.com/gitlab-org/gitlab). + +Vale supports creating [custom tests](https://errata-ai.github.io/vale/styles/), +stored in the `doc/.linting/vale/styles/gitlab` directory, that extend any of +several types of checks. + +To view linting suggestions locally, you must install Vale on your own machine, and +[configure the text editor of your choice](https://errata-ai.github.io/vale/#local-use-by-a-single-writer) +to display the results. + +Vale's test results are not currently displayed in CI, but may be displayed in the future. + ## Danger Bot GitLab uses [Danger](https://github.com/danger/danger) for some elements in diff --git a/spec/frontend/monitoring/components/dashboard_spec.js b/spec/frontend/monitoring/components/dashboard_spec.js index c2cd6deb502..1fd30757937 100644 --- a/spec/frontend/monitoring/components/dashboard_spec.js +++ b/spec/frontend/monitoring/components/dashboard_spec.js @@ -412,13 +412,17 @@ describe('Dashboard', () => { describe('cluster health', () => { beforeEach(done => { mock.onGet(propsData.metricsEndpoint).reply(statusCodes.OK, JSON.stringify({})); - createShallowWrapper({ hasMetrics: true }); + createShallowWrapper({ hasMetrics: true, showHeader: false }); // all_dashboards is not defined in health dashboards wrapper.vm.$store.commit(`monitoringDashboard/${types.SET_ALL_DASHBOARDS}`, undefined); wrapper.vm.$nextTick(done); }); + it('hides dashboard header by default', () => { + expect(wrapper.find({ ref: 'prometheusGraphsHeader' }).exists()).toEqual(false); + }); + it('renders correctly', () => { expect(wrapper.isVueInstance()).toBe(true); expect(wrapper.exists()).toBe(true); diff --git a/spec/views/notify/pipeline_failed_email.html.haml_spec.rb b/spec/views/notify/pipeline_failed_email.html.haml_spec.rb index b821b015c97..a540a53c91d 100644 --- a/spec/views/notify/pipeline_failed_email.html.haml_spec.rb +++ b/spec/views/notify/pipeline_failed_email.html.haml_spec.rb @@ -15,7 +15,7 @@ describe 'notify/pipeline_failed_email.html.haml' do user: user, ref: project.default_branch, sha: project.commit.sha, - status: :success) + status: :failed) end before do @@ -24,35 +24,51 @@ describe 'notify/pipeline_failed_email.html.haml' do assign(:merge_request, merge_request) end - context 'pipeline with user' do - it 'renders the email correctly' do - render + shared_examples_for 'renders the pipeline failed email correctly' do + context 'pipeline with user' do + it 'renders the email correctly' do + render - expect(rendered).to have_content "Your pipeline has failed" - expect(rendered).to have_content pipeline.project.name - expect(rendered).to have_content pipeline.git_commit_message.truncate(50).gsub(/\s+/, ' ') - expect(rendered).to have_content pipeline.commit.author_name - expect(rendered).to have_content "##{pipeline.id}" - expect(rendered).to have_content pipeline.user.name + expect(rendered).to have_content "Your pipeline has failed" + expect(rendered).to have_content pipeline.project.name + expect(rendered).to have_content pipeline.git_commit_message.truncate(50).gsub(/\s+/, ' ') + expect(rendered).to have_content pipeline.commit.author_name + expect(rendered).to have_content "##{pipeline.id}" + expect(rendered).to have_content pipeline.user.name + expect(rendered).to have_content build.name + end + + it_behaves_like 'correct pipeline information for pipelines for merge requests' end - it_behaves_like 'correct pipeline information for pipelines for merge requests' - end + context 'pipeline without user' do + before do + pipeline.update_attribute(:user, nil) + end - context 'pipeline without user' do - before do - pipeline.update_attribute(:user, nil) + it 'renders the email correctly' do + render + + expect(rendered).to have_content "Your pipeline has failed" + expect(rendered).to have_content pipeline.project.name + expect(rendered).to have_content pipeline.git_commit_message.truncate(50).gsub(/\s+/, ' ') + expect(rendered).to have_content pipeline.commit.author_name + expect(rendered).to have_content "##{pipeline.id}" + expect(rendered).to have_content "by API" + expect(rendered).to have_content build.name + end end + end - it 'renders the email correctly' do - render + context 'when the pipeline contains a failed job' do + let!(:build) { create(:ci_build, :failed, pipeline: pipeline, project: pipeline.project) } - expect(rendered).to have_content "Your pipeline has failed" - expect(rendered).to have_content pipeline.project.name - expect(rendered).to have_content pipeline.git_commit_message.truncate(50).gsub(/\s+/, ' ') - expect(rendered).to have_content pipeline.commit.author_name - expect(rendered).to have_content "##{pipeline.id}" - expect(rendered).to have_content "by API" - end + it_behaves_like 'renders the pipeline failed email correctly' + end + + context 'when the latest failed job is a bridge job' do + let!(:build) { create(:ci_bridge, status: :failed, pipeline: pipeline, project: pipeline.project) } + + it_behaves_like 'renders the pipeline failed email correctly' end end diff --git a/spec/views/notify/pipeline_failed_email.text.erb_spec.rb b/spec/views/notify/pipeline_failed_email.text.erb_spec.rb index d15969acf83..9a4cea408a6 100644 --- a/spec/views/notify/pipeline_failed_email.text.erb_spec.rb +++ b/spec/views/notify/pipeline_failed_email.text.erb_spec.rb @@ -23,19 +23,31 @@ describe 'notify/pipeline_failed_email.text.erb' do assign(:merge_request, merge_request) end - it 'renders the email correctly' do - job = create(:ci_build, :failed, pipeline: pipeline, project: pipeline.project) - - render - - expect(rendered).to have_content('Your pipeline has failed') - expect(rendered).to have_content(pipeline.project.name) - expect(rendered).to have_content(pipeline.git_commit_message.truncate(50).gsub(/\s+/, ' ')) - expect(rendered).to have_content(pipeline.commit.author_name) - expect(rendered).to have_content("##{pipeline.id}") - expect(rendered).to have_content(pipeline.user.name) - expect(rendered).to have_content("/-/jobs/#{job.id}/raw") + shared_examples_for 'renders the pipeline failed email correctly' do + it 'renders the email correctly' do + render + + expect(rendered).to have_content('Your pipeline has failed') + expect(rendered).to have_content(pipeline.project.name) + expect(rendered).to have_content(pipeline.git_commit_message.truncate(50).gsub(/\s+/, ' ')) + expect(rendered).to have_content(pipeline.commit.author_name) + expect(rendered).to have_content("##{pipeline.id}") + expect(rendered).to have_content(pipeline.user.name) + expect(rendered).to have_content(build.id) + end + + it_behaves_like 'correct pipeline information for pipelines for merge requests' end - it_behaves_like 'correct pipeline information for pipelines for merge requests' + context 'when the pipeline contains a failed job' do + let!(:build) { create(:ci_build, :failed, pipeline: pipeline, project: pipeline.project) } + + it_behaves_like 'renders the pipeline failed email correctly' + end + + context 'when the latest failed job is a bridge job' do + let!(:build) { create(:ci_bridge, status: :failed, pipeline: pipeline, project: pipeline.project) } + + it_behaves_like 'renders the pipeline failed email correctly' + end end |