Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
27c4555a42
commit
9c1284626f
25 changed files with 185 additions and 76 deletions
|
@ -381,7 +381,8 @@ export default {
|
||||||
dir="auto"
|
dir="auto"
|
||||||
:disabled="isSubmitting"
|
:disabled="isSubmitting"
|
||||||
name="note[note]"
|
name="note[note]"
|
||||||
class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area qa-comment-input"
|
class="note-textarea js-vue-comment-form js-note-text js-gfm-input js-autosize markdown-area"
|
||||||
|
data-qa-selector="comment_field"
|
||||||
data-supports-quick-actions="true"
|
data-supports-quick-actions="true"
|
||||||
:aria-label="__('Description')"
|
:aria-label="__('Description')"
|
||||||
:placeholder="__('Write a comment or drag your files here…')"
|
:placeholder="__('Write a comment or drag your files here…')"
|
||||||
|
@ -426,7 +427,8 @@ export default {
|
||||||
>
|
>
|
||||||
<gl-button
|
<gl-button
|
||||||
:disabled="isSubmitButtonDisabled"
|
:disabled="isSubmitButtonDisabled"
|
||||||
class="js-comment-button js-comment-submit-button qa-comment-button"
|
class="js-comment-button js-comment-submit-button"
|
||||||
|
data-qa-selector="comment_button"
|
||||||
type="submit"
|
type="submit"
|
||||||
category="primary"
|
category="primary"
|
||||||
variant="success"
|
variant="success"
|
||||||
|
@ -440,7 +442,8 @@ export default {
|
||||||
name="button"
|
name="button"
|
||||||
category="primary"
|
category="primary"
|
||||||
variant="success"
|
variant="success"
|
||||||
class="note-type-toggle js-note-new-discussion dropdown-toggle qa-note-dropdown"
|
class="note-type-toggle js-note-new-discussion dropdown-toggle"
|
||||||
|
data-qa-selector="note_dropdown"
|
||||||
data-display="static"
|
data-display="static"
|
||||||
data-toggle="dropdown"
|
data-toggle="dropdown"
|
||||||
icon="chevron-down"
|
icon="chevron-down"
|
||||||
|
@ -469,7 +472,10 @@ export default {
|
||||||
</li>
|
</li>
|
||||||
<li class="divider droplab-item-ignore"></li>
|
<li class="divider droplab-item-ignore"></li>
|
||||||
<li :class="{ 'droplab-item-selected': noteType === 'discussion' }">
|
<li :class="{ 'droplab-item-selected': noteType === 'discussion' }">
|
||||||
<button class="qa-discussion-option" @click.prevent="setNoteType('discussion')">
|
<button
|
||||||
|
data-qa-selector="discussion_menu_item"
|
||||||
|
@click.prevent="setNoteType('discussion')"
|
||||||
|
>
|
||||||
<i aria-hidden="true" class="fa fa-check icon"></i>
|
<i aria-hidden="true" class="fa fa-check icon"></i>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<strong>{{ __('Start thread') }}</strong>
|
<strong>{{ __('Start thread') }}</strong>
|
||||||
|
|
|
@ -275,7 +275,8 @@ export default {
|
||||||
v-gl-tooltip
|
v-gl-tooltip
|
||||||
type="button"
|
type="button"
|
||||||
title="Edit comment"
|
title="Edit comment"
|
||||||
class="note-action-button js-note-edit btn btn-transparent qa-note-edit-button"
|
class="note-action-button js-note-edit btn btn-transparent"
|
||||||
|
data-qa-selector="note_edit_button"
|
||||||
@click="onEdit"
|
@click="onEdit"
|
||||||
>
|
>
|
||||||
<gl-icon name="pencil" class="link-highlight" />
|
<gl-icon name="pencil" class="link-highlight" />
|
||||||
|
|
|
@ -338,7 +338,8 @@ export default {
|
||||||
v-model="updatedNoteBody"
|
v-model="updatedNoteBody"
|
||||||
:data-supports-quick-actions="!isEditing"
|
:data-supports-quick-actions="!isEditing"
|
||||||
name="note[note]"
|
name="note[note]"
|
||||||
class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form qa-reply-input"
|
class="note-textarea js-gfm-input js-note-text js-autosize markdown-area js-vue-issue-note-form"
|
||||||
|
data-qa-selector="reply_field"
|
||||||
dir="auto"
|
dir="auto"
|
||||||
:aria-label="__('Description')"
|
:aria-label="__('Description')"
|
||||||
:placeholder="__('Write a comment or drag your files here…')"
|
:placeholder="__('Write a comment or drag your files here…')"
|
||||||
|
@ -377,7 +378,8 @@ export default {
|
||||||
<button
|
<button
|
||||||
:disabled="isDisabled"
|
:disabled="isDisabled"
|
||||||
type="button"
|
type="button"
|
||||||
class="btn btn-success qa-start-review"
|
class="btn btn-success"
|
||||||
|
data-qa-selector="start_review_button"
|
||||||
@click="handleAddToReview"
|
@click="handleAddToReview"
|
||||||
>
|
>
|
||||||
<template v-if="hasDrafts">{{ __('Add to review') }}</template>
|
<template v-if="hasDrafts">{{ __('Add to review') }}</template>
|
||||||
|
@ -386,7 +388,8 @@ export default {
|
||||||
<button
|
<button
|
||||||
:disabled="isDisabled"
|
:disabled="isDisabled"
|
||||||
type="button"
|
type="button"
|
||||||
class="btn qa-comment-now js-comment-button"
|
class="btn js-comment-button"
|
||||||
|
data-qa-selector="comment_now_button"
|
||||||
@click="handleUpdate()"
|
@click="handleUpdate()"
|
||||||
>
|
>
|
||||||
{{ __('Add comment now') }}
|
{{ __('Add comment now') }}
|
||||||
|
@ -405,7 +408,8 @@ export default {
|
||||||
<button
|
<button
|
||||||
:disabled="isDisabled"
|
:disabled="isDisabled"
|
||||||
type="button"
|
type="button"
|
||||||
class="js-vue-issue-save btn btn-success js-comment-button qa-reply-comment-button"
|
class="js-vue-issue-save btn btn-success js-comment-button"
|
||||||
|
data-qa-selector="reply_comment_button"
|
||||||
@click="handleUpdate()"
|
@click="handleUpdate()"
|
||||||
>
|
>
|
||||||
{{ saveButtonTitle }}
|
{{ saveButtonTitle }}
|
||||||
|
|
|
@ -57,7 +57,12 @@ export default {
|
||||||
tooltip-placement="bottom"
|
tooltip-placement="bottom"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button class="btn btn-link js-replies-text qa-expand-replies" type="button" @click="toggle">
|
<button
|
||||||
|
class="btn btn-link js-replies-text"
|
||||||
|
data-qa-selector="expand_replies_button"
|
||||||
|
type="button"
|
||||||
|
@click="toggle"
|
||||||
|
>
|
||||||
{{ replies.length }} {{ n__('reply', 'replies', replies.length) }}
|
{{ replies.length }} {{ n__('reply', 'replies', replies.length) }}
|
||||||
</button>
|
</button>
|
||||||
{{ __('Last reply by') }}
|
{{ __('Last reply by') }}
|
||||||
|
@ -68,7 +73,8 @@ export default {
|
||||||
</template>
|
</template>
|
||||||
<span
|
<span
|
||||||
v-else
|
v-else
|
||||||
class="collapse-replies-btn js-collapse-replies qa-collapse-replies"
|
class="collapse-replies-btn js-collapse-replies"
|
||||||
|
data-qa-selector="collapse_replies_button"
|
||||||
@click="toggle"
|
@click="toggle"
|
||||||
>
|
>
|
||||||
<gl-icon name="chevron-down" /> {{ s__('Notes|Collapse replies') }}
|
<gl-icon name="chevron-down" /> {{ s__('Notes|Collapse replies') }}
|
||||||
|
|
|
@ -12,7 +12,7 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<timeline-entry-item class="note note-wrapper" data-qa-selector="skeleton_note">
|
<timeline-entry-item class="note note-wrapper" data-qa-selector="skeleton_note_placeholder">
|
||||||
<div class="timeline-icon"></div>
|
<div class="timeline-icon"></div>
|
||||||
<div class="timeline-content">
|
<div class="timeline-content">
|
||||||
<div class="note-header"></div>
|
<div class="note-header"></div>
|
||||||
|
|
|
@ -107,6 +107,14 @@ class ContainerRepository < ApplicationRecord
|
||||||
client.delete_repository_tag_by_name(self.path, name)
|
client.delete_repository_tag_by_name(self.path, name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reset_expiration_policy_started_at!
|
||||||
|
update!(expiration_policy_started_at: nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
def start_expiration_policy!
|
||||||
|
update!(expiration_policy_started_at: Time.zone.now)
|
||||||
|
end
|
||||||
|
|
||||||
def self.build_from_path(path)
|
def self.build_from_path(path)
|
||||||
self.new(project: path.repository_project,
|
self.new(project: path.repository_project,
|
||||||
name: path.repository_name)
|
name: path.repository_name)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<%= render partial: "confirmation_instructions_#{@resource.is_a?(User) ? 'account' : 'secondary'}" %>
|
<%= render partial: "confirmation_instructions_#{@resource.is_a?(User) ? 'account' : 'secondary'}" %>
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
Issue was <%= @issue_status %> by <%= sanitize_name(@updated_by.name) %>
|
Issue was <%= @issue_status %> by <%= sanitize_name(@updated_by.name) %>
|
||||||
|
|
||||||
Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
|
Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,17 @@ class CleanupContainerRepositoryWorker # rubocop:disable Scalability/IdempotentW
|
||||||
|
|
||||||
return unless valid?
|
return unless valid?
|
||||||
|
|
||||||
Projects::ContainerRepository::CleanupTagsService
|
if run_by_container_expiration_policy?
|
||||||
|
container_repository.start_expiration_policy!
|
||||||
|
end
|
||||||
|
|
||||||
|
result = Projects::ContainerRepository::CleanupTagsService
|
||||||
.new(project, current_user, params)
|
.new(project, current_user, params)
|
||||||
.execute(container_repository)
|
.execute(container_repository)
|
||||||
|
|
||||||
|
if run_by_container_expiration_policy? && result[:status] == :success
|
||||||
|
container_repository.reset_expiration_policy_started_at!
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -30,7 +38,7 @@ class CleanupContainerRepositoryWorker # rubocop:disable Scalability/IdempotentW
|
||||||
end
|
end
|
||||||
|
|
||||||
def run_by_container_expiration_policy?
|
def run_by_container_expiration_policy?
|
||||||
@params['container_expiration_policy'] && container_repository && project
|
@params['container_expiration_policy'] && container_repository.present? && project.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def project
|
def project
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: Add expiration policy started at support in container repositories
|
||||||
|
merge_request: 42598
|
||||||
|
author:
|
||||||
|
type: added
|
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddExpirationPolicyStartedAtToContainerRepositories < ActiveRecord::Migration[6.0]
|
||||||
|
DOWNTIME = false
|
||||||
|
|
||||||
|
def up
|
||||||
|
add_column(:container_repositories, :expiration_policy_started_at, :datetime_with_timezone)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column(:container_repositories, :expiration_policy_started_at)
|
||||||
|
end
|
||||||
|
end
|
1
db/schema_migrations/20200914070140
Normal file
1
db/schema_migrations/20200914070140
Normal file
|
@ -0,0 +1 @@
|
||||||
|
8cabe224e89ef77fe4a2bc1f8bf7381faaa10d1cab4907a26aeb2162a126af52
|
|
@ -11083,7 +11083,8 @@ CREATE TABLE container_repositories (
|
||||||
name character varying NOT NULL,
|
name character varying NOT NULL,
|
||||||
created_at timestamp without time zone NOT NULL,
|
created_at timestamp without time zone NOT NULL,
|
||||||
updated_at timestamp without time zone NOT NULL,
|
updated_at timestamp without time zone NOT NULL,
|
||||||
status smallint
|
status smallint,
|
||||||
|
expiration_policy_started_at timestamp with time zone
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE SEQUENCE container_repositories_id_seq
|
CREATE SEQUENCE container_repositories_id_seq
|
||||||
|
|
|
@ -1245,13 +1245,6 @@ unset http_proxy
|
||||||
unset https_proxy
|
unset https_proxy
|
||||||
```
|
```
|
||||||
|
|
||||||
### Gitaly not listening on new address after reconfiguring
|
|
||||||
|
|
||||||
When updating the `gitaly['listen_addr']` or `gitaly['prometheus_listen_addr']`
|
|
||||||
values, Gitaly may continue to listen on the old address after a `sudo gitlab-ctl reconfigure`.
|
|
||||||
|
|
||||||
When this occurs, performing a `sudo gitlab-ctl restart` will resolve the issue. This will no longer be necessary after [this issue](https://gitlab.com/gitlab-org/gitaly/-/issues/2521) is resolved.
|
|
||||||
|
|
||||||
### Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly server
|
### Permission denied errors appearing in Gitaly logs when accessing repositories from a standalone Gitaly server
|
||||||
|
|
||||||
If this error occurs even though file permissions are correct, it's likely that
|
If this error occurs even though file permissions are correct, it's likely that
|
||||||
|
|
|
@ -41,7 +41,8 @@ Example response:
|
||||||
"path": "group/project",
|
"path": "group/project",
|
||||||
"project_id": 9,
|
"project_id": 9,
|
||||||
"location": "gitlab.example.com:5000/group/project",
|
"location": "gitlab.example.com:5000/group/project",
|
||||||
"created_at": "2019-01-10T13:38:57.391Z"
|
"created_at": "2019-01-10T13:38:57.391Z",
|
||||||
|
"cleanup_policy_started_at": "2020-01-10T15:40:57.391Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
|
@ -49,7 +50,8 @@ Example response:
|
||||||
"path": "group/project/releases",
|
"path": "group/project/releases",
|
||||||
"project_id": 9,
|
"project_id": 9,
|
||||||
"location": "gitlab.example.com:5000/group/project/releases",
|
"location": "gitlab.example.com:5000/group/project/releases",
|
||||||
"created_at": "2019-01-10T13:39:08.229Z"
|
"created_at": "2019-01-10T13:39:08.229Z",
|
||||||
|
"cleanup_policy_started_at": "2020-08-17T03:12:35.489Z"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
@ -84,6 +86,7 @@ Example response:
|
||||||
"project_id": 9,
|
"project_id": 9,
|
||||||
"location": "gitlab.example.com:5000/group/project",
|
"location": "gitlab.example.com:5000/group/project",
|
||||||
"created_at": "2019-01-10T13:38:57.391Z",
|
"created_at": "2019-01-10T13:38:57.391Z",
|
||||||
|
"cleanup_policy_started_at": "2020-08-17T03:12:35.489Z",
|
||||||
"tags_count": 1,
|
"tags_count": 1,
|
||||||
"tags": [
|
"tags": [
|
||||||
{
|
{
|
||||||
|
@ -100,6 +103,7 @@ Example response:
|
||||||
"project_id": 11,
|
"project_id": 11,
|
||||||
"location": "gitlab.example.com:5000/group/other_project",
|
"location": "gitlab.example.com:5000/group/other_project",
|
||||||
"created_at": "2019-01-10T13:39:08.229Z",
|
"created_at": "2019-01-10T13:39:08.229Z",
|
||||||
|
"cleanup_policy_started_at": "2020-01-10T15:40:57.391Z",
|
||||||
"tags_count": 3,
|
"tags_count": 3,
|
||||||
"tags": [
|
"tags": [
|
||||||
{
|
{
|
||||||
|
|
|
@ -321,7 +321,7 @@ are listed in the descriptions of the relevant settings.
|
||||||
| `receive_max_input_size` | integer | no | Maximum push size (MB). |
|
| `receive_max_input_size` | integer | no | Maximum push size (MB). |
|
||||||
| `repository_checks_enabled` | boolean | no | GitLab will periodically run `git fsck` in all project and wiki repositories to look for silent disk corruption issues. |
|
| `repository_checks_enabled` | boolean | no | GitLab will periodically run `git fsck` in all project and wiki repositories to look for silent disk corruption issues. |
|
||||||
| `repository_size_limit` | integer | no | **(PREMIUM)** Size limit per repository (MB) |
|
| `repository_size_limit` | integer | no | **(PREMIUM)** Size limit per repository (MB) |
|
||||||
| `repository_storages_weighted` | hash of strings to integers | no | (GitLab 13.1 and later) Hash of names of taken from `gitlab.yml` to weights. New projects are created in one of these stores, chosen by a weighted random selection. |
|
| `repository_storages_weighted` | hash of strings to integers | no | (GitLab 13.1 and later) Hash of names of taken from `gitlab.yml` to [weights](../administration/repository_storage_paths.md#choose-where-new-repositories-will-be-stored). New projects are created in one of these stores, chosen by a weighted random selection. |
|
||||||
| `repository_storages` | array of strings | no | (GitLab 13.0 and earlier) List of names of enabled storage paths, taken from `gitlab.yml`. New projects are created in one of these stores, chosen at random. |
|
| `repository_storages` | array of strings | no | (GitLab 13.0 and earlier) List of names of enabled storage paths, taken from `gitlab.yml`. New projects are created in one of these stores, chosen at random. |
|
||||||
| `require_two_factor_authentication` | boolean | no | (**If enabled, requires:** `two_factor_grace_period`) Require all users to set up Two-factor authentication. |
|
| `require_two_factor_authentication` | boolean | no | (**If enabled, requires:** `two_factor_grace_period`) Require all users to set up Two-factor authentication. |
|
||||||
| `restricted_visibility_levels` | array of strings | no | Selected levels cannot be used by non-admin users for groups, projects or snippets. Can take `private`, `internal` and `public` as a parameter. Default is `null` which means there is no restriction. |
|
| `restricted_visibility_levels` | array of strings | no | Selected levels cannot be used by non-admin users for groups, projects or snippets. Can take `private`, `internal` and `public` as a parameter. Default is `null` which means there is no restriction. |
|
||||||
|
|
|
@ -131,7 +131,7 @@ You can then create workflows and automate any processes that involve testing,
|
||||||
building, and eventually deploying your project from the Docker image you
|
building, and eventually deploying your project from the Docker image you
|
||||||
created.
|
created.
|
||||||
|
|
||||||
Before diving into the details, some things you should be aware of:
|
Before diving into details, some things you should be aware of:
|
||||||
|
|
||||||
- You must [authenticate to the container registry](#authenticating-to-the-container-registry-with-gitlab-cicd)
|
- You must [authenticate to the container registry](#authenticating-to-the-container-registry-with-gitlab-cicd)
|
||||||
before running any commands. You can do this in the `before_script` if multiple
|
before running any commands. You can do this in the `before_script` if multiple
|
||||||
|
|
|
@ -16,6 +16,7 @@ module API
|
||||||
expose :project_id
|
expose :project_id
|
||||||
expose :location
|
expose :location
|
||||||
expose :created_at
|
expose :created_at
|
||||||
|
expose :expiration_policy_started_at, as: :cleanup_policy_started_at
|
||||||
expose :tags_count, if: -> (_, options) { options[:tags_count] }
|
expose :tags_count, if: -> (_, options) { options[:tags_count] }
|
||||||
expose :tags, using: Tag, if: -> (_, options) { options[:tags] }
|
expose :tags, using: Tag, if: -> (_, options) { options[:tags] }
|
||||||
end
|
end
|
||||||
|
|
|
@ -17685,6 +17685,9 @@ msgstr ""
|
||||||
msgid "OnDemandScans|Scan mode"
|
msgid "OnDemandScans|Scan mode"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "OnDemandScans|Scanner profile"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "OnDemandScans|Scanner settings"
|
msgid "OnDemandScans|Scanner settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -17694,6 +17697,9 @@ msgstr ""
|
||||||
msgid "OnDemandScans|Select one of the existing profiles"
|
msgid "OnDemandScans|Select one of the existing profiles"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "OnDemandScans|Site profile"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "OnDemandScans|Site profiles"
|
msgid "OnDemandScans|Site profiles"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,18 @@ module QA
|
||||||
def self.included(base)
|
def self.included(base)
|
||||||
super
|
super
|
||||||
|
|
||||||
|
base.view 'app/assets/javascripts/diffs/components/diff_file_header.vue' do
|
||||||
|
element :toggle_comments_button
|
||||||
|
end
|
||||||
|
|
||||||
|
base.view 'app/assets/javascripts/notes/components/discussion_actions.vue' do
|
||||||
|
element :discussion_reply_tab
|
||||||
|
element :resolve_discussion_button
|
||||||
|
end
|
||||||
|
|
||||||
base.view 'app/assets/javascripts/notes/components/comment_form.vue' do
|
base.view 'app/assets/javascripts/notes/components/comment_form.vue' do
|
||||||
element :note_dropdown
|
element :note_dropdown
|
||||||
element :discussion_option
|
element :discussion_menu_item
|
||||||
end
|
end
|
||||||
|
|
||||||
base.view 'app/assets/javascripts/notes/components/noteable_discussion.vue' do
|
base.view 'app/assets/javascripts/notes/components/noteable_discussion.vue' do
|
||||||
|
@ -23,39 +32,32 @@ module QA
|
||||||
end
|
end
|
||||||
|
|
||||||
base.view 'app/assets/javascripts/notes/components/note_form.vue' do
|
base.view 'app/assets/javascripts/notes/components/note_form.vue' do
|
||||||
element :reply_input
|
element :reply_field
|
||||||
element :reply_comment_button
|
element :reply_comment_button
|
||||||
end
|
end
|
||||||
|
|
||||||
base.view 'app/assets/javascripts/notes/components/discussion_actions.vue' do
|
|
||||||
element :discussion_reply_tab
|
|
||||||
element :resolve_discussion_button
|
|
||||||
end
|
|
||||||
|
|
||||||
base.view 'app/assets/javascripts/notes/components/toggle_replies_widget.vue' do
|
base.view 'app/assets/javascripts/notes/components/toggle_replies_widget.vue' do
|
||||||
element :expand_replies
|
element :expand_replies_button
|
||||||
element :collapse_replies
|
element :collapse_replies_button
|
||||||
end
|
end
|
||||||
|
|
||||||
base.view 'app/assets/javascripts/diffs/components/diff_file_header.vue' do
|
base.view 'app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue' do
|
||||||
element :toggle_comments_button
|
element :skeleton_note_placeholder
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def start_discussion(text)
|
def collapse_replies
|
||||||
fill_element :comment_input, text
|
click_element :collapse_replies_button
|
||||||
click_element :note_dropdown
|
|
||||||
click_element :discussion_option
|
|
||||||
click_element :comment_button
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def toggle_comments(position)
|
def edit_comment(text)
|
||||||
all_elements(:toggle_comments_button, minimum: position)[position - 1].click
|
click_element :note_edit_button
|
||||||
|
fill_element :reply_field, text
|
||||||
|
click_element :reply_comment_button
|
||||||
end
|
end
|
||||||
|
|
||||||
def type_reply_to_discussion(position, reply_text)
|
def expand_replies
|
||||||
all_elements(:discussion_reply_tab, minimum: position)[position - 1].click
|
click_element :expand_replies_button
|
||||||
fill_element :reply_input, reply_text
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def reply_to_discussion(position, reply_text)
|
def reply_to_discussion(position, reply_text)
|
||||||
|
@ -69,18 +71,24 @@ module QA
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def collapse_replies
|
def start_discussion(text)
|
||||||
click_element :collapse_replies
|
fill_element :comment_field, text
|
||||||
|
click_element :note_dropdown
|
||||||
|
click_element :discussion_menu_item
|
||||||
|
click_element :comment_button
|
||||||
end
|
end
|
||||||
|
|
||||||
def expand_replies
|
def toggle_comments(position)
|
||||||
click_element :expand_replies
|
all_elements(:toggle_comments_button, minimum: position)[position - 1].click
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit_comment(text)
|
def type_reply_to_discussion(position, reply_text)
|
||||||
click_element :note_edit_button
|
all_elements(:discussion_reply_tab, minimum: position)[position - 1].click
|
||||||
fill_element :reply_input, text
|
fill_element :reply_field, reply_text
|
||||||
click_element :reply_comment_button
|
end
|
||||||
|
|
||||||
|
def wait_for_loading
|
||||||
|
has_no_element?(:skeleton_note_placeholer)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -44,10 +44,6 @@ module QA
|
||||||
element :squash_checkbox
|
element :squash_checkbox
|
||||||
end
|
end
|
||||||
|
|
||||||
view 'app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue' do
|
|
||||||
element :skeleton_note
|
|
||||||
end
|
|
||||||
|
|
||||||
view 'app/views/projects/merge_requests/show.html.haml' do
|
view 'app/views/projects/merge_requests/show.html.haml' do
|
||||||
element :notes_tab
|
element :notes_tab
|
||||||
element :diffs_tab
|
element :diffs_tab
|
||||||
|
@ -74,8 +70,8 @@ module QA
|
||||||
view 'app/assets/javascripts/notes/components/note_form.vue' do
|
view 'app/assets/javascripts/notes/components/note_form.vue' do
|
||||||
element :unresolve_review_discussion_checkbox
|
element :unresolve_review_discussion_checkbox
|
||||||
element :resolve_review_discussion_checkbox
|
element :resolve_review_discussion_checkbox
|
||||||
element :start_review
|
element :start_review_button
|
||||||
element :comment_now
|
element :comment_now_button
|
||||||
end
|
end
|
||||||
|
|
||||||
view 'app/assets/javascripts/batch_comments/components/preview_dropdown.vue' do
|
view 'app/assets/javascripts/batch_comments/components/preview_dropdown.vue' do
|
||||||
|
@ -83,19 +79,19 @@ module QA
|
||||||
end
|
end
|
||||||
|
|
||||||
def start_review
|
def start_review
|
||||||
click_element :start_review
|
click_element :start_review_button
|
||||||
|
|
||||||
# After clicking the button, wait for it to disappear
|
# After clicking the button, wait for it to disappear
|
||||||
# before moving on to the next part of the test
|
# before moving on to the next part of the test
|
||||||
has_no_element? :start_review
|
has_no_element? :start_review_button
|
||||||
end
|
end
|
||||||
|
|
||||||
def comment_now
|
def comment_now
|
||||||
click_element :comment_now
|
click_element :comment_now_button
|
||||||
|
|
||||||
# After clicking the button, wait for it to disappear
|
# After clicking the button, wait for it to disappear
|
||||||
# before moving on to the next part of the test
|
# before moving on to the next part of the test
|
||||||
has_no_element? :comment_now
|
has_no_element? :comment_now_button
|
||||||
end
|
end
|
||||||
|
|
||||||
def submit_pending_reviews
|
def submit_pending_reviews
|
||||||
|
@ -117,7 +113,7 @@ module QA
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolve_review_discussion
|
def resolve_review_discussion
|
||||||
scroll_to_element :start_review
|
scroll_to_element :start_review_button
|
||||||
check_element :resolve_review_discussion_checkbox
|
check_element :resolve_review_discussion_checkbox
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -131,7 +127,7 @@ module QA
|
||||||
end
|
end
|
||||||
all_elements(:new_diff_line, minimum: 1).first.hover
|
all_elements(:new_diff_line, minimum: 1).first.hover
|
||||||
click_element(:diff_comment)
|
click_element(:diff_comment)
|
||||||
fill_element(:reply_input, text)
|
fill_element(:reply_field, text)
|
||||||
end
|
end
|
||||||
|
|
||||||
def click_discussions_tab
|
def click_discussions_tab
|
||||||
|
@ -266,10 +262,6 @@ module QA
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def wait_for_loading
|
|
||||||
has_no_element?(:skeleton_note)
|
|
||||||
end
|
|
||||||
|
|
||||||
def click_open_in_web_ide
|
def click_open_in_web_ide
|
||||||
click_element(:open_in_web_ide_button)
|
click_element(:open_in_web_ide_button)
|
||||||
wait_for_requests
|
wait_for_requests
|
||||||
|
|
|
@ -12,7 +12,7 @@ module QA
|
||||||
|
|
||||||
view 'app/assets/javascripts/notes/components/comment_form.vue' do
|
view 'app/assets/javascripts/notes/components/comment_form.vue' do
|
||||||
element :comment_button
|
element :comment_button
|
||||||
element :comment_input
|
element :comment_field
|
||||||
end
|
end
|
||||||
|
|
||||||
view 'app/assets/javascripts/notes/components/discussion_filter.vue' do
|
view 'app/assets/javascripts/notes/components/discussion_filter.vue' do
|
||||||
|
@ -84,7 +84,7 @@ module QA
|
||||||
# attachment option should be an absolute path
|
# attachment option should be an absolute path
|
||||||
def comment(text, attachment: nil, filter: :all_activities)
|
def comment(text, attachment: nil, filter: :all_activities)
|
||||||
method("select_#{filter}_filter").call
|
method("select_#{filter}_filter").call
|
||||||
fill_element :comment_input, "#{text}\n"
|
fill_element :comment_field, "#{text}\n"
|
||||||
|
|
||||||
unless attachment.nil?
|
unless attachment.nil?
|
||||||
QA::Page::Component::Dropzone.new(self, '.new-note')
|
QA::Page::Component::Dropzone.new(self, '.new-note')
|
||||||
|
@ -125,6 +125,8 @@ module QA
|
||||||
click_element(:title)
|
click_element(:title)
|
||||||
click_element :discussion_filter
|
click_element :discussion_filter
|
||||||
find_element(:filter_options, text: text).click
|
find_element(:filter_options, text: text).click
|
||||||
|
|
||||||
|
wait_for_loading
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
"created_at": {
|
"created_at": {
|
||||||
"type": "date-time"
|
"type": "date-time"
|
||||||
},
|
},
|
||||||
|
"cleanup_policy_started_at": {
|
||||||
|
"type": "date-time"
|
||||||
|
},
|
||||||
"tags_path": {
|
"tags_path": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
|
|
@ -184,6 +184,33 @@ RSpec.describe ContainerRepository do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#start_expiration_policy!' do
|
||||||
|
subject { repository.start_expiration_policy! }
|
||||||
|
|
||||||
|
it 'sets the expiration policy started at to now' do
|
||||||
|
Timecop.freeze do
|
||||||
|
expect { subject }
|
||||||
|
.to change { repository.expiration_policy_started_at }.from(nil).to(Time.zone.now)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#reset_expiration_policy_started_at!' do
|
||||||
|
subject { repository.reset_expiration_policy_started_at! }
|
||||||
|
|
||||||
|
before do
|
||||||
|
repository.start_expiration_policy!
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'resets the expiration policy started at' do
|
||||||
|
started_at = repository.expiration_policy_started_at
|
||||||
|
|
||||||
|
expect(started_at).not_to be_nil
|
||||||
|
expect { subject }
|
||||||
|
.to change { repository.expiration_policy_started_at }.from(started_at).to(nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe '.build_from_path' do
|
describe '.build_from_path' do
|
||||||
let(:registry_path) do
|
let(:registry_path) do
|
||||||
ContainerRegistry::Path.new(project.full_path + '/some/image')
|
ContainerRegistry::Path.new(project.full_path + '/some/image')
|
||||||
|
|
|
@ -40,14 +40,35 @@ RSpec.describe CleanupContainerRepositoryWorker, :clean_gitlab_redis_shared_stat
|
||||||
context 'container expiration policy' do
|
context 'container expiration policy' do
|
||||||
let(:params) { { key: 'value', 'container_expiration_policy' => true } }
|
let(:params) { { key: 'value', 'container_expiration_policy' => true } }
|
||||||
|
|
||||||
|
before do
|
||||||
|
allow(ContainerRepository)
|
||||||
|
.to receive(:find_by_id).with(repository.id).and_return(repository)
|
||||||
|
end
|
||||||
|
|
||||||
it 'executes the destroy service' do
|
it 'executes the destroy service' do
|
||||||
|
expect(repository).to receive(:start_expiration_policy!).and_call_original
|
||||||
|
expect(repository).to receive(:reset_expiration_policy_started_at!).and_call_original
|
||||||
expect(Projects::ContainerRepository::CleanupTagsService).to receive(:new)
|
expect(Projects::ContainerRepository::CleanupTagsService).to receive(:new)
|
||||||
.with(project, nil, params.merge('container_expiration_policy' => true))
|
.with(project, nil, params.merge('container_expiration_policy' => true))
|
||||||
.and_return(service)
|
.and_return(service)
|
||||||
|
|
||||||
expect(service).to receive(:execute)
|
expect(service).to receive(:execute).and_return(status: :success)
|
||||||
|
|
||||||
subject.perform(nil, repository.id, params)
|
subject.perform(nil, repository.id, params)
|
||||||
|
expect(repository.reload.expiration_policy_started_at).to be_nil
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't reset the expiration policy started at if the destroy service returns an error" do
|
||||||
|
expect(repository).to receive(:start_expiration_policy!).and_call_original
|
||||||
|
expect(repository).not_to receive(:reset_expiration_policy_started_at!)
|
||||||
|
expect(Projects::ContainerRepository::CleanupTagsService).to receive(:new)
|
||||||
|
.with(project, nil, params.merge('container_expiration_policy' => true))
|
||||||
|
.and_return(service)
|
||||||
|
|
||||||
|
expect(service).to receive(:execute).and_return(status: :error, message: 'timeout while deleting tags')
|
||||||
|
|
||||||
|
subject.perform(nil, repository.id, params)
|
||||||
|
expect(repository.reload.expiration_policy_started_at).not_to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue