rolemodel-rails 2.6.0 → 2.7.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 +4 -4
- data/README.md +12 -0
- data/lib/generators/rolemodel/core_setup/README.md +2 -1
- data/lib/generators/rolemodel/core_setup/core_setup_generator.rb +5 -1
- data/lib/generators/rolemodel/github/README.md +0 -4
- data/lib/generators/rolemodel/github/USAGE +0 -1
- data/lib/generators/rolemodel/github/github_generator.rb +0 -5
- data/lib/generators/rolemodel/heroku/templates/deploy-app/SKILL.md +10 -8
- data/lib/generators/rolemodel/linters/rubocop/templates/.rubocop/cops/form_error_response.rb +54 -0
- data/lib/generators/rolemodel/linters/rubocop/templates/.rubocop/cops/no_chrome_tag.rb +45 -0
- data/lib/generators/rolemodel/linters/rubocop/templates/.rubocop.yml +74 -0
- data/lib/generators/rolemodel/optics/README.md +3 -0
- data/lib/generators/rolemodel/optics/all_generator.rb +5 -1
- data/lib/generators/rolemodel/optics/base/README.md +2 -0
- data/lib/generators/rolemodel/optics/base/base_generator.rb +6 -0
- data/lib/generators/rolemodel/optics/icons/icon_library_options.rb +23 -0
- data/lib/generators/rolemodel/optics/icons/icons_generator.rb +1 -1
- data/lib/generators/rolemodel/readme/readme_generator.rb +1 -1
- data/lib/generators/rolemodel/sentry/templates/config/initializers/sentry.rb +0 -1
- data/lib/generators/rolemodel/soft_destroyable/README.md +1 -0
- data/lib/generators/rolemodel/soft_destroyable/soft_destroyable_generator.rb +6 -0
- data/lib/generators/rolemodel/testing/parallel_tests/templates/.rspec_parallel +3 -0
- data/lib/generators/rolemodel/testing/rspec/README.md +2 -0
- data/lib/generators/rolemodel/testing/rspec/rspec_generator.rb +7 -0
- data/lib/generators/rolemodel/testing/rspec/templates/.rspec +1 -0
- data/lib/generators/rolemodel/turbo/form/README.md +1 -0
- data/lib/generators/rolemodel/turbo/form/form_generator.rb +6 -0
- data/lib/generators/rolemodel/turbo/modals/README.md +1 -0
- data/lib/generators/rolemodel/turbo/modals/modals_generator.rb +6 -1
- data/lib/generators/rolemodel/webpack/webpack_generator.rb +1 -0
- data/lib/rolemodel/generator_base.rb +10 -3
- data/lib/rolemodel/skills_helper.rb +28 -0
- data/lib/rolemodel/version.rb +1 -1
- data/lib/rolemodel/yarn.rb +5 -1
- data/lib/rolemodel-rails.rb +1 -1
- metadata +8 -2
- data/lib/generators/rolemodel/github/templates/instructions +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 30fe14227c2e8b6871de0ae74dd94bb58a204fd1d1db523cbd34c006f81b3d08
|
|
4
|
+
data.tar.gz: 03c31aa3406bb87521c205bfe4e60a21834710e81a6bc40672291bf5ce7760dd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 02b574434c6cd1ecc72ed48a8b64205a5ac3430a708eabaf1529f2cd49261ec6bf15257af4e04c06cf7eb21331e674cdba104ee3f3ebe2c2692bcd2b614968c1
|
|
7
|
+
data.tar.gz: 331e633f75a0b959c76a81d082f9a3f983a09838d5ff29258e544271e2ff98302bee2bace098c6f409136247bb6f7a248a1cacb433f34a046a2ec1fb798640dd
|
data/README.md
CHANGED
|
@@ -110,6 +110,18 @@ bin/rails g
|
|
|
110
110
|
* [Tom Select](./lib/generators/rolemodel/tom_select)
|
|
111
111
|
* [Lograge](./lib/generators/rolemodel/lograge)
|
|
112
112
|
|
|
113
|
+
## Agent Skills
|
|
114
|
+
|
|
115
|
+
Generators that leave behind conventions a coding agent needs to follow also install the matching skill from [RoleModel/skills](https://github.com/RoleModel/skills) with [`npx skills`](https://github.com/vercel-labs/skills), without prompting. Skills land in `.agents/skills` (read by Copilot and Codex) and are symlinked into `.claude/skills`, and `skills-lock.json` records what was installed so `npx skills update` can refresh them. If you've picked agents in the skills CLI before, generators install for those agents instead of Claude Code, GitHub Copilot, and Codex.
|
|
116
|
+
|
|
117
|
+
| Generator | Skill |
|
|
118
|
+
|---|---|
|
|
119
|
+
| `rolemodel:optics:base` | `optics-context` |
|
|
120
|
+
| `rolemodel:testing:rspec` | `tdd` |
|
|
121
|
+
| `rolemodel:turbo:modals` | `turbo-modals` |
|
|
122
|
+
| `rolemodel:turbo:form` | `dynamic-forms` |
|
|
123
|
+
| `rolemodel:soft_destroyable` | `soft-destroyable` |
|
|
124
|
+
|
|
113
125
|
## Utilities
|
|
114
126
|
|
|
115
127
|
### `Rolemodel::Utility::TaskTools`
|
|
@@ -17,7 +17,8 @@ app you can push straight to Heroku right after generation.
|
|
|
17
17
|
- [Webpack](../webpack) — Webpack v5 for JS and CSS
|
|
18
18
|
- [Sentry](../sentry) — error monitoring for Ruby and JavaScript
|
|
19
19
|
- [Slim](../slim) — Slim templates
|
|
20
|
-
- [Optics](../optics) — Optics design system
|
|
20
|
+
- [Optics](../optics) — Optics design system (pass an icon library flag such as
|
|
21
|
+
`--material` to choose it up front; otherwise the icons generator asks)
|
|
21
22
|
- [Testing](../testing) — RSpec, FactoryBot, parallel_tests, TestProf
|
|
22
23
|
(pass `--js-runner` to include jasmine-playwright-runner)
|
|
23
24
|
- [SimpleForm](../simple_form) — SimpleForm with our configuration
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
require_relative '../optics/icons/icon_library_options'
|
|
2
|
+
|
|
1
3
|
module Rolemodel
|
|
2
4
|
class CoreSetupGenerator < ::Rolemodel::GeneratorBase
|
|
5
|
+
include Optics::IconLibraryOptions
|
|
6
|
+
|
|
3
7
|
class_option :skip_deployable, type: :boolean, default: false, desc: 'skip generators for app deployment (Heroku, Sentry, Lograge)'
|
|
4
8
|
|
|
5
9
|
def run_the_core_generators
|
|
6
10
|
generate 'rolemodel:slim'
|
|
7
11
|
generate 'rolemodel:webpack'
|
|
8
|
-
generate 'rolemodel:optics:all'
|
|
12
|
+
generate 'rolemodel:optics:all', *icon_library_flags
|
|
9
13
|
generate 'rolemodel:simple_form'
|
|
10
14
|
generate 'rolemodel:tom_select'
|
|
11
15
|
generate 'rolemodel:testing:all'
|
|
@@ -16,9 +16,5 @@ It doesn't need to be run first, but the parallel_tests generator must be run in
|
|
|
16
16
|
- Pull Request Template
|
|
17
17
|
- When you open a Pull Request in Github it will use the Markdown file as a [template](./templates/pull_request_template.md) for the content of the PR.
|
|
18
18
|
- Helpful for reminding collaborators to add specific details to the PR.
|
|
19
|
-
- Copilot Instructions
|
|
20
|
-
- Installed into `.github/instructions`, these are context-specific instructions for Copilot to help it give more accurate
|
|
21
|
-
and relevant results. These are a good starting point but they should be tweaked for your project's frameworks and
|
|
22
|
-
standards.
|
|
23
19
|
- Dependabot Configuration
|
|
24
20
|
- defines a set of rules that dependabot will use to keep your applications dependencies up-to-date on a weekly basis.
|
|
@@ -3,10 +3,6 @@
|
|
|
3
3
|
module Rolemodel
|
|
4
4
|
class GithubGenerator < GeneratorBase
|
|
5
5
|
GITHUB_ACTIONS_REPO = 'https://github.com/RoleModel/actions.git'
|
|
6
|
-
# Files which are both used by the gem source and copied to the target app without modification
|
|
7
|
-
# are placed in the `.github` folder at the top level of this repository. This folder is then
|
|
8
|
-
# symlinked to the `templates` folder relative to this generator so they can still be copied over.
|
|
9
|
-
# Any files which are significantly different or not used by the gem source are just in `templates`.
|
|
10
6
|
source_root File.expand_path('templates', __dir__)
|
|
11
7
|
|
|
12
8
|
class_option :playwright, type: :boolean, default: true,
|
|
@@ -22,7 +18,6 @@ module Rolemodel
|
|
|
22
18
|
end
|
|
23
19
|
|
|
24
20
|
def install_github_config
|
|
25
|
-
directory 'instructions', '.github/instructions'
|
|
26
21
|
directory 'workflows', '.github/workflows', force: true
|
|
27
22
|
template 'pull_request_template.md', '.github/pull_request_template.md'
|
|
28
23
|
end
|
|
@@ -24,12 +24,16 @@ go. Ask the user questions **one at a time**.
|
|
|
24
24
|
|
|
25
25
|
## Phase 0: Preflight
|
|
26
26
|
|
|
27
|
-
Run these checks before touching anything
|
|
28
|
-
fail:
|
|
29
|
-
|
|
30
|
-
1. `
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
Run these checks before touching anything (creating a missing GitHub repo is the one
|
|
28
|
+
exception). Stop and tell the user how to fix any that fail:
|
|
29
|
+
|
|
30
|
+
1. `gh auth status` — GitHub CLI authenticated.
|
|
31
|
+
2. `git remote get-url origin` — must be a GitHub repo. A brand-new app has no `origin` yet:
|
|
32
|
+
offer to create one, confirming the name (default: the app directory's name) and that it
|
|
33
|
+
should be private in the RoleModel org, then
|
|
34
|
+
`gh repo create RoleModel/<name> --private --source . --remote origin --push`.
|
|
35
|
+
Derive `REPO_NAME` from `gh repo view --json name -q .name` (fallback: basename of the
|
|
36
|
+
origin URL).
|
|
33
37
|
3. `heroku auth:whoami` — Heroku CLI installed and logged in.
|
|
34
38
|
4. Sentry MCP tools available (try listing organizations). If no Sentry MCP server is
|
|
35
39
|
connected, ask the user to add/authorize the Sentry MCP server
|
|
@@ -41,10 +45,8 @@ fail:
|
|
|
41
45
|
- reads `Rails.application.credentials...` → **credentials mode**
|
|
42
46
|
7. Deploy-readiness (recent `rolemodel-rails` bakes these in; older apps need the manual
|
|
43
47
|
fixes noted in each phase). Confirm the generated app already has:
|
|
44
|
-
- `terser-webpack-plugin` in `package.json` (webpack config imports it)
|
|
45
48
|
- custom cops under `.rubocop/cops/`, not `lib/cops/` (the latter crashes prod boot)
|
|
46
49
|
- `config/initializers/lograge.rb` uses `controller.try(:current_user)`
|
|
47
|
-
- `config/database.yml` `production:` block uses `url: <%= ENV["DATABASE_URL"] %>`
|
|
48
50
|
- a `ruby` directive in the `Gemfile` (so the version reaches `Gemfile.lock`)
|
|
49
51
|
- `stackprof` in the `Gemfile` (Sentry profiling)
|
|
50
52
|
If any are missing, apply the fix inline and note the app predates the generator update.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Cops
|
|
4
|
+
# Custom Cop to Ensure Form Error Response Statuses
|
|
5
|
+
#
|
|
6
|
+
# There are three levels of matching here:
|
|
7
|
+
# Methods (def on_if)
|
|
8
|
+
# This scans code and only stops on the method specified.
|
|
9
|
+
# E.G. `on_if` will only move into the below checks when it encounters an if statement.
|
|
10
|
+
#
|
|
11
|
+
# Node matcher (def_node_matcher :form_error)
|
|
12
|
+
# This scans the block of code (in this case, the else branch of the if block)
|
|
13
|
+
# using AST (Abstract Tree Syntax) to match certain patterns
|
|
14
|
+
#
|
|
15
|
+
# Regex
|
|
16
|
+
# This checks the specific matching line to ensure it meets our expectations
|
|
17
|
+
class FormErrorResponse < RuboCop::Cop::Base
|
|
18
|
+
extend RuboCop::Cop::AutoCorrector
|
|
19
|
+
|
|
20
|
+
def self.rack_version
|
|
21
|
+
Gem.loaded_specs['rack'].version
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.http_status
|
|
25
|
+
if rack_version >= '3.1'
|
|
26
|
+
:unprocessable_content
|
|
27
|
+
else
|
|
28
|
+
:unprocessable_entity
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Match code in the else branch that either: is the only line and looks like `render :something, ...`
|
|
33
|
+
# or is not the first line and looks like the same.
|
|
34
|
+
def_node_matcher :form_error, <<~PATTERN
|
|
35
|
+
{(... $(send nil? :render (:sym _) ...)) | $(send nil? :render (:sym _) ...)}
|
|
36
|
+
PATTERN
|
|
37
|
+
|
|
38
|
+
MSG = "Use status: :#{self.http_status} for invalid form requests."
|
|
39
|
+
|
|
40
|
+
# Ensure the render is returning the correct status, otherwise add the offense
|
|
41
|
+
STATUS_PAIR = /\(pair\s+\(sym :status\)\s+\(sym :#{self.http_status}\)\)/m
|
|
42
|
+
|
|
43
|
+
# Only check within if blocks
|
|
44
|
+
def on_if(node)
|
|
45
|
+
form_error(node.else_branch) do |name|
|
|
46
|
+
next if name.to_s.match?(STATUS_PAIR)
|
|
47
|
+
|
|
48
|
+
add_offense(name) do |corrector|
|
|
49
|
+
corrector.insert_after(name, ", status: :#{self.class.http_status}")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rubocop'
|
|
4
|
+
|
|
5
|
+
module Cops
|
|
6
|
+
# Detect occurences of the chrome tag in specs, and warn and remove them.
|
|
7
|
+
class NoChromeTag < RuboCop::Cop::Base
|
|
8
|
+
include RuboCop::Cop::RangeHelp
|
|
9
|
+
extend RuboCop::Cop::AutoCorrector
|
|
10
|
+
|
|
11
|
+
MSG = 'The :chrome tag is only for testing, and should not be checked into the repository.'
|
|
12
|
+
RESTRICT_ON_SEND = %i[describe context it feature scenario].freeze
|
|
13
|
+
|
|
14
|
+
def on_send(node) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
|
15
|
+
node.arguments.each do |a|
|
|
16
|
+
if a.sym_type? && a.value == :chrome
|
|
17
|
+
range = range_with_surrounding_comma(a.source_range)
|
|
18
|
+
add_offense(range) do |corrector|
|
|
19
|
+
corrector.replace(range, '')
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
next unless a.hash_type?
|
|
24
|
+
|
|
25
|
+
a.pairs.each do |pair|
|
|
26
|
+
next unless pair.key.value == :chrome
|
|
27
|
+
|
|
28
|
+
range = range_with_surrounding_comma(pair.source_range)
|
|
29
|
+
add_offense(range) do |corrector|
|
|
30
|
+
corrector.replace(range, '')
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def range_with_surrounding_comma(source_range)
|
|
37
|
+
buffer = source_range.source_buffer
|
|
38
|
+
src = buffer.source
|
|
39
|
+
end_pos = source_range.end_pos
|
|
40
|
+
comma_index = src[...end_pos].rindex(/\s*,\s*/)
|
|
41
|
+
|
|
42
|
+
Parser::Source::Range.new(buffer, comma_index, end_pos)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
require:
|
|
2
|
+
- ./.rubocop/cops/form_error_response.rb
|
|
3
|
+
- ./.rubocop/cops/no_chrome_tag.rb
|
|
4
|
+
plugins:
|
|
5
|
+
- rubocop-rails
|
|
6
|
+
|
|
7
|
+
AllCops:
|
|
8
|
+
Exclude:
|
|
9
|
+
- bin/**/*
|
|
10
|
+
- db/**/*
|
|
11
|
+
- vendor/**/*
|
|
12
|
+
- config/**/*
|
|
13
|
+
- node_modules/**/*
|
|
14
|
+
- tmp/**/*
|
|
15
|
+
NewCops: enable
|
|
16
|
+
|
|
17
|
+
Metrics:
|
|
18
|
+
Severity: refactor
|
|
19
|
+
|
|
20
|
+
# RSpec tests and rake tasks are expected to have
|
|
21
|
+
# large blocks, so exclude them from this cop.
|
|
22
|
+
Metrics/BlockLength:
|
|
23
|
+
Exclude:
|
|
24
|
+
- 'Rakefile'
|
|
25
|
+
- '**/*.rake'
|
|
26
|
+
- 'spec/**/*.rb'
|
|
27
|
+
|
|
28
|
+
# Hard to make this pass always and want to keep flexibility
|
|
29
|
+
Layout/ArrayAlignment:
|
|
30
|
+
Enabled: false
|
|
31
|
+
|
|
32
|
+
# Best Practices for readability
|
|
33
|
+
Layout:
|
|
34
|
+
Severity: refactor
|
|
35
|
+
|
|
36
|
+
Layout/FirstArrayElementIndentation:
|
|
37
|
+
EnforcedStyle: consistent
|
|
38
|
+
|
|
39
|
+
Layout/FirstHashElementIndentation:
|
|
40
|
+
EnforcedStyle: consistent
|
|
41
|
+
|
|
42
|
+
Lint/UnusedMethodArgument:
|
|
43
|
+
Severity: refactor
|
|
44
|
+
AutoCorrect: false
|
|
45
|
+
|
|
46
|
+
Lint/UnusedBlockArgument:
|
|
47
|
+
Severity: refactor
|
|
48
|
+
AutoCorrect: false
|
|
49
|
+
|
|
50
|
+
Lint/UselessAssignment:
|
|
51
|
+
Severity: refactor
|
|
52
|
+
AutoCorrect: false
|
|
53
|
+
|
|
54
|
+
Lint/UnderscorePrefixedVariableName:
|
|
55
|
+
Enabled: false
|
|
56
|
+
|
|
57
|
+
Lint/Loop:
|
|
58
|
+
Enabled: false
|
|
59
|
+
|
|
60
|
+
Lint/SuppressedException:
|
|
61
|
+
Enabled: false
|
|
62
|
+
|
|
63
|
+
Style:
|
|
64
|
+
Severity: refactor
|
|
65
|
+
|
|
66
|
+
# It is ok to use inject at times
|
|
67
|
+
Style/EachWithObject:
|
|
68
|
+
Enabled: false
|
|
69
|
+
|
|
70
|
+
Style/Documentation:
|
|
71
|
+
Enabled: false
|
|
72
|
+
|
|
73
|
+
Cops/NoChromeTag:
|
|
74
|
+
AutoCorrect: contextual
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
require_relative 'icons/icon_library_options'
|
|
2
|
+
|
|
1
3
|
module Rolemodel
|
|
2
4
|
module Optics
|
|
3
5
|
class AllGenerator < Rolemodel::GeneratorBase
|
|
6
|
+
include IconLibraryOptions
|
|
7
|
+
|
|
4
8
|
source_root File.expand_path('templates', __dir__)
|
|
5
9
|
|
|
6
10
|
def run_all_the_generators
|
|
7
11
|
generate 'rolemodel:optics:base'
|
|
8
|
-
generate 'rolemodel:optics:icons'
|
|
12
|
+
generate 'rolemodel:optics:icons', *icon_library_flags
|
|
9
13
|
end
|
|
10
14
|
end
|
|
11
15
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'icons_generator'
|
|
4
|
+
|
|
5
|
+
module Rolemodel
|
|
6
|
+
module Optics
|
|
7
|
+
# For generators that run optics:icons: accept its icon library flag (e.g. --material) and pass
|
|
8
|
+
# it along, so the icons generator doesn't stop to ask.
|
|
9
|
+
module IconLibraryOptions
|
|
10
|
+
LIBRARIES = IconsGenerator::SUPPORTED_LIBRARIES.keys.freeze
|
|
11
|
+
|
|
12
|
+
def self.included(base)
|
|
13
|
+
base.class_exclusive do
|
|
14
|
+
LIBRARIES.each { base.class_option it, type: :boolean, lazy_default: false, desc: "Use #{it} icon library" }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def icon_library_flags = LIBRARIES.select { options[it] }.map { "--#{it}" }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -42,7 +42,7 @@ module Rolemodel
|
|
|
42
42
|
private
|
|
43
43
|
|
|
44
44
|
def capture_user_selection
|
|
45
|
-
options.slice(*SUPPORTED_LIBRARIES.keys).invert[true] ||
|
|
45
|
+
options.slice(*SUPPORTED_LIBRARIES.keys).invert[true] || ask_or_default(
|
|
46
46
|
'What icon library would you like to add?',
|
|
47
47
|
default: SUPPORTED_LIBRARIES.keys.first.to_s,
|
|
48
48
|
limited_to: SUPPORTED_LIBRARIES.keys.map(&:to_s)
|
|
@@ -5,7 +5,7 @@ module Rolemodel
|
|
|
5
5
|
def install_readme
|
|
6
6
|
@project_name = Rails.application.class.try(:parent_name) || Rails.application.class.module_parent_name
|
|
7
7
|
@project = @project_name.underscore
|
|
8
|
-
template 'README.md.erb', 'README.md'
|
|
8
|
+
template 'README.md.erb', 'README.md', force: true
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
end
|
|
@@ -4,5 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
* Ruby module for SoftDestroyable
|
|
6
6
|
* Shared example file for testing your classes
|
|
7
|
+
* The [`soft-destroyable`](https://github.com/RoleModel/skills/tree/main/skills/soft-destroyable) agent skill, installed into `.agents/skills`
|
|
7
8
|
|
|
8
9
|
Adds module for soft destroyable of ActiveRecord classes with configurable cascading of association data
|
|
@@ -9,5 +9,11 @@ module Rolemodel
|
|
|
9
9
|
def add_shared_example
|
|
10
10
|
copy_file 'soft_destroyable_behavior.rb', 'spec/support/shared_examples/soft_destroyable_behavior.rb'
|
|
11
11
|
end
|
|
12
|
+
|
|
13
|
+
def install_agent_skill
|
|
14
|
+
say 'Installing the soft-destroyable agent skill', :green
|
|
15
|
+
|
|
16
|
+
install_skill 'soft-destroyable'
|
|
17
|
+
end
|
|
12
18
|
end
|
|
13
19
|
end
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
## What you get
|
|
4
4
|
|
|
5
|
+
* The [`tdd`](https://github.com/RoleModel/skills/tree/main/skills/tdd) agent skill, installed into `.agents/skills`
|
|
6
|
+
|
|
5
7
|
### RSpec Default
|
|
6
8
|
|
|
7
9
|
Based of rspec-rails install generator. Assume all configuration will be placed in `spec/support/*.rb`
|
|
@@ -34,10 +34,17 @@ module Rolemodel
|
|
|
34
34
|
def add_spec_files
|
|
35
35
|
say 'Adding Support Files', :green
|
|
36
36
|
|
|
37
|
+
template '.rspec', '.rspec'
|
|
37
38
|
directory 'spec'
|
|
38
39
|
|
|
39
40
|
append_file '.gitignore', 'spec/examples.txt'
|
|
40
41
|
end
|
|
42
|
+
|
|
43
|
+
def install_agent_skill
|
|
44
|
+
say 'Installing the tdd agent skill', :green
|
|
45
|
+
|
|
46
|
+
install_skill 'tdd'
|
|
47
|
+
end
|
|
41
48
|
end
|
|
42
49
|
end
|
|
43
50
|
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
--require spec_helper
|
|
@@ -5,5 +5,6 @@ Enable dynamic form interactions in new/existing rails apps with the [turbo_form
|
|
|
5
5
|
## What you get
|
|
6
6
|
|
|
7
7
|
- the `turbo_form` gem, set up by its `turbo_form:install` generator
|
|
8
|
+
- the [`dynamic-forms`](https://github.com/RoleModel/skills/tree/main/skills/dynamic-forms) agent skill, installed into `.agents/skills`
|
|
8
9
|
|
|
9
10
|
Draw the `:turbo_form` route concern on each resource with a dynamic form. See the gem's README for usage.
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
* RoleModel Modal pattern integration. See Notes below for usage documentation.
|
|
13
13
|
* RoleModel Panel pattern integration, if run with the `--panels` flag.
|
|
14
|
+
* The [`turbo-modals`](https://github.com/RoleModel/skills/tree/main/skills/turbo-modals) agent skill, installed into `.agents/skills`
|
|
14
15
|
|
|
15
16
|
> [!IMPORTANT]
|
|
16
17
|
> This generator does not provide RoleModel Panel integration, unless run with the `--panels` flag.
|
|
@@ -3,13 +3,20 @@
|
|
|
3
3
|
require 'rails/generators'
|
|
4
4
|
require 'rails/generators/bundle_helper'
|
|
5
5
|
require_relative 'replace_content_helper'
|
|
6
|
+
require_relative 'skills_helper'
|
|
6
7
|
require 'rolemodel/yarn'
|
|
7
8
|
|
|
8
9
|
module Rolemodel
|
|
9
10
|
class GeneratorBase < ::Rails::Generators::Base
|
|
10
|
-
include ::Rails::Generators::BundleHelper, ReplaceContentHelper
|
|
11
|
+
include ::Rails::Generators::BundleHelper, ReplaceContentHelper, SkillsHelper
|
|
11
12
|
|
|
12
13
|
private
|
|
14
|
+
|
|
15
|
+
# Thor's ask loops forever on EOF when limited_to is set, so only prompt when someone can answer.
|
|
16
|
+
def ask_or_default(statement, default:, **)
|
|
17
|
+
$stdin.tty? ? ask(statement, default:, **) : default
|
|
18
|
+
end
|
|
19
|
+
|
|
13
20
|
# based on https://github.com/rails/rails/blob/main/railties/lib/rails/generators/app_base.rb#L713
|
|
14
21
|
def run_bundle
|
|
15
22
|
bundle_command("install --quiet", "BUNDLE_IGNORE_MESSAGES" => "1")
|
|
@@ -22,13 +29,13 @@ module Rolemodel
|
|
|
22
29
|
end
|
|
23
30
|
|
|
24
31
|
# Enable Corepack and pin the project to Yarn 4+ before running any `yarn`
|
|
25
|
-
# command.
|
|
32
|
+
# command. Args/opts are passed explicitly: otherwise Thor forwards this
|
|
26
33
|
# generator's own CLI args (e.g. the test harness's --skip-bundle
|
|
27
34
|
# --skip-bootsnap) into Rolemodel::Yarn#setup, which takes none and raises
|
|
28
35
|
# Thor::InvocationError.
|
|
29
36
|
def ensure_yarn
|
|
30
37
|
return if Rails.root.join(destination_root, '.yarnrc.yml').exist?
|
|
31
|
-
invoke 'rolemodel:yarn:setup', [],
|
|
38
|
+
invoke 'rolemodel:yarn:setup', [], options.slice(:pretend)
|
|
32
39
|
end
|
|
33
40
|
|
|
34
41
|
def application_stylesheet_path
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Rolemodel
|
|
6
|
+
module SkillsHelper
|
|
7
|
+
SKILLS_REPO = 'RoleModel/skills'
|
|
8
|
+
DEFAULT_SKILL_AGENTS = %w[claude-code github-copilot codex].freeze
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def install_skill(name)
|
|
13
|
+
inside('.') { run "npx -y skills@latest add #{SKILLS_REPO} --skill #{name} --agent #{skill_agents.join(' ')} -y" }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Agents the user last picked in the skills CLI; it only offers them as defaults interactively.
|
|
17
|
+
def skill_agents
|
|
18
|
+
JSON.parse(File.read(skills_state_path))['lastSelectedAgents'].presence || DEFAULT_SKILL_AGENTS
|
|
19
|
+
rescue Errno::ENOENT, JSON::ParserError
|
|
20
|
+
DEFAULT_SKILL_AGENTS
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def skills_state_path
|
|
24
|
+
state_home = ENV['XDG_STATE_HOME']
|
|
25
|
+
state_home ? File.join(state_home, 'skills/.skill-lock.json') : File.expand_path('~/.agents/.skill-lock.json')
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/rolemodel/version.rb
CHANGED
data/lib/rolemodel/yarn.rb
CHANGED
|
@@ -16,7 +16,8 @@ module Rolemodel
|
|
|
16
16
|
|
|
17
17
|
yes! 'yarn set version stable'
|
|
18
18
|
yes! 'corepack enable'
|
|
19
|
-
|
|
19
|
+
# `yarn init` replaces an existing package.json, dropping the scripts and packages Rails added.
|
|
20
|
+
yes! 'yarn init' unless File.exist?(File.expand_path('package.json', destination_root))
|
|
20
21
|
|
|
21
22
|
ignore_yarn_install_state
|
|
22
23
|
end
|
|
@@ -32,6 +33,9 @@ module Rolemodel
|
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
def yes!(command)
|
|
36
|
+
say_status :run, command
|
|
37
|
+
return if options[:pretend]
|
|
38
|
+
|
|
35
39
|
Open3.popen3(command) do |stdin, stdout, stderr, wait_thr|
|
|
36
40
|
stdin.puts 'y'
|
|
37
41
|
stdin.close
|
data/lib/rolemodel-rails.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rolemodel-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- RoleModel Software Inc
|
|
@@ -203,7 +203,6 @@ files:
|
|
|
203
203
|
- lib/generators/rolemodel/github/github_generator.rb
|
|
204
204
|
- lib/generators/rolemodel/github/templates/CODEOWNERS
|
|
205
205
|
- lib/generators/rolemodel/github/templates/dependabot.yml
|
|
206
|
-
- lib/generators/rolemodel/github/templates/instructions
|
|
207
206
|
- lib/generators/rolemodel/github/templates/pull_request_template.md
|
|
208
207
|
- lib/generators/rolemodel/github/templates/workflows/ci.yml.tt
|
|
209
208
|
- lib/generators/rolemodel/github/templates/workflows/deploy-production.yml
|
|
@@ -239,6 +238,9 @@ files:
|
|
|
239
238
|
- lib/generators/rolemodel/linters/rubocop/README.md
|
|
240
239
|
- lib/generators/rolemodel/linters/rubocop/USAGE
|
|
241
240
|
- lib/generators/rolemodel/linters/rubocop/rubocop_generator.rb
|
|
241
|
+
- lib/generators/rolemodel/linters/rubocop/templates/.rubocop.yml
|
|
242
|
+
- lib/generators/rolemodel/linters/rubocop/templates/.rubocop/cops/form_error_response.rb
|
|
243
|
+
- lib/generators/rolemodel/linters/rubocop/templates/.rubocop/cops/no_chrome_tag.rb
|
|
242
244
|
- lib/generators/rolemodel/lograge/README.md
|
|
243
245
|
- lib/generators/rolemodel/lograge/USAGE
|
|
244
246
|
- lib/generators/rolemodel/lograge/lograge_generator.rb
|
|
@@ -262,6 +264,7 @@ files:
|
|
|
262
264
|
- lib/generators/rolemodel/optics/base/base_generator.rb
|
|
263
265
|
- lib/generators/rolemodel/optics/icons/README.md
|
|
264
266
|
- lib/generators/rolemodel/optics/icons/USAGE
|
|
267
|
+
- lib/generators/rolemodel/optics/icons/icon_library_options.rb
|
|
265
268
|
- lib/generators/rolemodel/optics/icons/icons_generator.rb
|
|
266
269
|
- lib/generators/rolemodel/optics/icons/templates/app/helpers/icon_helper.rb.tt
|
|
267
270
|
- lib/generators/rolemodel/react/README.md
|
|
@@ -371,9 +374,11 @@ files:
|
|
|
371
374
|
- lib/generators/rolemodel/testing/parallel_tests/README.md
|
|
372
375
|
- lib/generators/rolemodel/testing/parallel_tests/USAGE
|
|
373
376
|
- lib/generators/rolemodel/testing/parallel_tests/parallel_tests_generator.rb
|
|
377
|
+
- lib/generators/rolemodel/testing/parallel_tests/templates/.rspec_parallel
|
|
374
378
|
- lib/generators/rolemodel/testing/rspec/README.md
|
|
375
379
|
- lib/generators/rolemodel/testing/rspec/USAGE
|
|
376
380
|
- lib/generators/rolemodel/testing/rspec/rspec_generator.rb
|
|
381
|
+
- lib/generators/rolemodel/testing/rspec/templates/.rspec
|
|
377
382
|
- lib/generators/rolemodel/testing/rspec/templates/spec/rails_helper.rb.tt
|
|
378
383
|
- lib/generators/rolemodel/testing/rspec/templates/spec/spec_helper.rb.tt
|
|
379
384
|
- lib/generators/rolemodel/testing/rspec/templates/spec/support/capybara_config.rb.tt
|
|
@@ -455,6 +460,7 @@ files:
|
|
|
455
460
|
- lib/rolemodel/optics/tabler_icon_builder.rb
|
|
456
461
|
- lib/rolemodel/replace_content_helper.rb
|
|
457
462
|
- lib/rolemodel/resource_for/controller_extension.rb
|
|
463
|
+
- lib/rolemodel/skills_helper.rb
|
|
458
464
|
- lib/rolemodel/utility.rb
|
|
459
465
|
- lib/rolemodel/utility/task_tools.rb
|
|
460
466
|
- lib/rolemodel/version.rb
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
../../../../../.github/instructions
|