dri 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: fb31c263acfb2d576ed72028d207df2d36d76b1965ac00aa5228fbdd991a7524
4
+ data.tar.gz: 179c9389a9b3ce00a9f4ff357da3d1f4fdf3af9b22ec96a8d582dfb7d35bf17a
5
+ SHA512:
6
+ metadata.gz: d38a554fad6c98a72992c2d5c97eae39f6ecebce78ff466174f20074a4aa74b436ee6fcff6192ad4800515056fd9e53ec049a5aa1f6dfa90fdcafa2489376256
7
+ data.tar.gz: 2f2994a17800bd2d1fbf02ed9724e9b0428e4ded12ae9516135d19a6b529982d3e36d2148e6ef9df4f6bc740355555831ed035b440d30d89f94fdf814e3a1a99
data/.editorconfig ADDED
@@ -0,0 +1,9 @@
1
+ root = true
2
+
3
+ [*.rb]
4
+ charset = utf-8
5
+ end_of_line = lf
6
+ insert_final_newline = true
7
+ indent_style = space
8
+ indent_size = 2
9
+ trim_trailing_whitespace = true
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+
13
+ .dri_profile.yml
14
+ handover_reports/*
data/.gitlab-ci.yml ADDED
@@ -0,0 +1,28 @@
1
+ image: ruby:3.0.2
2
+
3
+ stages:
4
+ - build
5
+ - test
6
+ - deploy
7
+
8
+ before_script:
9
+ - gem install bundler:2.2.22
10
+ - bundle install
11
+
12
+ build_gem:
13
+ stage: build
14
+ script:
15
+ - gem build
16
+
17
+ rspec:
18
+ stage: test
19
+ script:
20
+ - bundle exec rspec
21
+
22
+ deploy:
23
+ stage: deploy
24
+ script:
25
+ - gem push dri*.gem
26
+ rules:
27
+ - if: '$CI_COMMIT_TAG'
28
+ when: always
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in dri.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 12.0"
7
+ gem "rspec", "~> 3.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,107 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ dri (0.1.0)
5
+ httparty (~> 0.20.0)
6
+ json (~> 2.6.1)
7
+ markdown-tables (~> 1.1.1)
8
+ pastel (~> 0.8.0)
9
+ thor (~> 1.0.1)
10
+ tty-box (~> 0.7.0)
11
+ tty-config (~> 0.4.0)
12
+ tty-editor (~> 0.6)
13
+ tty-font (~> 0.5)
14
+ tty-logger (~> 0.6.0)
15
+ tty-prompt (~> 0.23.1)
16
+ tty-spinner (~> 0.9)
17
+ tty-table (~> 0.12.0)
18
+
19
+ GEM
20
+ remote: https://rubygems.org/
21
+ specs:
22
+ addressable (2.8.0)
23
+ public_suffix (>= 2.0.2, < 5.0)
24
+ crack (0.4.5)
25
+ rexml
26
+ diff-lcs (1.5.0)
27
+ hashdiff (1.0.1)
28
+ httparty (0.20.0)
29
+ mime-types (~> 3.0)
30
+ multi_xml (>= 0.5.2)
31
+ json (2.6.1)
32
+ markdown-tables (1.1.1)
33
+ mime-types (3.4.1)
34
+ mime-types-data (~> 3.2015)
35
+ mime-types-data (3.2022.0105)
36
+ multi_xml (0.6.0)
37
+ pastel (0.8.0)
38
+ tty-color (~> 0.5)
39
+ public_suffix (4.0.6)
40
+ rake (12.3.3)
41
+ rexml (3.2.5)
42
+ rspec (3.11.0)
43
+ rspec-core (~> 3.11.0)
44
+ rspec-expectations (~> 3.11.0)
45
+ rspec-mocks (~> 3.11.0)
46
+ rspec-core (3.11.0)
47
+ rspec-support (~> 3.11.0)
48
+ rspec-expectations (3.11.0)
49
+ diff-lcs (>= 1.2.0, < 2.0)
50
+ rspec-support (~> 3.11.0)
51
+ rspec-mocks (3.11.0)
52
+ diff-lcs (>= 1.2.0, < 2.0)
53
+ rspec-support (~> 3.11.0)
54
+ rspec-support (3.11.0)
55
+ strings (0.2.1)
56
+ strings-ansi (~> 0.2)
57
+ unicode-display_width (>= 1.5, < 3.0)
58
+ unicode_utils (~> 1.4)
59
+ strings-ansi (0.2.0)
60
+ thor (1.0.1)
61
+ timecop (0.9.5)
62
+ tty-box (0.7.0)
63
+ pastel (~> 0.8)
64
+ strings (~> 0.2.0)
65
+ tty-cursor (~> 0.7)
66
+ tty-color (0.6.0)
67
+ tty-config (0.4.0)
68
+ tty-cursor (0.7.1)
69
+ tty-editor (0.7.0)
70
+ tty-prompt (~> 0.22)
71
+ tty-font (0.5.0)
72
+ tty-logger (0.6.0)
73
+ pastel (~> 0.8)
74
+ tty-prompt (0.23.1)
75
+ pastel (~> 0.8)
76
+ tty-reader (~> 0.8)
77
+ tty-reader (0.9.0)
78
+ tty-cursor (~> 0.7)
79
+ tty-screen (~> 0.8)
80
+ wisper (~> 2.0)
81
+ tty-screen (0.8.1)
82
+ tty-spinner (0.9.3)
83
+ tty-cursor (~> 0.7)
84
+ tty-table (0.12.0)
85
+ pastel (~> 0.8)
86
+ strings (~> 0.2.0)
87
+ tty-screen (~> 0.8)
88
+ unicode-display_width (2.1.0)
89
+ unicode_utils (1.4.0)
90
+ webmock (3.14.0)
91
+ addressable (>= 2.8.0)
92
+ crack (>= 0.3.2)
93
+ hashdiff (>= 0.4.0, < 2.0.0)
94
+ wisper (2.0.1)
95
+
96
+ PLATFORMS
97
+ ruby
98
+
99
+ DEPENDENCIES
100
+ dri!
101
+ rake (~> 12.0)
102
+ rspec (~> 3.0)
103
+ timecop (~> 0.9.1)
104
+ webmock (~> 3.5)
105
+
106
+ BUNDLED WITH
107
+ 2.1.4
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 GitLab, Inc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # DRI
2
+
3
+ So, are you the **D**irectly **R**esponsible **I**ndividual for GitLab's QA pipelines this week? Looking for a gem to help triage and report failing tests? Look no further.
4
+
5
+ Welcome to your new gem! DRI is a CLI ready to help:
6
+
7
+ - Fetching failing test cases by pipeline
8
+ - Reporting at the end of the timezone shift
9
+ - View today's newest and untriaged failures
10
+ - Take actions on failures
11
+
12
+ ... and more.
13
+
14
+ ## Installation
15
+
16
+ To install the `dri` gem:
17
+
18
+ ```shell
19
+ $ gem install dri
20
+ ```
21
+
22
+ And then execute `dri` to see all available options:
23
+
24
+ ```shell
25
+ $ dri
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ### Configuration
31
+
32
+ To use `dri` fully it is necessary to have:
33
+
34
+ - a Personal Access Token
35
+ - a triage emoji
36
+
37
+ The emoji is the [Award/My Reaction](https://docs.gitlab.com/ee/user/award_emojis.html) emoji associated with the failure issues to group all failures triaged on a given day. This emoji is a personal choice. Note that the same emoji should be used only while triaging failures and not associated with other issues out of the scope of triage.
38
+
39
+ To set up your personal profile:
40
+
41
+ ```shell
42
+ $ dri init
43
+ ```
44
+
45
+ To verify the profile is correctly set:
46
+
47
+ ```shell
48
+ $ dri profile
49
+ ```
50
+
51
+ ### Commands
52
+
53
+ - [1. init](#1-init)
54
+ - [2. profile](#2-profile)
55
+ - [3. fetch](#3-fetch)
56
+ - failures
57
+ - testcases
58
+ - [4. publish](#4-publish)
59
+ - report
60
+ - [5. rm](#5-rm)
61
+ - emoji
62
+ - [6. version](#6-version)
63
+
64
+ #### 1. init
65
+
66
+ ```shell
67
+ $ dri init
68
+ ```
69
+
70
+ Initializes the `dri` CLI with necessary configurations to run smoothly.
71
+
72
+ #### 2. profile
73
+
74
+ ```shell
75
+ $ dri profile
76
+ ```
77
+
78
+ Shows the current profile associated after initial configuration.
79
+ Pass the option `--edit` to edit the current profile.
80
+
81
+ #### 3. fetch
82
+
83
+ ```shell
84
+ $ dri fetch failures
85
+ ```
86
+
87
+ Fetches today's opened failures and lists them according to their triage status.
88
+ Helpful to understand if there are missing recent failures to be reviewed.
89
+
90
+ ```shell
91
+ $ dri fetch testcases
92
+ ```
93
+
94
+ Fetches test cases that failing currently and groups them by pipeline.
95
+ To filter the pipelines, pass the `--filter-pipelines` options to multi-select the pipelines you wish to consult.
96
+ (Use `Space` to select an option)
97
+
98
+ #### 4. publish
99
+
100
+ ```shell
101
+ $ dri publish report
102
+ ```
103
+
104
+ Publishes a handover report on the latest triage issue, in the [pipeline-triage](https://gitlab.com/gitlab-org/quality/pipeline-triage) project.
105
+
106
+ **Options**
107
+
108
+ ```shell
109
+ $ dri publish report --format=list # formats the report in a list
110
+ $ dri publish report --format=table # formats the report in a table (default)
111
+ $ dri publish report --dry-run # the report is only generated locally
112
+ ```
113
+
114
+ #### 5. rm
115
+
116
+ ```shell
117
+ $ dri rm emoji
118
+ ```
119
+
120
+ Removes the triage emoji from all triaged issues.
121
+
122
+ #### 6. version
123
+
124
+ ```shell
125
+ $ dri version
126
+ ```
127
+
128
+ `dri` gem version.
129
+
130
+ ## Copyright
131
+
132
+ Copyright (c) 2022 GitLab, Inc. See [MIT License](LICENSE.txt) for further details.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "dri"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/dri.gemspec ADDED
@@ -0,0 +1,41 @@
1
+ require_relative 'lib/dri/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "dri"
5
+ spec.license = "MIT"
6
+ spec.version = Dri::VERSION
7
+ spec.authors = ["GitLab Quality"]
8
+ spec.email = ["quality+dri@gitlab.com"]
9
+
10
+ spec.summary = %q{CLI app to help triage GitLab QA pipelines}
11
+ spec.homepage = 'https://gitlab.com/gitlab-org/quality/dri'
12
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
13
+
14
+ # Specify which files should be added to the gem when it is released.
15
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
16
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
17
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ end
19
+ spec.bindir = "exe"
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_dependency "tty-config", "~> 0.4.0"
24
+ spec.add_dependency "tty-font", "~> 0.5"
25
+ spec.add_dependency "tty-prompt", "~> 0.23.1"
26
+ spec.add_dependency "tty-spinner", "~> 0.9"
27
+ spec.add_dependency "tty-table", "~> 0.12.0"
28
+ spec.add_dependency 'tty-box', '~> 0.7.0'
29
+ spec.add_dependency 'tty-logger', '~> 0.6.0'
30
+ spec.add_dependency "tty-editor", "~> 0.6"
31
+ spec.add_dependency "pastel", "~> 0.8.0"
32
+ spec.add_dependency "thor", "~> 1.0.1"
33
+ spec.add_dependency "markdown-tables", "~> 1.1.1"
34
+ spec.add_dependency 'json', '~> 2.6.1'
35
+ spec.add_dependency 'httparty', '~> 0.20.0'
36
+
37
+ spec.add_development_dependency "rake"
38
+ spec.add_development_dependency 'rspec', '~> 3.10.0'
39
+ spec.add_development_dependency 'webmock', '~> 3.5'
40
+ spec.add_development_dependency "timecop", "~> 0.9.1"
41
+ end
data/exe/dri ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ lib_path = File.expand_path('../lib', __dir__)
5
+ $:.unshift(lib_path) if !$:.include?(lib_path)
6
+ require 'dri/cli'
7
+
8
+ Signal.trap('INT') do
9
+ warn("\n#{caller.join("\n")}: interrupted")
10
+ exit(1)
11
+ end
12
+
13
+ begin
14
+ Dri::CLI.start
15
+ rescue Dri::CLI::Error => err
16
+ puts "ERROR: #{err.message}"
17
+ exit 1
18
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "httparty"
4
+ require "json"
5
+ require "tty-config"
6
+
7
+ module Dri
8
+ class ApiClient
9
+
10
+ API_URL = 'https://gitlab.com/api/v4'
11
+ TESTCASES_PROJECT_ID = '11229385'
12
+ TRIAGE_PROJECT_ID = '34185524'
13
+ GITLAB_PROJECT_ID = '278964'
14
+
15
+ def initialize(config)
16
+ profile = config.read
17
+ @token = profile["settings"]["token"]
18
+ end
19
+
20
+ def header
21
+ @header ||= { 'Content-Type' => 'application/json', "Authorization" => "Bearer #{@token}" }
22
+ end
23
+
24
+ def fetch_triaged_failures(emoji:, state:)
25
+ url = ["#{API_URL}/issues"]
26
+ url << "?order_by=updated_at&my_reaction_emoji=#{emoji}"
27
+ url << "&scope=all&state=#{state}"
28
+
29
+ fetch_json(url.join)
30
+ end
31
+
32
+ def fetch_awarded_emojis(url)
33
+ fetch_json(url)
34
+ end
35
+
36
+ def fetch_failing_testcases(pipeline, state:)
37
+ url = ["#{API_URL}/projects/"]
38
+ url << "#{TESTCASES_PROJECT_ID}/issues?labels=#{pipeline}::failed"
39
+ url << "&state=#{state}&not[labels]=quarantine"
40
+ url << "&scope=all"
41
+
42
+ fetch_json(url.join)
43
+ end
44
+
45
+ def fetch_related_mrs(issue_iid:)
46
+ url = ["#{API_URL}/projects/"]
47
+ url << "#{GITLAB_PROJECT_ID}/issues/"
48
+ url << "#{issue_iid}/related_merge_requests"
49
+
50
+ fetch_json(url.join)
51
+ end
52
+
53
+ def fetch_current_triage_issue
54
+ url = ["#{API_URL}/projects/"]
55
+ url << "#{TRIAGE_PROJECT_ID}/issues?state=opened"
56
+ url << "&order_by=updated_at"
57
+
58
+ fetch_json(url.join)
59
+ end
60
+
61
+ def post_triage_report_note(iid:, body:)
62
+ url = ["#{API_URL}/projects/"]
63
+ url << "#{TRIAGE_PROJECT_ID}/issues/#{iid}/notes"
64
+
65
+ post_json(url.join, body)
66
+ end
67
+
68
+ def fetch_failures(date:, state:)
69
+ url = ["#{API_URL}/issues"]
70
+ url << "?labels=failure::new"
71
+ url << "&order_by=updated_at&state=#{state}"
72
+ url << "&scope=all"
73
+ url << "&created_after=#{date}"
74
+
75
+ fetch_json(url.join)
76
+ end
77
+
78
+ def fetch_failure_notes(issue_iid:)
79
+ url = ["#{API_URL}/projects/"]
80
+ url << "#{GITLAB_PROJECT_ID}/issues/"
81
+ url << "#{issue_iid}/notes?per_page=15"
82
+
83
+ fetch_json(url.join)
84
+ end
85
+
86
+ def delete_award_emoji(url)
87
+ delete_json(url)
88
+ end
89
+
90
+ private
91
+
92
+ def post_json(url, body)
93
+ options = {
94
+ body: { body: body },
95
+ headers: {
96
+ "Authorization" => "Bearer #{@token}"
97
+ }
98
+ }
99
+
100
+ response = HTTParty.post(url, options)
101
+ handle_response(response)
102
+ end
103
+
104
+ def delete_json(url)
105
+ response = HTTParty.delete(url, headers: header)
106
+ handle_response(response)
107
+ end
108
+
109
+ def handle_response(response)
110
+ #puts response.to_json
111
+ response
112
+ end
113
+
114
+ def fetch_json(url)
115
+ response = HTTParty.get(url, headers: header)
116
+
117
+ if response.code != 200
118
+ puts "Response error code \"#{response.code}\" - Unable to sync with GitLab"
119
+ exit 1
120
+ end
121
+
122
+ handle_response(JSON.parse(response.body))
123
+ end
124
+ end
125
+ end
data/lib/dri/cli.rb ADDED
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor'
4
+ require "pastel"
5
+ require "tty-font"
6
+
7
+ module Dri
8
+ # Handle the application command line parsing
9
+ # and the dispatch to various command objects
10
+ #
11
+ # @api public
12
+ class CLI < Thor
13
+ # Error raised by this runner
14
+ Error = Class.new(StandardError)
15
+
16
+ def self.exit_on_failure?
17
+ true
18
+ end
19
+
20
+ def help(*args)
21
+ font = TTY::Font.new(:doom)
22
+ pastel = Pastel.new(enabled: !options[:no_color])
23
+ puts pastel.yellow(font.write("DRI"))
24
+ super
25
+ end
26
+
27
+ class_option :no_color, type: :boolean, default: false,
28
+ desc: "Disable colorization in output"
29
+
30
+ desc 'version', 'dri version'
31
+ def version
32
+ require_relative 'version'
33
+ puts "v#{Dri::VERSION}"
34
+ end
35
+ map %w(--version -v) => :version
36
+
37
+ require_relative 'commands/rm'
38
+ register Dri::Commands::Rm, 'rm', 'rm [SUBCOMMAND]', 'Remove triage-related items'
39
+
40
+ desc 'profile', 'View current user settings'
41
+ method_option :help, aliases: '-h', type: :boolean,
42
+ desc: 'Display usage information'
43
+ method_option :edit, type: :string, banner: "editor",
44
+ desc: "Open the holdings configuration file for " \
45
+ "editing in EDITOR, or the default editor " \
46
+ "if not specified."
47
+ def profile(*)
48
+ if options[:help]
49
+ invoke :help, ['profile']
50
+ else
51
+ require_relative 'commands/profile'
52
+ Dri::Commands::Profile.new(options).execute
53
+ end
54
+ end
55
+
56
+ desc 'init', 'Create a configuration to use dri'
57
+ method_option :help, aliases: '-h', type: :boolean,
58
+ desc: 'Display usage information'
59
+ def init(*)
60
+ if options[:help]
61
+ invoke :help, ['init']
62
+ else
63
+ require_relative 'commands/init'
64
+ Dri::Commands::Init.new(options).execute
65
+ end
66
+ end
67
+
68
+ require_relative 'commands/fetch'
69
+ register Dri::Commands::Fetch, 'fetch', 'fetch [SUBCOMMAND]', 'Fetch failures & testcases'
70
+
71
+ require_relative 'commands/publish'
72
+ register Dri::Commands::Publish, 'publish', 'publish [SUBCOMMAND]', 'Publish report for handover'
73
+ end
74
+ end