Skip to content

Update GitHub Copilot rules and repository instructions#2072

Open
workkavint-ship-it wants to merge 1 commit intordkcentral:dev/initial-copilot-instructionsfrom
workkavint-ship-it:dev/Copilot-instructions-PluginDevelopmentUpdate
Open

Update GitHub Copilot rules and repository instructions#2072
workkavint-ship-it wants to merge 1 commit intordkcentral:dev/initial-copilot-instructionsfrom
workkavint-ship-it:dev/Copilot-instructions-PluginDevelopmentUpdate

Conversation

@workkavint-ship-it
Copy link
Copy Markdown

Reorganized the plugin development guide in Copilot Instructions by replacing one large 10-plugin-development.md file with a main hub and smaller sections(10.1–10.7) for specific topics like module files, lifecycle, configuration, and CMake.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 6, 2026

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@workkavint-ship-it
Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

Copy link
Copy Markdown
Contributor

@MFransen69 MFransen69 left a comment

Choose a reason for hiding this comment

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

Don't know if it is possible but wouldn't it be easier to point for this to the PSG python code (as we update that for new features and is reviewed at the moment)?
If that would not work I'm happy to approve this, scanned through it (it is impossible to review it line by line)

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR restructures the Copilot plugin-development guidance by replacing an oversized single document with a hub page and focused sub-sections (10.1–10.7) covering module files, coding style, class/registration, lifecycle, implementation patterns, configuration, and CMake build rules.

Changes:

  • Replaced the monolithic 10-plugin-development.md content with a checklist + index that links out to topic-focused sub-files.
  • Added new instruction documents 10.1 through 10.7 for plugin module, style, registration, lifecycle, implementation, config templates, and CMake conventions.
  • Consolidated plugin best-practices into a shorter summary + “common mistakes” table in the hub.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
.github/instructions/10-plugin-development.md New hub/index + checklist replacing the prior long-form guide.
.github/instructions/10.1-plugin-module.md New rules/examples for Module.h/Module.cpp and MODULE_NAME usage.
.github/instructions/10.2-plugin-codestyle.md New plugin-oriented style/naming/error-handling guidance.
.github/instructions/10.3-plugin-class-registration.md New guidance for plugin class structure, interface maps, and metadata registration.
.github/instructions/10.4-plugin-lifecycle.md New lifecycle rules for Initialize/Deinitialize and OOP deactivation handling.
.github/instructions/10.5-plugin-implementation.md New implementation patterns for sinks, JSON config parsing, IWeb handling, locking, refcounting.
.github/instructions/10.6-plugin-config.md New guidance for .conf.in templates vs legacy config approaches and validation rules.
.github/instructions/10.7-plugin-cmake.md New guidance for ${NAMESPACE} usage, plugin CMake structure, and strict compiler settings inheritance.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +64 to +79
- Declare `project(<PluginName>)` and `cmake_minimum_required(VERSION 3.15)` at the top.
- Call `find_package(Thunder)` and set `project_version(MAJOR.MINOR.PATCH)`.
- Derive `MODULE_NAME` from `${NAMESPACE}${PROJECT_NAME}`.
- Declare plugin-specific cache variables with the naming convention `PLUGIN_<UPPERCASENAME>_<SETTING>`.
- Build a shared library (`SHARED`) including all plugin `.cpp` files and `Module.cpp`.
- Set `CXX_STANDARD 11` and `CXX_STANDARD_REQUIRED YES` on the target.
- Link `CompileSettingsDebug::CompileSettingsDebug` privately (always required).
- Install the target into `${CMAKE_INSTALL_LIBDIR}/${STORAGE_DIRECTORY}/plugins`.
- Call `write_config()` as the **last** statement.

### Example

