Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
fef5449973
commit
42a29f3879
38 changed files with 411 additions and 200 deletions
|
@ -128,11 +128,13 @@ update-storybook-yarn-cache:
|
|||
- tmp/tests/frontend/
|
||||
- knapsack/
|
||||
|
||||
rspec frontend_fixture:
|
||||
# In gitlab-foss, generates FOSS fixtures. In gitlab, generates FOSS & EE fixtures.
|
||||
# That way, we don't need to have two separate jobs.
|
||||
rspec-all frontend_fixture:
|
||||
extends:
|
||||
- .frontend-fixtures-base
|
||||
- .frontend:rules:default-frontend-jobs
|
||||
parallel: 2
|
||||
parallel: 5
|
||||
|
||||
rspec frontend_fixture as-if-foss:
|
||||
extends:
|
||||
|
@ -140,12 +142,6 @@ rspec frontend_fixture as-if-foss:
|
|||
- .frontend:rules:default-frontend-jobs-as-if-foss
|
||||
- .as-if-foss
|
||||
|
||||
rspec-ee frontend_fixture:
|
||||
extends:
|
||||
- .frontend-fixtures-base
|
||||
- .frontend:rules:default-frontend-jobs-ee
|
||||
parallel: 3
|
||||
|
||||
graphql-schema-dump:
|
||||
variables:
|
||||
SETUP_DB: "false"
|
||||
|
@ -196,9 +192,7 @@ jest:
|
|||
- .frontend:rules:jest
|
||||
needs:
|
||||
- job: "detect-tests"
|
||||
- job: "rspec frontend_fixture"
|
||||
- job: "rspec-ee frontend_fixture"
|
||||
optional: true
|
||||
- job: "rspec-all frontend_fixture"
|
||||
artifacts:
|
||||
name: coverage-frontend
|
||||
expire_in: 31d
|
||||
|
@ -225,9 +219,7 @@ jest-integration:
|
|||
script:
|
||||
- run_timed_command "yarn jest:integration --ci"
|
||||
needs:
|
||||
- job: "rspec frontend_fixture"
|
||||
- job: "rspec-ee frontend_fixture"
|
||||
optional: true
|
||||
- job: "rspec-all frontend_fixture"
|
||||
- job: "graphql-schema-dump"
|
||||
|
||||
jest-as-if-foss:
|
||||
|
@ -341,9 +333,7 @@ startup-css-check:
|
|||
- .frontend:rules:default-frontend-jobs
|
||||
needs:
|
||||
- job: "compile-test-assets"
|
||||
- job: "rspec frontend_fixture"
|
||||
- job: "rspec-ee frontend_fixture"
|
||||
optional: true
|
||||
- job: "rspec-all frontend_fixture"
|
||||
|
||||
startup-css-check as-if-foss:
|
||||
extends:
|
||||
|
|
|
@ -495,13 +495,6 @@
|
|||
- <<: *if-default-refs
|
||||
changes: *code-backstage-patterns
|
||||
|
||||
.frontend:rules:default-frontend-jobs-ee:
|
||||
rules:
|
||||
- <<: *if-not-ee
|
||||
when: never
|
||||
- <<: *if-default-refs
|
||||
changes: *code-backstage-patterns
|
||||
|
||||
.frontend:rules:default-frontend-jobs-as-if-foss:
|
||||
rules:
|
||||
- <<: *if-not-ee
|
||||
|
|
|
@ -29,8 +29,7 @@ update-tests-metadata:
|
|||
- retrieve-tests-metadata
|
||||
- setup-test-env
|
||||
- rspec migration pg12
|
||||
- rspec frontend_fixture
|
||||
- rspec-ee frontend_fixture
|
||||
- rspec-all frontend_fixture
|
||||
- rspec unit pg12
|
||||
- rspec integration pg12
|
||||
- rspec system pg12
|
||||
|
|
|
@ -316,7 +316,7 @@ export default {
|
|||
</p>
|
||||
</gl-tooltip>
|
||||
|
||||
<span ref="countBadge" class="issue-count-badge board-card-info gl-mr-0 gl-pr-0">
|
||||
<span ref="countBadge" class="board-card-info gl-mr-0 gl-pr-0 gl-pl-3">
|
||||
<span v-if="allowSubEpics" class="gl-mr-3">
|
||||
<gl-icon name="epic" />
|
||||
{{ totalEpicsCount }}
|
||||
|
@ -334,7 +334,7 @@ export default {
|
|||
<span
|
||||
v-if="shouldRenderEpicProgress"
|
||||
ref="progressBadge"
|
||||
class="issue-count-badge board-card-info gl-pl-0"
|
||||
class="board-card-info gl-pl-0"
|
||||
>
|
||||
<span class="gl-mr-3" data-testid="epic-progress">
|
||||
<gl-icon name="progress" />
|
||||
|
|
|
@ -365,7 +365,7 @@ export default {
|
|||
>
|
||||
<span class="gl-display-inline-flex">
|
||||
<gl-tooltip :target="() => $refs.itemCount" :title="itemsTooltipLabel" />
|
||||
<span ref="itemCount" class="issue-count-badge-count">
|
||||
<span ref="itemCount" class="gl-display-inline-flex gl-align-items-center">
|
||||
<gl-icon class="gl-mr-2" :name="countIcon" />
|
||||
<item-count :items-size="itemsCount" :max-issue-count="list.maxIssueCount" />
|
||||
</span>
|
||||
|
@ -388,7 +388,7 @@ export default {
|
|||
v-gl-tooltip.hover
|
||||
:aria-label="$options.i18n.newIssue"
|
||||
:title="$options.i18n.newIssue"
|
||||
class="issue-count-badge-add-button no-drag"
|
||||
class="no-drag"
|
||||
icon="plus"
|
||||
@click="showNewIssueForm"
|
||||
/>
|
||||
|
|
|
@ -162,7 +162,6 @@ export default {
|
|||
icon="plus"
|
||||
:aria-label="__('Add a related issue')"
|
||||
:class="qaClass"
|
||||
class="js-issue-count-badge-add-button"
|
||||
@click="$emit('toggleAddRelatedIssuesForm', $event)"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -81,13 +81,13 @@ export default {
|
|||
{{ __('Related merge requests') }}
|
||||
</span>
|
||||
<div v-if="totalCount" class="d-inline-flex lh-100 align-middle">
|
||||
<div class="mr-count-badge gl-display-inline-flex">
|
||||
<div class="mr-count-badge-count">
|
||||
<svg class="s16 mr-1 text-secondary">
|
||||
<gl-icon name="merge-request" class="mr-1 text-secondary" />
|
||||
</svg>
|
||||
<span class="js-items-count">{{ totalCount }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="mr-count-badge gl-display-inline-flex gl-align-items-center gl-py-2 gl-px-3"
|
||||
>
|
||||
<svg class="s16 mr-1 text-secondary">
|
||||
<gl-icon name="merge-request" class="mr-1 text-secondary" />
|
||||
</svg>
|
||||
<span class="js-items-count">{{ totalCount }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@ import TokenAccess from './components/token_access.vue';
|
|||
Vue.use(VueApollo);
|
||||
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: createDefaultClient(),
|
||||
defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
|
||||
});
|
||||
|
||||
export const initTokenAccess = (containerId = 'js-ci-token-access-app') => {
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
@import './pages/groups';
|
||||
@import './pages/help';
|
||||
@import './pages/issuable';
|
||||
@import './pages/issues/issue_count_badge';
|
||||
@import './pages/issues';
|
||||
@import './pages/labels';
|
||||
@import './pages/login';
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
.issue-count-badge,
|
||||
.mr-count-badge {
|
||||
padding: 5px $gl-padding-8;
|
||||
}
|
||||
|
||||
.issue-count-badge-count,
|
||||
.mr-count-badge-count {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
23
app/services/ci/stuck_builds/drop_running_service.rb
Normal file
23
app/services/ci/stuck_builds/drop_running_service.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Ci
|
||||
module StuckBuilds
|
||||
class DropRunningService
|
||||
include DropHelpers
|
||||
|
||||
BUILD_RUNNING_OUTDATED_TIMEOUT = 1.hour
|
||||
|
||||
def execute
|
||||
Gitlab::AppLogger.info "#{self.class}: Cleaning running, timed-out builds"
|
||||
|
||||
drop(running_timed_out_builds, failure_reason: :stuck_or_timeout_failure)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def running_timed_out_builds
|
||||
Ci::Build.running.updated_at_before(BUILD_RUNNING_OUTDATED_TIMEOUT.ago)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,7 +5,6 @@ module Ci
|
|||
class DropService
|
||||
include DropHelpers
|
||||
|
||||
BUILD_RUNNING_OUTDATED_TIMEOUT = 1.hour
|
||||
BUILD_PENDING_OUTDATED_TIMEOUT = 1.day
|
||||
BUILD_SCHEDULED_OUTDATED_TIMEOUT = 1.hour
|
||||
BUILD_PENDING_STUCK_TIMEOUT = 1.hour
|
||||
|
@ -14,8 +13,6 @@ module Ci
|
|||
def execute
|
||||
Gitlab::AppLogger.info "#{self.class}: Cleaning stuck builds"
|
||||
|
||||
drop(running_timed_out_builds, failure_reason: :stuck_or_timeout_failure)
|
||||
|
||||
drop(
|
||||
pending_builds(BUILD_PENDING_OUTDATED_TIMEOUT.ago),
|
||||
failure_reason: :stuck_or_timeout_failure
|
||||
|
@ -50,13 +47,6 @@ module Ci
|
|||
BUILD_SCHEDULED_OUTDATED_TIMEOUT.ago
|
||||
)
|
||||
end
|
||||
|
||||
def running_timed_out_builds
|
||||
Ci::Build.running.where( # rubocop: disable CodeReuse/ActiveRecord
|
||||
'ci_builds.updated_at < ?',
|
||||
BUILD_RUNNING_OUTDATED_TIMEOUT.ago
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -228,6 +228,15 @@
|
|||
:weight: 1
|
||||
:idempotent: true
|
||||
:tags: []
|
||||
- :name: cronjob:ci_stuck_builds_drop_running
|
||||
:worker_name: Ci::StuckBuilds::DropRunningWorker
|
||||
:feature_category: :continuous_integration
|
||||
:has_external_dependencies:
|
||||
:urgency: :low
|
||||
:resource_boundary: :unknown
|
||||
:weight: 1
|
||||
:idempotent: true
|
||||
:tags: []
|
||||
- :name: cronjob:container_expiration_policy
|
||||
:worker_name: ContainerExpirationPolicyWorker
|
||||
:feature_category: :container_registry
|
||||
|
|
43
app/workers/ci/stuck_builds/drop_running_worker.rb
Normal file
43
app/workers/ci/stuck_builds/drop_running_worker.rb
Normal file
|
@ -0,0 +1,43 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Ci
|
||||
module StuckBuilds
|
||||
class DropRunningWorker
|
||||
include ApplicationWorker
|
||||
|
||||
idempotent!
|
||||
|
||||
# rubocop:disable Scalability/CronWorkerContext
|
||||
# This is an instance-wide cleanup query, so there's no meaningful
|
||||
# scope to consider this in the context of.
|
||||
include CronjobQueue
|
||||
# rubocop:enable Scalability/CronWorkerContext
|
||||
|
||||
data_consistency :always
|
||||
|
||||
feature_category :continuous_integration
|
||||
|
||||
EXCLUSIVE_LEASE_KEY = 'ci_stuck_builds_drop_running_worker_lease'
|
||||
|
||||
def perform
|
||||
return unless try_obtain_lease
|
||||
|
||||
begin
|
||||
Ci::StuckBuilds::DropRunningService.new.execute
|
||||
ensure
|
||||
remove_lease
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def try_obtain_lease
|
||||
@uuid = Gitlab::ExclusiveLease.new(EXCLUSIVE_LEASE_KEY, timeout: 30.minutes).try_obtain
|
||||
end
|
||||
|
||||
def remove_lease
|
||||
Gitlab::ExclusiveLease.cancel(EXCLUSIVE_LEASE_KEY, @uuid)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -17,6 +17,8 @@ class StuckCiJobsWorker # rubocop:disable Scalability/IdempotentWorker
|
|||
EXCLUSIVE_LEASE_KEY = 'stuck_ci_builds_worker_lease'
|
||||
|
||||
def perform
|
||||
Ci::StuckBuilds::DropRunningWorker.perform_in(20.minutes)
|
||||
|
||||
return unless try_obtain_lease
|
||||
|
||||
Ci::StuckBuilds::DropService.new.execute
|
||||
|
|
|
@ -1,15 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
def log_pool_size(db, previous_pool_size, current_pool_size)
|
||||
log_message = ["#{db} connection pool size: #{current_pool_size}"]
|
||||
|
||||
if previous_pool_size && current_pool_size > previous_pool_size
|
||||
log_message << "(increased from #{previous_pool_size} to match thread count)"
|
||||
end
|
||||
|
||||
Gitlab::AppLogger.debug(log_message.join(' '))
|
||||
end
|
||||
|
||||
Gitlab.ee do
|
||||
# We need to initialize the Geo database before
|
||||
# setting the Geo DB connection pool size.
|
||||
|
|
|
@ -252,7 +252,7 @@ graph RL;
|
|||
2_1-1 & 2_1-2 & 2_1-3 & 2_1-4 --> 1-6;
|
||||
end
|
||||
|
||||
2_2-2["rspec frontend_fixture/rspec-ee frontend_fixture (7 minutes)"];
|
||||
2_2-2["rspec-all frontend_fixture (7 minutes)"];
|
||||
class 2_2-2 criticalPath;
|
||||
click 2_2-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910143&udv=0"
|
||||
2_2-4["memory-on-boot (3.5 minutes)"];
|
||||
|
@ -284,7 +284,7 @@ graph RL;
|
|||
3_1-1["jest (14.5 minutes)"];
|
||||
class 3_1-1 criticalPath;
|
||||
click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0"
|
||||
subgraph "Needs `rspec frontend_fixture/rspec-ee frontend_fixture`";
|
||||
subgraph "Needs `rspec-all frontend_fixture`";
|
||||
3_1-1 --> 2_2-2;
|
||||
end
|
||||
|
||||
|
@ -355,7 +355,7 @@ graph RL;
|
|||
2_1-1 & 2_1-2 & 2_1-3 & 2_1-4 --> 1-6;
|
||||
end
|
||||
|
||||
2_2-2["rspec frontend_fixture/rspec-ee frontend_fixture (7 minutes)"];
|
||||
2_2-2["rspec-all frontend_fixture (7 minutes)"];
|
||||
class 2_2-2 criticalPath;
|
||||
click 2_2-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910143&udv=0"
|
||||
2_2-4["memory-on-boot (3.5 minutes)"];
|
||||
|
@ -395,7 +395,7 @@ graph RL;
|
|||
3_1-1["jest (14.5 minutes)"];
|
||||
class 3_1-1 criticalPath;
|
||||
click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0"
|
||||
subgraph "Needs `rspec frontend_fixture/rspec-ee frontend_fixture`";
|
||||
subgraph "Needs `rspec-all frontend_fixture`";
|
||||
3_1-1 --> 2_2-2;
|
||||
end
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ immediately identify which alerts you should prioritize investigating:
|
|||
|
||||
Alerts contain one of the following icons:
|
||||
|
||||
<!-- vale gitlab.SubstitutionWarning = NO -->
|
||||
|
||||
| Severity | Icon | Color (hexadecimal) |
|
||||
|----------|-------------------------|---------------------|
|
||||
| Critical | **{severity-critical}** | `#8b2615` |
|
||||
|
@ -62,6 +64,8 @@ Alerts contain one of the following icons:
|
|||
| Info | **{severity-info}** | `#418cd8` |
|
||||
| Unknown | **{severity-unknown}** | `#bababa` |
|
||||
|
||||
<!-- vale gitlab.SubstitutionWarning = YES -->
|
||||
|
||||
## Alert details page
|
||||
|
||||
Navigate to the Alert details view by visiting the [Alert list](alerts.md)
|
||||
|
|
|
@ -10,7 +10,7 @@ type: reference, howto
|
|||
Coverage-guided fuzzing sends random inputs to an instrumented version of your application in an
|
||||
effort to cause unexpected behavior. Such behavior indicates a bug that you should address.
|
||||
GitLab allows you to add coverage-guided fuzz testing to your pipelines. This helps you discover
|
||||
bugs and potential security issues that other QA processes may miss.
|
||||
bugs and potential security issues that other QA processes may miss.
|
||||
|
||||
We recommend that you use fuzz testing in addition to the other security scanners in [GitLab Secure](../index.md)
|
||||
and your own test processes. If you're using [GitLab CI/CD](../../../ci/index.md),
|
||||
|
@ -248,6 +248,8 @@ which shows an overview of all the security vulnerabilities in your groups, proj
|
|||
Clicking the vulnerability opens a modal that provides additional information about the
|
||||
vulnerability:
|
||||
|
||||
<!-- vale gitlab.Acronyms = NO -->
|
||||
|
||||
- Status: The vulnerability's status. As with any type of vulnerability, a coverage fuzzing
|
||||
vulnerability can be Detected, Confirmed, Dismissed, or Resolved.
|
||||
- Project: The project in which the vulnerability exists.
|
||||
|
@ -261,3 +263,5 @@ vulnerability:
|
|||
- Scanner: The scanner that detected the vulnerability (for example, Coverage Fuzzing).
|
||||
- Scanner Provider: The engine that did the scan. For Coverage Fuzzing, this can be any of the
|
||||
engines listed in [Supported fuzzing engines and languages](#supported-fuzzing-engines-and-languages).
|
||||
|
||||
<!-- vale gitlab.Acronyms = YES -->
|
||||
|
|
|
@ -27,6 +27,8 @@ analysis are available in the [security dashboards](../security_dashboard/index.
|
|||
|
||||
The results are sorted by the priority of the vulnerability:
|
||||
|
||||
<!-- vale gitlab.SubstitutionWarning = NO -->
|
||||
|
||||
1. Critical
|
||||
1. High
|
||||
1. Medium
|
||||
|
@ -34,6 +36,8 @@ The results are sorted by the priority of the vulnerability:
|
|||
1. Info
|
||||
1. Unknown
|
||||
|
||||
<!-- vale gitlab.SubstitutionWarning = YES -->
|
||||
|
||||
A pipeline consists of multiple jobs, including SAST and DAST scanning. If any job fails to finish
|
||||
for any reason, the security dashboard does not show SAST scanner output. For example, if the SAST
|
||||
job finishes but the DAST job fails, the security dashboard does not show SAST results. On failure,
|
||||
|
|
|
@ -45,6 +45,8 @@ From the Vulnerability Report you can:
|
|||
|
||||
You can filter the vulnerabilities table by:
|
||||
|
||||
<!-- vale gitlab.SubstitutionWarning = NO -->
|
||||
|
||||
| Filter | Available options |
|
||||
|:---------|:------------------|
|
||||
| Status | Detected, Confirmed, Dismissed, Resolved. |
|
||||
|
@ -53,6 +55,8 @@ You can filter the vulnerabilities table by:
|
|||
| Project | For more details, see [Project filter](#project-filter). |
|
||||
| Activity | For more details, see [Activity filter](#activity-filter). |
|
||||
|
||||
<!-- vale gitlab.SubstitutionWarning = YES -->
|
||||
|
||||
### Filter the list of vulnerabilities
|
||||
|
||||
To filter the list of vulnerabilities:
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
---
|
||||
type: reference, howto
|
||||
stage: Manage
|
||||
group: Import
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
|
@ -10,30 +9,30 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
Import your projects from Gitea to GitLab with minimal effort.
|
||||
|
||||
NOTE:
|
||||
This requires Gitea `v1.0.0` or newer.
|
||||
This requires Gitea `v1.0.0` or later.
|
||||
|
||||
The Gitea importer can import:
|
||||
|
||||
- Repository description (GitLab 8.15+)
|
||||
- Git repository data (GitLab 8.15+)
|
||||
- Issues (GitLab 8.15+)
|
||||
- Pull requests (GitLab 8.15+)
|
||||
- Milestones (GitLab 8.15+)
|
||||
- Labels (GitLab 8.15+)
|
||||
- Repository description
|
||||
- Git repository data
|
||||
- Issues
|
||||
- Pull requests
|
||||
- Milestones
|
||||
- Labels
|
||||
|
||||
When importing, repository public access is retained. If a repository is private in Gitea, it's
|
||||
created as private in GitLab as well.
|
||||
|
||||
## How it works
|
||||
|
||||
Since Gitea is currently not an OAuth provider, author/assignee cannot be mapped
|
||||
to users in your GitLab instance. This means that the project creator (most of
|
||||
the times the current user that started the import process) is set as the author,
|
||||
but a reference on the issue about the original Gitea author is kept.
|
||||
Because Gitea isn't an OAuth provider, author/assignee can't be mapped to users
|
||||
in your GitLab instance. This means the project creator (usually the user that
|
||||
started the import process) is set as the author. A reference, however, is kept
|
||||
on the issue about the original Gitea author.
|
||||
|
||||
The importer creates any new namespaces (groups) if they don't exist or in
|
||||
the case the namespace is taken, the repository is imported under the user's
|
||||
namespace that started the import process.
|
||||
The importer creates any new namespaces (groups) if they don't exist. If the
|
||||
namespace is taken, the repository is imported under the user's namespace
|
||||
that started the import process.
|
||||
|
||||
## Import your Gitea repositories
|
||||
|
||||
|
@ -41,7 +40,7 @@ The importer page is visible when you create a new project.
|
|||
|
||||
![New project page on GitLab](img/import_projects_from_new_project_page.png)
|
||||
|
||||
Click the **Gitea** link and the import authorization process starts.
|
||||
Select the **Gitea** link to start the import authorization process.
|
||||
|
||||
![New Gitea project import](img/import_projects_from_gitea_new_import.png)
|
||||
|
||||
|
@ -52,13 +51,13 @@ GitLab access your repositories:
|
|||
|
||||
1. Go to `https://your-gitea-instance/user/settings/applications` (replace
|
||||
`your-gitea-instance` with the host of your Gitea instance).
|
||||
1. Click **Generate New Token**.
|
||||
1. Select **Generate New Token**.
|
||||
1. Enter a token description.
|
||||
1. Click **Generate Token**.
|
||||
1. Select **Generate Token**.
|
||||
1. Copy the token hash.
|
||||
1. Go back to GitLab and provide the token to the Gitea importer.
|
||||
1. Hit the **List Your Gitea Repositories** button and wait while GitLab reads
|
||||
your repositories' information. Once done, you are taken to the importer
|
||||
1. Select **List Your Gitea Repositories** and wait while GitLab reads
|
||||
your repositories' information. After it's done, GitLab displays the importer
|
||||
page to select the repositories to import.
|
||||
|
||||
### Select which repositories to import
|
||||
|
@ -66,19 +65,19 @@ GitLab access your repositories:
|
|||
After you've authorized access to your Gitea repositories, you are
|
||||
redirected to the Gitea importer page.
|
||||
|
||||
From there, you can see the import statuses of your Gitea repositories.
|
||||
From there, you can view the import statuses of your Gitea repositories:
|
||||
|
||||
- Those that are being imported show a _started_ status,
|
||||
- those already successfully imported are green with a _done_ status,
|
||||
- whereas those that are not yet imported have an **Import** button on the
|
||||
- Those that are being imported show a _started_ status.
|
||||
- Those already successfully imported are green with a _done_ status.
|
||||
- Those that aren't yet imported have an **Import** button on the
|
||||
right side of the table.
|
||||
|
||||
You also can:
|
||||
|
||||
- Import all your Gitea projects in one go by hitting **Import all projects** in
|
||||
the upper left corner.
|
||||
- Filter projects by name. If filter is applied, hitting **Import all projects**
|
||||
only imports matched projects.
|
||||
- Import all of your Gitea projects in one go by selecting **Import all projects**
|
||||
in the upper left corner.
|
||||
- Filter projects by name. If filter is applied, selecting **Import all projects**
|
||||
imports only matched projects.
|
||||
|
||||
![Gitea importer page](img/import_projects_from_gitea_importer_v12_3.png)
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@
|
|||
"@babel/preset-env": "^7.10.1",
|
||||
"@gitlab/at.js": "1.5.7",
|
||||
"@gitlab/favicon-overlay": "2.0.0",
|
||||
"@gitlab/svgs": "1.212.0",
|
||||
"@gitlab/svgs": "1.213.0",
|
||||
"@gitlab/tributejs": "1.0.0",
|
||||
"@gitlab/ui": "32.11.4",
|
||||
"@gitlab/ui": "32.12.0",
|
||||
"@gitlab/visual-review-tools": "1.6.1",
|
||||
"@rails/actioncable": "6.1.3-2",
|
||||
"@rails/ujs": "6.1.3-2",
|
||||
|
|
|
@ -58,8 +58,8 @@ module QA
|
|||
testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1806',
|
||||
issue_1: 'https://gitlab.com/gitlab-org/gitlab/-/issues/331252',
|
||||
issue_2: 'https://gitlab.com/gitlab-org/gitlab/-/issues/333678',
|
||||
# mostly impacts testing as it makes small groups import slower
|
||||
issue_3: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332351'
|
||||
issue_3: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332351',
|
||||
except: { job: 'instance-image-slow-network' }
|
||||
) do
|
||||
Page::Group::BulkImport.perform do |import_page|
|
||||
import_page.import_group(imported_group.path, imported_group.sandbox.path)
|
||||
|
|
|
@ -109,14 +109,18 @@ function rspec_paralellized_job() {
|
|||
local test_level="${job_name[1]}"
|
||||
local report_name=$(echo "${CI_JOB_NAME}" | sed -E 's|[/ ]|_|g') # e.g. 'rspec unit pg12 1/24' would become 'rspec_unit_pg12_1_24'
|
||||
local rspec_opts="${1}"
|
||||
local spec_folder_prefix=""
|
||||
local spec_folder_prefixes=""
|
||||
|
||||
if [[ "${test_tool}" =~ "-ee" ]]; then
|
||||
spec_folder_prefix="ee/"
|
||||
spec_folder_prefixes="'ee/'"
|
||||
fi
|
||||
|
||||
if [[ "${test_tool}" =~ "-jh" ]]; then
|
||||
spec_folder_prefix="jh/"
|
||||
spec_folder_prefixes="'jh/'"
|
||||
fi
|
||||
|
||||
if [[ "${test_tool}" =~ "-all" ]]; then
|
||||
spec_folder_prefixes="['', 'ee/']"
|
||||
fi
|
||||
|
||||
export KNAPSACK_LOG_LEVEL="debug"
|
||||
|
@ -131,7 +135,7 @@ function rspec_paralellized_job() {
|
|||
cp "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" "${KNAPSACK_REPORT_PATH}"
|
||||
|
||||
if [[ -z "${KNAPSACK_TEST_FILE_PATTERN}" ]]; then
|
||||
pattern=$(ruby -r./tooling/quality/test_level.rb -e "puts Quality::TestLevel.new(%(${spec_folder_prefix})).pattern(:${test_level})")
|
||||
pattern=$(ruby -r./tooling/quality/test_level.rb -e "puts Quality::TestLevel.new(${spec_folder_prefixes}).pattern(:${test_level})")
|
||||
export KNAPSACK_TEST_FILE_PATTERN="${pattern}"
|
||||
fi
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ RSpec.describe 'Issue Boards new issue', :js do
|
|||
|
||||
wait_for_requests
|
||||
|
||||
page.within(first('.board .issue-count-badge-count')) do
|
||||
page.within(first('.board [data-testid="issue-count-badge"]')) do
|
||||
expect(page).to have_content('1')
|
||||
end
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ RSpec.describe 'Ensure Boards do not show stale data on browser back', :js do
|
|||
visit project_board_path(project, board)
|
||||
wait_for_requests
|
||||
|
||||
page.within(first('.board .issue-count-badge-count')) do
|
||||
page.within(first('.board [data-testid="issue-count-badge"]')) do
|
||||
expect(page).to have_content('0')
|
||||
end
|
||||
end
|
||||
|
@ -35,7 +35,7 @@ RSpec.describe 'Ensure Boards do not show stale data on browser back', :js do
|
|||
page.go_back
|
||||
wait_for_requests
|
||||
|
||||
page.within(first('.board .issue-count-badge-count')) do
|
||||
page.within(first('.board [data-testid="issue-count-badge"]')) do
|
||||
expect(page).to have_content('1')
|
||||
end
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ RSpec.describe 'Group Boards' do
|
|||
it 'adds an issue to the backlog' do
|
||||
page.within(find('.board', match: :first)) do
|
||||
issue_title = 'New Issue'
|
||||
find(:css, '.issue-count-badge-add-button').click
|
||||
click_button 'New issue'
|
||||
|
||||
wait_for_requests
|
||||
|
||||
|
|
|
@ -41,13 +41,13 @@ RSpec.describe 'Related issues', :js do
|
|||
visit project_issue_path(project, issue)
|
||||
|
||||
expect(page).to have_css('.related-issues-block')
|
||||
expect(page).not_to have_selector('.js-issue-count-badge-add-button')
|
||||
expect(page).not_to have_button 'Add a related issue'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when logged in but not a member' do
|
||||
before do
|
||||
gitlab_sign_in(user)
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
it 'shows widget when internal project' do
|
||||
|
@ -57,7 +57,7 @@ RSpec.describe 'Related issues', :js do
|
|||
visit project_issue_path(project, issue)
|
||||
|
||||
expect(page).to have_css('.related-issues-block')
|
||||
expect(page).not_to have_selector('.js-issue-count-badge-add-button')
|
||||
expect(page).not_to have_button 'Add a related issue'
|
||||
end
|
||||
|
||||
it 'does not show widget when private project' do
|
||||
|
@ -76,7 +76,7 @@ RSpec.describe 'Related issues', :js do
|
|||
visit project_issue_path(project, issue)
|
||||
|
||||
expect(page).to have_css('.related-issues-block')
|
||||
expect(page).not_to have_selector('.js-issue-count-badge-add-button')
|
||||
expect(page).not_to have_button 'Add a related issue'
|
||||
end
|
||||
|
||||
it 'shows widget on their own public issue' do
|
||||
|
@ -86,13 +86,13 @@ RSpec.describe 'Related issues', :js do
|
|||
visit project_issue_path(project, issue)
|
||||
|
||||
expect(page).to have_css('.related-issues-block')
|
||||
expect(page).not_to have_selector('.js-issue-count-badge-add-button')
|
||||
expect(page).not_to have_button 'Add a related issue'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when logged in and a guest' do
|
||||
before do
|
||||
gitlab_sign_in(user)
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
it 'shows widget when internal project' do
|
||||
|
@ -103,7 +103,7 @@ RSpec.describe 'Related issues', :js do
|
|||
visit project_issue_path(project, issue)
|
||||
|
||||
expect(page).to have_css('.related-issues-block')
|
||||
expect(page).not_to have_selector('.js-issue-count-badge-add-button')
|
||||
expect(page).not_to have_button 'Add a related issue'
|
||||
end
|
||||
|
||||
it 'shows widget when private project' do
|
||||
|
@ -114,7 +114,7 @@ RSpec.describe 'Related issues', :js do
|
|||
visit project_issue_path(project, issue)
|
||||
|
||||
expect(page).to have_css('.related-issues-block')
|
||||
expect(page).not_to have_selector('.js-issue-count-badge-add-button')
|
||||
expect(page).not_to have_button 'Add a related issue'
|
||||
end
|
||||
|
||||
it 'shows widget when public project' do
|
||||
|
@ -125,13 +125,13 @@ RSpec.describe 'Related issues', :js do
|
|||
visit project_issue_path(project, issue)
|
||||
|
||||
expect(page).to have_css('.related-issues-block')
|
||||
expect(page).not_to have_selector('.js-issue-count-badge-add-button')
|
||||
expect(page).not_to have_button 'Add a related issue'
|
||||
end
|
||||
end
|
||||
|
||||
context 'when logged in and a reporter' do
|
||||
before do
|
||||
gitlab_sign_in(user)
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
it 'shows widget when internal project' do
|
||||
|
@ -142,7 +142,7 @@ RSpec.describe 'Related issues', :js do
|
|||
visit project_issue_path(project, issue)
|
||||
|
||||
expect(page).to have_css('.related-issues-block')
|
||||
expect(page).to have_selector('.js-issue-count-badge-add-button')
|
||||
expect(page).to have_button 'Add a related issue'
|
||||
end
|
||||
|
||||
it 'shows widget when private project' do
|
||||
|
@ -153,7 +153,7 @@ RSpec.describe 'Related issues', :js do
|
|||
visit project_issue_path(project, issue)
|
||||
|
||||
expect(page).to have_css('.related-issues-block')
|
||||
expect(page).to have_selector('.js-issue-count-badge-add-button')
|
||||
expect(page).to have_button 'Add a related issue'
|
||||
end
|
||||
|
||||
it 'shows widget when public project' do
|
||||
|
@ -164,7 +164,7 @@ RSpec.describe 'Related issues', :js do
|
|||
visit project_issue_path(project, issue)
|
||||
|
||||
expect(page).to have_css('.related-issues-block')
|
||||
expect(page).to have_selector('.js-issue-count-badge-add-button')
|
||||
expect(page).to have_button 'Add a related issue'
|
||||
end
|
||||
|
||||
it 'shows widget on their own public issue' do
|
||||
|
@ -175,7 +175,7 @@ RSpec.describe 'Related issues', :js do
|
|||
visit project_issue_path(project, issue)
|
||||
|
||||
expect(page).to have_css('.related-issues-block')
|
||||
expect(page).to have_selector('.js-issue-count-badge-add-button')
|
||||
expect(page).to have_button 'Add a related issue'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -186,7 +186,7 @@ RSpec.describe 'Related issues', :js do
|
|||
|
||||
before do
|
||||
project.add_guest(user)
|
||||
gitlab_sign_in(user)
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
context 'visiting some issue someone else created' do
|
||||
|
@ -216,7 +216,7 @@ RSpec.describe 'Related issues', :js do
|
|||
before do
|
||||
project.add_maintainer(user)
|
||||
project_b.add_maintainer(user)
|
||||
gitlab_sign_in(user)
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
context 'without existing related issues' do
|
||||
|
@ -230,7 +230,7 @@ RSpec.describe 'Related issues', :js do
|
|||
end
|
||||
|
||||
it 'add related issue' do
|
||||
find('.js-issue-count-badge-add-button').click
|
||||
click_button 'Add a related issue'
|
||||
find('.js-add-issuable-form-input').set "#{issue_b.to_reference(project)} "
|
||||
find('.js-add-issuable-form-add-button').click
|
||||
|
||||
|
@ -247,7 +247,7 @@ RSpec.describe 'Related issues', :js do
|
|||
end
|
||||
|
||||
it 'add cross-project related issue' do
|
||||
find('.js-issue-count-badge-add-button').click
|
||||
click_button 'Add a related issue'
|
||||
find('.js-add-issuable-form-input').set "#{issue_project_b_a.to_reference(project)} "
|
||||
find('.js-add-issuable-form-add-button').click
|
||||
|
||||
|
@ -261,7 +261,7 @@ RSpec.describe 'Related issues', :js do
|
|||
end
|
||||
|
||||
it 'pressing enter should submit the form' do
|
||||
find('.js-issue-count-badge-add-button').click
|
||||
click_button 'Add a related issue'
|
||||
find('.js-add-issuable-form-input').set "#{issue_project_b_a.to_reference(project)} "
|
||||
find('.js-add-issuable-form-input').native.send_key(:enter)
|
||||
|
||||
|
@ -275,7 +275,7 @@ RSpec.describe 'Related issues', :js do
|
|||
end
|
||||
|
||||
it 'disallows duplicate entries' do
|
||||
find('.js-issue-count-badge-add-button').click
|
||||
click_button 'Add a related issue'
|
||||
find('.js-add-issuable-form-input').set 'duplicate duplicate duplicate'
|
||||
|
||||
items = all('.js-add-issuable-form-token-list-item')
|
||||
|
@ -288,7 +288,7 @@ RSpec.describe 'Related issues', :js do
|
|||
|
||||
it 'allows us to remove pending issues' do
|
||||
# Tests against https://gitlab.com/gitlab-org/gitlab/issues/11625
|
||||
find('.js-issue-count-badge-add-button').click
|
||||
click_button 'Add a related issue'
|
||||
find('.js-add-issuable-form-input').set 'issue1 issue2 issue3 '
|
||||
|
||||
items = all('.js-add-issuable-form-token-list-item')
|
||||
|
@ -351,7 +351,7 @@ RSpec.describe 'Related issues', :js do
|
|||
end
|
||||
|
||||
it 'add related issue' do
|
||||
find('.js-issue-count-badge-add-button').click
|
||||
click_button 'Add a related issue'
|
||||
find('.js-add-issuable-form-input').set "##{issue_d.iid} "
|
||||
find('.js-add-issuable-form-add-button').click
|
||||
|
||||
|
@ -367,7 +367,7 @@ RSpec.describe 'Related issues', :js do
|
|||
end
|
||||
|
||||
it 'add invalid related issue' do
|
||||
find('.js-issue-count-badge-add-button').click
|
||||
click_button 'Add a related issue'
|
||||
find('.js-add-issuable-form-input').set "#9999999 "
|
||||
find('.js-add-issuable-form-add-button').click
|
||||
|
||||
|
@ -382,7 +382,7 @@ RSpec.describe 'Related issues', :js do
|
|||
end
|
||||
|
||||
it 'add unauthorized related issue' do
|
||||
find('.js-issue-count-badge-add-button').click
|
||||
click_button 'Add a related issue'
|
||||
find('.js-add-issuable-form-input').set "#{issue_project_unauthorized_a.to_reference(project)} "
|
||||
find('.js-add-issuable-form-add-button').click
|
||||
|
||||
|
|
65
spec/services/ci/stuck_builds/drop_running_service_spec.rb
Normal file
65
spec/services/ci/stuck_builds/drop_running_service_spec.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Ci::StuckBuilds::DropRunningService do
|
||||
let!(:runner) { create :ci_runner }
|
||||
let!(:job) { create :ci_build, runner: runner }
|
||||
let(:created_at) { }
|
||||
let(:updated_at) { }
|
||||
|
||||
subject(:service) { described_class.new }
|
||||
|
||||
before do
|
||||
job_attributes = { status: status }
|
||||
job_attributes[:created_at] = created_at if created_at
|
||||
job_attributes[:updated_at] = updated_at if updated_at
|
||||
job.update!(job_attributes)
|
||||
end
|
||||
|
||||
context 'when job is running' do
|
||||
let(:status) { 'running' }
|
||||
|
||||
context 'when job was updated_at more than an hour ago' do
|
||||
let(:updated_at) { 2.hours.ago }
|
||||
|
||||
it_behaves_like 'job is dropped'
|
||||
end
|
||||
|
||||
context 'when job was updated in less than 1 hour ago' do
|
||||
let(:updated_at) { 30.minutes.ago }
|
||||
|
||||
it_behaves_like 'job is unchanged'
|
||||
end
|
||||
end
|
||||
|
||||
%w(success skipped failed canceled scheduled pending).each do |status|
|
||||
context "when job is #{status}" do
|
||||
let(:status) { status }
|
||||
let(:updated_at) { 2.days.ago }
|
||||
|
||||
context 'when created_at is the same as updated_at' do
|
||||
let(:created_at) { 2.days.ago }
|
||||
|
||||
it_behaves_like 'job is unchanged'
|
||||
end
|
||||
|
||||
context 'when created_at is before updated_at' do
|
||||
let(:created_at) { 3.days.ago }
|
||||
|
||||
it_behaves_like 'job is unchanged'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'for deleted project' do
|
||||
let(:status) { 'running' }
|
||||
let(:updated_at) { 2.days.ago }
|
||||
|
||||
before do
|
||||
job.project.update!(pending_delete: true)
|
||||
end
|
||||
|
||||
it_behaves_like 'job is dropped'
|
||||
end
|
||||
end
|
|
@ -17,48 +17,6 @@ RSpec.describe Ci::StuckBuilds::DropService do
|
|||
job.update!(job_attributes)
|
||||
end
|
||||
|
||||
shared_examples 'job is dropped' do
|
||||
it 'changes status' do
|
||||
expect(service).to receive(:drop).exactly(3).times.and_call_original
|
||||
expect(service).to receive(:drop_stuck).exactly(:once).and_call_original
|
||||
|
||||
service.execute
|
||||
job.reload
|
||||
|
||||
expect(job).to be_failed
|
||||
expect(job).to be_stuck_or_timeout_failure
|
||||
end
|
||||
|
||||
context 'when job have data integrity problem' do
|
||||
it "does drop the job and logs the reason" do
|
||||
job.update_columns(yaml_variables: '[{"key" => "value"}]')
|
||||
|
||||
expect(Gitlab::ErrorTracking).to receive(:track_exception)
|
||||
.with(anything, a_hash_including(build_id: job.id))
|
||||
.once
|
||||
.and_call_original
|
||||
|
||||
service.execute
|
||||
job.reload
|
||||
|
||||
expect(job).to be_failed
|
||||
expect(job).to be_data_integrity_failure
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'job is unchanged' do
|
||||
it 'does not change status' do
|
||||
expect(service).to receive(:drop).exactly(3).times.and_call_original
|
||||
expect(service).to receive(:drop_stuck).exactly(:once).and_call_original
|
||||
|
||||
service.execute
|
||||
job.reload
|
||||
|
||||
expect(job.status).to eq(status)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when job is pending' do
|
||||
let(:status) { 'pending' }
|
||||
|
||||
|
@ -195,7 +153,7 @@ RSpec.describe Ci::StuckBuilds::DropService do
|
|||
context 'when job was updated_at more than an hour ago' do
|
||||
let(:updated_at) { 2.hours.ago }
|
||||
|
||||
it_behaves_like 'job is dropped'
|
||||
it_behaves_like 'job is unchanged'
|
||||
end
|
||||
|
||||
context 'when job was updated in less than 1 hour ago' do
|
||||
|
@ -238,7 +196,7 @@ RSpec.describe Ci::StuckBuilds::DropService do
|
|||
job.project.update!(pending_delete: true)
|
||||
end
|
||||
|
||||
it_behaves_like 'job is dropped'
|
||||
it_behaves_like 'job is unchanged'
|
||||
end
|
||||
|
||||
describe 'drop stale scheduled builds' do
|
||||
|
|
|
@ -71,7 +71,7 @@ module FeatureFlagHelpers
|
|||
end
|
||||
|
||||
def add_linked_issue_button
|
||||
find('.js-issue-count-badge-add-button')
|
||||
find_button 'Add a related issue'
|
||||
end
|
||||
|
||||
def remove_linked_issue_button
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.shared_examples 'job is dropped' do
|
||||
it 'changes status' do
|
||||
service.execute
|
||||
job.reload
|
||||
|
||||
expect(job).to be_failed
|
||||
expect(job).to be_stuck_or_timeout_failure
|
||||
end
|
||||
|
||||
context 'when job has data integrity problem' do
|
||||
it 'drops the job and logs the reason' do
|
||||
job.update_columns(yaml_variables: '[{"key" => "value"}]')
|
||||
|
||||
expect(Gitlab::ErrorTracking)
|
||||
.to receive(:track_exception)
|
||||
.with(anything, a_hash_including(build_id: job.id))
|
||||
.once
|
||||
.and_call_original
|
||||
|
||||
service.execute
|
||||
job.reload
|
||||
|
||||
expect(job).to be_failed
|
||||
expect(job).to be_data_integrity_failure
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'job is unchanged' do
|
||||
it 'does not change status' do
|
||||
service.execute
|
||||
job.reload
|
||||
|
||||
expect(job.status).to eq(status)
|
||||
end
|
||||
end
|
|
@ -63,7 +63,14 @@ RSpec.describe Quality::TestLevel do
|
|||
context 'with a prefix' do
|
||||
it 'returns a pattern' do
|
||||
expect(described_class.new('ee/').pattern(:system))
|
||||
.to eq("ee/spec/{features}{,/**/}*_spec.rb")
|
||||
.to eq("{ee/}spec/{features}{,/**/}*_spec.rb")
|
||||
end
|
||||
end
|
||||
|
||||
context 'with several prefixes' do
|
||||
it 'returns a pattern' do
|
||||
expect(described_class.new(['', 'ee/', 'jh/']).pattern(:system))
|
||||
.to eq("{,ee/,jh/}spec/{features}{,/**/}*_spec.rb")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -138,7 +145,14 @@ RSpec.describe Quality::TestLevel do
|
|||
context 'with a prefix' do
|
||||
it 'returns a regexp' do
|
||||
expect(described_class.new('ee/').regexp(:system))
|
||||
.to eq(%r{ee/spec/(features)})
|
||||
.to eq(%r{(ee/)spec/(features)})
|
||||
end
|
||||
end
|
||||
|
||||
context 'with several prefixes' do
|
||||
it 'returns a regexp' do
|
||||
expect(described_class.new(['', 'ee/', 'jh/']).regexp(:system))
|
||||
.to eq(%r{(|ee/|jh/)spec/(features)})
|
||||
end
|
||||
end
|
||||
|
||||
|
|
70
spec/workers/ci/stuck_builds/drop_running_worker_spec.rb
Normal file
70
spec/workers/ci/stuck_builds/drop_running_worker_spec.rb
Normal file
|
@ -0,0 +1,70 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Ci::StuckBuilds::DropRunningWorker do
|
||||
include ExclusiveLeaseHelpers
|
||||
|
||||
let(:worker_lease_key) { Ci::StuckBuilds::DropRunningWorker::EXCLUSIVE_LEASE_KEY }
|
||||
let(:worker_lease_uuid) { SecureRandom.uuid }
|
||||
let(:worker2) { described_class.new }
|
||||
|
||||
subject(:worker) { described_class.new }
|
||||
|
||||
before do
|
||||
stub_exclusive_lease(worker_lease_key, worker_lease_uuid)
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
it_behaves_like 'an idempotent worker'
|
||||
|
||||
it 'executes an instance of Ci::StuckBuilds::DropRunningService' do
|
||||
expect_next_instance_of(Ci::StuckBuilds::DropRunningService) do |service|
|
||||
expect(service).to receive(:execute).exactly(:once)
|
||||
end
|
||||
|
||||
worker.perform
|
||||
end
|
||||
|
||||
context 'with an exclusive lease' do
|
||||
it 'does not execute concurrently' do
|
||||
expect(worker).to receive(:remove_lease).exactly(:once)
|
||||
expect(worker2).not_to receive(:remove_lease)
|
||||
|
||||
worker.perform
|
||||
|
||||
stub_exclusive_lease_taken(worker_lease_key)
|
||||
|
||||
worker2.perform
|
||||
end
|
||||
|
||||
it 'can execute in sequence' do
|
||||
expect(worker).to receive(:remove_lease).at_least(:once)
|
||||
expect(worker2).to receive(:remove_lease).at_least(:once)
|
||||
|
||||
worker.perform
|
||||
worker2.perform
|
||||
end
|
||||
|
||||
it 'cancels exclusive leases after worker perform' do
|
||||
expect_to_cancel_exclusive_lease(worker_lease_key, worker_lease_uuid)
|
||||
|
||||
worker.perform
|
||||
end
|
||||
|
||||
context 'when the DropRunningService fails' do
|
||||
it 'ensures cancellation of the exclusive lease' do
|
||||
expect_to_cancel_exclusive_lease(worker_lease_key, worker_lease_uuid)
|
||||
|
||||
allow_next_instance_of(Ci::StuckBuilds::DropRunningService) do |service|
|
||||
allow(service).to receive(:execute) do
|
||||
raise 'The query timed out'
|
||||
end
|
||||
end
|
||||
|
||||
expect { worker.perform }.to raise_error(/The query timed out/)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -16,7 +16,13 @@ RSpec.describe StuckCiJobsWorker do
|
|||
end
|
||||
|
||||
describe '#perform' do
|
||||
it 'executes an instance of Ci::StuckBuildsDropService' do
|
||||
it 'enqueues a Ci::StuckBuilds::DropRunningWorker job' do
|
||||
expect(Ci::StuckBuilds::DropRunningWorker).to receive(:perform_in).with(20.minutes).exactly(:once)
|
||||
|
||||
worker.perform
|
||||
end
|
||||
|
||||
it 'executes an instance of Ci::StuckBuilds::DropService' do
|
||||
expect_next_instance_of(Ci::StuckBuilds::DropService) do |service|
|
||||
expect(service).to receive(:execute).exactly(:once)
|
||||
end
|
||||
|
|
|
@ -60,20 +60,20 @@ module Quality
|
|||
system: ['features']
|
||||
}.freeze
|
||||
|
||||
attr_reader :prefix
|
||||
attr_reader :prefixes
|
||||
|
||||
def initialize(prefix = nil)
|
||||
@prefix = prefix
|
||||
def initialize(prefixes = nil)
|
||||
@prefixes = Array(prefixes)
|
||||
@patterns = {}
|
||||
@regexps = {}
|
||||
end
|
||||
|
||||
def pattern(level)
|
||||
@patterns[level] ||= "#{prefix}spec/#{folders_pattern(level)}{,/**/}*#{suffix(level)}"
|
||||
@patterns[level] ||= "#{prefixes_for_pattern}spec/#{folders_pattern(level)}{,/**/}*#{suffix(level)}"
|
||||
end
|
||||
|
||||
def regexp(level)
|
||||
@regexps[level] ||= Regexp.new("#{prefix}spec/#{folders_regex(level)}").freeze
|
||||
@regexps[level] ||= Regexp.new("#{prefixes_for_regex}spec/#{folders_regex(level)}").freeze
|
||||
end
|
||||
|
||||
def level_for(file_path)
|
||||
|
@ -102,6 +102,20 @@ module Quality
|
|||
|
||||
private
|
||||
|
||||
def prefixes_for_pattern
|
||||
return '' if prefixes.empty?
|
||||
|
||||
"{#{prefixes.join(',')}}"
|
||||
end
|
||||
|
||||
def prefixes_for_regex
|
||||
return '' if prefixes.empty?
|
||||
|
||||
regex_prefix = prefixes.map(&Regexp.method(:escape)).join('|')
|
||||
|
||||
"(#{regex_prefix})"
|
||||
end
|
||||
|
||||
def suffix(level)
|
||||
case level
|
||||
when :frontend_fixture
|
||||
|
|
16
yarn.lock
16
yarn.lock
|
@ -964,20 +964,20 @@
|
|||
stylelint-declaration-strict-value "1.7.7"
|
||||
stylelint-scss "3.18.0"
|
||||
|
||||
"@gitlab/svgs@1.212.0":
|
||||
version "1.212.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.212.0.tgz#21a5df04c52b10cc1b8521cd8ff7c7d6d13716db"
|
||||
integrity sha512-dv0bYTHA3hwi3mNU3bGMq1cd4HVKKFNwCNPgkF91JSp4Xt8DDtJ0Yq4X49ASsq4zCJ3odgkq2aPjEa/Sr5nINQ==
|
||||
"@gitlab/svgs@1.213.0":
|
||||
version "1.213.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.213.0.tgz#fcd9794049d2b15f5796dbab2a3d501679153582"
|
||||
integrity sha512-3d9EGpEkPDeW92Xx3FueFCJFZ/yL+uv5MWCUHmSt1tP9YmUhMXw/51c43c5+V17FuCyvhJS5tm3aEg3VYoWIRA==
|
||||
|
||||
"@gitlab/tributejs@1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
|
||||
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
|
||||
|
||||
"@gitlab/ui@32.11.4":
|
||||
version "32.11.4"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.11.4.tgz#ead781c4fd57b4f7bc6818de99e56d023f94c397"
|
||||
integrity sha512-plxOvtAIo+PIng1jBssj/QCx2ATIbZqQvLvCeezgAABgY107XhqZDw50VZL0texTX+0jGwB5PaXthmU/wnCk2w==
|
||||
"@gitlab/ui@32.12.0":
|
||||
version "32.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.12.0.tgz#a2e45a7587beb2b9a5014f36c10bac30e6f90f78"
|
||||
integrity sha512-WP7uyf8Ujd2ONOIYLG6s3oIl8/IWpI2H12r7rwNG+yD8EOhvHdK8QS9+b5gpAewYJjT4r2AV8m9QJXZChmmO6w==
|
||||
dependencies:
|
||||
"@babel/standalone" "^7.0.0"
|
||||
bootstrap-vue "2.18.1"
|
||||
|
|
Loading…
Reference in a new issue