Skip to content

plugin generator for creating a new plugin structure#150

Open
Michal-Koeckeis-Fresel wants to merge 11 commits intobunkerity:devfrom
Michal-Koeckeis-Fresel:template_generator
Open

plugin generator for creating a new plugin structure#150
Michal-Koeckeis-Fresel wants to merge 11 commits intobunkerity:devfrom
Michal-Koeckeis-Fresel:template_generator

Conversation

@Michal-Koeckeis-Fresel
Copy link
Copy Markdown

bash create_bunkerweb_plugin.sh -d "MYPLUGIN" --with-ui --with-jobs --with-configs --with-templates MYPLUGIN

@TheophileDiot
Copy link
Copy Markdown
Member

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 13, 2026

✅ Actions performed

Full review triggered.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 13, 2026

Plugin Generator + Complete Plugin Suite

This PR introduces a comprehensive plugin scaffold generator and six production-ready security plugins for BunkerWeb.

Template Area

templates/create_bunkerweb_plugin.sh (1649 lines)

  • New Bash script for generating BunkerWeb plugin skeletons
  • Accepts plugin name, description, version, execution order, stream mode, and optional feature flags (--with-ui, --with-jobs, --with-configs, --with-templates)
  • Generates standard plugin structure: plugin.json, Lua entrypoint, optional UI components (Flask + HTML), scheduled jobs, NGINX config templates, and custom configuration templates
  • Validates plugin names (alphanumeric, hyphens, underscores; max 50 chars) and numeric constraints (order 1–999)
  • Creates project-level and plugin-level README files
  • POSIX-compatible, designed for execution from templates directory

templates/README.md (446 lines)

  • Comprehensive documentation for the plugin generator
  • Details requirements, installation, command-line syntax, required/optional flags
  • Enumerates generated directory structure for base and optional components
  • Documents generated plugin features: logging, settings validation, endpoints, error handling, monitoring
  • Includes stream mode semantics, execution order ranges, validation rules, auto-generated documentation behaviour
  • Provides deployment integration examples for Docker and Linux, troubleshooting, best practices

Individual Plugins (Security-Critical)

ClamAV (v1.9)

  • Antivirus file scanning for uploaded files via ClamAV daemon
  • Stream mode: no; Settings: USE_CLAMAV (multisite), CLAMAV_HOST, CLAMAV_PORT, CLAMAV_TIMEOUT (global)
  • Includes UI component (ui/actions.py), comprehensive README, docs diagrams

Coraza (v1.9)

  • ModSecurity-compatible WAF (OpenResty client in Lua + standalone Go HTTP service in coraza/api/)
  • Stream mode: no; Settings: USE_CORAZA (multisite), CORAZA_API (global)
  • Coraza OpenResty client (coraza.lua) invokes external API service for request inspection
  • Includes Go service with Dockerfile, health checks, CRS integration script (crs.sh), configuration files
  • UI component provided

Discord (v1.9)

  • Alert webhook integration for Discord channels
  • Stream mode: yes; Settings: USE_DISCORD (multisite), DISCORD_WEBHOOK_URL, DISCORD_RETRY_IF_LIMITED (global)
  • UI component, README with examples

Slack (v1.9)

  • Alert webhook integration for Slack channels
  • Stream mode: partial; Settings: USE_SLACK (multisite), SLACK_WEBHOOK_URL, SLACK_RETRY_IF_LIMITED (global)
  • UI component, README with examples

VirusTotal (v1.9)

  • Antivirus file and IP scanning via VirusTotal API
  • Stream mode: partial; Settings: USE_VIRUSTOTAL (multisite), VIRUSTOTAL_API_KEY, VIRUSTOTAL_SCAN_FILE, etc. (global/multisite)
  • Includes extensive configuration for file/IP scanning, quota management, caching
  • UI component, README with API key setup

WebHook (v1.9)

  • Generic custom webhook alert delivery
  • Stream mode: yes; Settings: USE_WEBHOOK (multisite), WEBHOOK_URL, WEBHOOK_RETRY_IF_LIMITED (global)
  • UI component, README with deployment examples

Shared Areas

.github

  • Issue templates: bug_report.yml, feature_request.yml, new_plugin.yml
  • CodeQL configuration (codeql.yml)
  • Dependabot configuration (dependabot.yml)
  • CI/CD workflows: codeql.yml, tests.yml

.tests

  • Integration test scripts: clamav.sh, coraza.sh, virustotal.sh
  • Docker Compose configurations for each tested plugin
  • Utility functions (utils.sh), build/push helpers (build-push.sh, bw.sh)
  • JSON-to-Markdown conversion script (misc/json2md.py)

Root Directory

  • COMPATIBILITY.json: Tracks BunkerWeb core version compatibility with plugin collections (versions 0.3 through 1.8)
  • .pre-commit-config.yaml: Linting configuration (shellcheck, luacheck, stylua)
  • .shellcheckrc, stylua.toml, pyproject.toml: Code quality tool configs
  • .gitignore, .luacheckrc: Standard repo configs
  • CONTRIBUTING.md, SECURITY.md: Contribution and security policy documentation
  • README.md, LICENSE.md (AGPL-3.0), logo.png: Project-level documentation and branding

Version & Compatibility

  • All six plugins at version 1.9 (aligned, no drift)
  • COMPATIBILITY.json newly added; maps BunkerWeb core versions (1.8 latest) to supported plugin collection versions
  • No plugin.json schema changes; all plugins use standard format (id, name, description, version, stream, settings)

Security & Deployment Impact

  • High security impact: Introduction of WAF (Coraza), antivirus (ClamAV, VirusTotal), and alerting (Discord, Slack, WebHook) capabilities
  • Deployment: Docker and Linux integration guidance provided in plugin READMEs; Docker Compose examples in tests
  • Testing: Full integration tests added covering ClamAV, Coraza, and VirusTotal with Docker Compose; EICAR test file integration for antivirus validation
  • Documentation: Each plugin includes detailed README with configuration examples, multisite/global scope distinctions, stream mode behaviour
  • No user-visible behaviour changes to existing plugins (all additions are new)

Code Quality & Tooling

  • Pre-commit hooks configured for Bash (shellcheck), Lua (luacheck, stylua), and Python linting
  • CodeQL security scanning enabled
  • Dependabot dependency updates configured
  • Generator script is POSIX-compliant and robust (input validation, error handling, directory creation)

Walkthrough

Two new files introduce plugin scaffolding capabilities: a comprehensive Markdown guide documenting the plugin generation tool and a Bash script that automates BunkerWeb plugin template creation with conditional support for UI, scheduled jobs, and configuration components.

Changes

Cohort / File(s) Summary
Plugin Scaffolding Tool
templates/README.md, templates/create_bunkerweb_plugin.sh
Introduces plugin generation framework with detailed documentation and executable Bash script. Documentation enumerates usage syntax, CLI flags, generated directory structure, features, and deployment guidance. Script validates plugin names, parses options (description, version, output directory, execution order, stream mode, feature toggles), and conditionally generates plugin.json with settings, Lua lifecycle handlers, optional Flask UI components (actions.py, template.html, hooks.py), scheduled jobs, NGINX configuration templates, and configuration JSONs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🏗️ From command line, a plugin takes its form,
With docs to guide and templates warm,
Scaffolding cast in Bash's hand,
Your BunkerWeb dreams, at last, now stand,
Let fifty lines of code expand! ✨

🚥 Pre-merge checks | ❌ 2

❌ Failed checks (2 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title lacks a conventional commit format prefix (feat/fix/refactor) and is somewhat vague, using the non-specific phrase 'plugin structure' rather than clearly indicating this adds a new script. Revise the title to follow Conventional Commits format, e.g., 'feat: add plugin generator script for scaffolding new plugins' to clarify the main contribution and meet the style guide.
Description check ❓ Inconclusive The description contains only a command-line usage example and lacks substantive explanation of what the pull request accomplishes or why it was created. Expand the description to explain the purpose, functionality, and benefits of the plugin generator alongside the usage example provided.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@TheophileDiot
Copy link
Copy Markdown
Member

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 13, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@templates/create_bunkerweb_plugin.sh`:
- Around line 1-3: The script currently uses only "set -e"; update the script
startup to use Bash strict mode by replacing that with "set -euo pipefail"
(since the file uses a Bash shebang #!/bin/bash and Bash-specific features), so
that unset variables and pipeline failures are caught; ensure any uses of
optional environment variables are guarded or defaulted to avoid breaking on -u.
- Around line 209-216: The sed replacements use ${plugin_name_upper} before it
is set, causing empty substitutions; move the assignment of plugin_name_upper
(plugin_name_upper=$(echo "$plugin_name" | tr '[:lower:]' '[:upper:]')) before
any sed lines that reference ${plugin_name_upper} (specifically the sed that
replaces USE_PLUGIN_NAME_UPPER and PLUGIN_PLUGIN_NAME_UPPER for
"$plugin_dir/$plugin_name.lua"), so set plugin_name_upper immediately after
plugin_name is available and then run the sed commands, then remove backups as
currently done.
- Around line 734-764: The cleanup_old_data method currently hardcodes
cleanup_paths (including '/var/log/bunkerweb/' and '/tmp/bunkerweb/') which is
dangerous when run with elevated privileges; update cleanup_old_data to read
paths from configuration or environment variables (e.g.,
BUNKERWEB_CLEANUP_PATHS) and add a dry_run boolean flag and/or explicit
confirmation parameter so deletions only occur when confirmed, validate each
candidate path against an allowlist or required base directories (e.g., ensure
each path startswith '/tmp/' or a configured safe base) before unlinking, add a
guard that refuses to run when running as root (or requires a force flag), and
include a prominent warning comment above the function and detailed logging via
self.logger when dry_run is active and when any path is rejected; keep
references to cleanup_paths, plugin_name, files_removed, and cleanup_old_data so
you modify the same symbols.

In `@templates/README.md`:
- Around line 444-446: The file is missing a trailing newline after the final
line "**Happy Plugin Development!** 🚀"; open templates/README.md and add a
single POSIX-compliant newline character at the end of the file so the file ends
with an empty line following that closing text.
- Around line 440-443: Update the README heading and sentence to use British
English spelling: change the heading "## License" to "## Licence" and change
"licenses" to "licences" in the sentence "Check individual plugin licenses as
generated." so the sentence reads "Check individual plugin licences as
generated."; ensure only these textual edits are made in the same block of the
README content.
- Around line 106-158: In templates/README.md update the five directory-tree
code blocks under the headings "Basic Plugin Structure", "With UI Components
(`--with-ui`)", "With Job Scheduler (`--with-jobs`)", "With NGINX Configs
(`--with-configs`)" and "With Templates (`--with-templates`)" so each code fence
includes a language identifier of text (e.g., ```text) and has a blank line
before and after the fenced block; ensure you only modify those fenced blocks
(the directory trees) to add the blank lines and the `text` specifier to improve
Markdown rendering.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 89f8ebf1-a404-47e7-b056-be3c6fceb3ed

📥 Commits

Reviewing files that changed from the base of the PR and between 5ba988f and 29f9f90.

⛔ Files ignored due to path filters (2)
  • templates/template_diagram.drawio is excluded by !**/*.drawio and included by **
  • templates/template_diagram.svg is excluded by !**/*.svg, !**/*.svg and included by **
📒 Files selected for processing (2)
  • templates/README.md
  • templates/create_bunkerweb_plugin.sh
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*.sh

⚙️ CodeRabbit configuration file

**/*.sh: Shell scripts must match BunkerWeb's portability expectations:

  • If the script is POSIX shell, prefer set -eu; if it explicitly requires Bash, use set -euo pipefail.
  • Quote variables and command substitutions consistently and prefer ${var} when concatenating.
  • Do not use Bash-only features in /bin/sh scripts.
  • Handle failures explicitly, use trap for cleanup where temporary files are created, and use mktemp safely.
  • Never pipe a remote download straight into a shell interpreter; verify downloads by checksum or signature and avoid -k / --insecure.
  • Do not rely on inherited PATH in privileged contexts; set it explicitly where needed.
  • Avoid eval and unsafe command construction from untrusted data.

Files:

  • templates/create_bunkerweb_plugin.sh
**/*.md

⚙️ CodeRabbit configuration file

**/*.md: Documentation should be concise, accurate, and written in British English:

  • Keep the structure clear with a sensible heading hierarchy.
  • Each plugin README contains a settings table generated from plugin.json via .tests/misc/json2md.py; regenerate it whenever settings change rather than hand-editing the table.
  • The repository README shows a compatibility badge tied to the plugins-collection version in COMPATIBILITY.json — keep it in sync with any version bump.
  • Prefer concrete instructions, accurate examples, and explicit prerequisites (Docker, sudo, required env vars like VIRUSTOTAL_API_KEY).
  • When a PR changes behaviour, defaults, packaging, or security posture, ask for the corresponding documentation update.

Files:

  • templates/README.md
🪛 LanguageTool
templates/README.md

[uncategorized] ~50-~50: Loose punctuation mark.
Context: ...### Required Parameters - PLUGIN_NAME: Name of the plugin (alphanumeric, hyphe...

(UNLIKELY_OPENING_PUNCTUATION)


[duplication] ~59-~59: Possible typo: you repeated a word.
Context: ...XT| Plugin description | Required | |-v, --version VERSION| Plugin version | 1.0.0 | |-o, --ou...

(ENGLISH_WORD_REPEAT_RULE)


[typographical] ~60-~60: Two consecutive dots
Context: ...-o, --output DIR | Output directory | .. (parent directory) | | --order NUMBER...

(DOUBLE_PUNCTUATION)


[typographical] ~182-~182: If specifying a range, consider using an en dash instead of a hyphen.
Context: ...NAME_TIMEOUT| Operation timeout | 5 | 1-300 seconds | |PLUGIN_NAME_LOG_LEVEL` | L...

(HYPHEN_TO_EN)


[uncategorized] ~257-~257: Loose punctuation mark.
Context: ...igures TCP/UDP protocol support: - no: HTTP only (default for web-focused plug...

(UNLIKELY_OPENING_PUNCTUATION)


[duplication] ~345-~345: Possible typo: you repeated a word.
Context: ... - Maximum 50 characters 4. Missing Description - Description is required: use `-d "Your description"...

(ENGLISH_WORD_REPEAT_RULE)