```cmake
project(NetworkControl)
cmake_minimum_required(VERSION 3.15)

Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The example CMake structure places project() before cmake_minimum_required(), but the repository root CMakeLists (and common CMake policy expectations) require cmake_minimum_required() first so policies are set before project(). The structure bullets should either require the correct order or update the example to match it.

Copilot uses AI. Check for mistakes.
elseif(${CMAKE_COMPILER_IS_GNUCXX})
set(CMAKE_STRICT_CXX_COMPILER_SETTINGS "-Wall -Wextra -Wpedantic -Werror -Wnon-virtual-dtor")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_STRICT_COMPILER_SETTINGS "/W4")
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

In the strict compiler settings snippet, the MSVC branch sets CMAKE_STRICT_COMPILER_SETTINGS, but the flags appended to CMAKE_CXX_FLAGS come from CMAKE_STRICT_CXX_COMPILER_SETTINGS. As written, MSVC strict flags won’t be applied. Use a consistent variable (e.g., set CMAKE_STRICT_CXX_COMPILER_SETTINGS in the MSVC branch as well, or append the correct variable).

Suggested change
set(CMAKE_STRICT_COMPILER_SETTINGS "/W4")
set(CMAKE_STRICT_CXX_COMPILER_SETTINGS "/W4")

Copilot uses AI. Check for mistakes.
Comment on lines +41 to +42
| `startmode` | string | **Yes** | Controls how the plugin starts. Must be one of `"Activated"`, `"Deactivated"`, or `"Unavailable"`. Typically set via CMake variable: `"@PLUGIN_<n>_STARTMODE@"` |
| `autostart` | boolean | No | Legacy field. Superseded by `startmode`. Do **not** use alongside `startmode` |
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The .conf.in root-level fields list includes autostart and marks startmode as required, but the runtime config schema in Source/plugins/Configuration.h does not parse an autostart field and startmode has a default (so it’s not strictly required). To avoid incorrect guidance, drop autostart from the supported fields list (or clearly mark it as unsupported by this repo) and consider changing startmode from “Required: Yes” to “Recommended”.

Suggested change
| `startmode` | string | **Yes** | Controls how the plugin starts. Must be one of `"Activated"`, `"Deactivated"`, or `"Unavailable"`. Typically set via CMake variable: `"@PLUGIN_<n>_STARTMODE@"` |
| `autostart` | boolean | No | Legacy field. Superseded by `startmode`. Do **not** use alongside `startmode` |
| `startmode` | string | **Recommended** | Controls how the plugin starts. Must be one of `"Activated"`, `"Deactivated"`, or `"Unavailable"`. Typically set via CMake variable: `"@PLUGIN_<n>_STARTMODE@"` |

Copilot uses AI. Check for mistakes.
```cmake
set(autostart false)
set(callsign "org.rdk.MyPlugin")
set(preconditions "Platform")
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The .config example uses set(preconditions "Platform"), but the supported key in Thunder configs is precondition (singular). Using the plural form will be ignored by the config parser. Update the example to set(precondition ...) (and, if keeping .config examples at all, ensure all keys shown are actually supported).

Suggested change
set(preconditions "Platform")
set(precondition "Platform")

