# frozen_string_literal: true require "httparty" require "json" require "tty-config" require "cgi" require "gitlab" module Dri TokenNotProvidedError = Class.new(StandardError) class ApiClient # rubocop:disable Metrics/ClassLength API_URL = "https://gitlab.com/api/v4" OPS_API_URL = "https://ops.gitlab.net/api/v4" TESTCASES_PROJECT_ID = "11229385" TRIAGE_PROJECT_ID = "15291320" GITLAB_PROJECT_ID = "278964" FEATURE_FLAG_LOG_PROJECT_ID = "15208716" INFRA_TEAM_PROD_PROJECT_ID = "7444821" def initialize(config, ops = false) @token = config.read.dig("settings", "token") @ops_token = config.read.dig("settings", "ops_token") if @token.nil? || @ops_token.nil? raise TokenNotProvidedError, "Gitlab API client cannot be initialized without both access tokens. " \ "Run dri init again or dri profile --edit" end @ops_instance = ops end # Fetch triaged failures # # @param [String] emoji # @param [String] state # @return [Gitlab::ObjectifiedHash] def fetch_triaged_failures(emoji:, state:) gitlab.issues( GITLAB_PROJECT_ID, order_by: "updated_at", my_reaction_emoji: emoji, scope: "all", state: state ) end # Fetch award emojis # # @param [Integer] issue_iid # @return [Array] def fetch_awarded_emojis(issue_iid) gitlab.award_emojis(GITLAB_PROJECT_ID, issue_iid, "issue") end # Fetch failing testcases # # @param [String] pipeline # @param [String] state # @return [Array] def fetch_failing_testcases(pipeline, state:) gitlab.issues( TESTCASES_PROJECT_ID, labels: "#{pipeline}::failed", state: state, scope: "all", "not[labels]": "quarantine" ).auto_paginate end # Fetch issues related to failing test cases # # @return [Array] def fetch_test_failure_issues(labels: 'failure::new') gitlab.issues( GITLAB_PROJECT_ID, labels: labels, state: 'opened', scope: "all" ).auto_paginate end # Fetch related issue mrs # # @param [Integer] issue_iid # @return [Array] def fetch_related_mrs(issue_iid) gitlab.related_issue_merge_requests(GITLAB_PROJECT_ID, issue_iid) end # Fetch MRs # # @see https://docs.gitlab.com/ee/api/merge_requests.html for all passable options # # @param [Hash] options # @option options [String] state # @option options [String] order_by # @option options [String] sort # @option options [String] milestone # @option options [String] labels def fetch_mrs(project_id:, **options) gitlab.merge_requests(project_id, per_page: 100, **options).auto_paginate end # Fetch current triage issue # # @return [Gitlab::ObjectifiedHash] def fetch_current_triage_issue gitlab.issues(TRIAGE_PROJECT_ID, state: "opened", order_by: "updated_at") end # Create triage report note # # @param [Integer] iid # @param [String] body # @return [Gitlab::ObjectifiedHash] def post_triage_report_note(iid:, body:) gitlab.create_issue_note(TRIAGE_PROJECT_ID, iid, body) end # Fetch new failures # # @param [String] date # @param [String] state # @return [Array] def fetch_failures(date:, state:) gitlab.issues( GITLAB_PROJECT_ID, labels: "failure::new", order_by: "updated_at", state: state, scope: "all", created_after: date, per_page: 100 ) end # Fetch failure notes # # @param [Integer] issue_iid # @return [Array] def fetch_failure_notes(issue_iid) gitlab.issue_notes(GITLAB_PROJECT_ID, issue_iid, per_page: 100).auto_paginate end # Delete award emoji # # @param [Integer] issue_iid # @param [Integer] emoji_id # @return [Gitlab::ObjectifiedHash] def delete_award_emoji(issue_iid, emoji_id) gitlab.delete_award_emoji( GITLAB_PROJECT_ID, issue_iid, "issue", emoji_id ) end # Fetch feature flag log issues # # @param [String] date # @return [Array] def fetch_feature_flag_logs(date) gitlab.issues(FEATURE_FLAG_LOG_PROJECT_ID, created_after: date, per_page: 100).auto_paginate end # Fetch ongoing incidents # # @return [Array] def incidents gitlab.issues(INFRA_TEAM_PROD_PROJECT_ID, order_by: "updated_at", state: "opened", labels: "incident") end # Fetch pipelines # # @param [Integer] project_id # @return [Array] def pipelines(project_id:, options:, auto_paginate: false) if auto_paginate gitlab.pipelines(project_id, options).auto_paginate else gitlab.pipelines(project_id, options) end end # Fetch single pipeline # # @param [Integer] project_id # @param [Integer] pipeline_id # @return [] def pipeline(project_id, pipeline_id) gitlab.pipeline(project_id, pipeline_id) end # Fetch test report from a pipeline # # @param [Integer] project_id # @param [Integer] pipeline_id # @return [] def pipeline_test_report(project_id, pipeline_id) gitlab.pipeline_test_report(project_id, pipeline_id) end # Fetch pipeline bridges/downstream pipelines # # @param [Integer] project_id # @param [Integer] pipeline_id # @return [Array] def pipeline_bridges(project_id, pipeline_id, options = {}) gitlab.pipeline_bridges(project_id, pipeline_id, options).auto_paginate end # Fetch jobs from a pipeline # # @param [Integer] project_id # @param [Integer] pipeline_id # @return [Array] def pipeline_jobs(project_id, pipeline_id, options = {}) gitlab.pipeline_jobs(project_id, pipeline_id, options).auto_paginate end private attr_reader :token, :ops_token # Gitlab client # # @return [Gitlab::Client] def gitlab if @ops_instance @ops_client ||= Gitlab.client( endpoint: OPS_API_URL, private_token: ops_token ) else @gitlab_client ||= Gitlab.client( endpoint: API_URL, private_token: token ) end end end end