Commit 8320f795 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 45482d5a
......@@ -17,8 +17,7 @@ variables:
GIT_DEPTH: "20"
GIT_SUBMODULE_STRATEGY: "none"
GET_SOURCES_ATTEMPTS: "3"
KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/${CI_PROJECT_NAME}/rspec_report-master.json
EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/${CI_PROJECT_NAME}/rspec_report-master-ee.json
KNAPSACK_RSPEC_SUITE_REPORT_PATH: knapsack/report-master.json
FLAKY_RSPEC_SUITE_REPORT_PATH: rspec_flaky/report-suite.json
BUILD_ASSETS_IMAGE: "false"
ES_JAVA_OPTS: "-Xms256m -Xmx256m"
......
......@@ -77,7 +77,7 @@ gitlab:assets:compile pull-cache:
- .default-before_script
- .assets-compile-cache
- .only-code-qa-changes
- .use-pg
- .use-pg9
stage: prepare
script:
- node --version
......@@ -120,7 +120,7 @@ compile-assets pull-cache:
- .default-only
- .default-before_script
- .only-code-changes
- .use-pg
- .use-pg9
dependencies: ["compile-assets", "compile-assets pull-cache", "setup-test-env"]
karma:
......
......@@ -110,19 +110,34 @@
- $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org"
kubernetes: active
.use-pg:
.use-pg9:
services:
- name: postgres:9.6.14
- name: postgres:9.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:alpine
.use-pg-10:
.use-pg10:
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.22-chrome-73.0-node-12.x-yarn-1.16-postgresql-10-graphicsmagick-1.3.33"
services:
- name: postgres:10.9
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:alpine
.use-pg9-ee:
services:
- name: postgres:9.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:alpine
- name: docker.elastic.co/elasticsearch/elasticsearch:5.6.12
.use-pg10-ee:
image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.22-chrome-73.0-node-12.x-yarn-1.16-postgresql-10-graphicsmagick-1.3.33"
services:
- name: postgres:10.9
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:alpine
- name: docker.elastic.co/elasticsearch/elasticsearch:5.6.12
.only-ee:
only:
variables:
......
......@@ -36,7 +36,7 @@ memory-static:
memory-on-boot:
extends:
- .only-code-memory-job-base
- .use-pg-10
- .use-pg10
variables:
NODE_ENV: "production"
RAILS_ENV: "production"
......
......@@ -33,31 +33,29 @@
- .default-before_script
- .only-code-qa-changes
setup-test-env:
extends:
- .only-code-qa-rails-job-base
- .use-pg9
stage: prepare
script:
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
- scripts/gitaly-test-build # Do not use 'bundle exec' here
artifacts:
expire_in: 7d
paths:
- tmp/tests
- config/secrets.yml
- vendor/gitaly-ruby
cache:
policy: pull-push
.rspec-base:
extends: .only-code-rails-job-base
stage: test
script:
- JOB_NAME=( $CI_JOB_NAME )
- TEST_TOOL=${JOB_NAME[0]}
- TEST_LEVEL=${JOB_NAME[1]}
- DATABASE=${JOB_NAME[2]}
- export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${TEST_TOOL}_${TEST_LEVEL}_${DATABASE}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export KNAPSACK_GENERATE_REPORT=true KNAPSACK_LOG_LEVEL=debug KNAPSACK_TEST_DIR=spec
- export SUITE_FLAKY_RSPEC_REPORT_PATH=${FLAKY_RSPEC_SUITE_REPORT_PATH}
- export FLAKY_RSPEC_REPORT_PATH=rspec_flaky/all_${TEST_TOOL}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export NEW_FLAKY_RSPEC_REPORT_PATH=rspec_flaky/new_${TEST_TOOL}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export FLAKY_RSPEC_GENERATE_REPORT=true
- export CACHE_CLASSES=true
- cp ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH}
- '[[ -f $FLAKY_RSPEC_REPORT_PATH ]] || echo "{}" > ${FLAKY_RSPEC_REPORT_PATH}'
- '[[ -f $NEW_FLAKY_RSPEC_REPORT_PATH ]] || echo "{}" > ${NEW_FLAKY_RSPEC_REPORT_PATH}'
- scripts/gitaly-test-spawn
- date
- 'export KNAPSACK_TEST_FILE_PATTERN=$(ruby -r./lib/quality/test_level.rb -e "puts Quality::TestLevel.new.pattern(:${TEST_LEVEL})")'
- mkdir -p tmp/memory_test
- export MEMORY_TEST_PATH="tmp/memory_test/${TEST_TOOL}_${TEST_LEVEL}_${DATABASE}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_memory.csv"
- knapsack rspec "--color --format documentation --format RspecJunitFormatter --out junit_rspec.xml --tag level:${TEST_LEVEL} --tag ~geo"
- date
- source scripts/rspec_helpers.sh
- rspec_paralellized_job "--tag ~quarantine --tag ~geo"
artifacts:
expire_in: 31d
when: always
......@@ -71,78 +69,145 @@
reports:
junit: junit_rspec.xml
.rspec-base-pg:
.rspec-base-pg9:
extends:
- .rspec-base
- .use-pg
- .use-pg9
.rspec-base-pg-10:
.rspec-base-pg10:
extends:
- .rspec-base
- .use-pg-10
- .use-pg10
- .only-master
setup-test-env:
extends:
- .only-code-qa-rails-job-base
- .use-pg
stage: prepare
script:
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
- scripts/gitaly-test-build # Do not use 'bundle exec' here
artifacts:
expire_in: 7d
paths:
- tmp/tests
- config/secrets.yml
- vendor/gitaly-ruby
cache:
policy: pull-push
rspec unit pg9:
extends: .rspec-base-pg9
parallel: 20
rspec integration pg9:
extends: .rspec-base-pg9
parallel: 6
rspec unit pg:
extends: .rspec-base-pg
rspec system pg9:
extends: .rspec-base-pg9
parallel: 24
rspec unit pg10:
extends: .rspec-base-pg10
parallel: 20
rspec integration pg:
extends: .rspec-base-pg
rspec integration pg10:
extends: .rspec-base-pg10
parallel: 6
rspec system pg:
extends: .rspec-base-pg
rspec system pg10:
extends: .rspec-base-pg10
parallel: 24
rspec unit pg-10:
.rspec-ee-base-pg9:
extends:
- .rspec-base
- .only-ee
- .use-pg9-ee
.rspec-ee-base-pg10:
extends:
- .rspec-base
- .only-ee
- .use-pg10-ee
rspec-ee unit pg9:
extends: .rspec-ee-base-pg9
parallel: 7
rspec-ee integration pg9:
extends: .rspec-ee-base-pg9
parallel: 3
rspec-ee system pg9:
extends: .rspec-ee-base-pg9
parallel: 5
rspec-ee unit pg10:
extends:
- .rspec-base-pg-10
- .rspec-ee-base-pg10
- .only-master
parallel: 20
parallel: 7
rspec integration pg-10:
rspec-ee integration pg10:
extends:
- .rspec-base-pg-10
- .rspec-ee-base-pg10
- .only-master
parallel: 6
parallel: 3
rspec system pg-10:
rspec-ee system pg10:
extends:
- .rspec-base-pg-10
- .rspec-ee-base-pg10
- .only-master
parallel: 24
parallel: 5
rspec-fast-spec-helper:
extends: .rspec-base-pg
.rspec-ee-base-geo:
extends:
- .rspec-base
- .only-ee
script:
- bundle exec rspec spec/fast_spec_helper.rb
- source scripts/rspec_helpers.sh
- scripts/prepare_postgres_fdw.sh
- rspec_paralellized_job "--tag ~quarantine --tag geo"
.rspec-ee-base-geo-pg9:
extends:
- .rspec-ee-base-geo
- .use-pg9-ee
.rspec-ee-base-geo-pg10:
extends:
- .rspec-ee-base-geo
- .use-pg10-ee
rspec-ee unit pg9 geo:
extends: .rspec-ee-base-geo-pg9
parallel: 2
rspec-ee integration pg9 geo:
extends: .rspec-ee-base-geo-pg9
rspec quarantine pg:
rspec-ee system pg9 geo:
extends: .rspec-ee-base-geo-pg9
rspec-ee unit pg10 geo:
extends: .rspec-ee-base-geo-pg10
parallel: 2
rspec-ee integration pg10 geo:
extends: .rspec-ee-base-geo-pg10
rspec-ee system pg10 geo:
extends: .rspec-ee-base-geo-pg10
rspec quarantine pg9:
extends:
- .rspec-base-pg
- .rspec-base-pg9
- .only-master
variables:
RSPEC_OPTS: "--tag quarantine -- spec/"
script:
- export NO_KNAPSACK=1 CACHE_CLASSES=true
- scripts/gitaly-test-spawn
- bin/rspec --color --format documentation --tag quarantine -- spec/
- source scripts/rspec_helpers.sh
- rspec_simple_job "${RSPEC_OPTS}"
allow_failure: true
rspec-ee quarantine pg9:
extends:
- rspec quarantine pg9
- .only-ee
variables:
RSPEC_OPTS: "--tag quarantine -- ee/spec/"
rspec fast_spec_helper:
extends: .rspec-base-pg9
script:
- bin/rspec spec/fast_spec_helper.rb
static-analysis:
extends: .only-code-qa-rails-job-base
dependencies: ["setup-test-env", "compile-assets", "compile-assets pull-cache"]
......@@ -174,7 +239,7 @@ downtime_check:
.db-job-base:
extends:
- .only-code-rails-job-base
- .use-pg
- .use-pg9
stage: test
dependencies: ["setup-test-env"]
needs: ["setup-test-env"]
......@@ -258,108 +323,6 @@ coverage:
- coverage/assets/
- tmp/memory_test/
## EE-specific content
.rspec-base-ee:
extends:
- .rspec-base
- .only-ee
script:
- JOB_NAME=( $CI_JOB_NAME )
- TEST_TOOL=${JOB_NAME[0]}
- TEST_LEVEL=${JOB_NAME[1]}
- DATABASE=${JOB_NAME[2]}
- export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${TEST_TOOL}_${TEST_LEVEL}_${DATABASE}_ee_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- export KNAPSACK_GENERATE_REPORT=true KNAPSACK_LOG_LEVEL=debug KNAPSACK_TEST_DIR=spec
- export CACHE_CLASSES=true
- cp ${EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH}
- scripts/gitaly-test-spawn
- date
- 'export KNAPSACK_TEST_FILE_PATTERN=$(ruby -r./lib/quality/test_level.rb -e "puts Quality::TestLevel.new(%(ee/)).pattern(:${TEST_LEVEL})")'
- mkdir -p tmp/memory_test
- export MEMORY_TEST_PATH="tmp/memory_test/ee_${TEST_TOOL}_${TEST_LEVEL}_${DATABASE}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_memory.csv"
- knapsack rspec "--color --format documentation --format RspecJunitFormatter --out junit_rspec.xml --tag level:${TEST_LEVEL} --tag ~geo"
- date
.rspec-base-pg-ee:
extends: .rspec-base-ee
services:
- name: postgres:9.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:alpine
- name: docker.elastic.co/elasticsearch/elasticsearch:5.6.12
rspec unit pg ee:
extends: .rspec-base-pg-ee
parallel: 7
rspec integration pg ee:
extends: .rspec-base-pg-ee
parallel: 3
rspec system pg ee:
extends: .rspec-base-pg-ee
parallel: 5
.rspec-base-geo:
extends: .rspec-base-ee
parallel: 3
script:
- JOB_NAME=( $CI_JOB_NAME )
- TEST_TOOL=${JOB_NAME[0]}
- TEST_LEVEL=${JOB_NAME[1]}
- DATABASE=${JOB_NAME[2]}
- export KNAPSACK_TEST_FILE_PATTERN="ee/spec/**{,/*/**}/*_spec.rb" KNAPSACK_GENERATE_REPORT=true CACHE_CLASSES=true
- export KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${TEST_TOOL}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json
- cp ${EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH} ${KNAPSACK_REPORT_PATH}
- source scripts/prepare_postgres_fdw.sh
- scripts/gitaly-test-spawn
- mkdir -p tmp/memory_test
- export MEMORY_TEST_PATH="tmp/memory_test/ee_${TEST_TOOL}_${TEST_LEVEL}_${DATABASE}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_memory.csv"
- knapsack rspec "-Ispec --color --format documentation --format RspecJunitFormatter --out junit_rspec.xml --tag geo"
rspec geo pg ee:
extends:
- .rspec-base-geo
- .use-pg
except:
variables:
- $CI_COMMIT_REF_NAME =~ /(^geo[\/-].*|.*-geo$)/
rspec geo pg-10 ee:
extends:
- .rspec-base-geo
- .use-pg-10
except:
variables:
- $CI_COMMIT_REF_NAME =~ /(^geo[\/-].*|.*-geo$)/
quick-rspec geo pg ee:
extends:
- .rspec-base-geo
- .use-pg
stage: quick-test
only:
variables:
- $CI_COMMIT_REF_NAME =~ /(^geo[\/-].*|.*-geo$)/
quick-rspec geo pg-10 ee:
extends:
- .rspec-base-geo
- .use-pg-10
stage: quick-test
only:
variables:
- $CI_COMMIT_REF_NAME =~ /(^geo[\/-].*|.*-geo$)/
rspec quarantine pg ee:
extends:
- rspec quarantine pg
- .only-ee
script:
- export NO_KNAPSACK=1 CACHE_CLASSES=true
- scripts/gitaly-test-spawn
- bin/rspec --color --format documentation --format RspecJunitFormatter --out junit_rspec.xml --tag quarantine -- ee/spec/
db:rollback geo:
extends:
- db:rollback
......@@ -367,5 +330,3 @@ db:rollback geo:
script:
- bundle exec rake geo:db:migrate VERSION=20170627195211
- bundle exec rake geo:db:migrate
## END of EE-specific content
.tests-metadata-state:
extends:
- .default-only
- .only-code-changes
variables:
TESTS_METADATA_S3_BUCKET: "gitlab-ce-cache"
before_script:
- source scripts/utils.sh
cache:
key: tests_metadata
paths:
- knapsack/
- rspec_flaky/
artifacts:
expire_in: 31d
paths:
......@@ -13,55 +19,29 @@
- rspec_profiling/
retrieve-tests-metadata:
extends:
- .tests-metadata-state
- .only-code-changes
extends: .tests-metadata-state
stage: prepare
cache:
key: tests_metadata
policy: pull
script:
- mkdir -p knapsack/${CI_PROJECT_NAME}/
- wget -O $KNAPSACK_RSPEC_SUITE_REPORT_PATH http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/$KNAPSACK_RSPEC_SUITE_REPORT_PATH || rm $KNAPSACK_RSPEC_SUITE_REPORT_PATH
- '[[ -f $KNAPSACK_RSPEC_SUITE_REPORT_PATH ]] || echo "{}" > ${KNAPSACK_RSPEC_SUITE_REPORT_PATH}'
- mkdir -p rspec_flaky/
- mkdir -p rspec_profiling/
- wget -O $FLAKY_RSPEC_SUITE_REPORT_PATH http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/$FLAKY_RSPEC_SUITE_REPORT_PATH || rm $FLAKY_RSPEC_SUITE_REPORT_PATH
- '[[ -f $FLAKY_RSPEC_SUITE_REPORT_PATH ]] || echo "{}" > ${FLAKY_RSPEC_SUITE_REPORT_PATH}'
- '[[ ! -d "ee/" ]] || wget -O $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/$EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH || rm $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH'
- '[[ ! -d "ee/" ]] || [[ -f $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH ]] || echo "{}" > ${EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH}'
- source scripts/rspec_helpers.sh
- retrieve_tests_metadata
update-tests-metadata:
extends:
- .tests-metadata-state
- .only-code-changes
extends: .tests-metadata-state
stage: post-test
cache:
key: tests_metadata
paths:
- knapsack/
- rspec_flaky/
policy: push
script:
- retry gem install fog-aws mime-types activesupport rspec_profiling postgres-copy --no-document
- echo "{}" > ${KNAPSACK_RSPEC_SUITE_REPORT_PATH}
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec_*_pg_node_*.json
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH'
- '[[ ! -d "ee/" ]] || echo "{}" > ${EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH}'
- '[[ ! -d "ee/" ]] || scripts/merge-reports ${EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec_*_pg_ee_*node_*.json'
- '[[ ! -d "ee/" ]] || [[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH'
- rm -f knapsack/${CI_PROJECT_NAME}/*_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}
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $FLAKY_RSPEC_SUITE_REPORT_PATH'
- rm -f rspec_flaky/all_*.json rspec_flaky/new_*.json
- scripts/insert-rspec-profiling-data
- source scripts/rspec_helpers.sh
- update_tests_metadata
only:
refs:
- master
- schedules
variables:
- $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org"
- $CI_SERVER_HOST == "dev.gitlab.org"
# Only update the Knapsack metadata on GitLab.com/gitlab-org/gitlab
- $CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/gitlab"
flaky-examples-check:
extends:
......
......@@ -63,7 +63,7 @@ const handleUserPopoverMouseOver = event => {
UsersCache.retrieveById(userId)
.then(userData => {
if (!userData) {
return;
return undefined;
}
Object.assign(user, {
......@@ -76,19 +76,16 @@ const handleUserPopoverMouseOver = event => {
loaded: true,
});
UsersCache.retrieveStatusById(userId)
.then(status => {
if (!status) {
return;
}
return UsersCache.retrieveStatusById(userId);
})
.then(status => {
if (!status) {
return;
}
Object.assign(user, {
status,
});
})
.catch(() => {
throw new Error(`User status for "${userId}" could not be retrieved!`);
});
Object.assign(user, {
status,
});
})
.catch(() => {
renderedPopover.$destroy();
......
......@@ -58,7 +58,7 @@ module GitlabRoutingHelper
end
def commits_url(entity, *args)
project_commits_url(entity.project, entity.ref, *args)
project_commits_url(entity.project, entity.source_ref, *args)
end
def commit_url(entity, *args)
......
......@@ -15,7 +15,7 @@ module Emails
def pipeline_mail(pipeline, recipients, status)
@project = pipeline.project
@pipeline = pipeline
@merge_request = pipeline.merge_requests_as_head_pipeline.first
@merge_request = pipeline.all_merge_requests.first
add_headers
# We use bcc here because we don't want to generate this emails for a
......@@ -44,7 +44,7 @@ module Emails
commit = [@pipeline.short_sha]
commit << "in #{@merge_request.to_reference}" if @merge_request
subject("Pipeline ##{@pipeline.id} has #{status} for #{@pipeline.ref}", commit.join(' '))
subject("Pipeline ##{@pipeline.id} has #{status} for #{@pipeline.source_ref}", commit.join(' '))
end
end
end
......@@ -34,7 +34,7 @@
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
%a.muted{ href: commits_url(@pipeline), style: "color:#333333;text-decoration:none;" }
= @pipeline.ref
= @pipeline.source_ref
%tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" } Commit
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:400;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
......
Your pipeline has failed.
Project: <%= @project.name %> ( <%= project_url(@project) %> )
Branch: <%= @pipeline.ref %> ( <%= commits_url(@pipeline) %> )
Branch: <%= @pipeline.source_ref %> ( <%= commits_url(@pipeline) %> )
<% if @merge_request -%>
Merge Request: <%= @merge_request.to_reference %> ( <%= merge_request_url(@merge_request) %> )
<% end -%>
......
......@@ -34,7 +34,7 @@
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "" }/
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
%a.muted{ href: commits_url(@pipeline), style: "color:#333333;text-decoration:none;" }
= @pipeline.ref
= @pipeline.source_ref
%tr
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" } Commit
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:400;padding:14px 0;margin:0;color:#333333;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
......
Your pipeline has passed.
Project: <%= @project.name %> ( <%= project_url(@project) %> )
Branch: <%= @pipeline.ref %> ( <%= commits_url(@pipeline) %> )
Branch: <%= @pipeline.source_ref %> ( <%= commits_url(@pipeline) %> )
<% if @merge_request -%>
Merge Request: <%= @merge_request.to_reference %> ( <%= merge_request_url(@merge_request) %> )
<% end -%>
......
- if show_auto_devops_implicitly_enabled_banner?(project, current_user)
.qa-auto-devops-banner.auto-devops-implicitly-enabled-banner.alert.alert-warning
.qa-auto-devops-banner.auto-devops-implicitly-enabled-banner.alert.alert-info
- more_information_link = link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank', class: 'alert-link'
- auto_devops_message = s_("AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}") % { more_information_link: more_information_link }
= auto_devops_message.html_safe
......
---
title: Update PumaWorkerKiller defaults
merge_request: 17758
author:
type: performance
---
title: Add proper label REST API for update, delete and promote
merge_request: 17239
author: Mathieu Parent
type: added
---
title: Show the original branch name and link of merge request in pipeline emails
merge_request: 17513
author:
type: fixed
......@@ -51,6 +51,40 @@ Example response:
]
```
## Get a single group label
Get a single label for a given group.
```
GET /groups/:id/labels/:label_id
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user. |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
| `include_ancestor_groups` | boolean | no | Include ancestor groups. Defaults to `true`. |
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/labels/bug
```
Example response:
```json
{
"id": 7,
"name": "bug",
"color": "#FF0000",
"text_color" : "#FFFFFF",
"description": null,
"open_issues_count": 0,
"closed_issues_count": 0,
"open_merge_requests_count": 0,
"subscribed": false
}
```
## Create a new group label
Create a new group label for a given group.
......@@ -91,19 +125,19 @@ Example response:
Updates an existing group label. At least one parameter is required, to update the group label.
```
PUT /groups/:id/labels
PUT /groups/:id/labels/:label_id
```
| Attribute | Type | Required | Description |
| ------------- | ------- | -------- | ---------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | The name of the label |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
| `new_name` | string | no | The new name of the label |
| `color` | string | no | The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the [CSS color names](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords) |
| `description` | string | no | The description of the label. |
```bash
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"name": "Feature Proposal", "new_name": "Feature Idea" }' https://gitlab.example.com/api/v4/groups/5/labels
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" --data '{"new_name": "Feature Idea" }' https://gitlab.example.com/api/v4/groups/5/labels/Feature%20Proposal
```
Example response:
......@@ -122,23 +156,27 @@ Example response:
}
```
NOTE: **Note:** An older endpoint `PUT /groups/:id/labels` with `name` in the params is still available, but deprecated.
## Delete a group label
Deletes a group label with a given name.
```
DELETE /groups/:id/labels
DELETE /groups/:id/labels/:label_id
```
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | The name of the label. |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
```bash
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/labels?name=bug
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/labels/bug
```
NOTE: **Note:** An older endpoint `DELETE /groups/:id/labels` with `name` in the params is still available, but deprecated.
## Subscribe to a group label
Subscribes the authenticated user to a group label to receive notifications. If
......
......@@ -90,6 +90,42 @@ Example response:
]
```
## Get a single project label
Get a single label for a given project.
```
GET /projects/:id/labels/:label_id
```
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
| `include_ancestor_groups` | boolean | no | Include ancestor groups. Defaults to `true`. |
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/labels/bug
```
Example response:
```json
{
"id" : 1,
"name" : "bug",
"color" : "#d9534f",
"text_color" : "#FFFFFF",
"description": "Bug reported by user",
"open_issues_count": 1,
"closed_issues_count": 0,
"open_merge_requests_count": 1,
"subscribed": false,
"priority": 10,
"is_project_label": true
}
```
## Create a new label
Creates a new label for the given repository with the given name and color.
......@@ -133,40 +169,40 @@ Example response:
Deletes a label with a given name.
```
DELETE /projects/:id/labels
DELETE /projects/:id/labels/:label_id
```
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer | yes (or `name`) | The id of the existing label |
| `name` | string | yes (or `label_id`) | The name of the existing label |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
```bash
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/labels?name=bug"
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/labels/bug"
```
NOTE: **Note:** An older endpoint `DELETE /projects/:id/labels` with `name` in the params is still available, but deprecated.
## Edit an existing label
Updates an existing label with new name or new color. At least one parameter
is required, to update the label.
```
PUT /projects/:id/labels
PUT /projects/:id/labels/:label_id
```
| Attribute | Type | Required | Description |
| --------------- | ------- | --------------------------------- | ------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer | yes (or `name`) | The id of the existing label |
| `name` | string | yes (or `label_id`) | The name of the existing label |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
| `new_name` | string | yes if `color` is not provided | The new name of the label |
| `color` | string | yes if `new_name` is not provided | The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the [CSS color names](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords) |
| `description` | string | no | The new description of the label |
| `priority` | integer | no | The new priority of the label. Must be greater or equal than zero or `null` to remove the priority. |
```bash
curl --request PUT --data "name=documentation&new_name=docs&color=#8E44AD&description=Documentation" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/labels"
curl --request PUT --data "new_name=docs&color=#8E44AD&description=Documentation" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/labels/documentation"
```
Example response:
......@@ -187,6 +223,8 @@ Example response:
}
```
NOTE: **Note:** An older endpoint `PUT /projects/:id/labels` with `name` or `label_id` in the params is still available, but deprecated.
## Promote a project label to a group label
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/25218) in GitLab 12.3.
......@@ -194,16 +232,16 @@ Example response:
Promotes a project label to a group label.
```
PUT /projects/:id/labels/promote
PUT /projects/:id/labels/:label_id/promote
```
| Attribute | Type | Required | Description |
| --------------- | ------- | --------------------------------- | ------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | The name of the existing label |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
```bash
curl --request PUT --data "name=documentation" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/labels/promote"
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/labels/documentation/promote"
```
Example response:
......@@ -221,6 +259,8 @@ Example response:
}
```
NOTE: **Note:** An older endpoint `PUT /projects/:id/labels/promote` with `name` in the params is still available, but deprecated.
## Subscribe to a label
Subscribes the authenticated user to a label to receive notifications.
......
......@@ -149,8 +149,13 @@ You can find the groups listed in the [Product Stages, Groups, and Categories](h
We use the term group to map down product requirements from our product stages.
As a team needs some way to collect the work their members are planning to be assigned to, we use the `~group::` labels to do so.
Normally there is a 1:1 relationship between Stage labels and Group labels. In the spirit of "Everyone can contribute",
any issue can be picked up by any group, depending on current priorities. For example, an issue labeled ~"devops::create" may be picked up by the ~"group::access" group.
Normally there is a 1:1 relationship between Stage labels and Group labels. In
the spirit of "Everyone can contribute", any issue can be picked up by any group,
depending on current priorities. When picking up an issue belonging to a different
group, it should be relabelled. For example, if an issue labelled ~"devops::create"
and ~"group::knowledge" is picked up by someone in the Access group of the Plan stage,
the issue should be relabelled as ~"group::access" while keeping the original
~"devops::create" unchanged.
We also use stage and group labels to help quantify our [throughput](https://about.gitlab.com/handbook/engineering/management/throughput/).
Please read [Stage and Group labels in Throughtput](https://about.gitlab.com/handbook/engineering/management/throughput/#stage-and-group-labels-in-throughput) for more information on how the labels are used in this context.
......
......@@ -4,27 +4,24 @@
Our current CI parallelization setup is as follows:
1. The `knapsack` job in the prepare stage that is supposed to ensure we have a
`knapsack/${CI_PROJECT_NAME}/rspec_report-master.json` file:
- The `knapsack/${CI_PROJECT_NAME}/rspec_report-master.json` file is fetched
from S3, if it's not here we initialize the file with `{}`.
1. Each `rspec x y` job are run with `knapsack rspec` and should have an evenly
distributed share of tests:
- It works because the jobs have access to the
`knapsack/${CI_PROJECT_NAME}/rspec_report-master.json` since the "artifacts
from all previous stages are passed by default".
1. The `retrieve-tests-metadata` job in the `prepare` stage ensures we have a
`knapsack/report-master.json` file:
- The `knapsack/report-master.json` file is fetched from S3, if it's not here
we initialize the file with `{}`.
1. Each `[rspec|rspec-ee] [unit|integration|system|geo] n m` job are run with
`knapsack rspec` and should have an evenly distributed share of tests:
- It works because the jobs have access to the `knapsack/report-master.json`
since the "artifacts from all previous stages are passed by default".
- the jobs set their own report path to
`KNAPSACK_REPORT_PATH=knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json`.
`"knapsack/${TEST_TOOL}_${TEST_LEVEL}_${DATABASE}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json"`.
- if knapsack is doing its job, test files that are run should be listed under
`Report specs`, not under `Leftover specs`.
1. The `update-knapsack` job takes all the
`knapsack/${CI_PROJECT_NAME}/${JOB_NAME[0]}_node_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json`
files from the `rspec x y` jobs and merge them all together into a single
`knapsack/${CI_PROJECT_NAME}/rspec_report-master.json` file that is then
uploaded to S3.
After that, the next pipeline will use the up-to-date
`knapsack/${CI_PROJECT_NAME}/rspec_report-master.json` file.
1. The `update-tests-metadata` job (which only runs on scheduled pipelines for
[the canonical project](https://gitlab.com/gitlab-org/gitlab) takes all the
`knapsack/rspec*_pg_*.json` files and merge them all together into a single
`knapsack/report-master.json` file that is then uploaded to S3.
After that, the next pipeline will use the up-to-date `knapsack/report-master.json` file.
## Monitoring
......
......@@ -53,3 +53,15 @@ In summary:
- **Do**: Split tests across separate files, unless the tests share expensive setup.
- **Don't**: Put new tests in an existing file without considering the impact on parallelization.
## Limit the use of `before(:all)` hook
Limit the use of `before(:all)` to perform setup tasks with only API calls, non UI operations
or basic UI operations such as login.
We use [`capybara-screenshot`](https://github.com/mattheworiordan/capybara-screenshot) library to automatically save screenshots on failures.
This library [saves the screenshots in the RSpec's `after` hook](https://github.com/mattheworiordan/capybara-screenshot/blob/master/lib/capybara-screenshot/rspec.rb#L97).
[If there is a failure in `before(:all)`, the `after` hook is not called](https://github.com/rspec/rspec-core/pull/2652/files#diff-5e04af96d5156e787f28d519a8c99615R148) and so the screenshots are not saved.
Given this fact, we should limit the use of `before(:all)` to only those operations where a screenshot is not
necessary in case of failure and QA logs would be enough for debugging.
......@@ -26,6 +26,18 @@ module API
get_labels(user_group, Entities::GroupLabel, include_ancestor_groups: params[:include_ancestor_groups])
end
desc 'Get a single label' do
detail 'This feature was added in GitLab 12.4.'
success Entities::GroupLabel
end
params do
optional :include_ancestor_groups, type: Boolean, default: true,
desc: 'Include ancestor groups'
end
get ':id/labels/:name' do
get_label(user_group, Entities::GroupLabel, include_ancestor_groups: params[:include_ancestor_groups])
end
desc 'Create a new label' do
detail 'This feature was added in GitLab 11.8'
success Entities::GroupLabel
......@@ -38,22 +50,21 @@ module API
end
desc 'Update an existing label. At least one optional parameter is required.' do
detail 'This feature was added in GitLab 11.8'
detail 'This feature was added in GitLab 11.8 and deprecated in GitLab 12.4.'
success Entities::GroupLabel
end
params do
requires :name, type: String, desc: 'The name of the label to be updated'
optional :new_name, type: String, desc: 'The new name of the label'
optional :color, type: String, desc: "The new color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the allowed CSS color names"
optional :description, type: String, desc: 'The new description of label'
at_least_one_of :new_name, :color, :description
optional :label_id, type: Integer, desc: 'The id of the label to be updated'
optional :name, type: String, desc: 'The name of the label to be updated'
use :group_label_update_params
exactly_one_of :label_id, :name
end
put ':id/labels' do
update_label(user_group, Entities::GroupLabel)
end
desc 'Delete an existing label' do
detail 'This feature was added in GitLab 11.8'
detail 'This feature was added in GitLab 11.8 and deprecated in GitLab 12.4.'
success Entities::GroupLabel
end
params do
......@@ -62,6 +73,29 @@ module API
delete ':id/labels' do
delete_label(user_group)
end
desc 'Update an existing label. At least one optional parameter is required.' do
detail 'This feature was added in GitLab 12.4.'
success Entities::GroupLabel
end
params do
requires :name, type: String, desc: 'The name or id of the label to be updated'
use :group_label_update_params
end
put ':id/labels/:name' do
update_label(user_group, Entities::GroupLabel)
end
desc 'Delete an existing label' do
detail 'This feature was added in GitLab 12.4.'
success Entities::GroupLabel
end
params do
requires :name, type: String, desc: 'The name or id of the label to be deleted'
end
delete ':id/labels/:name' do
delete_label(user_group)
end
end
end
end
......@@ -11,6 +11,23 @@ module API
optional :description, type: String, desc: 'The description of label to be created'
end
params :label_update_params do
optional :new_name, type: String, desc: 'The new name of the label'
optional :color, type: String, desc: "The new color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the allowed CSS color names"
optional :description, type: String, desc: 'The new description of label'
end
params :project_label_update_params do
use :label_update_params
optional :priority, type: Integer, desc: 'The priority of the label', allow_blank: true
at_least_one_of :new_name, :color, :description, :priority
end
params :group_label_update_params do
use :label_update_params
at_least_one_of :new_name, :color, :description
end
def find_label(parent, id_or_title, include_ancestor_groups: true)
labels = available_labels_for(parent, include_ancestor_groups: include_ancestor_groups)
label = labels.find_by_id(id_or_title) || labels.find_by_title(id_or_title)
......@@ -26,6 +43,12 @@ module API
with_counts: params[:with_counts]
end
def get_label(parent, entity, include_ancestor_groups: true)
label = find_label(parent, params_id_or_title, include_ancestor_groups: include_ancestor_groups)
present label, with: entity, current_user: current_user, parent: parent
end
def create_label(parent, entity)
authorize! :admin_label, parent
......@@ -57,6 +80,7 @@ module API
# params is used to update the label so we need to remove this field here
params.delete(:label_id)
params.delete(:name)
label = ::Labels::UpdateService.new(declared_params(include_missing: false)).execute(label)
render_validation_error!(label) unless label.valid?
......@@ -80,6 +104,24 @@ module API
destroy_conditionally!(label)
end
def promote_label(parent)
authorize! :admin_label, parent
label = find_label(parent, params[:name], include_ancestor_groups: false)
begin
group_label = ::Labels::PromoteService.new(parent, current_user).execute(label)
if group_label
present group_label, with: Entities::GroupLabel, current_user: current_user, parent: parent.group
else
render_api_error!('Failed to promote project label to group label', 400)
end
rescue => error
render_api_error!(error.to_s, 400)
end
end
def params_id_or_title
@params_id_or_title ||= params[:label_id] || params[:name]
end
......
......@@ -25,6 +25,18 @@ module API
get_labels(user_project, Entities::ProjectLabel, include_ancestor_groups: params[:include_ancestor_groups])
end
desc 'Get a single label' do
detail 'This feature was added in GitLab 12.4.'
success Entities::ProjectLabel
end
params do
optional :include_ancestor_groups, type: Boolean, default: true,
desc: 'Include ancestor groups'
end
get ':id/labels/:name' do
get_label(user_project, Entities::ProjectLabel, include_ancestor_groups: params[:include_ancestor_groups])
end
desc 'Create a new label' do
success Entities::ProjectLabel
end
......@@ -37,23 +49,21 @@ module API
end
desc 'Update an existing label. At least one optional parameter is required.' do
detail 'This feature was deprecated in GitLab 12.4.'
success Entities::ProjectLabel
end
params do
optional :label_id, type: Integer, desc: 'The id of the label to be updated'
optional :name, type: String, desc: 'The name of the label to be updated'
optional :new_name, type: String, desc: 'The new name of the label'
optional :color, type: String, desc: "The new color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the allowed CSS color names"
optional :description, type: String, desc: 'The new description of label'
optional :priority, type: Integer, desc: 'The priority of the label', allow_blank: true
use :project_label_update_params
exactly_one_of :label_id, :name
at_least_one_of :new_name, :color, :description, :priority
end
put ':id/labels' do
update_label(user_project, Entities::ProjectLabel)
end
desc 'Delete an existing label' do
detail 'This feature was deprecated in GitLab 12.4.'
success Entities::ProjectLabel
end
params do
......@@ -66,28 +76,48 @@ module API
end
desc 'Promote a label to a group label' do
detail 'This feature was added in GitLab 12.3'
detail 'This feature was added in GitLab 12.3 and deprecated in GitLab 12.4.'
success Entities::GroupLabel
end
params do
requires :name, type: String, desc: 'The name of the label to be promoted'
end
put ':id/labels/promote' do
authorize! :admin_label, user_project
promote_label(user_project)
end
label = find_label(user_project, params[:name], include_ancestor_groups: false)
desc 'Update an existing label. At least one optional parameter is required.' do
detail 'This feature was added in GitLab 12.4.'
success Entities::ProjectLabel
end
params do
requires :name, type: String, desc: 'The name or id of the label to be updated'
use :project_label_update_params
end
put ':id/labels/:name' do
update_label(user_project, Entities::ProjectLabel)
end
begin
group_label = ::Labels::PromoteService.new(user_project, current_user).execute(label)
desc 'Delete an existing label' do
detail 'This feature was added in GitLab 12.4.'
success Entities::ProjectLabel
end
params do
requires :name, type: String, desc: 'The name or id of the label to be deleted'
end
delete ':id/labels/:name' do
delete_label(user_project)
end
if group_label
present group_label, with: Entities::GroupLabel, current_user: current_user, parent: user_project.group
else
render_api_error!('Failed to promote project label to group label', 400)
end
rescue => error
render_api_error!(error.to_s, 400)
end
desc 'Promote a label to a group label' do
detail 'This feature was added in GitLab 12.4.'
success Entities::GroupLabel
end
params do
requires :name, type: String, desc: 'The name or id of the label to be promoted'
end
put ':id/labels/:name/promote' do
promote_label(user_project)
end
end
end
......
......@@ -3,7 +3,7 @@
module Gitlab
module Cluster
class PumaWorkerKillerInitializer
def self.start(puma_options, puma_per_worker_max_memory_mb: 650)
def self.start(puma_options, puma_per_worker_max_memory_mb: 850, puma_master_max_memory_mb: 550)
require 'puma_worker_killer'
PumaWorkerKiller.config do |config|
......@@ -12,10 +12,9 @@ module Gitlab
# not each worker as is the case with GITLAB_UNICORN_MEMORY_MAX
worker_count = puma_options[:workers] || 1
# The Puma Worker Killer checks the total RAM used by both the master
# and worker processes. Bump the limits to N+1 instead of N workers
# to account for this:
# and worker processes.
# https://github.com/schneems/puma_worker_killer/blob/v0.1.0/lib/puma_worker_killer/puma_memory.rb#L57
config.ram = (worker_count + 1) * puma_per_worker_max_memory_mb
config.ram = puma_master_max_memory_mb + (worker_count * puma_per_worker_max_memory_mb)
config.frequency = 20 # seconds
......@@ -23,10 +22,9 @@ module Gitlab
# of available RAM.
config.percent_usage = 0.98
# Ideally we'll never hit the maximum amount of memory. If so the worker
# is restarted already, thus periodically restarting workers shouldn't be
# needed.
config.rolling_restart_frequency = false
# Ideally we'll never hit the maximum amount of memory. Restart the workers
# regularly rather than rely on OOM behavior for periodic restarting.
config.rolling_restart_frequency = 43200 # 12 hours in seconds.
observer = Gitlab::Cluster::PumaWorkerKillerObserver.new
config.pre_term = observer.callback
......
......@@ -53,11 +53,11 @@ module Quality
end
def pattern(level)
@patterns[level] ||= "#{prefix}spec/{#{TEST_LEVEL_FOLDERS.fetch(level).join(',')}}{,/**/}*_spec.rb"
@patterns[level] ||= "#{prefix}spec/#{folders_pattern(level)}{,/**/}*_spec.rb"
end
def regexp(level)
@regexps[level] ||= Regexp.new("#{prefix}spec/(#{TEST_LEVEL_FOLDERS.fetch(level).join('|')})").freeze
@regexps[level] ||= Regexp.new("#{prefix}spec/#{folders_regex(level)}").freeze
end
def level_for(file_path)
......@@ -72,5 +72,27 @@ module Quality
raise UnknownTestLevelError, "Test level for #{file_path} couldn't be set. Please rename the file properly or change the test level detection regexes in #{__FILE__}."
end
end
private
def folders_pattern(level)
case level
# Geo specs aren't in a specific folder, but they all have the :geo tag, so we must search for them globally
when :all, :geo
'**'
else
"{#{TEST_LEVEL_FOLDERS.fetch(level).join(',')}}"
end
end
def folders_regex(level)
case level
# Geo specs aren't in a specific folder, but they all have the :geo tag, so we must search for them globally
when :all, :geo
''
else
"(#{TEST_LEVEL_FOLDERS.fetch(level).join('|')})"
end
end
end
end
#!/bin/bash
function retrieve_tests_metadata() {
mkdir -p knapsack/ rspec_flaky/ rspec_profiling/
if [[ ! -f "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" ]]; then
wget -O "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" "http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}"
fi
if [[ ! -f "${FLAKY_RSPEC_SUITE_REPORT_PATH}" ]]; then
wget -O "${FLAKY_RSPEC_SUITE_REPORT_PATH}" "http://${TESTS_METADATA_S3_BUCKET}.s3.amazonaws.com/${FLAKY_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
fi
}
function update_tests_metadata() {
echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}"
scripts/merge-reports "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" "knapsack/rspec*_pg9_*.json"
if [[ -n "${TESTS_METADATA_S3_BUCKET}" ]]; then
scripts/sync-reports put "${TESTS_METADATA_S3_BUCKET}" "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}"
fi
rm -f "knapsack/rspec*.json"
scripts/merge-reports "${FLAKY_RSPEC_SUITE_REPORT_PATH}" "rspec_flaky/all_*.json"
export FLAKY_RSPEC_GENERATE_REPORT="1"
scripts/prune-old-flaky-specs "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
if [[ -n ${TESTS_METADATA_S3_BUCKET} ]]; then
scripts/sync-reports put "${TESTS_METADATA_S3_BUCKET}" "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
fi
rm -f "rspec_flaky/all_*.json" "rspec_flaky/new_*.json"
scripts/insert-rspec-profiling-data
}
function rspec_simple_job() {
local rspec_opts="${1}"
export NO_KNAPSACK="1"
export CACHE_CLASSES="true"
scripts/gitaly-test-spawn
bin/rspec --color --format documentation --format RspecJunitFormatter --out junit_rspec.xml "${rspec_opts}"
}
function rspec_paralellized_job() {
read -ra job_name <<< "$CI_JOB_NAME"
local test_tool="${job_name[0]}"
local test_level="${job_name[1]}"
local database="${job_name[2]}"
local rspec_opts="${1}"
local spec_folder_prefix=""
if [[ "${test_tool}" =~ "-ee" ]]; then
spec_folder_prefix="ee/"
fi
export CACHE_CLASSES="true"
export KNAPSACK_LOG_LEVEL="debug"
export KNAPSACK_REPORT_PATH="knapsack/${test_tool}_${test_level}_${database}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json"
if [[ -z "${KNAPSACK_TEST_FILE_PATTERN}" ]]; then
pattern=$(ruby -r./lib/quality/test_level.rb -e "puts Quality::TestLevel.new(%(${spec_folder_prefix})).pattern(:${test_level})")
export KNAPSACK_TEST_FILE_PATTERN="${pattern}"
fi
echo "KNAPSACK_TEST_FILE_PATTERN: ${KNAPSACK_TEST_FILE_PATTERN}"
if [[ -d "ee/" ]]; then
export KNAPSACK_GENERATE_REPORT="true"
export FLAKY_RSPEC_GENERATE_REPORT="true"
export SUITE_FLAKY_RSPEC_REPORT_PATH="${FLAKY_RSPEC_SUITE_REPORT_PATH}"
export FLAKY_RSPEC_REPORT_PATH="rspec_flaky/all_${test_tool}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json"
export NEW_FLAKY_RSPEC_REPORT_PATH="rspec_flaky/new_${test_tool}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_report.json"
cp "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" "${KNAPSACK_REPORT_PATH}"
if [[ ! -f $FLAKY_RSPEC_REPORT_PATH ]]; then
echo "{}" > "${FLAKY_RSPEC_REPORT_PATH}"
fi
if [[ ! -f $NEW_FLAKY_RSPEC_REPORT_PATH ]]; then
echo "{}" > "${NEW_FLAKY_RSPEC_REPORT_PATH}"
fi
fi
scripts/gitaly-test-spawn
mkdir -p tmp/memory_test
export MEMORY_TEST_PATH="tmp/memory_test/${test_tool}_${test_level}_${database}_${CI_NODE_INDEX}_${CI_NODE_TOTAL}_memory.csv"
knapsack rspec "-Ispec --color --format documentation --format RspecJunitFormatter --out junit_rspec.xml ${rspec_opts}"
date
}
......@@ -2,6 +2,7 @@ import $ from 'jquery';
import Dropzone from 'dropzone';
import Mousetrap from 'mousetrap';
import ZenMode from '~/zen_mode';
import initNotes from '~/init_notes';
describe('ZenMode', () => {
let zen;
......@@ -28,6 +29,7 @@ describe('ZenMode', () => {
beforeEach(() => {
loadFixtures(fixtureName);
initNotes();
dropzoneForElementSpy = spyOn(Dropzone, 'forElement').and.callFake(() => ({
enable: () => true,
......
......@@ -4,6 +4,20 @@ require 'fast_spec_helper'
RSpec.describe Quality::TestLevel do
describe '#pattern' do
context 'when level is all' do
it 'returns a pattern' do
expect(subject.pattern(:all))
.to eq("spec/**{,/**/}*_spec.rb")
end
end
context 'when level is geo' do
it 'returns a pattern' do
expect(subject.pattern(:geo))
.to eq("spec/**{,/**/}*_spec.rb")
end
end
context 'when level is unit' do
it 'returns a pattern' do
expect(subject.pattern(:unit))
......@@ -44,6 +58,20 @@ RSpec.describe Quality::TestLevel do
end
describe '#regexp' do
context 'when level is all' do
it 'returns a regexp' do
expect(subject.regexp(:all))
.to eq(%r{spec/})
end
end
context 'when level is geo' do
it 'returns a regexp' do
expect(subject.regexp(:geo))
.to eq(%r{spec/})
end
end
context 'when level is unit' do
it 'returns a regexp' do
expect(subject.regexp(:unit))
......
# frozen_string_literal: true
require 'spec_helper'
require 'email_spec'
describe Emails::Pipelines do
include EmailSpec::Matchers
set(:project) { create(:project, :repository) }
shared_examples_for 'correct pipeline information' do
it 'has a correct information' do
expect(subject)
.to have_subject "#{project.name} | Pipeline ##{pipeline.id} has " \
"#{status} for #{pipeline.source_ref} | " \
"#{pipeline.short_sha}".to_s
expect(subject).to have_body_text pipeline.source_ref
expect(subject).to have_body_text status_text
end
context 'when pipeline for merge requests' do
let(:pipeline) { merge_request.all_pipelines.first }
let(:merge_request) do
create(:merge_request, :with_detached_merge_request_pipeline,
source_project: project,
target_project: project)
end
it 'has a correct information with merge request link' do
expect(subject)
.to have_subject "#{project.name} | Pipeline ##{pipeline.id} has " \
"#{status} for #{pipeline.source_ref} | " \
"#{pipeline.short_sha} in !#{merge_request.iid}".to_s
expect(subject).to have_body_text merge_request.to_reference
expect(subject).to have_body_text pipeline.source_ref
expect(subject).not_to have_body_text pipeline.ref
end
end
end
describe '#pipeline_success_email' do
subject { Notify.pipeline_success_email(pipeline, pipeline.user.try(:email)) }
let(:pipeline) { create(:ci_pipeline, project: project, ref: ref, sha: sha) }
let(:ref) { 'master' }
let(:sha) { project.commit(ref).sha }
it_behaves_like 'correct pipeline information' do
let(:status) { 'succeeded' }
let(:status_text) { 'Your pipeline has passed.' }
end
end
describe '#pipeline_failed_email' do
subject { Notify.pipeline_failed_email(pipeline, pipeline.user.try(:email)) }
let(:pipeline) { create(:ci_pipeline, project: project, ref: ref, sha: sha) }
let(:ref) { 'master' }
let(:sha) { project.commit(ref).sha }
it_behaves_like 'correct pipeline information' do
let(:status) { 'failed' }
let(:status_text) { 'Your pipeline has failed.' }
end
end
end
......@@ -65,6 +65,17 @@ describe API::GroupLabels do
end
end
describe 'GET :id/labels/:label_id' do
it 'returns a single label for the group' do
get api("/groups/#{group.id}/labels/#{group_label1.name}", user)
expect(response).to have_gitlab_http_status(200)
expect(json_response['name']).to eq(group_label1.name)
expect(json_response['color']).to eq(group_label1.color)
expect(json_response['description']).to eq(group_label1.description)
end
end
describe 'POST /groups/:id/labels' do
it 'returns created label when all params are given' do
post api("/groups/#{group.id}/labels", user),
......@@ -117,7 +128,7 @@ describe API::GroupLabels do
end
end
describe 'DELETE /groups/:id/labels' do
describe 'DELETE /groups/:id/labels (deprecated)' do
it 'returns 204 for existing label' do
delete api("/groups/#{group.id}/labels", user), params: { name: group_label1.name }
......@@ -154,7 +165,37 @@ describe API::GroupLabels do
end
end
describe 'PUT /groups/:id/labels' do
describe 'DELETE /groups/:id/labels/:label_id' do
it 'returns 204 for existing label' do
delete api("/groups/#{group.id}/labels/#{group_label1.name}", user)
expect(response).to have_gitlab_http_status(204)
end
it 'returns 404 for non existing label' do
delete api("/groups/#{group.id}/labels/not_exists", user)
expect(response).to have_gitlab_http_status(404)
expect(json_response['message']).to eq('404 Label Not Found')
end
it "does not delete parent's group labels" do
subgroup = create(:group, parent: group)
subgroup_label = create(:group_label, title: 'feature', group: subgroup)
delete api("/groups/#{subgroup.id}/labels/#{subgroup_label.name}", user)
expect(response).to have_gitlab_http_status(204)
expect(subgroup.labels.size).to eq(0)
expect(group.labels).to include(group_label1)
end
it_behaves_like '412 response' do
let(:request) { api("/groups/#{group.id}/labels/#{group_label1.name}", user) }
end
end
describe 'PUT /groups/:id/labels (deprecated)' do
it 'returns 200 if name and colors and description are changed' do
put api("/groups/#{group.id}/labels", user),
params: {
......@@ -199,7 +240,7 @@ describe API::GroupLabels do
put api("/groups/#{group.id}/labels", user), params: { new_name: group_label1.name }
expect(response).to have_gitlab_http_status(400)
expect(json_response['error']).to eq('name is missing')
expect(json_response['error']).to eq('label_id, name are missing, exactly one parameter must be provided')
end
it 'returns 400 if no new parameters given' do
......@@ -211,6 +252,53 @@ describe API::GroupLabels do
end
end
describe 'PUT /groups/:id/labels/:label_id' do
it 'returns 200 if name and colors and description are changed' do
put api("/groups/#{group.id}/labels/#{group_label1.name}", user),
params: {
new_name: 'New Label',
color: '#FFFFFF',
description: 'test'
}
expect(response).to have_gitlab_http_status(200)
expect(json_response['name']).to eq('New Label')
expect(json_response['color']).to eq('#FFFFFF')
expect(json_response['description']).to eq('test')
end
it "does not update parent's group label" do
subgroup = create(:group, parent: group)
subgroup_label = create(:group_label, title: 'feature', group: subgroup)
put api("/groups/#{subgroup.id}/labels/#{subgroup_label.name}", user),
params: {
new_name: 'New Label'
}
expect(response).to have_gitlab_http_status(200)
expect(subgroup.labels[0].name).to eq('New Label')
expect(group_label1.name).to eq('feature')
end
it 'returns 404 if label does not exist' do
put api("/groups/#{group.id}/labels/not_exists", user),
params: {
new_name: 'label3'
}
expect(response).to have_gitlab_http_status(404)
end
it 'returns 400 if no new parameters given' do
put api("/groups/#{group.id}/labels/#{group_label1.name}", user)
expect(response).to have_gitlab_http_status(400)
expect(json_response['error']).to eq('new_name, color, description are missing, '\
'at least one parameter must be provided')
end
end
describe 'POST /groups/:id/labels/:label_id/subscribe' do
context 'when label_id is a label title' do
it 'subscribes to the label' do
......
This diff is collapsed.
......@@ -69,7 +69,7 @@ module JavaScriptFixturesHelpers
link_tags = doc.css('link')
link_tags.remove
scripts = doc.css("script:not([type='text/template']):not([type='text/x-template'])")
scripts = doc.css("script:not([type='text/template']):not([type='text/x-template']):not([type='application/json'])")
scripts.remove
fixture = doc.to_html
......
# frozen_string_literal: true
shared_examples_for 'correct pipeline information for pipelines for merge requests' do
context 'when pipeline for merge request' do
let(:pipeline) { merge_request.all_pipelines.first }
let(:merge_request) do
create(:merge_request, :with_detached_merge_request_pipeline,
source_project: project,
target_project: project)
end
it 'renders a source ref of the pipeline' do
render
expect(rendered).to have_content pipeline.source_ref
expect(rendered).not_to have_content pipeline.ref
end
end
end
......@@ -33,6 +33,8 @@ describe 'notify/pipeline_failed_email.html.haml' do
expect(rendered).to have_content "##{pipeline.id}"
expect(rendered).to have_content pipeline.user.name
end
it_behaves_like 'correct pipeline information for pipelines for merge requests'
end
context 'pipeline without user' do
......
......@@ -36,4 +36,6 @@ describe 'notify/pipeline_failed_email.text.erb' do
expect(rendered).to have_content(pipeline.user.name)
expect(rendered).to have_content("/-/jobs/#{job.id}/raw")
end
it_behaves_like 'correct pipeline information for pipelines for merge requests'
end
......@@ -33,6 +33,8 @@ describe 'notify/pipeline_success_email.html.haml' do
expect(rendered).to have_content "##{pipeline.id}"
expect(rendered).to have_content pipeline.user.name
end
it_behaves_like 'correct pipeline information for pipelines for merge requests'
end
context 'pipeline without user' do
......
# frozen_string_literal: true
require 'spec_helper'
describe 'notify/pipeline_success_email.text.erb' do
let(:user) { create(:user, developer_projects: [project]) }
let(:project) { create(:project, :repository) }
let(:merge_request) { create(:merge_request, :simple, source_project: project) }
let(:pipeline) do
create(:ci_pipeline,
:success,
project: project,
user: user,
ref: project.default_branch,
sha: project.commit.sha)
end
before do
assign(:project, project)
assign(:pipeline, pipeline)
assign(:merge_request, merge_request)
end
it_behaves_like 'correct pipeline information for pipelines for merge requests'
end
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