Copilot uses AI. Check for mistakes.
Comment on lines +92 to +105
namespace Thunder {

namespace {
static Metadata<Plugin::NetworkControl> metadata(
// Version
1, 0, 0,
// Preconditions
{},
// Terminations
{},
// Controls
{ subsystem::NETWORK }
);
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The Plugin::Metadata<> example declares static Metadata<Plugin::NetworkControl> metadata(...), but in this codebase the type is Plugin::Metadata<...> (see e.g. Source/Thunder/Controller.cpp). Without the Plugin:: qualifier (or an explicit using), this example won’t compile as written.

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +66
All CMake targets, `find_package` calls, `target_link_libraries` references, and install paths must use the `${NAMESPACE}` variable instead of hardcoded framework names (e.g., `WPEFrameworkPlugins`, `WPEFrameworkCore`). This ensures smooth upgrades (e.g., `WPEFramework → Thunder`) and prevents regressions.

### Correct Example

```cmake
set(MODULE_NAME ${NAMESPACE}${PROJECT_NAME})

find_package(${NAMESPACE}Plugins REQUIRED)
find_package(${NAMESPACE}Definitions REQUIRED)

target_link_libraries(${MODULE_NAME}
PRIVATE
CompileSettingsDebug::CompileSettingsDebug
${NAMESPACE}Plugins::${NAMESPACE}Plugins
${NAMESPACE}Definitions::${NAMESPACE}Definitions)

install(TARGETS ${MODULE_NAME}
DESTINATION ${CMAKE_INSTALL_LIBDIR}/${STORAGE_DIRECTORY}/plugins
COMPONENT ${NAMESPACE}_Runtime)
```

### Incorrect Example

```cmake
set(MODULE_NAME WPEFramework${PROJECT_NAME})

find_package(WPEFrameworkPlugins REQUIRED)
target_link_libraries(${MODULE_NAME}
PRIVATE
WPEFrameworkPlugins::WPEFrameworkPlugins)
```

---

## Plugin CMake Structure

### Requirement

Every plugin `CMakeLists.txt` must follow this standard structure:

- Declare `project(<PluginName>)` and `cmake_minimum_required(VERSION 3.15)` at the top.
- Call `find_package(Thunder)` and set `project_version(MAJOR.MINOR.PATCH)`.
- Derive `MODULE_NAME` from `${NAMESPACE}${PROJECT_NAME}`.
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The “Namespace Usage” requirement says all find_package calls must use ${NAMESPACE}, but the next section mandates find_package(Thunder). This is internally inconsistent and can mislead readers; either document find_package(Thunder) as an explicit exception/bootstrapping step (before ${NAMESPACE} is available) or adjust the namespace rule wording to exclude it.

Copilot uses AI. Check for mistakes.
Comment on lines +131 to +167
Plugins implementing `PluginHost::IWeb` follow this pattern:

- Compute `_skipURL` in `Initialize()` as the length of `service->WebPrefix()`.
- Use a static `Core::ProxyPoolType<Web::Response>` (and per-body-type pools) at file scope.
- In `Inbound()`, attach the correct body type to the request based on the verb and URL path.
- In `Process()`, dispatch on `request.Verb` (HTTP_GET / HTTP_PUT / HTTP_POST) to dedicated `GetMethod()`, `PutMethod()`, `PostMethod()` helpers.
- Always set `result->ErrorCode` and `result->Message`.
- Return `Web::STATUS_OK` on success; `Web::STATUS_BAD_REQUEST` or `Web::STATUS_NO_CONTENT` on failure.

### Example

```cpp
static Core::ProxyPoolType<Web::Response> responseFactory(4);
static Core::ProxyPoolType<Web::JSONBodyType<Core::JSON::ArrayType<Core::JSON::String>>> jsonStringListFactory(1);

void NetworkControl::Inbound(Web::Request& request)
{
Core::TextSegmentIterator index(
Core::TextFragment(request.Path, _skipURL,
static_cast<uint32_t>(request.Path.length() - _skipURL)),
false, '/');

if (request.Verb == Web::Request::HTTP_POST) {
index.Next();
if (index.IsValid() && index.Next()) {
if (index.Current().Text() == _T("DNS")) {
request.Body(jsonStringListFactory.Element());
}
}
}
}

Core::ProxyType<Web::Response>
NetworkControl::Process(const Web::Request& request)
{
Core::ProxyType<Web::Response> result(PluginHost::IFactories::Instance().Response());
Core::TextSegmentIterator index(
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

The IWeb guidance says to use a static Core::ProxyPoolType<Web::Response> for responses, but the example (and existing code in this repo, e.g. Source/Thunder/Controller.cpp) uses PluginHost::IFactories::Instance().Response() to obtain Web::Response objects. This should be made consistent (either update the requirement to recommend IFactories::Instance().Response() or update the example + justify the pool approach).

Copilot uses AI. Check for mistakes.
| Preprocessor macros | `UPPER_SNAKE_CASE` | `MODULE_NAME`, `VARIABLE_IS_NOT_USED` |

- Close namespaces with trailing comments: `} // namespace Plugin` and `} // namespace Thunder`.
- Use `#pragma once` in all plugin headers except `Module.h` (which uses `#ifndef MODULE_NAME` for the define guard).
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

This bullet says to use #pragma once in all plugin headers except Module.h, but 10.1-plugin-module.md explicitly requires Module.h to use #pragma once (and the example there does). Please reconcile these two instructions so they don’t contradict each other.

Suggested change
- Use `#pragma once` in all plugin headers except `Module.h` (which uses `#ifndef MODULE_NAME` for the define guard).
- Use `#pragma once` in all plugin headers, including `Module.h`.

Copilot uses AI. Check for mistakes.
| `resumed` | boolean | No | When `true`, Thunder will resume the plugin after a crash |
| `startuporder` | integer | No | Numeric priority controlling activation order. Lower values activate earlier |
| `systemrootpath` | string | No | Overrides the system root path for this plugin |
| `termination` | object | No | Configures crash/exit handling behaviour for the plugin process |
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

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

In the root-level fields table, termination is documented as an “object” for crash/exit handling, but in Thunder plugin configs termination is an array of subsystem names (e.g. ["NOT_NETWORK"]) used for deactivation triggers (see Source/plugins/Configuration.h, where Termination is an array). Please correct the type/description here to avoid conflating it with other termination/crash-handling concepts.

Suggested change
| `termination` | object | No | Configures crash/exit handling behaviour for the plugin process |
| `termination` | array of strings | No | List of Thunder subsystems whose *inactivity* should trigger plugin deactivation (for example: `["NOT_NETWORK"]`) |

Copilot uses AI. Check for mistakes.
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.

3 participants