Module: PactBroker::Client::CLI::WebhookCommands

Included in:
Broker
Defined in:
lib/pact_broker/client/cli/webhook_commands.rb

Class Method Summary collapse

Class Method Details

.included(thor) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/pact_broker/client/cli/webhook_commands.rb', line 8

def self.included(thor)
  thor.class_eval do

    no_commands do
      def self.shared_options_for_webhook_commands
        method_option :request, banner: "METHOD", aliases: "-X", desc: "Webhook HTTP method", required: true
        method_option :header, aliases: "-H", type: :array, desc: "Webhook Header"
        method_option :data, aliases: "-d", desc: "Webhook payload. Provide a JSON string (remember to escape characters appropriately for the shell) or a file path prefixed with the @ symbol, as per the curl usage for this flag."
        method_option :user, aliases: "-u", desc: "Webhook basic auth username and password eg. username:password"
        method_option :consumer, desc: "Consumer name"
        method_option :consumer_label, desc: "Consumer label, mutually exclusive with consumer name"
        method_option :provider, desc: "Provider name"
        method_option :provider_label, desc: "Provider label, mutually exclusive with provider name"
        method_option :description, desc: "Webhook description"
        method_option :contract_content_changed, type: :boolean, desc: "Trigger this webhook when the pact content changes"
        method_option :contract_published, type: :boolean, desc: "Trigger this webhook when a pact is published"
        method_option :provider_verification_published, type: :boolean, desc: "Trigger this webhook when a provider verification result is published"
        method_option :provider_verification_failed, type: :boolean, desc: "Trigger this webhook when a failed provider verification result is published"
        method_option :provider_verification_succeeded, type: :boolean, desc: "Trigger this webhook when a successful provider verification result is published"
        method_option :contract_requiring_verification_published, type: :boolean, desc: "Trigger this webhook when a contract is published that requires verification"
        method_option :team_uuid, banner: "UUID", desc: "UUID of the PactFlow team to which the webhook should be assigned (PactFlow only)"
        shared_authentication_options
      end
    end

    shared_options_for_webhook_commands

    desc 'create-webhook URL', 'Creates a webhook using the same switches as a curl request.'
    long_desc File.read(File.join(File.dirname(__FILE__), 'create_webhook_long_desc.txt'))
    def create_webhook webhook_url
      run_webhook_commands webhook_url
    end

    desc 'create-or-update-webhook URL', 'Creates or updates a webhook with a provided uuid and using the same switches as a curl request.'
    shared_options_for_webhook_commands
    method_option :uuid, type: :string, required: true, desc: "Specify the uuid for the webhook"
    long_desc File.read(File.join(File.dirname(__FILE__), 'create_or_update_webhook_long_desc.txt'))
    def create_or_update_webhook webhook_url
      run_webhook_commands webhook_url
    end

    desc 'test-webhook', 'Test the execution of a webhook'
    method_option :uuid, type: :string, required: true, desc: "Specify the uuid for the webhook"
    shared_authentication_options
    def test_webhook
      require 'pact_broker/client/webhooks/test'
      result = PactBroker::Client::Webhooks::Test.call(options, pact_broker_client_options)
      $stdout.puts result.message
    end

    no_commands do

      def parse_webhook_events
        events = []
        events << 'contract_content_changed' if options.contract_content_changed
        events << 'contract_published' if options.contract_published
        events << 'provider_verification_published' if options.provider_verification_published
        events << 'provider_verification_succeeded' if options.provider_verification_succeeded
        events << 'provider_verification_failed' if options.provider_verification_failed
        events << 'contract_requiring_verification_published' if options.contract_requiring_verification_published
        events
      end

      def parse_webhook_options(webhook_url)
        validate_mutual_exclusiveness_of_participant_name_and_label_options
        events = parse_webhook_events

        # TODO update for contract_requiring_verification_published when released
        if events.size == 0
          raise WebhookCreationError.new("You must specify at least one of --contract-content-changed, --contract-published, --provider-verification-published, --provider-verification-succeeded or --provider-verification-failed")
        end

        username = options.user ? options.user.split(":", 2).first : nil
        password = options.user ? options.user.split(":", 2).last : nil

        headers = (options.header || []).each_with_object({}) { | header, headers | headers[header.split(":", 2).first.strip] = header.split(":", 2).last.strip }

        body = options.data
        if body && body.start_with?("@")
          filepath = body[1..-1]
          begin
            body = File.read(filepath)
          rescue StandardError => e
            raise WebhookCreationError.new("Couldn't read data from file \"#{filepath}\" due to #{e.class} #{e.message}")
          end
        end

        {
          uuid: options.uuid,
          description: options.description,
          http_method: options.request,
          url: webhook_url,
          headers: headers,
          username: username,
          password: password,
          body: body,
          consumer: options.consumer,
          consumer_label: options.consumer_label,
          provider: options.provider,
          provider_label: options.provider_label,
          events: events,
          team_uuid: options.team_uuid
        }
      end

      def run_webhook_commands webhook_url
        require 'pact_broker/client/webhooks/create'

        validate_credentials
        result = PactBroker::Client::Webhooks::Create.call(parse_webhook_options(webhook_url), options.broker_base_url, pact_broker_client_options)
        $stdout.puts result.message
        exit(1) unless result.success
      rescue PactBroker::Client::Error => e
        raise WebhookCreationError, "#{e.class} - #{e.message}"
      end

      def validate_mutual_exclusiveness_of_participant_name_and_label_options
        if options.consumer && options.consumer_label
          raise WebhookCreationError.new("Consumer name (--consumer) and label (--consumer_label) options are mutually exclusive")
        end

        if options.provider && options.provider_label
          raise WebhookCreationError.new("Provider name (--provider) and label (--provider_label) options are mutually exclusive")
        end
      end
    end
  end
end