Commit 100709af authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 55585427 4326e564
......@@ -37,19 +37,19 @@
.if-automated-merge-request: &if-automated-merge-request
if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == "release-tools/update-gitaly" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /stable-ee$/'
.if-merge-request-title-as-if-foss: &if-merge-request-title-as-if-foss
.if-merge-request-labels-as-if-foss: &if-merge-request-labels-as-if-foss
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-as-if-foss/'
.if-merge-request-title-update-caches: &if-merge-request-title-update-caches
.if-merge-request-labels-update-caches: &if-merge-request-labels-update-caches
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:update-cache/'
.if-merge-request-title-run-all-rspec: &if-merge-request-title-run-all-rspec
.if-merge-request-labels-run-all-rspec: &if-merge-request-labels-run-all-rspec
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-all-rspec/'
.if-merge-request-title-run-all-jest: &if-merge-request-title-run-all-jest
.if-merge-request-labels-run-all-jest: &if-merge-request-labels-run-all-jest
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-all-jest/'
.if-merge-request-run-decomposed: &if-merge-request-run-decomposed
.if-merge-request-labels-run-decomposed: &if-merge-request-labels-run-decomposed
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-decomposed/'
.if-security-merge-request: &if-security-merge-request
......@@ -368,11 +368,11 @@
rules:
- <<: *if-default-branch-schedule-2-hourly
- <<: *if-security-schedule
- <<: *if-merge-request-title-update-caches
- <<: *if-merge-request-labels-update-caches
.shared:rules:update-gitaly-binaries-cache:
rules:
- <<: *if-merge-request-title-update-caches
- <<: *if-merge-request-labels-update-caches
- changes: *gitaly-patterns
######################
......@@ -481,14 +481,14 @@
.frontend:rules:compile-test-assets:
rules:
- changes: *code-backstage-qa-patterns
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
.frontend:rules:compile-test-assets-as-if-foss:
rules:
- <<: *if-not-ee
when: never
- changes: *code-backstage-qa-patterns
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
.frontend:rules:default-frontend-jobs:
rules:
......@@ -501,8 +501,8 @@
when: never
- <<: *if-security-merge-request
changes: *code-backstage-patterns
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-as-if-foss
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *startup-css-patterns
- <<: *if-merge-request
......@@ -510,7 +510,7 @@
.frontend:rules:jest:
rules:
- <<: *if-merge-request-title-run-all-jest
- <<: *if-merge-request-labels-run-all-jest
- <<: *if-default-refs
changes: *core-frontend-patterns
- <<: *if-merge-request
......@@ -530,7 +530,7 @@
when: never
- <<: *if-automated-merge-request
when: never
- <<: *if-merge-request-title-run-all-jest
- <<: *if-merge-request-labels-run-all-jest
when: never
- <<: *if-default-refs
changes: *core-frontend-patterns
......@@ -548,7 +548,7 @@
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-labels-as-if-foss
when: never
- <<: *if-merge-request
changes: *frontend-patterns
......@@ -618,8 +618,8 @@
when: never
- <<: *if-security-merge-request
changes: *code-qa-patterns
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-as-if-foss
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
......@@ -645,11 +645,11 @@
###############
.rails:rules:decomposed-databases:
rules:
- <<: *if-merge-request-run-decomposed
- <<: *if-merge-request-labels-run-decomposed
.rails:rules:ee-and-foss-migration:
rules:
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-merge-request
......@@ -666,7 +666,7 @@
when: never
- <<: *if-automated-merge-request
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
changes: *ci-patterns
......@@ -679,7 +679,7 @@
rules:
- <<: *if-merge-request
changes: *db-patterns
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
.rails:rules:db:gitlabcom-database-testing:
rules:
......@@ -691,7 +691,7 @@
.rails:rules:ee-and-foss-unit:
rules:
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-automated-merge-request
......@@ -706,7 +706,7 @@
when: never
- <<: *if-automated-merge-request
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
changes: *ci-patterns
......@@ -716,7 +716,7 @@
.rails:rules:ee-and-foss-integration:
rules:
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-automated-merge-request
......@@ -731,7 +731,7 @@
when: never
- <<: *if-automated-merge-request
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
changes: *ci-patterns
......@@ -741,7 +741,7 @@
.rails:rules:ee-and-foss-system:
rules:
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-automated-merge-request
......@@ -756,7 +756,7 @@
when: never
- <<: *if-automated-merge-request
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
changes: *ci-patterns
......@@ -766,7 +766,7 @@
.rails:rules:ee-and-foss-fast_spec_helper:
rules:
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-automated-merge-request
......@@ -781,7 +781,7 @@
when: never
- <<: *if-automated-merge-request
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
changes: *ci-patterns
......@@ -792,13 +792,13 @@
.rails:rules:code-backstage-qa:
rules:
- changes: *code-backstage-qa-patterns
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
.rails:rules:ee-only-migration:
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-merge-request
......@@ -817,7 +817,7 @@
when: never
- <<: *if-automated-merge-request
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
changes: *ci-patterns
......@@ -830,7 +830,7 @@
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-automated-merge-request
......@@ -847,7 +847,7 @@
when: never
- <<: *if-automated-merge-request
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
changes: *ci-patterns
......@@ -859,7 +859,7 @@
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-automated-merge-request
......@@ -876,7 +876,7 @@
when: never
- <<: *if-automated-merge-request
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
changes: *ci-patterns
......@@ -888,7 +888,7 @@
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-automated-merge-request
......@@ -905,7 +905,7 @@
when: never
- <<: *if-automated-merge-request
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
changes: *ci-patterns
......@@ -917,12 +917,12 @@
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-security-merge-request
changes: *db-patterns
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-labels-as-if-foss
changes: *db-patterns
- <<: *if-automated-merge-request
changes: *db-patterns
......@@ -943,7 +943,7 @@
- <<: *if-security-merge-request
changes: *db-patterns
when: never
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-labels-as-if-foss
changes: *db-patterns
when: never
......@@ -951,7 +951,7 @@
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-automated-merge-request
......@@ -960,7 +960,7 @@
when: never
- <<: *if-security-merge-request
changes: *backend-patterns
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-labels-as-if-foss
changes: *backend-patterns
.rails:rules:as-if-foss-unit:minimal:
......@@ -976,14 +976,14 @@
when: never
- <<: *if-security-merge-request
changes: *backend-patterns
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-labels-as-if-foss
changes: *backend-patterns
.rails:rules:as-if-foss-integration:
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-automated-merge-request
......@@ -992,7 +992,7 @@
when: never
- <<: *if-security-merge-request
changes: *backend-patterns
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-labels-as-if-foss
changes: *backend-patterns
.rails:rules:as-if-foss-integration:minimal:
......@@ -1008,14 +1008,14 @@
when: never
- <<: *if-security-merge-request
changes: *backend-patterns
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-labels-as-if-foss
changes: *backend-patterns
.rails:rules:as-if-foss-system:
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *ci-patterns
- <<: *if-automated-merge-request
......@@ -1024,7 +1024,7 @@
when: never
- <<: *if-security-merge-request
changes: *code-backstage-patterns
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-labels-as-if-foss
changes: *code-backstage-patterns
.rails:rules:as-if-foss-system:minimal:
......@@ -1040,19 +1040,19 @@
when: never
- <<: *if-security-merge-request
changes: *code-backstage-patterns
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-labels-as-if-foss
changes: *code-backstage-patterns
.rails:rules:ee-and-foss-db-library-code:
rules:
- changes: *db-library-patterns
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
.rails:rules:ee-mr-and-default-branch-only:
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
- <<: *if-merge-request
changes: *code-backstage-patterns
- <<: *if-default-branch-refs
......@@ -1061,13 +1061,13 @@
.rails:rules:detect-tests:
rules:
- changes: *code-backstage-patterns
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
.rails:rules:rspec-foss-impact:
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-labels-as-if-foss
when: never
- <<: *if-security-merge-request
changes: *code-backstage-patterns
......@@ -1099,7 +1099,7 @@
- <<: *if-not-ee
when: never
- <<: *if-default-branch-schedule-nightly
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
.rails:rules:rspec-coverage:
rules:
......@@ -1109,7 +1109,7 @@
changes: *code-backstage-patterns
when: always
- <<: *if-default-branch-schedule-2-hourly
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
when: always
.rails:rules:default-branch-schedule-nightly--code-backstage:
......@@ -1144,7 +1144,7 @@
rules:
- <<: *if-not-ee
when: never
- <<: *if-merge-request-title-as-if-foss
- <<: *if-merge-request-labels-as-if-foss
changes: *code-backstage-qa-patterns
- <<: *if-security-merge-request
changes: *code-backstage-qa-patterns
......@@ -1159,7 +1159,7 @@
rules:
- <<: *if-merge-request
changes: ["vendor/gems/mail-smtp_pool/**/*"]
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
##################
# Releases rules #
......@@ -1504,7 +1504,7 @@
rules:
- changes: *code-backstage-patterns
when: on_success
- <<: *if-merge-request-title-run-all-rspec
- <<: *if-merge-request-labels-run-all-rspec
.test-metadata:rules:update-tests-metadata:
rules:
......
---
stage: Growth
group: Product Intelligence
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
redirect_to: 'https://metrics.gitlab.com/snowplow.html'
remove_date: '2021-12-28'
---
<!---
This documentation is auto generated by a script.
Please do not edit this file directly, check generate_event_dictionary task on lib/tasks/gitlab/snowplow.rake.
--->
<!-- vale gitlab.Spelling = NO -->
# Event Dictionary
This file is autogenerated, please do not edit it directly.
To generate these files from the GitLab repository, run:
```shell
bundle exec rake gitlab:snowplow:generate_event_dictionary
```
The Event Dictionary is based on the following event definition YAML files:
- [`config/events`](https://gitlab.com/gitlab-org/gitlab/-/tree/f9a404301ca22d038e7b9a9eb08d9c1bbd6c4d84/config/events)
- [`ee/config/events`](https://gitlab.com/gitlab-org/gitlab/-/tree/f9a404301ca22d038e7b9a9eb08d9c1bbd6c4d84/ee/config/events)
## Event definitions
### `epics promote`
| category | action | label | property | value |
|---|---|---|---|---|
| `epics` | `promote` | `` | `The string "issue_id"` | `ID of the issue` |
Issue promoted to epic
YAML definition: `/ee/config/events/epics_promote.yml`
Owner: `group::product planning`
Tiers: `premium`, `ultimate`
......@@ -39,7 +39,7 @@ Snowplow is an enterprise-grade marketing and Product Intelligence platform whic
- [Understanding the structure of Snowplow data](https://docs.snowplowanalytics.com/docs/understanding-your-pipeline/canonical-event/)
- [Our Iglu schema registry](https://gitlab.com/gitlab-org/iglu)
- [List of events used in our codebase (Event Dictionary)](dictionary.md)
- [List of events used in our codebase (Event Dictionary)](https://metrics.gitlab.com/snowplow.html)
## Enable Snowplow tracking
......
......@@ -14,7 +14,7 @@ general best practices for code reviews, refer to our [code review guide](../cod
## Resources for reviewers
- [Snowplow Guide](index.md)
- [Event Dictionary](dictionary.md)
- [Event Dictionary](https://metrics.gitlab.com/snowplow.html)
## Review process
......
# frozen_string_literal: true
module Gitlab
module Tracking
module Docs
# Helper with functions to be used by HAML templates
module Helper
def auto_generated_comment
<<-MARKDOWN.strip_heredoc
---
stage: Growth
group: Product Intelligence
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
<!---
This documentation is auto generated by a script.
Please do not edit this file directly, check generate_event_dictionary task on lib/tasks/gitlab/snowplow.rake.
--->
<!-- vale gitlab.Spelling = NO -->
MARKDOWN
end
def render_description(object)
return 'Missing description' unless object.description.present?
object.description
end
def render_event_taxonomy(object)
headers = %w[category action label property value]
values = %i[category action label property_description value_description]
values = values.map { |key| backtick(object.attributes[key]) }
values = values.join(" | ")
[
"| #{headers.join(" | ")} |",
"#{'|---' * headers.size}|",
"| #{values} |"
].join("\n")
end
def md_link_to(anchor_text, url)
"[#{anchor_text}](#{url})"
end
def render_owner(object)
"Owner: #{backtick(object.product_group)}"
end
def render_tiers(object)
"Tiers: #{object.tiers.map(&method(:backtick)).join(', ')}"
end
def render_yaml_definition_path(object)
"YAML definition: #{backtick(object.yaml_path)}"
end
def backtick(string)
"`#{string}`"
end
end
end
end
end
# frozen_string_literal: true
module Gitlab
module Tracking
module Docs
class Renderer
include Gitlab::Tracking::Docs::Helper
DICTIONARY_PATH = Rails.root.join('doc', 'development', 'snowplow')
TEMPLATE_PATH = Rails.root.join('lib', 'gitlab', 'tracking', 'docs', 'templates', 'default.md.haml')
def initialize(event_definitions)
@layout = Haml::Engine.new(File.read(TEMPLATE_PATH))
@event_definitions = event_definitions.sort
end
def contents
# Render and remove an extra trailing new line
@contents ||= @layout.render(self, event_definitions: @event_definitions).sub!(/\n(?=\Z)/, '')
end
def write
filename = DICTIONARY_PATH.join('dictionary.md').to_s
FileUtils.mkdir_p(DICTIONARY_PATH)
File.write(filename, contents)
filename
end
end
end
end
end
= auto_generated_comment
:plain
# Event Dictionary
This file is autogenerated, please do not edit it directly.
To generate these files from the GitLab repository, run:
```shell
bundle exec rake gitlab:snowplow:generate_event_dictionary
```
The Event Dictionary is based on the following event definition YAML files:
- [`config/events`](https://gitlab.com/gitlab-org/gitlab/-/tree/f9a404301ca22d038e7b9a9eb08d9c1bbd6c4d84/config/events)
- [`ee/config/events`](https://gitlab.com/gitlab-org/gitlab/-/tree/f9a404301ca22d038e7b9a9eb08d9c1bbd6c4d84/ee/config/events)
## Event definitions
\
- event_definitions.each do |_path, object|
= "### `#{object.category} #{object.action}`"
\
= render_event_taxonomy(object)
\
= render_description(object)
\
= render_yaml_definition_path(object)
\
= render_owner(object)
\
= render_tiers(object)
\
# frozen_string_literal: true
namespace :gitlab do
namespace :snowplow do
desc 'GitLab | Snowplow | Generate event dictionary'
task generate_event_dictionary: :environment do
items = Gitlab::Tracking::EventDefinition.definitions
Gitlab::Tracking::Docs::Renderer.new(items).write
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Tracking::Docs::Helper do
let_it_be(:klass) do
Class.new do
include Gitlab::Tracking::Docs::Helper
end
end
describe '#auto_generated_comment' do
it 'renders information about missing description' do
expect(klass.new.auto_generated_comment).to match /This documentation is auto generated by a script/
end
end
describe '#render_description' do
context 'description is empty' do
it 'renders information about missing description' do
object = double(description: '')
expect(klass.new.render_description(object)).to eq('Missing description')
end
end
context 'description is present' do
it 'render description' do
object = double(description: 'some description')
expect(klass.new.render_description(object)).to eq('some description')
end
end
end
describe '#render_event_taxonomy' do
it 'render table with event taxonomy' do
attributes = {
category: 'epics',
action: 'promote',
label: nil,
property_description: 'String with issue id',
value_description: 'Integer issue id'
}
object = double(attributes: attributes)
event_taxonomy = <<~MD.chomp
| category | action | label | property | value |
|---|---|---|---|---|
| `epics` | `promote` | `` | `String with issue id` | `Integer issue id` |
MD
expect(klass.new.render_event_taxonomy(object)).to eq(event_taxonomy)
end
end
describe '#md_link_to' do
it 'render link in md format' do
expect(klass.new.md_link_to('zelda', 'link')).to eq('[zelda](link)')
end
end
describe '#render_owner' do
it 'render information about group owning event' do
object = double(product_group: "group::product intelligence")
expect(klass.new.render_owner(object)).to eq("Owner: `group::product intelligence`")
end
end
describe '#render_tiers' do
it 'render information about tiers' do
object = double(tiers: %w[bronze silver gold])
expect(klass.new.render_tiers(object)).to eq("Tiers: `bronze`, `silver`, `gold`")
end
end
describe '#render_yaml_definition_path' do
it 'render relative location of yaml definition' do
object = double(yaml_path: 'config/events/button_click.yaml')
expect(klass.new.render_yaml_definition_path(object)).to eq("YAML definition: `config/events/button_click.yaml`")
end
end
describe '#backtick' do
it 'wraps string in backticks chars' do
expect(klass.new.backtick('test')).to eql("`test`")
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Tracking::Docs::Renderer do
describe 'contents' do
let(:dictionary_path) { described_class::DICTIONARY_PATH }
let(:items) { Gitlab::Tracking::EventDefinition.definitions.first(10).to_h }
it 'generates dictionary for given items' do
generated_dictionary = described_class.new(items).contents
table_of_contents_items = items.values.map { |item| "#{item.category} #{item.action}"}
generated_dictionary_keys = RDoc::Markdown
.parse(generated_dictionary)
.table_of_contents
.select { |metric_doc| metric_doc.level == 3 }
.map { |item| item.text.match(%r{<code>(.*)</code>})&.captures&.first }
expect(generated_dictionary_keys).to match_array(table_of_contents_items)
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment