-
Notifications
You must be signed in to change notification settings - Fork 0
Plugin System
Diese Seite dokumentiert das Beez-Plugin-System auf dem Branch milestone-17/plugin-system: wie Plugins aufgebaut sind, was sie exportieren können, welche neuen DSL-Funktionen es gibt, und welche Standard-Phasen, Standard-Scopes und Standard-Workflows das Coditary-Ökosystem verwendet.
-
ReqPack Declaration — Plugins in
reqpack.beezdeklarieren - Workflow Declaration — Workflows lokal oder aus Plugins importieren
- Task Declaration — Tasks und Plugin-Task-Importe
-
Configure Step —
configure_step()für lokale Steps - Phases and Scopes — Konzepte Phase + Scope
-
Beez API —
beez.env,beez.env_or, … -
Step Context —
ctxin Step-Callbacks
| Bereich | Neu / geändert |
|---|---|
| Plugins | Vollständiges Plugin-Format mit plugin(), config, steps, optional workflows und tasks
|
| Konfiguration | Plugin Config DSL: defaults, profile_defs, finalize, optional schema
|
| Projekt-Konfiguration |
configure({ ... }) ersetzt viele einzelne configure_step()-Aufrufe für Plugins |
| Workflows | Gestufte Workflows ({ "setup", { "setup[app]" } }), Import via workflows({ name = "org/plugin:workflow" })
|
| Tasks | Plugin-Tasks exportieren und in build.lua importieren |
| Phasen / Scopes | Standardisierte Namen (setup, quality, compile, …) und Scopes (app, lint, audit, …) |
| Referenz-Syntax |
phase[scope] und step[scope] statt separater scope-Felder in Tasks |
| Lua-API |
beez.env_or, beez.shell.run, beez.char.quote, beez.increment.run
|
Ein Beez-Plugin liegt unter einem Pfad wie:
plugins/<organization>/<plugin-name>/<version>/
beez_plugin.lua # Einstieg: plugin(), workflows{}, tasks{}
src/ # Lua-Module (config, runner, command, defaults, …)
In build.lua wird das Plugin über ReqPack geladen:
reqpack {
beez = {
{
name = "coditary/cppcheck",
path = "./plugins/coditary/cppcheck",
version = "1.0.0",
},
},
}Beez lädt dann plugins/coditary/cppcheck/1.0.0/beez_plugin.lua. Der path zeigt auf das Plugin-Verzeichnis ohne Versions-Suffix; die version wählt den Unterordner.
Versionierte Plugin-Steps können auch per CLI referenziert werden (plugin:step@1.0.0). Nicht installierte Versionen können bei Bedarf aus dem Plugin-Cache nachgeladen werden.
In beez_plugin.lua:
plugin("cppcheck", {
version = "1.0.0",
description = "Incremental cppcheck static analysis",
organization = "coditary",
config = { ... }, -- optional: Plugin Config DSL
steps = { ... }, -- Pflicht: Tabelle der Steps (darf leer sein, z. B. nur Workflow-Plugin)
})| Feld | Pflicht | Bedeutung |
|---|---|---|
version |
ja | Semantische Version (muss zu reqpack.beez passen) |
organization |
empfohlen | Organisation für qualifizierte Namen (coditary/cppcheck) |
description |
nein | Kurzbeschreibung für beez --list
|
config |
nein | Plugin-weite Konfiguration (siehe unten) |
steps |
ja | Map step_name → step_table
|
Der erste Parameter von plugin("name", …) muss mit dem Verzeichnisnamen übereinstimmen (cppcheck, nicht coditary/cppcheck).
Gleiche Felder wie bei globalem step() in build.lua:
steps = {
cppcheck_check = {
phase = "quality",
scope = "analyze",
input = { "src/**/*.cpp" },
description = "cppcheck (configurable profiles)",
config = {
profile = "analyze",
profiles = { "analyze" },
},
run = function(ctx)
return require("src.runner").check(ctx)
end,
},
}Steps werden registriert als:
- Kurzname:
cppcheck_check(wenn nur ein Plugin diesen Namen hat) - Qualifiziert:
coditary/cppcheck:cppcheck_check - Mit Scope-Alias:
cppcheck_check:analyze(wenn der Step-Scope gesetzt ist)
Lazy Steps: Ein Step-Eintrag kann eine Funktion sein, die beim Laden eine Step-Tabelle zurückgibt — nützlich für viele ähnliche Steps (z. B. Conan-Configure pro Build-Profil).
Plugin-Konfiguration wird zentral in config definiert und pro Step-Aufruf zusammengeführt.
config = {
defaults = {
binary = "cppcheck",
parallelism = 16,
-- alle Standardwerte des Plugins
},
profile_defs = {
analyze = {
patterns = { "src/**/*.cpp" },
log_prefix = "[cppcheck/analyze]",
},
security = {
patterns = { "src/**/*.cpp" },
log_prefix = "[cppcheck/security]",
},
},
finalize = function(resolved)
-- letzte Anpassung nach Merge
resolved.enable = config.normalize_enable(resolved.enable)
return resolved
end,
schema = { ... }, -- optional: JSON-Schema-Subset für Validierung
},Für einen Plugin-Step mit config = { profile = "analyze", foo = "bar" }:
-
defaults— Plugin-Basis -
profile_defs[profile]— nur wennprofilegesetzt ist undprofile_defsnicht leer ist -
Step-
configaus der Step-Definition -
configure()/configure_plugin()ausbuild.lua(global oder pro Step untersteps) -
finalize(cfg)— optional, normalisiert das Ergebnis
| Kontext | Bedeutung von profile
|
|---|---|
In profile_defs
|
Schlüssel für ein Plugin-Profil (analyze, security, fast, …) |
Ohne profile_defs
|
Beliebiges semantisches Feld (z. B. Build-Profil code, debug) — wird nicht gegen profile_defs geprüft |
Plugins wie conan und clang-build nutzen profile = "code" als Build-Profil, ohne profile_defs.
run = function(ctx)
local cfg = ctx.get_config()
-- cfg enthält das zusammengeführte Plugin-Config-Table
return require("src.runner").check(ctx)
endEmpfohlenes Plugin-internes Muster:
-
src/config.lua—resolve(step_cfg)mitbeez.data.cloneund Normalisierung -
src/runner.lua— Orchestrierung, ruftbeez.shell.run/beez.increment.runauf -
src/command.lua— reine Shell-Befehlsstrings -
src/defaults.lua— Konstanten und Default-Muster
In build.lua konfigurierst du alle Plugins gebündelt:
configure({
{ "coditary/cppcheck", {
check_rev = "2",
steps = {
cppcheck_check = { profiles = { "analyze", "security" } },
},
}},
{ "coditary/conan", {
reports_dir = "report",
lock_rev = "1",
}},
{ ":clean:artifacts", {
-- Standalone-Step (führender Doppelpunkt)
}},
})Jeder Eintrag ist { ziel, config_tabelle }:
| Ziel | Wirkung |
|---|---|
"coditary/plugin" |
Plugin-Config mergen; optional steps = { step_name = { ... } } pro Step |
":step_name" |
Nur diesen Step konfigurieren (lokal oder Plugin-Step) |
Äquivalent für ein einzelnes Plugin:
configure_plugin("coditary/demo", { foo = "bar" })configure() ist die bevorzugte Form für mehrere Plugins in einem Block.
Nach plugin() kannst du Workflows definieren:
workflows {
build = {
{ "setup", { "setup[app]" } },
{ "compile", { "compile[app]" } },
{ "bundle", { "bundle[app]" } },
{ "test", { "test[test]" } },
},
quality = {
{ "quality", { "quality[lint]", "quality[format]", "quality[analyze]" } },
{ "verify", { "verify[security]" } },
},
}Jeder Workflow-Eintrag ist { "<stufenname>", { "<phase[scope]>", ... } }:
-
Stufenname — nur für Lesbarkeit und Logging (z. B.
"setup","compile") - Invocations — Liste von Phase/Scope-Referenzen, die parallel in dieser Stufe laufen
- Stufen laufen sequenziell nacheinander
| Syntax | Bedeutung |
|---|---|
"compile[app]" |
Phase compile, Scope app
|
"setup" |
Phase setup, alle Scopes dieser Phase |
"compile:app" |
Alternative Schreibweise (Doppelpunkt) |
Legacy-Format (weiterhin gültig, nicht mit staged mischen):
workflow("ci", {
{ phase = "compile", scope = "code" },
})workflows({
build = "coditary/pipeline:build",
quality = "coditary/pipeline:quality",
all = "coditary/pipeline:all",
})Referenzformat: "<organization>/<plugin>:<workflow_name>".
Lokale Definition inline:
workflows({
quick = {
{ "test", { "test[test]" } },
},
})tasks {
format = {
{ plugin = "coditary/clang-format", step = "format_check" },
"echo done",
},
}Kurzform (Task-Name = Plugin-Task-Name):
task("coditary/demo:format")Alias:
task("my_format", {
plugin = "coditary/clang-format",
task = "format",
})Direkte Plugin-Schritt-Kette (ohne exportierten Plugin-Task):
task("debug", {
{ plugin = "coditary/conan", step = "configure[debug]" },
{ plugin = "coditary/clang-build", step = "compile[debug]" },
{ plugin = "coditary/clang-build", step = "link[debug]" },
})Statt separatem scope-Feld:
-- neu (empfohlen)
{ plugin = "coditary/conan", step = "configure[debug]" }
-- mehrere Scopes parallel als separate Step-Aufrufe
{ step = "compile[app,coverage]" } -- nicht kombinierbar mit plugin:step:nameVeraltet (wird abgelehnt):
{ name = "compile", scope = "debug" } -- Fehler: use step[name[scope]]task("rebuild", {
{ phase = "compile[app]" },
{ phase = "bundle[app]" },
})Das Coditary-Pipeline-Plugin und die mitgelieferten Plugins verwenden diese Phasen (in typischer Reihenfolge):
| Phase | Typische Inhalte |
|---|---|
setup |
Conan install, CMake configure, Verzeichnisse anlegen |
generate |
Code-Generierung, CompDB-Index |
quality |
Lint, Format-Check, statische Analyse (cppcheck analyze, clang-tidy) |
compile |
Kompilierung (Release, Debug, Coverage, Sanitize, Fuzz, …) |
bundle |
Link, Binaries bauen |
test |
Unit-, Integration-, Performance-, Fuzz-Tests |
package |
SBOM, Lockfiles, Coverage-Reports, Audit-Artefakte |
verify |
Security-Scans, OSV-Audit, Fuzz-Seed-Verifikation |
publish |
Veröffentlichung (reserviert für zukünftige Steps) |
Alte Namen (configure, build, qa, fuzz, report, clean) wurden durch diese Standard-Phasen ersetzt.
| Scope | Verwendung |
|---|---|
app |
Haupt-Release-Build (Conan + Compile + Link Release) |
debug |
Debug-Build |
coverage |
Coverage-Instrumentierung und Coverage-Tests |
sanitize |
ASan/UBSan-Build und -Tests |
tsan |
Thread-Sanitizer |
fuzz |
Fuzz-Build und kurzer Fuzz-Lauf |
fuzz-corpus |
Fuzz mit committed Corpus |
fuzz-torture |
Langer Fuzz-Lauf |
test |
Normale Tests (ctest, Integration, …) |
lint |
clang-tidy Lint-Profil |
format |
clang-format Check |
analyze |
cppcheck/clang-tidy Analyze-Profil |
security |
Security-orientierte Static-Analysis |
audit |
Supply-Chain: SBOM, Lockfiles, OSV |
docs |
Dokumentation |
code |
Semantisches Build-Profil in Conan/CMake (kein Workflow-Scope-Zwang) |
repo |
Repository-weite Wartung (z. B. clean) |
Scopes sind Konventionen im Coditary-Ökosystem. Eigene Projekte können weitere Scopes definieren; Workflows wählen dann per phase[scope].
Das Plugin coditary/pipeline exportiert vorgefertigte Workflows. Import in build.lua:
workflows({
build = "coditary/pipeline:build",
quality = "coditary/pipeline:quality",
debug = "coditary/pipeline:debug",
coverage = "coditary/pipeline:coverage",
sanitize = "coditary/pipeline:sanitize",
tsan = "coditary/pipeline:tsan",
fuzzer_smoke = "coditary/pipeline:fuzzer_smoke",
fuzzer_corpus = "coditary/pipeline:fuzzer_corpus",
fuzzer_torture = "coditary/pipeline:fuzzer_torture",
all = "coditary/pipeline:all",
clean = "coditary/pipeline:clean",
standard = "coditary/pipeline:standard",
})| Workflow | Kurzbeschreibung |
|---|---|
build |
setup → compile → bundle → test (app) |
quality |
lint, format, analyze → audit package → security verify |
debug |
Debug-Setup, Compile, Bundle |
coverage |
Coverage-Setup, Compile, Coverage-Tests, Coverage-Report |
sanitize / tsan
|
Sanitizer-Varianten |
fuzzer_* |
Fuzz-Build und unterschiedliche Test-Intensitäten |
all |
Vollständige CI-Pipeline (mehrere Build-Varianten + Quality + Verify) |
clean |
setup[repo] — Artefakte löschen |
standard |
Alle Standard-Phasen ohne Scope-Einschränkung (setup, generate, quality, …) |
standard eignet sich, wenn alle registrierten Steps einer Phase laufen sollen — analog zu beez -p setup ohne Scope.
Liest eine Umgebungsvariable; wenn nicht gesetzt, den Default.
local build_type = beez.env_or("BUILD_TYPE", "Release")
local scanner = beez.env_or("OSV_SCANNER", beez.env_or("HOME", "") .. "/.local/bin/osv-scanner")Mehrere Keys werden der Reihe nach probiert (wie eine Fallback-Kette).
Führt einen Shell-Befehl synchron über den Step-Worker aus (spawn + wait). Ersetzt manuelle ctx:spawn/ctx:wait-Ketten für einfache Befehle.
local code = beez.shell.run(ctx, "[conan]", "conan install . -of build/conan")
if code ~= 0 then
return code
end| Option | Bedeutung |
|---|---|
return_output = true |
Gibt ein Paar { exit_code, output } zurück (Lua: result.first, result.second) |
Bei Fehler wird log_prefix und die Ausgabe auf stdout geschrieben (sofern nicht silent).
Escapet einen String für die Verwendung in Shell-Befehlen (POSIX single-quote-Stil).
local cmd = "echo " .. beez.char.quote("it's fine")Lua-Implementierung für inkrementelle Tool-Läufe über viele Dateien (parallel, Success-Cache, Worker). Wird von cppcheck, clang-tidy, clang-format u. a. genutzt.
return beez.increment.run(ctx, cfg)config enthält typischerweise patterns, build_command, cache_key, parallelism, output-Filter — siehe src/plugins/lua/api/increment/increment.lua.
Tiefe Kopie einer Config-Tabelle — wichtig, wenn ctx.get_config() materialisierte Tabellen liefert, deren Overlay-Keys in pairs() sichtbar, aber per cfg.key nicht zugreifbar sind.
beez_plugin.lua → plugin(), workflows{}, tasks{}
src/
defaults.lua → Konstanten, Glob-Muster, Revisions-Keys
config.lua → resolve(step_cfg): Merge + Normalisierung
command.lua → Shell-Befehle als Strings
runner.lua → Step-Logik, beez.shell.run / beez.increment.run
- Verzeichnis
plugins/<org>/<name>/1.0.0/anlegen -
beez_plugin.luamitplugin(),steps, optionalconfig/workflows/tasks - Standard-phase und scope aus den Tabellen oben wählen
- In
build.lua:reqpack.beez+configure({ { "org/name", { ... } } }) - Workflows importieren oder lokal definieren
-
input/output/cache_key/*_revfür Step-Cache setzen
| Plugin | Schwerpunkt |
|---|---|
cppcheck |
Plugin Config DSL mit profile_defs + finalize
|
clang-tidy |
Mehrere Profile (lint, analyze, security) |
conan |
Dynamische Steps pro Build-Profil, profile = "code"
|
clang-build |
Compile/Link pro Profil (app, debug, coverage, …) |
osv-audit |
beez.shell.run, Config-Resolve mit beez.data.clone
|
pipeline |
Nur Workflows, keine Steps |
order() akzeptiert beliebig viele Step-Namen und registriert eine Kette:
order("step_a", "step_b", "step_c")
-- äquivalent zu: order("step_a","step_b") + order("step_b","step_c")| Aktion | Beispiel |
|---|---|
| Workflow aus Plugin | beez all |
| Einzelner Plugin-Step | beez -s coditary/cppcheck:cppcheck_check |
| Phase+Scope | beez -p quality[lint] |
| Plugin-Task | beez coditary/demo:format |
- First Pipeline — erstes Projekt mit Plugins
- DSL Patterns — inkrementelle Checks, Worker
-
Step Cache —
input,output, Revisions-Keys - Development and Contribution — Beez selbst bauen und testen
Quick Reference · Glossary · FAQ
- Fundamentals
- Core Concepts
- Project Layout
- First Pipeline
- Phases and Scopes
- How Phases and Scopes Work
- Selecting with Phases and Scopes
- Designing Phases and Scopes
- Parallel Execution and Dependencies
- Configuration
- Configuration Overview
- Global User Config
- Project Config
- Environment Variables
- Performance Settings
- Cache Settings
- Config Reference
- CLI
- CLI Overview
- Running Targets
- Filtering by Phase
- Running a Single Step
- Listing Entities
- Output and Logging Flags
- Cache and Maintenance Flags
- Meta and Utility Commands
-
Project Scaffolding —
beez --init(embedded Tempify) - CLI Flag Reference
- Lua DSL
- DSL Overview
- Plugin System — Plugins, Config DSL, Standard-Workflows
- Step Declaration
- Task Declaration
- Workflow Declaration
- Order Declaration
- Configure Step
- ReqPack Declaration
- Beez API
- Step Context
- DSL Patterns
- Caching
- Caching Overview
- Step Cache
- Success Cache
- Glob Metadata Cache
- Artifact Patterns
- Cache Keys and Invalidation
- Cache Storage and Maintenance
- Caching Troubleshooting
- UI and Output
- Output Modes
- Progress and Animation
- Colors and Themes
- Run Summaries
- Logging and Log Files
- Development and Contribution
- Building and Setup
- Repository Layout
- Testing
- Code Quality
- Feature Development Workflow
- Submitting Changes