Skip to content
Snippets Groups Projects
Commit 66d42037 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent a496f41f
No related branches found
No related tags found
No related merge requests found
Showing
with 352 additions and 285 deletions
Loading
Loading
@@ -44,13 +44,15 @@ docs lint:
- .default-tags
- .default-retry
- .docs:rules:docs-lint
image: "registry.gitlab.com/gitlab-org/gitlab-docs:docs-lint"
image: "registry.gitlab.com/gitlab-org/gitlab-docs:lint"
stage: test
needs: []
script:
- scripts/lint-doc.sh
# Lint Markdown
- markdownlint --config .markdownlint.json 'doc/**/*.md'
# Lint content (error-level text-scoped rules only)
- vale --minAlertLevel error --ignore-syntax doc
# Prepare docs for build
- mv doc/ /tmp/gitlab-docs/content/$DOCS_GITLAB_REPO_SUFFIX
- cd /tmp/gitlab-docs
Loading
Loading
Loading
Loading
@@ -207,11 +207,11 @@ karma-as-if-foss:
extends: .frontend-job-base
script:
- date
- yarn jest --ci --coverage
- yarn jest --ci --coverage --testSequencer ./scripts/frontend/parallel_ci_sequencer.js
cache:
key: jest
paths:
- tmp/jest/jest/
- tmp/cache/jest/
policy: pull-push
 
jest:
Loading
Loading
@@ -229,6 +229,7 @@ jest:
- tmp/tests/frontend/
reports:
junit: junit_jest.xml
parallel: 2
 
jest-as-if-foss:
extends:
Loading
Loading
@@ -239,6 +240,26 @@ jest-as-if-foss:
cache:
policy: pull
 
