Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
f825fd1d88
commit
135dd0646b
|
@ -54,16 +54,6 @@ Gitlab/Json:
|
|||
- 'app/models/merge_request_diff_commit.rb'
|
||||
- 'app/presenters/packages/composer/packages_presenter.rb'
|
||||
- 'app/presenters/projects/security/configuration_presenter.rb'
|
||||
- 'app/services/bulk_imports/lfs_objects_export_service.rb'
|
||||
- 'app/services/ci/pipeline_artifacts/coverage_report_service.rb'
|
||||
- 'app/services/ci/pipeline_artifacts/create_code_quality_mr_diff_report_service.rb'
|
||||
- 'app/services/ci/pipeline_trigger_service.rb'
|
||||
- 'app/services/ci/register_job_service.rb'
|
||||
- 'app/services/google_cloud/create_service_accounts_service.rb'
|
||||
- 'app/services/google_cloud/setup_cloudsql_instance_service.rb'
|
||||
- 'app/services/merge_requests/add_context_service.rb'
|
||||
- 'app/services/projects/lfs_pointers/lfs_download_link_list_service.rb'
|
||||
- 'app/services/service_ping/submit_service.rb'
|
||||
- 'app/workers/google_cloud/create_cloudsql_instance_worker.rb'
|
||||
- 'config/initializers/rack_multipart_patch.rb'
|
||||
- 'db/migrate/20210305031822_create_dast_site_profile_variables.rb'
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -176,7 +176,7 @@ gem 'typhoeus', '~> 1.4.0' # Used with Elasticsearch to support http keep-alive
|
|||
|
||||
# Markdown and HTML processing
|
||||
gem 'html-pipeline', '~> 2.13.2'
|
||||
gem 'deckar01-task_list', '2.3.1'
|
||||
gem 'deckar01-task_list', '2.3.2'
|
||||
gem 'gitlab-markup', '~> 1.8.0'
|
||||
gem 'github-markup', '~> 1.7.0', require: 'github/markup'
|
||||
gem 'commonmarker', '~> 0.23.6'
|
||||
|
|
|
@ -97,7 +97,7 @@
|
|||
{"name":"danger-gitlab","version":"8.0.0","platform":"ruby","checksum":"497dd7d0f6513913de651019223d8058cf494df10acbd17de92b175dfa04a3a8"},
|
||||
{"name":"database_cleaner","version":"1.7.0","platform":"ruby","checksum":"bdf833c197afac7054015bcde2567c3834c366bbfe6a377c30151ca984b32016"},
|
||||
{"name":"dead_end","version":"3.1.1","platform":"ruby","checksum":"1011df7f7c0149be004e11cbbc37747760227c55305cd902fd3c06e1394b2f5b"},
|
||||
{"name":"deckar01-task_list","version":"2.3.1","platform":"ruby","checksum":"205a08c22a8f05c063d43c452aeada4214b58fdce1e55e92ec709e2cfb9e7ca1"},
|
||||
{"name":"deckar01-task_list","version":"2.3.2","platform":"ruby","checksum":"5a19092548d24309d8b2c2704d64cdc08a4a615823c9a722f4142edec1de8805"},
|
||||
{"name":"declarative","version":"0.0.20","platform":"ruby","checksum":"8021dd6cb17ab2b61233c56903d3f5a259c5cf43c80ff332d447d395b17d9ff9"},
|
||||
{"name":"declarative-option","version":"0.1.0","platform":"ruby","checksum":"17508349f51c5631e5ad4158c29f78a4b2de618abffa066d76c11953705f91bc"},
|
||||
{"name":"declarative_policy","version":"1.1.0","platform":"ruby","checksum":"9af4cf299ade03f2bbf63908f2ce6a117d132fc714c39a128596667fb13331cb"},
|
||||
|
|
|
@ -321,7 +321,7 @@ GEM
|
|||
gitlab (~> 4.2, >= 4.2.0)
|
||||
database_cleaner (1.7.0)
|
||||
dead_end (3.1.1)
|
||||
deckar01-task_list (2.3.1)
|
||||
deckar01-task_list (2.3.2)
|
||||
html-pipeline
|
||||
declarative (0.0.20)
|
||||
declarative-option (0.1.0)
|
||||
|
@ -1584,7 +1584,7 @@ DEPENDENCIES
|
|||
crystalball (~> 0.7.0)
|
||||
cvss-suite (~> 3.0.1)
|
||||
database_cleaner (~> 1.7.0)
|
||||
deckar01-task_list (= 2.3.1)
|
||||
deckar01-task_list (= 2.3.2)
|
||||
declarative_policy (~> 1.1.0)
|
||||
default_value_for (~> 3.4.0)
|
||||
deprecation_toolkit (~> 1.5.1)
|
||||
|
|
|
@ -233,13 +233,7 @@ export default {
|
|||
:description="$options.translations.addTokenNameDescription"
|
||||
label-for="deploy_token_name"
|
||||
>
|
||||
<gl-form-input
|
||||
id="deploy_token_name"
|
||||
v-model="name"
|
||||
name="deploy_token_name"
|
||||
class="qa-deploy-token-name"
|
||||
data-qa-selector="deploy_token_name_field"
|
||||
/>
|
||||
<gl-form-input id="deploy_token_name" v-model="name" name="deploy_token_name" />
|
||||
</gl-form-group>
|
||||
<gl-form-group
|
||||
:label="$options.translations.addTokenExpiryLabel"
|
||||
|
|
|
@ -39,7 +39,7 @@ export function initStoreFromElement(element) {
|
|||
|
||||
export function initPropsFromElement(element) {
|
||||
return {
|
||||
providerTitle: element.dataset.provider,
|
||||
providerTitle: element.dataset.providerTitle,
|
||||
filterable: parseBoolean(element.dataset.filterable),
|
||||
paginatable: parseBoolean(element.dataset.paginatable),
|
||||
optionalStages: JSON.parse(element.dataset.optionalStages),
|
||||
|
|
|
@ -169,7 +169,8 @@ export default class LazyLoader {
|
|||
delete img.dataset.src;
|
||||
img.classList.remove('lazy');
|
||||
img.classList.add('js-lazy-loaded');
|
||||
img.classList.add('qa-js-lazy-loaded');
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
img.dataset.qa_selector = 'js_lazy_loaded_content';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ module Types
|
|||
class Runner < BasePermissionType
|
||||
graphql_name 'RunnerPermissions'
|
||||
|
||||
abilities :read_runner, :update_runner, :delete_runner
|
||||
abilities :read_runner, :update_runner, :delete_runner, :assign_runner
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -70,10 +70,11 @@ module IconsHelper
|
|||
# gl_loading_icon(css_class: "foo-bar")
|
||||
#
|
||||
# See also https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-loading-icon--default
|
||||
def gl_loading_icon(inline: false, color: 'dark', size: 'sm', css_class: nil)
|
||||
def gl_loading_icon(inline: false, color: 'dark', size: 'sm', css_class: nil, data: nil)
|
||||
spinner = content_tag(:span, "", {
|
||||
class: %[gl-spinner gl-spinner-#{color} gl-spinner-#{size} gl-vertical-align-text-bottom!],
|
||||
aria: { label: _('Loading') }
|
||||
aria: { label: _('Loading') },
|
||||
data: data
|
||||
})
|
||||
|
||||
container_classes = ['gl-spinner-container']
|
||||
|
|
|
@ -71,20 +71,20 @@ class Integration < ApplicationRecord
|
|||
|
||||
alias_attribute :type, :type_new
|
||||
|
||||
default_value_for :active, false
|
||||
default_value_for :alert_events, true
|
||||
default_value_for :category, 'common'
|
||||
default_value_for :commit_events, true
|
||||
default_value_for :confidential_issues_events, true
|
||||
default_value_for :confidential_note_events, true
|
||||
default_value_for :issues_events, true
|
||||
default_value_for :job_events, true
|
||||
default_value_for :merge_requests_events, true
|
||||
default_value_for :note_events, true
|
||||
default_value_for :pipeline_events, true
|
||||
default_value_for :push_events, true
|
||||
default_value_for :tag_push_events, true
|
||||
default_value_for :wiki_page_events, true
|
||||
attribute :active, default: false
|
||||
attribute :alert_events, default: true
|
||||
attribute :category, default: 'common'
|
||||
attribute :commit_events, default: true
|
||||
attribute :confidential_issues_events, default: true
|
||||
attribute :confidential_note_events, default: true
|
||||
attribute :issues_events, default: true
|
||||
attribute :job_events, default: true
|
||||
attribute :merge_requests_events, default: true
|
||||
attribute :note_events, default: true
|
||||
attribute :pipeline_events, default: true
|
||||
attribute :push_events, default: true
|
||||
attribute :tag_push_events, default: true
|
||||
attribute :wiki_page_events, default: true
|
||||
|
||||
after_initialize :initialize_properties
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ module BulkImports
|
|||
def write_lfs_json
|
||||
filepath = File.join(export_path, "#{BulkImports::FileTransfer::ProjectConfig::LFS_OBJECTS_RELATION}.json")
|
||||
|
||||
File.write(filepath, lfs_json.to_json)
|
||||
File.write(filepath, Gitlab::Json.dump(lfs_json))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -39,7 +39,7 @@ module Ci
|
|||
def carrierwave_file
|
||||
strong_memoize(:carrier_wave_file) do
|
||||
CarrierWaveStringFile.new_file(
|
||||
file_content: report.to_json,
|
||||
file_content: Gitlab::Json.dump(report),
|
||||
filename: Ci::PipelineArtifact::DEFAULT_FILE_NAMES.fetch(:code_coverage),
|
||||
content_type: 'application/json'
|
||||
)
|
||||
|
|
|
@ -77,9 +77,9 @@ module Ci
|
|||
end
|
||||
|
||||
def build_quality_mr_diff_report(mr_diff_report)
|
||||
mr_diff_report.each_with_object({}) do |diff_report, hash|
|
||||
Gitlab::Json.dump(mr_diff_report.each_with_object({}) do |diff_report, hash|
|
||||
hash[diff_report.first] = Ci::CodequalityMrDiffReportSerializer.new.represent(diff_report.second) # rubocop: disable CodeReuse/Serializer
|
||||
end.to_json
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -93,7 +93,7 @@ module Ci
|
|||
|
||||
def payload_variable
|
||||
{ key: PAYLOAD_VARIABLE_KEY,
|
||||
value: params.except(*PAYLOAD_VARIABLE_HIDDEN_PARAMS).to_json,
|
||||
value: Gitlab::Json.dump(params.except(*PAYLOAD_VARIABLE_HIDDEN_PARAMS)),
|
||||
variable_type: :file }
|
||||
end
|
||||
|
||||
|
|
|
@ -226,7 +226,7 @@ module Ci
|
|||
log_artifacts_context(build)
|
||||
log_build_dependencies_size(presented_build)
|
||||
|
||||
build_json = ::API::Entities::Ci::JobRequest::Response.new(presented_build).to_json
|
||||
build_json = Gitlab::Json.dump(::API::Entities::Ci::JobRequest::Response.new(presented_build))
|
||||
Result.new(build, build_json, true)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'openssl'
|
||||
|
||||
module Clusters
|
||||
module Kubernetes
|
||||
class ConfigureIstioIngressService
|
||||
PASSTHROUGH_RESOURCE = Kubeclient::Resource.new(
|
||||
mode: 'PASSTHROUGH'
|
||||
).freeze
|
||||
|
||||
MTLS_RESOURCE = Kubeclient::Resource.new(
|
||||
mode: 'MUTUAL',
|
||||
privateKey: '/etc/istio/ingressgateway-certs/tls.key',
|
||||
serverCertificate: '/etc/istio/ingressgateway-certs/tls.crt',
|
||||
caCertificates: '/etc/istio/ingressgateway-ca-certs/cert.pem'
|
||||
).freeze
|
||||
|
||||
def initialize(cluster:)
|
||||
@cluster = cluster
|
||||
@platform = cluster.platform
|
||||
@kubeclient = platform.kubeclient
|
||||
@knative = cluster.application_knative
|
||||
end
|
||||
|
||||
def execute
|
||||
return configure_certificates if serverless_domain_cluster
|
||||
|
||||
configure_passthrough
|
||||
rescue Kubeclient::HttpError => e
|
||||
knative.make_errored!(_('Kubernetes error: %{error_code}') % { error_code: e.error_code })
|
||||
rescue StandardError
|
||||
knative.make_errored!(_('Failed to update.'))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :cluster, :platform, :kubeclient, :knative
|
||||
|
||||
def serverless_domain_cluster
|
||||
knative&.serverless_domain_cluster
|
||||
end
|
||||
|
||||
def configure_certificates
|
||||
create_or_update_istio_cert_and_key
|
||||
set_gateway_wildcard_https(MTLS_RESOURCE)
|
||||
end
|
||||
|
||||
def create_or_update_istio_cert_and_key
|
||||
name = OpenSSL::X509::Name.parse("CN=#{knative.hostname}")
|
||||
|
||||
key = OpenSSL::PKey::RSA.new(2048)
|
||||
|
||||
cert = OpenSSL::X509::Certificate.new
|
||||
cert.version = 2
|
||||
cert.serial = 0
|
||||
cert.not_before = Time.current
|
||||
cert.not_after = Time.current + 1000.years
|
||||
|
||||
cert.public_key = key.public_key
|
||||
cert.subject = name
|
||||
cert.issuer = name
|
||||
cert.sign(key, OpenSSL::Digest.new('SHA256'))
|
||||
|
||||
serverless_domain_cluster.update!(
|
||||
key: key.to_pem,
|
||||
certificate: cert.to_pem
|
||||
)
|
||||
|
||||
kubeclient.create_or_update_secret(istio_ca_certs_resource)
|
||||
kubeclient.create_or_update_secret(istio_certs_resource)
|
||||
end
|
||||
|
||||
def istio_ca_certs_resource
|
||||
Gitlab::Kubernetes::GenericSecret.new(
|
||||
'istio-ingressgateway-ca-certs',
|
||||
{
|
||||
'cert.pem': Base64.strict_encode64(serverless_domain_cluster.certificate)
|
||||
},
|
||||
Clusters::Kubernetes::ISTIO_SYSTEM_NAMESPACE
|
||||
).generate
|
||||
end
|
||||
|
||||
def istio_certs_resource
|
||||
Gitlab::Kubernetes::TlsSecret.new(
|
||||
'istio-ingressgateway-certs',
|
||||
serverless_domain_cluster.certificate,
|
||||
serverless_domain_cluster.key,
|
||||
Clusters::Kubernetes::ISTIO_SYSTEM_NAMESPACE
|
||||
).generate
|
||||
end
|
||||
|
||||
def set_gateway_wildcard_https(tls_resource)
|
||||
gateway_resource = gateway
|
||||
gateway_resource.spec.servers.each do |server|
|
||||
next unless server.hosts == ['*'] && server.port.name == 'https'
|
||||
|
||||
server.tls = tls_resource
|
||||
end
|
||||
kubeclient.update_gateway(gateway_resource)
|
||||
end
|
||||
|
||||
def configure_passthrough
|
||||
set_gateway_wildcard_https(PASSTHROUGH_RESOURCE)
|
||||
end
|
||||
|
||||
def gateway
|
||||
kubeclient.get_gateway('knative-ingress-gateway', Clusters::Kubernetes::KNATIVE_SERVING_NAMESPACE)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -53,11 +53,11 @@ module Git
|
|||
def create_pipelines
|
||||
return unless params.fetch(:create_pipelines, true)
|
||||
|
||||
Ci::CreatePipelineService
|
||||
.new(project, current_user, pipeline_params)
|
||||
.execute!(:push, pipeline_options)
|
||||
rescue Ci::CreatePipelineService::CreateError => ex
|
||||
log_pipeline_errors(ex)
|
||||
if ::Feature.enabled?(:refactored_create_pipeline_execution_method, project)
|
||||
create_pipeline_refactored
|
||||
else
|
||||
create_pipeline_legacy
|
||||
end
|
||||
end
|
||||
|
||||
def execute_project_hooks
|
||||
|
@ -148,14 +148,14 @@ module Git
|
|||
{}
|
||||
end
|
||||
|
||||
def log_pipeline_errors(exception)
|
||||
def log_pipeline_errors(error_message)
|
||||
data = {
|
||||
class: self.class.name,
|
||||
correlation_id: Labkit::Correlation::CorrelationId.current_id.to_s,
|
||||
project_id: project.id,
|
||||
project_path: project.full_path,
|
||||
message: "Error creating pipeline",
|
||||
errors: exception.to_s,
|
||||
errors: error_message,
|
||||
pipeline_params: sanitized_pipeline_params
|
||||
}
|
||||
|
||||
|
@ -175,5 +175,21 @@ module Git
|
|||
Gitlab::IntegrationsLogger
|
||||
end
|
||||
end
|
||||
|
||||
def create_pipeline_refactored
|
||||
response = Ci::CreatePipelineService
|
||||
.new(project, current_user, pipeline_params)
|
||||
.execute(:push, **pipeline_options)
|
||||
|
||||
log_pipeline_errors(response.message) unless response.payload.persisted?
|
||||
end
|
||||
|
||||
def create_pipeline_legacy
|
||||
Ci::CreatePipelineService
|
||||
.new(project, current_user, pipeline_params)
|
||||
.execute!(:push, pipeline_options)
|
||||
rescue Ci::CreatePipelineService::CreateError => ex
|
||||
log_pipeline_errors(ex.to_s) # Stringifying the ex here as I removed stringifying in log_pipeline_errors.
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,8 +10,8 @@ module GoogleCloud
|
|||
service_accounts_service.add_for_project(
|
||||
environment_name,
|
||||
service_account.project_id,
|
||||
service_account.to_json,
|
||||
service_account_key.to_json,
|
||||
Gitlab::Json.dump(service_account),
|
||||
Gitlab::Json.dump(service_account_key),
|
||||
ProtectedBranch.protected?(project, environment_name) || ProtectedTag.protected?(project, environment_name)
|
||||
)
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module GoogleCloud
|
|||
get_instance_response = google_api_client.get_cloudsql_instance(gcp_project_id, instance_name)
|
||||
|
||||
if get_instance_response.state != INSTANCE_STATE_RUNNABLE
|
||||
return error("CloudSQL instance not RUNNABLE: #{get_instance_response.to_json}")
|
||||
return error("CloudSQL instance not RUNNABLE: #{Gitlab::Json.dump(get_instance_response)}")
|
||||
end
|
||||
|
||||
save_instance_ci_vars(get_instance_response)
|
||||
|
@ -42,7 +42,7 @@ module GoogleCloud
|
|||
|
||||
success
|
||||
rescue Google::Apis::Error => err
|
||||
error(message: err.to_json)
|
||||
error(message: Gitlab::Json.dump(err))
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -97,7 +97,7 @@ module GoogleCloud
|
|||
database_response = google_api_client.create_cloudsql_database(gcp_project_id, instance_name, database_name)
|
||||
|
||||
if database_response.status != OPERATION_STATE_DONE
|
||||
return error("Database creation failed: #{database_response.to_json}")
|
||||
return error("Database creation failed: #{Gitlab::Json.dump(database_response)}")
|
||||
end
|
||||
|
||||
success
|
||||
|
@ -109,7 +109,7 @@ module GoogleCloud
|
|||
user_response = google_api_client.create_cloudsql_user(gcp_project_id, instance_name, username, password)
|
||||
|
||||
if user_response.status != OPERATION_STATE_DONE
|
||||
return error("User creation failed: #{user_response.to_json}")
|
||||
return error("User creation failed: #{Gitlab::Json.dump(user_response)}")
|
||||
end
|
||||
|
||||
success
|
||||
|
|
|
@ -65,7 +65,7 @@ module MergeRequests
|
|||
sha: sha,
|
||||
authored_date: Gitlab::Database.sanitize_timestamp(commit_hash[:authored_date]),
|
||||
committed_date: Gitlab::Database.sanitize_timestamp(commit_hash[:committed_date]),
|
||||
trailers: commit_hash.fetch(:trailers, {}).to_json
|
||||
trailers: Gitlab::Json.dump(commit_hash.fetch(:trailers, {}))
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -95,10 +95,12 @@ module Projects
|
|||
end
|
||||
|
||||
def request_body(oids)
|
||||
{
|
||||
body = {
|
||||
operation: DOWNLOAD_ACTION,
|
||||
objects: oids.map { |oid, size| { oid: oid, size: size } }
|
||||
}.to_json
|
||||
}
|
||||
|
||||
Gitlab::Json.dump(body)
|
||||
end
|
||||
|
||||
def headers
|
||||
|
|
|
@ -63,7 +63,7 @@ module ServicePing
|
|||
def submit_payload(payload, path: USAGE_DATA_PATH)
|
||||
Gitlab::HTTP.post(
|
||||
URI.join(base_url, path),
|
||||
body: payload.to_json,
|
||||
body: Gitlab::Json.dump(payload),
|
||||
allow_local_requests: true,
|
||||
headers: { 'Content-type' => 'application/json' }
|
||||
)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
- filterable = local_assigns.fetch(:filterable, true)
|
||||
- paginatable = local_assigns.fetch(:paginatable, false)
|
||||
- default_namespace_path = (local_assigns[:default_namespace] || current_user.namespace).full_path
|
||||
- provider_title = Gitlab::ImportSources.title(provider)
|
||||
- provider_title = Gitlab::ImportSources.title(local_assigns.fetch(:provider))
|
||||
- optional_stages = local_assigns.fetch(:optional_stages, [])
|
||||
|
||||
- header_title _("New project"), new_project_path
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
img.src = imgUrl;
|
||||
img.removeAttribute('data-src');
|
||||
img.classList.remove('lazy');
|
||||
img.classList.add('js-lazy-loaded', 'qa-js-lazy-loaded');
|
||||
img.classList.add('js-lazy-loaded');
|
||||
img.dataset.qa_selector = 'js_lazy_loaded_content';
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
|
||||
.form-group
|
||||
= f.label :key, s_('Profiles|Key'), class: 'label-bold'
|
||||
= f.text_area :key, class: "form-control gl-form-input js-add-ssh-key-validation-input qa-key-public-key-field", rows: 8, required: true, data: { supported_algorithms: Gitlab::SSHPublicKey.supported_algorithms }
|
||||
= f.text_area :key, class: "form-control gl-form-input js-add-ssh-key-validation-input", rows: 8, required: true, data: { supported_algorithms: Gitlab::SSHPublicKey.supported_algorithms, qa_selector: 'key_public_key_field' }
|
||||
%p.form-text.text-muted= s_('Profiles|Begins with %{ssh_key_algorithms}.') % { ssh_key_algorithms: ssh_key_allowed_algorithms }
|
||||
.form-row
|
||||
.col.form-group
|
||||
= f.label :title, s_('Profiles|Title'), class: 'label-bold'
|
||||
= f.text_field :title, class: "form-control gl-form-input input-lg qa-key-title-field", required: true, placeholder: s_('Profiles|Example: MacBook key')
|
||||
= f.text_field :title, class: "form-control gl-form-input input-lg", required: true, placeholder: s_('Profiles|Example: MacBook key'), data: { qa_selector: 'key_title_field' }
|
||||
%p.form-text.text-muted= s_('Profiles|Key titles are publicly visible.')
|
||||
|
||||
.form-row
|
||||
|
@ -29,4 +29,4 @@
|
|||
button_options: { class: 'js-add-ssh-key-validation-confirm-submit' }) do
|
||||
= _("Yes, add it")
|
||||
.gl-mt-3
|
||||
= f.submit s_('Profiles|Add key'), class: "js-add-ssh-key-validation-original-submit qa-add-key-button", pajamas_button: true
|
||||
= f.submit s_('Profiles|Add key'), class: "js-add-ssh-key-validation-original-submit", pajamas_button: true, data: { qa_selector: 'add_key_button' }
|
||||
|
|
|
@ -16,5 +16,5 @@
|
|||
|
||||
- if create_mr_button_from_event?(event)
|
||||
= c.actions do
|
||||
= render Pajamas::ButtonComponent.new(variant: :confirm, href: create_mr_path_from_push_event(event), button_options: { class: 'qa-create-merge-request' }) do
|
||||
= render Pajamas::ButtonComponent.new(variant: :confirm, href: create_mr_path_from_push_event(event), button_options: { data: { qa_selector: 'create_merge_request_button' }}) do
|
||||
= _('Create merge request')
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
- if current_action?(:new) || current_action?(:create)
|
||||
%span.float-left.gl-mr-3
|
||||
\/
|
||||
= text_field_tag 'file_name', params[:file_name], placeholder: "File name",
|
||||
= text_field_tag 'file_name', params[:file_name], placeholder: "File name", data: { qa_selector: 'file_name_field' },
|
||||
required: true, class: 'form-control gl-form-input new-file-name js-file-path-name-input', value: params[:file_name] || (should_suggest_gitlab_ci_yml? ? '.gitlab-ci.yml' : '')
|
||||
= render 'template_selectors'
|
||||
- if should_suggest_gitlab_ci_yml?
|
||||
|
@ -38,7 +38,7 @@
|
|||
.file-editor.code
|
||||
- if Feature.enabled?(:source_editor_toolbar, current_user)
|
||||
#editor-toolbar
|
||||
.js-edit-mode-pane.qa-editor#editor{ data: { 'editor-loading': true, qa_selector: 'source_editor_preview_container' } }<
|
||||
.js-edit-mode-pane#editor{ data: { 'editor-loading': true, qa_selector: 'source_editor_preview_container' } }<
|
||||
%pre.editor-loading-content= params[:content] || local_assigns[:blob_data]
|
||||
- if local_assigns[:path]
|
||||
.js-edit-mode-pane#preview.hide
|
||||
|
|
|
@ -1 +1 @@
|
|||
= gl_loading_icon(size: "md", css_class: "qa-spinner gl-my-4")
|
||||
= gl_loading_icon(size: "md", css_class: "gl-my-4", data: { qa_selector: 'spinner_placeholder' })
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
- merged = local_assigns.fetch(:merged, false)
|
||||
- commit = @repository.commit(branch.dereferenced_target)
|
||||
- merge_project = merge_request_source_project_for_project(@project)
|
||||
%li{ class: "branch-item gl-display-flex! gl-align-items-center! js-branch-item js-branch-#{branch.name}", data: { name: branch.name } }
|
||||
%li{ class: "branch-item gl-display-flex! gl-align-items-center! js-branch-item js-branch-#{branch.name}", data: { name: branch.name, qa_selector: 'branch_container', qa_name: branch.name } }
|
||||
.branch-info
|
||||
.gl-display-flex.gl-align-items-center
|
||||
= sprite_icon('branch', size: 12, css_class: 'gl-flex-shrink-0')
|
||||
= link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name gl-ml-3 qa-branch-name' do
|
||||
= link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name gl-ml-3', data: { qa_selector: 'branch_link' } do
|
||||
= branch.name
|
||||
= clipboard_button(text: branch.name, title: _("Copy branch name"))
|
||||
- if branch.name == @repository.root_ref
|
||||
= gl_badge_tag s_('DefaultBranchLabel|default'), { variant: :info, size: :sm }, { class: 'gl-ml-2' }
|
||||
= gl_badge_tag s_('DefaultBranchLabel|default'), { variant: :info, size: :sm }, { class: 'gl-ml-2', data: { qa_selector: 'badge_content' } }
|
||||
- elsif merged
|
||||
= gl_badge_tag s_('Branches|merged'), { variant: :info, size: :sm }, { class: 'gl-ml-2', title: s_('Branches|Merged into %{default_branch}') % { default_branch: @repository.root_ref }, data: { toggle: 'tooltip', container: 'body' } }
|
||||
= gl_badge_tag s_('Branches|merged'), { variant: :info, size: :sm }, { class: 'gl-ml-2', title: s_('Branches|Merged into %{default_branch}') % { default_branch: @repository.root_ref }, data: { toggle: 'tooltip', container: 'body', qa_selector: 'badge_content' } }
|
||||
- if protected_branch?(@project, branch)
|
||||
= gl_badge_tag s_('Branches|protected'), { variant: :success, size: :sm }, { class: 'gl-ml-2' }
|
||||
= gl_badge_tag s_('Branches|protected'), { variant: :success, size: :sm }, { class: 'gl-ml-2', data: { qa_selector: 'badge_content' } }
|
||||
|
||||
= render_if_exists 'projects/branches/diverged_from_upstream', branch: branch
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
- c.header do
|
||||
= panel_title
|
||||
- c.body do
|
||||
%ul.content-list.all-branches.qa-all-branches
|
||||
%ul.content-list.all-branches{ data: { qa_selector: 'all_branches_container' } }
|
||||
- branches.first(overview_max_branches).each do |branch|
|
||||
= render "projects/branches/branch", branch: branch, merged: project.repository.merged_to_root_ref?(branch), commit_status: @branch_pipeline_statuses[branch.name], show_commit_status: @branch_pipeline_statuses.any?
|
||||
- if branches.size > overview_max_branches
|
||||
|
|
|
@ -14,13 +14,14 @@
|
|||
|
||||
- if can? current_user, :push_code, @project
|
||||
= link_to project_merged_branches_path(@project),
|
||||
class: 'gl-button btn btn-danger btn-danger-secondary has-tooltip qa-delete-merged-branches',
|
||||
class: 'gl-button btn btn-danger btn-danger-secondary has-tooltip',
|
||||
title: s_("Branches|Delete all branches that are merged into '%{default_branch}'") % { default_branch: @project.repository.root_ref },
|
||||
method: :delete,
|
||||
aria: { label: s_('Branches|Delete merged branches') },
|
||||
data: { confirm: s_('Branches|Deleting the merged branches cannot be undone. Are you sure?'),
|
||||
confirm_btn_variant: 'danger',
|
||||
container: 'body' } do
|
||||
container: 'body',
|
||||
qa_selector: 'delete_merged_branches_link' } do
|
||||
= s_('Branches|Delete merged branches')
|
||||
= link_to new_project_branch_path(@project), class: 'gl-button btn btn-confirm' do
|
||||
= s_('Branches|New branch')
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
%p
|
||||
= _('You can get started by cloning the repository or start adding files to it with one of the following options.')
|
||||
|
||||
.project-buttons.qa-quick-actions
|
||||
.project-buttons{ data: { qa_selector: 'quick_actions_container' } }
|
||||
.project-clone-holder.d-block.d-md-none.gl-mt-3.gl-mr-3
|
||||
= render "shared/mobile_clone_panel"
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
= f.label :auth_method, _('Authentication method'), class: 'label-bold'
|
||||
= f.select :auth_method,
|
||||
options_for_select(auth_options, mirror.auth_method),
|
||||
{}, { class: "custom-select gl-form-select js-mirror-auth-type qa-authentication-method" }
|
||||
{}, { class: "custom-select gl-form-select js-mirror-auth-type", data: { qa_selector: 'authentication_method_field' } }
|
||||
= f.hidden_field :auth_method, value: "password", class: "js-hidden-mirror-auth-type"
|
||||
|
||||
.form-group
|
||||
.well-password-auth.collapse.js-well-password-auth
|
||||
= f.label :password, _("Password"), class: "label-bold"
|
||||
= f.password_field :password, class: 'form-control gl-form-input qa-password js-mirror-password-field', autocomplete: 'off'
|
||||
= f.password_field :password, class: 'form-control gl-form-input js-mirror-password-field', autocomplete: 'off', data: { qa_selector: 'password_field' }
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
%span.qa-disabled-mirror-badge.rspec-disabled-mirror-badge{ data: { toggle: 'tooltip', html: 'true' }, title: _('Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them.') }
|
||||
%span.rspec-disabled-mirror-badge{ data: { toggle: 'tooltip', html: 'true' }, title: _('Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them.') }
|
||||
= gl_badge_tag _('Disabled'), variant: :warning
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
.form-group.has-feedback
|
||||
= label_tag :url, _('Git repository URL'), class: 'label-light'
|
||||
= text_field_tag :url, nil, class: 'form-control gl-form-input js-mirror-url js-repo-url qa-mirror-repository-url-input', placeholder: _('Input the remote repository URL'), required: true, pattern: "(#{protocols}):\/\/.+", autocomplete: 'new-password'
|
||||
= text_field_tag :url, nil, class: 'form-control gl-form-input js-mirror-url js-repo-url', placeholder: _('Input the remote repository URL'), required: true, pattern: "(#{protocols}):\/\/.+", autocomplete: 'new-password', data: { qa_selector: 'mirror_repository_url_field' }
|
||||
|
||||
= render 'projects/mirrors/instructions'
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
|||
= link_to _('Learn more.'), help_page_path('user/project/repository/mirror/index.md', anchor: 'mirror-only-protected-branches'), target: '_blank', rel: 'noopener noreferrer'
|
||||
|
||||
.panel-footer
|
||||
= f.submit _('Mirror repository'), class: 'js-mirror-submit qa-mirror-repository-button', name: :update_remote_mirror, pajamas_button: true
|
||||
= f.submit _('Mirror repository'), class: 'js-mirror-submit', name: :update_remote_mirror, pajamas_button: true, data: { qa_selector: 'mirror_repository_button' }
|
||||
- else
|
||||
= render Pajamas::AlertComponent.new(dismissible: false) do |c|
|
||||
= c.body do
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.form-group
|
||||
= label_tag :mirror_direction, _('Mirror direction'), class: 'label-light'
|
||||
.select-wrapper
|
||||
= select_tag :mirror_direction, options_for_select([[_('Push'), 'push']]), class: 'form-control gl-form-select select-control js-mirror-direction qa-mirror-direction', disabled: true
|
||||
= select_tag :mirror_direction, options_for_select([[_('Push'), 'push']]), class: 'form-control gl-form-select select-control js-mirror-direction', disabled: true, data: { qa_selector: 'mirror_direction_field' }
|
||||
= sprite_icon('chevron-down', css_class: "gl-icon gl-absolute gl-top-3 gl-right-3 gl-text-gray-200")
|
||||
|
||||
= render partial: "projects/mirrors/mirror_repos_push", locals: { f: f }
|
||||
|
|
|
@ -25,17 +25,17 @@
|
|||
= render_if_exists 'projects/mirrors/table_pull_row'
|
||||
- @project.remote_mirrors.each_with_index do |mirror, index|
|
||||
- next if mirror.new_record?
|
||||
%tr.rspec-mirrored-repository-row{ class: ('bg-secondary' if mirror.disabled?), data: { qa_selector: 'mirrored_repository_row' } }
|
||||
%td{ data: { qa_selector: 'mirror_repository_url_cell' } }= mirror.safe_url || _('Invalid URL')
|
||||
%tr.rspec-mirrored-repository-row{ class: ('bg-secondary' if mirror.disabled?), data: { qa_selector: 'mirrored_repository_row_container' } }
|
||||
%td{ data: { qa_selector: 'mirror_repository_url_content' } }= mirror.safe_url || _('Invalid URL')
|
||||
%td= _('Push')
|
||||
%td
|
||||
= mirror.last_update_started_at.present? ? time_ago_with_tooltip(mirror.last_update_started_at) : _('Never')
|
||||
%td{ data: { qa_selector: 'mirror_last_update_at_cell' } }= mirror.last_update_at.present? ? time_ago_with_tooltip(mirror.last_update_at) : _('Never')
|
||||
%td{ data: { qa_selector: 'mirror_last_update_at_content' } }= mirror.last_update_at.present? ? time_ago_with_tooltip(mirror.last_update_at) : _('Never')
|
||||
%td
|
||||
- if mirror.disabled?
|
||||
= render 'projects/mirrors/disabled_mirror_badge'
|
||||
- if mirror.last_error.present?
|
||||
= gl_badge_tag _('Error'), { variant: :danger }, { data: { toggle: 'tooltip', html: 'true', qa_selector: 'mirror_error_badge' }, title: html_escape(mirror.last_error.try(:strip)) }
|
||||
= gl_badge_tag _('Error'), { variant: :danger }, { data: { toggle: 'tooltip', html: 'true', qa_selector: 'mirror_error_badge_content' }, title: html_escape(mirror.last_error.try(:strip)) }
|
||||
%td.gl-display-flex
|
||||
- if mirror_settings_enabled
|
||||
.btn-group.mirror-actions-group{ role: 'group' }
|
||||
|
@ -44,4 +44,4 @@
|
|||
= render 'shared/remote_mirror_update_button', remote_mirror: mirror
|
||||
= render Pajamas::ButtonComponent.new(variant: :danger,
|
||||
icon: 'remove',
|
||||
button_options: { class: 'js-delete-mirror qa-delete-mirror rspec-delete-mirror', title: _('Remove'), data: { mirror_id: mirror.id, toggle: 'tooltip', container: 'body' } })
|
||||
button_options: { class: 'js-delete-mirror rspec-delete-mirror', title: _('Remove'), data: { mirror_id: mirror.id, toggle: 'tooltip', container: 'body' } })
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
= s_("Pipelines|(queued for %{queued_duration})") % { queued_duration: time_interval_in_words(@pipeline.queued_duration)}
|
||||
|
||||
- if has_pipeline_badges?(@pipeline)
|
||||
.well-segment.qa-pipeline-badges
|
||||
.well-segment
|
||||
.icon-container
|
||||
= sprite_icon('flag', css_class: 'gl-top-0!')
|
||||
- if @pipeline.schedule?
|
||||
|
|
|
@ -3,14 +3,16 @@
|
|||
= f.hidden_field(:name)
|
||||
|
||||
= dropdown_tag(_('Select branch or create wildcard'),
|
||||
options: { toggle_class: "js-protected-branch-select js-filter-submit wide monospace qa-protected-branch-select #{toggle_classes}",
|
||||
options: { toggle_class: "js-protected-branch-select js-filter-submit wide monospace #{toggle_classes}",
|
||||
filter: true,
|
||||
dropdown_class: "dropdown-menu-selectable git-revision-dropdown qa-protected-branch-dropdown",
|
||||
dropdown_class: "dropdown-menu-selectable git-revision-dropdown",
|
||||
dropdown_qa_selector: "protected_branch_dropdown_content",
|
||||
placeholder: _("Search protected branches"),
|
||||
footer_content: true,
|
||||
data: { show_no: true, show_any: true, show_upcoming: true,
|
||||
selected: params[:protected_branch_name],
|
||||
project_id: @project.try(:id) } }) do
|
||||
project_id: @project.try(:id),
|
||||
qa_selector: "protected_branch_dropdown" } }) do
|
||||
|
||||
%ul.dropdown-footer-list
|
||||
%li
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
.settings-header
|
||||
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
|
||||
= s_("ProtectedBranch|Protected branches")
|
||||
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle qa-expand-protected-branches' }) do
|
||||
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-settings-toggle' }) do
|
||||
= expanded ? _('Collapse') : _('Expand')
|
||||
%p
|
||||
= s_("ProtectedBranch|Keep stable branches secure and force developers to use merge requests.")
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
.settings-content
|
||||
#js-artifacts-settings-app{ data: { full_path: @project.full_path, help_page_path: help_page_path('ci/pipelines/job_artifacts', anchor: 'keep-artifacts-from-most-recent-successful-jobs') } }
|
||||
|
||||
%section.qa-variables-settings.settings.no-animate#js-cicd-variables-settings{ class: ('expanded' if expanded), data: { qa_selector: 'variables_settings_content' } }
|
||||
%section.settings.no-animate#js-cicd-variables-settings{ class: ('expanded' if expanded), data: { qa_selector: 'variables_settings_content' } }
|
||||
.settings-header
|
||||
= render 'ci/variables/header', expanded: expanded
|
||||
.settings-content
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
- breadcrumb_title @snippet.to_reference
|
||||
- page_title "#{@snippet.title} (#{@snippet.to_reference})", _("Snippets")
|
||||
|
||||
#js-snippet-view{ data: {'qa-selector': 'snippet_view', 'snippet-gid': @snippet.to_global_id, 'report-abuse-path': snippet_report_abuse_path(@snippet), 'can-report-spam': @snippet.submittable_as_spam_by?(current_user).to_s } }
|
||||
#js-snippet-view{ data: { 'snippet-gid': @snippet.to_global_id, 'report-abuse-path': snippet_report_abuse_path(@snippet), 'can-report-spam': @snippet.submittable_as_spam_by?(current_user).to_s } }
|
||||
|
||||
.gl-px-0.gl-py-2
|
||||
= render 'award_emoji/awards_block', awardable: @snippet, inline: true, api_awards_path: project_snippets_award_api_path(@snippet)
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
.row.empty-state
|
||||
.col-12
|
||||
.svg-content
|
||||
= image_tag 'illustrations/snippets_empty.svg', data: { qa_selector: 'svg_content' }
|
||||
.svg-content{ data: { qa_selector: 'svg_content' } }
|
||||
= image_tag 'illustrations/snippets_empty.svg'
|
||||
.text-content.gl-text-center.gl-pt-0
|
||||
- if current_user
|
||||
%h4
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
.js-issuable-todo{ data: { project_path: issuable_sidebar[:project_full_path], iid: issuable_sidebar[:iid], id: issuable_sidebar[:id] } }
|
||||
|
||||
= form_for issuable_type, url: issuable_sidebar[:issuable_json_path], remote: true, html: { class: 'issuable-context-form inline-update js-issuable-update' } do |f|
|
||||
.block.assignee.qa-assignee-block{ class: "#{'gl-mt-3' if !signed_in && moved_sidebar_enabled}", data: { qa_selector: 'assignee_block_container' } }
|
||||
.block.assignee{ class: "#{'gl-mt-3' if !signed_in && moved_sidebar_enabled}", data: { qa_selector: 'assignee_block_container' } }
|
||||
= render "shared/issuable/sidebar_assignees", issuable_sidebar: issuable_sidebar, assignees: assignees, signed_in: signed_in
|
||||
|
||||
- if issuable_sidebar[:supports_severity]
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
- content_for :prefetch_asset_tags do
|
||||
- webpack_preload_asset_tag('monaco', prefetch: true)
|
||||
|
||||
#js-snippet-view{ data: {'qa-selector': 'snippet_view', 'snippet-gid': @snippet.to_global_id, 'report-abuse-path': snippet_report_abuse_path(@snippet), 'can-report-spam': @snippet.submittable_as_spam_by?(current_user).to_s } }
|
||||
#js-snippet-view{ data: { 'snippet-gid': @snippet.to_global_id, 'report-abuse-path': snippet_report_abuse_path(@snippet), 'can-report-spam': @snippet.submittable_as_spam_by?(current_user).to_s } }
|
||||
|
||||
.row-content-block.top-block.content-component-block.gl-px-0.gl-py-2
|
||||
= render 'award_emoji/awards_block', awardable: @snippet, inline: true
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# DEPRECATED
|
||||
#
|
||||
# To be removed by https://gitlab.com/gitlab-org/gitlab/-/issues/366573
|
||||
class ClusterConfigureIstioWorker # rubocop:disable Scalability/IdempotentWorker
|
||||
include ApplicationWorker
|
||||
|
||||
|
@ -10,9 +13,5 @@ class ClusterConfigureIstioWorker # rubocop:disable Scalability/IdempotentWorker
|
|||
|
||||
worker_has_external_dependencies!
|
||||
|
||||
def perform(cluster_id)
|
||||
Clusters::Cluster.find_by_id(cluster_id).try do |cluster|
|
||||
Clusters::Kubernetes::ConfigureIstioIngressService.new(cluster: cluster).execute
|
||||
end
|
||||
end
|
||||
def perform(cluster_id); end
|
||||
end
|
||||
|
|
|
@ -21,13 +21,12 @@ class RunPipelineScheduleWorker # rubocop:disable Scalability/IdempotentWorker
|
|||
end
|
||||
|
||||
def run_pipeline_schedule(schedule, user)
|
||||
Ci::CreatePipelineService.new(schedule.project,
|
||||
user,
|
||||
ref: schedule.ref)
|
||||
.execute!(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: schedule)
|
||||
rescue Ci::CreatePipelineService::CreateError => e
|
||||
# This is a user operation error such as corrupted .gitlab-ci.yml. Log the error for debugging purpose.
|
||||
log_extra_metadata_on_done(:pipeline_creation_error, e)
|
||||
if ::Feature.enabled?(:refactored_create_pipeline_execution_method, schedule.project)
|
||||
create_pipeline_refactored(schedule, user)
|
||||
else
|
||||
create_pipeline_legacy(schedule, user)
|
||||
end
|
||||
|
||||
rescue StandardError => e
|
||||
error(schedule, e)
|
||||
end
|
||||
|
@ -57,4 +56,24 @@ class RunPipelineScheduleWorker # rubocop:disable Scalability/IdempotentWorker
|
|||
Gitlab::Metrics.counter(:pipeline_schedule_creation_failed_total,
|
||||
"Counter of failed attempts of pipeline schedule creation")
|
||||
end
|
||||
|
||||
def create_pipeline_refactored(schedule, user)
|
||||
response = Ci::CreatePipelineService
|
||||
.new(schedule.project, user, ref: schedule.ref)
|
||||
.execute(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: schedule)
|
||||
|
||||
return response if response.payload.persisted?
|
||||
|
||||
# This is a user operation error such as corrupted .gitlab-ci.yml. Log the error for debugging purpose.
|
||||
log_extra_metadata_on_done(:pipeline_creation_error, response.message)
|
||||
end
|
||||
|
||||
def create_pipeline_legacy(schedule, user)
|
||||
Ci::CreatePipelineService
|
||||
.new(schedule.project, user, ref: schedule.ref)
|
||||
.execute!(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: schedule)
|
||||
rescue Ci::CreatePipelineService::CreateError => e
|
||||
# This is a user operation error such as corrupted .gitlab-ci.yml. Log the error for debugging purpose.
|
||||
log_extra_metadata_on_done(:pipeline_creation_error, e)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: refactored_create_pipeline_execution_method
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98965
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/378257
|
||||
milestone: '15.6'
|
||||
type: development
|
||||
group: group::pipeline execution
|
||||
default_enabled: false
|
|
@ -317,7 +317,6 @@ sudo gitlab-rake gitlab:geo:check
|
|||
to gather the following, basic troubleshooting information.
|
||||
|
||||
WARNING:
|
||||
|
||||
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
|
||||
|
||||
#### Get the number of verification failed repositories
|
||||
|
@ -855,7 +854,6 @@ therefore short-circuited. `last_sync_failure` is now set to `The file is missin
|
|||
examples, but things generally work the same for the other types.
|
||||
|
||||
WARNING:
|
||||
|
||||
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
|
||||
|
||||
#### The Replicator
|
||||
|
|
|
@ -736,7 +736,6 @@ ApplicationSetting.current
|
|||
### Open object in `irb`
|
||||
|
||||
WARNING:
|
||||
|
||||
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
|
||||
|
||||
Sometimes it is easier to go through a method if you are in the context of the object. You can shim into the namespace of `Object` to let you open `irb` in the context of any object:
|
||||
|
|
|
@ -23,7 +23,7 @@ GET /projects/:id/deployments
|
|||
| `updated_after` | datetime | no | Return deployments updated after the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
|
||||
| `updated_before` | datetime | no | Return deployments updated before the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
|
||||
| `environment` | string | no | The [name of the environment](../ci/environments/index.md) to filter deployments by. |
|
||||
| `status` | string | no | The status to filter deployments by. One of `created`, `running`, `success`, `failed`, `canceled`, `blocked`.
|
||||
| `status` | string | no | The status to filter deployments by. One of `created`, `running`, `success`, `failed`, `canceled`, or `blocked`.
|
||||
|
||||
```shell
|
||||
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments"
|
||||
|
@ -487,7 +487,11 @@ curl --request "DELETE" --header "PRIVATE-TOKEN: <your_access_token>" "https://g
|
|||
Example responses:
|
||||
|
||||
```json
|
||||
{ "message": "202 Accepted" }
|
||||
{ "message": "204 Deployment destroyed" }
|
||||
```
|
||||
|
||||
```json
|
||||
{ "message": "403 Forbidden" }
|
||||
```
|
||||
|
||||
```json
|
||||
|
|
|
@ -70,8 +70,8 @@ POST /projects/:id/feature_flags_user_lists
|
|||
| Attribute | Type | Required | Description |
|
||||
| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
|
||||
| `name` | string | yes | The name of the feature flag. |
|
||||
| `user_xids` | string | yes | A comma-separated list of user IDs. |
|
||||
| `name` | string | yes | The name of the list. |
|
||||
| `user_xids` | string | yes | A comma-separated list of external user IDs. |
|
||||
|
||||
```shell
|
||||
curl "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists" \
|
||||
|
@ -142,8 +142,8 @@ PUT /projects/:id/feature_flags_user_lists/:iid
|
|||
| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
|
||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
|
||||
| `iid` | integer/string | yes | The internal ID of the project's feature flag user list. |
|
||||
| `name` | string | no | The name of the feature flag. |
|
||||
| `user_xids` | string | no | A comma-separated list of user IDs. |
|
||||
| `name` | string | no | The name of the list. |
|
||||
| `user_xids` | string | no | A comma-separated list of external user IDs. |
|
||||
|
||||
```shell
|
||||
curl "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists/1" \
|
||||
|
|
|
@ -151,7 +151,7 @@ POST /projects/:id/feature_flags
|
|||
| `strategies:name` | JSON | no | The strategy name. Can be `default`, `gradualRolloutUserId`, `userWithId`, or `gitlabUserList`. In [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/36380) and later, can be [`flexibleRollout`](https://docs.getunleash.io/user_guide/activation_strategy#gradual-rollout). |
|
||||
| `strategies:parameters` | JSON | no | The strategy parameters. |
|
||||
| `strategies:scopes` | JSON | no | The scopes for the strategy. |
|
||||
| `strategies:scopes:environment_scope` | string | no | The environment spec for the scope. |
|
||||
| `strategies:scopes:environment_scope` | string | no | The environment scope of the scope. |
|
||||
|
||||
```shell
|
||||
curl "https://gitlab.example.com/api/v4/projects/1/feature_flags" \
|
||||
|
@ -213,8 +213,8 @@ PUT /projects/:id/feature_flags/:feature_flag_name
|
|||
| `strategies:name` | JSON | no | The strategy name. |
|
||||
| `strategies:parameters` | JSON | no | The strategy parameters. |
|
||||
| `strategies:scopes` | JSON | no | The scopes for the strategy. |
|
||||
| `strategies:scopes:id` | JSON | no | The scopes ID. |
|
||||
| `strategies:scopes:environment_scope` | string | no | The environment spec for the scope. |
|
||||
| `strategies:scopes:id` | JSON | no | The environment scope ID. |
|
||||
| `strategies:scopes:environment_scope` | string | no | The environment scope of the scope. |
|
||||
|
||||
```shell
|
||||
curl "https://gitlab.example.com/api/v4/projects/1/feature_flags/awesome_feature" \
|
||||
|
|
|
@ -18081,6 +18081,7 @@ Counts of requirements by their state.
|
|||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="runnerpermissionsassignrunner"></a>`assignRunner` | [`Boolean!`](#boolean) | Indicates the user can perform `assign_runner` on this resource. |
|
||||
| <a id="runnerpermissionsdeleterunner"></a>`deleteRunner` | [`Boolean!`](#boolean) | Indicates the user can perform `delete_runner` on this resource. |
|
||||
| <a id="runnerpermissionsreadrunner"></a>`readRunner` | [`Boolean!`](#boolean) | Indicates the user can perform `read_runner` on this resource. |
|
||||
| <a id="runnerpermissionsupdaterunner"></a>`updateRunner` | [`Boolean!`](#boolean) | Indicates the user can perform `update_runner` on this resource. |
|
||||
|
|
|
@ -396,7 +396,19 @@ a project, you can disable this behavior to save space:
|
|||
You can disable this behavior for all projects on a self-managed instance in the
|
||||
[instance's CI/CD settings](../../user/admin_area/settings/continuous_integration.md#keep-the-latest-artifacts-for-all-jobs-in-the-latest-successful-pipelines).
|
||||
|
||||
## Troubleshooting job artifacts
|
||||
## Troubleshooting
|
||||
|
||||
### Job does not retrieve certain artifacts
|
||||
|
||||
By default, jobs fetch all artifacts from previous stages, but jobs using `dependencies`
|
||||
or `needs` do not fetch artifacts from all jobs by default.
|
||||
|
||||
If you use these keywords, artifacts are fetched from only a subset of jobs. Review
|
||||
the keyword reference for information on how to fetch artifacts with these keywords:
|
||||
|
||||
- [`dependencies`](../yaml/index.md#dependencies)
|
||||
- [`needs`](../yaml/index.md#needs)
|
||||
- [`needs:artifacts`](../yaml/index.md#needsartifacts)
|
||||
|
||||
### Error message `No files to upload`
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
against the official specification.
|
||||
- They support [snapshot testing](#markdown-snapshot-testing) of GitLab
|
||||
internal GLFM processing logic. This is accomplished by automatically
|
||||
generating YAML ["example snapshot files"](#example-snapshot-files)
|
||||
generating YAML ["example snapshot files"](#output-example-snapshot-files)
|
||||
which are used as fixtures to drive automated testing within the GitLab app.
|
||||
- There are [various scripts and logic](#scripts)
|
||||
which are used to accomplish the above goals.
|
||||
|
@ -104,13 +104,13 @@ serve as input to automated conformance tests. It is
|
|||
|
||||
Here are the HTML-rendered versions of the specifications:
|
||||
|
||||
- [GitLab Flavored Markdown (GLFM) specification](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output/spec.html), which extends the:
|
||||
- [GitLab Flavored Markdown (GLFM) specification](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output_spec/spec.html), which extends the:
|
||||
- [GitHub Flavored Markdown (GFM) specification](https://github.github.com/gfm/) (rendered from the [source `spec.txt` for GFM specification](https://github.com/github/cmark-gfm/blob/master/test/spec.txt)), which extends the:
|
||||
- [CommonMark specification](https://spec.commonmark.org/0.30/) (rendered from the [source `spec.txt` for CommonMark specification](https://github.com/commonmark/commonmark-spec/blob/master/spec.txt))
|
||||
|
||||
NOTE:
|
||||
The creation of the
|
||||
[HTML-rendered version of the GitLab Flavored Markdown (GLFM) specification](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output/spec.html)
|
||||
[HTML-rendered version of the GitLab Flavored Markdown (GLFM) specification](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output_spec/spec.html)
|
||||
file is still pending.
|
||||
|
||||
However, GLFM has more complex parsing, rendering, and testing requirements than
|
||||
|
@ -177,7 +177,7 @@ In this context, it should not be confused with other similar or related meaning
|
|||
_example_, such as
|
||||
[RSpec examples](https://relishapp.com/rspec/rspec-core/docs/example-groups/basic-structure-describe-it).
|
||||
|
||||
See the section on the [`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd) file
|
||||
See the section on the [`glfm_official_specification.md`](#glfm_official_specificationmd) file
|
||||
for more details on the backtick-delimited Markdown+HTML example syntax.
|
||||
|
||||
### Parsers and renderers
|
||||
|
@ -341,7 +341,7 @@ The GitLab [Markdown API](../../../api/markdown.md) generates HTML
|
|||
for a given Markdown string using this method.
|
||||
|
||||
The Markdown specified in the [Markdown examples](#markdown-examples) is used to automatically generate HTML in
|
||||
[`glfm_specification/example_snapshots/html.yml`](#glfm_specificationexample_snapshotshtmlyml) via
|
||||
[`glfm_specification/output_example_snapshots/html.yml`](#htmlyml) via
|
||||
[`update-example-snapshots.rb`](#update-example-snapshotsrb-script). These examples are
|
||||
used when running [Markdown snapshot testing](#markdown-snapshot-testing).
|
||||
|
||||
|
@ -353,7 +353,7 @@ in the ProseMirror WYSIWYG editor.
|
|||
|
||||
Just like static HTML,
|
||||
the Markdown specified in the [Markdown examples](#markdown-examples) is used to automatically generate HTML in
|
||||
[`glfm_specification/example_snapshots/html.yml`](#glfm_specificationexample_snapshotshtmlyml) via
|
||||
[`glfm_specification/output_example_snapshots/html.yml`](#htmlyml) via
|
||||
[`update-example-snapshots.rb`](#update-example-snapshotsrb-script). These examples are
|
||||
used when running [Markdown snapshot testing](#markdown-snapshot-testing).
|
||||
|
||||
|
@ -387,10 +387,10 @@ Here are more details on the sources of canonical HTML examples:
|
|||
version of [`spec.txt`](#spectxt).
|
||||
1. For the examples which are part of the GLFM [_official specification_](#official-specifications),
|
||||
the canonical HTML is manually maintained and curated via the examples contained in the
|
||||
[`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd) [input specification file](#input-specification-files).
|
||||
[`glfm_official_specification.md`](#glfm_official_specificationmd) [input specification file](#input-specification-files).
|
||||
1. For the examples which are part of the GLFM [_internal extensions_](#internal-extensions),
|
||||
the canonical HTML **is never specified**, and **must be left empty in all examples** contained in
|
||||
the [`glfm_internal_extension_examples.md`](#glfm_internal_extension_examplesmd) [input specification file](#input-specification-files).
|
||||
the [`glfm_internal_extensions.md`](#glfm_internal_extensionsmd) [input specification file](#input-specification-files).
|
||||
|
||||
### Canonicalization of HTML
|
||||
|
||||
|
@ -401,7 +401,7 @@ or HTML elements, to support specific appearance and behavioral requirements.
|
|||
Neither the backend nor the frontend rendering logic can directly render the clean, basic HTML
|
||||
which is necessary to perform comparison to the [canonical HTML](#canonical-html)
|
||||
when running [Markdown conformance testing](#markdown-conformance-testing)
|
||||
for the [GLFM official specification examples](#glfm_official_specification_examplesmd).
|
||||
for the [GLFM official specification examples](#glfm_official_specificationmd).
|
||||
|
||||
Nor should they be able to, because:
|
||||
|
||||
|
@ -443,7 +443,7 @@ Fixture-based normalization should be used whenever possible, because it is simp
|
|||
understand than regex-based normalization.
|
||||
|
||||
The [Markdown snapshot testing](#markdown-snapshot-testing) uses RSpec to generate the
|
||||
[example snapshot files](#example-snapshot-files). RSpec enables you to:
|
||||
[example snapshot files](#output-example-snapshot-files). RSpec enables you to:
|
||||
|
||||
- Use the same powerful fixture support and helpers as all the rest of the GitLab RSpec suite.
|
||||
- Use fixtures to control the state of the database when the example snapshots are generated.
|
||||
|
@ -575,10 +575,10 @@ The documentation on the implementation is split into three sections:
|
|||
|
||||
1. [Scripts](#scripts).
|
||||
1. [Specification files](#specification-files).
|
||||
1. [Example snapshot files](#example-snapshot-files):
|
||||
1. [Example snapshot files](#output-example-snapshot-files):
|
||||
These YAML files are used as input data
|
||||
or fixtures to drive the various tests, and are located under
|
||||
`glfm_specification/example_snapshots`. All example snapshot files are automatically
|
||||
`glfm_specification/output_example_snapshots`. All example snapshot files are automatically
|
||||
generated based on the specification files and the implementation of the parsers and renderers.
|
||||
However, they can also be directly edited if necessary, such as to
|
||||
test-drive an incomplete implementation.
|
||||
|
@ -620,8 +620,8 @@ end
|
|||
subgraph input:<br/>input specification files
|
||||
C[ghfm_spec_v_0.29.md] --> A
|
||||
D[glfm_intro.md] --> A
|
||||
E[glfm_official_specification_examples.md] --> A
|
||||
F[glfm_internal_extension_examples.md] --> A
|
||||
E[glfm_official_specification.md] --> A
|
||||
F[glfm_internal_extensions.md] --> A
|
||||
end
|
||||
subgraph output:<br/>GLFM specification files
|
||||
A --> G[spec.txt]
|
||||
|
@ -646,7 +646,7 @@ script, which expects canonical HTML, against the GitLab renderer implementation
|
|||
|
||||
`scripts/glfm/run-spec-tests.sh` is a convenience shell script which runs
|
||||
conformance specs via the CommonMark standard `spec_tests.py` script,
|
||||
which uses the `glfm_specification/output/spec.txt` file and `scripts/glfm/canonicalize-html.rb`
|
||||
which uses the `glfm_specification/output_spec/spec.txt` file and `scripts/glfm/canonicalize-html.rb`
|
||||
helper script to test the GLFM renderer implementations' support for rendering Markdown
|
||||
specification examples to canonical HTML.
|
||||
|
||||
|
@ -672,9 +672,9 @@ end
|
|||
#### `update-example-snapshots.rb` script
|
||||
|
||||
The `scripts/glfm/update-example-snapshots.rb` script uses the GLFM
|
||||
`glfm_specification/output/spec.txt` specification file and the
|
||||
`glfm_specification/output_spec/spec.txt` specification file and the
|
||||
`glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml`
|
||||
file to create and update the [example snapshot](#example-snapshot-files)
|
||||
file to create and update the [example snapshot](#output-example-snapshot-files)
|
||||
YAML files:
|
||||
|
||||
```mermaid
|
||||
|
@ -746,7 +746,7 @@ runs the [`update-specification.rb`](#update-specificationrb-script).
|
|||
It fails with an exception and non-zero return code if running these scripts
|
||||
results in any diffs to the generated and committed
|
||||
[output specification files](#output-specification-files) or
|
||||
[example snapshot files](#example-snapshot-files).
|
||||
[example snapshot files](#output-example-snapshot-files).
|
||||
|
||||
This script is run via the `glfm-verify` CI job to ensure that all changes to the
|
||||
[input specification files](#input-specification-files)
|
||||
|
@ -766,12 +766,16 @@ subcategories based on their usage and purpose:
|
|||
[`ghfm_spec_v_0.29.md`](#github-flavored-markdown-specification) specification.
|
||||
- `gitlab_flavored_markdown`: Contains all `glfm_*` files.
|
||||
- `*.md` [input specification files](#input-specification-files),
|
||||
which represent the GLFM specification itself.
|
||||
which represent the source of truth for the GLFM specification and all associated examples.
|
||||
- `*.yml` [input specification configuration files](#input-specification-configuration-files),
|
||||
which control various aspects of the automated GLFM scripts and processes.
|
||||
- `output`: Contains [output specification files](#output-specification-files),
|
||||
which are automatically generated from the
|
||||
- `output_spec`: Contains the `spec.txt` and `spec.html` [output specification files](#output-specification-files),
|
||||
which represent the [GLFM official specification](#official-specifications), and are automatically generated from the
|
||||
input files by running the [`update-specification.rb`](#update-specificationrb-script) script.
|
||||
- `output_example_snapshots`: Contains [output example snapshot files](#output-example-snapshot-files).
|
||||
which are used to drive [snapshot testing](#markdown-snapshot-testing), and are automatically generated from the
|
||||
input files by running the [`update-specification.rb`](#update-specificationrb-script)
|
||||
and [`scripts/glfm/update-example-snapshots.rb`](#update-example-snapshotsrb-script) scripts.
|
||||
|
||||
#### Input specification files
|
||||
|
||||
|
@ -790,31 +794,22 @@ is a copy of the official latest [GFM `spec.txt`](https://github.com/github/cmar
|
|||
- When it is downloaded, the version number is added to the filename.
|
||||
- The extension is changed from `*.txt` to `*.md` so that it can be handled better by Markdown editors.
|
||||
|
||||
It currently contains additional **Introduction** and **Appendix** prose-only header sections which do not
|
||||
contain any examples.
|
||||
|
||||
All header sections which contain examples are expected to be contained within a contiguous file section
|
||||
which is delimited by:
|
||||
|
||||
1. The beginning of the second H1 header (the first one after the **Introduction** section)
|
||||
1. An `<!-- END TESTS -->` HTML comment line.
|
||||
|
||||
NOTE:
|
||||
For extra clarity, this file uses the `ghfm` acronym in its name instead of `gfm`, as
|
||||
explained in the [Acronyms section](#acronyms-glfm-ghfm-gfm-commonmark).
|
||||
|
||||
##### `glfm_intro.md`
|
||||
##### `glfm_official_specification.md`
|
||||
|
||||
[`glfm_specification/input/gitlab_flavored_markdown/glfm_intro.md`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/gitlab_flavored_markdown/glfm_intro.md)
|
||||
is the GitLab-specific version of the prose in the introduction section of the GLFM specification.
|
||||
|
||||
- It is manually updated.
|
||||
- The `update-specification.rb` script inserts it into the generated GLFM `spec.txt` to replace
|
||||
the GitHub-specific GFM version of the introductory section.
|
||||
|
||||
##### `glfm_canonical_examples.txt`
|
||||
|
||||
The `glfm_canonical_examples.txt` file is deprecated and no longer exists. It has been replaced by two files:
|
||||
|
||||
- [`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd)
|
||||
which contains the [GLFM official specification](#official-specifications) examples.
|
||||
- [`glfm_internal_extension_examples.md`](#glfm_internal_extension_examplesmd)
|
||||
which contains the [GLFM internal extension](#internal-extensions) examples.
|
||||
|
||||
##### `glfm_official_specification_examples.md`
|
||||
|
||||
[`glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification_examples.md`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification_examples.md)
|
||||
[`glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification.md`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification.md)
|
||||
consists of the manually updated Markdown+HTML examples for the
|
||||
[GLFM official specification](#official-specifications), and their associated documentation and descriptions.
|
||||
|
||||
|
@ -832,7 +827,12 @@ consists of the manually updated Markdown+HTML examples for the
|
|||
- `H3` header sections must be nested within `H2` header sections. They cannot be
|
||||
nested directly within `H1` header sections.
|
||||
|
||||
`glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification_examples.md` sample entries:
|
||||
It _may_ contain additional prose-only header sections which do not contain any examples.
|
||||
|
||||
All header sections which contain examples _must_ be contained within a contiguous file section which
|
||||
is delimited by `<!-- BEGIN TESTS -->` and `<!-- END TESTS -->` HTML comment lines.
|
||||
|
||||
`glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification.md` sample entries:
|
||||
|
||||
<!-- markdownlint-disable MD048 -->
|
||||
|
||||
|
@ -864,13 +864,13 @@ bold
|
|||
|
||||
<!-- markdownlint-enable MD048 -->
|
||||
|
||||
##### `glfm_internal_extension_examples.md`
|
||||
##### `glfm_internal_extensions.md`
|
||||
|
||||
[`glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extension_examples.md`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extension_examples.md)
|
||||
[`glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extensions.md`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/input/gitlab_flavored_markdown/glfm_internal_extensions.md)
|
||||
consists of the manually updated Markdown examples for the
|
||||
[GLFM internal extensions](#internal-extensions), and their associated documentation and descriptions.
|
||||
|
||||
Its general format is identical to [`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd),
|
||||
Its general format is identical to [`glfm_official_specification.md`](#glfm_official_specificationmd),
|
||||
consisting of `H1`, `H2`, or `H3` sections containing [Markdown examples](#markdown-examples) in the
|
||||
[standard backtick-delimited `spec.txt` format](#various-markdown-specifications).
|
||||
|
||||
|
@ -878,7 +878,12 @@ However, as described in the [canonical HTML section](#canonical-html), only the
|
|||
example is specified, and the HTML portion is left empty, because internal extension examples are
|
||||
never used for [Markdown conformance testing](#markdown-conformance-testing).
|
||||
|
||||
`glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification_examples.md` sample entries:
|
||||
It _may_ contain additional prose-only header sections which do not contain any examples.
|
||||
|
||||
All header sections which contain examples _must_ be contained within a contiguous file section which
|
||||
is delimited by `<!-- BEGIN TESTS -->` and `<!-- END TESTS -->` HTML comment lines.
|
||||
|
||||
`glfm_specification/input/gitlab_flavored_markdown/glfm_official_specification.md` sample entries:
|
||||
|
||||
NOTE:
|
||||
All lines in this example are prefixed with a `|` character. This prefix helps avoid false
|
||||
|
@ -908,7 +913,7 @@ See the main [specification files](#specification-files) section for more contex
|
|||
|
||||
All of the manually curated example names in the configuration files must correspond to
|
||||
an existing [Markdown example](#markdown-examples) name found in
|
||||
[`example_snapshots/examples_index.yml`](#glfm_specificationexample_snapshotsexamples_indexyml),
|
||||
[`output_example_snapshots/examples_index.yml`](#examples_indexyml),
|
||||
which is automatically generated based on the [input specification files](#input-specification-files).
|
||||
|
||||
If there is an invalid reference to an example name that does not exist, the
|
||||
|
@ -943,16 +948,16 @@ controls the behavior of the [scripts](#scripts) and [tests](#types-of-markdown-
|
|||
The following optional entries are supported for each example. They all default to `false`:
|
||||
|
||||
- `skip_update_example_snapshots`: When true, skips any addition or update of any this example's entries
|
||||
in the [`glfm_specification/example_snapshots/html.yml`](#glfm_specificationexample_snapshotshtmlyml) file
|
||||
or the [`glfm_specification/example_snapshots/prosemirror_json.yml`](#glfm_specificationexample_snapshotsprosemirror_jsonyml) file.
|
||||
in the [`glfm_specification/output_example_snapshots/html.yml`](#htmlyml) file
|
||||
or the [`glfm_specification/output_example_snapshots/prosemirror_json.yml`](#prosemirror_jsonyml) file.
|
||||
If this value is truthy, then no other `skip_update_example_snapshot_*` entries can be truthy,
|
||||
and an error is raised if any of them are.
|
||||
- `skip_update_example_snapshot_html_static`: When true, skips addition or update of this example's [static HTML](#static-html)
|
||||
entry in the [`glfm_specification/example_snapshots/html.yml`](#glfm_specificationexample_snapshotshtmlyml) file.
|
||||
entry in the [`glfm_specification/output_example_snapshots/html.yml`](#htmlyml) file.
|
||||
- `skip_update_example_snapshot_html_wysiwyg`: When true, skips addition or update of this example's [WYSIWYG HTML](#wysiwyg-html)
|
||||
entry in the [`glfm_specification/example_snapshots/html.yml`](#glfm_specificationexample_snapshotshtmlyml) file.
|
||||
entry in the [`glfm_specification/output_example_snapshots/html.yml`](#htmlyml) file.
|
||||
- `skip_update_example_snapshot_prosemirror_json`: When true, skips addition or update of this example's
|
||||
entry in the [`glfm_specification/example_snapshots/prosemirror_json.yml`](#glfm_specificationexample_snapshotsprosemirror_jsonyml) file.
|
||||
entry in the [`glfm_specification/output_example_snapshots/prosemirror_json.yml`](#prosemirror_jsonyml) file.
|
||||
- `skip_running_conformance_static_tests`: When true, skips running the [Markdown conformance tests](#markdown-conformance-testing)
|
||||
of the [static HTML](#static-html) for this example.
|
||||
- `skip_running_conformance_wysiwyg_tests`: When true, skips running the [Markdown conformance tests](#markdown-conformance-testing)
|
||||
|
@ -962,7 +967,7 @@ The following optional entries are supported for each example. They all default
|
|||
- `skip_running_snapshot_wysiwyg_html_tests`: When true, skips running the [Markdown snapshot tests](#markdown-snapshot-testing)
|
||||
of the [WYSIWYG HTML](#wysiwyg-html) for this example.
|
||||
- `skip_running_snapshot_prosemirror_json_tests`: When true, skips running the [Markdown snapshot tests](#markdown-snapshot-testing)
|
||||
of the [ProseMirror JSON](#glfm_specificationexample_snapshotsprosemirror_jsonyml) for this example.
|
||||
of the [ProseMirror JSON](#prosemirror_jsonyml) for this example.
|
||||
|
||||
`glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml` sample entry:
|
||||
|
||||
|
@ -1033,9 +1038,9 @@ or [environment-variable-based normalization](#environment-variable-based-normal
|
|||
snapshot:
|
||||
07_01_00_href: *07_01_00_href
|
||||
07_01_00_id: *07_01_00_id
|
||||
wysiwyg:
|
||||
07_01_00_href: *07_01_00_href
|
||||
07_01_00_id: *07_01_00_id
|
||||
wysiwyg:
|
||||
07_01_00_href: *07_01_00_href
|
||||
07_01_00_id: *07_01_00_id
|
||||
prosemirror_json:
|
||||
07_01_00_href: *07_01_00_href
|
||||
07_01_00_id: *07_01_00_id
|
||||
|
@ -1093,36 +1098,66 @@ move or copy a hosted version of the rendered HTML `spec.html` version to anothe
|
|||
|
||||
##### spec.txt
|
||||
|
||||
[`glfm_specification/output/spec.txt`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output/spec.txt)
|
||||
[`glfm_specification/output_spec/spec.txt`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output_spec/spec.txt)
|
||||
is a Markdown specification file, in the standard format
|
||||
with prose and Markdown + canonical HTML examples.
|
||||
|
||||
It also serves as input for other scripts such as `update-example-snapshots.rb`
|
||||
and `run-spec-tests.sh`.
|
||||
It also serves as input for other scripts such as
|
||||
`run-spec-tests.sh`.
|
||||
|
||||
It is generated or updated by the `update-specification.rb` script, using the
|
||||
[input specification files](#input-specification-files) as input.
|
||||
See the [`update-specification.rb` script section](#update-specificationrb-script)
|
||||
for a diagram and more description on this process.
|
||||
|
||||
NOTE:
|
||||
Even though `spec.txt` is a Markdown file, it is named with a `*.txt` extension
|
||||
for consistency with the GFM and CommonMark specifications. All other GLFM
|
||||
Markdown files are named with a `*.md` extension for compatibility with
|
||||
various editors to enable Markdown formatting and syntax highlighting.
|
||||
|
||||
##### spec.html
|
||||
|
||||
[`glfm_specification/output/spec.html`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output/spec.html)
|
||||
[`glfm_specification/output_spec/spec.html`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output_spec/spec.html)
|
||||
is an HTML file, rendered based on `spec.txt`. It is
|
||||
also generated (or updated) by the `update-specification.rb` script at the same time as
|
||||
generated (or updated) by the `update-specification.rb` script at the same time as
|
||||
`spec.txt`.
|
||||
|
||||
It corresponds to the HTML-rendered versions of the
|
||||
"GitHub Flavored Markdown" (<abbr title="GitHub Flavored Markdown">GFM</abbr>)
|
||||
[specification](https://github.github.com/gfm/)
|
||||
and the [CommonMark specification](https://spec.commonmark.org/0.30/).
|
||||
and the [CommonMark specification](https://spec.commonmark.org/0.30/), but only
|
||||
contains GitLab Flavored Markdown (GLFM) examples.
|
||||
|
||||
### Example snapshot files
|
||||
NOTE:
|
||||
|
||||
The `example_snapshots` directory contains files which are generated by the
|
||||
`update-example-snapshots.rb` script based off of the files in the
|
||||
`glfm_specification/input` directory. They are used as fixtures to drive the
|
||||
various Markdown snapshot tests.
|
||||
The formatting of this HTML is currently not identical to the GFM and CommonMark
|
||||
HTML-rendered specification. It is only the raw output of running `spec.txt` through
|
||||
the GitLab Markdown renderer. Properly formatting the HTML will require
|
||||
duplicating or reusing the Lua script and template from the CommonMark project:
|
||||
[CommonMark Makefile](https://github.com/commonmark/commonmark-spec/blob/master/Makefile#L11)
|
||||
|
||||
#### Output example snapshot files
|
||||
|
||||
The `output_example_snapshots` directory contains files which are generated by the
|
||||
`update-specification.rb` and `update-example-snapshots.rb` scripts based off of the files in the
|
||||
`glfm_specification/input` directory.
|
||||
|
||||
The `output-specification.rb` script generates
|
||||
`output_snapshot_examples/glfm_snapshot_spec.md` and `output_snapshot_examples/glfm_snapshot_spec.html`.
|
||||
These files are Markdown specification files containing examples generated based on input files,
|
||||
similar to the `output_spec/spec.txt` and `output_spec/spec.html`, with the following differences:
|
||||
|
||||
1. They contain a superset of _all_ examples from
|
||||
the Commonmark, GitHub Flavored Markdown, and GitLab Flavored Markdown specifications, whereas
|
||||
`spec.*` only contains the GLFM specification. This is to provide a single place to refer to
|
||||
all examples when working with [snapshot testing](#markdown-snapshot-testing).
|
||||
1. They contain _only_ header sections which contain examples. They do not contain any prose-only
|
||||
sections which do not contain examples.
|
||||
|
||||
The `update-example-snapshots.rb` script generates the various
|
||||
`output_snapshot_examples/*.yml` files, which
|
||||
are used as fixtures to drive the [snapshot testing](#markdown-snapshot-testing).
|
||||
|
||||
After the entire GLFM implementation is complete for both backend (Ruby) and
|
||||
frontend (JavaScript), all of these YAML files can be automatically generated.
|
||||
|
@ -1131,9 +1166,47 @@ key in `glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.ym
|
|||
can be used to disable automatic generation of some examples. They can instead
|
||||
be manually edited as necessary to help drive the implementations.
|
||||
|
||||
#### `glfm_specification/example_snapshots/examples_index.yml`
|
||||
##### `glfm_snapshot_spec.md`
|
||||
|
||||
[`glfm_specification/example_snapshots/examples_index.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/example_snapshots/examples_index.yml)
|
||||
[`glfm_specification/output_example_snapshots/glfm_snapshot_spec.md`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output_example_snapshots/glfm_snapshot_spec.md)
|
||||
is a Markdown file, containing standard Markdown + canonical HTML examples like [`spec.txt`](#spectxt).
|
||||
|
||||
It is generated or updated by the `update-specification.rb` script, using the
|
||||
[input specification files](#input-specification-files) as input.
|
||||
See the [`update-specification.rb` script section](#update-specificationrb-script)
|
||||
for a diagram and more description on this process. It also serves as input for other
|
||||
scripts such as `update-example-snapshots.rb`.
|
||||
|
||||
It is similar to [`spec.txt`](#spectxt), with the following differences:
|
||||
|
||||
1. [`spec.txt`](#spectxt) contains only examples for GitLab Flavored Markdown, but
|
||||
`glfm_snapshot_spec.md` also contains the full superset of examples from the
|
||||
"GitHub Flavored Markdown" (<abbr title="GitHub Flavored Markdown">GFM</abbr>)[specification](https://github.github.com/gfm/)
|
||||
and the [CommonMark specification](https://spec.commonmark.org/0.30/) specifications.
|
||||
1. [`spec.txt`](#spectxt) represents the full GLFM specification, including additional header sections
|
||||
containing only explanatory prose and no examples, but `glfm_snapshot_spec.md` consists of only
|
||||
header sections which contain examples. This is because its purpose is to serve as input for
|
||||
the other [`output example snapshot files`](#output-example-snapshot-files) - it is not intended
|
||||
to serve as an actual [specification file](#output-specification-files)
|
||||
like [`spec.txt`](#spectxt) or [`spec.html`](#spechtml).
|
||||
|
||||
##### `glfm_snapshot_spec.html`
|
||||
|
||||
[`glfm_specification/output_snapshot_examples/glfm_snapshot_spec.html`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output_snapshot_examples/glfm_snapshot_spec.html)
|
||||
is an HTML file, rendered based on `glfm_snapshot_spec.md`. It is
|
||||
generated (or updated) by the `update-specification.rb` script at the same time as
|
||||
`glfm_snapshot_spec.md`.
|
||||
|
||||
NOTE:
|
||||
The formatting of this HTML is currently not identical to the GFM and CommonMark
|
||||
HTML-rendered specification. It is only the raw output of running `glfm_snapshot_spec.md` through
|
||||
the GitLab Markdown renderer. Properly formatting the HTML will require
|
||||
duplicating or reusing the Lua script and template from the CommonMark project:
|
||||
[CommonMark Makefile](https://github.com/commonmark/commonmark-spec/blob/master/Makefile#L11)
|
||||
|
||||
##### `examples_index.yml`
|
||||
|
||||
[`glfm_specification/output_example_snapshots/examples_index.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output_example_snapshots/examples_index.yml)
|
||||
is the main list of all
|
||||
CommonMark, GFM, and GLFM example names, each with a uniquely identifying name.
|
||||
|
||||
|
@ -1142,9 +1215,9 @@ CommonMark, GFM, and GLFM example names, each with a uniquely identifying name.
|
|||
- For CommonMark and GFM examples,
|
||||
these sections originally came from the GFM `spec.txt`.
|
||||
- For GLFM examples, it is generated from
|
||||
[`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd) and [`glfm_internal_extension_examples.md`](#glfm_internal_extension_examplesmd).
|
||||
[`glfm_official_specification.md`](#glfm_official_specificationmd) and [`glfm_internal_extensions.md`](#glfm_internal_extensionsmd).
|
||||
- It also contains extra metadata about each example, such as:
|
||||
1. `spec_txt_example_position` - The position of the example in the generated GLFM `spec.txt` file.
|
||||
1. `spec_example_position` - The position of the example in the generated GLFM `spec.txt` file.
|
||||
- This value is the index order of each individual Markdown + HTML5 example in the file. It is _not_
|
||||
the line number in the file.
|
||||
- This value can be used to locate the example in the rendered `spec.html` file, because the standard
|
||||
|
@ -1159,49 +1232,49 @@ CommonMark, GFM, and GLFM example names, each with a uniquely identifying name.
|
|||
examples where multiple examples exist for the same Section 7 subsection are
|
||||
added to the end of the sub-section.
|
||||
|
||||
`glfm_specification/example_snapshots/examples_index.yml` sample entries:
|
||||
`examples_index.yml` sample entries:
|
||||
|
||||
```yaml
|
||||
02_01_00_preliminaries_characters_and_lines_1:
|
||||
spec_txt_example_position: 1
|
||||
spec_example_position: 1
|
||||
source_specification: commonmark
|
||||
03_01_00_blocks_and_inlines_precedence_1:
|
||||
spec_txt_example_position: 12
|
||||
spec_example_position: 12
|
||||
source_specification: commonmark
|
||||
05_03_00_container_blocks_task_list_items_1:
|
||||
spec_txt_example_position: 279
|
||||
spec_example_position: 279
|
||||
source_specification: github
|
||||
06_04_00_inlines_emphasis_and_strong_emphasis_1:
|
||||
spec_txt_example_position: 360
|
||||
spec_example_position: 360
|
||||
source_specification: github
|
||||
07_01_00_audio_link_1:
|
||||
spec_txt_example_position: 301
|
||||
spec_example_position: 301
|
||||
source_specification: gitlab
|
||||
```
|
||||
|
||||
#### `glfm_specification/example_snapshots/markdown.yml`
|
||||
##### `markdown.yml`
|
||||
|
||||
[`glfm_specification/example_snapshots/markdown.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/example_snapshots/markdown.yml) contains the original Markdown
|
||||
for each entry in `glfm_specification/example_snapshots/examples_index.yml`
|
||||
[`glfm_specification/output_example_snapshots/markdown.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output_example_snapshots/markdown.yml) contains the original Markdown
|
||||
for each entry in `glfm_specification/output_example_snapshots/examples_index.yml`:
|
||||
|
||||
- For CommonMark and GFM Markdown,
|
||||
it is generated (or updated) from the standard GFM
|
||||
`spec.txt` using the `update-example-snapshots.rb` script.
|
||||
- For GLFM, it is generated (or updated) from the
|
||||
[`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd) and [`glfm_internal_extension_examples.md`](#glfm_internal_extension_examplesmd)
|
||||
[`glfm_official_specification.md`](#glfm_official_specificationmd) and [`glfm_internal_extensions.md`](#glfm_internal_extensionsmd)
|
||||
input specification files.
|
||||
|
||||
`glfm_specification/example_snapshots/markdown.yml` sample entry:
|
||||
`glfm_specification/output_example_snapshots/markdown.yml` sample entry:
|
||||
|
||||
```yaml
|
||||
06_04_00_inlines_emphasis_and_strong_emphasis_1: |
|
||||
*foo bar*
|
||||
```
|
||||
|
||||
#### `glfm_specification/example_snapshots/html.yml`
|
||||
##### `html.yml`
|
||||
|
||||
[`glfm_specification/example_snapshots/html.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/example_snapshots/html.yml)
|
||||
contains the HTML for each entry in `glfm_specification/example_snapshots/examples_index.yml`
|
||||
[`glfm_specification/output_example_snapshots/html.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output_example_snapshots/html.yml)
|
||||
contains the HTML for each entry in `glfm_specification/output_example_snapshots/examples_index.yml`:
|
||||
|
||||
Three types of entries exist, with different HTML for each:
|
||||
|
||||
|
@ -1209,16 +1282,16 @@ Three types of entries exist, with different HTML for each:
|
|||
- The ["Canonical"](#canonicalization-of-html) HTML.
|
||||
- For CommonMark and GFM examples, the HTML comes from the examples in `spec.txt`.
|
||||
- For [GLFM official specification](#official-specifications) examples, it is generated/updated from
|
||||
[`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd).
|
||||
[`glfm_official_specification.md`](#glfm_official_specificationmd).
|
||||
- **Static**
|
||||
- This is the static (backend (Ruby)-generated) HTML for each entry in
|
||||
`glfm_specification/example_snapshots/examples_index.yml`.
|
||||
`glfm_specification/output_example_snapshots/examples_index.yml`.
|
||||
- It is generated/updated from backend [Markdown API](../../../api/markdown.md)
|
||||
(or the underlying internal classes) via the `update-example-snapshots.rb` script,
|
||||
but can be manually updated for static examples with incomplete implementations.
|
||||
- **WYSIWYG**
|
||||
- The WYSIWYG (frontend, JavaScript-generated) HTML for each entry in
|
||||
`glfm_specification/example_snapshots/examples_index.yml`.
|
||||
`glfm_specification/output_example_snapshots/examples_index.yml`.
|
||||
- It is generated (or updated) from the frontend Content Editor implementation via the
|
||||
`update-example-snapshots.rb` script. It can be manually updated for WYSIWYG
|
||||
examples with incomplete implementations.
|
||||
|
@ -1226,7 +1299,7 @@ Three types of entries exist, with different HTML for each:
|
|||
Any exceptions or failures which occur when generating HTML are replaced with an
|
||||
`Error - check implementation` value.
|
||||
|
||||
`glfm_specification/example_snapshots/html.yml` sample entry:
|
||||
`glfm_specification/output_example_snapshots/html.yml` sample entry:
|
||||
|
||||
```yaml
|
||||
06_04_00_inlines_emphasis_and_strong_emphasis_1:
|
||||
|
@ -1242,16 +1315,16 @@ NOTE:
|
|||
The actual `static` or `WYSIWYG` entries may differ from the example `html.yml`,
|
||||
depending on how the implementations evolve.
|
||||
|
||||
#### `glfm_specification/example_snapshots/prosemirror_json.yml`
|
||||
##### `prosemirror_json.yml`
|
||||
|
||||
[`glfm_specification/example_snapshots/prosemirror_json.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/example_snapshots/prosemirror_json.yml)
|
||||
contains the ProseMirror JSON for each entry in `glfm_specification/example_snapshots/examples_index.yml`
|
||||
[`glfm_specification/output_example_snapshots/prosemirror_json.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/glfm_specification/output_example_snapshots/prosemirror_json.yml)
|
||||
contains the ProseMirror JSON for each entry in `glfm_specification/output_example_snapshots/examples_index.yml`
|
||||
|
||||
- It is generated (or updated) from the frontend code via the `update-example-snapshots.rb`
|
||||
script, but can be manually updated for examples with incomplete implementations.
|
||||
- Any exceptions or failures when generating are replaced with a `Error - check implementation` value.
|
||||
|
||||
`glfm_specification/example_snapshots/prosemirror_json.yml` sample entry:
|
||||
`glfm_specification/output_example_snapshots/prosemirror_json.yml` sample entry:
|
||||
|
||||
```yaml
|
||||
06_04_00_inlines_emphasis_and_strong_emphasis_1: |-
|
||||
|
@ -1291,13 +1364,13 @@ This section describes how the scripts can be used to manage the GLFM specificat
|
|||
|
||||
1. If you are working on an in-progress feature or bug, make any necessary manual updates to the [input specification files](#input-specification-files). This may include:
|
||||
1. Updating the canonical Markdown or HTML examples in
|
||||
[`glfm_official_specification_examples.md`](#glfm_official_specification_examplesmd) or [`glfm_internal_extension_examples.md`](#glfm_internal_extension_examplesmd).
|
||||
[`glfm_official_specification.md`](#glfm_official_specificationmd) or [`glfm_internal_extensions.md`](#glfm_internal_extensionsmd).
|
||||
1. Updating `glfm_specification/input/gitlab_flavored_markdown/glfm_example_status.yml` to reflect the current status of the examples or tests.
|
||||
1. Run [`update-specification.rb`](#update-specificationrb-script) to update the `spec.txt` to reflect any changes which were made to the [input specification files](#input-specification-files).
|
||||
1. Visually inspect and confirm any resulting changes to the [output specification files](#output-specification-files).
|
||||
1. Run [`update-example-snapshots.rb`](#update-example-snapshotsrb-script) to update the [example snapshot files](#example-snapshot-files).
|
||||
1. Visually inspect and confirm any resulting changes to the [example snapshot files](#example-snapshot-files).
|
||||
1. Run [`update-example-snapshots.rb`](#update-example-snapshotsrb-script) to update the [example snapshot files](#output-example-snapshot-files).
|
||||
1. Visually inspect and confirm any resulting changes to the [example snapshot files](#output-example-snapshot-files).
|
||||
1. Run [`run-snapshot-tests.sh`](#run-snapshot-testssh-script) as a convenience script to run all relevant frontend (RSpec) and backend (Jest) tests which use the example snapshots.
|
||||
1. Any frontend or backend snapshot test may also be run individually.
|
||||
1. All frontend and backend tests are also run as part of the continuous integration suite, as they normally are.
|
||||
1. Commit any changes to the [input specification files](#input-specification-files), [output specification files](#output-specification-files), or [example snapshot files](#example-snapshot-files).
|
||||
1. Commit any changes to the [input specification files](#input-specification-files), [output specification files](#output-specification-files), or [example snapshot files](#output-example-snapshot-files).
|
||||
|
|
|
@ -44,8 +44,9 @@ You can quickly see which comments involve you, because
|
|||
mentions for yourself (the user currently signed in) are highlighted
|
||||
in a different color.
|
||||
|
||||
Avoid mentioning `@all` in issues and merge requests, because it sends an email notification
|
||||
to all the members of that project's group. This might be interpreted as spam.
|
||||
Avoid mentioning `@all` in issues and merge requests. It sends an email notification
|
||||
to all members of that project's parent group, not only the participants of the project,
|
||||
and may be interpreted as spam.
|
||||
Notifications and mentions can be disabled in
|
||||
[a group's settings](../group/manage.md#disable-email-notifications).
|
||||
|
||||
|
|
|
@ -823,7 +823,6 @@ Group.find_by_sql("SELECT * FROM namespaces WHERE name LIKE '%oup'")
|
|||
If transferring a group doesn't work through the UI or API, you may want to attempt the transfer in a [Rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session):
|
||||
|
||||
WARNING:
|
||||
|
||||
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
|
||||
|
||||
```ruby
|
||||
|
@ -855,7 +854,6 @@ At times, a group deletion may get stuck. If needed, in a [Rails console session
|
|||
you can attempt to delete a group using the following command:
|
||||
|
||||
WARNING:
|
||||
|
||||
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
|
||||
|
||||
```ruby
|
||||
|
|
|
@ -121,3 +121,13 @@ To resolve this, ensure that:
|
|||
- If you have set the `TF_HTTP_PASSWORD` CI/CD variable, make sure that you either:
|
||||
- Set the same value as `TF_PASSWORD`
|
||||
- Remove `TF_HTTP_PASSWORD` variable if your CI/CD job does not explicitly use it.
|
||||
|
||||
### Enable Developer role access to destructive commands
|
||||
|
||||
To permit a user with the Developer role to run destructive commands, you need a workaround:
|
||||
|
||||
1. [Create a project access token](../../project/settings/project_access_tokens.md#create-a-project-access-token) with `api` scope.
|
||||
1. Add `TF_USERNAME` and `TF_PASSWORD` to your CI/CD variables:
|
||||
1. Set the value of `TF_USERNAME` to the username of your project access token.
|
||||
1. Set the value of `TF_PASSWORD` to the password of your project access token.
|
||||
1. Optional. Protect the variables to make them only available in pipelines that run on protected branches or protected tags.
|
||||
|
|
|
@ -134,7 +134,6 @@ To disable notifications for all projects that have Slack integration enabled,
|
|||
[start a rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session) and use a script similar to the following:
|
||||
|
||||
WARNING:
|
||||
|
||||
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
|
||||
|
||||
```ruby
|
||||
|
|
|
@ -326,7 +326,6 @@ repository mirroring, mirroring breaks when people leave the company. Use this
|
|||
script to migrate disparate mirroring users and tokens into a single service account:
|
||||
|
||||
WARNING:
|
||||
|
||||
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
|
||||
|
||||
```ruby
|
||||
|
|
|
@ -304,7 +304,6 @@ For example, to enable **Check whether the commit author is a GitLab user** and
|
|||
and create a filter for allowing commits from a specific email domain only through rails console:
|
||||
|
||||
WARNING:
|
||||
|
||||
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
|
||||
|
||||
``` ruby
|
||||
|
|
|
@ -516,7 +516,6 @@ If a project or repository has been updated but the state is not reflected in th
|
|||
You can do so through [a Rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session) and one of the following:
|
||||
|
||||
WARNING:
|
||||
|
||||
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
|
||||
|
||||
```ruby
|
||||
|
@ -546,7 +545,6 @@ end
|
|||
If a project cannot be deleted, you can attempt to delete it through [Rails console](../../administration/operations/rails_console.md#starting-a-rails-console-session).
|
||||
|
||||
WARNING:
|
||||
|
||||
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
|
||||
|
||||
```ruby
|
||||
|
@ -571,7 +569,6 @@ To toggle a specific feature, you can [start a Rails console session](../../admi
|
|||
and run the following function:
|
||||
|
||||
WARNING:
|
||||
|
||||
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
|
||||
|
||||
```ruby
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<!-- BEGIN TESTS -->
|
||||
# GitLab Internal Extension Markdown
|
||||
|
||||
## Audio
|
||||
|
@ -109,3 +110,4 @@ also requires an EE license enabling the `group_wikis` feature:
|
|||
.
|
||||
<p><a href="group-wikis-test-file">group-wikis-test-file</a></p>
|
||||
````````````````````````````````
|
||||
<!-- END TESTS -->
|
|
@ -1,3 +0,0 @@
|
|||
# Introduction
|
||||
|
||||
TODO: Write a GitLab-specific version of the GitHub Flavored Markdown intro section.
|
|
@ -1,7 +1,12 @@
|
|||
# Introduction
|
||||
|
||||
TODO: Write a GitLab-specific version of the GitHub Flavored Markdown intro section.
|
||||
|
||||
<!-- BEGIN TESTS -->
|
||||
# GitLab Official Specification Markdown
|
||||
|
||||
Currently, only some of the GitLab-specific markdown features are
|
||||
listed in this section. We will eventually add all
|
||||
listed in this section. We may eventually add all
|
||||
GitLab-specific features currently listed as supported in the
|
||||
[user-facing documentation for GitLab Flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html).
|
||||
|
||||
|
@ -275,3 +280,4 @@ A table of contents can be indented with up to three spaces.
|
|||
</nav>
|
||||
<h1>Heading 1</h1>
|
||||
````````````````````````````````
|
||||
<!-- END TESTS -->
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -2,11 +2,6 @@
|
|||
title: GitLab Flavored Markdown (GLFM) Spec
|
||||
version: alpha
|
||||
...
|
||||
|
||||
# Introduction
|
||||
|
||||
TODO: Write a GitLab-specific version of the GitHub Flavored Markdown intro section.
|
||||
|
||||
# Preliminaries
|
||||
|
||||
## Characters and lines
|
||||
|
@ -9603,7 +9598,7 @@ Multiple spaces
|
|||
# GitLab Official Specification Markdown
|
||||
|
||||
Currently, only some of the GitLab-specific markdown features are
|
||||
listed in this section. We will eventually add all
|
||||
listed in this section. We may eventually add all
|
||||
GitLab-specific features currently listed as supported in the
|
||||
[user-facing documentation for GitLab Flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html).
|
||||
|
||||
|
@ -9989,342 +9984,3 @@ also requires an EE license enabling the `group_wikis` feature:
|
|||
.
|
||||
<p><a href="group-wikis-test-file">group-wikis-test-file</a></p>
|
||||
````````````````````````````````
|
||||
|
||||
<!-- END TESTS -->
|
||||
|
||||
# Appendix: A parsing strategy
|
||||
|
||||
In this appendix we describe some features of the parsing strategy
|
||||
used in the CommonMark reference implementations.
|
||||
|
||||
## Overview
|
||||
|
||||
Parsing has two phases:
|
||||
|
||||
1. In the first phase, lines of input are consumed and the block
|
||||
structure of the document---its division into paragraphs, block quotes,
|
||||
list items, and so on---is constructed. Text is assigned to these
|
||||
blocks but not parsed. Link reference definitions are parsed and a
|
||||
map of links is constructed.
|
||||
|
||||
2. In the second phase, the raw text contents of paragraphs and headings
|
||||
are parsed into sequences of Markdown inline elements (strings,
|
||||
code spans, links, emphasis, and so on), using the map of link
|
||||
references constructed in phase 1.
|
||||
|
||||
At each point in processing, the document is represented as a tree of
|
||||
**blocks**. The root of the tree is a `document` block. The `document`
|
||||
may have any number of other blocks as **children**. These children
|
||||
may, in turn, have other blocks as children. The last child of a block
|
||||
is normally considered **open**, meaning that subsequent lines of input
|
||||
can alter its contents. (Blocks that are not open are **closed**.)
|
||||
Here, for example, is a possible document tree, with the open blocks
|
||||
marked by arrows:
|
||||
|
||||
``` tree
|
||||
-> document
|
||||
-> block_quote
|
||||
paragraph
|
||||
"Lorem ipsum dolor\nsit amet."
|
||||
-> list (type=bullet tight=true bullet_char=-)
|
||||
list_item
|
||||
paragraph
|
||||
"Qui *quodsi iracundia*"
|
||||
-> list_item
|
||||
-> paragraph
|
||||
"aliquando id"
|
||||
```
|
||||
|
||||
## Phase 1: block structure
|
||||
|
||||
Each line that is processed has an effect on this tree. The line is
|
||||
analyzed and, depending on its contents, the document may be altered
|
||||
in one or more of the following ways:
|
||||
|
||||
1. One or more open blocks may be closed.
|
||||
2. One or more new blocks may be created as children of the
|
||||
last open block.
|
||||
3. Text may be added to the last (deepest) open block remaining
|
||||
on the tree.
|
||||
|
||||
Once a line has been incorporated into the tree in this way,
|
||||
it can be discarded, so input can be read in a stream.
|
||||
|
||||
For each line, we follow this procedure:
|
||||
|
||||
1. First we iterate through the open blocks, starting with the
|
||||
root document, and descending through last children down to the last
|
||||
open block. Each block imposes a condition that the line must satisfy
|
||||
if the block is to remain open. For example, a block quote requires a
|
||||
`>` character. A paragraph requires a non-blank line.
|
||||
In this phase we may match all or just some of the open
|
||||
blocks. But we cannot close unmatched blocks yet, because we may have a
|
||||
[lazy continuation line].
|
||||
|
||||
2. Next, after consuming the continuation markers for existing
|
||||
blocks, we look for new block starts (e.g. `>` for a block quote).
|
||||
If we encounter a new block start, we close any blocks unmatched
|
||||
in step 1 before creating the new block as a child of the last
|
||||
matched block.
|
||||
|
||||
3. Finally, we look at the remainder of the line (after block
|
||||
markers like `>`, list markers, and indentation have been consumed).
|
||||
This is text that can be incorporated into the last open
|
||||
block (a paragraph, code block, heading, or raw HTML).
|
||||
|
||||
Setext headings are formed when we see a line of a paragraph
|
||||
that is a [setext heading underline].
|
||||
|
||||
Reference link definitions are detected when a paragraph is closed;
|
||||
the accumulated text lines are parsed to see if they begin with
|
||||
one or more reference link definitions. Any remainder becomes a
|
||||
normal paragraph.
|
||||
|
||||
We can see how this works by considering how the tree above is
|
||||
generated by four lines of Markdown:
|
||||
|
||||
``` markdown
|
||||
> Lorem ipsum dolor
|
||||
sit amet.
|
||||
> - Qui *quodsi iracundia*
|
||||
> - aliquando id
|
||||
```
|
||||
|
||||
At the outset, our document model is just
|
||||
|
||||
``` tree
|
||||
-> document
|
||||
```
|
||||
|
||||
The first line of our text,
|
||||
|
||||
``` markdown
|
||||
> Lorem ipsum dolor
|
||||
```
|
||||
|
||||
causes a `block_quote` block to be created as a child of our
|
||||
open `document` block, and a `paragraph` block as a child of
|
||||
the `block_quote`. Then the text is added to the last open
|
||||
block, the `paragraph`:
|
||||
|
||||
``` tree
|
||||
-> document
|
||||
-> block_quote
|
||||
-> paragraph
|
||||
"Lorem ipsum dolor"
|
||||
```
|
||||
|
||||
The next line,
|
||||
|
||||
``` markdown
|
||||
sit amet.
|
||||
```
|
||||
|
||||
is a "lazy continuation" of the open `paragraph`, so it gets added
|
||||
to the paragraph's text:
|
||||
|
||||
``` tree
|
||||
-> document
|
||||
-> block_quote
|
||||
-> paragraph
|
||||
"Lorem ipsum dolor\nsit amet."
|
||||
```
|
||||
|
||||
The third line,
|
||||
|
||||
``` markdown
|
||||
> - Qui *quodsi iracundia*
|
||||
```
|
||||
|
||||
causes the `paragraph` block to be closed, and a new `list` block
|
||||
opened as a child of the `block_quote`. A `list_item` is also
|
||||
added as a child of the `list`, and a `paragraph` as a child of
|
||||
the `list_item`. The text is then added to the new `paragraph`:
|
||||
|
||||
``` tree
|
||||
-> document
|
||||
-> block_quote
|
||||
paragraph
|
||||
"Lorem ipsum dolor\nsit amet."
|
||||
-> list (type=bullet tight=true bullet_char=-)
|
||||
-> list_item
|
||||
-> paragraph
|
||||
"Qui *quodsi iracundia*"
|
||||
```
|
||||
|
||||
The fourth line,
|
||||
|
||||
``` markdown
|
||||
> - aliquando id
|
||||
```
|
||||
|
||||
causes the `list_item` (and its child the `paragraph`) to be closed,
|
||||
and a new `list_item` opened up as child of the `list`. A `paragraph`
|
||||
is added as a child of the new `list_item`, to contain the text.
|
||||
We thus obtain the final tree:
|
||||
|
||||
``` tree
|
||||
-> document
|
||||
-> block_quote
|
||||
paragraph
|
||||
"Lorem ipsum dolor\nsit amet."
|
||||
-> list (type=bullet tight=true bullet_char=-)
|
||||
list_item
|
||||
paragraph
|
||||
"Qui *quodsi iracundia*"
|
||||
-> list_item
|
||||
-> paragraph
|
||||
"aliquando id"
|
||||
```
|
||||
|
||||
## Phase 2: inline structure
|
||||
|
||||
Once all of the input has been parsed, all open blocks are closed.
|
||||
|
||||
We then "walk the tree," visiting every node, and parse raw
|
||||
string contents of paragraphs and headings as inlines. At this
|
||||
point we have seen all the link reference definitions, so we can
|
||||
resolve reference links as we go.
|
||||
|
||||
``` tree
|
||||
document
|
||||
block_quote
|
||||
paragraph
|
||||
str "Lorem ipsum dolor"
|
||||
softbreak
|
||||
str "sit amet."
|
||||
list (type=bullet tight=true bullet_char=-)
|
||||
list_item
|
||||
paragraph
|
||||
str "Qui "
|
||||
emph
|
||||
str "quodsi iracundia"
|
||||
list_item
|
||||
paragraph
|
||||
str "aliquando id"
|
||||
```
|
||||
|
||||
Notice how the [line ending] in the first paragraph has
|
||||
been parsed as a `softbreak`, and the asterisks in the first list item
|
||||
have become an `emph`.
|
||||
|
||||
### An algorithm for parsing nested emphasis and links
|
||||
|
||||
By far the trickiest part of inline parsing is handling emphasis,
|
||||
strong emphasis, links, and images. This is done using the following
|
||||
algorithm.
|
||||
|
||||
When we're parsing inlines and we hit either
|
||||
|
||||
- a run of `*` or `_` characters, or
|
||||
- a `[` or `![`
|
||||
|
||||
we insert a text node with these symbols as its literal content, and we
|
||||
add a pointer to this text node to the [delimiter stack](@).
|
||||
|
||||
The [delimiter stack] is a doubly linked list. Each
|
||||
element contains a pointer to a text node, plus information about
|
||||
|
||||
- the type of delimiter (`[`, `![`, `*`, `_`)
|
||||
- the number of delimiters,
|
||||
- whether the delimiter is "active" (all are active to start), and
|
||||
- whether the delimiter is a potential opener, a potential closer,
|
||||
or both (which depends on what sort of characters precede
|
||||
and follow the delimiters).
|
||||
|
||||
When we hit a `]` character, we call the *look for link or image*
|
||||
procedure (see below).
|
||||
|
||||
When we hit the end of the input, we call the *process emphasis*
|
||||
procedure (see below), with `stack_bottom` = NULL.
|
||||
|
||||
#### *look for link or image*
|
||||
|
||||
Starting at the top of the delimiter stack, we look backwards
|
||||
through the stack for an opening `[` or `![` delimiter.
|
||||
|
||||
- If we don't find one, we return a literal text node `]`.
|
||||
|
||||
- If we do find one, but it's not *active*, we remove the inactive
|
||||
delimiter from the stack, and return a literal text node `]`.
|
||||
|
||||
- If we find one and it's active, then we parse ahead to see if
|
||||
we have an inline link/image, reference link/image, compact reference
|
||||
link/image, or shortcut reference link/image.
|
||||
|
||||
+ If we don't, then we remove the opening delimiter from the
|
||||
delimiter stack and return a literal text node `]`.
|
||||
|
||||
+ If we do, then
|
||||
|
||||
* We return a link or image node whose children are the inlines
|
||||
after the text node pointed to by the opening delimiter.
|
||||
|
||||
* We run *process emphasis* on these inlines, with the `[` opener
|
||||
as `stack_bottom`.
|
||||
|
||||
* We remove the opening delimiter.
|
||||
|
||||
* If we have a link (and not an image), we also set all
|
||||
`[` delimiters before the opening delimiter to *inactive*. (This
|
||||
will prevent us from getting links within links.)
|
||||
|
||||
#### *process emphasis*
|
||||
|
||||
Parameter `stack_bottom` sets a lower bound to how far we
|
||||
descend in the [delimiter stack]. If it is NULL, we can
|
||||
go all the way to the bottom. Otherwise, we stop before
|
||||
visiting `stack_bottom`.
|
||||
|
||||
Let `current_position` point to the element on the [delimiter stack]
|
||||
just above `stack_bottom` (or the first element if `stack_bottom`
|
||||
is NULL).
|
||||
|
||||
We keep track of the `openers_bottom` for each delimiter
|
||||
type (`*`, `_`) and each length of the closing delimiter run
|
||||
(modulo 3). Initialize this to `stack_bottom`.
|
||||
|
||||
Then we repeat the following until we run out of potential
|
||||
closers:
|
||||
|
||||
- Move `current_position` forward in the delimiter stack (if needed)
|
||||
until we find the first potential closer with delimiter `*` or `_`.
|
||||
(This will be the potential closer closest
|
||||
to the beginning of the input -- the first one in parse order.)
|
||||
|
||||
- Now, look back in the stack (staying above `stack_bottom` and
|
||||
the `openers_bottom` for this delimiter type) for the
|
||||
first matching potential opener ("matching" means same delimiter).
|
||||
|
||||
- If one is found:
|
||||
|
||||
+ Figure out whether we have emphasis or strong emphasis:
|
||||
if both closer and opener spans have length >= 2, we have
|
||||
strong, otherwise regular.
|
||||
|
||||
+ Insert an emph or strong emph node accordingly, after
|
||||
the text node corresponding to the opener.
|
||||
|
||||
+ Remove any delimiters between the opener and closer from
|
||||
the delimiter stack.
|
||||
|
||||
+ Remove 1 (for regular emph) or 2 (for strong emph) delimiters
|
||||
from the opening and closing text nodes. If they become empty
|
||||
as a result, remove them and remove the corresponding element
|
||||
of the delimiter stack. If the closing node is removed, reset
|
||||
`current_position` to the next element in the stack.
|
||||
|
||||
- If none is found:
|
||||
|
||||
+ Set `openers_bottom` to the element before `current_position`.
|
||||
(We know that there are no openers for this kind of closer up to and
|
||||
including this point, so this puts a lower bound on future searches.)
|
||||
|
||||
+ If the closer at `current_position` is not a potential opener,
|
||||
remove it from the delimiter stack (since we know it can't
|
||||
be a closer either).
|
||||
|
||||
+ Advance `current_position` to the next element in the stack.
|
||||
|
||||
After we're done, we remove all delimiters above `stack_bottom` from the
|
||||
delimiter stack.
|
|
@ -0,0 +1,276 @@
|
|||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="1:1-4:3" class="code highlight js-syntax-highlight language-yaml" lang="yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">GitLab Flavored Markdown (GLFM) Spec</span></span>
|
||||
<span id="LC2" class="line" lang="yaml"><span class="na">version</span><span class="pi">:</span> <span class="s">alpha</span></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<h1 data-sourcepos="5:1-5:14" dir="auto">
|
||||
<a id="user-content-introduction" class="anchor" href="#introduction" aria-hidden="true"></a>Introduction</h1>
|
||||
<p data-sourcepos="7:1-7:84" dir="auto">TODO: Write a GitLab-specific version of the GitHub Flavored Markdown intro section.</p>
|
||||
|
||||
<h1 data-sourcepos="10:1-10:40" dir="auto">
|
||||
<a id="user-content-gitlab-official-specification-markdown" class="anchor" href="#gitlab-official-specification-markdown" aria-hidden="true"></a>GitLab Official Specification Markdown</h1>
|
||||
<p data-sourcepos="12:1-15:104" dir="auto">Currently, only some of the GitLab-specific markdown features are
|
||||
listed in this section. We may eventually add all
|
||||
GitLab-specific features currently listed as supported in the
|
||||
<a href="https://docs.gitlab.com/ee/user/markdown.html" rel="nofollow noreferrer noopener" target="_blank">user-facing documentation for GitLab Flavored Markdown</a>.</p>
|
||||
<p data-sourcepos="17:1-18:69" dir="auto">There is currently only this single top-level heading, but the
|
||||
examples may be split into multiple top-level headings in the future.</p>
|
||||
<h2 data-sourcepos="20:1-20:12" dir="auto">
|
||||
<a id="user-content-footnotes" class="anchor" href="#footnotes" aria-hidden="true"></a>Footnotes</h2>
|
||||
<p data-sourcepos="22:1-23:143" dir="auto">See
|
||||
<a href="https://docs.gitlab.com/ee/user/markdown.html#footnotes" rel="nofollow noreferrer noopener" target="_blank">the footnotes section of the user-facing documentation for GitLab Flavored Markdown</a>.</p>
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="25:1-49:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">footnote reference tag [^fortytwo]</span>
|
||||
<span id="LC2" class="line" lang="plaintext"></span>
|
||||
<span id="LC3" class="line" lang="plaintext">[^fortytwo]: footnote text</span>
|
||||
<span id="LC4" class="line" lang="plaintext">.</span>
|
||||
<span id="LC5" class="line" lang="plaintext"><p></span>
|
||||
<span id="LC6" class="line" lang="plaintext">footnote reference tag</span>
|
||||
<span id="LC7" class="line" lang="plaintext"><sup></span>
|
||||
<span id="LC8" class="line" lang="plaintext"><a href="#fn-fortytwo-42" id="fnref-fortytwo-42" data-footnote-ref></span>
|
||||
<span id="LC9" class="line" lang="plaintext">1</span>
|
||||
<span id="LC10" class="line" lang="plaintext"></a></span>
|
||||
<span id="LC11" class="line" lang="plaintext"></sup></span>
|
||||
<span id="LC12" class="line" lang="plaintext"></p></span>
|
||||
<span id="LC13" class="line" lang="plaintext"><section data-footnotes></span>
|
||||
<span id="LC14" class="line" lang="plaintext"><ol></span>
|
||||
<span id="LC15" class="line" lang="plaintext"><li id="fn-fortytwo-42"></span>
|
||||
<span id="LC16" class="line" lang="plaintext"><p></span>
|
||||
<span id="LC17" class="line" lang="plaintext">footnote text</span>
|
||||
<span id="LC18" class="line" lang="plaintext"><a href="#fnref-fortytwo-42" data-footnote-backref></span>
|
||||
<span id="LC19" class="line" lang="plaintext"></a></span>
|
||||
<span id="LC20" class="line" lang="plaintext"></p></span>
|
||||
<span id="LC21" class="line" lang="plaintext"></li></span>
|
||||
<span id="LC22" class="line" lang="plaintext"></ol></span>
|
||||
<span id="LC23" class="line" lang="plaintext"></section></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<h2 data-sourcepos="51:1-51:18" dir="auto">
|
||||
<a id="user-content-task-list-items" class="anchor" href="#task-list-items" aria-hidden="true"></a>Task list items</h2>
|
||||
<p data-sourcepos="53:1-54:117" dir="auto">See
|
||||
<a href="https://docs.gitlab.com/ee/user/markdown.html#task-lists" rel="nofollow noreferrer noopener" target="_blank">Task lists</a> in the GitLab Flavored Markdown documentation.</p>
|
||||
<p data-sourcepos="56:1-59:39" dir="auto">Task list items (checkboxes) are defined as a GitHub Flavored Markdown extension in a section above.
|
||||
GitLab extends the behavior of task list items to support additional features.
|
||||
Some of these features are in-progress, and should not yet be considered part of the official
|
||||
GitLab Flavored Markdown specification.</p>
|
||||
<p data-sourcepos="61:1-61:85" dir="auto">Some of the behavior of task list items is implemented as client-side JavaScript/CSS.</p>
|
||||
<p data-sourcepos="63:1-63:80" dir="auto">The following are some basic examples; more examples may be added in the future.</p>
|
||||
<p data-sourcepos="65:1-65:16" dir="auto">Incomplete task:</p>
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="67:1-77:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [ ] incomplete</span>
|
||||
<span id="LC2" class="line" lang="plaintext">.</span>
|
||||
<span id="LC3" class="line" lang="plaintext"><ul></span>
|
||||
<span id="LC4" class="line" lang="plaintext"><li></span>
|
||||
<span id="LC5" class="line" lang="plaintext"><task-button/></span>
|
||||
<span id="LC6" class="line" lang="plaintext"><input type="checkbox" disabled/></span>
|
||||
<span id="LC7" class="line" lang="plaintext">incomplete</span>
|
||||
<span id="LC8" class="line" lang="plaintext"></li></span>
|
||||
<span id="LC9" class="line" lang="plaintext"></ul></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<p data-sourcepos="79:1-79:15" dir="auto">Completed task:</p>
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="81:1-91:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [x] completed</span>
|
||||
<span id="LC2" class="line" lang="plaintext">.</span>
|
||||
<span id="LC3" class="line" lang="plaintext"><ul></span>
|
||||
<span id="LC4" class="line" lang="plaintext"><li></span>
|
||||
<span id="LC5" class="line" lang="plaintext"><task-button/></span>
|
||||
<span id="LC6" class="line" lang="plaintext"><input type="checkbox" checked disabled/></span>
|
||||
<span id="LC7" class="line" lang="plaintext">completed</span>
|
||||
<span id="LC8" class="line" lang="plaintext"></li></span>
|
||||
<span id="LC9" class="line" lang="plaintext"></ul></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<p data-sourcepos="93:1-93:18" dir="auto">Inapplicable task:</p>
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="95:1-107:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [~] inapplicable</span>
|
||||
<span id="LC2" class="line" lang="plaintext">.</span>
|
||||
<span id="LC3" class="line" lang="plaintext"><ul></span>
|
||||
<span id="LC4" class="line" lang="plaintext"><li></span>
|
||||
<span id="LC5" class="line" lang="plaintext"><task-button/></span>
|
||||
<span id="LC6" class="line" lang="plaintext"><input type="checkbox" data-inapplicable disabled></span>
|
||||
<span id="LC7" class="line" lang="plaintext"><s></span>
|
||||
<span id="LC8" class="line" lang="plaintext">inapplicable</span>
|
||||
<span id="LC9" class="line" lang="plaintext"></s></span>
|
||||
<span id="LC10" class="line" lang="plaintext"></li></span>
|
||||
<span id="LC11" class="line" lang="plaintext"></ul></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<p data-sourcepos="109:1-110:50" dir="auto">Inapplicable task in a "loose" list. Note that the <code><del></code> tag is not applied to the
|
||||
loose text; it has strikethrough applied with CSS.</p>
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="112:1-131:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">- [~] inapplicable</span>
|
||||
<span id="LC2" class="line" lang="plaintext"></span>
|
||||
<span id="LC3" class="line" lang="plaintext"> text in loose list</span>
|
||||
<span id="LC4" class="line" lang="plaintext">.</span>
|
||||
<span id="LC5" class="line" lang="plaintext"><ul></span>
|
||||
<span id="LC6" class="line" lang="plaintext"><li></span>
|
||||
<span id="LC7" class="line" lang="plaintext"><p></span>
|
||||
<span id="LC8" class="line" lang="plaintext"><task-button/></span>
|
||||
<span id="LC9" class="line" lang="plaintext"><input type="checkbox" data-inapplicable disabled></span>
|
||||
<span id="LC10" class="line" lang="plaintext"><s></span>
|
||||
<span id="LC11" class="line" lang="plaintext">inapplicable</span>
|
||||
<span id="LC12" class="line" lang="plaintext"></s></span>
|
||||
<span id="LC13" class="line" lang="plaintext"></p></span>
|
||||
<span id="LC14" class="line" lang="plaintext"><p></span>
|
||||
<span id="LC15" class="line" lang="plaintext">text in loose list</span>
|
||||
<span id="LC16" class="line" lang="plaintext"></p></span>
|
||||
<span id="LC17" class="line" lang="plaintext"></li></span>
|
||||
<span id="LC18" class="line" lang="plaintext"></ul></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<h2 data-sourcepos="133:1-133:15" dir="auto">
|
||||
<a id="user-content-front-matter" class="anchor" href="#front-matter" aria-hidden="true"></a>Front matter</h2>
|
||||
<p data-sourcepos="135:1-136:121" dir="auto">See
|
||||
<a href="https://docs.gitlab.com/ee/user/markdown.html#front-matter" rel="nofollow noreferrer noopener" target="_blank">Front matter</a> in the GitLab Flavored Markdown documentation.</p>
|
||||
<p data-sourcepos="138:1-139:95" dir="auto">Front matter is metadata included at the beginning of a Markdown document, preceding the content.
|
||||
This data can be used by static site generators like Jekyll, Hugo, and many other applications.</p>
|
||||
<p data-sourcepos="141:1-141:18" dir="auto">YAML front matter:</p>
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="143:1-153:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">---</span>
|
||||
<span id="LC2" class="line" lang="plaintext">title: YAML front matter</span>
|
||||
<span id="LC3" class="line" lang="plaintext">---</span>
|
||||
<span id="LC4" class="line" lang="plaintext">.</span>
|
||||
<span id="LC5" class="line" lang="plaintext"><pre></span>
|
||||
<span id="LC6" class="line" lang="plaintext"><code></span>
|
||||
<span id="LC7" class="line" lang="plaintext">title: YAML front matter</span>
|
||||
<span id="LC8" class="line" lang="plaintext"></code></span>
|
||||
<span id="LC9" class="line" lang="plaintext"></pre></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<p data-sourcepos="155:1-155:18" dir="auto">TOML front matter:</p>
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="157:1-167:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">+++</span>
|
||||
<span id="LC2" class="line" lang="plaintext">title: TOML front matter</span>
|
||||
<span id="LC3" class="line" lang="plaintext">+++</span>
|
||||
<span id="LC4" class="line" lang="plaintext">.</span>
|
||||
<span id="LC5" class="line" lang="plaintext"><pre></span>
|
||||
<span id="LC6" class="line" lang="plaintext"><code></span>
|
||||
<span id="LC7" class="line" lang="plaintext">title: TOML front matter</span>
|
||||
<span id="LC8" class="line" lang="plaintext"></code></span>
|
||||
<span id="LC9" class="line" lang="plaintext"></pre></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<p data-sourcepos="169:1-169:18" dir="auto">JSON front matter:</p>
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="171:1-185:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">;;;</span>
|
||||
<span id="LC2" class="line" lang="plaintext">{</span>
|
||||
<span id="LC3" class="line" lang="plaintext"> "title": "JSON front matter"</span>
|
||||
<span id="LC4" class="line" lang="plaintext">}</span>
|
||||
<span id="LC5" class="line" lang="plaintext">;;;</span>
|
||||
<span id="LC6" class="line" lang="plaintext">.</span>
|
||||
<span id="LC7" class="line" lang="plaintext"><pre></span>
|
||||
<span id="LC8" class="line" lang="plaintext"><code></span>
|
||||
<span id="LC9" class="line" lang="plaintext">{</span>
|
||||
<span id="LC10" class="line" lang="plaintext"> "title": "JSON front matter"</span>
|
||||
<span id="LC11" class="line" lang="plaintext">}</span>
|
||||
<span id="LC12" class="line" lang="plaintext"></code></span>
|
||||
<span id="LC13" class="line" lang="plaintext"></pre></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<p data-sourcepos="187:1-187:66" dir="auto">Front matter blocks should be inserted at the top of the document:</p>
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="189:1-199:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">text</span>
|
||||
<span id="LC2" class="line" lang="plaintext"></span>
|
||||
<span id="LC3" class="line" lang="plaintext">---</span>
|
||||
<span id="LC4" class="line" lang="plaintext">title: YAML front matter</span>
|
||||
<span id="LC5" class="line" lang="plaintext">---</span>
|
||||
<span id="LC6" class="line" lang="plaintext">.</span>
|
||||
<span id="LC7" class="line" lang="plaintext"><p>text</p></span>
|
||||
<span id="LC8" class="line" lang="plaintext"><hr></span>
|
||||
<span id="LC9" class="line" lang="plaintext"><h2>title: YAML front matter</h2></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<p data-sourcepos="201:1-201:74" dir="auto">Front matter block delimiters shouldn’t be preceded by space characters:</p>
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="203:1-210:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> ---</span>
|
||||
<span id="LC2" class="line" lang="plaintext">title: YAML front matter</span>
|
||||
<span id="LC3" class="line" lang="plaintext">---</span>
|
||||
<span id="LC4" class="line" lang="plaintext">.</span>
|
||||
<span id="LC5" class="line" lang="plaintext"><hr></span>
|
||||
<span id="LC6" class="line" lang="plaintext"><h2>title: YAML front matter</h2></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<h2 data-sourcepos="212:1-212:20" dir="auto">
|
||||
<a id="user-content-table-of-contents" class="anchor" href="#table-of-contents" aria-hidden="true"></a>Table of contents</h2>
|
||||
<p data-sourcepos="214:1-216:46" dir="auto">See
|
||||
<a href="https://docs.gitlab.com/ee/user/markdown.html#table-of-contents" rel="nofollow noreferrer noopener" target="_blank">table of contents</a>
|
||||
in the GitLab Flavored Markdown documentation.</p>
|
||||
<p data-sourcepos="218:1-219:58" dir="auto">A table of contents is an unordered list that links to subheadings in the document.
|
||||
Add either the <code>[[_TOC_]]</code> or </p><ul class="section-nav">
|
||||
<li><a href="#introduction">Introduction</a></li>
|
||||
<li>
|
||||
<a href="#gitlab-official-specification-markdown">GitLab Official Specification Markdown</a><ul>
|
||||
<li><a href="#footnotes">Footnotes</a></li>
|
||||
<li><a href="#task-list-items">Task list items</a></li>
|
||||
<li><a href="#front-matter">Front matter</a></li>
|
||||
<li><a href="#table-of-contents">Table of contents</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul> tag on its own line.
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="221:1-238:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[TOC]</span>
|
||||
<span id="LC2" class="line" lang="plaintext"></span>
|
||||
<span id="LC3" class="line" lang="plaintext"># Heading 1</span>
|
||||
<span id="LC4" class="line" lang="plaintext"></span>
|
||||
<span id="LC5" class="line" lang="plaintext">## Heading 2</span>
|
||||
<span id="LC6" class="line" lang="plaintext">.</span>
|
||||
<span id="LC7" class="line" lang="plaintext"><nav></span>
|
||||
<span id="LC8" class="line" lang="plaintext"> <ul></span>
|
||||
<span id="LC9" class="line" lang="plaintext"> <li><a href="#heading-1">Heading 1</a></li></span>
|
||||
<span id="LC10" class="line" lang="plaintext"> <ul></span>
|
||||
<span id="LC11" class="line" lang="plaintext"> <li><a href="#heading-2">Heading 2</a></li></span>
|
||||
<span id="LC12" class="line" lang="plaintext"> </ul></span>
|
||||
<span id="LC13" class="line" lang="plaintext"> </ul></span>
|
||||
<span id="LC14" class="line" lang="plaintext"></nav></span>
|
||||
<span id="LC15" class="line" lang="plaintext"><h1>Heading 1</h1></span>
|
||||
<span id="LC16" class="line" lang="plaintext"><h2>Heading 2</h2></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="240:1-257:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[_TOC_]]</span>
|
||||
<span id="LC2" class="line" lang="plaintext"></span>
|
||||
<span id="LC3" class="line" lang="plaintext"># Heading 1</span>
|
||||
<span id="LC4" class="line" lang="plaintext"></span>
|
||||
<span id="LC5" class="line" lang="plaintext">## Heading 2</span>
|
||||
<span id="LC6" class="line" lang="plaintext">.</span>
|
||||
<span id="LC7" class="line" lang="plaintext"><nav></span>
|
||||
<span id="LC8" class="line" lang="plaintext"> <ul></span>
|
||||
<span id="LC9" class="line" lang="plaintext"> <li><a href="#heading-1">Heading 1</a></li></span>
|
||||
<span id="LC10" class="line" lang="plaintext"> <ul></span>
|
||||
<span id="LC11" class="line" lang="plaintext"> <li><a href="#heading-2">Heading 2</a></li></span>
|
||||
<span id="LC12" class="line" lang="plaintext"> </ul></span>
|
||||
<span id="LC13" class="line" lang="plaintext"> </ul></span>
|
||||
<span id="LC14" class="line" lang="plaintext"></nav></span>
|
||||
<span id="LC15" class="line" lang="plaintext"><h1>Heading 1</h1></span>
|
||||
<span id="LC16" class="line" lang="plaintext"><h2>Heading 2</h2></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<p data-sourcepos="259:1-260:5" dir="auto">A table of contents is a block element. It should preceded and followed by a blank
|
||||
line.</p>
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="262:1-271:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">[[_TOC_]]</span>
|
||||
<span id="LC2" class="line" lang="plaintext">text</span>
|
||||
<span id="LC3" class="line" lang="plaintext"></span>
|
||||
<span id="LC4" class="line" lang="plaintext">text</span>
|
||||
<span id="LC5" class="line" lang="plaintext">[TOC]</span>
|
||||
<span id="LC6" class="line" lang="plaintext">.</span>
|
||||
<span id="LC7" class="line" lang="plaintext"><p>[[<em>TOC</em>]]text</p></span>
|
||||
<span id="LC8" class="line" lang="plaintext"><p>text[TOC]</p></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
<p data-sourcepos="273:1-273:60" dir="auto">A table of contents can be indented with up to three spaces.</p>
|
||||
<div class="gl-relative markdown-code-block js-markdown-code">
|
||||
<pre data-sourcepos="275:1-286:32" class="code highlight js-syntax-highlight language-plaintext" lang="plaintext" data-canonical-lang="example" v-pre="true"><code><span id="LC1" class="line" lang="plaintext"> [[_TOC_]]</span>
|
||||
<span id="LC2" class="line" lang="plaintext"></span>
|
||||
<span id="LC3" class="line" lang="plaintext"># Heading 1</span>
|
||||
<span id="LC4" class="line" lang="plaintext">.</span>
|
||||
<span id="LC5" class="line" lang="plaintext"><nav></span>
|
||||
<span id="LC6" class="line" lang="plaintext"> <ul></span>
|
||||
<span id="LC7" class="line" lang="plaintext"> <li><a href="#heading-1">Heading 1</a></li></span>
|
||||
<span id="LC8" class="line" lang="plaintext"> </ul></span>
|
||||
<span id="LC9" class="line" lang="plaintext"></nav></span>
|
||||
<span id="LC10" class="line" lang="plaintext"><h1>Heading 1</h1></span></code></pre>
|
||||
<copy-code></copy-code>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,287 @@
|
|||
---
|
||||
title: GitLab Flavored Markdown (GLFM) Spec
|
||||
version: alpha
|
||||
...
|
||||
# Introduction
|
||||
|
||||
TODO: Write a GitLab-specific version of the GitHub Flavored Markdown intro section.
|
||||
|
||||
<!-- BEGIN TESTS -->
|
||||
# GitLab Official Specification Markdown
|
||||
|
||||
Currently, only some of the GitLab-specific markdown features are
|
||||
listed in this section. We may eventually add all
|
||||
GitLab-specific features currently listed as supported in the
|
||||
[user-facing documentation for GitLab Flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html).
|
||||
|
||||
There is currently only this single top-level heading, but the
|
||||
examples may be split into multiple top-level headings in the future.
|
||||
|
||||
## Footnotes
|
||||
|
||||
See
|
||||
[the footnotes section of the user-facing documentation for GitLab Flavored Markdown](https://docs.gitlab.com/ee/user/markdown.html#footnotes).
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
footnote reference tag [^fortytwo]
|
||||
|
||||
[^fortytwo]: footnote text
|
||||
.
|
||||
<p>
|
||||
footnote reference tag
|
||||
<sup>
|
||||
<a href="#fn-fortytwo-42" id="fnref-fortytwo-42" data-footnote-ref>
|
||||
1
|
||||
</a>
|
||||
</sup>
|
||||
</p>
|
||||
<section data-footnotes>
|
||||
<ol>
|
||||
<li id="fn-fortytwo-42">
|
||||
<p>
|
||||
footnote text
|
||||
<a href="#fnref-fortytwo-42" data-footnote-backref>
|
||||
</a>
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
````````````````````````````````
|
||||
|
||||
## Task list items
|
||||
|
||||
See
|
||||
[Task lists](https://docs.gitlab.com/ee/user/markdown.html#task-lists) in the GitLab Flavored Markdown documentation.
|
||||
|
||||
Task list items (checkboxes) are defined as a GitHub Flavored Markdown extension in a section above.
|
||||
GitLab extends the behavior of task list items to support additional features.
|
||||
Some of these features are in-progress, and should not yet be considered part of the official
|
||||
GitLab Flavored Markdown specification.
|
||||
|
||||
Some of the behavior of task list items is implemented as client-side JavaScript/CSS.
|
||||
|
||||
The following are some basic examples; more examples may be added in the future.
|
||||
|
||||
Incomplete task:
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
- [ ] incomplete
|
||||
.
|
||||
<ul>
|
||||
<li>
|
||||
<task-button/>
|
||||
<input type="checkbox" disabled/>
|
||||
incomplete
|
||||
</li>
|
||||
</ul>
|
||||
````````````````````````````````
|
||||
|
||||
Completed task:
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
- [x] completed
|
||||
.
|
||||
<ul>
|
||||
<li>
|
||||
<task-button/>
|
||||
<input type="checkbox" checked disabled/>
|
||||
completed
|
||||
</li>
|
||||
</ul>
|
||||
````````````````````````````````
|
||||
|
||||
Inapplicable task:
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
- [~] inapplicable
|
||||
.
|
||||
<ul>
|
||||
<li>
|
||||
<task-button/>
|
||||
<input type="checkbox" data-inapplicable disabled>
|
||||
<s>
|
||||
inapplicable
|
||||
</s>
|
||||
</li>
|
||||
</ul>
|
||||
````````````````````````````````
|
||||
|
||||
Inapplicable task in a "loose" list. Note that the `<del>` tag is not applied to the
|
||||
loose text; it has strikethrough applied with CSS.
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
- [~] inapplicable
|
||||
|
||||
text in loose list
|
||||
.
|
||||
<ul>
|
||||
<li>
|
||||
<p>
|
||||
<task-button/>
|
||||
<input type="checkbox" data-inapplicable disabled>
|
||||
<s>
|
||||
inapplicable
|
||||
</s>
|
||||
</p>
|
||||
<p>
|
||||
text in loose list
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
````````````````````````````````
|
||||
|
||||
## Front matter
|
||||
|
||||
See
|
||||
[Front matter](https://docs.gitlab.com/ee/user/markdown.html#front-matter) in the GitLab Flavored Markdown documentation.
|
||||
|
||||
Front matter is metadata included at the beginning of a Markdown document, preceding the content.
|
||||
This data can be used by static site generators like Jekyll, Hugo, and many other applications.
|
||||
|
||||
YAML front matter:
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
---
|
||||
title: YAML front matter
|
||||
---
|
||||
.
|
||||
<pre>
|
||||
<code>
|
||||
title: YAML front matter
|
||||
</code>
|
||||
</pre>
|
||||
````````````````````````````````
|
||||
|
||||
TOML front matter:
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
+++
|
||||
title: TOML front matter
|
||||
+++
|
||||
.
|
||||
<pre>
|
||||
<code>
|
||||
title: TOML front matter
|
||||
</code>
|
||||
</pre>
|
||||
````````````````````````````````
|
||||
|
||||
JSON front matter:
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
;;;
|
||||
{
|
||||
"title": "JSON front matter"
|
||||
}
|
||||
;;;
|
||||
.
|
||||
<pre>
|
||||
<code>
|
||||
{
|
||||
"title": "JSON front matter"
|
||||
}
|
||||
</code>
|
||||
</pre>
|
||||
````````````````````````````````
|
||||
|
||||
Front matter blocks should be inserted at the top of the document:
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
text
|
||||
|
||||
---
|
||||
title: YAML front matter
|
||||
---
|
||||
.
|
||||
<p>text</p>
|
||||
<hr>
|
||||
<h2>title: YAML front matter</h2>
|
||||
````````````````````````````````
|
||||
|
||||
Front matter block delimiters shouldn’t be preceded by space characters:
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
---
|
||||
title: YAML front matter
|
||||
---
|
||||
.
|
||||
<hr>
|
||||
<h2>title: YAML front matter</h2>
|
||||
````````````````````````````````
|
||||
|
||||
## Table of contents
|
||||
|
||||
See
|
||||
[table of contents](https://docs.gitlab.com/ee/user/markdown.html#table-of-contents)
|
||||
in the GitLab Flavored Markdown documentation.
|
||||
|
||||
A table of contents is an unordered list that links to subheadings in the document.
|
||||
Add either the `[[_TOC_]]` or `[TOC]` tag on its own line.
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
[TOC]
|
||||
|
||||
# Heading 1
|
||||
|
||||
## Heading 2
|
||||
.
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="#heading-1">Heading 1</a></li>
|
||||
<ul>
|
||||
<li><a href="#heading-2">Heading 2</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
</nav>
|
||||
<h1>Heading 1</h1>
|
||||
<h2>Heading 2</h2>
|
||||
````````````````````````````````
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
[[_TOC_]]
|
||||
|
||||
# Heading 1
|
||||
|
||||
## Heading 2
|
||||
.
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="#heading-1">Heading 1</a></li>
|
||||
<ul>
|
||||
<li><a href="#heading-2">Heading 2</a></li>
|
||||
</ul>
|
||||
</ul>
|
||||
</nav>
|
||||
<h1>Heading 1</h1>
|
||||
<h2>Heading 2</h2>
|
||||
````````````````````````````````
|
||||
|
||||
A table of contents is a block element. It should preceded and followed by a blank
|
||||
line.
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
[[_TOC_]]
|
||||
text
|
||||
|
||||
text
|
||||
[TOC]
|
||||
.
|
||||
<p>[[<em>TOC</em>]]text</p>
|
||||
<p>text[TOC]</p>
|
||||
````````````````````````````````
|
||||
|
||||
A table of contents can be indented with up to three spaces.
|
||||
|
||||
```````````````````````````````` example gitlab
|
||||
[[_TOC_]]
|
||||
|
||||
# Heading 1
|
||||
.
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="#heading-1">Heading 1</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<h1>Heading 1</h1>
|
||||
````````````````````````````````
|
||||
<!-- END TESTS -->
|
|
@ -9,8 +9,8 @@ module QA
|
|||
def self.included(base)
|
||||
super
|
||||
|
||||
base.view 'app/assets/javascripts/lazy_loader.js' do
|
||||
element :js_lazy_loaded
|
||||
base.view 'app/views/layouts/_img_loader.html.haml' do
|
||||
element :js_lazy_loaded_content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -38,7 +38,7 @@ module QA
|
|||
# webdriver to miss the hit so we wait for the svg to load before
|
||||
# clicking the button.
|
||||
within_element(:svg_content) do
|
||||
has_element?(:js_lazy_loaded)
|
||||
has_element?(:js_lazy_loaded_content)
|
||||
end
|
||||
|
||||
click_element(:create_first_page_link)
|
||||
|
|
|
@ -12,10 +12,6 @@ module QA
|
|||
element :editor_toolbar_button
|
||||
end
|
||||
|
||||
view 'app/views/projects/blob/_editor.html.haml' do
|
||||
element :source_editor_preview_container
|
||||
end
|
||||
|
||||
def has_markdown_preview?(component, content)
|
||||
within_element(:source_editor_preview_container) do
|
||||
has_css?(component, exact_text: content)
|
||||
|
|
|
@ -11,7 +11,7 @@ module QA
|
|||
include Shared::Editor
|
||||
|
||||
view 'app/views/projects/blob/_editor.html.haml' do
|
||||
element :file_name, "text_field_tag 'file_name'" # rubocop:disable QA/ElementWithPattern
|
||||
element :file_name_field
|
||||
end
|
||||
|
||||
view 'app/views/projects/blob/_template_selectors.html.haml' do
|
||||
|
@ -23,7 +23,7 @@ module QA
|
|||
end
|
||||
|
||||
def add_name(name)
|
||||
fill_in 'file_name', with: name
|
||||
fill_element(:file_name_field, with: name)
|
||||
end
|
||||
|
||||
def select_template(template_type, template)
|
||||
|
|
|
@ -11,7 +11,7 @@ module QA
|
|||
super
|
||||
|
||||
base.view 'app/views/projects/blob/_editor.html.haml' do
|
||||
element :editor
|
||||
element :source_editor_preview_container
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -30,7 +30,7 @@ module QA
|
|||
private
|
||||
|
||||
def text_area
|
||||
within_element :editor do
|
||||
within_element :source_editor_preview_container do
|
||||
find('textarea', visible: false)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,7 +23,7 @@ module QA
|
|||
# This can cause webdriver to miss the hit so we wait for the svg to load (implicitly with has_element?)
|
||||
# before clicking the button.
|
||||
within_element(:label_svg_content) do
|
||||
has_element?(:js_lazy_loaded)
|
||||
has_element?(:js_lazy_loaded_content)
|
||||
end
|
||||
|
||||
click_element :create_new_label_button
|
||||
|
|
|
@ -16,22 +16,22 @@ module QA
|
|||
end
|
||||
|
||||
view 'app/views/projects/branches/_branch.html.haml' do
|
||||
element :branch_name
|
||||
element :badge_content
|
||||
element :branch_container
|
||||
element :branch_link
|
||||
end
|
||||
|
||||
view 'app/views/projects/branches/_panel.html.haml' do
|
||||
element :all_branches
|
||||
element :all_branches_container
|
||||
end
|
||||
|
||||
view 'app/views/projects/branches/index.html.haml' do
|
||||
element :delete_merged_branches
|
||||
element :delete_merged_branches_link
|
||||
end
|
||||
|
||||
def delete_branch(branch_name)
|
||||
within_element(:all_branches) do
|
||||
within(".js-branch-#{branch_name}") do
|
||||
click_element(:delete_branch_button)
|
||||
end
|
||||
within_element(:branch_container, name: branch_name) do
|
||||
click_element(:delete_branch_button)
|
||||
end
|
||||
|
||||
click_element(:delete_branch_confirmation_button)
|
||||
|
@ -41,22 +41,20 @@ module QA
|
|||
|
||||
def has_no_branch?(branch_name, reload: false)
|
||||
wait_until(reload: reload) do
|
||||
within_element(:all_branches) do
|
||||
has_no_element?(:branch_name, text: branch_name)
|
||||
within_element(:all_branches_container) do
|
||||
has_no_element?(:branch_link, text: branch_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def has_branch_with_badge?(branch_name, badge)
|
||||
within_element(:all_branches) do
|
||||
within(".js-branch-#{branch_name} .badge") do
|
||||
has_text?(badge)
|
||||
end
|
||||
within_element(:branch_container, name: branch_name) do
|
||||
has_element?(:badge_content, text: badge)
|
||||
end
|
||||
end
|
||||
|
||||
def delete_merged_branches
|
||||
click_element(:delete_merged_branches)
|
||||
click_element(:delete_merged_branches_link)
|
||||
click_confirmation_ok_button
|
||||
end
|
||||
end
|
||||
|
|
|
@ -35,10 +35,6 @@ module QA
|
|||
element :status_icon, 'ci-status-icon-${status}' # rubocop:disable QA/ElementWithPattern
|
||||
end
|
||||
|
||||
view 'app/views/projects/pipelines/_info.html.haml' do
|
||||
element :pipeline_badges
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue' do
|
||||
element :job_dropdown_container
|
||||
element :jobs_dropdown_menu
|
||||
|
@ -68,12 +64,6 @@ module QA
|
|||
has_no_element?(:job_link, text: job_name)
|
||||
end
|
||||
|
||||
def has_tag?(tag_name)
|
||||
within_element(:pipeline_badges) do
|
||||
has_selector?('.badge', text: tag_name)
|
||||
end
|
||||
end
|
||||
|
||||
def linked_pipelines
|
||||
all_elements(:linked_pipeline_container, minimum: 1)
|
||||
end
|
||||
|
|
|
@ -6,25 +6,25 @@ module QA
|
|||
module Settings
|
||||
class MirroringRepositories < Page::Base
|
||||
view 'app/views/projects/mirrors/_authentication_method.html.haml' do
|
||||
element :authentication_method
|
||||
element :password
|
||||
element :authentication_method_field
|
||||
element :password_field
|
||||
end
|
||||
|
||||
view 'app/views/projects/mirrors/_mirror_repos.html.haml' do
|
||||
element :mirror_repository_url_input
|
||||
element :mirror_repository_url_field
|
||||
element :mirror_repository_button
|
||||
end
|
||||
|
||||
view 'app/views/projects/mirrors/_mirror_repos_list.html.haml' do
|
||||
element :mirror_repository_url_cell
|
||||
element :mirror_last_update_at_cell
|
||||
element :mirror_error_badge
|
||||
element :mirrored_repository_row
|
||||
element :mirror_repository_url_content
|
||||
element :mirror_last_update_at_content
|
||||
element :mirror_error_badge_content
|
||||
element :mirrored_repository_row_container
|
||||
element :copy_public_key_button
|
||||
end
|
||||
|
||||
view 'app/views/projects/mirrors/_mirror_repos_form.html.haml' do
|
||||
element :mirror_direction
|
||||
element :mirror_direction_field
|
||||
end
|
||||
|
||||
view 'app/views/shared/_remote_mirror_update_button.html.haml' do
|
||||
|
@ -37,28 +37,23 @@ module QA
|
|||
element :fingerprints_list
|
||||
end
|
||||
|
||||
view 'app/views/projects/mirrors/_authentication_method.html.haml' do
|
||||
element :authentication_method
|
||||
element :password
|
||||
end
|
||||
|
||||
def repository_url=(value)
|
||||
fill_element :mirror_repository_url_input, value
|
||||
fill_element :mirror_repository_url_field, value
|
||||
end
|
||||
|
||||
def password=(value)
|
||||
fill_element :password, value
|
||||
fill_element :password_field, value
|
||||
end
|
||||
|
||||
def mirror_direction=(value)
|
||||
raise ArgumentError, "Mirror direction must be 'Push' or 'Pull'" unless %w[Push Pull].include?(value)
|
||||
|
||||
select_element(:mirror_direction, value)
|
||||
select_element(:mirror_direction_field, value)
|
||||
|
||||
# Changing the mirror direction causes the fields below to change,
|
||||
# and that change is animated, so we need to wait for the animation
|
||||
# to complete otherwise changes to those fields could fail
|
||||
wait_for_animated_element :authentication_method
|
||||
wait_for_animated_element :authentication_method_field
|
||||
end
|
||||
|
||||
def authentication_method=(value)
|
||||
|
@ -66,13 +61,13 @@ module QA
|
|||
raise ArgumentError, "Authentication method must be 'SSH public key', 'Password', or 'None'"
|
||||
end
|
||||
|
||||
select_element(:authentication_method, value)
|
||||
select_element(:authentication_method_field, value)
|
||||
end
|
||||
|
||||
def public_key(url)
|
||||
row_index = find_repository_row_index url
|
||||
|
||||
within_element_by_index(:mirrored_repository_row, row_index) do
|
||||
within_element_by_index(:mirrored_repository_row_container, row_index) do
|
||||
find_element(:copy_public_key_button)['data-clipboard-text']
|
||||
end
|
||||
end
|
||||
|
@ -92,7 +87,7 @@ module QA
|
|||
def update(url)
|
||||
row_index = find_repository_row_index(url)
|
||||
|
||||
within_element_by_index(:mirrored_repository_row, row_index) do
|
||||
within_element_by_index(:mirrored_repository_row_container, row_index) do
|
||||
# When a repository is first mirrored, the update process might
|
||||
# already be started, so the button is already "clicked"
|
||||
click_element :update_now_button unless has_element? :updating_button
|
||||
|
@ -105,16 +100,16 @@ module QA
|
|||
row_index = find_repository_row_index(url)
|
||||
|
||||
wait_until(sleep_interval: 1) do
|
||||
within_element_by_index(:mirrored_repository_row, row_index) do
|
||||
last_update = find_element(:mirror_last_update_at_cell, wait: 0)
|
||||
within_element_by_index(:mirrored_repository_row_container, row_index) do
|
||||
last_update = find_element(:mirror_last_update_at_content, wait: 0)
|
||||
last_update.has_text?('just now') || last_update.has_text?('seconds')
|
||||
end
|
||||
end
|
||||
|
||||
# Fail early if the page still shows that there has been no update
|
||||
within_element_by_index(:mirrored_repository_row, row_index) do
|
||||
find_element(:mirror_last_update_at_cell, wait: 0).assert_no_text('Never')
|
||||
assert_no_element(:mirror_error_badge)
|
||||
within_element_by_index(:mirrored_repository_row_container, row_index) do
|
||||
find_element(:mirror_last_update_at_content, wait: 0).assert_no_text('Never')
|
||||
assert_no_element(:mirror_error_badge_content)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -122,7 +117,7 @@ module QA
|
|||
|
||||
def find_repository_row_index(target_url)
|
||||
wait_until(max_duration: 5, reload: false) do
|
||||
all_elements(:mirror_repository_url_cell, minimum: 1).index do |url|
|
||||
all_elements(:mirror_repository_url_content, minimum: 1).index do |url|
|
||||
# The url might be a sanitized url but the target_url won't be so
|
||||
# we compare just the paths instead of the full url
|
||||
URI.parse(url.text).path == target_url.path
|
||||
|
|
|
@ -6,8 +6,8 @@ module QA
|
|||
module Settings
|
||||
class ProtectedBranches < Page::Base
|
||||
view 'app/views/projects/protected_branches/shared/_dropdown.html.haml' do
|
||||
element :protected_branch_select
|
||||
element :protected_branch_dropdown
|
||||
element :protected_branch_dropdown_content
|
||||
end
|
||||
|
||||
view 'app/views/projects/protected_branches/_create_protected_branch.html.haml' do
|
||||
|
@ -22,9 +22,9 @@ module QA
|
|||
end
|
||||
|
||||
def select_branch(branch_name)
|
||||
click_element :protected_branch_select
|
||||
click_element :protected_branch_dropdown
|
||||
|
||||
within_element(:protected_branch_dropdown) do
|
||||
within_element(:protected_branch_dropdown_content) do
|
||||
click_on branch_name
|
||||
end
|
||||
end
|
||||
|
|
|
@ -32,7 +32,7 @@ module QA
|
|||
end
|
||||
|
||||
view 'app/views/projects/_last_push.html.haml' do
|
||||
element :create_merge_request
|
||||
element :create_merge_request_button
|
||||
end
|
||||
|
||||
view 'app/views/projects/_home_panel.html.haml' do
|
||||
|
@ -54,7 +54,7 @@ module QA
|
|||
end
|
||||
|
||||
view 'app/views/projects/empty.html.haml' do
|
||||
element :quick_actions
|
||||
element :quick_actions_container
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/repository/components/breadcrumbs.vue' do
|
||||
|
@ -72,7 +72,7 @@ module QA
|
|||
end
|
||||
|
||||
view 'app/views/projects/blob/viewers/_loading.html.haml' do
|
||||
element :spinner
|
||||
element :spinner_placeholder
|
||||
end
|
||||
|
||||
view 'app/views/projects/buttons/_download.html.haml' do
|
||||
|
@ -80,11 +80,11 @@ module QA
|
|||
end
|
||||
|
||||
def wait_for_viewers_to_load
|
||||
has_no_element?(:spinner, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
|
||||
has_no_element?(:spinner_placeholder, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
|
||||
end
|
||||
|
||||
def create_first_new_file!
|
||||
within_element(:quick_actions) do
|
||||
within_element(:quick_actions_container) do
|
||||
click_link_with_text 'New file'
|
||||
end
|
||||
end
|
||||
|
@ -122,7 +122,7 @@ module QA
|
|||
end
|
||||
|
||||
def has_create_merge_request_button?
|
||||
has_css?(element_selector_css(:create_merge_request))
|
||||
has_css?(element_selector_css(:create_merge_request_button))
|
||||
end
|
||||
|
||||
def has_file?(name)
|
||||
|
@ -152,7 +152,7 @@ module QA
|
|||
has_create_merge_request_button?
|
||||
end
|
||||
|
||||
click_element :create_merge_request
|
||||
click_element :create_merge_request_button
|
||||
end
|
||||
|
||||
def open_web_ide!
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner do
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
describe 'Pipeline API defined variable inheritance' do
|
||||
include_context 'variable inheritance test prep'
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :requires_admin do
|
||||
RSpec.describe 'Verify', :requires_admin, product_group: :pipeline_execution do
|
||||
describe 'When user is blocked' do
|
||||
let!(:admin_api_client) { Runtime::API::Client.as_admin }
|
||||
let!(:user_api_client) { Runtime::API::Client.new(:gitlab, user: user) }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, feature_flag: {
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring, feature_flag: {
|
||||
name: 'ci_stop_expanding_file_vars_for_runners',
|
||||
scope: :project
|
||||
} do
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner do
|
||||
RSpec.describe 'Verify', :runner, product_group: :runner do
|
||||
describe 'Runner removal' do
|
||||
include Support::API
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module QA
|
||||
RSpec.describe 'Verify' do
|
||||
describe 'Add or Remove CI variable via UI', :smoke do
|
||||
describe 'Add or Remove CI variable via UI', :smoke, product_group: :pipeline_authoring do
|
||||
let(:project) do
|
||||
Resource::Project.fabricate_via_api! do |project|
|
||||
project.name = 'project-with-ci-variables'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner do
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
describe 'Pipeline with customizable variable' do
|
||||
let(:executor) { "qa-runner-#{Time.now.to_i}" }
|
||||
let(:pipeline_job_name) { 'customizable-variable' }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner do
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
describe 'Pipeline with protected variable' do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" }
|
||||
let(:protected_value) { Faker::Alphanumeric.alphanumeric(8) }
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module QA
|
||||
RSpec.describe 'Verify' do
|
||||
describe 'Pipeline with prefill variables' do
|
||||
describe 'Pipeline with prefill variables', product_group: :pipeline_authoring do
|
||||
let(:prefill_variable_description1) { Faker::Lorem.sentence }
|
||||
let(:prefill_variable_value1) { Faker::Lorem.word }
|
||||
let(:prefill_variable_description2) { Faker::Lorem.sentence }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner do
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
describe 'UI defined variable' do
|
||||
include_context 'variable inheritance test prep'
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner do
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
describe 'UI defined variable' do
|
||||
include_context 'variable inheritance test prep'
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :smoke, :runner, quarantine: {
|
||||
RSpec.describe 'Verify', :smoke, :runner, product_group: :pipeline_execution, quarantine: {
|
||||
issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/356295',
|
||||
type: :investigating
|
||||
} do
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module QA
|
||||
RSpec.describe 'Verify' do
|
||||
describe 'Include local config file paths with wildcard', :reliable do
|
||||
describe 'Include local config file paths with wildcard', :reliable, product_group: :pipeline_authoring do
|
||||
let(:project) do
|
||||
Resource::Project.fabricate_via_api! do |project|
|
||||
project.name = 'project-with-pipeline'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner do
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_authoring do
|
||||
describe 'Include multiple files from a project' do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" }
|
||||
let(:expected_text) { Faker::Lorem.sentence }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner, :requires_admin do
|
||||
RSpec.describe 'Verify', :runner, :requires_admin, product_group: :pipeline_insights do
|
||||
describe 'Artifacts' do
|
||||
context 'when locked' do
|
||||
let(:file_name) { 'artifact.txt' }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Verify', :runner do
|
||||
RSpec.describe 'Verify', :runner, product_group: :pipeline_execution do
|
||||
context 'When pipeline is blocked' do
|
||||
let(:executor) { "qa-runner-#{Faker::Alphanumeric.alphanumeric(8)}" }
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue