lex-lex 0.1.2 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 054d9dec8f2440e350e0ae8d8a11170fd58c19fd132252a3999d947620b474b4
4
- data.tar.gz: 19e379da49b5d0443be0aca55dbc438b35ca11cc384007fb5ce6724264e39df1
3
+ metadata.gz: 0b474e02feee750156314596b621bd8fe8425d08a0175bdb143e5a867f924f8b
4
+ data.tar.gz: e87547d06e779d04651916c1c9fc5c3fc2cd704906aa842b9928a2e758e058c1
5
5
  SHA512:
6
- metadata.gz: d9c206401d69d73ec3b0432530eb82d494f0a0e68a8c3d8d8aa04d206bb7bf23f4451646c89bffcbaa7169571fcbf75b25b2ae3f2c38a92095922e900a05c839
7
- data.tar.gz: 9fa51e2d5cf2350abb5a63ddbf5a47ae409cb6d6ed23d502182ee542dd8c39fe0b9f7b5190e5be0c75f7b1882b675d3f4182587157fe7949fdf857d47b5b9570
6
+ metadata.gz: 0dedff5f561b638b61eb814699cb8ae10f07e6bd73be9acca5392226bcb1a813209426d0be17dc65c4a5d814f6de8e19e45b6a40f31cb2fa98a6934cc2881639
7
+ data.tar.gz: 21703e95634726a6f429f58dde4a6d35f79f814a606be40f62308f33fe06ea56f87bab43506d0ff39ff139d4b1d3a04ebe756fee96f268dc0dcf162e9c345543
@@ -0,0 +1,16 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches: [main]
5
+ pull_request:
6
+
7
+ jobs:
8
+ ci:
9
+ uses: LegionIO/.github/.github/workflows/ci.yml@main
10
+
11
+ release:
12
+ needs: ci
13
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
14
+ uses: LegionIO/.github/.github/workflows/release.yml@main
15
+ secrets:
16
+ rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
data/.rubocop.yml CHANGED
@@ -1,24 +1,66 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.4
3
+ NewCops: enable
4
+ SuggestExtensions: false
5
+
1
6
  Layout/LineLength:
2
- Max: 120
3
- Metrics/MethodLength:
4
- Max: 55
5
- Metrics/ClassLength:
6
- Max: 1500
7
- Metrics/BlockLength:
8
- Max: 75
9
- Metrics/AbcSize:
10
- Max: 50
7
+ Max: 160
8
+
11
9
  Layout/SpaceAroundEqualsInParameterDefault:
12
10
  EnforcedStyle: space
13
- Style/SymbolArray:
14
- Enabled: true
11
+
15
12
  Layout/HashAlignment:
16
13
  EnforcedHashRocketStyle: table
17
14
  EnforcedColonStyle: table
15
+
16
+ Metrics/MethodLength:
17
+ Max: 50
18
+
19
+ Metrics/ClassLength:
20
+ Max: 1500
21
+
22
+ Metrics/ModuleLength:
23
+ Max: 1500
24
+
25
+ Metrics/AbcSize:
26
+ Max: 60
27
+
28
+ Metrics/CyclomaticComplexity:
29
+ Max: 15
30
+
31
+ Metrics/PerceivedComplexity:
32
+ Max: 17
33
+
18
34
  Style/Documentation:
19
35
  Enabled: false
20
- AllCops:
21
- TargetRubyVersion: 2.5
22
- NewCops: enable
36
+
37
+ Style/SymbolArray:
38
+ Enabled: true
39
+
23
40
  Style/FrozenStringLiteralComment:
41
+ Enabled: true
42
+ EnforcedStyle: always
43
+
44
+ Naming/FileName:
45
+ Enabled: false
46
+
47
+ Naming/PredicateMethod:
48
+ Enabled: false
49
+
50
+ Naming/PredicatePrefix:
24
51
  Enabled: false
52
+
53
+ Gemspec/DevelopmentDependencies:
54
+ Enabled: false
55
+
56
+ Metrics/ParameterLists:
57
+ Enabled: false
58
+
59
+ Metrics/BlockLength:
60
+ Max: 40
61
+ Exclude:
62
+ - 'spec/**/*'
63
+
64
+ Style/OneClassPerFile:
65
+ Exclude:
66
+ - 'spec/**/*'
data/CHANGELOG.md ADDED
@@ -0,0 +1,28 @@
1
+ # Changelog
2
+
3
+ ## [0.2.0] - 2026-03-14
4
+
5
+ ### Added
6
+ - Sync runner: reconciles in-memory extensions with database on startup
7
+ - Sync Once actor: fires 5s after startup, guarded by `Legion::Data.connected?`
8
+ - Nil guards on all CRUD operations (return `{ success: false }` instead of raising)
9
+ - Comprehensive spec suite (55 specs)
10
+
11
+ ### Changed
12
+ - Modernized to Ruby >= 3.4
13
+ - Register.save uses direct module calls instead of `Legion::Runner.run` chain
14
+ - Register.save is now an instance method (was `self.save`)
15
+ - Updated gemspec: GitHub URLs, rubygems_mfa_required, modern dev dependencies
16
+ - Updated rubocop config to match current LegionIO conventions
17
+ - All runners guard `include Legion::Extensions::Helpers::Lex` with `defined?` check
18
+
19
+ ### Removed
20
+ - Bitbucket pipeline config
21
+ - Docker deployment script
22
+ - Old Dockerfile
23
+
24
+ ## [0.1.3] - Legacy
25
+
26
+ - Original Bitbucket-era release
27
+ - Ruby 2.5 minimum
28
+ - Extension/Runner/Function CRUD via `Legion::Runner.run` chain
data/CLAUDE.md ADDED
@@ -0,0 +1,78 @@
1
+ # lex-lex: Extension Registry for LegionIO
2
+
3
+ **Repository Level 3 Documentation**
4
+ - **Parent**: `/Users/miverso2/rubymine/legion/extensions-core/CLAUDE.md`
5
+ - **Grandparent**: `/Users/miverso2/rubymine/legion/CLAUDE.md`
6
+
7
+ ## Purpose
8
+
9
+ Core Legion Extension that persists extension, runner, and function metadata to the database. When LEX gems load, `LegionIO` publishes a `LexRegister` message to RabbitMQ. This extension consumes those messages and writes the catalog to `legion-data` models. Also provides a sync runner that reconciles in-memory extension state with the database on startup.
10
+
11
+ Without lex-lex, the extensions/runners/functions DB tables remain empty, and the REST API, MCP tools, and CLI commands that query extension metadata return stale results.
12
+
13
+ **GitHub**: https://github.com/LegionIO/lex-lex
14
+ **License**: MIT
15
+ **Version**: 0.2.0
16
+
17
+ ## Architecture
18
+
19
+ ```
20
+ Legion::Extensions::Lex
21
+ ├── Runners/
22
+ │ ├── Extension # CRUD on Legion::Data::Model::Extension
23
+ │ ├── Runner # CRUD on Legion::Data::Model::Runner
24
+ │ ├── Function # CRUD on Legion::Data::Model::Function + arg schema building
25
+ │ ├── Register # Orchestration: persist full extension descriptor from LexRegister message
26
+ │ └── Sync # Reconcile in-memory @extensions with DB (guarded by Data.connected?)
27
+ └── Actors/
28
+ └── Sync # Once actor: fires 5s after startup, calls Sync.sync
29
+ ```
30
+
31
+ ## Data Flow
32
+
33
+ ```
34
+ Extension loads (LegionIO/lib/legion/extensions.rb)
35
+ -> Publishes LexRegister message (routing key: extension_manager.register.save)
36
+ -> RabbitMQ queue "lex.register" (defined in lex-tasker)
37
+ -> lex-lex Subscription actor consumes message
38
+ -> Register.save persists extension + runners + functions to DB
39
+
40
+ Startup (after all extensions load):
41
+ -> Sync Once actor fires (5s delay)
42
+ -> Reads Legion::Extensions.@extensions and @loaded_extensions
43
+ -> Creates/updates DB records to match in-memory state
44
+ ```
45
+
46
+ ## Key Design Decisions
47
+
48
+ - **Direct DB calls**: Register.save calls Extension/Runner/Function modules directly instead of going through `Legion::Runner.run`. Registration is infrastructure plumbing, not business logic — task tracking overhead is unnecessary.
49
+ - **Idempotent**: All create methods check for existing records and update instead of duplicating.
50
+ - **Guard on sync**: Sync runner checks `Legion::Settings[:data][:connected]` before any DB operations.
51
+ - **data_required?**: Set to `true` — extension will not load if `legion-data` is unavailable.
52
+
53
+ ## File Map
54
+
55
+ | Path | Purpose |
56
+ |------|---------|
57
+ | `lib/legion/extensions/lex.rb` | Entry point, requires all runners |
58
+ | `lib/legion/extensions/lex/version.rb` | VERSION constant (0.2.0) |
59
+ | `lib/legion/extensions/lex/runners/extension.rb` | Extension CRUD |
60
+ | `lib/legion/extensions/lex/runners/runner.rb` | Runner CRUD |
61
+ | `lib/legion/extensions/lex/runners/function.rb` | Function CRUD + build_args |
62
+ | `lib/legion/extensions/lex/runners/register.rb` | Orchestration: full extension registration |
63
+ | `lib/legion/extensions/lex/runners/sync.rb` | In-memory to DB reconciliation |
64
+ | `lib/legion/extensions/lex/actors/sync.rb` | Once actor for startup sync |
65
+
66
+ ## Testing
67
+
68
+ ```bash
69
+ bundle install
70
+ bundle exec rspec # 55 specs
71
+ bundle exec rubocop # 0 offenses
72
+ ```
73
+
74
+ Specs run standalone without the full Legion framework. The spec_helper provides in-memory stubs for `Legion::Data::Model::*`, `Legion::Settings`, `Legion::Extensions::Helpers::Lex`, and `Legion::JSON`.
75
+
76
+ ---
77
+
78
+ **Maintained By**: Matthew Iverson (@Esity)
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  gemspec
data/Gemfile.lock CHANGED
@@ -1,62 +1,91 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lex-lex (0.1.2)
4
+ lex-lex (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- ast (2.4.1)
10
- diff-lcs (1.4.4)
11
- docile (1.3.2)
12
- parallel (1.19.2)
13
- parser (2.7.2.0)
9
+ addressable (2.8.9)
10
+ public_suffix (>= 2.0.2, < 8.0)
11
+ ast (2.4.3)
12
+ bigdecimal (4.0.1)
13
+ diff-lcs (1.6.2)
14
+ docile (1.4.1)
15
+ json (2.19.1)
16
+ json-schema (6.2.0)
17
+ addressable (~> 2.8)
18
+ bigdecimal (>= 3.1, < 5)
19
+ language_server-protocol (3.17.0.5)
20
+ lint_roller (1.1.0)
21
+ mcp (0.8.0)
22
+ json-schema (>= 4.1)
23
+ parallel (1.27.0)
24
+ parser (3.3.10.2)
14
25
  ast (~> 2.4.1)
15
- rainbow (3.0.0)
16
- rake (13.0.1)
17
- regexp_parser (1.8.2)
18
- rexml (3.2.4)
19
- rspec (3.10.0)
20
- rspec-core (~> 3.10.0)
21
- rspec-expectations (~> 3.10.0)
22
- rspec-mocks (~> 3.10.0)
23
- rspec-core (3.10.0)
24
- rspec-support (~> 3.10.0)
25
- rspec-expectations (3.10.0)
26
+ racc
27
+ prism (1.9.0)
28
+ public_suffix (7.0.5)
29
+ racc (1.8.1)
30
+ rainbow (3.1.1)
31
+ rake (13.3.1)
32
+ regexp_parser (2.11.3)
33
+ rspec (3.13.2)
34
+ rspec-core (~> 3.13.0)
35
+ rspec-expectations (~> 3.13.0)
36
+ rspec-mocks (~> 3.13.0)
37
+ rspec-core (3.13.6)
38
+ rspec-support (~> 3.13.0)
39
+ rspec-expectations (3.13.5)
26
40
  diff-lcs (>= 1.2.0, < 2.0)
27
- rspec-support (~> 3.10.0)
28
- rspec-mocks (3.10.0)
41
+ rspec-support (~> 3.13.0)
42
+ rspec-mocks (3.13.8)
29
43
  diff-lcs (>= 1.2.0, < 2.0)
30
- rspec-support (~> 3.10.0)
31
- rspec-support (3.10.0)
32
- rubocop (1.1.0)
44
+ rspec-support (~> 3.13.0)
45
+ rspec-support (3.13.7)
46
+ rspec_junit_formatter (0.6.0)
47
+ rspec-core (>= 2, < 4, != 2.12.0)
48
+ rubocop (1.85.1)
49
+ json (~> 2.3)
50
+ language_server-protocol (~> 3.17.0.2)
51
+ lint_roller (~> 1.1.0)
52
+ mcp (~> 0.6)
33
53
  parallel (~> 1.10)
34
- parser (>= 2.7.1.5)
54
+ parser (>= 3.3.0.2)
35
55
  rainbow (>= 2.2.2, < 4.0)
36
- regexp_parser (>= 1.8)
37
- rexml
38
- rubocop-ast (>= 1.0.1)
56
+ regexp_parser (>= 2.9.3, < 3.0)
57
+ rubocop-ast (>= 1.49.0, < 2.0)
39
58
  ruby-progressbar (~> 1.7)
40
- unicode-display_width (>= 1.4.0, < 2.0)
41
- rubocop-ast (1.1.0)
42
- parser (>= 2.7.1.5)
43
- ruby-progressbar (1.10.1)
44
- simplecov (0.19.1)
59
+ unicode-display_width (>= 2.4.0, < 4.0)
60
+ rubocop-ast (1.49.1)
61
+ parser (>= 3.3.7.2)
62
+ prism (~> 1.7)
63
+ rubocop-rspec (3.9.0)
64
+ lint_roller (~> 1.1)
65
+ rubocop (~> 1.81)
66
+ ruby-progressbar (1.13.0)
67
+ simplecov (0.22.0)
45
68
  docile (~> 1.1)
46
69
  simplecov-html (~> 0.11)
47
- simplecov-html (0.12.3)
48
- unicode-display_width (1.7.0)
70
+ simplecov_json_formatter (~> 0.1)
71
+ simplecov-html (0.13.2)
72
+ simplecov_json_formatter (0.1.4)
73
+ unicode-display_width (3.2.0)
74
+ unicode-emoji (~> 4.1)
75
+ unicode-emoji (4.2.0)
49
76
 
50
77
  PLATFORMS
78
+ arm64-darwin-25
51
79
  ruby
52
80
 
53
81
  DEPENDENCIES
54
- bundler (>= 2)
55
82
  lex-lex!
56
83
  rake
57
- rspec
58
- rubocop
84
+ rspec (~> 3.13)
85
+ rspec_junit_formatter
86
+ rubocop (~> 1.75)
87
+ rubocop-rspec
59
88
  simplecov
60
89
 
61
90
  BUNDLED WITH
62
- 2.1.4
91
+ 2.6.9
data/README.md CHANGED
@@ -1,40 +1,40 @@
1
- # Legion::Extensions::Lex
1
+ # lex-lex
2
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/legion/extensions/lex`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Extension registry for [LegionIO](https://github.com/LegionIO). Persists extension, runner, and function metadata to the database when LEX gems load.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ ## What It Does
6
6
 
7
- ## Installation
7
+ When LegionIO loads extensions, it publishes `LexRegister` messages to RabbitMQ. This extension:
8
8
 
9
- Add this line to your application's Gemfile:
9
+ 1. **Consumes** those messages via a subscription actor
10
+ 2. **Persists** extension/runner/function records to `legion-data` models
11
+ 3. **Syncs** in-memory extension state with the database on startup
10
12
 
11
- ```ruby
12
- gem 'legion-extensions-lex'
13
- ```
14
-
15
- And then execute:
13
+ Without lex-lex, the REST API (`/api/extensions`), MCP tools (`legion.list_extensions`), and CLI (`legion lex list`) return empty results.
16
14
 
17
- $ bundle install
15
+ ## Runners
18
16
 
19
- Or install it yourself as:
17
+ | Runner | Methods | Purpose |
18
+ |--------|---------|---------|
19
+ | Extension | create, update, get, delete | CRUD for extensions |
20
+ | Runner | create, update, get, delete | CRUD for runners |
21
+ | Function | create, update, get, delete, build_args | CRUD for functions + arg schema |
22
+ | Register | save | Persist full extension descriptor |
23
+ | Sync | sync | Reconcile in-memory state with DB |
20
24
 
21
- $ gem install legion-extensions-lex
25
+ ## Requirements
22
26
 
23
- ## Usage
24
-
25
- TODO: Write usage instructions here
27
+ - Ruby >= 3.4
28
+ - `legion-data` must be connected (`data_required? true`)
26
29
 
27
30
  ## Development
28
31
 
29
- 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.
30
-
31
- 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).
32
-
33
- ## Contributing
34
-
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/legion-extensions-lex.
36
-
32
+ ```bash
33
+ bundle install
34
+ bundle exec rspec
35
+ bundle exec rubocop
36
+ ```
37
37
 
38
38
  ## License
39
39
 
40
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
40
+ MIT
data/lex-lex.gemspec CHANGED
@@ -8,26 +8,28 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ['Esity']
9
9
  spec.email = ['matthewdiverson@gmail.com']
10
10
 
11
- spec.summary = 'Lex::Lex manages Legion Extensions'
12
- spec.description = 'Used by Legion to keep track of which LEXs are installed and available in the cluster'
13
- spec.homepage = 'https://bitbucket.org/legion-io'
11
+ spec.summary = 'Legion Extension Registry'
12
+ spec.description = 'Persists extension, runner, and function metadata to the database when LEX gems load'
13
+ spec.homepage = 'https://github.com/LegionIO/lex-lex'
14
14
  spec.license = 'MIT'
15
- spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
15
+ spec.required_ruby_version = '>= 3.4'
16
16
 
17
- spec.metadata['homepage_uri'] = spec.homepage
18
- spec.metadata['source_code_uri'] = 'https://bitbucket.org/legion-io/lex-lex'
19
- spec.metadata['documentation_uri'] = 'https://legionio.atlassian.net/wiki/spaces/LEX/pages/612270215'
20
- spec.metadata['changelog_uri'] = 'https://legionio.atlassian.net/wiki/spaces/LEX/pages/614891616'
21
- spec.metadata['bug_tracker_uri'] = 'https://bitbucket.org/legion-io/lex-lex/issues'
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+ spec.metadata['source_code_uri'] = 'https://github.com/LegionIO/lex-lex'
19
+ spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-lex'
20
+ spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-lex'
21
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-lex/issues'
22
+ spec.metadata['rubygems_mfa_required'] = 'true'
22
23
 
23
24
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
24
25
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
26
  end
26
27
  spec.require_paths = ['lib']
27
28
 
28
- spec.add_development_dependency 'bundler', '>= 2'
29
29
  spec.add_development_dependency 'rake'
30
- spec.add_development_dependency 'rspec'
31
- spec.add_development_dependency 'rubocop'
30
+ spec.add_development_dependency 'rspec', '~> 3.13'
31
+ spec.add_development_dependency 'rspec_junit_formatter'
32
+ spec.add_development_dependency 'rubocop', '~> 1.75'
33
+ spec.add_development_dependency 'rubocop-rspec'
32
34
  spec.add_development_dependency 'simplecov'
33
35
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'legion/extensions/actors/once'
4
+
5
+ module Legion
6
+ module Extensions
7
+ module Lex
8
+ module Actor
9
+ class Sync < Legion::Extensions::Actors::Once
10
+ def runner_class
11
+ Legion::Extensions::Lex::Runners::Sync
12
+ end
13
+
14
+ def runner_function
15
+ 'sync'
16
+ end
17
+
18
+ def use_runner?
19
+ false
20
+ end
21
+
22
+ def check_subtask?
23
+ false
24
+ end
25
+
26
+ def generate_task?
27
+ false
28
+ end
29
+
30
+ def enabled?
31
+ return false unless defined?(Legion::Settings)
32
+
33
+ Legion::Settings[:data][:connected] == true
34
+ rescue StandardError
35
+ false
36
+ end
37
+
38
+ def delay
39
+ 5.0
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,57 +1,60 @@
1
- module Legion::Extensions::Lex # rubocop:disable Style/ClassAndModuleChildren
2
- module Runners
3
- module Extension
4
- include Legion::Extensions::Helpers::Lex
5
-
6
- def create(name:, namespace:, active: 1, **opts)
7
- exist = model.where(name: name).first
8
- unless exist.nil?
9
- update_hash = { extension_id: exist.values[:id], namespace: namespace, **opts }
10
- return Legion::Runner.run(runner_class: to_s,
11
- function: 'update',
12
- args: update_hash,
13
- parent_id: opts[:task_id],
14
- master_id: opts[:master_id] || opts[:task_id])[:result]
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Lex
6
+ module Runners
7
+ module Extension
8
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
9
+
10
+ def create(name:, namespace:, active: true, **opts)
11
+ existing = Legion::Data::Model::Extension.where(name: name).first
12
+ return update(extension_id: existing.values[:id], namespace: namespace, active: active, **opts) if existing
13
+
14
+ insert = { name: name, namespace: namespace, active: active }
15
+ insert[:exchange] = opts.fetch(:exchange, name)
16
+ insert[:uri] = opts.fetch(:uri, name)
17
+ id = Legion::Data::Model::Extension.insert(insert)
18
+ { success: true, extension_id: id }
19
+ end
20
+
21
+ def update(extension_id:, **opts)
22
+ extension = Legion::Data::Model::Extension[extension_id]
23
+ return { success: false, reason: 'extension not found' } if extension.nil?
24
+
25
+ update = {}
26
+ %i[name namespace active exchange uri].each do |column|
27
+ next unless opts.key?(column)
28
+ next if extension.values[column] == opts[column]
29
+
30
+ update[column] = opts[column]
31
+ end
32
+
33
+ return { success: true, changed: false, extension_id: extension_id } if update.empty?
34
+
35
+ extension.update(update)
36
+ { success: true, changed: true, updates: update, extension_id: extension_id }
37
+ end
38
+
39
+ def get(extension_id: nil, name: nil, namespace: nil, **_opts)
40
+ dataset = Legion::Data::Model::Extension
41
+ dataset = dataset.where(id: extension_id) if extension_id
42
+ dataset = dataset.where(name: name) if name
43
+ dataset = dataset.where(namespace: namespace) if namespace
44
+ record = dataset.first
45
+ return { success: false, reason: 'not found' } if record.nil?
46
+
47
+ { success: true, values: record.values }
48
+ end
49
+
50
+ def delete(extension_id:, **_opts)
51
+ record = Legion::Data::Model::Extension[extension_id]
52
+ return { success: false, reason: 'not found' } if record.nil?
53
+
54
+ record.delete
55
+ { success: true, extension_id: extension_id }
56
+ end
15
57
  end
16
-
17
- insert = { name: name, namespace: namespace, active: active }
18
- insert[:exchange] = opts.key?(:exchange) ? opts[:exchange] : name
19
- insert[:uri] = opts.key?(:uri) ? opts[:uri] : name
20
- { success: true, extension_id: model.insert(insert) }
21
- end
22
-
23
- def update(extension_id:, **opts)
24
- extension = Legion::Data::Model::Extension[extension_id]
25
- update = {}
26
- %i[name namespace active exchange uri].each do |column|
27
- next unless opts.key? column
28
- next if extension.values[column] == opts[column]
29
-
30
- update[column] = opts[column]
31
- end
32
-
33
- { success: true, changed: false, extension_id: extension_id } if update.count.zero?
34
- extension.update(update)
35
- { success: true, changed: true, updates: update, extension_id: extension_id }
36
- end
37
-
38
- def get(**opts)
39
- extension = Legion::Data::Model::Extension
40
- extension.where(id: opts[:extension_id]) if opts.key? :extension_id
41
- extension.where(name: opts[:name]) if opts.key? :name
42
- extension.where(namespace: opts[:namespace]) if opts.key? :namespace
43
- { success: true, values: extension.first.values }
44
- end
45
-
46
- def delete(extension_id:, **_opts)
47
- Legion::Data::Model::Extension[extension_id].delete
48
- { success: true, extension_id: extension_id }
49
- end
50
-
51
- private
52
-
53
- def model
54
- Legion::Data::Model::Extension
55
58
  end
56
59
  end
57
60
  end
@@ -1,55 +1,64 @@
1
- module Legion::Extensions::Lex # rubocop:disable Style/ClassAndModuleChildren
2
- module Runners
3
- module Function
4
- include Legion::Extensions::Helpers::Lex
5
-
6
- def create(runner_id:, name:, active: 1, **opts)
7
- exist = Legion::Data::Model::Function.where(name: name.to_s).where(runner_id: runner_id).first
8
- unless exist.nil?
9
- log.debug "function: #{exist.values[:id]} already exists, updating it"
10
- update_hash = { function_id: exist.values[:id], name: name, active: active, **opts }
11
- return Legion::Runner.run(runner_class: 'Legion::Extensions::Lex::Runners::Function',
12
- function: 'update',
13
- args: update_hash,
14
- parent_id: opts[:task_id],
15
- master_id: opts[:master_id])
16
- end
17
- insert = { runner_id: runner_id, name: name.to_s, active: active }
18
- insert[:args] = Legion::JSON.dump(opts[:formatted_args]) if opts.key? :formatted_args
1
+ # frozen_string_literal: true
19
2
 
20
- { success: true, function_id: Legion::Data::Model::Function.insert(insert) }
21
- end
3
+ module Legion
4
+ module Extensions
5
+ module Lex
6
+ module Runners
7
+ module Function
8
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
22
9
 
23
- def update(function_id:, **opts)
24
- function = Legion::Data::Model::Function[function_id]
25
- update = {}
26
- update[:active] = true unless function.values[:active]
10
+ def create(runner_id:, name:, active: true, **opts)
11
+ existing = Legion::Data::Model::Function.where(name: name.to_s, runner_id: runner_id).first
12
+ return update(function_id: existing.values[:id], name: name, active: active, **opts) if existing
27
13
 
28
- if opts.key? :formatted_args
29
- args = JSON.dump(opts[:formatted_args])
30
- update[:args] = args unless args == function.values[:args]
31
- end
14
+ insert = { runner_id: runner_id, name: name.to_s, active: active }
15
+ insert[:args] = Legion::JSON.dump(opts[:formatted_args]) if opts.key?(:formatted_args)
32
16
 
33
- return { success: true, changed: false, function_id: function_id } if update.count.zero?
17
+ id = Legion::Data::Model::Function.insert(insert)
18
+ { success: true, function_id: id }
19
+ end
34
20
 
35
- function.update(update)
36
- { success: true, changed: true, updates: update, function_id: function_id }
37
- end
21
+ def update(function_id:, **opts)
22
+ function = Legion::Data::Model::Function[function_id]
23
+ return { success: false, reason: 'function not found' } if function.nil?
38
24
 
39
- def get(function_id:, **_opts)
40
- { function_id: function_id, values: Legion::Data::Model::Function[function_id].values }
41
- end
25
+ update = {}
26
+ update[:active] = opts[:active] if opts.key?(:active) && function.values[:active] != opts[:active]
42
27
 
43
- def delete(function_id:, **_opts)
44
- { function_id: function_id, result: Legion::Data::Model::Function[function_id].delete }
45
- end
28
+ if opts.key?(:formatted_args)
29
+ args = Legion::JSON.dump(opts[:formatted_args])
30
+ update[:args] = args unless args == function.values[:args]
31
+ end
32
+
33
+ return { success: true, changed: false, function_id: function_id } if update.empty?
34
+
35
+ function.update(update)
36
+ { success: true, changed: true, updates: update, function_id: function_id }
37
+ end
38
+
39
+ def get(function_id:, **_opts)
40
+ record = Legion::Data::Model::Function[function_id]
41
+ return { success: false, reason: 'not found' } if record.nil?
42
+
43
+ { success: true, values: record.values }
44
+ end
45
+
46
+ def delete(function_id:, **_opts)
47
+ record = Legion::Data::Model::Function[function_id]
48
+ return { success: false, reason: 'not found' } if record.nil?
49
+
50
+ record.delete
51
+ { success: true, function_id: function_id }
52
+ end
46
53
 
47
- def self.build_args(raw_args:, **_opts)
48
- args = {}
49
- raw_args.each do |arg|
50
- args[arg[1]] = arg[0] unless %w[opts options].include? arg[1]
54
+ def build_args(raw_args:, **_opts)
55
+ args = {}
56
+ raw_args.each do |arg|
57
+ args[arg[1]] = arg[0] unless %w[opts options].include?(arg[1].to_s)
58
+ end
59
+ { success: true, formatted_args: args }
60
+ end
51
61
  end
52
- { success: true, formatted_args: args }
53
62
  end
54
63
  end
55
64
  end
@@ -1,68 +1,57 @@
1
- module Legion::Extensions::Lex # rubocop:disable Style/ClassAndModuleChildren
2
- module Runners
3
- module Register
4
- include Legion::Extensions::Helpers::Lex
1
+ # frozen_string_literal: true
5
2
 
6
- def self.save(opts:, **_options)
7
- extension_id = nil
8
- extension = nil
9
- master_id = opts[:task_id]
10
- opts.each do |runner_name, opt|
11
- if extension_id.nil?
12
- extension_args = {
13
- namespace: opt[:extension_class],
14
- name: opt[:extension_name],
15
- parent_id: opts[:task_id],
16
- master_id: opts[:master_id]
17
- }
18
- extension = Legion::Runner.run(runner_class: 'Legion::Extensions::Lex::Runners::Extension',
19
- function: 'create',
20
- args: extension_args,
21
- parent_id: opts[:task_id],
22
- master_id: master_id)
23
- extension_id = extension[:result][:extension_id]
24
- @parent_id = extension[:task_id]
25
- end
3
+ module Legion
4
+ module Extensions
5
+ module Lex
6
+ module Runners
7
+ module Register
8
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
9
+
10
+ def save(opts:, **_options)
11
+ return { success: false, reason: 'no opts provided' } if opts.nil? || opts.empty?
12
+
13
+ extension_id = nil
14
+ runners_created = 0
15
+ functions_created = 0
16
+
17
+ opts.each do |runner_name, runner_opts|
18
+ next unless runner_opts.is_a?(Hash)
19
+
20
+ if extension_id.nil?
21
+ ext_result = Extension.create(
22
+ name: runner_opts[:extension_name],
23
+ namespace: runner_opts[:extension_class].to_s
24
+ )
25
+ extension_id = ext_result[:extension_id]
26
+ end
27
+
28
+ runner_result = Runner.create(
29
+ extension_id: extension_id,
30
+ name: runner_name.to_s,
31
+ namespace: runner_opts[:runner_class].to_s
32
+ )
33
+ runner_id = runner_result[:runner_id]
34
+ runners_created += 1
26
35
 
27
- runner_args = { extension_id: extension_id,
28
- name: runner_name,
29
- namespace: opt[:runner_class],
30
- parent_id: @parent_id,
31
- master_id: opts[:task_id] }
32
- runner = Legion::Runner.run(runner_class: 'Legion::Extensions::Lex::Runners::Runner',
33
- function: 'create',
34
- args: runner_args,
35
- parent_id: @parent_id,
36
- master_id: master_id)
36
+ next unless runner_opts[:class_methods].is_a?(Hash)
37
37
 
38
- runner_id = if runner[:result].key? :result
39
- runner[:result][:result][:runner_id]
40
- else
41
- runner[:result][:runner_id]
42
- end
38
+ runner_opts[:class_methods].each do |func_name, func_opts|
39
+ formatted = (Function.build_args(raw_args: func_opts[:args])[:formatted_args] if func_opts.is_a?(Hash) && func_opts[:args])
43
40
 
44
- opt[:class_methods].each do |function, values|
45
- build_args_hash = { master_id: master_id, parent_id: runner[:task_id], raw_args: values[:args] }
46
- args = Legion::Runner.run(runner_class: 'Legion::Extensions::Lex::Runners::Function',
47
- function: 'build_args',
48
- generate_task: false,
49
- check_subtask: false,
50
- args: build_args_hash,
51
- parent_id: runner[:task_id],
52
- master_id: master_id)
41
+ Function.create(
42
+ runner_id: runner_id,
43
+ name: func_name.to_s,
44
+ formatted_args: formatted
45
+ )
46
+ functions_created += 1
47
+ end
48
+ end
53
49
 
54
- function_args = { runner_id: runner_id,
55
- name: function,
56
- formatted_args: args[:result][:formatted_args],
57
- master_id: master_id, parent_id: runner[:task_id] }
58
- Legion::Runner.run(runner_class: 'Legion::Extensions::Lex::Runners::Function',
59
- function: 'create',
60
- args: function_args,
61
- parent_id: args[:task_id],
62
- master_id: master_id)
50
+ { success: true, extension_id: extension_id, runners: runners_created, functions: functions_created }
51
+ rescue StandardError => e
52
+ { success: false, error: e.message }
63
53
  end
64
54
  end
65
- { success: true }
66
55
  end
67
56
  end
68
57
  end
@@ -1,45 +1,61 @@
1
- module Legion::Extensions::Lex # rubocop:disable Style/ClassAndModuleChildren
2
- module Runners
3
- module Runner
4
- include Legion::Extensions::Helpers::Lex
5
-
6
- def create(extension_id:, name:, active: 1, **opts)
7
- exist = Legion::Data::Model::Runner.where(name: name.to_s).where(extension_id: extension_id).first
8
- unless exist.nil?
9
- update_hash = { runner_id: exist.values[:id], name: name, active: active, **opts }
10
- return Legion::Runner.run(runner_class: 'Legion::Extensions::Lex::Runners::Runner',
11
- function: 'update',
12
- args: update_hash,
13
- parent_id: opts[:task_id],
14
- master_id: opts[:master_id])
15
- end
16
- insert = { extension_id: extension_id, name: name.to_s, active: active, namespace: opts[:namespace] }
17
- insert[:queue] = opts.key?(:queue) ? opts[:queue] : name.to_s
18
- insert[:uri] = opts.key?(:uri) ? opts[:uri] : name.to_s
19
- { success: true, runner_id: Legion::Data::Model::Runner.insert(insert) }
20
- end
1
+ # frozen_string_literal: true
21
2
 
22
- def update(runner_id:, **opts)
23
- runner = Legion::Data::Model::Runner[runner_id]
24
- update = {}
25
- %i[name namespace active queue uri].each do |column|
26
- next unless opts.key? column
27
- next if runner.values[column] == opts[column]
3
+ module Legion
4
+ module Extensions
5
+ module Lex
6
+ module Runners
7
+ module Runner
8
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
28
9
 
29
- update[column] = opts[column]
30
- end
10
+ def create(extension_id:, name:, active: true, **opts)
11
+ existing = Legion::Data::Model::Runner.where(name: name.to_s, extension_id: extension_id).first
12
+ return update(runner_id: existing.values[:id], name: name, active: active, **opts) if existing
31
13
 
32
- { success: true, changed: false, runner_id: runner_id } if update.count.zero?
33
- runner.update(update)
34
- { success: true, changed: true, updates: update, runner_id: runner_id }
35
- end
14
+ insert = {
15
+ extension_id: extension_id,
16
+ name: name.to_s,
17
+ active: active,
18
+ namespace: opts[:namespace]
19
+ }
20
+ insert[:queue] = opts.fetch(:queue, name.to_s)
21
+ insert[:uri] = opts.fetch(:uri, name.to_s)
22
+ id = Legion::Data::Model::Runner.insert(insert)
23
+ { success: true, runner_id: id }
24
+ end
36
25
 
37
- def get(runner_id:, **_opts)
38
- Legion::Data::Model::Runner[runner_id].values
39
- end
26
+ def update(runner_id:, **opts)
27
+ runner = Legion::Data::Model::Runner[runner_id]
28
+ return { success: false, reason: 'runner not found' } if runner.nil?
29
+
30
+ update = {}
31
+ %i[name namespace active queue uri].each do |column|
32
+ next unless opts.key?(column)
33
+ next if runner.values[column] == opts[column]
34
+
35
+ update[column] = opts[column]
36
+ end
40
37
 
41
- def delete(runner_id:, **_opts)
42
- { runner_id: runner_id, result: Legion::Data::Model::Runner[runner_id].delete }
38
+ return { success: true, changed: false, runner_id: runner_id } if update.empty?
39
+
40
+ runner.update(update)
41
+ { success: true, changed: true, updates: update, runner_id: runner_id }
42
+ end
43
+
44
+ def get(runner_id:, **_opts)
45
+ record = Legion::Data::Model::Runner[runner_id]
46
+ return { success: false, reason: 'not found' } if record.nil?
47
+
48
+ { success: true, values: record.values }
49
+ end
50
+
51
+ def delete(runner_id:, **_opts)
52
+ record = Legion::Data::Model::Runner[runner_id]
53
+ return { success: false, reason: 'not found' } if record.nil?
54
+
55
+ record.delete
56
+ { success: true, runner_id: runner_id }
57
+ end
58
+ end
43
59
  end
44
60
  end
45
61
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Lex
6
+ module Runners
7
+ module Sync
8
+ include Legion::Extensions::Helpers::Lex if defined?(Legion::Extensions::Helpers::Lex)
9
+
10
+ def sync(**_opts)
11
+ return { success: false, reason: 'legion-data not connected' } unless Legion::Settings[:data][:connected]
12
+
13
+ extensions = Legion::Extensions.instance_variable_get(:@extensions) || {}
14
+ loaded = Legion::Extensions.instance_variable_get(:@loaded_extensions) || []
15
+
16
+ synced = 0
17
+ created = 0
18
+ updated = 0
19
+
20
+ loaded.each do |ext_name|
21
+ values = extensions[ext_name]
22
+ next if values.nil?
23
+
24
+ existing = Legion::Data::Model::Extension.where(name: ext_name).first
25
+ if existing.nil?
26
+ Legion::Data::Model::Extension.insert(
27
+ name: ext_name,
28
+ namespace: values[:extension_class].to_s,
29
+ active: true,
30
+ exchange: ext_name,
31
+ uri: ext_name
32
+ )
33
+ created += 1
34
+ else
35
+ ns = values[:extension_class].to_s
36
+ existing.update(namespace: ns, active: true) if existing.values[:namespace] != ns
37
+ updated += 1
38
+ end
39
+ synced += 1
40
+ end
41
+
42
+ { success: true, synced: synced, created: created, updated: updated }
43
+ rescue StandardError => e
44
+ { success: false, error: e.message }
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -3,7 +3,7 @@
3
3
  module Legion
4
4
  module Extensions
5
5
  module Lex
6
- VERSION = '0.1.2'
6
+ VERSION = '0.2.0'
7
7
  end
8
8
  end
9
9
  end
@@ -1,13 +1,20 @@
1
- require 'legion/extensions/lex/version'
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lex/version'
4
+ require_relative 'lex/runners/extension'
5
+ require_relative 'lex/runners/runner'
6
+ require_relative 'lex/runners/function'
7
+ require_relative 'lex/runners/register'
8
+ require_relative 'lex/runners/sync'
2
9
 
3
10
  module Legion
4
11
  module Extensions
5
12
  module Lex
6
- extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
7
- end
13
+ extend Legion::Extensions::Core if Legion::Extensions.const_defined?(:Core)
8
14
 
9
- def data_required?
10
- true
15
+ def data_required?
16
+ true
17
+ end
11
18
  end
12
19
  end
13
20
  end
metadata CHANGED
@@ -1,45 +1,44 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-lex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2020-11-02 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
- name: bundler
13
+ name: rake
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
16
  - - ">="
18
17
  - !ruby/object:Gem::Version
19
- version: '2'
18
+ version: '0'
20
19
  type: :development
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
- version: '2'
25
+ version: '0'
27
26
  - !ruby/object:Gem::Dependency
28
- name: rake
27
+ name: rspec
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
- - - ">="
30
+ - - "~>"
32
31
  - !ruby/object:Gem::Version
33
- version: '0'
32
+ version: '3.13'
34
33
  type: :development
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
37
36
  requirements:
38
- - - ">="
37
+ - - "~>"
39
38
  - !ruby/object:Gem::Version
40
- version: '0'
39
+ version: '3.13'
41
40
  - !ruby/object:Gem::Dependency
42
- name: rspec
41
+ name: rspec_junit_formatter
43
42
  requirement: !ruby/object:Gem::Requirement
44
43
  requirements:
45
44
  - - ">="
@@ -54,6 +53,20 @@ dependencies:
54
53
  version: '0'
55
54
  - !ruby/object:Gem::Dependency
56
55
  name: rubocop
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.75'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.75'
68
+ - !ruby/object:Gem::Dependency
69
+ name: rubocop-rspec
57
70
  requirement: !ruby/object:Gem::Requirement
58
71
  requirements:
59
72
  - - ">="
@@ -80,40 +93,43 @@ dependencies:
80
93
  - - ">="
81
94
  - !ruby/object:Gem::Version
82
95
  version: '0'
83
- description: Used by Legion to keep track of which LEXs are installed and available
84
- in the cluster
96
+ description: Persists extension, runner, and function metadata to the database when
97
+ LEX gems load
85
98
  email:
86
99
  - matthewdiverson@gmail.com
87
100
  executables: []
88
101
  extensions: []
89
102
  extra_rdoc_files: []
90
103
  files:
104
+ - ".github/workflows/ci.yml"
91
105
  - ".gitignore"
92
106
  - ".rspec"
93
107
  - ".rubocop.yml"
108
+ - CHANGELOG.md
109
+ - CLAUDE.md
94
110
  - Gemfile
95
111
  - Gemfile.lock
96
112
  - LICENSE.txt
97
113
  - README.md
98
- - Rakefile
99
- - bitbucket-pipelines.yml
100
114
  - lex-lex.gemspec
101
115
  - lib/legion/extensions/lex.rb
116
+ - lib/legion/extensions/lex/actors/sync.rb
102
117
  - lib/legion/extensions/lex/runners/extension.rb
103
118
  - lib/legion/extensions/lex/runners/function.rb
104
119
  - lib/legion/extensions/lex/runners/register.rb
105
120
  - lib/legion/extensions/lex/runners/runner.rb
121
+ - lib/legion/extensions/lex/runners/sync.rb
106
122
  - lib/legion/extensions/lex/version.rb
107
- homepage: https://bitbucket.org/legion-io
123
+ homepage: https://github.com/LegionIO/lex-lex
108
124
  licenses:
109
125
  - MIT
110
126
  metadata:
111
- homepage_uri: https://bitbucket.org/legion-io
112
- source_code_uri: https://bitbucket.org/legion-io/lex-lex
113
- documentation_uri: https://legionio.atlassian.net/wiki/spaces/LEX/pages/612270215
114
- changelog_uri: https://legionio.atlassian.net/wiki/spaces/LEX/pages/614891616
115
- bug_tracker_uri: https://bitbucket.org/legion-io/lex-lex/issues
116
- post_install_message:
127
+ homepage_uri: https://github.com/LegionIO/lex-lex
128
+ source_code_uri: https://github.com/LegionIO/lex-lex
129
+ changelog_uri: https://github.com/LegionIO/lex-lex
130
+ documentation_uri: https://github.com/LegionIO/lex-lex
131
+ bug_tracker_uri: https://github.com/LegionIO/lex-lex/issues
132
+ rubygems_mfa_required: 'true'
117
133
  rdoc_options: []
118
134
  require_paths:
119
135
  - lib
@@ -121,15 +137,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
121
137
  requirements:
122
138
  - - ">="
123
139
  - !ruby/object:Gem::Version
124
- version: 2.5.0
140
+ version: '3.4'
125
141
  required_rubygems_version: !ruby/object:Gem::Requirement
126
142
  requirements:
127
143
  - - ">="
128
144
  - !ruby/object:Gem::Version
129
145
  version: '0'
130
146
  requirements: []
131
- rubygems_version: 3.1.4
132
- signing_key:
147
+ rubygems_version: 3.6.9
133
148
  specification_version: 4
134
- summary: Lex::Lex manages Legion Extensions
149
+ summary: Legion Extension Registry
135
150
  test_files: []
data/Rakefile DELETED
@@ -1,8 +0,0 @@
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
@@ -1,69 +0,0 @@
1
- image: ruby:2.7
2
-
3
- pipelines:
4
- tags:
5
- "v*":
6
- - step:
7
- name: Rubocop
8
- caches:
9
- - bundler
10
- script:
11
- - gem install rubocop
12
- - gem update rubocop
13
- - rubocop
14
- - step:
15
- name: RSpec
16
- caches:
17
- - bundler
18
- script:
19
- - gem install bundler
20
- - gem update bundler
21
- - bundle update
22
- - bundle exec rspec
23
- - step:
24
- name: Push to RubyGems
25
- deployment: RubyGems
26
- script:
27
- - gem install bundler gem-release rspec
28
- - bundle install
29
- - (umask 077 ; echo $gem_creds | base64 --decode > ~/.gem/credentials)
30
- - gem release
31
- artifacts:
32
- - pkg/**
33
- branches:
34
- master:
35
- - step:
36
- caches:
37
- - bundler
38
- script:
39
- - gem install rubocop
40
- - gem update rubocop
41
- - rubocop
42
- - step:
43
- caches:
44
- - bundler
45
- script:
46
- - gem install bundler
47
- - gem update bundler
48
- - bundle update
49
- - bundle exec rspec
50
- develop:
51
- - step:
52
- caches:
53
- - bundler
54
- script:
55
- - gem install rubocop
56
- - gem update rubocop
57
- - rubocop
58
- - step:
59
- caches:
60
- - bundler
61
- script:
62
- - gem install bundler
63
- - gem update bundler
64
- - bundle update
65
- - bundle exec rspec
66
-
67
- definitions:
68
- caches:
69
- bundler: /usr/local/bundle