Commit b3e0658c authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 82a534c2
...@@ -34,15 +34,15 @@ module SearchHelper ...@@ -34,15 +34,15 @@ module SearchHelper
from: from, from: from,
to: to, to: to,
count: count, count: count,
scope: search_entries_info_label(scope, count), scope: search_entries_scope_label(scope, count),
term: term term: term
} }
end end
def search_entries_info_label(scope, count) def search_entries_scope_label(scope, count)
case scope case scope
when 'blobs', 'snippet_blobs', 'wiki_blobs' when 'blobs'
ns_('SearchResults|result', 'SearchResults|results', count) ns_('SearchResults|code result', 'SearchResults|code results', count)
when 'commits' when 'commits'
ns_('SearchResults|commit', 'SearchResults|commits', count) ns_('SearchResults|commit', 'SearchResults|commits', count)
when 'issues' when 'issues'
...@@ -55,10 +55,14 @@ module SearchHelper ...@@ -55,10 +55,14 @@ module SearchHelper
ns_('SearchResults|comment', 'SearchResults|comments', count) ns_('SearchResults|comment', 'SearchResults|comments', count)
when 'projects' when 'projects'
ns_('SearchResults|project', 'SearchResults|projects', count) ns_('SearchResults|project', 'SearchResults|projects', count)
when 'snippet_blobs'
ns_('SearchResults|snippet result', 'SearchResults|snippet results', count)
when 'snippet_titles' when 'snippet_titles'
ns_('SearchResults|snippet', 'SearchResults|snippets', count) ns_('SearchResults|snippet', 'SearchResults|snippets', count)
when 'users' when 'users'
ns_('SearchResults|user', 'SearchResults|users', count) ns_('SearchResults|user', 'SearchResults|users', count)
when 'wiki_blobs'
ns_('SearchResults|wiki result', 'SearchResults|wiki results', count)
else else
raise "Unrecognized search scope '#{scope}'" raise "Unrecognized search scope '#{scope}'"
end end
...@@ -72,6 +76,13 @@ module SearchHelper ...@@ -72,6 +76,13 @@ module SearchHelper
end end
end end
def search_entries_empty_message(scope, term)
(s_("SearchResults|We couldn't find any %{scope} matching %{term}") % {
scope: search_entries_scope_label(scope, 0),
term: "<code>#{term}</code>"
}).html_safe
end
def find_project_for_result_blob(projects, result) def find_project_for_result_blob(projects, result)
@project @project
end end
......
.append-bottom-10
%h4= _('Set up a %{type} Runner automatically') % { type: type }
%p
- link_to_help_page = link_to(_('Learn more about Kubernetes'),
help_page_path('user/project/clusters/index'),
target: '_blank',
rel: 'noopener noreferrer')
= _('You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}').html_safe % { link_to_help_page: link_to_help_page }
%ol
%li
= _('Click the button below to begin the install process by navigating to the Kubernetes page')
%li
= _('Select an existing Kubernetes cluster or create a new one')
%li
= _('From the Kubernetes cluster details view, install Runner from the applications list')
= link_to _('Install Runner on Kubernetes'),
clusters_path,
class: 'btn btn-info'
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
-# Proper policies should be implemented per -# Proper policies should be implemented per
-# https://gitlab.com/gitlab-org/gitlab-foss/issues/45894 -# https://gitlab.com/gitlab-org/gitlab-foss/issues/45894
- if can?(current_user, :admin_pipeline, @group) - if can?(current_user, :admin_pipeline, @group)
= render partial: 'ci/runner/how_to_setup_runner_automatically',
locals: { type: 'group',
clusters_path: group_clusters_path(@group) }
%hr
= render partial: 'ci/runner/how_to_setup_runner', = render partial: 'ci/runner/how_to_setup_runner',
locals: { registration_token: @group.runners_token, locals: { registration_token: @group.runners_token,
type: 'group', type: 'group',
......
...@@ -2,28 +2,9 @@ ...@@ -2,28 +2,9 @@
= _('Specific Runners') = _('Specific Runners')
.bs-callout.help-callout .bs-callout.help-callout
.append-bottom-10 = render partial: 'ci/runner/how_to_setup_runner_automatically',
%h4= _('Set up a specific Runner automatically') locals: { type: 'specific',
clusters_path: project_clusters_path(@project) }
%p
- link_to_help_page = link_to(_('Learn more about Kubernetes'),
help_page_path('user/project/clusters/index'),
target: '_blank',
rel: 'noopener noreferrer')
= _('You can easily install a Runner on a Kubernetes cluster. %{link_to_help_page}').html_safe % { link_to_help_page: link_to_help_page }
%ol
%li
= _('Click the button below to begin the install process by navigating to the Kubernetes page')
%li
= _('Select an existing Kubernetes cluster or create a new one')
%li
= _('From the Kubernetes cluster details view, install Runner from the applications list')
= link_to _('Install Runner on Kubernetes'),
project_clusters_path(@project),
class: 'btn btn-info'
%hr %hr
= render partial: 'ci/runner/how_to_setup_runner', = render partial: 'ci/runner/how_to_setup_runner',
locals: { registration_token: @project.runners_token, locals: { registration_token: @project.runners_token,
......
...@@ -2,5 +2,4 @@ ...@@ -2,5 +2,4 @@
.search_glyph .search_glyph
%h4 %h4
= icon('search') = icon('search')
= _("We couldn't find any results matching") = search_entries_empty_message(@scope, @search_term)
%code= @search_term
---
title: Add kubernetes section to group runner settings
merge_request: 16338
author:
type: added
---
title: Use search scope label in empty results message
merge_request: 16324
author:
type: changed
...@@ -116,6 +116,12 @@ Parameters: ...@@ -116,6 +116,12 @@ Parameters:
- `message` (optional) - Creates annotated tag. - `message` (optional) - Creates annotated tag.
- `release_description` (optional) - Add release notes to the Git tag and store it in the GitLab database. - `release_description` (optional) - Add release notes to the Git tag and store it in the GitLab database.
```bash
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/tags?tag_name=test&ref=master"
```
Example response:
```json ```json
{ {
"commit": { "commit": {
......
...@@ -393,20 +393,21 @@ PUT /users/:id ...@@ -393,20 +393,21 @@ PUT /users/:id
Parameters: Parameters:
- `email` - Email - `id` (required) - The ID of the user
- `username` - Username - `email` (optional) - Email
- `name` - Name - `username` (optional) - Username
- `password` - Password - `name` (optional) - Name
- `skype` - Skype ID - `password` (optional) - Password
- `linkedin` - LinkedIn - `skype` (optional) - Skype ID
- `twitter` - Twitter account - `linkedin` (optional) - LinkedIn
- `website_url` - Website URL - `twitter` (optional) - Twitter account
- `organization` - Organization name - `website_url` (optional) - Website URL
- `projects_limit` - Limit projects each user can create - `organization` (optional) - Organization name
- `extern_uid` - External UID - `projects_limit` (optional) - Limit projects each user can create
- `provider` - External provider name - `extern_uid` (optional) - External UID
- `provider` (optional) - External provider name
- `group_id_for_saml` (optional) - ID of group where SAML has been configured - `group_id_for_saml` (optional) - ID of group where SAML has been configured
- `bio` - User's biography - `bio` (optional) - User's biography
- `location` (optional) - User's location - `location` (optional) - User's location
- `public_email` (optional) - The public email of the user - `public_email` (optional) - The public email of the user
- `admin` (optional) - User is admin - true or false (default) - `admin` (optional) - User is admin - true or false (default)
...@@ -419,7 +420,7 @@ Parameters: ...@@ -419,7 +420,7 @@ Parameters:
- `private_profile` (optional) - User's profile is private - true or false (default) - `private_profile` (optional) - User's profile is private - true or false (default)
- `shared_runners_minutes_limit` (optional) - Pipeline minutes quota for this user **(STARTER)** - `shared_runners_minutes_limit` (optional) - Pipeline minutes quota for this user **(STARTER)**
- `extra_shared_runners_minutes_limit` (optional) - Extra pipeline minutes quota for this user **(STARTER)** - `extra_shared_runners_minutes_limit` (optional) - Extra pipeline minutes quota for this user **(STARTER)**
- `note` (optional) - Admin notes for this user **(STARTER)** - `note` (optional) - Admin notes for this user **(STARTER)**
On password update, user will be forced to change it upon next login. On password update, user will be forced to change it upon next login.
Note, at the moment this method does only return a `404` error, Note, at the moment this method does only return a `404` error,
......
...@@ -28,7 +28,7 @@ to accomplish their work with GitLab. ...@@ -28,7 +28,7 @@ to accomplish their work with GitLab.
1. Follow GitLab's [Merge Request Guidelines](../contributing/merge_request_workflow.md#merge-request-guidelines). 1. Follow GitLab's [Merge Request Guidelines](../contributing/merge_request_workflow.md#merge-request-guidelines).
If you need any help to choose the correct place for a doc, discuss a documentation If you need any help to choose the correct place for a doc, discuss a documentation
idea or outline, or request any other help, ping the Technical Writer for the relevant idea or outline, or request any other help, ping the technical writer for the relevant
[DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages) [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages)
in your issue or MR, or write within `#docs` if you are a member of GitLab's Slack workspace. in your issue or MR, or write within `#docs` if you are a member of GitLab's Slack workspace.
...@@ -39,7 +39,7 @@ This person must make a good-faith effort to ensure that the content is clear ...@@ -39,7 +39,7 @@ This person must make a good-faith effort to ensure that the content is clear
(sufficiently easy for the intended audience to navigate and understand) and (sufficiently easy for the intended audience to navigate and understand) and
that it meets the [Documentation Guidelines](index.md) and [Style Guide](styleguide.md). that it meets the [Documentation Guidelines](index.md) and [Style Guide](styleguide.md).
If the author or reviewer has any questions, or would like a techncial writer's review If the author or reviewer has any questions, or would like a technical writer's review
before merging, mention the writer who is assigned to the relevant [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages). before merging, mention the writer who is assigned to the relevant [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages).
The process can involve the following parties/phases, and is replicated in the `Documentation` MR template for GitLab CE and EE, to help with following the process. The process can involve the following parties/phases, and is replicated in the `Documentation` MR template for GitLab CE and EE, to help with following the process.
......
...@@ -13557,6 +13557,14 @@ msgstr "" ...@@ -13557,6 +13557,14 @@ msgstr ""
msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for \"%{term}\"" msgid "SearchResults|Showing %{from} - %{to} of %{count} %{scope} for \"%{term}\""
msgstr "" msgstr ""
msgid "SearchResults|We couldn't find any %{scope} matching %{term}"
msgstr ""
msgid "SearchResults|code result"
msgid_plural "SearchResults|code results"
msgstr[0] ""
msgstr[1] ""
msgid "SearchResults|comment" msgid "SearchResults|comment"
msgid_plural "SearchResults|comments" msgid_plural "SearchResults|comments"
msgstr[0] "" msgstr[0] ""
...@@ -13587,13 +13595,13 @@ msgid_plural "SearchResults|projects" ...@@ -13587,13 +13595,13 @@ msgid_plural "SearchResults|projects"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "SearchResults|result" msgid "SearchResults|snippet"
msgid_plural "SearchResults|results" msgid_plural "SearchResults|snippets"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "SearchResults|snippet" msgid "SearchResults|snippet result"
msgid_plural "SearchResults|snippets" msgid_plural "SearchResults|snippet results"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
...@@ -13602,6 +13610,11 @@ msgid_plural "SearchResults|users" ...@@ -13602,6 +13610,11 @@ msgid_plural "SearchResults|users"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "SearchResults|wiki result"
msgid_plural "SearchResults|wiki results"
msgstr[0] ""
msgstr[1] ""
msgid "Seats currently in use" msgid "Seats currently in use"
msgstr "" msgstr ""
...@@ -14031,10 +14044,10 @@ msgstr "" ...@@ -14031,10 +14044,10 @@ msgstr ""
msgid "Set up CI/CD" msgid "Set up CI/CD"
msgstr "" msgstr ""
msgid "Set up a %{type} Runner manually" msgid "Set up a %{type} Runner automatically"
msgstr "" msgstr ""
msgid "Set up a specific Runner automatically" msgid "Set up a %{type} Runner manually"
msgstr "" msgstr ""
msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}" msgid "Set up assertions/attributes/claims (email, first_name, last_name) and NameID according to %{docsLinkStart}the documentation %{icon}%{docsLinkEnd}"
...@@ -17519,9 +17532,6 @@ msgstr "" ...@@ -17519,9 +17532,6 @@ msgstr ""
msgid "We could not determine the path to remove the issue" msgid "We could not determine the path to remove the issue"
msgstr "" msgstr ""
msgid "We couldn't find any results matching"
msgstr ""
msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You will be guided by two types of helpers, best recognized by their color." msgid "We created a short guided tour that will help you learn the basics of GitLab and how it will help you be better at your job. It should only take a couple of minutes. You will be guided by two types of helpers, best recognized by their color."
msgstr "" msgstr ""
......
...@@ -23,6 +23,7 @@ module QA ...@@ -23,6 +23,7 @@ module QA
autoload :Feature, 'qa/runtime/feature' autoload :Feature, 'qa/runtime/feature'
autoload :Fixtures, 'qa/runtime/fixtures' autoload :Fixtures, 'qa/runtime/fixtures'
autoload :Logger, 'qa/runtime/logger' autoload :Logger, 'qa/runtime/logger'
autoload :GPG, 'qa/runtime/gpg'
module API module API
autoload :Client, 'qa/runtime/api/client' autoload :Client, 'qa/runtime/api/client'
...@@ -67,7 +68,9 @@ module QA ...@@ -67,7 +68,9 @@ module QA
autoload :Fork, 'qa/resource/fork' autoload :Fork, 'qa/resource/fork'
autoload :SSHKey, 'qa/resource/ssh_key' autoload :SSHKey, 'qa/resource/ssh_key'
autoload :Snippet, 'qa/resource/snippet' autoload :Snippet, 'qa/resource/snippet'
autoload :Tag, 'qa/resource/tag'
autoload :ProjectMember, 'qa/resource/project_member' autoload :ProjectMember, 'qa/resource/project_member'
autoload :UserGPG, 'qa/resource/user_gpg'
module Events module Events
autoload :Base, 'qa/resource/events/base' autoload :Base, 'qa/resource/events/base'
......
...@@ -14,7 +14,7 @@ module QA ...@@ -14,7 +14,7 @@ module QA
include Scenario::Actable include Scenario::Actable
RepositoryCommandError = Class.new(StandardError) RepositoryCommandError = Class.new(StandardError)
attr_writer :use_lfs attr_writer :use_lfs, :gpg_key_id
attr_accessor :env_vars attr_accessor :env_vars
InvalidCredentialsError = Class.new(RuntimeError) InvalidCredentialsError = Class.new(RuntimeError)
...@@ -25,6 +25,7 @@ module QA ...@@ -25,6 +25,7 @@ module QA
# .netrc can be utilised # .netrc can be utilised
self.env_vars = [%Q{HOME="#{tmp_home_dir}"}] self.env_vars = [%Q{HOME="#{tmp_home_dir}"}]
@use_lfs = false @use_lfs = false
@gpg_key_id = nil
end end
def self.perform(*args) def self.perform(*args)
...@@ -99,10 +100,18 @@ module QA ...@@ -99,10 +100,18 @@ module QA
git_lfs_track_result.to_s + git_add_result.to_s git_lfs_track_result.to_s + git_add_result.to_s
end end
def delete_tag(tag_name)
run(%Q{git push origin --delete #{tag_name}}).to_s
end
def commit(message) def commit(message)
run(%Q{git commit -m "#{message}"}).to_s run(%Q{git commit -m "#{message}"}).to_s
end end
def commit_with_gpg(message)
run(%Q{git config user.signingkey #{@gpg_key_id} && git config gpg.program $(which gpg) && git commit -S -m "#{message}"}).to_s
end
def push_changes(branch = 'master') def push_changes(branch = 'master')
run("git push #{uri} #{branch}").to_s run("git push #{uri} #{branch}").to_s
end end
......
...@@ -47,3 +47,5 @@ module QA ...@@ -47,3 +47,5 @@ module QA
end end
end end
end end
QA::Page::Project::Settings::Repository.prepend_if_ee('QA::EE::Page::Project::Settings::Repository')
...@@ -8,9 +8,9 @@ module QA ...@@ -8,9 +8,9 @@ module QA
class Push < Base class Push < Base
attr_accessor :file_name, :file_content, :commit_message, attr_accessor :file_name, :file_content, :commit_message,
:branch_name, :new_branch, :output, :repository_http_uri, :branch_name, :new_branch, :output, :repository_http_uri,
:repository_ssh_uri, :ssh_key, :user, :use_lfs :repository_ssh_uri, :ssh_key, :user, :use_lfs, :tag_name
attr_writer :remote_branch attr_writer :remote_branch, :gpg_key_id
def initialize def initialize
@file_name = 'file.txt' @file_name = 'file.txt'
...@@ -21,6 +21,8 @@ module QA ...@@ -21,6 +21,8 @@ module QA
@repository_http_uri = "" @repository_http_uri = ""
@ssh_key = nil @ssh_key = nil
@use_lfs = false @use_lfs = false
@tag_name = nil
@gpg_key_id = nil
end end
def remote_branch def remote_branch
...@@ -67,29 +69,43 @@ module QA ...@@ -67,29 +69,43 @@ module QA
email = user.email email = user.email
end end
unless @gpg_key_id.nil?
repository.gpg_key_id = @gpg_key_id
end
@output += repository.clone @output += repository.clone
repository.configure_identity(username, email) repository.configure_identity(username, email)
@output += repository.checkout(branch_name, new_branch: new_branch) @output += repository.checkout(branch_name, new_branch: new_branch)
if @directory if @tag_name
@directory.each_child do |f| @output += repository.delete_tag(@tag_name)
@output += repository.add_file(f.basename, f.read) if f.file?
end
elsif @files
@files.each do |f|
repository.add_file(f[:name], f[:content])
end
else else
@output += repository.add_file(file_name, file_content) if @directory
end @directory.each_child do |f|
@output += repository.add_file(f.basename, f.read) if f.file?
end
elsif @files
@files.each do |f|
repository.add_file(f[:name], f[:content])
end
else
@output += repository.add_file(file_name, file_content)
end
@output += repository.commit(commit_message) @output += commit_to repository
@output += repository.push_changes("#{branch_name}:#{remote_branch}") @output += repository.push_changes("#{branch_name}:#{remote_branch}")
end
repository.delete_ssh_key repository.delete_ssh_key
end end
end end
private
def commit_to(repository)
@gpg_key_id.nil? ? repository.commit(@commit_message) : repository.commit_with_gpg(@commit_message)
end
end end
end end
end end
......
# frozen_string_literal: true
module QA
module Resource
class Tag < Base
attr_accessor :project, :name, :ref
def resource_web_url(resource)
super
rescue ResourceURLMissingError
# this particular resource does not expose a web_url property
end
def api_get_path
"/projects/#{project.id}/repository/tags/#{name}"
end
def api_post_path
"/projects/#{project.id}/repository/tags"
end
def api_post_body
{
tag_name: name,
ref: ref
}
end
end
end
end
# frozen_string_literal: true
module QA
module Resource
class UserGPG < Base
attr_accessor :id, :gpg
attr_reader :key_id
def initialize
@gpg = Runtime::GPG.new
@key_id = @gpg.key_id
end
def fabricate_via_api!
super
@id = self.api_response[:id]
rescue ResourceFabricationFailedError => error
if error.message.include? 'has already been taken'
self
else
raise ResourceFabricationFailedError error
end
end
def resource_web_url(resource)
super
rescue ResourceURLMissingError
# this particular resource does not expose a web_url property
end
def api_get_path
"/user/gpg_keys/#{@id}"
end
def api_post_path
'/user/gpg_keys'
end
def api_post_body
{
key: @gpg.key
}
end
end
end
end
# frozen_string_literal: true
module QA
module Runtime
class GPG
attr_reader :key, :key_id
def initialize
@key_id = 'B8358D73048DACC4'
import_key(File.expand_path('qa/ee/fixtures/gpg/admin.asc'))
@key = collect_key.first
end
private
def import_key(path)
import_key = "gpg --import #{path}"
execute(import_key)
end
def collect_key
get_ascii_format = "gpg --armor --export #{@key_id}"
execute(get_ascii_format)
end
def execute(command)
Open3.capture2e(*command) do |stdin, out, wait|
out.each_char { |char| print char }
if wait.value.exited? && wait.value.exitstatus.nonzero?
raise CommandError, "Command `#{command}` failed!"
end
end
end
end
end
end
...@@ -25,6 +25,10 @@ module QA ...@@ -25,6 +25,10 @@ module QA
Runtime::Env.user_password || default_password Runtime::Env.user_password || default_password
end end
def email
default_email
end
def ldap_user? def ldap_user?
Runtime::Env.ldap_username && Runtime::Env.ldap_password Runtime::Env.ldap_username && Runtime::Env.ldap_password
end end
......
...@@ -272,6 +272,12 @@ describe 'Runners' do ...@@ -272,6 +272,12 @@ describe 'Runners' do
expect(page).to have_content 'This group does not provide any group Runners yet' expect(page).to have_content 'This group does not provide any group Runners yet'
end end
it 'user can see a link to install runners on kubernetes clusters' do
visit group_settings_ci_cd_path(group)
expect(page).to have_link('Install Runner on Kubernetes', href: group_clusters_path(group))
end
end end
context 'group with a runner' do context 'group with a runner' do
......
...@@ -103,19 +103,17 @@ describe SearchHelper do ...@@ -103,19 +103,17 @@ describe SearchHelper do
using RSpec::Parameterized::TableSyntax using RSpec::Parameterized::TableSyntax
where(:scope, :label) do where(:scope, :label) do
'blobs' | 'code result'
'commits' | 'commit' 'commits' | 'commit'
'issues' | 'issue' 'issues' | 'issue'
'merge_requests' | 'merge request' 'merge_requests' | 'merge request'
'milestones' | 'milestone' 'milestones' | 'milestone'
'notes' | 'comment'
'projects' | 'project' 'projects' | 'project'
'snippet_blobs' | 'snippet result'
'snippet_titles' | 'snippet' 'snippet_titles' | 'snippet'
'users' | 'user' 'users' | 'user'
'wiki_blobs' | 'wiki result'
'blobs' | 'result'
'snippet_blobs' | 'result'
'wiki_blobs' | 'result'
'notes' | 'comment'
end end
with_them do with_them do
...@@ -140,6 +138,15 @@ describe SearchHelper do ...@@ -140,6 +138,15 @@ describe SearchHelper do
end end
end end
describe 'search_entries_empty_message' do
it 'returns the formatted entry message' do
message = search_entries_empty_message('projects', 'foo')
expect(message).to eq("We couldn't find any projects matching <code>foo</code>")
expect(message).to be_html_safe
end
end
describe 'search_filter_input_options' do describe 'search_filter_input_options' do
context 'project' do context 'project' do
before do before do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment