create-addon
Scaffold a new Dradis addon gem with the correct boilerplate structure. Ask questions to determine the addon type, name, description, and capabilities, then generate all required files in a new directory.
소스 정보
- 저장소
- dradis/dradis-ce
- 최근 소스 활동
- 2026년 3월 16일 16:07
- 감지된 SKILL.md 언어
- 영어
- 스타
- 845
- 포크
- 228
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
SKILL.md 표시 중
SKILL.md
소스 지침 · 읽기 전용 미리보기- name
- create-addon
- description
- Scaffold a new Dradis addon gem with the correct boilerplate structure. Ask questions to determine the addon type, name, description, and capabilities, then generate all required files in a new directory.
You are scaffolding a new Dradis addon. Follow these steps exactly.
## Step 1 — Gather information
Ask the user the following questions one group at a time. Keep the tone friendly and jargon-free. Wait for all answers in a group before moving to the next group.
**Group 1 — The basics:**
Ask these four questions together:
1. **What would you like to call your addon?** This can be a tool name, a product name, or just a short descriptive name. For example: "Custom Importer", "Custom Exporter", "ACME Risk Matrix". It will be used to name the addon directory and files.
2. **Describe what your addon does in one sentence.** For example: "Imports findings from our internal scanning tool into Dradis" or "Displays all project findings in a custom risk matrix table tailored to ACME's scoring methodology."
3. **Your name** — this will appear in the addon's metadata.
4. **Your email address** — also used in the addon's metadata.
---
**Group 2 — What should your addon do?**
Ask this as a simple choice. Frame it conversationally:
> Dradis addons can do one or more of the following things. Which fits what you're building?
>
> **Option A — Import files**
> Your addon will let users upload a file — any kind of file — and Dradis will read it and turn the contents into items in the project (like issues, notes, or evidence). Choose this if you have data in a file that you want to bring into Dradis automatically.
>
> **Option B — Export / generate reports**
> Your addon will take the data already in a Dradis project and produce an output file from it — for example, a custom HTML report, a CSV export, or any other format your team needs. Choose this if you want to generate something *from* Dradis.
>
> **Option C — Add new pages to Dradis**
> Your addon will add its own screens or interfaces inside the Dradis web app — for example, a custom risk matrix table, a team-specific findings view, or a bespoke workflow that only makes sense for your organisation. Choose this if you're building something that needs its own UI.
>
> **Option D — A combination**
> Mix and match any of the above. Just tell us which ones apply.
## Step 2 — Confirm before creating
Silently derive the following from the addon name:
- `<slug>` — lowercase, hyphenated (e.g. `custom-importer`, `acme-risk-matrix`)
- `<module_name>` — CamelCase (e.g. `CustomImporter`, `AcmeRiskMatrix`)
- `<plugin_name>` — underscored (e.g. `custom_importer`, `acme_risk_matrix`)
Then confirm with the user using only the details they gave you:
> Here's what I'll create:
>
> - **Name:** <addon name they provided>
> - **Description:** <description they provided>
> - **Type:** <what they chose — Import, Export, Custom pages, or a combination>
> - **Location:** `../plugins/dradis-<slug>/`
>
> Shall I go ahead?
## Step 3 — Generate files
Create all files inside `../plugins/dradis-<slug>/` (a sibling directory to `dradis-ce`, under a `plugins/` folder). Generate every file listed below with correct content based on the answers.
---
### Files to generate
#### `dradis-<slug>.gemspec`
```ruby
$:.push File.expand_path('../lib', __FILE__)
require 'dradis/plugins/<slug>/version'
version = Dradis::Plugins::<module_name>::VERSION::STRING
Gem::Specification.new do |spec|
spec.platform = Gem::Platform::RUBY
spec.name = 'dradis-<slug>'
spec.version = version
spec.summary = '<description>'
spec.description = '<description>'
spec.license = 'GPL-2'
spec.authors = ['<author_name>']
spec.email = ['<author_email>']
spec.homepage = 'https://dradis.com'
spec.files = `git ls-files`.split($\)
spec.executables = spec.files.grep(%r{^bin/}).map { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ['lib']
spec.add_dependency 'dradis-plugins', '~> 4.0'
spec.add_development_dependency 'bundler', '~> 2.0'
spec.add_development_dependency 'combustion', '~> 1.3'
spec.add_development_dependency 'rake'
spec.add_development_dependency 'rspec-rails'
end
```
#### `Gemfile`
```ruby
source 'https://rubygems.org'
gemspec
```
#### `Rakefile`
```ruby
require 'bundler/gem_tasks'
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec)
task default: :spec
```
#### `lib/dradis-<slug>.rb`
```ruby
require 'dradis-plugins'
require 'dradis/plugins/<slug>'
```
#### `lib/dradis/plugins/<slug>.rb`
```ruby
module Dradis::Plugins::<module_name>
PLUGIN_NAME = :<plugin_name>
end
require 'dradis/plugins/<slug>/engine'
require 'dradis/plugins/<slug>/gem_version'
require 'dradis/plugins/<slug>/version'
```
If upload addon, also add:
```ruby
require 'dradis/plugins/<slug>/field_processor'
require 'dradis/plugins/<slug>/importer'
require 'dradis/plugins/<slug>/mapping'
```
#### `lib/dradis/plugins/<slug>/engine.rb`
The `provides` line reflects the user's chosen option(s):
- Import only: `provides :upload`
- Export only: `provides :export`
- Custom pages only: `provides :addon`
- Any combination: `provides :upload, :export` / `provides :upload, :addon` / etc.
```ruby
module Dradis::Plugins::<module_name>
class Engine < ::Rails::Engine
isolate_namespace Dradis::Plugins::<module_name>
include ::Dradis::Plugins::Base
description '<description>'
provides :<capability> # one or more of: :upload, :export, :addon
end
end
```
If `provides :addon` or `provides :export` is included, add an initializer block to mount the engine.
Use `routes.append` (not `prepend`) so the engine never overrides the main app's routes:
```ruby
initializer '<slug>.mount_engine' do
Rails.application.routes.append do
mount Dradis::Plugins::<module_name>::Engine => '/', as: :<plugin_name>
end
end
```
#### `lib/dradis/plugins/<slug>/version.rb`
```ruby
require_relative 'gem_version'
module Dradis
module Plugins
module <module_name>
module VERSION
MAJOR = 0
MINOR = 1
TINY = 0
PRE = nil
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
end
end
end
```
#### `lib/dradis/plugins/<slug>/gem_version.rb`
```ruby
module Dradis
module Plugins
module <module_name>
def self.gem_version
Gem::Version.new VERSION::STRING
end
end
end
end
```
#### `lib/dradis/plugins/<slug>/importer.rb` (upload addons only)
```ruby
module Dradis::Plugins::<module_name>
class Importer < Dradis::Plugins::Upload::Importer
# Override the import method to process the uploaded file.
#
# The `params` hash includes:
# params[:file] - path to the uploaded file (a Tempfile or String path)
# params[:project] - the current Dradis project
#
# Use content_service to create nodes, issues, and evidence:
# content_service.create_node(label: 'hostname')
# content_service.create_note(node: node, text: '#[Title]#\nValue')
# content_service.create_issue(text: '#[Title]#\nValue')
# content_service.create_evidence(issue: issue, node: node, content: '#[Port]#\n443')
#
# Use mapping_service to apply field mappings from templates:
# mapping_service.apply_mapping(source: :<entity>, data: object)
def import(params = {})
file_content = File.read(params[:file])
# TODO: parse file_content and iterate over findings
logger.info { 'Done.' }
end
end
end
```
#### `lib/dradis/plugins/<slug>/field_processor.rb` (upload addons only)
```ruby
module Dradis::Plugins::<module_name>
class FieldProcessor < Dradis::Plugins::Upload::FieldProcessor
# Map a Liquid template field name to a value from the source data object.
#
# `params[:data]` is the object you passed to mapping_service.apply_mapping.
# `params[:field]` is the field name from the template (e.g. '<plugin_name>[entity.attribute]').
#
# Example:
# when '<plugin_name>[finding.title]' then object.title
def value(params = {})
_object = params[:data]
_field = params[:field]
case params[:field]
# TODO: add field mappings here
# when '<plugin_name>[finding.title]' then object.title
end
end
end
end
```
#### `lib/dradis/plugins/<slug>/mapping.rb` (upload addons only)
```ruby
module Dradis::Plugins::<module_name>
module Mapping
# DEFAULT_MAPPING defines the default Liquid templates used when importing.
# Keys are entity types (matching your importer), values are field-to-template maps.
# Template variables use the syntax: {{ <plugin_name>[entity.attribute] }}
DEFAULT_MAPPING = {
issue: {
'Title' => '{{ <plugin_name>[issue.title] }}',
'Description' => '{{ <plugin_name>[issue.description] }}'
},
evidence: {
'Output' => '{{ <plugin_name>[evidence.output] }}'
}
}.freeze
SOURCE_FIELDS = {
issue: %w[
issue.title
issue.description
],
evidence: %w[
evidence.output
]
}.freeze
end
end
```
Adjust entity names and fields based on the user's answers about their data model.
#### `templates/` (upload addons only)
Create both sample files. Use the Dradis `#[FieldName]#` syntax.
**`templates/issue.sample`:**
```
#[Title]#
{{ <plugin_name>[issue.title] }}
#[Description]#
{{ <plugin_name>[issue.description] }}
```
**`templates/evidence.sample`:**
```
#[Output]#
{{ <plugin_name>[evidence.output] }}
```
#### `spec/spec_helper.rb`
```ruby
ENV['RAILS_ENV'] ||= 'test'
require 'combustion'
Combustion.initialize! :all
require 'rspec/rails'
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_host_groups
end
```
#### `spec/dradis/plugins/<slug>/importer_spec.rb` (upload addons only)
```ruby
require 'spec_helper'
describe Dradis::Plugins::<module_name>::Importer do
pending 'add importer specs here'
end
```
#### `spec/fixtures/files/.gitkeep`
Empty placeholder file so the fixtures directory is tracked.
#### `.gitignore`
```
*.gem
*.rbc
.bundle
.config
.yardoc
Gemfile.lock
InstalledFiles
_yardoc/
coverage/
doc/
lib/bundler/man/
pkg/
rdoc/
spec/reports/
test/tmp/
test/version_tmp/
tmp/
```
#### `LICENSE`
```
Copyright (c) <year> <author_name>
This software is open source and available under the GNU General Public License
version 2 (GPL-2). See https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
```
#### `CHANGELOG.md`
```markdown
# Changelog
## [Unreleased]
### Added
- Initial release
```
#### `README.md`
```markdown
# dradis-<slug>
<description>
## Installation
Add to your Dradis `Gemfile`:
```ruby
gem 'dradis-<slug>'
```
Then run:
```
bundle install
```
## Usage
<!-- TODO: describe how to use this addon -->
GitHub에서 보기이 SKILL.md는 매우 커서 SkillsMP가 여기에는 첫 섹션만 미리 보여줍니다. GitHub에서 보기