coverage-frontend:
extends:
- .default-tags
- .default-retry
- .frontend:rules:default-frontend-jobs
needs: ["jest"]
stage: post-test
before_script:
- yarn install --frozen-lockfile --cache-folder .yarn-cache --prefer-offline
script:
- yarn node scripts/frontend/merge_coverage_frontend.js
artifacts:
name: coverage-frontend
expire_in: 31d
paths:
- coverage-frontend/
cache:
paths:
- .yarn-cache/
.qa-frontend-node:
extends:
- .default-tags
Loading
Loading
Loading
Loading
@@ -123,5 +123,6 @@
"YouTrack"
],
"code_blocks": false
}
},
"code-fence-style": false
}
<script>
import _ from 'underscore';
import { GlIcon } from '@gitlab/ui';
import { GlIcon, GlButton } from '@gitlab/ui';
import successSvg from 'icons/_icon_status_success.svg';
import warningSvg from 'icons/_icon_status_warning.svg';
import readyToMergeMixin from 'ee_else_ce/vue_merge_request_widget/mixins/ready_to_merge';
Loading
Loading
@@ -26,6 +26,7 @@ export default {
CommitEdit,
CommitMessageDropdown,
GlIcon,
GlButton,
MergeImmediatelyConfirmationDialog: () =>
import(
'ee_component/vue_merge_request_widget/components/merge_immediately_confirmation_dialog.vue'
Loading
Loading
@@ -67,18 +68,13 @@ export default {
 
return 'success';
},
mergeButtonClass() {
const defaultClass = 'btn btn-sm btn-success accept-merge-request';
const failedClass = `${defaultClass} btn-danger`;
const inActionClass = `${defaultClass} btn-info`;
mergeButtonVariant() {
if (this.status === 'failed') {
return failedClass;
return 'danger';
} else if (this.status === 'pending') {
return inActionClass;
return 'info';
}
return defaultClass;
return 'success';
},
iconClass() {
if (
Loading
Loading
@@ -267,16 +263,16 @@ export default {
<div class="media-body">
<div class="mr-widget-body-controls media space-children">
<span class="btn-group">
<button
<gl-button
size="sm"
class="qa-merge-button accept-merge-request"
:variant="mergeButtonVariant"
:disabled="isMergeButtonDisabled"
:class="mergeButtonClass"
type="button"
class="qa-merge-button"
:loading="isMakingRequest"
@click="handleMergeButtonClick(isAutoMergeAvailable)"
>
<i v-if="isMakingRequest" class="fa fa-spinner fa-spin" aria-hidden="true"></i>
{{ mergeButtonText }}
</button>
</gl-button>
<button
v-if="shouldShowMergeImmediatelyDropdown"
:disabled="isMergeButtonDisabled"
Loading
Loading
<script>
import $ from 'jquery';
import { __ } from '~/locale';
import { GlButton } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import createFlash from '~/flash';
import statusIcon from '../mr_widget_status_icon.vue';
import StatusIcon from '../mr_widget_status_icon.vue';
import tooltip from '../../../vue_shared/directives/tooltip';
import eventHub from '../../event_hub';
 
export default {
name: 'WorkInProgress',
components: {
statusIcon,
StatusIcon,
GlButton,
},
directives: {
tooltip,
Loading
Loading
@@ -23,8 +25,15 @@ export default {
isMakingRequest: false,
};
},
computed: {
wipInfoTooltip() {
return s__(
'mrWidget|When this merge request is ready, remove the WIP: prefix from the title to allow it to be merged',
);
},
},
methods: {
removeWIP() {
handleRemoveWIP() {
this.isMakingRequest = true;
this.service
.removeWIP()
Loading
Loading
@@ -52,29 +61,22 @@ export default {
<i
v-tooltip
class="fa fa-question-circle"
:title="
s__(
'mrWidget|When this merge request is ready, remove the WIP: prefix from the title to allow it to be merged',
)
"
:aria-label="
s__(
'mrWidget|When this merge request is ready, remove the WIP: prefix from the title to allow it to be merged',
)
"
:title="wipInfoTooltip"
:aria-label="wipInfoTooltip"
>
</i>
</span>
<button
<gl-button
v-if="mr.removeWIPPath"
size="sm"
variant="default"
:disabled="isMakingRequest"
type="button"
class="btn btn-default btn-sm js-remove-wip"
@click="removeWIP"
:loading="isMakingRequest"
class="js-remove-wip"
@click="handleRemoveWIP"
>
<i v-if="isMakingRequest" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
{{ s__('mrWidget|Resolve WIP status') }}
</button>
</gl-button>
</div>
</div>
</template>
Loading
Loading
@@ -28,6 +28,10 @@ module Resolvers
end
end
 
def self.complexity
0
end
def self.resolver_complexity(args, child_complexity:)
complexity = 1
complexity += 1 if args[:sort]
Loading
Loading
Loading
Loading
@@ -9,7 +9,7 @@ module Types
def initialize(*args, **kwargs, &block)
@calls_gitaly = !!kwargs.delete(:calls_gitaly)
@constant_complexity = !!kwargs[:complexity]
kwargs[:complexity] ||= field_complexity(kwargs[:resolver_class])
kwargs[:complexity] = field_complexity(kwargs[:resolver_class], kwargs[:complexity])
@feature_flag = kwargs[:feature_flag]
kwargs = check_feature_flag(kwargs)
 
Loading
Loading
@@ -51,7 +51,9 @@ module Types
args
end
 
def field_complexity(resolver_class)
def field_complexity(resolver_class, current)
return current if current.present? && current > 0
if resolver_class
field_resolver_complexity
else
Loading
Loading
@@ -66,22 +68,30 @@ module Types
# proc because we set complexity depending on arguments and number of
# items which can be loaded.
proc do |ctx, args, child_complexity|
next base_complexity unless resolver_complexity_enabled?(ctx)
# Resolvers may add extra complexity depending on used arguments
complexity = child_complexity + self.resolver&.try(:resolver_complexity, args, child_complexity: child_complexity).to_i
complexity += 1 if calls_gitaly?
field_defn = to_graphql
if field_defn.connection?
# Resolvers may add extra complexity depending on number of items being loaded.
page_size = field_defn.connection_max_page_size || ctx.schema.default_max_page_size
limit_value = [args[:first], args[:last], page_size].compact.min
multiplier = self.resolver&.try(:complexity_multiplier, args).to_f
complexity += complexity * limit_value * multiplier
end
complexity += complexity * connection_complexity_multiplier(ctx, args)
 
complexity.to_i
end
end
def resolver_complexity_enabled?(ctx)
ctx.fetch(:graphql_resolver_complexity_flag) { |key| ctx[key] = Feature.enabled?(:graphql_resolver_complexity) }
end
def connection_complexity_multiplier(ctx, args)
# Resolvers may add extra complexity depending on number of items being loaded.
field_defn = to_graphql
return 0 unless field_defn.connection?
page_size = field_defn.connection_max_page_size || ctx.schema.default_max_page_size
limit_value = [args[:first], args[:last], page_size].compact.min
multiplier = self.resolver&.try(:complexity_multiplier, args).to_f
limit_value * multiplier
end
end
end
Loading
Loading
@@ -16,7 +16,7 @@ module Spammable
attr_accessor :spam_log
alias_method :spam?, :spam
 
after_validation :check_for_spam, on: [:create, :update]
after_validation :invalidate_if_spam, on: [:create, :update]
 
cattr_accessor :spammable_attrs, instance_accessor: false do
[]
Loading
Loading
@@ -37,7 +37,7 @@ module Spammable
end
end
 
def check_for_spam
def invalidate_if_spam
error_msg = if Gitlab::Recaptcha.enabled?
"Your #{spammable_entity_type} has been recognized as spam. "\
"Please, change the content or solve the reCAPTCHA to proceed."
Loading
Loading
---
title: Update iOS (Swift) project template logo
merge_request: 25049
author:
type: changed
require 'gitlab/testing/request_blocker_middleware'
require 'gitlab/testing/request_inspector_middleware'
require 'gitlab/testing/clear_thread_memory_cache_middleware'
 
Rails.application.configure do
# Make sure the middleware is inserted first in middleware chain
config.middleware.insert_before(ActionDispatch::Static, Gitlab::Testing::RequestBlockerMiddleware)
config.middleware.insert_before(ActionDispatch::Static, Gitlab::Testing::RequestInspectorMiddleware)
config.middleware.insert_before(ActionDispatch::Static, Gitlab::Testing::ClearThreadMemoryCacheMiddleware)
 
# Settings specified here will take precedence over those in config/application.rb
 
Loading
Loading
Loading
Loading
@@ -75,7 +75,7 @@ must disable the **primary** node.
single recommendation. You may need to:
 
- Reconfigure the load balancers.
- Change DNS records (e.g., point the primary DNS record to the **secondary**
- Change DNS records (for example, point the primary DNS record to the **secondary**
node in order to stop usage of the **primary** node).
- Stop the virtual servers.
- Block traffic through a firewall.
Loading
Loading
Loading
Loading
@@ -337,8 +337,8 @@ How this feature will work:
### Be careful with sensitive information
 
With some [Runner Executors](https://docs.gitlab.com/runner/executors/README.html),
if you can run a job on the Runner, you can get access to any code it runs
and get the token of the Runner. With shared Runners, this means that anyone
if you can run a job on the Runner, you can get full access to the file system,
and thus any code it runs as well as the token of the Runner. With shared Runners, this means that anyone
that runs jobs on the Runner, can access anyone else's code that runs on the
Runner.
 
Loading
Loading
Loading
Loading
@@ -825,10 +825,8 @@ This could result in some unexpected behavior, including:
 
Available rule clauses include:
 
- [`if`](#rulesif)
(similar to [`only:variables`](#onlyvariablesexceptvariables)).
- [`changes`](#ruleschanges)
(same as [`only:changes`](#onlychangesexceptchanges)).
- [`if`](#rulesif) (similar to [`only:variables`](#onlyvariablesexceptvariables))
- [`changes`](#ruleschanges) (same as [`only:changes`](#onlychangesexceptchanges))
- [`exists`](#rulesexists)
 
For example, using `if`. This configuration specifies that `job` should be built
Loading
Loading
@@ -895,7 +893,6 @@ docker build:
- if: '$VAR == "string value"'
when: manual # Will include the job and set to when:manual if the expression evaluates to true, after the `changes:` rule fails to match.
- when: on_success # If neither of the first rules match, set to on_success
```
 
In this example, a job either set to:
Loading
Loading
@@ -956,6 +953,47 @@ job:
 
In this example, if the first rule matches, then the job will have `when: manual` and `allow_failure: true`.
 
#### Exclude jobs with `rules:` from certain pipelines
Jobs with `rules:` can cause two pipelines to be created unexpectedly:
- One pipeline from pushing a commit to a branch.
- A second ["detached" pipeline for a merge request](../merge_request_pipelines/index.md).
`only` and `except` jobs do not trigger merge request pipelines by default, but this
is not the case for jobs with `rules:`, which may be surprising if migrating from `only`
and `except` to `rules:`.
If you are using `rules:` and you see two pipelines for commits to branches that have
a merge request, you have two options:
- Individually exclude each job that uses `rules:` from merge request pipelines. The
example below will cause the job to **not** run in *pipelines for merge requests*,
but it **will** run in pipelines for *new tags and pipelines running on branch refs*:
```yaml
job:
rules:
- if: $CI_MERGE_REQUEST_ID
when: never
- when: manual
script:
- echo hello
```
- Add a global [`workflow: rules`](#workflowrules) to allow pipelines in only certain
situations. The example below will only run pipelines for merge requests, new tags and
changes to master. It will **not** run any pipelines *on any branch except master*, but
it will run **detached merge request pipelines** for any merge request, targeting any branch:
```yaml
workflow:
rules:
- if: $CI_MERGE_REQUEST_ID
- if: $CI_COMMIT_TAG
- if: $CI_COMMIT_BRANCH == "master"
```
#### Complex rule clauses
 
To conjoin `if`, `changes`, and `exists` clauses with an AND, use them in the
Loading
Loading
Loading
Loading
@@ -146,6 +146,7 @@ graph RL;
U2["frontend-fixtures-as-if-foss<br/>(EE default refs only)"];
V["webpack-dev-server, static-analysis"];
M[coverage];
O[coverage-frontend];
N["pages (master only)"];
Q[package-and-qa];
S["RSpec<br/>(e.g. rspec unit pg9)"]
Loading
Loading
@@ -190,6 +191,7 @@ subgraph "`test` stage"
 
subgraph "`post-test` stage"
M --> |happens after| S
O --> |needs `jest`| I
end
 
subgraph "`review-prepare` stage"
Loading
Loading
This diff is collapsed.
Loading
Loading
@@ -41,7 +41,7 @@ Please note that for the deactivation option to be visible to an admin, the user
Users can also be deactivated using the [GitLab API](../../api/users.md#deactivate-user).
 
NOTE: **Note:**
A deactivated user does not consume a [seat](../../subscriptions/index.md#managing-subscriptions).
A deactivated user does not consume a [seat](../../subscriptions/index.md#choosing-the-number-of-users).
 
## Activating a user
 
Loading
Loading
@@ -60,7 +60,7 @@ Users can also be activated using the [GitLab API](../../api/users.md#activate-u
 
NOTE: **Note:**
Activating a user will change the user's state to active and it consumes a
[seat](../../subscriptions/index.md#managing-subscriptions).
[seat](../../subscriptions/index.md#choosing-the-number-of-users).
 
TIP: **Tip:**
A deactivated user can also activate their account by themselves by simply logging back via the UI.
Loading
Loading
@@ -30,7 +30,7 @@ Personal projects, and group and user history of the blocked user will be left i
Users can also be blocked using the [GitLab API](../../api/users.md#block-user).
 
NOTE: **Note:**
A blocked user does not consume a [seat](../../subscriptions/index.md#managing-subscriptions).
A blocked user does not consume a [seat](../../subscriptions/index.md#choosing-the-number-of-users).
 
## Unblocking a user
 
Loading
Loading
@@ -45,4 +45,4 @@ Users can also be unblocked using the [GitLab API](../../api/users.md#unblock-us
 
NOTE: **Note:**
Unblocking a user will change the user's state to active and it consumes a
[seat](../../subscriptions/index.md#managing-subscriptions).
[seat](../../subscriptions/index.md#choosing-the-number-of-users).
Loading
Loading
@@ -117,7 +117,7 @@ service included with GitLab that coordinates the jobs.
 
If the project is on GitLab.com, shared Runners are available
(the first 2000 minutes are free, you can
[buy more later](../../subscriptions/index.md#extra-shared-runners-pipeline-minutes))
[buy more later](../../subscriptions/index.md#purchasing-additional-ci-minutes))
and you do not have to deploy one if they are enough for your needs. If a
project-specific Runner is desired, or there are no shared Runners, it is easy
to deploy one.
Loading
Loading
Loading
Loading
@@ -104,7 +104,7 @@ Linux Shared Runners on GitLab.com run in [autoscale mode] and are powered by Go
Autoscaling means reduced waiting times to spin up CI/CD jobs, and isolated VMs for each project,
thus maximizing security. They're free to use for public open source projects and limited
to 2000 CI minutes per month per group for private projects. More minutes
[can be purchased](../../subscriptions/index.md#extra-shared-runners-pipeline-minutes), if
[can be purchased](../../subscriptions/index.md#purchasing-additional-ci-minutes), if
needed. Read about all [GitLab.com plans](https://about.gitlab.com/pricing/).
 
All your CI/CD jobs run on [n1-standard-1 instances](https://cloud.google.com/compute/docs/machine-types) with 3.75GB of RAM, CoreOS and the latest Docker Engine
Loading
Loading
Loading
Loading
@@ -55,6 +55,14 @@ if (IS_EE) {
collectCoverageFrom.push(rootDirEE.replace('$1', '/**/*.{js,vue}'));
}
 
const coverageDirectory = () => {
if (process.env.CI_NODE_INDEX && process.env.CI_NODE_TOTAL) {
return `<rootDir>/coverage-frontend/jest-${process.env.CI_NODE_INDEX}-${process.env.CI_NODE_TOTAL}`;
}
return '<rootDir>/coverage-frontend/';
};
// eslint-disable-next-line import/no-commonjs
module.exports = {
clearMocks: true,
Loading
Loading
@@ -62,7 +70,7 @@ module.exports = {
moduleFileExtensions: ['js', 'json', 'vue'],
moduleNameMapper,
collectCoverageFrom,
coverageDirectory: '<rootDir>/coverage-frontend/',
coverageDirectory: coverageDirectory(),
coverageReporters: ['json', 'lcov', 'text-summary', 'clover'],
cacheDirectory: '<rootDir>/tmp/cache/jest',
modulePathIgnorePatterns: ['<rootDir>/.yarn-cache/'],
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment