gitlab_internal_events_cli 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.tool-versions +1 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +90 -0
- data/LICENSE.txt +19 -0
- data/README.md +164 -0
- data/Rakefile +10 -0
- data/exe/gitlab-internal-events-cli +7 -0
- data/gitlab_internal_events_cli.gemspec +39 -0
- data/lib/gitlab_internal_events_cli/cli.rb +59 -0
- data/lib/gitlab_internal_events_cli/configuration.rb +115 -0
- data/lib/gitlab_internal_events_cli/event.rb +73 -0
- data/lib/gitlab_internal_events_cli/flows/event_definer.rb +306 -0
- data/lib/gitlab_internal_events_cli/flows/flow_advisor.rb +90 -0
- data/lib/gitlab_internal_events_cli/flows/metric_definer.rb +468 -0
- data/lib/gitlab_internal_events_cli/flows/usage_viewer.rb +474 -0
- data/lib/gitlab_internal_events_cli/gitlab_prompt.rb +9 -0
- data/lib/gitlab_internal_events_cli/global_state.rb +63 -0
- data/lib/gitlab_internal_events_cli/helpers/cli_inputs.rb +138 -0
- data/lib/gitlab_internal_events_cli/helpers/event_options.rb +63 -0
- data/lib/gitlab_internal_events_cli/helpers/files.rb +84 -0
- data/lib/gitlab_internal_events_cli/helpers/formatting.rb +166 -0
- data/lib/gitlab_internal_events_cli/helpers/group_ownership.rb +160 -0
- data/lib/gitlab_internal_events_cli/helpers/metric_options.rb +253 -0
- data/lib/gitlab_internal_events_cli/helpers/schema_loader.rb +25 -0
- data/lib/gitlab_internal_events_cli/helpers/service_ping_dashboards.rb +22 -0
- data/lib/gitlab_internal_events_cli/helpers.rb +47 -0
- data/lib/gitlab_internal_events_cli/http_cache.rb +52 -0
- data/lib/gitlab_internal_events_cli/metric.rb +406 -0
- data/lib/gitlab_internal_events_cli/schema_resolver.rb +25 -0
- data/lib/gitlab_internal_events_cli/subflows/database_metric_definer.rb +71 -0
- data/lib/gitlab_internal_events_cli/subflows/event_metric_definer.rb +258 -0
- data/lib/gitlab_internal_events_cli/text/event_definer.rb +166 -0
- data/lib/gitlab_internal_events_cli/text/flow_advisor.rb +64 -0
- data/lib/gitlab_internal_events_cli/text/metric_definer.rb +138 -0
- data/lib/gitlab_internal_events_cli/time_framed_key_path.rb +18 -0
- data/lib/gitlab_internal_events_cli/version.rb +5 -0
- data/lib/gitlab_internal_events_cli.rb +36 -0
- metadata +170 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 53b38b01e7214b61bb0a8768a926f2a335c7fcdd509c23879aa00627a15b9e6d
|
|
4
|
+
data.tar.gz: 7a23d46213056876709d6c6c1d77b068c94bf8b54a4887faec103747718d2b0f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e869509a120eeb35c09557cdc96c7ce6313338a95ef7dc59b7110202e55719460e01abf1e1f497f0eab3cd2df9a860eb3932f0fdd4307cb350d2cfa8976dc460
|
|
7
|
+
data.tar.gz: 11afd1175a2873484df7af82f9071610811bcd07e69aa0438eab73dc97bb94ac4008478e78af4b6b50234b0f8a943c6a4a71c9ecd17358816c8c826e3fec9e3e
|
data/.rspec
ADDED
data/.tool-versions
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ruby 3.4.8
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
gitlab_internal_events_cli (0.0.1)
|
|
5
|
+
json_schemer (~> 2.3.0)
|
|
6
|
+
pastel (~> 0.8.0)
|
|
7
|
+
tty-prompt (~> 0.23)
|
|
8
|
+
|
|
9
|
+
GEM
|
|
10
|
+
remote: https://rubygems.org/
|
|
11
|
+
specs:
|
|
12
|
+
ast (2.4.3)
|
|
13
|
+
bigdecimal (4.0.1)
|
|
14
|
+
diff-lcs (1.6.2)
|
|
15
|
+
hana (1.3.7)
|
|
16
|
+
json (2.18.0)
|
|
17
|
+
json_schemer (2.3.0)
|
|
18
|
+
bigdecimal
|
|
19
|
+
hana (~> 1.3)
|
|
20
|
+
regexp_parser (~> 2.0)
|
|
21
|
+
simpleidn (~> 0.2)
|
|
22
|
+
language_server-protocol (3.17.0.5)
|
|
23
|
+
lint_roller (1.1.0)
|
|
24
|
+
parallel (1.27.0)
|
|
25
|
+
parser (3.3.10.1)
|
|
26
|
+
ast (~> 2.4.1)
|
|
27
|
+
racc
|
|
28
|
+
pastel (0.8.0)
|
|
29
|
+
tty-color (~> 0.5)
|
|
30
|
+
prism (1.9.0)
|
|
31
|
+
racc (1.8.1)
|
|
32
|
+
rainbow (3.1.1)
|
|
33
|
+
rake (13.3.1)
|
|
34
|
+
regexp_parser (2.11.3)
|
|
35
|
+
rspec (3.13.2)
|
|
36
|
+
rspec-core (~> 3.13.0)
|
|
37
|
+
rspec-expectations (~> 3.13.0)
|
|
38
|
+
rspec-mocks (~> 3.13.0)
|
|
39
|
+
rspec-core (3.13.6)
|
|
40
|
+
rspec-support (~> 3.13.0)
|
|
41
|
+
rspec-expectations (3.13.5)
|
|
42
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
43
|
+
rspec-support (~> 3.13.0)
|
|
44
|
+
rspec-mocks (3.13.7)
|
|
45
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
46
|
+
rspec-support (~> 3.13.0)
|
|
47
|
+
rspec-support (3.13.7)
|
|
48
|
+
rubocop (1.84.0)
|
|
49
|
+
json (~> 2.3)
|
|
50
|
+
language_server-protocol (~> 3.17.0.2)
|
|
51
|
+
lint_roller (~> 1.1.0)
|
|
52
|
+
parallel (~> 1.10)
|
|
53
|
+
parser (>= 3.3.0.2)
|
|
54
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
55
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
56
|
+
rubocop-ast (>= 1.49.0, < 2.0)
|
|
57
|
+
ruby-progressbar (~> 1.7)
|
|
58
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
59
|
+
rubocop-ast (1.49.0)
|
|
60
|
+
parser (>= 3.3.7.2)
|
|
61
|
+
prism (~> 1.7)
|
|
62
|
+
ruby-progressbar (1.13.0)
|
|
63
|
+
simpleidn (0.2.3)
|
|
64
|
+
tty-color (0.6.0)
|
|
65
|
+
tty-cursor (0.7.1)
|
|
66
|
+
tty-prompt (0.23.1)
|
|
67
|
+
pastel (~> 0.8)
|
|
68
|
+
tty-reader (~> 0.8)
|
|
69
|
+
tty-reader (0.9.0)
|
|
70
|
+
tty-cursor (~> 0.7)
|
|
71
|
+
tty-screen (~> 0.8)
|
|
72
|
+
wisper (~> 2.0)
|
|
73
|
+
tty-screen (0.8.2)
|
|
74
|
+
unicode-display_width (3.2.0)
|
|
75
|
+
unicode-emoji (~> 4.1)
|
|
76
|
+
unicode-emoji (4.2.0)
|
|
77
|
+
wisper (2.0.1)
|
|
78
|
+
|
|
79
|
+
PLATFORMS
|
|
80
|
+
arm64-darwin-24
|
|
81
|
+
ruby
|
|
82
|
+
|
|
83
|
+
DEPENDENCIES
|
|
84
|
+
gitlab_internal_events_cli!
|
|
85
|
+
rake (~> 13.0)
|
|
86
|
+
rspec (~> 3.0)
|
|
87
|
+
rubocop (~> 1.21)
|
|
88
|
+
|
|
89
|
+
BUNDLED WITH
|
|
90
|
+
2.6.6
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2024 GitLab B.V.
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# GitLab Internal Events CLI
|
|
2
|
+
|
|
3
|
+
An interactive CLI tool for creating event and metric definition files for GitLab's Internal Events tracking.
|
|
4
|
+
|
|
5
|
+
This gem extracts the Internal Events CLI from the GitLab monorepo, making it an independent, configurable Ruby gem that can be used in GitLab projects.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Interactive CLI** - Guided flows for creating events and metrics
|
|
10
|
+
- **YAML Generation** - Creates properly formatted event and metric definition files
|
|
11
|
+
- **Code Examples** - Generates code snippets for instrumentation in Rails, RSpec, JavaScript, Vue, and HAML
|
|
12
|
+
- **Configurable** - Adapt paths to work with custom project structures
|
|
13
|
+
- **Metadata Fetching** - Stages and groups fetched directly from GitLab repository
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
Add this line to your application's Gemfile:
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
gem 'gitlab_internal_events_cli', path: 'path/to/this/repo'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
And then execute:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
bundle install
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Or install it yourself as:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
gem install gitlab_internal_events_cli
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
### Running the CLI
|
|
38
|
+
|
|
39
|
+
From the root of a GitLab project (or any project with the expected directory structure):
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
gitlab-internal-events-cli
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The CLI provides an interactive menu to:
|
|
46
|
+
- **New Event** - Define a new event to track specific scenarios
|
|
47
|
+
- **New Metric** - Define metrics that count events over time
|
|
48
|
+
- **View Usage** - See code examples for existing events
|
|
49
|
+
- **Help/Flow Advisor** - Get guidance on which tool to use
|
|
50
|
+
|
|
51
|
+
### Configuration
|
|
52
|
+
|
|
53
|
+
The CLI can be configured via a `.gitlab_internal_events_cli.yml` file in your project root:
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
# Optional: Customize paths and URLs
|
|
57
|
+
project_root: .
|
|
58
|
+
|
|
59
|
+
# Local file paths (relative to project_root)
|
|
60
|
+
event_paths:
|
|
61
|
+
- config/events/*.yml
|
|
62
|
+
- ee/config/events/*.yml
|
|
63
|
+
metric_paths:
|
|
64
|
+
- config/metrics/counts_all/*.yml
|
|
65
|
+
- config/metrics/counts_7d/*.yml
|
|
66
|
+
- config/metrics/counts_28d/*.yml
|
|
67
|
+
- ee/config/metrics/counts_all/*.yml
|
|
68
|
+
- ee/config/metrics/counts_7d/*.yml
|
|
69
|
+
- ee/config/metrics/counts_28d/*.yml
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Architecture
|
|
73
|
+
|
|
74
|
+
### Metadata Fetching
|
|
75
|
+
|
|
76
|
+
The gem fetches metadata from GitLab repositories:
|
|
77
|
+
- **Stages/Groups**: Fetched from `gitlab-com/www-gitlab-com` master branch for product organization
|
|
78
|
+
|
|
79
|
+
This ensures the CLI has up-to-date information about product stages and groups without duplicating data.
|
|
80
|
+
|
|
81
|
+
### Milestone Detection
|
|
82
|
+
|
|
83
|
+
The milestone is automatically detected from the `VERSION` file in the project root:
|
|
84
|
+
1. **VERSION file**: Extracts `X.Y` from content like `17.8.0-pre`
|
|
85
|
+
1. **Fallback**: Defaults to `"TODO"` if not found
|
|
86
|
+
|
|
87
|
+
### Directory Structure
|
|
88
|
+
|
|
89
|
+
The CLI expects the following structure (configurable):
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
project/
|
|
93
|
+
├── VERSION # Milestone detection
|
|
94
|
+
├── config/
|
|
95
|
+
│ ├── events/*.yml # Event definitions
|
|
96
|
+
│ ├── metrics/
|
|
97
|
+
│ │ ├── counts_all/*.yml # Total count metrics
|
|
98
|
+
│ │ ├── counts_7d/*.yml # Weekly metrics
|
|
99
|
+
│ │ └── counts_28d/*.yml # Monthly metrics
|
|
100
|
+
│ └── feature_categories.yml # Feature categories
|
|
101
|
+
└── ee/ # Enterprise Edition
|
|
102
|
+
├── config/events/*.yml
|
|
103
|
+
└── config/metrics/...
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Development
|
|
107
|
+
|
|
108
|
+
After checking out the repo, run:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
bundle install
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Run the tests:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
bundle exec rspec
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Run rubocop:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
bundle exec rubocop
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Building and running the gem locally
|
|
127
|
+
|
|
128
|
+
Build the gem:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
gem build gitlab_internal_events_cli.gemspec
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
This produces a `.gem` file in the current directory (e.g. `gitlab_internal_events_cli-0.0.1.gem`).
|
|
135
|
+
|
|
136
|
+
Install it locally:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
gem install ./gitlab_internal_events_cli-0.0.1.gem
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Then run the CLI from the root of a GitLab project:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
gitlab-internal-events-cli
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Alternatively, run directly from the repo without installing the gem:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
bundle exec exe/gitlab-internal-events-cli
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Migration from GitLab Monorepo
|
|
155
|
+
|
|
156
|
+
This gem was extracted from the original CLI at `gitlab/scripts/internal_events/cli.rb`. Key changes:
|
|
157
|
+
|
|
158
|
+
1. **Configuration System**: All hardcoded paths are now configurable
|
|
159
|
+
2. **Standalone Gem**: Can be used outside the GitLab monorepo with proper configuration
|
|
160
|
+
3. **Module Renamed**: `InternalEventsCli` → `GitlabInternalEventsCli`
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
The gem is available as open source under the terms of the [MIT License](LICENSE.txt).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/gitlab_internal_events_cli/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'gitlab_internal_events_cli'
|
|
7
|
+
spec.version = GitlabInternalEventsCli::VERSION
|
|
8
|
+
spec.authors = ['GitLab']
|
|
9
|
+
spec.email = ['gitlab@gitlab.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'GitLab CLI tool for defining internal events and metrics'
|
|
12
|
+
spec.description = 'An interactive CLI tool for creating event and metric definition files ' \
|
|
13
|
+
"for GitLab's internal analytics system."
|
|
14
|
+
spec.homepage = 'https://gitlab.com/gitlab-org/analytics-section/product-analytics/analytics-cli'
|
|
15
|
+
spec.license = 'MIT'
|
|
16
|
+
spec.required_ruby_version = '>= 3.0.0'
|
|
17
|
+
|
|
18
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
19
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
|
20
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
21
|
+
|
|
22
|
+
spec.files = Dir.chdir(__dir__) do
|
|
23
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
24
|
+
(File.expand_path(f) == __FILE__) ||
|
|
25
|
+
f.start_with?(*%w[bin/ test/ spec/ features/ .git .gitlab-ci.yml .rubocop])
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
spec.bindir = 'exe'
|
|
29
|
+
spec.executables = ['gitlab-internal-events-cli']
|
|
30
|
+
spec.require_paths = ['lib']
|
|
31
|
+
|
|
32
|
+
spec.add_dependency 'json_schemer', '~> 2.3.0'
|
|
33
|
+
spec.add_dependency 'pastel', '~> 0.8.0'
|
|
34
|
+
spec.add_dependency 'tty-prompt', '~> 0.23'
|
|
35
|
+
|
|
36
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
37
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
|
38
|
+
spec.add_development_dependency 'rubocop', '~> 1.21'
|
|
39
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GitlabInternalEventsCli
|
|
4
|
+
class Cli
|
|
5
|
+
include Helpers
|
|
6
|
+
|
|
7
|
+
attr_reader :cli
|
|
8
|
+
|
|
9
|
+
def initialize(cli)
|
|
10
|
+
@cli = cli
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def run
|
|
14
|
+
HttpCache.preload!
|
|
15
|
+
|
|
16
|
+
cli.say feedback_notice
|
|
17
|
+
cli.say instructions
|
|
18
|
+
|
|
19
|
+
task = cli.select('What would you like to do?', **select_opts) do |menu|
|
|
20
|
+
menu.enum '.'
|
|
21
|
+
|
|
22
|
+
menu.choice "New Event -- track when a specific scenario occurs on gitlab instances\n " \
|
|
23
|
+
'ex) a user applies a label to an issue', :new_event
|
|
24
|
+
menu.choice "New Metric -- track the count of existing events over time\n " \
|
|
25
|
+
'ex) count unique users who assign labels to issues per month', :new_metric
|
|
26
|
+
menu.choice 'View Usage -- look at code and testing examples for existing events & metrics', :view_usage
|
|
27
|
+
menu.choice '...am I in the right place?', :help_decide
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
case task
|
|
31
|
+
when :new_event
|
|
32
|
+
Flows::EventDefiner.new(cli).run
|
|
33
|
+
when :new_metric
|
|
34
|
+
Flows::MetricDefiner.new(cli).run
|
|
35
|
+
when :view_usage
|
|
36
|
+
Flows::UsageViewer.new(cli).run
|
|
37
|
+
when :help_decide
|
|
38
|
+
Flows::FlowAdvisor.new(cli).run
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def instructions
|
|
43
|
+
cli.say <<~TEXT.freeze
|
|
44
|
+
#{format_info('INSTRUCTIONS:')}
|
|
45
|
+
To start tracking usage of a feature...
|
|
46
|
+
|
|
47
|
+
1) Define event (using CLI)
|
|
48
|
+
2) Trigger event (from code)
|
|
49
|
+
3) Define metric (using CLI)
|
|
50
|
+
4) View data in Tableau (after merge & deploy)
|
|
51
|
+
|
|
52
|
+
This CLI will help you create the correct definition files, then provide code examples for instrumentation and testing.
|
|
53
|
+
|
|
54
|
+
Learn more: https://docs.gitlab.com/ee/development/internal_analytics/#fundamental-concepts
|
|
55
|
+
|
|
56
|
+
TEXT
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'json'
|
|
5
|
+
require 'yaml'
|
|
6
|
+
require 'timeout'
|
|
7
|
+
|
|
8
|
+
module GitlabInternalEventsCli
|
|
9
|
+
class Configuration
|
|
10
|
+
DEFAULT_STAGES_URL = 'https://gitlab.com/gitlab-com/www-gitlab-com/-/raw/master/data/stages.yml'
|
|
11
|
+
DEFAULT_EVENT_SCHEMA_URL = 'https://gitlab.com/gitlab-org/gitlab/-/raw/master/config/events/schema.json'
|
|
12
|
+
DEFAULT_METRIC_SCHEMA_URL = 'https://gitlab.com/gitlab-org/gitlab/-/raw/master/config/metrics/schema/base.json'
|
|
13
|
+
DEFAULT_FEATURE_CATEGORIES_URL = 'https://gitlab.com/gitlab-org/gitlab/-/raw/master/config/feature_categories.yml'
|
|
14
|
+
DEFAULT_VERSION_URL = 'https://gitlab.com/gitlab-org/gitlab/-/raw/master/VERSION'
|
|
15
|
+
|
|
16
|
+
attr_accessor :project_root,
|
|
17
|
+
:event_paths,
|
|
18
|
+
:metric_paths,
|
|
19
|
+
:feature_categories_path,
|
|
20
|
+
:feature_categories_url,
|
|
21
|
+
:event_schema_url,
|
|
22
|
+
:metric_schema_url,
|
|
23
|
+
:stages_url
|
|
24
|
+
attr_writer :milestone
|
|
25
|
+
|
|
26
|
+
def initialize
|
|
27
|
+
@project_root = Dir.pwd
|
|
28
|
+
@event_paths = [
|
|
29
|
+
'config/events/*.yml',
|
|
30
|
+
'ee/config/events/*.yml'
|
|
31
|
+
]
|
|
32
|
+
@metric_paths = [
|
|
33
|
+
'config/metrics/counts_all/*.yml',
|
|
34
|
+
'config/metrics/counts_7d/*.yml',
|
|
35
|
+
'config/metrics/counts_28d/*.yml',
|
|
36
|
+
'ee/config/metrics/counts_all/*.yml',
|
|
37
|
+
'ee/config/metrics/counts_7d/*.yml',
|
|
38
|
+
'ee/config/metrics/counts_28d/*.yml'
|
|
39
|
+
]
|
|
40
|
+
@feature_categories_path = 'config/feature_categories.yml'
|
|
41
|
+
@feature_categories_url = DEFAULT_FEATURE_CATEGORIES_URL
|
|
42
|
+
@event_schema_url = DEFAULT_EVENT_SCHEMA_URL
|
|
43
|
+
@metric_schema_url = DEFAULT_METRIC_SCHEMA_URL
|
|
44
|
+
@stages_url = DEFAULT_STAGES_URL
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def milestone
|
|
48
|
+
@milestone ||= milestone_from_version_file || milestone_from_remote || 'TODO'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def resolve_event_paths
|
|
52
|
+
event_paths.flat_map { |pattern| Dir[File.join(project_root, pattern)] }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def resolve_metric_paths
|
|
56
|
+
metric_paths.flat_map { |pattern| Dir[File.join(project_root, pattern)] }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def absolute_path(relative_path)
|
|
60
|
+
File.join(project_root, relative_path)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def load_from_file(config_path = nil)
|
|
64
|
+
config_path ||= File.join(project_root, '.gitlab_internal_events_cli.yml')
|
|
65
|
+
return unless File.exist?(config_path)
|
|
66
|
+
|
|
67
|
+
config = YAML.safe_load_file(config_path, symbolize_names: true)
|
|
68
|
+
apply_config(config)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def apply_config(config)
|
|
74
|
+
config.each do |key, value|
|
|
75
|
+
setter = "#{key}="
|
|
76
|
+
send(setter, value) if respond_to?(setter)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def milestone_from_version_file
|
|
81
|
+
version_file = File.join(project_root, 'VERSION')
|
|
82
|
+
return unless File.exist?(version_file)
|
|
83
|
+
|
|
84
|
+
extract_milestone(File.read(version_file))
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def milestone_from_remote
|
|
88
|
+
content = HttpCache.get(DEFAULT_VERSION_URL)
|
|
89
|
+
return unless content
|
|
90
|
+
|
|
91
|
+
extract_milestone(content)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def extract_milestone(content)
|
|
95
|
+
match = content.strip.match(/(\d+\.\d+)/)
|
|
96
|
+
match&.captures&.first
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
class << self
|
|
101
|
+
attr_writer :configuration
|
|
102
|
+
|
|
103
|
+
def configuration
|
|
104
|
+
@configuration ||= Configuration.new
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def configure
|
|
108
|
+
yield(configuration)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def reset_configuration!
|
|
112
|
+
@configuration = Configuration.new
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GitlabInternalEventsCli
|
|
4
|
+
NEW_EVENT_FIELDS = %i[
|
|
5
|
+
description
|
|
6
|
+
internal_events
|
|
7
|
+
status
|
|
8
|
+
category
|
|
9
|
+
action
|
|
10
|
+
value_type
|
|
11
|
+
extra_properties
|
|
12
|
+
identifiers
|
|
13
|
+
additional_properties
|
|
14
|
+
product_group
|
|
15
|
+
product_categories
|
|
16
|
+
milestone
|
|
17
|
+
introduced_by_url
|
|
18
|
+
tiers
|
|
19
|
+
classification
|
|
20
|
+
].freeze
|
|
21
|
+
|
|
22
|
+
EVENT_DEFAULTS = {
|
|
23
|
+
internal_events: true,
|
|
24
|
+
status: 'active',
|
|
25
|
+
product_group: nil,
|
|
26
|
+
introduced_by_url: 'TODO'
|
|
27
|
+
}.freeze
|
|
28
|
+
|
|
29
|
+
ExistingEvent = Struct.new(*NEW_EVENT_FIELDS, :file_path, keyword_init: true) do
|
|
30
|
+
def identifiers
|
|
31
|
+
self[:identifiers] || []
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def available_filters
|
|
35
|
+
additional_properties&.keys || []
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
NewEvent = Struct.new(*NEW_EVENT_FIELDS, keyword_init: true) do
|
|
40
|
+
def formatted_output
|
|
41
|
+
EVENT_DEFAULTS
|
|
42
|
+
.merge(to_h.compact)
|
|
43
|
+
.slice(*NEW_EVENT_FIELDS)
|
|
44
|
+
.transform_keys(&:to_s)
|
|
45
|
+
.to_yaml(line_width: 150)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def file_path
|
|
49
|
+
File.join(
|
|
50
|
+
*[
|
|
51
|
+
('ee' unless tiers.include?('free')),
|
|
52
|
+
'config',
|
|
53
|
+
'events',
|
|
54
|
+
"#{action}.yml"
|
|
55
|
+
].compact
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def bulk_assign(key_value_pairs)
|
|
60
|
+
key_value_pairs.each { |key, value| self[key] = value }
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
class Event
|
|
65
|
+
def self.parse(**args)
|
|
66
|
+
ExistingEvent.new(**args)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.new(**args)
|
|
70
|
+
NewEvent.new(**args)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|