[grammar] ~357-~357: The verb form ‘execute’ does not seem to be suitable in this context.
Context: ...File Permissions Ensure the script has execute permissions: ```bash ls -la create_bunk...

(HAVE_VB)


[uncategorized] ~385-~385: If this is a compound adjective that modifies the following noun, use a hyphen.
Context: ...bs \ --with-ui \ analytics ### Rate Limiting Pluginbash ./create_bunkerweb_plugi...

(EN_COMPOUND_ADJECTIVE_INTERNAL)


[grammar] ~408-~408: Did you mean “to Use”?
Context: ...c plugin, add components as needed 2. Use Templates: Leverage generated templat...

(MISSING_TO_BEFORE_A_VERB)


[locale-violation] ~440-~440: License must be spelled with a “c” when used as a noun in British English. Use “licence”.
Context: ...er](https://bunkerity.discord.com/) ## License This script is provided as-is for Bunk...

(LICENCE_LICENSE_NOUN_SINGULAR)


[locale-violation] ~442-~442: licenses must be spelled with a “c” when used as a noun in British English. Use “licences”.
Context: ...in development. Check individual plugin licenses as generated. --- **Happy Plugin Deve...

(LICENCE_LICENSE_NOUN_PLURAL)

🪛 markdownlint-cli2 (0.22.0)
templates/README.md

[warning] 29-29: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 35-35: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 70-70: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 71-71: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 75-75: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 76-76: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 89-89: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 90-90: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 97-97: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 98-98: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 108-108: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 109-109: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 109-109: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 119-119: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 120-120: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 120-120: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 130-130: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 131-131: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 131-131: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 137-137: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 138-138: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 138-138: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 150-150: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 151-151: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 151-151: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 231-231: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 236-236: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 240-240: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 274-274: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 279-279: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 289-289: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 297-297: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 305-305: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 306-306: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 315-315: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 316-316: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 333-333: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 351-351: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 358-358: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 365-365: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 366-366: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 375-375: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 376-376: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 385-385: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 386-386: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 395-395: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 396-396: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 406-406: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 413-413: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 419-419: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 446-446: Files should end with a single newline character

(MD047, single-trailing-newline)

🪛 Shellcheck (0.11.0)
templates/create_bunkerweb_plugin.sh

[style] 111-111: See if you can use ${variable//search/replace} instead.

(SC2001)

🔇 Additional comments (14)
templates/create_bunkerweb_plugin.sh (12)

5-34: LGTM!

The usage function is well-structured with clear option documentation and examples.


36-55: LGTM!

Validation logic is sound: checks for empty input, disallowed characters, and length constraints.


57-85: LGTM!

Directory structure creation is conditional and appropriate. The commented-out modsec directories align with the later note about ModSecurity rules being disabled by default due to syntax complexity.


101-145: LGTM!

The generated plugin.json structure matches the established schema with proper id, name, settings objects containing context, default, help, regex, and type fields. The conditional jobs array is cleanly handled.


219-333: LGTM!

The generated actions.py provides a solid Flask handler template with proper request handling, validation, and error logging.


335-612: LGTM!

The HTML template is well-structured with proper Jinja2 templating, responsive CSS, and appropriate JavaScript for form handling and status updates.


992-1129: LGTM!

The NGINX configuration templates are well-structured with appropriate Jinja2 conditionals, shared memory dictionaries, and proper separation between HTTP and stream contexts.


1131-1212: LGTM!

The configuration templates provide sensible defaults for development, production, and custom environments with appropriate step structures.


1214-1305: LGTM!

The project README template provides comprehensive setup and installation guidance.


1307-1473: LGTM!

The plugin README generation is thorough with installation instructions, configuration examples, and troubleshooting guidance.


1475-1561: LGTM!

The main orchestration function is well-structured with proper confirmation before overwriting existing directories and comprehensive progress output.


1563-1650: LGTM!

Argument parsing is robust with proper validation for stream modes, order ranges, and required parameters. Error messages are directed to stderr appropriately.

templates/README.md (2)

1-67: LGTM!

The documentation provides a clear overview of the plugin generator with comprehensive feature descriptions and well-organised options tables.


221-226: Documentation inconsistent with script: "daily" vs "day".

The script generates "every": "day" in plugin.json (line 139 of script), but this documentation lists "daily". Additionally, the script's usage note on line 32 mentions valid values as minute/hour/day/week/once, which differs from what's documented here.

🔧 Proposed fix
 Available job frequencies:
 - `hour` - Run every hour
-- `daily` - Run once per day (default)
-- `weekly` - Run once per week  
-- `monthly` - Run once per month
+- `day` - Run once per day (default)
+- `week` - Run once per week
+- `minute` - Run every minute
+- `once` - Run once at startup

Comment on lines +1 to +3
#!/bin/bash

set -e
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use set -euo pipefail for Bash scripts.

The script explicitly requires Bash (shebang #!/bin/bash) and uses Bash-specific features such as sed -i.bak and read -r into $REPLY. Per coding guidelines, Bash scripts should use set -euo pipefail to catch unset variable usage and pipeline failures.

🔧 Proposed fix
 #!/bin/bash
 
-set -e
+set -euo pipefail

As per coding guidelines: "If the script is POSIX shell, prefer set -eu; if it explicitly requires Bash, use set -euo pipefail."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#!/bin/bash
set -e
#!/bin/bash
set -euo pipefail
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/create_bunkerweb_plugin.sh` around lines 1 - 3, The script
currently uses only "set -e"; update the script startup to use Bash strict mode
by replacing that with "set -euo pipefail" (since the file uses a Bash shebang
#!/bin/bash and Bash-specific features), so that unset variables and pipeline
failures are caught; ensure any uses of optional environment variables are
guarded or defaulted to avoid breaking on -u.

Comment on lines +209 to +216
sed -i.bak "s|PLUGIN_NAME_LOWER|${plugin_name}|g" "$plugin_dir/$plugin_name.lua"
sed -i.bak "s|USE_PLUGIN_NAME_UPPER|USE_${plugin_name_upper}|g" "$plugin_dir/$plugin_name.lua"

local plugin_name_upper
plugin_name_upper=$(echo "$plugin_name" | tr '[:lower:]' '[:upper:]')
sed -i.bak "s|PLUGIN_PLUGIN_NAME_UPPER|PLUGIN_${plugin_name_upper}|g" "$plugin_dir/$plugin_name.lua"

rm -f "$plugin_dir/$plugin_name.lua.bak"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Variable plugin_name_upper used before definition.

Line 210 references ${plugin_name_upper} but the variable is not assigned until line 213. This causes the sed replacement to substitute USE_PLUGIN_NAME_UPPER with USE_ (empty suffix), breaking the generated Lua file's enable/disable checks.

🐛 Proposed fix: move variable assignment before use
     sed -i.bak "s|PLUGIN_NAME_LOWER|${plugin_name}|g" "$plugin_dir/$plugin_name.lua"
+    
+    local plugin_name_upper
+    plugin_name_upper=$(echo "$plugin_name" | tr '[:lower:]' '[:upper:]')
     sed -i.bak "s|USE_PLUGIN_NAME_UPPER|USE_${plugin_name_upper}|g" "$plugin_dir/$plugin_name.lua"
     
-    local plugin_name_upper
-    plugin_name_upper=$(echo "$plugin_name" | tr '[:lower:]' '[:upper:]')
     sed -i.bak "s|PLUGIN_PLUGIN_NAME_UPPER|PLUGIN_${plugin_name_upper}|g" "$plugin_dir/$plugin_name.lua"
     
     rm -f "$plugin_dir/$plugin_name.lua.bak"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sed -i.bak "s|PLUGIN_NAME_LOWER|${plugin_name}|g" "$plugin_dir/$plugin_name.lua"
sed -i.bak "s|USE_PLUGIN_NAME_UPPER|USE_${plugin_name_upper}|g" "$plugin_dir/$plugin_name.lua"
local plugin_name_upper
plugin_name_upper=$(echo "$plugin_name" | tr '[:lower:]' '[:upper:]')
sed -i.bak "s|PLUGIN_PLUGIN_NAME_UPPER|PLUGIN_${plugin_name_upper}|g" "$plugin_dir/$plugin_name.lua"
rm -f "$plugin_dir/$plugin_name.lua.bak"
sed -i.bak "s|PLUGIN_NAME_LOWER|${plugin_name}|g" "$plugin_dir/$plugin_name.lua"
local plugin_name_upper
plugin_name_upper=$(echo "$plugin_name" | tr '[:lower:]' '[:upper:]')
sed -i.bak "s|USE_PLUGIN_NAME_UPPER|USE_${plugin_name_upper}|g" "$plugin_dir/$plugin_name.lua"
sed -i.bak "s|PLUGIN_PLUGIN_NAME_UPPER|PLUGIN_${plugin_name_upper}|g" "$plugin_dir/$plugin_name.lua"
rm -f "$plugin_dir/$plugin_name.lua.bak"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/create_bunkerweb_plugin.sh` around lines 209 - 216, The sed
replacements use ${plugin_name_upper} before it is set, causing empty
substitutions; move the assignment of plugin_name_upper
(plugin_name_upper=$(echo "$plugin_name" | tr '[:lower:]' '[:upper:]')) before
any sed lines that reference ${plugin_name_upper} (specifically the sed that
replaces USE_PLUGIN_NAME_UPPER and PLUGIN_PLUGIN_NAME_UPPER for
"$plugin_dir/$plugin_name.lua"), so set plugin_name_upper immediately after
plugin_name is available and then run the sed commands, then remove backups as
currently done.

Comment on lines +734 to +764
def cleanup_old_data(self):
"""
Clean up old log files and temporary data
"""
try:
self.logger.info("Starting data cleanup")

cleanup_paths = [
'/var/log/bunkerweb/',
'/tmp/bunkerweb/',
f'/tmp/{self.plugin_name}/'
]

cutoff_date = datetime.now() - timedelta(days=7)
files_removed = 0

for cleanup_path in cleanup_paths:
if os.path.exists(cleanup_path):
for file_path in Path(cleanup_path).glob('**/*'):
if file_path.is_file():
file_modified = datetime.fromtimestamp(file_path.stat().st_mtime)
if file_modified < cutoff_date:
file_path.unlink()
files_removed += 1

self.logger.info(f"Cleanup completed. Removed {files_removed} old files")
return True

except Exception as e:
self.logger.error(f"Cleanup failed: {str(e)}")
return False
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Consider adding a safety guard or making cleanup paths configurable.

The hardcoded cleanup paths (/var/log/bunkerweb/, /tmp/bunkerweb/) could inadvertently delete important files if the job runs with elevated privileges. Consider either:

  1. Adding a dry-run mode or explicit confirmation
  2. Making paths configurable via environment variables
  3. Adding a more prominent warning comment in the generated code
♻️ Suggested safety enhancement
     def cleanup_old_data(self):
         """
         Clean up old log files and temporary data
+        WARNING: Review and customize these paths before enabling in production
         """
         try:
             self.logger.info("Starting data cleanup")
             
+            # CAUTION: Modify these paths to match your environment
+            # Consider using environment variables for production deployments
             cleanup_paths = [
-                '/var/log/bunkerweb/',
-                '/tmp/bunkerweb/',
+                os.getenv('${plugin_name_upper}_CLEANUP_LOG_PATH', '/var/log/bunkerweb/'),
+                os.getenv('${plugin_name_upper}_CLEANUP_TMP_PATH', '/tmp/bunkerweb/'),
                 f'/tmp/{self.plugin_name}/'
             ]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/create_bunkerweb_plugin.sh` around lines 734 - 764, The
cleanup_old_data method currently hardcodes cleanup_paths (including
'/var/log/bunkerweb/' and '/tmp/bunkerweb/') which is dangerous when run with
elevated privileges; update cleanup_old_data to read paths from configuration or
environment variables (e.g., BUNKERWEB_CLEANUP_PATHS) and add a dry_run boolean
flag and/or explicit confirmation parameter so deletions only occur when
confirmed, validate each candidate path against an allowlist or required base
directories (e.g., ensure each path startswith '/tmp/' or a configured safe
base) before unlinking, add a guard that refuses to run when running as root (or
requires a force flag), and include a prominent warning comment above the
function and detailed logging via self.logger when dry_run is active and when
any path is rejected; keep references to cleanup_paths, plugin_name,
files_removed, and cleanup_old_data so you modify the same symbols.

Comment on lines +106 to +158
## Generated Structure

### Basic Plugin Structure
```
plugin-name/
├── plugin.json # Plugin metadata and settings
├── plugin-name.lua # Main Lua execution file
├── README.md # Comprehensive documentation
└── docs/ # Documentation assets
├── template_diagram.drawio
└── template_diagram.svg
```

### With UI Components (`--with-ui`)
```
plugin-name/
├── ui/
│ ├── actions.py # Flask request handlers
│ ├── template.html # Web interface template
│ ├── hooks.py # Flask lifecycle hooks
│ ├── blueprints/ # Custom Flask blueprints
│ └── templates/ # Additional UI templates
```

### With Job Scheduler (`--with-jobs`)
```
plugin-name/
├── jobs/
│ └── plugin-name-job.py # Scheduled job script (daily by default)
```

### With NGINX Configs (`--with-configs`)
```
plugin-name/
├── confs/
│ ├── server-http/ # Server-level HTTP configurations
│ ├── http/ # HTTP-level configurations
│ ├── default-server-http/ # Default server configurations
│ ├── modsec/ # ModSecurity rules
│ ├── modsec-crs/ # ModSecurity CRS rules
│ ├── stream/ # Stream-level configurations
│ └── server-stream/ # Server-level stream configurations
```

### With Templates (`--with-templates`)
```
plugin-name/
├── templates/
│ ├── plugin-name-template.json # Main template
│ ├── plugin-name-dev.json # Development template
│ ├── plugin-name-prod.json # Production template
│ └── plugin-name-template/ # Template with custom configs
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Add blank lines around code blocks and specify language identifiers.

Multiple code blocks lack language specifiers and blank line separation from headings. This affects rendering consistency across different Markdown parsers.

✨ Example fix pattern
 ### Basic Plugin Structure
+

+```text
plugin-name/
├── plugin.json # Plugin metadata and settings
...

+
### With UI Components (`--with-ui`)

Apply similar changes to all structure code blocks (lines 109, 120, 131, 138, 151) by adding blank lines before and after, and using text as the language identifier for directory tree listings.

🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 108-108: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 109-109: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 109-109: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 119-119: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 120-120: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 120-120: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 130-130: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 131-131: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 131-131: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 137-137: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 138-138: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 138-138: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 150-150: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 151-151: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 151-151: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/README.md` around lines 106 - 158, In templates/README.md update
the five directory-tree code blocks under the headings "Basic Plugin Structure",
"With UI Components (`--with-ui`)", "With Job Scheduler (`--with-jobs`)", "With
NGINX Configs (`--with-configs`)" and "With Templates (`--with-templates`)" so
each code fence includes a language identifier of text (e.g., ```text) and has a
blank line before and after the fenced block; ensure you only modify those
fenced blocks (the directory trees) to add the blank lines and the `text`
specifier to improve Markdown rendering.

