Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-09-23 00:09:45 +00:00
parent 27c4555a42
commit 9c1284626f
25 changed files with 185 additions and 76 deletions

View file

@ -381,7 +381,8 @@ export default {
dir="auto"
:disabled="isSubmitting"
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"
:aria-label="__('Description')"
:placeholder="__('Write a comment or drag your files here…')"
@ -426,7 +427,8 @@ export default {
>
<gl-button
: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"
category="primary"
variant="success"
@ -440,7 +442,8 @@ export default {
name="button"
category="primary"
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-toggle="dropdown"
icon="chevron-down"
@ -469,7 +472,10 @@ export default {
</li>
<li class="divider droplab-item-ignore"></li>
<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>
<div class="description">
<strong>{{ __('Start thread') }}</strong>

View file

@ -275,7 +275,8 @@ export default {
v-gl-tooltip
type="button"
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"
>
<gl-icon name="pencil" class="link-highlight" />

View file

@ -338,7 +338,8 @@ export default {
v-model="updatedNoteBody"
:data-supports-quick-actions="!isEditing"
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"
:aria-label="__('Description')"
:placeholder="__('Write a comment or drag your files here…')"
@ -377,7 +378,8 @@ export default {
<button
:disabled="isDisabled"
type="button"
class="btn btn-success qa-start-review"
class="btn btn-success"
data-qa-selector="start_review_button"
@click="handleAddToReview"
>
<template v-if="hasDrafts">{{ __('Add to review') }}</template>
@ -386,7 +388,8 @@ export default {
<button
:disabled="isDisabled"
type="button"
class="btn qa-comment-now js-comment-button"
class="btn js-comment-button"
data-qa-selector="comment_now_button"
@click="handleUpdate()"
>
{{ __('Add comment now') }}
@ -405,7 +408,8 @@ export default {
<button
:disabled="isDisabled"
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()"
>
{{ saveButtonTitle }}

View file

@ -57,7 +57,12 @@ export default {
tooltip-placement="bottom"
/>
</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) }}
</button>
{{ __('Last reply by') }}
@ -68,7 +73,8 @@ export default {
</template>
<span
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"
>
<gl-icon name="chevron-down" /> {{ s__('Notes|Collapse replies') }}

View file

@ -12,7 +12,7 @@ export default {
</script>
<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-content">
<div class="note-header"></div>

View file

@ -107,6 +107,14 @@ class ContainerRepository < ApplicationRecord
client.delete_repository_tag_by_name(self.path, name)
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)
self.new(project: path.repository_project,
name: path.repository_name)

View file

@ -1 +1 @@
<%= render partial: "confirmation_instructions_#{@resource.is_a?(User) ? 'account' : 'secondary'}" %>
<%= render partial: "confirmation_instructions_#{@resource.is_a?(User) ? 'account' : 'secondary'}" %>

View file

@ -1,4 +1,3 @@
Issue was <%= @issue_status %> by <%= sanitize_name(@updated_by.name) %>
Issue <%= @issue.iid %>: <%= url_for(project_issue_url(@issue.project, @issue)) %>

View file

@ -16,9 +16,17 @@ class CleanupContainerRepositoryWorker # rubocop:disable Scalability/IdempotentW
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)
.execute(container_repository)
if run_by_container_expiration_policy? && result[:status] == :success
container_repository.reset_expiration_policy_started_at!
end
end
private
@ -30,7 +38,7 @@ class CleanupContainerRepositoryWorker # rubocop:disable Scalability/IdempotentW
end
def run_by_container_expiration_policy?
@params['container_expiration_policy'] && container_repository && project
@params['container_expiration_policy'] && container_repository.present? && project.present?
end
def project

View file

@ -0,0 +1,5 @@
---
title: Add expiration policy started at support in container repositories
merge_request: 42598
author:
type: added

View file

@ -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

View file

@ -0,0 +1 @@
8cabe224e89ef77fe4a2bc1f8bf7381faaa10d1cab4907a26aeb2162a126af52

View file

@ -11083,7 +11083,8 @@ CREATE TABLE container_repositories (
name character varying NOT NULL,
created_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

View file

@ -1245,13 +1245,6 @@ unset http_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
If this error occurs even though file permissions are correct, it's likely that

View file

@ -41,7 +41,8 @@ Example response:
"path": "group/project",
"project_id": 9,
"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,
@ -49,7 +50,8 @@ Example response:
"path": "group/project/releases",
"project_id": 9,
"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,
"location": "gitlab.example.com:5000/group/project",
"created_at": "2019-01-10T13:38:57.391Z",
"cleanup_policy_started_at": "2020-08-17T03:12:35.489Z",
"tags_count": 1,
"tags": [
{
@ -100,6 +103,7 @@ Example response:
"project_id": 11,
"location": "gitlab.example.com:5000/group/other_project",
"created_at": "2019-01-10T13:39:08.229Z",
"cleanup_policy_started_at": "2020-01-10T15:40:57.391Z",
"tags_count": 3,
"tags": [
{

View file

@ -321,7 +321,7 @@ are listed in the descriptions of the relevant settings.
| `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_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. |
| `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. |

View file

@ -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
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)
before running any commands. You can do this in the `before_script` if multiple

View file

@ -16,6 +16,7 @@ module API
expose :project_id
expose :location
expose :created_at
expose :expiration_policy_started_at, as: :cleanup_policy_started_at
expose :tags_count, if: -> (_, options) { options[:tags_count] }
expose :tags, using: Tag, if: -> (_, options) { options[:tags] }
end

View file

@ -17685,6 +17685,9 @@ msgstr ""
msgid "OnDemandScans|Scan mode"
msgstr ""
msgid "OnDemandScans|Scanner profile"
msgstr ""
msgid "OnDemandScans|Scanner settings"
msgstr ""
@ -17694,6 +17697,9 @@ msgstr ""
msgid "OnDemandScans|Select one of the existing profiles"
msgstr ""
msgid "OnDemandScans|Site profile"
msgstr ""
msgid "OnDemandScans|Site profiles"
msgstr ""

View file

@ -9,9 +9,18 @@ module QA
def self.included(base)
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
element :note_dropdown
element :discussion_option
element :discussion_menu_item
end
base.view 'app/assets/javascripts/notes/components/noteable_discussion.vue' do
@ -23,39 +32,32 @@ module QA
end
base.view 'app/assets/javascripts/notes/components/note_form.vue' do
element :reply_input
element :reply_field
element :reply_comment_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/toggle_replies_widget.vue' do
element :expand_replies
element :collapse_replies
element :expand_replies_button
element :collapse_replies_button
end
base.view 'app/assets/javascripts/diffs/components/diff_file_header.vue' do
element :toggle_comments_button
base.view 'app/assets/javascripts/vue_shared/components/notes/skeleton_note.vue' do
element :skeleton_note_placeholder
end
end
def start_discussion(text)
fill_element :comment_input, text
click_element :note_dropdown
click_element :discussion_option
click_element :comment_button
def collapse_replies
click_element :collapse_replies_button
end
def toggle_comments(position)
all_elements(:toggle_comments_button, minimum: position)[position - 1].click
def edit_comment(text)
click_element :note_edit_button
fill_element :reply_field, text
click_element :reply_comment_button
end
def type_reply_to_discussion(position, reply_text)
all_elements(:discussion_reply_tab, minimum: position)[position - 1].click
fill_element :reply_input, reply_text
def expand_replies
click_element :expand_replies_button
end
def reply_to_discussion(position, reply_text)
@ -69,18 +71,24 @@ module QA
end
end
def collapse_replies
click_element :collapse_replies
def start_discussion(text)
fill_element :comment_field, text
click_element :note_dropdown
click_element :discussion_menu_item
click_element :comment_button
end
def expand_replies
click_element :expand_replies
def toggle_comments(position)
all_elements(:toggle_comments_button, minimum: position)[position - 1].click
end
def edit_comment(text)
click_element :note_edit_button
fill_element :reply_input, text
click_element :reply_comment_button
def type_reply_to_discussion(position, reply_text)
all_elements(:discussion_reply_tab, minimum: position)[position - 1].click
fill_element :reply_field, reply_text
end
def wait_for_loading
has_no_element?(:skeleton_note_placeholer)
end
end
end

View file

@ -44,10 +44,6 @@ module QA
element :squash_checkbox
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
element :notes_tab
element :diffs_tab
@ -74,8 +70,8 @@ module QA
view 'app/assets/javascripts/notes/components/note_form.vue' do
element :unresolve_review_discussion_checkbox
element :resolve_review_discussion_checkbox
element :start_review
element :comment_now
element :start_review_button
element :comment_now_button
end
view 'app/assets/javascripts/batch_comments/components/preview_dropdown.vue' do
@ -83,19 +79,19 @@ module QA
end
def start_review
click_element :start_review
click_element :start_review_button
# After clicking the button, wait for it to disappear
# before moving on to the next part of the test
has_no_element? :start_review
has_no_element? :start_review_button
end
def comment_now
click_element :comment_now
click_element :comment_now_button
# After clicking the button, wait for it to disappear
# before moving on to the next part of the test
has_no_element? :comment_now
has_no_element? :comment_now_button
end
def submit_pending_reviews
@ -117,7 +113,7 @@ module QA
end
def resolve_review_discussion
scroll_to_element :start_review
scroll_to_element :start_review_button
check_element :resolve_review_discussion_checkbox
end
@ -131,7 +127,7 @@ module QA
end
all_elements(:new_diff_line, minimum: 1).first.hover
click_element(:diff_comment)
fill_element(:reply_input, text)
fill_element(:reply_field, text)
end
def click_discussions_tab
@ -266,10 +262,6 @@ module QA
end
end
def wait_for_loading
has_no_element?(:skeleton_note)
end
def click_open_in_web_ide
click_element(:open_in_web_ide_button)
wait_for_requests

View file

@ -12,7 +12,7 @@ module QA
view 'app/assets/javascripts/notes/components/comment_form.vue' do
element :comment_button
element :comment_input
element :comment_field
end
view 'app/assets/javascripts/notes/components/discussion_filter.vue' do
@ -84,7 +84,7 @@ module QA
# attachment option should be an absolute path
def comment(text, attachment: nil, filter: :all_activities)
method("select_#{filter}_filter").call
fill_element :comment_input, "#{text}\n"
fill_element :comment_field, "#{text}\n"
unless attachment.nil?
QA::Page::Component::Dropzone.new(self, '.new-note')
@ -125,6 +125,8 @@ module QA
click_element(:title)
click_element :discussion_filter
find_element(:filter_options, text: text).click
wait_for_loading
end
end
end

View file

@ -20,6 +20,9 @@
"created_at": {
"type": "date-time"
},
"cleanup_policy_started_at": {
"type": "date-time"
},
"tags_path": {
"type": "string"
},

View file

@ -184,6 +184,33 @@ RSpec.describe ContainerRepository do
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
let(:registry_path) do
ContainerRegistry::Path.new(project.full_path + '/some/image')

View file

@ -40,14 +40,35 @@ RSpec.describe CleanupContainerRepositoryWorker, :clean_gitlab_redis_shared_stat
context 'container expiration policy' do
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
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)
.with(project, nil, params.merge('container_expiration_policy' => true))
.and_return(service)
expect(service).to receive(:execute)
expect(service).to receive(:execute).and_return(status: :success)
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