learn-lab 0.1.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +48 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.rubocop.yml +31 -0
- data/CHANGELOG.md +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +72 -0
- data/Rakefile +13 -0
- data/bin/ci +9 -0
- data/bin/console +14 -0
- data/bin/rspec +29 -0
- data/bin/rubocop +29 -0
- data/bin/setup +17 -0
- data/exe/learn-lab +6 -0
- data/learn-lab.gemspec +39 -0
- data/lib/learn_lab.rb +33 -0
- data/lib/learn_lab/cli.rb +57 -0
- data/lib/learn_lab/configuration.rb +42 -0
- data/lib/learn_lab/errors.rb +7 -0
- data/lib/learn_lab/file_system.rb +67 -0
- data/lib/learn_lab/prompt.rb +24 -0
- data/lib/learn_lab/test/parsers/mocha.rb +41 -0
- data/lib/learn_lab/test/parsers/null.rb +37 -0
- data/lib/learn_lab/test/parsers/rspec.rb +41 -0
- data/lib/learn_lab/test/runner.rb +45 -0
- data/lib/learn_lab/test/strategies/mocha.rb +54 -0
- data/lib/learn_lab/test/strategies/none.rb +22 -0
- data/lib/learn_lab/test/strategies/rspec.rb +44 -0
- data/lib/learn_lab/test/strategy.rb +74 -0
- data/lib/learn_lab/token.rb +30 -0
- data/lib/learn_lab/vcs.rb +24 -0
- data/lib/learn_lab/version.rb +5 -0
- metadata +180 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f02fc168601cfde48fab19367a3a9fcb2fa5a88f0c010e507b4c71329e06ecc2
|
4
|
+
data.tar.gz: d3e0e54341575734de538394c133a1b40952cf33dfb9481065a03d518e6e6650
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fda10060c1877e47e94b7d933b5adff5ea921e564732f93631d13d2c05cd06585034f4915df81573607734d9b043b5872da879baf126210386d17bbf8c101b7b
|
7
|
+
data.tar.gz: 0a8df382daa76d1b2ce64e134c30fec8d833620701783be28fdee2224448b98889a70387cf8605a755a2f6a9832e9fcc8944fdbde8ffe05775c08b1db3611e77
|
@@ -0,0 +1,48 @@
|
|
1
|
+
version: 2.1
|
2
|
+
jobs:
|
3
|
+
build:
|
4
|
+
parallelism: 1
|
5
|
+
docker:
|
6
|
+
- image: circleci/ruby:2.6.5-node-browsers
|
7
|
+
working_directory: ~/repo
|
8
|
+
steps:
|
9
|
+
- checkout
|
10
|
+
- restore_cache:
|
11
|
+
keys:
|
12
|
+
- v1-dependencies-{{ checksum "learn-lab.gemspec" }}
|
13
|
+
- v1-dependencies-
|
14
|
+
- run:
|
15
|
+
name: Install Dependencies
|
16
|
+
command: |
|
17
|
+
./bin/setup circleci
|
18
|
+
- save_cache:
|
19
|
+
paths:
|
20
|
+
- ./vendor/bundle
|
21
|
+
key: v1-dependencies-{{ checksum "learn-lab.gemspec" }}
|
22
|
+
- run:
|
23
|
+
name: Run CI Script
|
24
|
+
command: |
|
25
|
+
./bin/ci
|
26
|
+
- store_test_results:
|
27
|
+
path: /tmp/test-results
|
28
|
+
- store_artifacts:
|
29
|
+
path: /tmp/test-results
|
30
|
+
destination: test-results
|
31
|
+
workflows:
|
32
|
+
build:
|
33
|
+
jobs:
|
34
|
+
- build
|
35
|
+
nightly:
|
36
|
+
triggers:
|
37
|
+
- schedule:
|
38
|
+
cron: "0 0 * * *"
|
39
|
+
filters:
|
40
|
+
branches:
|
41
|
+
only:
|
42
|
+
- master
|
43
|
+
jobs:
|
44
|
+
- build
|
45
|
+
experimental:
|
46
|
+
notify:
|
47
|
+
branches:
|
48
|
+
only: master
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
AllCops:
|
2
|
+
NewCops: enable
|
3
|
+
Exclude:
|
4
|
+
- 'Gemfile'
|
5
|
+
- 'Rakefile'
|
6
|
+
- 'bin/*'
|
7
|
+
- 'spec/fixtures/**/*'
|
8
|
+
- 'tmp/**/*'
|
9
|
+
- 'vendor/bundle/**/*'
|
10
|
+
TargetRubyVersion: 2.5
|
11
|
+
|
12
|
+
Layout/SpaceAroundEqualsInParameterDefault:
|
13
|
+
EnforcedStyle: no_space
|
14
|
+
|
15
|
+
Metrics/BlockLength:
|
16
|
+
ExcludedMethods:
|
17
|
+
- describe
|
18
|
+
- context
|
19
|
+
- it
|
20
|
+
|
21
|
+
Layout/LineLength:
|
22
|
+
Max: 89
|
23
|
+
|
24
|
+
Style/BlockDelimiters:
|
25
|
+
EnforcedStyle: braces_for_chaining
|
26
|
+
|
27
|
+
Style/RaiseArgs:
|
28
|
+
EnforcedStyle: compact
|
29
|
+
|
30
|
+
Style/YodaCondition:
|
31
|
+
EnforcedStyle: require_for_equality_operators_only
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Changelog
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
|
+
|
7
|
+
## [Unreleased]
|
8
|
+
### Added
|
9
|
+
### Changed
|
10
|
+
### Removed
|
11
|
+
### Fixed
|
12
|
+
|
13
|
+
## [0.1.0.rc1]
|
14
|
+
Initial version with support for `config` and `test` commands.
|
15
|
+
|
16
|
+
[Unreleased]: https://github.com/flatiron-labs/learn-lab/compare/v0.1.0.rc1...HEAD
|
17
|
+
[0.1.0]: https://github.com/flatiron-labs/learn-lab/releases/tag/v0.1.0.rc1
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2020 Flatiron School
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Learn Lab
|
2
|
+
|
3
|
+
The command line interface for Flatiron School enterprise.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
To install the gem, run:
|
8
|
+
|
9
|
+
```
|
10
|
+
$ gem install learn-lab
|
11
|
+
```
|
12
|
+
|
13
|
+
then run:
|
14
|
+
|
15
|
+
```
|
16
|
+
$ learn-lab config
|
17
|
+
```
|
18
|
+
|
19
|
+
to configure your settings.
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
From within a lesson directory, run:
|
24
|
+
|
25
|
+
```
|
26
|
+
$ learn-lab [command]
|
27
|
+
```
|
28
|
+
|
29
|
+
To see a list of available commands, run:
|
30
|
+
|
31
|
+
```
|
32
|
+
$ learn-lab help
|
33
|
+
```
|
34
|
+
|
35
|
+
## Development
|
36
|
+
|
37
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
38
|
+
|
39
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
40
|
+
|
41
|
+
This project uses RSpec for tests, and Rubocop for linting code. The default
|
42
|
+
Bundler generated scripts provided for both are in the `bin` folder. CI is
|
43
|
+
done through
|
44
|
+
[CircleCI](https://app.circleci.com/pipelines/github/flatiron-labs/learn-lab). All pushes to any branch will trigger a build that runs specs and lints the code.
|
45
|
+
|
46
|
+
### Cutting a New Release
|
47
|
+
|
48
|
+
Steps for releasing a new version:
|
49
|
+
|
50
|
+
* update the version number in `version.rb`
|
51
|
+
* update the CHANGELOG
|
52
|
+
- create a new release heading with the new version number and date
|
53
|
+
- create an empty [Unreleased] section with empty headings
|
54
|
+
- update links at the bottom to reflect new version
|
55
|
+
* commit the changes with a message like: "Prepping for release x.x.x"
|
56
|
+
* run `bundle exec rake release` -- this will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org)
|
57
|
+
* post a message in the `#engineering-all-staff` Slack channel announcing the new release
|
58
|
+
|
59
|
+
## Contributing
|
60
|
+
|
61
|
+
Bug reports and pull requests are welcome on
|
62
|
+
[GitHub](https://github.com/flatiron-labs/learn-lab/issues). To submit a pull request:
|
63
|
+
|
64
|
+
1. [Fork](https://github.com/flatiron-labs/learn-lab/fork) the repo
|
65
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
66
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
67
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
68
|
+
5. Create a new Pull Request
|
69
|
+
|
70
|
+
## License
|
71
|
+
|
72
|
+
Licensed under the [MIT License](https://github.com/flatiron-labs/learn-lab/blob/master/LICENSE.txt).
|
data/Rakefile
ADDED
data/bin/ci
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "learn_lab"
|
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/rspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rspec' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rspec-core", "rspec")
|
data/bin/rubocop
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rubocop' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rubocop", "rubocop")
|
data/bin/setup
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
set -euo pipefail
|
3
|
+
IFS=$'\n\t'
|
4
|
+
|
5
|
+
if [ "${1-}" = "circleci" ]; then
|
6
|
+
echo "== Installing Bundler =="
|
7
|
+
gem install bundler:2.1.4
|
8
|
+
echo "== Running Bundle Install =="
|
9
|
+
bundle install --jobs=4 --retry=3 --path ./vendor/bundle && bundle clean
|
10
|
+
else
|
11
|
+
echo "== Running Bundle Install =="
|
12
|
+
bundle install
|
13
|
+
fi
|
14
|
+
|
15
|
+
echo "== Running NPM Install for Spec Fixtures =="
|
16
|
+
npm install --prefix spec/fixtures/mocha/mocha-app/
|
17
|
+
npm install --prefix spec/fixtures/mocha/mocha-with-failures/
|
data/exe/learn-lab
ADDED
data/learn-lab.gemspec
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/learn_lab/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'learn-lab'
|
7
|
+
spec.version = LearnLab::VERSION
|
8
|
+
spec.authors = ['Flatiron School']
|
9
|
+
spec.email = ['learn@flatironschool.com']
|
10
|
+
|
11
|
+
spec.summary = 'The command line interface for Flatiron School enterprise.'
|
12
|
+
spec.homepage = 'https://github.com/flatiron-labs/learn-lab'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
|
15
|
+
|
16
|
+
spec.metadata['allowed_push_host'] = 'https://rubygems.org/'
|
17
|
+
spec.metadata['changelog_uri'] = 'https://github.com/flatiron-labs/learn-lab/blob/master/CHANGELOG.md'
|
18
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
19
|
+
spec.metadata['source_code_uri'] = spec.homepage
|
20
|
+
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
24
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
end
|
26
|
+
|
27
|
+
spec.bindir = 'exe'
|
28
|
+
spec.executables = ['learn-lab']
|
29
|
+
spec.require_paths = ['lib']
|
30
|
+
|
31
|
+
spec.add_development_dependency 'aruba', '~> 1.0'
|
32
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
33
|
+
spec.add_development_dependency 'rspec', '~> 3.9'
|
34
|
+
spec.add_development_dependency 'rspec_junit_formatter', '~> 0.4'
|
35
|
+
spec.add_development_dependency 'rubocop', '~> 1.0'
|
36
|
+
|
37
|
+
spec.add_runtime_dependency 'git', '~> 1.7'
|
38
|
+
spec.add_runtime_dependency 'thor', '~> 1.0'
|
39
|
+
end
|
data/lib/learn_lab.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'base64'
|
4
|
+
require 'json'
|
5
|
+
require 'git'
|
6
|
+
require 'thor'
|
7
|
+
require 'yaml'
|
8
|
+
|
9
|
+
require 'learn_lab/configuration'
|
10
|
+
require 'learn_lab/errors'
|
11
|
+
require 'learn_lab/file_system'
|
12
|
+
require 'learn_lab/prompt'
|
13
|
+
require 'learn_lab/test/runner'
|
14
|
+
require 'learn_lab/test/parsers/mocha'
|
15
|
+
require 'learn_lab/test/parsers/null'
|
16
|
+
require 'learn_lab/test/parsers/rspec'
|
17
|
+
require 'learn_lab/test/strategy'
|
18
|
+
require 'learn_lab/test/strategies/mocha'
|
19
|
+
require 'learn_lab/test/strategies/none'
|
20
|
+
require 'learn_lab/test/strategies/rspec'
|
21
|
+
require 'learn_lab/token'
|
22
|
+
require 'learn_lab/vcs'
|
23
|
+
require 'learn_lab/version'
|
24
|
+
|
25
|
+
require 'learn_lab/cli'
|
26
|
+
|
27
|
+
# Top-level module
|
28
|
+
#
|
29
|
+
module LearnLab
|
30
|
+
def self.file_system
|
31
|
+
FileSystem.new
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
# Command-line interface.
|
5
|
+
#
|
6
|
+
class CLI < Thor
|
7
|
+
desc 'test', 'Run tests and get a token'
|
8
|
+
long_desc <<-LONG_DESC
|
9
|
+
`learn-lab test` will run your tests and output a token that can be
|
10
|
+
copy/pasted into Canvas.
|
11
|
+
LONG_DESC
|
12
|
+
# rubocop:disable Metrics/AbcSize
|
13
|
+
# rubocop:disable Metrics/MethodLength
|
14
|
+
def test
|
15
|
+
configuration = Configuration.open
|
16
|
+
unless configuration.valid?
|
17
|
+
puts 'Please run `learn-lab config` first'
|
18
|
+
exit 0
|
19
|
+
end
|
20
|
+
repo = VCS.new(LearnLab.file_system.pwd)
|
21
|
+
results = LearnLab::Test::Runner.new(repo).run
|
22
|
+
exit 0 unless results[:failure_count].zero?
|
23
|
+
token = Token.new(configuration.email, repo.remote_url)
|
24
|
+
puts "Your token is:\n\n"
|
25
|
+
puts chunk(token.encoded, 30)
|
26
|
+
end
|
27
|
+
# rubocop:enable Metrics/AbcSize
|
28
|
+
# rubocop:enable Metrics/MethodLength
|
29
|
+
|
30
|
+
desc 'config', 'Configure gem'
|
31
|
+
long_desc <<-LONG_DESC
|
32
|
+
`learn-lab config` will configure this gem. It will prompt you for any
|
33
|
+
information it needs and save the configuration to a file in your $HOME directory.
|
34
|
+
LONG_DESC
|
35
|
+
def config
|
36
|
+
configuration = Configuration.open
|
37
|
+
email = configuration.email || '<not set>'
|
38
|
+
|
39
|
+
question = "Enter the email you use to log into Canvas\n" \
|
40
|
+
"(your current email is '#{email}'):"
|
41
|
+
|
42
|
+
prompt = Prompt.new
|
43
|
+
|
44
|
+
# TODO: What kind of email validation do we want here?
|
45
|
+
configuration.email = prompt.ask(question) { |value| !value.empty? }
|
46
|
+
|
47
|
+
configuration.save!
|
48
|
+
puts 'Configuration saved!'
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def chunk(string, size)
|
54
|
+
string.scan(/.{1,#{size}}/)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
# Interface for dealing with persisted configuration file in YAML format.
|
5
|
+
#
|
6
|
+
class Configuration
|
7
|
+
attr_reader :path, :fs
|
8
|
+
attr_accessor :email
|
9
|
+
|
10
|
+
def self.open(filename='enterprise.yml', **options)
|
11
|
+
fs = options.fetch(:fs) { LearnLab.file_system }
|
12
|
+
path = fs.join(fs.home, '.flatiron-school', filename)
|
13
|
+
data = fs.read_yaml_file(path)
|
14
|
+
new(path, data)
|
15
|
+
rescue ConfigurationError
|
16
|
+
path = fs.join(fs.home, '.flatiron-school', 'enterprise.yml')
|
17
|
+
new(path, {})
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize(path, data, **options)
|
21
|
+
@path = path
|
22
|
+
@fs = options.fetch(:fs) { LearnLab.file_system }
|
23
|
+
@email = data[:email]
|
24
|
+
end
|
25
|
+
|
26
|
+
def save!
|
27
|
+
directory = fs.dirname(path)
|
28
|
+
fs.mkdir(directory) unless fs.directory?(directory)
|
29
|
+
fs.write_yaml_file(path, payload, mode: 'w')
|
30
|
+
end
|
31
|
+
|
32
|
+
def valid?
|
33
|
+
!email.nil?
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def payload
|
39
|
+
{ 'email' => email }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
# Wraps file system related commands.
|
5
|
+
#
|
6
|
+
class FileSystem
|
7
|
+
def read_file(path)
|
8
|
+
File.read(path)
|
9
|
+
end
|
10
|
+
|
11
|
+
def read_yaml_file(path, fallback: {})
|
12
|
+
data = YAML.load_file(path, fallback: fallback)
|
13
|
+
data.transform_keys(&:to_sym)
|
14
|
+
rescue Errno::ENOENT, Psych::SyntaxError => e
|
15
|
+
raise ConfigurationError.new(e)
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_json_file(path)
|
19
|
+
data = File.exist?(path) ? read_file(path) : '{}'
|
20
|
+
JSON.parse(data, symbolize_names: true)
|
21
|
+
end
|
22
|
+
|
23
|
+
def home
|
24
|
+
Dir.home
|
25
|
+
end
|
26
|
+
|
27
|
+
def pwd
|
28
|
+
FileUtils.pwd
|
29
|
+
end
|
30
|
+
|
31
|
+
def join(*args)
|
32
|
+
File.join(*args)
|
33
|
+
end
|
34
|
+
|
35
|
+
def dirname(path)
|
36
|
+
File.dirname(path)
|
37
|
+
end
|
38
|
+
|
39
|
+
def mkdir(path)
|
40
|
+
FileUtils.mkdir_p(path)
|
41
|
+
end
|
42
|
+
|
43
|
+
def directory?(path)
|
44
|
+
File.directory?(path)
|
45
|
+
end
|
46
|
+
|
47
|
+
def write_yaml_file(path, data, **options)
|
48
|
+
File.write(path, data.to_yaml, **options)
|
49
|
+
end
|
50
|
+
|
51
|
+
def file_exist?(path)
|
52
|
+
File.exist?(path)
|
53
|
+
end
|
54
|
+
|
55
|
+
def dir_exist?(path)
|
56
|
+
Dir.exist?(path)
|
57
|
+
end
|
58
|
+
|
59
|
+
def dir_entries(path)
|
60
|
+
Dir.entries(path)
|
61
|
+
end
|
62
|
+
|
63
|
+
def rm(path)
|
64
|
+
FileUtils.rm(path)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
# Special prompt that keeps asking for input until it is valid.
|
5
|
+
#
|
6
|
+
class Prompt
|
7
|
+
attr_reader :output
|
8
|
+
|
9
|
+
def initialize(output=$stdout)
|
10
|
+
@output = output
|
11
|
+
end
|
12
|
+
|
13
|
+
def ask(question, &block)
|
14
|
+
input_is_valid = false
|
15
|
+
until input_is_valid
|
16
|
+
output.print("\n#{question} > ")
|
17
|
+
answer = $stdin.gets.chomp
|
18
|
+
input_is_valid = block_given? ? block.call(answer) : true
|
19
|
+
end
|
20
|
+
|
21
|
+
answer
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
module Test
|
5
|
+
module Parsers
|
6
|
+
# Parse Mocha test result output
|
7
|
+
#
|
8
|
+
class Mocha
|
9
|
+
attr_reader :output
|
10
|
+
|
11
|
+
def initialize(output)
|
12
|
+
@output = output
|
13
|
+
end
|
14
|
+
|
15
|
+
def framework
|
16
|
+
'mocha'
|
17
|
+
end
|
18
|
+
|
19
|
+
def duration
|
20
|
+
output ? output[:stats][:duration] : 0
|
21
|
+
end
|
22
|
+
|
23
|
+
def example_count
|
24
|
+
output ? output[:stats][:tests] : 1
|
25
|
+
end
|
26
|
+
|
27
|
+
def passing_count
|
28
|
+
output ? output[:stats][:passes] : 0
|
29
|
+
end
|
30
|
+
|
31
|
+
def pending_count
|
32
|
+
output ? output[:stats][:pending] : 0
|
33
|
+
end
|
34
|
+
|
35
|
+
def failure_count
|
36
|
+
output ? output[:stats][:failures] : 1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
module Test
|
5
|
+
module Parsers
|
6
|
+
# Null parser. Used when no test suite has been detected.
|
7
|
+
#
|
8
|
+
class Null
|
9
|
+
attr_reader :output
|
10
|
+
|
11
|
+
def framework
|
12
|
+
'none'
|
13
|
+
end
|
14
|
+
|
15
|
+
def duration
|
16
|
+
0
|
17
|
+
end
|
18
|
+
|
19
|
+
def example_count
|
20
|
+
0
|
21
|
+
end
|
22
|
+
|
23
|
+
def passing_count
|
24
|
+
0
|
25
|
+
end
|
26
|
+
|
27
|
+
def pending_count
|
28
|
+
0
|
29
|
+
end
|
30
|
+
|
31
|
+
def failure_count
|
32
|
+
0
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
module Test
|
5
|
+
module Parsers
|
6
|
+
# Parse RSpec test result output.
|
7
|
+
#
|
8
|
+
class Rspec
|
9
|
+
attr_reader :output
|
10
|
+
|
11
|
+
def initialize(output)
|
12
|
+
@output = output
|
13
|
+
end
|
14
|
+
|
15
|
+
def framework
|
16
|
+
'rspec'
|
17
|
+
end
|
18
|
+
|
19
|
+
def duration
|
20
|
+
output ? output[:summary][:duration] : 0
|
21
|
+
end
|
22
|
+
|
23
|
+
def example_count
|
24
|
+
output ? output[:summary][:example_count] : 1
|
25
|
+
end
|
26
|
+
|
27
|
+
def passing_count
|
28
|
+
example_count - failure_count - pending_count
|
29
|
+
end
|
30
|
+
|
31
|
+
def pending_count
|
32
|
+
output ? output[:summary][:pending_count] : 0
|
33
|
+
end
|
34
|
+
|
35
|
+
def failure_count
|
36
|
+
output ? output[:summary][:failure_count] : 1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
module Test
|
5
|
+
# Runs a test suite. Lifted from the `learn-test` gem without Ironboard
|
6
|
+
# related code.
|
7
|
+
#
|
8
|
+
class Runner
|
9
|
+
attr_reader :repo, :options
|
10
|
+
|
11
|
+
def initialize(repo, options={})
|
12
|
+
@repo = repo
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
strategy.check_dependencies
|
18
|
+
strategy.run
|
19
|
+
results = strategy.results
|
20
|
+
strategy.cleanup unless options.fetch(:keep, false)
|
21
|
+
results
|
22
|
+
end
|
23
|
+
|
24
|
+
def working_directory
|
25
|
+
repo.working_directory
|
26
|
+
end
|
27
|
+
|
28
|
+
def strategy
|
29
|
+
@strategy ||= begin
|
30
|
+
detected = strategies.map { |s| s.new(self) }.detect(&:detect)
|
31
|
+
detected || LearnLab::Test::Strategies::None.new(self)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def strategies
|
38
|
+
[
|
39
|
+
LearnLab::Test::Strategies::Mocha,
|
40
|
+
LearnLab::Test::Strategies::Rspec
|
41
|
+
]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
module Test
|
5
|
+
module Strategies
|
6
|
+
# Test strategy for Mocha.
|
7
|
+
#
|
8
|
+
class Mocha < Strategy
|
9
|
+
def check_dependencies
|
10
|
+
msg = 'Please install NodeJS: https://nodejs.org/en/download'
|
11
|
+
raise MissingDependencyError.new(msg) if `which node`.empty?
|
12
|
+
end
|
13
|
+
|
14
|
+
def detect
|
15
|
+
js_dependency?(:mocha) || js_dependency?(:'learn-browser')
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
command = if js_dependency?(:'learn-browser') || js_test_script?
|
20
|
+
'npm test'
|
21
|
+
else
|
22
|
+
'node_modules/.bin/mocha -R mocha-multi ' \
|
23
|
+
"--reporter-options spec=-,json=#{result_filename}"
|
24
|
+
end
|
25
|
+
system(command)
|
26
|
+
end
|
27
|
+
|
28
|
+
def parser
|
29
|
+
@parser ||= LearnLab::Test::Parsers::Mocha.new(output)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def js_package
|
35
|
+
@js_package ||= begin
|
36
|
+
path = fs.join(runner.working_directory, 'package.json')
|
37
|
+
fs.read_json_file(path)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def js_dependency?(dep)
|
42
|
+
%i[dependencies devDependencies].any? do |key|
|
43
|
+
js_package[key] && js_package[key][dep]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def js_test_script?
|
48
|
+
(js_package[:scripts] && js_package[:scripts][:test] || '') \
|
49
|
+
.include?(result_filename)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
module Test
|
5
|
+
module Strategies
|
6
|
+
# Null strategy object used when no test suite is detected.
|
7
|
+
#
|
8
|
+
class None < Strategy
|
9
|
+
def run
|
10
|
+
out.puts <<~MSG
|
11
|
+
This directory doesn't appear to have any specs in it, so
|
12
|
+
there’s no test to run.
|
13
|
+
MSG
|
14
|
+
end
|
15
|
+
|
16
|
+
def parser
|
17
|
+
@parser ||= LearnLab::Test::Parsers::Null.new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
module Test
|
5
|
+
module Strategies
|
6
|
+
# Test Strategy for RSpec. Mostly lifted from the `learn-test` gem
|
7
|
+
# without Ironboard specific code. Some other refactorings were also
|
8
|
+
# made to improve test coverage and fix Rubocop warnings.
|
9
|
+
#
|
10
|
+
class Rspec < Strategy
|
11
|
+
def detect
|
12
|
+
spec_dir = fs.join(runner.working_directory, 'spec')
|
13
|
+
fs.dir_exist?(spec_dir) && \
|
14
|
+
(fs.dir_entries(spec_dir).include?('spec_helper.rb') || \
|
15
|
+
fs.dir_entries(spec_dir).include?('rails_helper.rb'))
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
command_options = [
|
20
|
+
'--format documentation',
|
21
|
+
'--format j',
|
22
|
+
"--out #{result_filename}"
|
23
|
+
]
|
24
|
+
system("#{bundle_command}rspec #{command_options.join(' ')}")
|
25
|
+
end
|
26
|
+
|
27
|
+
def parser
|
28
|
+
@parser ||= LearnLab::Test::Parsers::Rspec.new(output)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def bundle_command
|
34
|
+
bundler? ? 'bundle exec ' : ''
|
35
|
+
end
|
36
|
+
|
37
|
+
def bundler?
|
38
|
+
fs.file_exist?('Gemfile') && \
|
39
|
+
!!fs.read_file('Gemfile').match(/^\s*gem\s*('|")rspec(-[^'"]+)?('|").*$/)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
module Test
|
5
|
+
# Base class for all test tools. Extracted from the `learn-test` gem with
|
6
|
+
# some modifications (i.e. this doesn't talk to Ironboard).
|
7
|
+
#
|
8
|
+
class Strategy
|
9
|
+
attr_reader :runner, :options, :out, :fs
|
10
|
+
|
11
|
+
def initialize(runner, out=$stdout)
|
12
|
+
@runner = runner
|
13
|
+
@options = runner.options
|
14
|
+
@out = out
|
15
|
+
@fs = LearnLab.file_system
|
16
|
+
end
|
17
|
+
|
18
|
+
def check_dependencies; end
|
19
|
+
|
20
|
+
def run
|
21
|
+
raise NotImplementedError.new(
|
22
|
+
'you must implement how this strategy runs its tests'
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
def parser
|
27
|
+
raise NotImplementedError.new('you must define a parser')
|
28
|
+
end
|
29
|
+
|
30
|
+
# rubocop:disable Metrics/MethodLength
|
31
|
+
def results
|
32
|
+
{
|
33
|
+
repo_name: runner.repo,
|
34
|
+
build: {
|
35
|
+
test_suite: [{
|
36
|
+
framework: parser.framework,
|
37
|
+
formatted_output: output,
|
38
|
+
duration: parser.duration
|
39
|
+
}]
|
40
|
+
},
|
41
|
+
example_count: parser.example_count,
|
42
|
+
passing_count: parser.passing_count,
|
43
|
+
pending_count: parser.pending_count,
|
44
|
+
failure_count: parser.failure_count
|
45
|
+
}
|
46
|
+
end
|
47
|
+
# rubocop:enable Metrics/MethodLength
|
48
|
+
|
49
|
+
def output
|
50
|
+
return unless result_file?
|
51
|
+
|
52
|
+
fs.read_json_file(result_file_path)
|
53
|
+
end
|
54
|
+
|
55
|
+
def cleanup
|
56
|
+
fs.rm(result_file_path) if result_file?
|
57
|
+
end
|
58
|
+
|
59
|
+
def result_filename
|
60
|
+
'.results.json'
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def result_file?
|
66
|
+
fs.file_exist?(result_file_path)
|
67
|
+
end
|
68
|
+
|
69
|
+
def result_file_path
|
70
|
+
fs.join(runner.working_directory, result_filename)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
# Encodable token. Consists of an email, GitHub URL, and timestamp encoded
|
5
|
+
# as a Base64 URL safe string.
|
6
|
+
#
|
7
|
+
class Token
|
8
|
+
attr_reader :email, :url, :timestamp
|
9
|
+
|
10
|
+
def initialize(email, url, timestamp=Time.now.utc)
|
11
|
+
@email = email
|
12
|
+
@url = url
|
13
|
+
@timestamp = timestamp
|
14
|
+
end
|
15
|
+
|
16
|
+
def encoded
|
17
|
+
Base64.urlsafe_encode64(payload.to_json)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def payload
|
23
|
+
{
|
24
|
+
lms_email: email,
|
25
|
+
vcs_url: url,
|
26
|
+
timestamp: timestamp
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LearnLab
|
4
|
+
# Adapter for the Version Control System.
|
5
|
+
#
|
6
|
+
class VCS
|
7
|
+
def initialize(directory, &block)
|
8
|
+
@repo = Git.open(directory)
|
9
|
+
rescue StandardError => e
|
10
|
+
msg = "You don't appear to be in a Learn lesson's directory. Please " \
|
11
|
+
'cd to an appropriate directory and try again.'
|
12
|
+
|
13
|
+
block_given? ? block.call(msg, e) : raise(LearnLab::Error.new(msg))
|
14
|
+
end
|
15
|
+
|
16
|
+
def remote_url
|
17
|
+
@repo.remote.url
|
18
|
+
end
|
19
|
+
|
20
|
+
def working_directory
|
21
|
+
@repo.dir.path
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: learn-lab
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0.rc1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Flatiron School
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-11-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aruba
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '13.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '13.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.9'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.9'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec_junit_formatter
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.4'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.4'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: git
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.7'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.7'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: thor
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.0'
|
111
|
+
description:
|
112
|
+
email:
|
113
|
+
- learn@flatironschool.com
|
114
|
+
executables:
|
115
|
+
- learn-lab
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- ".circleci/config.yml"
|
120
|
+
- ".gitignore"
|
121
|
+
- ".rspec"
|
122
|
+
- ".rubocop.yml"
|
123
|
+
- CHANGELOG.md
|
124
|
+
- Gemfile
|
125
|
+
- LICENSE.txt
|
126
|
+
- README.md
|
127
|
+
- Rakefile
|
128
|
+
- bin/ci
|
129
|
+
- bin/console
|
130
|
+
- bin/rspec
|
131
|
+
- bin/rubocop
|
132
|
+
- bin/setup
|
133
|
+
- exe/learn-lab
|
134
|
+
- learn-lab.gemspec
|
135
|
+
- lib/learn_lab.rb
|
136
|
+
- lib/learn_lab/cli.rb
|
137
|
+
- lib/learn_lab/configuration.rb
|
138
|
+
- lib/learn_lab/errors.rb
|
139
|
+
- lib/learn_lab/file_system.rb
|
140
|
+
- lib/learn_lab/prompt.rb
|
141
|
+
- lib/learn_lab/test/parsers/mocha.rb
|
142
|
+
- lib/learn_lab/test/parsers/null.rb
|
143
|
+
- lib/learn_lab/test/parsers/rspec.rb
|
144
|
+
- lib/learn_lab/test/runner.rb
|
145
|
+
- lib/learn_lab/test/strategies/mocha.rb
|
146
|
+
- lib/learn_lab/test/strategies/none.rb
|
147
|
+
- lib/learn_lab/test/strategies/rspec.rb
|
148
|
+
- lib/learn_lab/test/strategy.rb
|
149
|
+
- lib/learn_lab/token.rb
|
150
|
+
- lib/learn_lab/vcs.rb
|
151
|
+
- lib/learn_lab/version.rb
|
152
|
+
homepage: https://github.com/flatiron-labs/learn-lab
|
153
|
+
licenses:
|
154
|
+
- MIT
|
155
|
+
metadata:
|
156
|
+
allowed_push_host: https://rubygems.org/
|
157
|
+
changelog_uri: https://github.com/flatiron-labs/learn-lab/blob/master/CHANGELOG.md
|
158
|
+
homepage_uri: https://github.com/flatiron-labs/learn-lab
|
159
|
+
source_code_uri: https://github.com/flatiron-labs/learn-lab
|
160
|
+
post_install_message:
|
161
|
+
rdoc_options: []
|
162
|
+
require_paths:
|
163
|
+
- lib
|
164
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: 2.5.0
|
169
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 1.3.1
|
174
|
+
requirements: []
|
175
|
+
rubyforge_project:
|
176
|
+
rubygems_version: 2.7.6
|
177
|
+
signing_key:
|
178
|
+
specification_version: 4
|
179
|
+
summary: The command line interface for Flatiron School enterprise.
|
180
|
+
test_files: []
|