Comment on lines +440 to +443
## License

This script is provided as-is for BunkerWeb plugin development. Check individual plugin licenses as generated.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use British English spelling for "licence".

Per documentation guidelines, British English should be used. "License" (noun) should be "Licence" and "licenses" should be "licences".

🔧 Proposed fix
-## License
+## Licence
 
-This script is provided as-is for BunkerWeb plugin development. Check individual plugin licenses as generated.
+This script is provided as-is for BunkerWeb plugin development. Check individual plugin licences as generated.

As per coding guidelines: "Documentation should be concise, accurate, and written in British English."

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## License
This script is provided as-is for BunkerWeb plugin development. Check individual plugin licenses as generated.
## Licence
This script is provided as-is for BunkerWeb plugin development. Check individual plugin licences as generated.
🧰 Tools
🪛 LanguageTool

[locale-violation] ~440-~440: License must be spelled with a “c” when used as a noun in British English. Use “licence”.
Context: ...er](https://bunkerity.discord.com/) ## License This script is provided as-is for Bunk...

(LICENCE_LICENSE_NOUN_SINGULAR)


[locale-violation] ~442-~442: licenses must be spelled with a “c” when used as a noun in British English. Use “licences”.
Context: ...in development. Check individual plugin licenses as generated. --- **Happy Plugin Deve...

(LICENCE_LICENSE_NOUN_PLURAL)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/README.md` around lines 440 - 443, Update the README heading and
sentence to use British English spelling: change the heading "## License" to "##
Licence" and change "licenses" to "licences" in the sentence "Check individual
plugin licenses as generated." so the sentence reads "Check individual plugin
licences as generated."; ensure only these textual edits are made in the same
block of the README content.

Comment on lines +444 to +446
---

**Happy Plugin Development!** 🚀 No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

Add trailing newline at end of file.

The file should end with a single newline character for POSIX compliance.

🧰 Tools
🪛 markdownlint-cli2 (0.22.0)

[warning] 446-446: Files should end with a single newline character

(MD047, single-trailing-newline)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@templates/README.md` around lines 444 - 446, The file is missing a trailing
newline after the final line "**Happy Plugin Development!** 🚀"; open
templates/README.md and add a single POSIX-compliant newline character at the
end of the file so the file ends with an empty line following that closing text.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants