superbot-cloud 0.1.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.
data/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # Superbot::Cloud
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/superbot/cloud`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ Superbot cloud is a gem that adds cloud functionality for the superbot
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'superbot-cloud'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install superbot-cloud
22
+
23
+ ## Usage
24
+
25
+ Login to the cloud
26
+
27
+ ```ruby
28
+ superbot cloud login
29
+ ```
30
+
31
+ List your organizations from the cloud
32
+
33
+ ```ruby
34
+ superbot cloud org list
35
+ ```
36
+
37
+ Upload test to the cloud
38
+
39
+ ```ruby
40
+ superbot cloud test upload testfolder
41
+ ```
42
+
43
+ For more commands see `superbot cloud --help`
44
+
45
+ ## Development
46
+
47
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
48
+
49
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
50
+
51
+ ## Contributing
52
+
53
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/superbot-cloud. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
54
+
55
+ ## License
56
+
57
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
58
+
59
+ ## Code of Conduct
60
+
61
+ Everyone interacting in the Superbot::Cloud project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/superbot-cloud/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require 'superbot'
6
+ require "superbot/cloud"
7
+
8
+ # You can add fixtures and/or initialization code here to make experimenting
9
+ # with your gem easier. You can also use a different console, if you like.
10
+
11
+ # (If you use this, don't forget to add pry to your Gemfile!)
12
+ # require "pry"
13
+ # Pry.start
14
+
15
+ require "irb"
16
+ IRB.start(__FILE__)
data/bin/release ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env sh
2
+
3
+ set -e
4
+
5
+ VERSION=$(exe/superbot-cloud version)
6
+ GEM_FILE="superbot-cloud-$VERSION.gem"
7
+
8
+ gem uninstall -a -x superbot-cloud
9
+
10
+ [ -e "$GEM_FILE" ] && rm "$GEM_FILE"
11
+
12
+ gem build superbot-cloud
13
+ gem install superbot-cloud-$VERSION.gem
14
+ VERSION_INSTALLED=$(superbot-cloud version)
15
+
16
+ if [ "$VERSION" != "$VERSION_INSTALLED" ]; then
17
+ echo "!version"
18
+ exit 1
19
+ fi
20
+
21
+ superbot-cloud
22
+
23
+ echo "ok"
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
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # add lib to libpath (only needed when running from the sources)
5
+ require 'pathname'
6
+ lib_path = File.expand_path('../../lib', Pathname.new(__FILE__).realpath)
7
+ $LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
8
+
9
+ STDOUT.sync = true
10
+
11
+ require 'superbot'
12
+ require 'superbot/cloud'
13
+
14
+ Superbot::CLI::CloudCommand.run
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Superbot
4
+ module Cloud
5
+ LOGIN_URI = 'https://superapp-production.herokuapp.com/login/cloud'
6
+ CREDENTIALS_PATH = File.join(Dir.home, '.superbot')
7
+ CREDENTIALS_FILE_PATH = File.join(CREDENTIALS_PATH, 'cloud_token.json')
8
+
9
+ def self.credentials
10
+ return unless File.exist?(CREDENTIALS_FILE_PATH)
11
+
12
+ @credentials ||= JSON.parse(File.read(CREDENTIALS_FILE_PATH), symbolize_names: true)
13
+ end
14
+
15
+ def self.save_credentials(data)
16
+ data.transform_keys!(&:to_sym)
17
+ FileUtils.mkdir_p Superbot::Cloud::CREDENTIALS_PATH
18
+ File.write Superbot::Cloud::CREDENTIALS_FILE_PATH, data.to_json
19
+ "Logged in as #{data[:email]}".tap do |message|
20
+ puts message
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ require_relative "cloud/version"
27
+ require_relative "cloud/api"
28
+ require_relative "cloud/cli"
29
+ require_relative "cloud/web_login"
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http/post/multipart'
4
+
5
+ module Superbot
6
+ module Cloud
7
+ module Api
8
+ BASE_URI = "https://superapp-production.herokuapp.com/api/v1"
9
+ ENDPOINT_MAP = {
10
+ login: { method: :post, endpoint: 'sessions' },
11
+ token: { method: :post, endpoint: 'token' },
12
+ organization_list: { method: :get, endpoint: 'organizations' },
13
+ test_list: { method: :get, endpoint: 'tests' },
14
+ test_upload: { method: :post_multipart, endpoint: 'tests' },
15
+ delete_test: { method: :delete, endpoint: 'tests', required_param: :name }
16
+ }.freeze
17
+
18
+ def self.request(type, params: {})
19
+ method, endpoint, required_param = ENDPOINT_MAP[type].values
20
+ uri = URI.parse([BASE_URI, endpoint, params[required_param]].compact.join('/'))
21
+
22
+ req = Net::HTTP.const_get(
23
+ method.to_s.split('_').map(&:capitalize).join('::')
24
+ ).new(uri, params.compact)
25
+ req.set_form_data(params.compact) unless method == :post_multipart
26
+ if Superbot::Cloud.credentials
27
+ req['Authorization'] = format(
28
+ 'Token token="%<token>s", email="%<email>s"',
29
+ **Superbot::Cloud.credentials.slice(:email, :token)
30
+ )
31
+ end
32
+
33
+ response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
34
+ http.request(req)
35
+ end
36
+ parsed_response = response.class.body_permitted? && JSON.parse(response.body, symbolize_names: true) || {}
37
+ return parsed_response if response.is_a? Net::HTTPSuccess
38
+
39
+ abort parsed_response[:errors]
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "cli/root_command"
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'net/http'
4
+ require 'launchy'
5
+
6
+ module Superbot
7
+ module CLI
8
+ module Cloud
9
+ class LoginCommand < Clamp::Command
10
+ option ['-i', '--interactive'], :flag, 'interactive login from command line'
11
+ option ['-f', '--force'], :flag, 'force override current credentials'
12
+
13
+ def execute
14
+ return proceed_to_login if force? || Superbot::Cloud.credentials.nil?
15
+
16
+ begin
17
+ Superbot::Cloud::Api.request(:token)
18
+ puts "Logged in as #{Superbot::Cloud.credentials[:email]}"
19
+ rescue SystemExit => e
20
+ abort unless e.message == 'Invalid credentials'
21
+ proceed_to_login
22
+ end
23
+ end
24
+
25
+ def proceed_to_login
26
+ interactive? ? console_login : web_login
27
+ end
28
+
29
+ def console_login
30
+ email = (print 'Email: '; $stdin.gets.rstrip)
31
+ password = (print 'Password: '; $stdin.gets.rstrip)
32
+ api_response = Superbot::Cloud::Api.request(:login, params: { email: email, password: password })
33
+ Superbot::Cloud.save_credentials(api_response)
34
+ end
35
+
36
+ def web_login
37
+ Superbot::Cloud::WebLogin.run!
38
+ Launchy.open(cloud_login_uri)
39
+
40
+ puts "Your browser has been opened to visit:"
41
+ puts cloud_login_uri
42
+ puts ""
43
+ puts "Press enter to exit"
44
+ $stdin.gets
45
+ end
46
+
47
+ def cloud_login_uri
48
+ URI.parse(Superbot::Cloud::LOGIN_URI).tap do |uri|
49
+ uri.query = URI.encode_www_form(redirect_uri: 'http://localhost:4567/login')
50
+ end.to_s
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Superbot
4
+ module CLI
5
+ module Cloud
6
+ module Organization
7
+ class ListCommand < Clamp::Command
8
+ include Superbot::Cloud::Validations
9
+
10
+ def execute
11
+ require_login
12
+ list_organizations
13
+ end
14
+
15
+ def list_organizations
16
+ api_response = Superbot::Cloud::Api.request(:organization_list)
17
+ puts(api_response.map { |org| org[:name] })
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'organization/list_command'
4
+
5
+ module Superbot
6
+ module CLI
7
+ module Cloud
8
+ class OrganizationCommand < Clamp::Command
9
+ subcommand ['list'], "List user organizations from the cloud", Cloud::Organization::ListCommand
10
+
11
+ def self.run
12
+ super
13
+ rescue StandardError => exc
14
+ warn exc.message
15
+ warn exc.backtrace.join("\n")
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Superbot
4
+ module CLI
5
+ module Cloud
6
+ module Test
7
+ class DeleteCommand < Clamp::Command
8
+ include Superbot::Cloud::Validations
9
+
10
+ option ["-o", "--org"], "ORGANIZATION", "Organization to search test for deletion", attribute_name: :organization
11
+ parameter "NAME", "the name of the test to delete", required: true
12
+
13
+ def execute
14
+ require_login
15
+ delete_test
16
+ end
17
+
18
+ def delete_test
19
+ Superbot::Cloud::Api.request(:delete_test, params: { name: name, organization_name: organization })
20
+ puts "Tests successfully deleted"
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Superbot
4
+ module CLI
5
+ module Cloud
6
+ module Test
7
+ class ListCommand < Clamp::Command
8
+ include Superbot::Cloud::Validations
9
+
10
+ option ["-o", "--org"], "ORGANIZATION", "Organization to list tests for", attribute_name: :organization
11
+
12
+ def execute
13
+ require_login
14
+ list_tests
15
+ end
16
+
17
+ def list_tests
18
+ api_response = Superbot::Cloud::Api.request(:test_list, params: { organization_name: organization })
19
+ abort api_response[:errors] if api_response[:errors]
20
+ puts "Organization: #{api_response[:organization]}"
21
+ puts "Tests:"
22
+ api_response[:tests].each do |test|
23
+ puts(test[:name], test[:files].map { |f| "- #{f[:filename]}" })
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'fileutils'
4
+ require 'net/http/post/multipart'
5
+ require 'marcel'
6
+ require 'pathname'
7
+
8
+ module Superbot
9
+ module CLI
10
+ module Cloud
11
+ module Test
12
+ class UploadCommand < Clamp::Command
13
+ include Superbot::Validations
14
+ include Superbot::Cloud::Validations
15
+
16
+ parameter "PATH", "the path to folder containing tests to upload" do |path|
17
+ validates_project_path path
18
+ end
19
+
20
+ option ["-o", "--org"], "ORGANIZATION", "Organization to upload tests for", attribute_name: :organization
21
+
22
+ def execute
23
+ require_login
24
+ upload_tests
25
+ end
26
+
27
+ def upload_tests
28
+ Dir.glob(File.join(path, '*.rb')) do |test_file|
29
+ puts "Uploading files from #{path}..."
30
+ filename = File.basename(test_file)
31
+ content_type = Marcel::MimeType.for(Pathname.new(test_file), name: filename)
32
+
33
+ File.open(test_file) do |file|
34
+ api_response = Superbot::Cloud::Api.request(
35
+ :test_upload,
36
+ params: {
37
+ name: Zaru.sanitize!(path),
38
+ organization_name: organization,
39
+ file: UploadIO.new(file, content_type, filename)
40
+ }
41
+ )
42
+
43
+ print filename, ' - ', api_response[:errors] || 'Success'
44
+ puts
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'test/list_command'
4
+ require_relative 'test/upload_command'
5
+ require_relative 'test/delete_command'
6
+
7
+ module Superbot
8
+ module CLI
9
+ module Cloud
10
+ class TestCommand < Clamp::Command
11
+ subcommand ['list'], "List user tests from the cloud", Cloud::Test::ListCommand
12
+ subcommand ['upload'], "Upload test to the cloud", Cloud::Test::UploadCommand
13
+ subcommand ['delete'], "Delete test from the cloud", Cloud::Test::DeleteCommand
14
+
15
+ def self.run
16
+ super
17
+ rescue StandardError => exc
18
+ warn exc.message
19
+ warn exc.backtrace.join("\n")
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end