analytics_ops 0.1.0

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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +47 -0
  3. data/CODE_OF_CONDUCT.md +10 -0
  4. data/CONTRIBUTING.md +67 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +188 -0
  7. data/SECURITY.md +56 -0
  8. data/docs/api-support-matrix.md +50 -0
  9. data/docs/architecture.md +89 -0
  10. data/docs/authentication.md +86 -0
  11. data/docs/commands.md +112 -0
  12. data/docs/configuration-schema-v1.json +129 -0
  13. data/docs/configuration.md +167 -0
  14. data/docs/google-client-compatibility.md +59 -0
  15. data/docs/plan-format.md +89 -0
  16. data/docs/plan-schema-v1.json +224 -0
  17. data/docs/rails.md +73 -0
  18. data/docs/reports.md +124 -0
  19. data/docs/safety.md +93 -0
  20. data/docs/troubleshooting.md +103 -0
  21. data/exe/analytics-ops +6 -0
  22. data/lib/analytics_ops/applier.rb +52 -0
  23. data/lib/analytics_ops/canonical.rb +65 -0
  24. data/lib/analytics_ops/cli.rb +427 -0
  25. data/lib/analytics_ops/clients/admin.rb +446 -0
  26. data/lib/analytics_ops/clients/data.rb +314 -0
  27. data/lib/analytics_ops/configuration/document.rb +25 -0
  28. data/lib/analytics_ops/configuration/loader.rb +76 -0
  29. data/lib/analytics_ops/configuration/schema.rb +107 -0
  30. data/lib/analytics_ops/configuration/validator.rb +344 -0
  31. data/lib/analytics_ops/configuration.rb +19 -0
  32. data/lib/analytics_ops/desired_state.rb +40 -0
  33. data/lib/analytics_ops/errors.rb +31 -0
  34. data/lib/analytics_ops/plan.rb +551 -0
  35. data/lib/analytics_ops/planner.rb +233 -0
  36. data/lib/analytics_ops/rails/railtie.rb +65 -0
  37. data/lib/analytics_ops/rails.rb +5 -0
  38. data/lib/analytics_ops/redaction.rb +46 -0
  39. data/lib/analytics_ops/reports/catalog.rb +100 -0
  40. data/lib/analytics_ops/reports/definition.rb +226 -0
  41. data/lib/analytics_ops/reports/result.rb +90 -0
  42. data/lib/analytics_ops/reports.rb +13 -0
  43. data/lib/analytics_ops/resources.rb +79 -0
  44. data/lib/analytics_ops/snapshot.rb +45 -0
  45. data/lib/analytics_ops/version.rb +5 -0
  46. data/lib/analytics_ops/workspace.rb +212 -0
  47. data/lib/analytics_ops.rb +21 -0
  48. data/lib/generators/analytics_ops/install_generator.rb +23 -0
  49. data/lib/generators/analytics_ops/templates/analytics-ops +9 -0
  50. data/lib/generators/analytics_ops/templates/analytics_ops.yml +23 -0
  51. data/sig/analytics_ops.rbs +395 -0
  52. metadata +131 -0
@@ -0,0 +1,395 @@
1
+ module AnalyticsOps
2
+ VERSION: String
3
+
4
+ type record = Hash[String, untyped]
5
+
6
+ class Error < StandardError
7
+ end
8
+
9
+ class ConfigurationError < Error
10
+ end
11
+
12
+ class EnvironmentVariableError < ConfigurationError
13
+ end
14
+
15
+ class UnsupportedVersionError < ConfigurationError
16
+ end
17
+
18
+ class AuthenticationError < Error
19
+ end
20
+
21
+ class AuthorizationError < Error
22
+ end
23
+
24
+ class UnsupportedCapabilityError < Error
25
+ end
26
+
27
+ class ConflictError < Error
28
+ end
29
+
30
+ class InvalidPlanError < Error
31
+ end
32
+
33
+ class StalePlanError < Error
34
+ end
35
+
36
+ class ConfirmationRequiredError < Error
37
+ end
38
+
39
+ class QuotaError < Error
40
+ end
41
+
42
+ class TimeoutError < Error
43
+ end
44
+
45
+ class InvalidRequestError < Error
46
+ end
47
+
48
+ class RemoteError < Error
49
+ end
50
+
51
+ class PartialApplyError < Error
52
+ attr_reader result: Applier::Result
53
+
54
+ def initialize: (String message, result: Applier::Result) -> void
55
+ end
56
+
57
+ module Resources
58
+ class Value
59
+ def to_h: () -> record
60
+ def ==: (untyped other) -> bool
61
+ def eql?: (untyped other) -> bool
62
+ def hash: () -> Integer
63
+ end
64
+
65
+ class Account < Value
66
+ attr_reader id: String
67
+ attr_reader name: String
68
+ attr_reader display_name: String
69
+ attr_reader properties: Array[record]
70
+ end
71
+
72
+ class Property < Value
73
+ attr_reader id: String
74
+ attr_reader name: String
75
+ attr_reader display_name: String
76
+ attr_reader parent: String?
77
+ attr_reader property_type: String
78
+ attr_reader can_edit: bool?
79
+ end
80
+
81
+ class DataStream < Value
82
+ attr_reader id: String
83
+ attr_reader name: String
84
+ attr_reader display_name: String
85
+ attr_reader type: String
86
+ attr_reader default_uri: String?
87
+ attr_reader measurement_id: String?
88
+ end
89
+
90
+ class Retention < Value
91
+ attr_reader name: String
92
+ attr_reader event_data: String
93
+ attr_reader user_data: String
94
+ attr_reader reset_on_new_activity: bool
95
+ end
96
+
97
+ class KeyEvent < Value
98
+ attr_reader name: String
99
+ attr_reader event_name: String
100
+ attr_reader counting_method: String
101
+ end
102
+
103
+ class CustomDimension < Value
104
+ attr_reader name: String
105
+ attr_reader parameter_name: String
106
+ attr_reader display_name: String
107
+ attr_reader description: String
108
+ attr_reader scope: String
109
+ attr_reader disallow_ads_personalization: bool
110
+ end
111
+
112
+ class CustomMetric < Value
113
+ attr_reader name: String
114
+ attr_reader parameter_name: String
115
+ attr_reader display_name: String
116
+ attr_reader description: String
117
+ attr_reader scope: String
118
+ attr_reader measurement_unit: String
119
+ end
120
+ end
121
+
122
+ module Configuration
123
+ SCHEMA: record
124
+
125
+ def self.load: (String path, ?environment: Hash[String, String]) -> Document
126
+
127
+ class Document
128
+ attr_reader version: Integer
129
+ attr_reader profiles: Hash[String, DesiredState]
130
+
131
+ def initialize: (version: Integer, profiles: Hash[String, DesiredState]) -> void
132
+ def profile: (String | Symbol name) -> DesiredState
133
+ end
134
+ end
135
+
136
+ class DesiredState
137
+ attr_reader profile: String
138
+ attr_reader property_id: String
139
+ attr_reader streams: Array[record]
140
+ attr_reader retention: record?
141
+ attr_reader key_events: Array[String]
142
+ attr_reader custom_dimensions: Array[record]
143
+ attr_reader custom_metrics: Array[record]
144
+ attr_reader manual_requirements: Array[String]
145
+ attr_reader google_signals: record?
146
+
147
+ def initialize: (
148
+ profile: String,
149
+ property_id: String,
150
+ streams: Array[record],
151
+ retention: record?,
152
+ key_events: Array[String],
153
+ custom_dimensions: Array[record],
154
+ custom_metrics: Array[record],
155
+ manual_requirements: Array[String],
156
+ google_signals: record?
157
+ ) -> void
158
+ def to_h: () -> record
159
+ end
160
+
161
+ class Snapshot
162
+ attr_reader property: Resources::Property
163
+ attr_reader streams: Array[Resources::DataStream]
164
+ attr_reader retention: Resources::Retention?
165
+ attr_reader key_events: Array[Resources::KeyEvent]
166
+ attr_reader custom_dimensions: Array[Resources::CustomDimension]
167
+ attr_reader custom_metrics: Array[Resources::CustomMetric]
168
+
169
+ def initialize: (
170
+ property: Resources::Property,
171
+ streams: Array[Resources::DataStream],
172
+ retention: Resources::Retention?,
173
+ key_events: Array[Resources::KeyEvent],
174
+ custom_dimensions: Array[Resources::CustomDimension],
175
+ custom_metrics: Array[Resources::CustomMetric]
176
+ ) -> void
177
+ def property_id: () -> String
178
+ def to_h: () -> record
179
+ def fingerprint: () -> String
180
+ end
181
+
182
+ class Plan
183
+ FORMAT_VERSION: Integer
184
+
185
+ class Change < Resources::Value
186
+ attr_reader resource_type: String
187
+ attr_reader resource_identity: String
188
+ attr_reader operation: String
189
+ attr_reader api_maturity: String
190
+ attr_reader before: record?
191
+ attr_reader after: record
192
+ attr_reader reversible: bool
193
+ attr_reader rollback: String
194
+
195
+ def self.from_h: (record raw) -> Change
196
+ end
197
+
198
+ class Finding < Resources::Value
199
+ attr_reader severity: String
200
+ attr_reader code: String
201
+ attr_reader resource_identity: String
202
+ attr_reader message: String
203
+
204
+ def self.from_h: (record raw) -> Finding
205
+ end
206
+
207
+ attr_reader format_version: Integer
208
+ attr_reader profile: String
209
+ attr_reader property_id: String
210
+ attr_reader snapshot_fingerprint: String
211
+ attr_reader changes: Array[Change]
212
+ attr_reader findings: Array[Finding]
213
+
214
+ def initialize: (
215
+ profile: String,
216
+ property_id: String,
217
+ snapshot_fingerprint: String,
218
+ changes: Array[Change],
219
+ findings: Array[Finding],
220
+ ?format_version: Integer
221
+ ) -> void
222
+ def self.load: (String path) -> Plan
223
+ def self.from_h: (record raw) -> Plan
224
+ def empty?: () -> bool
225
+ def drift?: () -> bool
226
+ def to_h: () -> record
227
+ def to_json: (*untyped arguments) -> String
228
+ def write: (String path) -> String
229
+ end
230
+
231
+ class Planner
232
+ def initialize: (desired_state: DesiredState, snapshot: Snapshot) -> void
233
+ def call: () -> Plan
234
+ end
235
+
236
+ class Applier
237
+ class Result < Resources::Value
238
+ attr_reader status: String
239
+ attr_reader applied: Array[record]
240
+ attr_reader failed: record?
241
+ attr_reader remaining: Array[record]
242
+ end
243
+
244
+ def initialize: (admin: Clients::Admin) -> void
245
+ def call: (Plan plan, ?confirm: bool) -> Result
246
+ end
247
+
248
+ module Reports
249
+ class Definition
250
+ attr_reader name: String
251
+ attr_reader kind: String
252
+ attr_reader dimensions: Array[String]
253
+ attr_reader metrics: Array[String]
254
+ attr_reader date_ranges: Array[record]
255
+ attr_reader dimension_filter: record?
256
+ attr_reader metric_filter: record?
257
+ attr_reader order_bys: Array[record]
258
+ attr_reader offset: Integer
259
+ attr_reader limit: Integer
260
+
261
+ def initialize: (
262
+ name: String,
263
+ kind: String,
264
+ dimensions: Array[String],
265
+ metrics: Array[String],
266
+ ?date_ranges: Array[record],
267
+ ?dimension_filter: record?,
268
+ ?metric_filter: record?,
269
+ ?order_bys: Array[record],
270
+ ?offset: Integer,
271
+ ?limit: Integer
272
+ ) -> void
273
+ def realtime?: () -> bool
274
+ def to_h: () -> record
275
+ end
276
+
277
+ module Catalog
278
+ def self.fetch: (String | Symbol name, ?kind: String?) -> Definition
279
+ def self.names: () -> Array[String]
280
+ end
281
+
282
+ class Result
283
+ attr_reader name: String
284
+ attr_reader kind: String
285
+ attr_reader dimension_headers: Array[String]
286
+ attr_reader metric_headers: Array[String]
287
+ attr_reader rows: Array[record]
288
+ attr_reader row_count: Integer
289
+ attr_reader metadata: record
290
+
291
+ def initialize: (
292
+ name: String,
293
+ kind: String,
294
+ dimension_headers: Array[String],
295
+ metric_headers: Array[String],
296
+ rows: Array[record],
297
+ row_count: Integer,
298
+ metadata: record
299
+ ) -> void
300
+ def headers: () -> Array[String]
301
+ def to_h: () -> record
302
+ end
303
+ end
304
+
305
+ module Clients
306
+ class Admin
307
+ def initialize: (
308
+ ?client: untyped,
309
+ ?credentials: untyped,
310
+ ?transport: Symbol,
311
+ ?timeout: Float?,
312
+ ?logger: untyped
313
+ ) -> void
314
+ def discover: () -> Array[Resources::Account]
315
+ def property_access: (String property_id) -> Resources::Property
316
+ def snapshot: (String property_id) -> Snapshot
317
+ def capabilities: () -> Hash[String, bool]
318
+ def compatibility: () -> record
319
+ def apply_change: (Plan::Change change, property_id: String) -> Plan::Change
320
+ end
321
+
322
+ class Data
323
+ def initialize: (
324
+ ?client: untyped,
325
+ ?credentials: untyped,
326
+ ?transport: Symbol,
327
+ ?timeout: Float?,
328
+ ?logger: untyped
329
+ ) -> void
330
+ def run: (String property_id, Reports::Definition definition) -> Reports::Result
331
+ def available?: () -> bool
332
+ def compatibility: () -> record
333
+ end
334
+ end
335
+
336
+ class Workspace
337
+ class Verification
338
+ attr_reader converged: bool
339
+ attr_reader plan: Plan
340
+
341
+ def initialize: (plan: Plan) -> void
342
+ def to_h: () -> record
343
+ end
344
+
345
+ class DoctorResult
346
+ attr_reader checks: Array[record]
347
+
348
+ def initialize: (checks: Array[record]) -> void
349
+ def success?: () -> bool
350
+ def to_h: () -> record
351
+ end
352
+
353
+ attr_reader desired_state: DesiredState
354
+
355
+ def self.load: (
356
+ String path,
357
+ profile: String,
358
+ ?environment: Hash[String, String],
359
+ ?admin: Clients::Admin?,
360
+ ?data: Clients::Data?,
361
+ ?credentials: untyped,
362
+ ?transport: Symbol,
363
+ ?timeout: Float?,
364
+ ?logger: untyped
365
+ ) -> Workspace
366
+ def initialize: (
367
+ desired_state: DesiredState,
368
+ ?admin: Clients::Admin?,
369
+ ?data: Clients::Data?,
370
+ ?credentials: untyped,
371
+ ?transport: Symbol,
372
+ ?timeout: Float?,
373
+ ?logger: untyped
374
+ ) -> void
375
+ def discover: () -> Array[Resources::Account]
376
+ def snapshot: () -> Snapshot
377
+ def audit: () -> Plan
378
+ def plan: () -> Plan
379
+ def apply: (Plan | String plan_or_path, ?confirm: bool) -> Applier::Result
380
+ def verify: () -> Verification
381
+ def report: (String | Reports::Definition name_or_definition) -> Reports::Result
382
+ def realtime: (?String | Reports::Definition name_or_definition) -> Reports::Result
383
+ def doctor: () -> DoctorResult
384
+ end
385
+
386
+ class CLI
387
+ def self.start: (
388
+ Array[String] arguments,
389
+ ?out: untyped,
390
+ ?err: untyped,
391
+ ?input: untyped,
392
+ ?workspace_loader: untyped
393
+ ) -> Integer
394
+ end
395
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: analytics_ops
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nelson Chaves
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: google-analytics-admin
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: 0.8.0
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: 0.8.0
26
+ - !ruby/object:Gem::Dependency
27
+ name: google-analytics-data
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: 0.9.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.9.0
40
+ description: |-
41
+ Analytics Ops provides configuration-as-code, drift detection, explicit
42
+ plans, safe application, and reporting for Google Analytics 4 properties.
43
+ Its plain-Ruby core uses Google's official API clients, with optional Rails
44
+ integration and no network access during application boot.
45
+ email:
46
+ - nelsonchavespro@gmail.com
47
+ executables:
48
+ - analytics-ops
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - CHANGELOG.md
53
+ - CODE_OF_CONDUCT.md
54
+ - CONTRIBUTING.md
55
+ - LICENSE.txt
56
+ - README.md
57
+ - SECURITY.md
58
+ - docs/api-support-matrix.md
59
+ - docs/architecture.md
60
+ - docs/authentication.md
61
+ - docs/commands.md
62
+ - docs/configuration-schema-v1.json
63
+ - docs/configuration.md
64
+ - docs/google-client-compatibility.md
65
+ - docs/plan-format.md
66
+ - docs/plan-schema-v1.json
67
+ - docs/rails.md
68
+ - docs/reports.md
69
+ - docs/safety.md
70
+ - docs/troubleshooting.md
71
+ - exe/analytics-ops
72
+ - lib/analytics_ops.rb
73
+ - lib/analytics_ops/applier.rb
74
+ - lib/analytics_ops/canonical.rb
75
+ - lib/analytics_ops/cli.rb
76
+ - lib/analytics_ops/clients/admin.rb
77
+ - lib/analytics_ops/clients/data.rb
78
+ - lib/analytics_ops/configuration.rb
79
+ - lib/analytics_ops/configuration/document.rb
80
+ - lib/analytics_ops/configuration/loader.rb
81
+ - lib/analytics_ops/configuration/schema.rb
82
+ - lib/analytics_ops/configuration/validator.rb
83
+ - lib/analytics_ops/desired_state.rb
84
+ - lib/analytics_ops/errors.rb
85
+ - lib/analytics_ops/plan.rb
86
+ - lib/analytics_ops/planner.rb
87
+ - lib/analytics_ops/rails.rb
88
+ - lib/analytics_ops/rails/railtie.rb
89
+ - lib/analytics_ops/redaction.rb
90
+ - lib/analytics_ops/reports.rb
91
+ - lib/analytics_ops/reports/catalog.rb
92
+ - lib/analytics_ops/reports/definition.rb
93
+ - lib/analytics_ops/reports/result.rb
94
+ - lib/analytics_ops/resources.rb
95
+ - lib/analytics_ops/snapshot.rb
96
+ - lib/analytics_ops/version.rb
97
+ - lib/analytics_ops/workspace.rb
98
+ - lib/generators/analytics_ops/install_generator.rb
99
+ - lib/generators/analytics_ops/templates/analytics-ops
100
+ - lib/generators/analytics_ops/templates/analytics_ops.yml
101
+ - sig/analytics_ops.rbs
102
+ homepage: https://github.com/nelsonchaves/analytics_ops#readme
103
+ licenses:
104
+ - MIT
105
+ metadata:
106
+ allowed_push_host: https://rubygems.org
107
+ homepage_uri: https://github.com/nelsonchaves/analytics_ops#readme
108
+ source_code_uri: https://github.com/nelsonchaves/analytics_ops
109
+ changelog_uri: https://github.com/nelsonchaves/analytics_ops/blob/master/CHANGELOG.md
110
+ bug_tracker_uri: https://github.com/nelsonchaves/analytics_ops/issues
111
+ documentation_uri: https://github.com/nelsonchaves/analytics_ops/tree/master/docs
112
+ rubygems_mfa_required: 'true'
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: 3.2.0
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubygems_version: 4.0.16
128
+ specification_version: 4
129
+ summary: Manage Google Analytics 4 configuration and reports safely from Ruby and
130
+ Rails.
131
+ test_files: []