Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
ee2c09733d
commit
840c85c174
6
Gemfile
6
Gemfile
|
@ -129,7 +129,7 @@ gem 'fog-local', '~> 0.6'
|
|||
gem 'fog-openstack', '~> 1.0'
|
||||
gem 'fog-rackspace', '~> 0.1.1'
|
||||
gem 'fog-aliyun', '~> 0.3'
|
||||
gem 'gitlab-fog-azure-rm', '~> 1.2.0', require: false
|
||||
gem 'gitlab-fog-azure-rm', '~> 1.2.0', require: 'fog/azurerm'
|
||||
|
||||
# for Google storage
|
||||
gem 'google-api-client', '~> 0.33'
|
||||
|
@ -290,7 +290,7 @@ gem 'autoprefixer-rails', '10.2.5.1'
|
|||
gem 'terser', '1.0.2'
|
||||
|
||||
gem 'addressable', '~> 2.8'
|
||||
gem 'gemojione', '~> 3.3'
|
||||
gem 'tanuki_emoji', '~> 0.5'
|
||||
gem 'gon', '~> 6.4.0'
|
||||
gem 'request_store', '~> 1.5'
|
||||
gem 'base32', '~> 0.3.0'
|
||||
|
@ -348,6 +348,8 @@ group :development do
|
|||
|
||||
# thin instead webrick
|
||||
gem 'thin', '~> 1.8.0'
|
||||
|
||||
gem 'sprite-factory', '~> 1.7'
|
||||
end
|
||||
|
||||
group :development, :test do
|
||||
|
|
|
@ -436,8 +436,6 @@ GEM
|
|||
ruby-progressbar (~> 1.4)
|
||||
fuzzyurl (0.9.0)
|
||||
gemoji (3.0.1)
|
||||
gemojione (3.3.0)
|
||||
json
|
||||
get_process_mem (0.2.5)
|
||||
ffi (~> 1.0)
|
||||
gettext (3.3.6)
|
||||
|
@ -1216,6 +1214,7 @@ GEM
|
|||
spring (2.1.1)
|
||||
spring-commands-rspec (1.0.4)
|
||||
spring (>= 0.9.1)
|
||||
sprite-factory (1.7.1)
|
||||
sprockets (3.7.2)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
|
@ -1246,6 +1245,7 @@ GEM
|
|||
sys-filesystem (1.1.9)
|
||||
ffi
|
||||
sysexits (1.2.0)
|
||||
tanuki_emoji (0.5.0)
|
||||
temple (0.8.2)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
|
@ -1454,7 +1454,6 @@ DEPENDENCIES
|
|||
fog-rackspace (~> 0.1.1)
|
||||
fugit (~> 1.2.1)
|
||||
fuubar (~> 2.2.0)
|
||||
gemojione (~> 3.3)
|
||||
gettext (~> 3.3)
|
||||
gettext_i18n_rails (~> 1.8.0)
|
||||
gettext_i18n_rails_js (~> 1.3)
|
||||
|
@ -1622,11 +1621,13 @@ DEPENDENCIES
|
|||
spamcheck (~> 0.1.0)
|
||||
spring (~> 2.1.0)
|
||||
spring-commands-rspec (~> 1.0.4)
|
||||
sprite-factory (~> 1.7)
|
||||
sprockets (~> 3.7.0)
|
||||
sshkey (~> 2.0)
|
||||
stackprof (~> 0.2.15)
|
||||
state_machines-activerecord (~> 0.8.0)
|
||||
sys-filesystem (~> 1.1.6)
|
||||
tanuki_emoji (~> 0.5)
|
||||
terser (= 1.0.2)
|
||||
test-prof (~> 1.0.7)
|
||||
test_file_finder (~> 0.1.3)
|
||||
|
|
|
@ -9,6 +9,7 @@ let emojiMap = null;
|
|||
let validEmojiNames = null;
|
||||
export const FALLBACK_EMOJI_KEY = 'grey_question';
|
||||
|
||||
// Keep the version in sync with `lib/gitlab/emoji.rb`
|
||||
export const EMOJI_VERSION = '1';
|
||||
|
||||
const isLocalStorageAvailable = AccessorUtilities.canUseLocalStorage();
|
||||
|
|
|
@ -40,7 +40,7 @@ class AwardEmojisFinder
|
|||
def validate_name_param
|
||||
return unless params[:name]
|
||||
|
||||
raise ArgumentError, 'Invalid name param' unless params[:name].to_s.in?(Gitlab::Emoji.emojis_names)
|
||||
raise ArgumentError, 'Invalid name param' unless TanukiEmoji.find_by_alpha_code(params[:name].to_s)
|
||||
end
|
||||
|
||||
def validate_awarded_by_param
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module EmojiHelper
|
||||
def emoji_icon(*args)
|
||||
raw Gitlab::Emoji.gl_emoji_tag(*args)
|
||||
def emoji_icon(emoji_name, *options)
|
||||
emoji = TanukiEmoji.find_by_alpha_code(emoji_name)
|
||||
raw Gitlab::Emoji.gl_emoji_tag(emoji, *options)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -7,7 +7,8 @@ module ReminderEmailsHelper
|
|||
s_('InviteReminderEmail|Invitation pending')
|
||||
when 1
|
||||
if format == :html
|
||||
s_('InviteReminderEmail|Hey there %{wave_emoji}').html_safe % { wave_emoji: Gitlab::Emoji.gl_emoji_tag('wave') }
|
||||
wave_emoji_tag = Gitlab::Emoji.gl_emoji_tag(TanukiEmoji.find_by_alpha_code('wave'))
|
||||
s_('InviteReminderEmail|Hey there %{wave_emoji}').html_safe % { wave_emoji: wave_emoji_tag }
|
||||
else
|
||||
s_('InviteReminderEmail|Hey there!')
|
||||
end
|
||||
|
|
|
@ -14,7 +14,7 @@ class AwardEmoji < ApplicationRecord
|
|||
validates :user, presence: true
|
||||
validates :awardable, presence: true, unless: :importing?
|
||||
|
||||
validates :name, presence: true, inclusion: { in: Gitlab::Emoji.emojis_names }
|
||||
validates :name, presence: true, 'gitlab/emoji_name': true
|
||||
validates :name, uniqueness: { scope: [:user, :awardable_type, :awardable_id] }, unless: -> { ghost_user? || importing? }
|
||||
|
||||
participant :user
|
||||
|
|
|
@ -1214,7 +1214,19 @@ module Ci
|
|||
end
|
||||
|
||||
def kubernetes_variables
|
||||
[] # Overridden in EE
|
||||
::Gitlab::Ci::Variables::Collection.new.tap do |collection|
|
||||
# A cluster deployemnt may also define a KUBECONFIG variable, so to keep existing
|
||||
# configurations working we shouldn't overwrite it here.
|
||||
# This check will be removed when Cluster and Agent configurations are
|
||||
# merged in https://gitlab.com/gitlab-org/gitlab/-/issues/335089
|
||||
break collection if deployment&.deployment_cluster
|
||||
|
||||
template = ::Ci::GenerateKubeconfigService.new(self).execute # rubocop: disable CodeReuse/ServiceClass
|
||||
|
||||
if template.valid?
|
||||
collection.append(key: 'KUBECONFIG', value: template.to_yaml, public: false, file: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def conditionally_allow_failure!(exit_code)
|
||||
|
|
|
@ -1264,6 +1264,16 @@ module Ci
|
|||
end
|
||||
end
|
||||
|
||||
def authorized_cluster_agents
|
||||
strong_memoize(:authorized_cluster_agents) do
|
||||
if ::Feature.enabled?(:group_authorized_agents, project, default_enabled: :yaml)
|
||||
::Clusters::AgentAuthorizationsFinder.new(project).execute.map(&:agent)
|
||||
else
|
||||
::Clusters::DeployableAgentsFinder.new(project).execute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_message(severity, content)
|
||||
|
|
|
@ -31,7 +31,7 @@ class CustomEmoji < ApplicationRecord
|
|||
private
|
||||
|
||||
def valid_emoji_name
|
||||
if Gitlab::Emoji.emoji_exists?(name)
|
||||
if TanukiEmoji.find_by_alpha_code(name)
|
||||
errors.add(:name, _('%{name} is already being used for another emoji') % { name: self.name })
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,7 @@ class UserStatus < ApplicationRecord
|
|||
enum availability: { not_set: 0, busy: 1 }
|
||||
|
||||
validates :user, presence: true
|
||||
validates :emoji, inclusion: { in: Gitlab::Emoji.emojis_names }
|
||||
validates :emoji, 'gitlab/emoji_name': true
|
||||
validates :message, length: { maximum: 100 }, allow_blank: true
|
||||
|
||||
scope :scheduled_for_cleanup, -> { where(arel_table[:clear_status_at].lteq(Time.current)) }
|
||||
|
|
|
@ -4,24 +4,24 @@ class AwardEmojiPresenter < Gitlab::View::Presenter::Delegated
|
|||
presents ::AwardEmoji, as: :award_emoji
|
||||
|
||||
def description
|
||||
as_emoji['description']
|
||||
as_emoji&.description
|
||||
end
|
||||
|
||||
def unicode
|
||||
as_emoji['unicode']
|
||||
as_emoji&.hex
|
||||
end
|
||||
|
||||
def emoji
|
||||
as_emoji['moji']
|
||||
as_emoji&.codepoints
|
||||
end
|
||||
|
||||
def unicode_version
|
||||
Gitlab::Emoji.emoji_unicode_version(award_emoji.name)
|
||||
as_emoji&.unicode_version
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def as_emoji
|
||||
@emoji ||= Gitlab::Emoji.emojis[award_emoji.name] || {}
|
||||
@emoji ||= TanukiEmoji.find_by_alpha_code(award_emoji.name)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,7 +14,7 @@ module AwardEmojis
|
|||
private
|
||||
|
||||
def normalize_name(name)
|
||||
Gitlab::Emoji.normalize_emoji_name(name)
|
||||
TanukiEmoji.find_by_alpha_code(name)&.name || name
|
||||
end
|
||||
|
||||
# Provide more error state data than what BaseService allows.
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Ci
|
||||
class GenerateKubeconfigService
|
||||
def initialize(build)
|
||||
@build = build
|
||||
@template = Gitlab::Kubernetes::Kubeconfig::Template.new
|
||||
end
|
||||
|
||||
def execute
|
||||
template.add_cluster(
|
||||
name: cluster_name,
|
||||
url: Gitlab::Kas.tunnel_url
|
||||
)
|
||||
|
||||
agents.each do |agent|
|
||||
user = user_name(agent)
|
||||
|
||||
template.add_user(
|
||||
name: user,
|
||||
token: agent_token(agent)
|
||||
)
|
||||
|
||||
template.add_context(
|
||||
name: context_name(agent),
|
||||
cluster: cluster_name,
|
||||
user: user
|
||||
)
|
||||
end
|
||||
|
||||
template
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :build, :template
|
||||
|
||||
def agents
|
||||
build.pipeline.authorized_cluster_agents
|
||||
end
|
||||
|
||||
def cluster_name
|
||||
'gitlab'
|
||||
end
|
||||
|
||||
def user_name(agent)
|
||||
['agent', agent.id].join(delimiter)
|
||||
end
|
||||
|
||||
def context_name(agent)
|
||||
[agent.project.full_path, agent.name].join(delimiter)
|
||||
end
|
||||
|
||||
def agent_token(agent)
|
||||
['ci', agent.id, build.token].join(delimiter)
|
||||
end
|
||||
|
||||
def delimiter
|
||||
':'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Gitlab::EmojiNameValidator
|
||||
#
|
||||
# Validates that the provided value matches an indexed emoji alpha code
|
||||
#
|
||||
# @example Usage
|
||||
# class AwardEmoji < ApplicationRecord
|
||||
# validate :name, 'gitlab/emoji_name': true
|
||||
# end
|
||||
module Gitlab
|
||||
class EmojiNameValidator < ActiveModel::EachValidator
|
||||
def validate_each(record, attribute, value)
|
||||
unless TanukiEmoji.find_by_alpha_code(value.to_s)
|
||||
record.errors.add(attribute, (options[:message] || 'is not a valid emoji name'))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -199,7 +199,7 @@ module Gitlab
|
|||
config.assets.enabled = true
|
||||
|
||||
# Support legacy unicode file named img emojis, `1F939.png`
|
||||
config.assets.paths << Gemojione.images_path
|
||||
config.assets.paths << TanukiEmoji.images_path
|
||||
config.assets.paths << "#{config.root}/vendor/assets/fonts"
|
||||
|
||||
config.assets.precompile << "application_utilities.css"
|
||||
|
|
|
@ -17,7 +17,7 @@ class DirectUploadsValidator
|
|||
|
||||
raise ValidationError, "No provider configured for '#{uploader_type}'. #{supported_provider_text}" if provider.blank?
|
||||
|
||||
return if provider_loaded?(provider)
|
||||
return if provider_supported?(provider)
|
||||
|
||||
raise ValidationError, "Object storage provider '#{provider}' is not supported " \
|
||||
"when 'direct_upload' is used for '#{uploader_type}'. #{supported_provider_text}"
|
||||
|
@ -25,12 +25,8 @@ class DirectUploadsValidator
|
|||
|
||||
private
|
||||
|
||||
def provider_loaded?(provider)
|
||||
return false unless SUPPORTED_DIRECT_UPLOAD_PROVIDERS.include?(provider)
|
||||
|
||||
require 'fog/azurerm' if provider == ObjectStorage::Config::AZURE_PROVIDER
|
||||
|
||||
true
|
||||
def provider_supported?(provider)
|
||||
SUPPORTED_DIRECT_UPLOAD_PROVIDERS.include?(provider)
|
||||
end
|
||||
|
||||
def supported_provider_text
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
require './spec/support/sidekiq_middleware'
|
||||
|
||||
Gitlab::Seeder.quiet do
|
||||
EMOJI = Gitlab::Emoji.emojis.keys
|
||||
|
||||
def seed_award_emoji(klass)
|
||||
klass.order(Gitlab::Database.random).limit(klass.count / 2).each do |awardable|
|
||||
awardable.project.authorized_users.where('project_authorizations.access_level > ?', Gitlab::Access::GUEST).sample(2).each do |user|
|
||||
AwardEmojis::AddService.new(awardable, EMOJI.sample, user).execute
|
||||
AwardEmojis::AddService.new(awardable, TanukiEmoji.index.all.sample.name, user).execute
|
||||
|
||||
awardable.notes.user.sample(2).each do |note|
|
||||
AwardEmojis::AddService.new(note, EMOJI.sample, user).execute
|
||||
AwardEmojis::AddService.new(note, TanukiEmoji.index.all.sample.name, user).execute
|
||||
end
|
||||
|
||||
print '.'
|
||||
|
|
|
@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# Cluster Image Scanning **(ULTIMATE)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 14.1.
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/) in GitLab 14.1.
|
||||
|
||||
WARNING:
|
||||
This analyzer is in [Alpha](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha)
|
||||
|
@ -208,7 +208,7 @@ The cluster image scanning tool emits a JSON report file. For more information,
|
|||
Here's an example cluster image scanning report:
|
||||
|
||||
```json-doc
|
||||
{{
|
||||
{
|
||||
"version": "14.0.2",
|
||||
"scan": {
|
||||
"scanner": {
|
||||
|
|
|
@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# Container Scanning **(ULTIMATE)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3672) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.4.
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3672) in GitLab 10.4.
|
||||
|
||||
Your application's Docker image may itself be based on Docker images that contain known
|
||||
vulnerabilities. By including an extra job in your pipeline that scans for those vulnerabilities and
|
||||
|
@ -148,7 +148,7 @@ Support depends on the scanner:
|
|||
|
||||
#### UBI-based images
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5775) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 14.1.
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5775) in GitLab 14.1.
|
||||
|
||||
GitLab also offers [Red Hat UBI](https://www.redhat.com/en/blog/introducing-red-hat-universal-base-image)
|
||||
versions of the container-scanning images. You can therefore replace standard images with UBI-based
|
||||
|
|
|
@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# Policies **(ULTIMATE)**
|
||||
|
||||
> - Introduced in GitLab Ultimate 13.10 [with a flag](https://gitlab.com/groups/gitlab-org/-/epics/5329) named `security_orchestration_policies_configuration`. Disabled by default.
|
||||
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/321258) in GitLab Ultimate 14.3.
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5329) in GitLab 13.10 with a flag named `security_orchestration_policies_configuration`. Disabled by default.
|
||||
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/321258) in GitLab 14.3.
|
||||
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/321258) in GitLab 14.4.
|
||||
|
||||
Policies in GitLab provide security teams a way to require scans of their choice to be run
|
||||
|
@ -49,7 +49,7 @@ users must make changes by following the
|
|||
|
||||
## Policy editor
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3403) in GitLab Ultimate 13.4.
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3403) in GitLab 13.4.
|
||||
|
||||
You can use the policy editor to create, edit, and delete policies:
|
||||
|
||||
|
@ -79,7 +79,7 @@ mode to fix your policy before Rule mode is available again.
|
|||
|
||||
## Container Network Policy
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32365) in GitLab Ultimate 12.9.
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32365) in GitLab 12.9.
|
||||
|
||||
The **Container Network Policy** section provides packet flow metrics for
|
||||
your application's Kubernetes namespace. This section has the following
|
||||
|
@ -154,7 +154,7 @@ at the bottom of the editor.
|
|||
|
||||
### Configure a Network Policy Alert
|
||||
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) and [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in GitLab Ultimate 13.9.
|
||||
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) and [enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in GitLab 13.9.
|
||||
> - The feature flag was removed and the Threat Monitoring Alerts Project was [made generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/287676) in GitLab 14.0.
|
||||
|
||||
You can use policy alerts to track your policy's impact. Alerts are only available if you've
|
||||
|
|
|
@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# Threat Monitoring **(ULTIMATE)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14707) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9.
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14707) in GitLab 12.9.
|
||||
|
||||
The **Threat Monitoring** page provides alerts and metrics
|
||||
for the GitLab application runtime security features. You can access
|
||||
|
@ -20,7 +20,7 @@ GitLab supports statistics for the following security features:
|
|||
|
||||
## Container Network Policy Alert list
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.9.
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3438) in GitLab 13.9.
|
||||
|
||||
The policy alert list displays your policy's alert activity. You can sort the list by these columns:
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
stage: Create
|
||||
group: Code Review
|
||||
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
|
||||
---
|
||||
|
||||
# GitLab Workflow VS Code extension **(FREE)**
|
||||
|
||||
The [GitLab VS Code Extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)
|
||||
integrates GitLab with Visual Studio Code. You can decrease context switching and
|
||||
do more day-to-day tasks in Visual Studio Code, such as:
|
||||
|
||||
- [View issues](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#browse-issues-review-mrs).
|
||||
- Run [common commands](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#commands)
|
||||
from the Visual Studio Code [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
|
||||
- Create and [review](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#merge-request-reviews)
|
||||
merge requests directly from Visual Studio Code.
|
||||
- [Validate your GitLab CI configuration](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#validate-gitlab-ci-configuration).
|
||||
- [View the status of your pipeline](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#information-about-your-branch-pipelines-mr-closing-issue).
|
||||
- [Create](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#create-snippet)
|
||||
and paste snippets to, and from, your editor.
|
||||
- [Browse repositories](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#browse-a-repository-without-cloning)
|
||||
without cloning them.
|
||||
|
||||
## Download the extension
|
||||
|
||||
Download the extension from the [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow).
|
||||
|
||||
## Configure the extension
|
||||
|
||||
After you [download the extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)
|
||||
you can [configure](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#extension-settings):
|
||||
|
||||
- [Features to display or hide](https://gitlab.com/gitlab-org/gitlab-vscode-extension#extension-settings).
|
||||
- [Self-signed certificate](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#self-signed-certificates) information.
|
||||
|
||||
## Report issues with the extension
|
||||
|
||||
Report any issues, bugs, or feature requests in the
|
||||
[`gitlab-vscode-extension` issue queue](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues).
|
||||
|
||||
## Resources
|
||||
|
||||
- [Download the extension](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)
|
||||
- [Extension documentation](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/blob/main/README.md)
|
||||
- The extension source code is available in the
|
||||
[`gitlab-vscode-extension`](https://gitlab.com/gitlab-org/gitlab-vscode-extension/) project.
|
File diff suppressed because it is too large
Load Diff
|
@ -210,9 +210,7 @@ module Backup
|
|||
|
||||
def object_storage_config
|
||||
@object_storage_config ||= begin
|
||||
config = ObjectStorage::Config.new(Gitlab.config.backup.upload)
|
||||
config.load_provider
|
||||
config
|
||||
ObjectStorage::Config.new(Gitlab.config.backup.upload)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@ module Banzai
|
|||
# Based on HTML::Pipeline::EmojiFilter
|
||||
class EmojiFilter < HTML::Pipeline::Filter
|
||||
IGNORED_ANCESTOR_TAGS = %w(pre code tt).to_set
|
||||
IGNORE_UNICODE_EMOJIS = %w(™ © ®).freeze
|
||||
|
||||
def call
|
||||
doc.xpath('descendant-or-self::text()').each do |node|
|
||||
|
@ -35,7 +34,8 @@ module Banzai
|
|||
def emoji_name_element_unicode_filter(text)
|
||||
text.gsub(emoji_pattern) do |match|
|
||||
name = Regexp.last_match(1)
|
||||
Gitlab::Emoji.gl_emoji_tag(name)
|
||||
emoji = TanukiEmoji.find_by_alpha_code(name)
|
||||
Gitlab::Emoji.gl_emoji_tag(emoji)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -46,26 +46,19 @@ module Banzai
|
|||
# Returns a String with unicode emoji replaced with gl-emoji unicode.
|
||||
def emoji_unicode_element_unicode_filter(text)
|
||||
text.gsub(emoji_unicode_pattern) do |moji|
|
||||
emoji_info = Gitlab::Emoji.emojis_by_moji[moji]
|
||||
Gitlab::Emoji.gl_emoji_tag(emoji_info['name'])
|
||||
emoji = TanukiEmoji.find_by_codepoints(moji)
|
||||
Gitlab::Emoji.gl_emoji_tag(emoji)
|
||||
end
|
||||
end
|
||||
|
||||
# Build a regexp that matches all valid :emoji: names.
|
||||
def self.emoji_pattern
|
||||
@emoji_pattern ||=
|
||||
%r{(?<=[^[:alnum:]:]|\n|^)
|
||||
:(#{Gitlab::Emoji.emojis_names.map { |name| Regexp.escape(name) }.join('|')}):
|
||||
(?=[^[:alnum:]:]|$)}x
|
||||
@emoji_pattern ||= TanukiEmoji.index.alpha_code_pattern
|
||||
end
|
||||
|
||||
# Build a regexp that matches all valid unicode emojis names.
|
||||
def self.emoji_unicode_pattern
|
||||
@emoji_unicode_pattern ||=
|
||||
begin
|
||||
filtered_emojis = Gitlab::Emoji.emojis_unicodes - IGNORE_UNICODE_EMOJIS
|
||||
/(#{filtered_emojis.map { |moji| Regexp.escape(moji) }.join('|')})/
|
||||
end
|
||||
@emoji_unicode_pattern ||= TanukiEmoji.index.codepoints_pattern
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -4,40 +4,15 @@ module Gitlab
|
|||
module Emoji
|
||||
extend self
|
||||
|
||||
def emojis
|
||||
Gemojione.index.instance_variable_get(:@emoji_by_name)
|
||||
end
|
||||
# When updating emoji assets increase the version below
|
||||
# and update the version number in `app/assets/javascripts/emoji/index.js`
|
||||
EMOJI_VERSION = 1
|
||||
|
||||
def emojis_by_moji
|
||||
Gemojione.index.instance_variable_get(:@emoji_by_moji)
|
||||
end
|
||||
|
||||
def emojis_unicodes
|
||||
emojis_by_moji.keys
|
||||
end
|
||||
|
||||
def emojis_names
|
||||
emojis.keys
|
||||
end
|
||||
|
||||
def emojis_aliases
|
||||
@emoji_aliases ||= Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'aliases.json')))
|
||||
end
|
||||
|
||||
def emoji_filename(name)
|
||||
emojis[name]["unicode"]
|
||||
end
|
||||
|
||||
def emoji_unicode_filename(moji)
|
||||
emojis_by_moji[moji]["unicode"]
|
||||
end
|
||||
|
||||
def emoji_unicode_version(name)
|
||||
emoji_unicode_versions_by_name[name]
|
||||
end
|
||||
|
||||
def normalize_emoji_name(name)
|
||||
emojis_aliases[name] || name
|
||||
# Return a Pathname to emoji's current versioned folder
|
||||
#
|
||||
# @return [Pathname] Absolute Path to versioned emojis folder in `public`
|
||||
def emoji_public_absolute_path
|
||||
Rails.root.join("public/-/emojis/#{EMOJI_VERSION}")
|
||||
end
|
||||
|
||||
def emoji_image_tag(name, src)
|
||||
|
@ -54,23 +29,19 @@ module Gitlab
|
|||
ActionController::Base.helpers.tag(:img, image_options)
|
||||
end
|
||||
|
||||
def emoji_exists?(name)
|
||||
emojis.has_key?(name)
|
||||
end
|
||||
|
||||
# CSS sprite fallback takes precedence over image fallback
|
||||
def gl_emoji_tag(name, options = {})
|
||||
emoji_name = emojis_aliases[name] || name
|
||||
emoji_info = emojis[emoji_name]
|
||||
return unless emoji_info
|
||||
# @param [TanukiEmoji::Character] emoji
|
||||
# @param [Hash] options
|
||||
def gl_emoji_tag(emoji, options = {})
|
||||
return unless emoji
|
||||
|
||||
data = {
|
||||
name: emoji_name,
|
||||
unicode_version: emoji_unicode_version(emoji_name)
|
||||
name: emoji.name,
|
||||
unicode_version: emoji.unicode_version
|
||||
}
|
||||
options = { title: emoji_info['description'], data: data }.merge(options)
|
||||
options = { title: emoji.description, data: data }.merge(options)
|
||||
|
||||
ActionController::Base.helpers.content_tag('gl-emoji', emoji_info['moji'], options)
|
||||
ActionController::Base.helpers.content_tag('gl-emoji', emoji.codepoints, options)
|
||||
end
|
||||
|
||||
def custom_emoji_tag(name, image_source)
|
||||
|
@ -82,12 +53,5 @@ module Gitlab
|
|||
emoji_image_tag(name, image_source).html_safe
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def emoji_unicode_versions_by_name
|
||||
@emoji_unicode_versions_by_name ||=
|
||||
Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'emoji-unicode-version-map.json')))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -56,20 +56,10 @@ module Gitlab
|
|||
end
|
||||
|
||||
def download(url, upload_path)
|
||||
File.open(upload_path, 'wb') do |file|
|
||||
Gitlab::HTTP.get(url, stream_body: true) do |fragment|
|
||||
if [301, 302, 307].include?(fragment.code)
|
||||
Gitlab::Import::Logger.warn(message: "received redirect fragment", fragment_code: fragment.code)
|
||||
elsif fragment.code == 200
|
||||
file.write(fragment)
|
||||
else
|
||||
raise Gitlab::ImportExport::Error, "unsupported response downloading fragment #{fragment.code}"
|
||||
end
|
||||
end
|
||||
File.open(upload_path, 'w') do |file|
|
||||
# Download (stream) file from the uploader's location
|
||||
IO.copy_stream(URI.parse(url).open, file)
|
||||
end
|
||||
rescue StandardError => e
|
||||
@shared.error(e) # rubocop:disable Gitlab/ModuleWithInstanceVariables
|
||||
raise e
|
||||
end
|
||||
|
||||
def tar_with_options(archive:, dir:, options:)
|
||||
|
|
|
@ -12,16 +12,6 @@ module ObjectStorage
|
|||
@options = options.to_hash.deep_symbolize_keys
|
||||
end
|
||||
|
||||
def load_provider
|
||||
if aws?
|
||||
require 'fog/aws'
|
||||
elsif google?
|
||||
require 'fog/google'
|
||||
elsif azure?
|
||||
require 'fog/azurerm'
|
||||
end
|
||||
end
|
||||
|
||||
def credentials
|
||||
@credentials ||= options[:connection] || {}
|
||||
end
|
||||
|
|
|
@ -1,245 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
namespace :gemojione do
|
||||
desc 'Generates Emoji SHA256 digests'
|
||||
|
||||
task aliases: ['yarn:check', 'environment'] do
|
||||
require 'json'
|
||||
|
||||
aliases = {}
|
||||
|
||||
index_file = File.join(Rails.root, 'fixtures', 'emojis', 'index.json')
|
||||
index = Gitlab::Json.parse(File.read(index_file))
|
||||
|
||||
index.each_pair do |key, data|
|
||||
data['aliases'].each do |a|
|
||||
a.tr!(':', '')
|
||||
|
||||
aliases[a] = key
|
||||
end
|
||||
end
|
||||
|
||||
out = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json')
|
||||
File.open(out, 'w') do |handle|
|
||||
handle.write(Gitlab::Json.pretty_generate(aliases, indent: ' ', space: '', space_before: ''))
|
||||
end
|
||||
end
|
||||
|
||||
task digests: ['yarn:check', 'environment'] do
|
||||
require 'digest/sha2'
|
||||
require 'json'
|
||||
|
||||
# We don't have `node_modules` available in built versions of GitLab
|
||||
FileUtils.cp_r(Rails.root.join('node_modules', 'emoji-unicode-version', 'emoji-unicode-version-map.json'), File.join(Rails.root, 'fixtures', 'emojis'))
|
||||
|
||||
dir = Gemojione.images_path
|
||||
resultant_emoji_map = {}
|
||||
resultant_emoji_map_new = {}
|
||||
|
||||
Gitlab::Emoji.emojis.each do |name, emoji_hash|
|
||||
# Ignore aliases
|
||||
unless Gitlab::Emoji.emojis_aliases.key?(name)
|
||||
fpath = File.join(dir, "#{emoji_hash['unicode']}.png")
|
||||
hash_digest = Digest::SHA256.file(fpath).hexdigest
|
||||
|
||||
category = emoji_hash['category']
|
||||
if name == 'gay_pride_flag'
|
||||
category = 'flags'
|
||||
end
|
||||
|
||||
entry = {
|
||||
category: category,
|
||||
moji: emoji_hash['moji'],
|
||||
description: emoji_hash['description'],
|
||||
unicodeVersion: Gitlab::Emoji.emoji_unicode_version(name),
|
||||
digest: hash_digest
|
||||
}
|
||||
|
||||
resultant_emoji_map[name] = entry
|
||||
|
||||
# Our new map is only characters to make the json substantially smaller
|
||||
new_entry = {
|
||||
c: category,
|
||||
e: emoji_hash['moji'],
|
||||
d: emoji_hash['description'],
|
||||
u: Gitlab::Emoji.emoji_unicode_version(name)
|
||||
}
|
||||
|
||||
resultant_emoji_map_new[name] = new_entry
|
||||
end
|
||||
end
|
||||
|
||||
out = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json')
|
||||
File.open(out, 'w') do |handle|
|
||||
handle.write(Gitlab::Json.pretty_generate(resultant_emoji_map))
|
||||
end
|
||||
|
||||
out_new = File.join(Rails.root, 'public', '-', 'emojis', '1', 'emojis.json')
|
||||
File.open(out_new, 'w') do |handle|
|
||||
handle.write(Gitlab::Json.pretty_generate(resultant_emoji_map_new))
|
||||
end
|
||||
end
|
||||
|
||||
# This task will generate a standard and Retina sprite of all of the current
|
||||
# Gemojione Emojis, with the accompanying SCSS map.
|
||||
#
|
||||
# It will not appear in `rake -T` output, and the dependent gems are not
|
||||
# included in the Gemfile by default, because this task will only be needed
|
||||
# occasionally, such as when new Emojis are added to Gemojione.
|
||||
task sprite: :environment do
|
||||
begin
|
||||
require 'sprite_factory'
|
||||
require 'rmagick'
|
||||
rescue LoadError
|
||||
# noop
|
||||
end
|
||||
|
||||
check_requirements!
|
||||
|
||||
SIZE = 20
|
||||
RETINA = SIZE * 2
|
||||
|
||||
# Update these values to the width and height of the spritesheet when
|
||||
# new emoji are added.
|
||||
SPRITESHEET_WIDTH = 860
|
||||
SPRITESHEET_HEIGHT = 840
|
||||
|
||||
# Set up a map to rename image files
|
||||
emoji_unicode_string_to_name_map = {}
|
||||
Gitlab::Emoji.emojis.each do |name, emoji_hash|
|
||||
# Ignore aliases
|
||||
unless Gitlab::Emoji.emojis_aliases.key?(name)
|
||||
emoji_unicode_string_to_name_map[emoji_hash['unicode']] = name
|
||||
end
|
||||
end
|
||||
|
||||
# Copy the Gemojione assets to the temporary folder for renaming
|
||||
emoji_dir = "app/assets/images/emoji"
|
||||
FileUtils.rm_rf(emoji_dir)
|
||||
FileUtils.mkdir_p(emoji_dir, mode: 0700)
|
||||
FileUtils.cp_r(File.join(Gemojione.images_path, '.'), emoji_dir)
|
||||
Dir[File.join(emoji_dir, "**/*.png")].each do |png|
|
||||
image_path = png
|
||||
rename_to_named_emoji_image!(emoji_unicode_string_to_name_map, image_path)
|
||||
end
|
||||
|
||||
Dir.mktmpdir do |tmpdir|
|
||||
FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
|
||||
|
||||
Dir.chdir(tmpdir) do
|
||||
Dir["**/*.png"].each do |png|
|
||||
tmp_image_path = File.join(tmpdir, png)
|
||||
resize!(tmp_image_path, SIZE)
|
||||
end
|
||||
end
|
||||
|
||||
style_path = Rails.root.join(*%w(app assets stylesheets framework emoji_sprites.scss))
|
||||
|
||||
# Combine the resized assets into a packed sprite and re-generate the SCSS
|
||||
SpriteFactory.cssurl = "image-url('$IMAGE')"
|
||||
SpriteFactory.run!(tmpdir, {
|
||||
output_style: style_path,
|
||||
output_image: "app/assets/images/emoji.png",
|
||||
selector: '.emoji-',
|
||||
style: :scss,
|
||||
nocomments: true,
|
||||
pngcrush: true,
|
||||
layout: :packed
|
||||
})
|
||||
|
||||
# SpriteFactory's SCSS is a bit too verbose for our purposes here, so
|
||||
# let's simplify it
|
||||
system(%Q(sed -i '' "s/width: #{SIZE}px; height: #{SIZE}px; background: image-url('emoji.png')/background-position:/" #{style_path}))
|
||||
system(%Q(sed -i '' "s/ no-repeat//" #{style_path}))
|
||||
system(%Q(sed -i '' "s/ 0px/ 0/g" #{style_path}))
|
||||
|
||||
# Append a generic rule that applies to all Emojis
|
||||
File.open(style_path, 'a') do |f|
|
||||
f.puts
|
||||
f.puts <<-CSS.strip_heredoc
|
||||
.emoji-icon {
|
||||
background-image: image-url('emoji.png');
|
||||
background-repeat: no-repeat;
|
||||
color: transparent;
|
||||
text-indent: -99em;
|
||||
height: #{SIZE}px;
|
||||
width: #{SIZE}px;
|
||||
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: 2),
|
||||
only screen and (min--moz-device-pixel-ratio: 2),
|
||||
only screen and (-o-min-device-pixel-ratio: 2/1),
|
||||
only screen and (min-device-pixel-ratio: 2),
|
||||
only screen and (min-resolution: 192dpi),
|
||||
only screen and (min-resolution: 2dppx) {
|
||||
background-image: image-url('emoji@2x.png');
|
||||
background-size: #{SPRITESHEET_WIDTH}px #{SPRITESHEET_HEIGHT}px;
|
||||
}
|
||||
}
|
||||
CSS
|
||||
end
|
||||
end
|
||||
|
||||
# Now do it again but for Retina
|
||||
Dir.mktmpdir do |tmpdir|
|
||||
# Copy the Gemojione assets to the temporary folder for resizing
|
||||
FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
|
||||
|
||||
Dir.chdir(tmpdir) do
|
||||
Dir["**/*.png"].each do |png|
|
||||
tmp_image_path = File.join(tmpdir, png)
|
||||
resize!(tmp_image_path, RETINA)
|
||||
end
|
||||
end
|
||||
|
||||
# Combine the resized assets into a packed sprite and re-generate the SCSS
|
||||
SpriteFactory.run!(tmpdir, {
|
||||
output_image: "app/assets/images/emoji@2x.png",
|
||||
style: false,
|
||||
nocomments: true,
|
||||
pngcrush: true,
|
||||
layout: :packed
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
def check_requirements!
|
||||
return if defined?(SpriteFactory) && defined?(Magick)
|
||||
|
||||
puts <<-MSG.strip_heredoc
|
||||
This task is disabled by default and should only be run when the Gemojione
|
||||
gem is updated with new Emojis.
|
||||
|
||||
To enable this task, *temporarily* add the following lines to Gemfile and
|
||||
re-bundle:
|
||||
|
||||
gem 'sprite-factory'
|
||||
gem 'rmagick'
|
||||
MSG
|
||||
|
||||
exit 1
|
||||
end
|
||||
|
||||
def resize!(image_path, size)
|
||||
# Resize the image in-place, save it, and free the object
|
||||
image = Magick::Image.read(image_path).first
|
||||
image.resize!(size, size)
|
||||
image.write(image_path) { self.quality = 100 }
|
||||
image.destroy!
|
||||
end
|
||||
|
||||
EMOJI_IMAGE_PATH_RE = /(.*?)(([0-9a-f]-?)+)\.png$/i.freeze
|
||||
def rename_to_named_emoji_image!(emoji_unicode_string_to_name_map, image_path)
|
||||
# Rename file from unicode to emoji name
|
||||
matches = EMOJI_IMAGE_PATH_RE.match(image_path)
|
||||
preceding_path = matches[1]
|
||||
unicode_string = matches[2]
|
||||
name = emoji_unicode_string_to_name_map[unicode_string]
|
||||
if name
|
||||
new_png_path = File.join(preceding_path, "#{name}.png")
|
||||
FileUtils.mv(image_path, new_png_path)
|
||||
new_png_path
|
||||
else
|
||||
puts "Warning: emoji_unicode_string_to_name_map missing entry for #{unicode_string}. Full path: #{image_path}"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,260 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
namespace :tanuki_emoji do
|
||||
desc 'Generates Emoji aliases fixtures'
|
||||
task aliases: :environment do
|
||||
aliases = {}
|
||||
|
||||
TanukiEmoji.index.all.each do |emoji|
|
||||
emoji.aliases.each do |emoji_alias|
|
||||
aliases[TanukiEmoji::Character.format_name(emoji_alias)] = emoji.name
|
||||
end
|
||||
end
|
||||
|
||||
aliases_json_file = File.join(Rails.root, 'fixtures', 'emojis', 'aliases.json')
|
||||
File.open(aliases_json_file, 'w') do |handle|
|
||||
handle.write(Gitlab::Json.pretty_generate(aliases, indent: ' ', space: '', space_before: ''))
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Generates Emoji SHA256 digests'
|
||||
task digests: :environment do
|
||||
require 'digest/sha2'
|
||||
|
||||
digest_emoji_map = {}
|
||||
emojis_map = {}
|
||||
|
||||
TanukiEmoji.index.all.each do |emoji|
|
||||
emoji_path = Gitlab::Emoji.emoji_public_absolute_path.join("#{emoji.name}.png")
|
||||
|
||||
digest_entry = {
|
||||
category: emoji.category,
|
||||
moji: emoji.codepoints,
|
||||
description: emoji.description,
|
||||
unicodeVersion: emoji.unicode_version,
|
||||
digest: Digest::SHA256.file(emoji_path).hexdigest
|
||||
}
|
||||
|
||||
digest_emoji_map[emoji.name] = digest_entry
|
||||
|
||||
# Our new map is only characters to make the json substantially smaller
|
||||
emoji_entry = {
|
||||
c: emoji.category,
|
||||
e: emoji.codepoints,
|
||||
d: emoji.description,
|
||||
u: emoji.unicode_version
|
||||
}
|
||||
|
||||
emojis_map[emoji.name] = emoji_entry
|
||||
end
|
||||
|
||||
digests_json = File.join(Rails.root, 'fixtures', 'emojis', 'digests.json')
|
||||
File.open(digests_json, 'w') do |handle|
|
||||
handle.write(Gitlab::Json.pretty_generate(digest_emoji_map))
|
||||
end
|
||||
|
||||
emojis_json = Gitlab::Emoji.emoji_public_absolute_path.join('emojis.json')
|
||||
File.open(emojis_json, 'w') do |handle|
|
||||
handle.write(Gitlab::Json.pretty_generate(emojis_map))
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Import emoji assets from TanukiEmoji to versioned folder'
|
||||
task import: :environment do
|
||||
require 'mini_magick'
|
||||
|
||||
# Setting to the same size as previous gemojione images
|
||||
EMOJI_SIZE = 64
|
||||
|
||||
emoji_dir = Gitlab::Emoji.emoji_public_absolute_path
|
||||
|
||||
puts "Importing emojis into: #{emoji_dir} ..."
|
||||
|
||||
# Re-create the assets folder and copy emojis renaming them to use name instead of unicode hex
|
||||
FileUtils.rm_rf(emoji_dir) if Dir.exist?(emoji_dir)
|
||||
FileUtils.mkdir_p(emoji_dir, mode: 0700)
|
||||
|
||||
TanukiEmoji.index.all.each do |emoji|
|
||||
source = File.join(TanukiEmoji.images_path, emoji.image_name)
|
||||
destination = File.join(emoji_dir, "#{emoji.name}.png")
|
||||
|
||||
FileUtils.cp(source, destination)
|
||||
resize!(destination, EMOJI_SIZE)
|
||||
print emoji.codepoints
|
||||
end
|
||||
|
||||
puts
|
||||
puts 'Done!'
|
||||
end
|
||||
|
||||
# This task will generate a standard and Retina sprite of all of the current
|
||||
# TanukiEmoji Emojis, with the accompanying SCSS map.
|
||||
#
|
||||
# It will not appear in `rake -T` output, and the dependent gems are not
|
||||
# included in the Gemfile by default, because this task will only be needed
|
||||
# occasionally, such as when new Emojis are added to TanukiEmoji.
|
||||
task sprite: :environment do
|
||||
begin
|
||||
require 'sprite_factory'
|
||||
# Sprite-Factory still requires rmagick, but maybe could be migrated to support minimagick
|
||||
# Upstream issue: https://github.com/jakesgordon/sprite-factory/issues/47#issuecomment-929302890
|
||||
require 'rmagick'
|
||||
rescue LoadError
|
||||
# noop
|
||||
end
|
||||
|
||||
check_requirements!
|
||||
|
||||
SIZE = 20
|
||||
RETINA = SIZE * 2
|
||||
|
||||
# Update these values to the width and height of the spritesheet when
|
||||
# new emoji are added.
|
||||
SPRITESHEET_WIDTH = 860
|
||||
SPRITESHEET_HEIGHT = 840
|
||||
|
||||
emoji_dir = Gitlab::Emoji.emoji_public_absolute_path
|
||||
|
||||
puts "Preparing sprites for regular size: #{SIZE}px..."
|
||||
|
||||
Dir.mktmpdir do |tmpdir|
|
||||
FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
|
||||
|
||||
Dir.chdir(tmpdir) do
|
||||
Dir["**/*.png"].each do |png|
|
||||
tmp_image_path = File.join(tmpdir, png)
|
||||
resize!(tmp_image_path, SIZE)
|
||||
print '.'
|
||||
end
|
||||
end
|
||||
puts ' Done!'
|
||||
|
||||
puts "\n"
|
||||
|
||||
style_path = Rails.root.join(*%w(app assets stylesheets emoji_sprites.scss))
|
||||
|
||||
print 'Compiling sprites regular sprites... '
|
||||
|
||||
# Combine the resized assets into a packed sprite and re-generate the SCSS
|
||||
SpriteFactory.cssurl = "image-url('$IMAGE')"
|
||||
SpriteFactory.run!(tmpdir, {
|
||||
output_style: style_path,
|
||||
output_image: "app/assets/images/emoji.png",
|
||||
selector: '.emoji-',
|
||||
style: :scss,
|
||||
nocomments: true,
|
||||
pngcrush: true,
|
||||
layout: :packed
|
||||
})
|
||||
|
||||
# SpriteFactory's SCSS is a bit too verbose for our purposes here, so
|
||||
# let's simplify it
|
||||
system(%Q(sed -i '' "s/width: #{SIZE}px; height: #{SIZE}px; background: image-url('emoji.png')/background-position:/" #{style_path}))
|
||||
system(%Q(sed -i '' "s/ no-repeat//" #{style_path}))
|
||||
system(%Q(sed -i '' "s/ 0px/ 0/g" #{style_path}))
|
||||
|
||||
# Append a generic rule that applies to all Emojis
|
||||
File.open(style_path, 'a') do |f|
|
||||
f.puts
|
||||
f.puts <<-CSS.strip_heredoc
|
||||
.emoji-icon {
|
||||
background-image: image-url('emoji.png');
|
||||
background-repeat: no-repeat;
|
||||
color: transparent;
|
||||
text-indent: -99em;
|
||||
height: #{SIZE}px;
|
||||
width: #{SIZE}px;
|
||||
|
||||
/* stylelint-disable media-feature-name-no-vendor-prefix */
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: 2),
|
||||
only screen and (min--moz-device-pixel-ratio: 2),
|
||||
only screen and (-o-min-device-pixel-ratio: 2/1),
|
||||
only screen and (min-device-pixel-ratio: 2),
|
||||
only screen and (min-resolution: 192dpi),
|
||||
only screen and (min-resolution: 2dppx) {
|
||||
background-image: image-url('emoji@2x.png');
|
||||
background-size: #{SPRITESHEET_WIDTH}px #{SPRITESHEET_HEIGHT}px;
|
||||
}
|
||||
/* stylelint-enable media-feature-name-no-vendor-prefix */
|
||||
}
|
||||
CSS
|
||||
end
|
||||
end
|
||||
puts 'Done!'
|
||||
|
||||
puts "\n"
|
||||
|
||||
puts "Preparing sprites for HiDPI size: #{RETINA}px..."
|
||||
|
||||
# Now do it again but for Retina
|
||||
Dir.mktmpdir do |tmpdir|
|
||||
# Copy the TanukiEmoji assets to the temporary folder for resizing
|
||||
FileUtils.cp_r(File.join(emoji_dir, '.'), tmpdir)
|
||||
|
||||
Dir.chdir(tmpdir) do
|
||||
Dir["**/*.png"].each do |png|
|
||||
tmp_image_path = File.join(tmpdir, png)
|
||||
resize!(tmp_image_path, RETINA)
|
||||
print '.'
|
||||
end
|
||||
end
|
||||
puts ' Done!'
|
||||
|
||||
puts "\n"
|
||||
|
||||
print 'Compiling HiDPI sprites...'
|
||||
|
||||
# Combine the resized assets into a packed sprite and re-generate the SCSS
|
||||
SpriteFactory.run!(tmpdir, {
|
||||
output_image: "app/assets/images/emoji@2x.png",
|
||||
style: false,
|
||||
nocomments: true,
|
||||
pngcrush: true,
|
||||
layout: :packed
|
||||
})
|
||||
end
|
||||
|
||||
puts ' Done!'
|
||||
end
|
||||
|
||||
def check_requirements!
|
||||
unless defined?(Magick)
|
||||
puts <<~MSG
|
||||
This task is disabled by default and should only be run when the TanukiEmoji
|
||||
gem is updated with new Emojis.
|
||||
|
||||
To enable this task, *temporarily* add the following lines to Gemfile and
|
||||
re-bundle:
|
||||
|
||||
gem 'rmagick', '~> 3.2'
|
||||
|
||||
It depends on ImageMagick 6, which can be installed via HomeBrew with:
|
||||
|
||||
brew unlink imagemagick
|
||||
brew install imagemagick@6 && brew link imagemagick@6 --force
|
||||
MSG
|
||||
|
||||
exit 1
|
||||
end
|
||||
|
||||
return if Dir.exist? Gitlab::Emoji.emoji_public_absolute_path
|
||||
|
||||
puts <<~MSG
|
||||
You first need to import the assets for Emoji version: #{Gitlab::Emoji::EMOJI_VERSION}
|
||||
|
||||
Run the following task:
|
||||
|
||||
rake tanuki_emoji:import
|
||||
MSG
|
||||
|
||||
exit 1
|
||||
end
|
||||
|
||||
def resize!(image_path, size)
|
||||
# Resize the image in-place, save it, and free the object
|
||||
image = MiniMagick::Image.open(image_path)
|
||||
image.quality(100)
|
||||
image.resize("#{size}x#{size}")
|
||||
image.write(image_path)
|
||||
end
|
||||
end
|
|
@ -128,7 +128,6 @@
|
|||
"dropzone": "^4.2.0",
|
||||
"editorconfig": "^0.15.3",
|
||||
"emoji-regex": "^7.0.3",
|
||||
"emoji-unicode-version": "^0.2.1",
|
||||
"fast-mersenne-twister": "1.0.2",
|
||||
"file-loader": "^6.2.0",
|
||||
"fuzzaldrin-plus": "^0.6.0",
|
||||
|
|
|
@ -56,13 +56,13 @@ describe('gl_emoji', () => {
|
|||
'bomb emoji just with name attribute',
|
||||
'<gl-emoji data-name="bomb"></gl-emoji>',
|
||||
'<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb">💣</gl-emoji>',
|
||||
'<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/1/bomb.png" width="20" height="20" align="absmiddle"></gl-emoji>',
|
||||
`<gl-emoji data-name="bomb" data-unicode-version="6.0" title="bomb"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" width="20" height="20" align="absmiddle"></gl-emoji>`,
|
||||
],
|
||||
[
|
||||
'bomb emoji with name attribute and unicode version',
|
||||
'<gl-emoji data-name="bomb" data-unicode-version="6.0">💣</gl-emoji>',
|
||||
'<gl-emoji data-name="bomb" data-unicode-version="6.0">💣</gl-emoji>',
|
||||
'<gl-emoji data-name="bomb" data-unicode-version="6.0"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/1/bomb.png" width="20" height="20" align="absmiddle"></gl-emoji>',
|
||||
`<gl-emoji data-name="bomb" data-unicode-version="6.0"><img class="emoji" title=":bomb:" alt=":bomb:" src="/-/emojis/${EMOJI_VERSION}/bomb.png" width="20" height="20" align="absmiddle"></gl-emoji>`,
|
||||
],
|
||||
[
|
||||
'bomb emoji with sprite fallback',
|
||||
|
@ -80,7 +80,7 @@ describe('gl_emoji', () => {
|
|||
'invalid emoji',
|
||||
'<gl-emoji data-name="invalid_emoji"></gl-emoji>',
|
||||
'<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament">❔</gl-emoji>',
|
||||
'<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament"><img class="emoji" title=":grey_question:" alt=":grey_question:" src="/-/emojis/1/grey_question.png" width="20" height="20" align="absmiddle"></gl-emoji>',
|
||||
`<gl-emoji data-name="grey_question" data-unicode-version="6.0" title="white question mark ornament"><img class="emoji" title=":grey_question:" alt=":grey_question:" src="/-/emojis/${EMOJI_VERSION}/grey_question.png" width="20" height="20" align="absmiddle"></gl-emoji>`,
|
||||
],
|
||||
])('%s', (name, markup, withEmojiSupport, withoutEmojiSupport) => {
|
||||
it(`renders correctly with emoji support`, async () => {
|
||||
|
|
|
@ -6,6 +6,7 @@ RSpec.describe EmojiHelper do
|
|||
describe '#emoji_icon' do
|
||||
let(:options) { {} }
|
||||
let(:emoji_text) { 'rocket' }
|
||||
let(:unicode_version) { '6.0' }
|
||||
let(:aria_hidden_option) { "aria-hidden=\"true\"" }
|
||||
|
||||
subject { helper.emoji_icon(emoji_text, options) }
|
||||
|
@ -14,7 +15,7 @@ RSpec.describe EmojiHelper do
|
|||
is_expected.to include('<gl-emoji',
|
||||
"title=\"#{emoji_text}\"",
|
||||
"data-name=\"#{emoji_text}\"",
|
||||
"data-unicode-version=\"#{::Gitlab::Emoji.emoji_unicode_version(emoji_text)}\"")
|
||||
"data-unicode-version=\"#{unicode_version}\"")
|
||||
is_expected.not_to include(aria_hidden_option)
|
||||
end
|
||||
|
||||
|
@ -25,7 +26,7 @@ RSpec.describe EmojiHelper do
|
|||
is_expected.to include('<gl-emoji',
|
||||
"title=\"#{emoji_text}\"",
|
||||
"data-name=\"#{emoji_text}\"",
|
||||
"data-unicode-version=\"#{::Gitlab::Emoji.emoji_unicode_version(emoji_text)}\"",
|
||||
"data-unicode-version=\"#{unicode_version}\"",
|
||||
aria_hidden_option)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,9 +15,6 @@ RSpec.describe 'CarrierWave::Storage::Fog::File' do
|
|||
subject { CarrierWave::Storage::Fog::File.new(uploader, storage, test_filename) }
|
||||
|
||||
before do
|
||||
require 'fog/azurerm'
|
||||
require 'fog/aws'
|
||||
|
||||
stub_object_storage(connection_params: connection_options, remote_directory: bucket_name)
|
||||
|
||||
allow(uploader).to receive(:fog_directory).and_return(bucket_name)
|
||||
|
|
|
@ -28,9 +28,9 @@ RSpec.describe Banzai::Filter::EmojiFilter do
|
|||
it 'replaces name versions of trademark, copyright, and registered trademark' do
|
||||
doc = filter('<p>:tm: :copyright: :registered:</p>')
|
||||
|
||||
expect(doc.css('gl-emoji')[0].text).to eq '™'
|
||||
expect(doc.css('gl-emoji')[1].text).to eq '©'
|
||||
expect(doc.css('gl-emoji')[2].text).to eq '®'
|
||||
expect(doc.css('gl-emoji')[0].text).to eq '™️'
|
||||
expect(doc.css('gl-emoji')[1].text).to eq '©️'
|
||||
expect(doc.css('gl-emoji')[2].text).to eq '®️'
|
||||
end
|
||||
|
||||
it 'correctly encodes the URL' do
|
||||
|
|
|
@ -3,18 +3,20 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Banzai::Pipeline::EmojiPipeline do
|
||||
let(:emoji) { TanukiEmoji.find_by_alpha_code('100') }
|
||||
|
||||
def parse(text)
|
||||
described_class.to_html(text, {})
|
||||
end
|
||||
|
||||
it 'replaces emoji' do
|
||||
expected_result = "Hello world #{Gitlab::Emoji.gl_emoji_tag('100')}"
|
||||
expected_result = "Hello world #{Gitlab::Emoji.gl_emoji_tag(emoji)}"
|
||||
|
||||
expect(parse('Hello world :100:')).to eq(expected_result)
|
||||
end
|
||||
|
||||
it 'filters out HTML tags' do
|
||||
expected_result = "Hello <b>world</b> #{Gitlab::Emoji.gl_emoji_tag('100')}"
|
||||
expected_result = "Hello <b>world</b> #{Gitlab::Emoji.gl_emoji_tag(emoji)}"
|
||||
|
||||
expect(parse('Hello <b>world</b> :100:')).to eq(expected_result)
|
||||
end
|
||||
|
|
|
@ -3,90 +3,6 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Emoji do
|
||||
let_it_be(:emojis) { Gemojione.index.instance_variable_get(:@emoji_by_name) }
|
||||
let_it_be(:emojis_by_moji) { Gemojione.index.instance_variable_get(:@emoji_by_moji) }
|
||||
let_it_be(:emoji_unicode_versions_by_name) { Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'emoji-unicode-version-map.json'))) }
|
||||
let_it_be(:emojis_aliases) { Gitlab::Json.parse(File.read(Rails.root.join('fixtures', 'emojis', 'aliases.json'))) }
|
||||
|
||||
describe '.emojis' do
|
||||
it 'returns emojis' do
|
||||
current_emojis = described_class.emojis
|
||||
|
||||
expect(current_emojis).to eq(emojis)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.emojis_by_moji' do
|
||||
it 'return emojis by moji' do
|
||||
current_emojis_by_moji = described_class.emojis_by_moji
|
||||
|
||||
expect(current_emojis_by_moji).to eq(emojis_by_moji)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.emojis_unicodes' do
|
||||
it 'returns emoji unicodes' do
|
||||
emoji_keys = described_class.emojis_unicodes
|
||||
|
||||
expect(emoji_keys).to eq(emojis_by_moji.keys)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.emojis_names' do
|
||||
it 'returns emoji names' do
|
||||
emoji_names = described_class.emojis_names
|
||||
|
||||
expect(emoji_names).to eq(emojis.keys)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.emojis_aliases' do
|
||||
it 'returns emoji aliases' do
|
||||
emoji_aliases = described_class.emojis_aliases
|
||||
|
||||
expect(emoji_aliases).to eq(emojis_aliases)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.emoji_filename' do
|
||||
it 'returns emoji filename' do
|
||||
# "100" => {"unicode"=>"1F4AF"...}
|
||||
emoji_filename = described_class.emoji_filename('100')
|
||||
|
||||
expect(emoji_filename).to eq(emojis['100']['unicode'])
|
||||
end
|
||||
end
|
||||
|
||||
describe '.emoji_unicode_filename' do
|
||||
it 'returns emoji unicode filename' do
|
||||
emoji_unicode_filename = described_class.emoji_unicode_filename('💯')
|
||||
|
||||
expect(emoji_unicode_filename).to eq(emojis_by_moji['💯']['unicode'])
|
||||
end
|
||||
end
|
||||
|
||||
describe '.emoji_unicode_version' do
|
||||
it 'returns emoji unicode version by name' do
|
||||
emoji_unicode_version = described_class.emoji_unicode_version('100')
|
||||
|
||||
expect(emoji_unicode_version).to eq(emoji_unicode_versions_by_name['100'])
|
||||
end
|
||||
end
|
||||
|
||||
describe '.normalize_emoji_name' do
|
||||
it 'returns same name if not found in aliases' do
|
||||
emoji_name = described_class.normalize_emoji_name('random')
|
||||
|
||||
expect(emoji_name).to eq('random')
|
||||
end
|
||||
|
||||
it 'returns name if name found in aliases' do
|
||||
emoji_name = described_class.normalize_emoji_name('small_airplane')
|
||||
|
||||
expect(emoji_name).to eq(emojis_aliases['small_airplane'])
|
||||
end
|
||||
end
|
||||
|
||||
describe '.emoji_image_tag' do
|
||||
it 'returns emoji image tag' do
|
||||
emoji_image = described_class.emoji_image_tag('emoji_one', 'src_url')
|
||||
|
@ -104,29 +20,17 @@ RSpec.describe Gitlab::Emoji do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.emoji_exists?' do
|
||||
it 'returns true if the name exists' do
|
||||
emoji_exists = described_class.emoji_exists?('100')
|
||||
|
||||
expect(emoji_exists).to be_truthy
|
||||
end
|
||||
|
||||
it 'returns false if the name does not exist' do
|
||||
emoji_exists = described_class.emoji_exists?('random')
|
||||
|
||||
expect(emoji_exists).to be_falsey
|
||||
end
|
||||
end
|
||||
|
||||
describe '.gl_emoji_tag' do
|
||||
it 'returns gl emoji tag if emoji is found' do
|
||||
gl_tag = described_class.gl_emoji_tag('small_airplane')
|
||||
emoji = TanukiEmoji.find_by_alpha_code('small_airplane')
|
||||
gl_tag = described_class.gl_emoji_tag(emoji)
|
||||
|
||||
expect(gl_tag).to eq('<gl-emoji title="small airplane" data-name="airplane_small" data-unicode-version="7.0">🛩</gl-emoji>')
|
||||
end
|
||||
|
||||
it 'returns nil if emoji name is not found' do
|
||||
gl_tag = described_class.gl_emoji_tag('random')
|
||||
it 'returns nil if emoji is not found' do
|
||||
emoji = TanukiEmoji.find_by_alpha_code('random')
|
||||
gl_tag = described_class.gl_emoji_tag(emoji)
|
||||
|
||||
expect(gl_tag).to be_nil
|
||||
end
|
||||
|
|
|
@ -17,10 +17,6 @@ RSpec.describe Gitlab::ImportExport::CommandLineUtil do
|
|||
def initialize
|
||||
@shared = Gitlab::ImportExport::Shared.new(nil)
|
||||
end
|
||||
|
||||
def download(url, upload_path)
|
||||
super(url, upload_path)
|
||||
end
|
||||
end.new
|
||||
end
|
||||
|
||||
|
@ -105,44 +101,4 @@ RSpec.describe Gitlab::ImportExport::CommandLineUtil do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#download' do
|
||||
before do
|
||||
stub_request(:get, loc)
|
||||
.to_return(
|
||||
status: 200,
|
||||
body: content
|
||||
)
|
||||
end
|
||||
|
||||
context 'a non-localhost uri' do
|
||||
let(:loc) { 'https://gitlab.com' }
|
||||
let(:content) { File.open('spec/fixtures/rails_sample.tif') }
|
||||
|
||||
it 'gets the contents' do
|
||||
Tempfile.create("foo") do |f|
|
||||
subject.download(loc, f.path)
|
||||
expect(f.read).to eq(File.open('spec/fixtures/rails_sample.tif').read)
|
||||
end
|
||||
end
|
||||
|
||||
it 'streams the contents' do
|
||||
expect(Gitlab::HTTP).to receive(:get).with(loc, hash_including(stream_body: true))
|
||||
Tempfile.create("foo") do |f|
|
||||
subject.download(loc, f.path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'a localhost uri' do
|
||||
let(:loc) { 'https://localhost:8081/foo/bar' }
|
||||
let(:content) { 'foo' }
|
||||
|
||||
it 'throws a blocked url error' do
|
||||
Tempfile.create("foo") do |f|
|
||||
expect { subject.download(loc, f.path) }.to raise_error(Gitlab::HTTP::BlockedUrlError)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -36,46 +36,6 @@ RSpec.describe ObjectStorage::Config do
|
|||
|
||||
subject { described_class.new(raw_config.as_json) }
|
||||
|
||||
describe '#load_provider' do
|
||||
before do
|
||||
subject.load_provider
|
||||
end
|
||||
|
||||
context 'with AWS' do
|
||||
it 'registers AWS as a provider' do
|
||||
expect(Fog.providers.keys).to include(:aws)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with Google' do
|
||||
let(:credentials) do
|
||||
{
|
||||
provider: 'Google',
|
||||
google_storage_access_key_id: 'GOOGLE_ACCESS_KEY_ID',
|
||||
google_storage_secret_access_key: 'GOOGLE_SECRET_ACCESS_KEY'
|
||||
}
|
||||
end
|
||||
|
||||
it 'registers Google as a provider' do
|
||||
expect(Fog.providers.keys).to include(:google)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with Azure' do
|
||||
let(:credentials) do
|
||||
{
|
||||
provider: 'AzureRM',
|
||||
azure_storage_account_name: 'azuretest',
|
||||
azure_storage_access_key: 'ABCD1234'
|
||||
}
|
||||
end
|
||||
|
||||
it 'registers AzureRM as a provider' do
|
||||
expect(Fog.providers.keys).to include(:azurerm)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#credentials' do
|
||||
it { expect(subject.credentials).to eq(credentials) }
|
||||
end
|
||||
|
|
|
@ -201,10 +201,6 @@ RSpec.describe ObjectStorage::DirectUpload do
|
|||
end
|
||||
|
||||
shared_examples 'a valid AzureRM upload' do
|
||||
before do
|
||||
require 'fog/azurerm'
|
||||
end
|
||||
|
||||
it_behaves_like 'a valid upload'
|
||||
|
||||
it 'enables the Workhorse client' do
|
||||
|
|
|
@ -3411,6 +3411,31 @@ RSpec.describe Ci::Build do
|
|||
|
||||
it { is_expected.to include(key: job_variable.key, value: job_variable.value, public: false, masked: false) }
|
||||
end
|
||||
|
||||
describe 'kubernetes variables' do
|
||||
let(:service) { double(execute: template) }
|
||||
let(:template) { double(to_yaml: 'example-kubeconfig', valid?: template_valid) }
|
||||
let(:template_valid) { true }
|
||||
|
||||
before do
|
||||
allow(Ci::GenerateKubeconfigService).to receive(:new).with(build).and_return(service)
|
||||
end
|
||||
|
||||
it { is_expected.to include(key: 'KUBECONFIG', value: 'example-kubeconfig', public: false, file: true) }
|
||||
|
||||
context 'job is deploying to a cluster' do
|
||||
let(:deployment) { create(:deployment, deployment_cluster: create(:deployment_cluster)) }
|
||||
let(:build) { create(:ci_build, pipeline: pipeline, deployment: deployment) }
|
||||
|
||||
it { is_expected.not_to include(key: 'KUBECONFIG', value: 'example-kubeconfig', public: false, file: true) }
|
||||
end
|
||||
|
||||
context 'generated config is invalid' do
|
||||
let(:template_valid) { false }
|
||||
|
||||
it { is_expected.not_to include(key: 'KUBECONFIG', value: 'example-kubeconfig', public: false, file: true) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#scoped_variables' do
|
||||
|
|
|
@ -4595,4 +4595,37 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#authorized_cluster_agents' do
|
||||
let(:pipeline) { create(:ci_empty_pipeline, :created) }
|
||||
let(:agent) { instance_double(Clusters::Agent) }
|
||||
let(:authorization) { instance_double(Clusters::Agents::GroupAuthorization, agent: agent) }
|
||||
let(:finder) { double(execute: [authorization]) }
|
||||
|
||||
it 'retrieves agent records from the finder and caches the result' do
|
||||
expect(Clusters::AgentAuthorizationsFinder).to receive(:new).once
|
||||
.with(pipeline.project)
|
||||
.and_return(finder)
|
||||
|
||||
expect(pipeline.authorized_cluster_agents).to contain_exactly(agent)
|
||||
expect(pipeline.authorized_cluster_agents).to contain_exactly(agent) # cached
|
||||
end
|
||||
|
||||
context 'group_authorized_agents feature flag is disabled' do
|
||||
let(:finder) { double(execute: [agent]) }
|
||||
|
||||
before do
|
||||
stub_feature_flags(group_authorized_agents: false)
|
||||
end
|
||||
|
||||
it 'retrieves agent records from the legacy finder and caches the result' do
|
||||
expect(Clusters::DeployableAgentsFinder).to receive(:new).once
|
||||
.with(pipeline.project)
|
||||
.and_return(finder)
|
||||
|
||||
expect(pipeline.authorized_cluster_agents).to contain_exactly(agent)
|
||||
expect(pipeline.authorized_cluster_agents).to contain_exactly(agent) # cached
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -14,7 +14,7 @@ RSpec.describe CustomEmoji do
|
|||
end
|
||||
|
||||
describe 'exclusion of duplicated emoji' do
|
||||
let(:emoji_name) { Gitlab::Emoji.emojis_names.sample }
|
||||
let(:emoji_name) { TanukiEmoji.index.all.sample.name }
|
||||
let(:group) { create(:group, :private) }
|
||||
|
||||
it 'disallows emoji names of built-in emoji' do
|
||||
|
|
|
@ -6,21 +6,22 @@ RSpec.describe AwardEmojiPresenter do
|
|||
let(:emoji_name) { 'thumbsup' }
|
||||
let(:award_emoji) { build(:award_emoji, name: emoji_name) }
|
||||
let(:presenter) { described_class.new(award_emoji) }
|
||||
let(:emoji) { TanukiEmoji.find_by_alpha_code(emoji_name) }
|
||||
|
||||
describe '#description' do
|
||||
it { expect(presenter.description).to eq Gitlab::Emoji.emojis[emoji_name]['description'] }
|
||||
it { expect(presenter.description).to eq emoji.description }
|
||||
end
|
||||
|
||||
describe '#unicode' do
|
||||
it { expect(presenter.unicode).to eq Gitlab::Emoji.emojis[emoji_name]['unicode'] }
|
||||
it { expect(presenter.unicode).to eq emoji.hex }
|
||||
end
|
||||
|
||||
describe '#unicode_version' do
|
||||
it { expect(presenter.unicode_version).to eq Gitlab::Emoji.emoji_unicode_version(emoji_name) }
|
||||
it { expect(presenter.unicode_version).to eq('6.0') }
|
||||
end
|
||||
|
||||
describe '#emoji' do
|
||||
it { expect(presenter.emoji).to eq Gitlab::Emoji.emojis[emoji_name]['moji'] }
|
||||
it { expect(presenter.emoji).to eq emoji.codepoints }
|
||||
end
|
||||
|
||||
describe 'when presenting an award emoji with an invalid name' do
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe AwardEmojis::BaseService do
|
||||
let(:awardable) { build(:note) }
|
||||
let(:current_user) { build(:user) }
|
||||
|
||||
describe '.initialize' do
|
||||
subject { described_class }
|
||||
|
||||
it 'uses same emoji name if not an alias' do
|
||||
emoji_name = 'horse'
|
||||
|
||||
expect(subject.new(awardable, emoji_name, current_user).name).to eq(emoji_name)
|
||||
end
|
||||
|
||||
it 'uses emoji original name if its an alias' do
|
||||
emoji_alias = 'small_airplane'
|
||||
emoji_name = 'airplane_small'
|
||||
|
||||
expect(subject.new(awardable, emoji_alias, current_user).name).to eq(emoji_name)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,50 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Ci::GenerateKubeconfigService do
|
||||
describe '#execute' do
|
||||
let(:project) { create(:project) }
|
||||
let(:build) { create(:ci_build, project: project) }
|
||||
let(:agent1) { create(:cluster_agent, project: project) }
|
||||
let(:agent2) { create(:cluster_agent) }
|
||||
|
||||
let(:template) { instance_double(Gitlab::Kubernetes::Kubeconfig::Template) }
|
||||
|
||||
subject { described_class.new(build).execute }
|
||||
|
||||
before do
|
||||
expect(Gitlab::Kubernetes::Kubeconfig::Template).to receive(:new).and_return(template)
|
||||
expect(build.pipeline).to receive(:authorized_cluster_agents).and_return([agent1, agent2])
|
||||
end
|
||||
|
||||
it 'adds a cluster, and a user and context for each available agent' do
|
||||
expect(template).to receive(:add_cluster).with(
|
||||
name: 'gitlab',
|
||||
url: Gitlab::Kas.tunnel_url
|
||||
).once
|
||||
|
||||
expect(template).to receive(:add_user).with(
|
||||
name: "agent:#{agent1.id}",
|
||||
token: "ci:#{agent1.id}:#{build.token}"
|
||||
)
|
||||
expect(template).to receive(:add_user).with(
|
||||
name: "agent:#{agent2.id}",
|
||||
token: "ci:#{agent2.id}:#{build.token}"
|
||||
)
|
||||
|
||||
expect(template).to receive(:add_context).with(
|
||||
name: "#{project.full_path}:#{agent1.name}",
|
||||
cluster: 'gitlab',
|
||||
user: "agent:#{agent1.id}"
|
||||
)
|
||||
expect(template).to receive(:add_context).with(
|
||||
name: "#{agent2.project.full_path}:#{agent2.name}",
|
||||
cluster: 'gitlab',
|
||||
user: "agent:#{agent2.id}"
|
||||
)
|
||||
|
||||
expect(subject).to eq(template)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -53,7 +53,7 @@ RSpec.describe Users::UpdateService do
|
|||
result = update_user(user, status: { emoji: "Moo!" })
|
||||
|
||||
expect(result[:status]).to eq(:error)
|
||||
expect(result[:message]).to eq("Emoji is not included in the list")
|
||||
expect(result[:message]).to eq("Emoji is not a valid emoji name")
|
||||
end
|
||||
|
||||
it 'updates user detail with provided attributes' do
|
||||
|
|
|
@ -4810,11 +4810,6 @@ emoji-regex@^8.0.0:
|
|||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||
|
||||
emoji-unicode-version@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/emoji-unicode-version/-/emoji-unicode-version-0.2.1.tgz#0ebf3666b5414097971d34994e299fce75cdbafc"
|
||||
integrity sha1-Dr82ZrVBQJeXHTSZTimfznXNuvw=
|
||||
|
||||
emojis-list@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
|
||||
|
|
Loading…
Reference in New Issue