Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Development documentation

Under this section, you will find the development documentation of Wazuh Indexer. This documentation contains instructions to compile, run, test and package the source code. Moreover, you will find instructions to set up a development environment in order to get started at developing the Wazuh Indexer.

This documentation assumes basic knowledge of certain tools and technologies, such as Docker, Bash (Linux) or Git.

Before you start coding, read the sections below: they cover how to open good pull requests and how our GitHub Actions behave when you do. Getting this right up front saves CI minutes and review cycles for everyone.

Pull requests

These are the standard procedures for creating, updating, and reviewing pull requests across the Wazuh Indexer repositories.

Lifecycle

┌──────────┐    ┌──────────────┐    ┌─────────────────┐    ┌───────┐
│  Draft   │───▶│ Local build  │───▶│ Ready for       │───▶│ Merge │
│  PR      │    │ & test       │    │ review (CI runs)│    │       │
└──────────┘    └──────────────┘    └─────────────────┘    └───────┘

Every pull request must start in Draft status. Workflows do not run on Draft PRs — this is enforced across all repositories to avoid wasting GitHub Actions minutes on work in progress — so use Draft status freely while iterating on your changes.

Before marking the PR as ready, build the project successfully and run the tests locally to verify they pass. This prevents avoidable CI failures that waste runner time and delay reviews. Once everything is complete and locally validated, click “Ready for review” and move the linked issue to Pending review. This is the moment workflows are triggered for the first time.

To address review feedback, push new commits on top of the branch and re-request review once you have resolved all comments. Avoid amending or rebasing published commits during review, and if CI fails after pushing, investigate and fix it before requesting re-review. When the PR is approved and CI passes, it can be merged. Use squash merge for single-purpose PRs to keep a clean history.

Body template

Use the following template when creating a pull request:

## Description

<!--
Provide a brief description of the problem this pull request addresses. Include relevant context to help reviewers understand the purpose and scope of the changes.

If this pull request resolves an existing issue, reference it here. For example:
Closes #<issue_number>
-->

## Proposed Changes

<!--
Summarize the changes made in this pull request. Include:
- Features added
- Bugs fixed
- Any relevant technical details
-->

### Results and Evidence

<!--
Provide evidence of the changes made, such as:
- Logs
- Screenshots
- Before/after comparisons
-->

### Artifacts Affected

<!--
List the artifacts impacted by this pull request, such as:
- Executables (specify platforms if applicable)
- Default configuration files
- Packages
-->

### Configuration Changes

<!--
If applicable, list any configuration changes introduced by this pull request, including:
- New configuration parameters
- Changes to default values
- Backward compatibility notes
-->

### Documentation Updates

<!--
If applicable, list the sections of documentation that have been updated as part of this pull request.
-->

### Tests Introduced

<!--
If applicable, describe any new unit or integration tests added as part of this pull request. Include:
- Scope of the tests
- Any relevant details about test coverage
-->

## Review Checklist

<!--
List any manual tests completed to verify the functionality of the changes. Include any manual tests that are still required for final approval.
-->

- [ ] Code changes reviewed
- [ ] Relevant evidence provided
- [ ] Tests cover the new functionality
- [ ] Configuration changes documented
- [ ] Developer documentation reflects the changes
- [ ] Meets requirements and/or definition of done
- [ ] No unresolved dependencies with other issues
- [ ] PR is linked to the relevant issue(s)
- [ ] Correct labels applied (e.g., `no-changelog`)
- [ ] ...

Always link the related issue with Resolves #<number> so it auto-closes on merge, and describe why rather than just what — the diff already shows what changed, so the description should explain the motivation.

Include instructions to test your changes, and any other relevant information for reviewers. Use the checklist to indicate that you have completed all required steps before requesting review.

Reviewing a PR

Start from the linked issue to understand the context and acceptance criteria, then read the description and checklist before reading the code. Focus your feedback on correctness, clarity, and maintainability, and use GitHub’s suggestion feature for small fixes to speed up the process. Approve only when you are confident the changes are correct and complete.

Changelog

Every PR is expected to include a changelog entry, classified as Added, Changed, Removed, or Fixed. The 5_codequality_changelog.yml workflow enforces this. Apply the no-changelog label to bypass the check when the linked issue belongs to a private repository, or when the PR genuinely does not require a changelog update.

Changelog entries must always reference the issue, not the pull request, so the entry stays meaningful independently of how the change was implemented. An issue only belongs in the changelog if it affects the product and represents a change from a previously released version — internal/CI changes are never included, and neither are fixes for problems introduced in an unpublished version.

Best practices

  • Keep PRs small and focused. One issue per PR whenever possible.
  • Write descriptive commit messages. They should explain why, not just what.
  • Do not trigger CI unnecessarily. Keep PRs in Draft until ready, and validate locally first.

Workflows and Actions

This section defines the naming conventions and operational rules for the GitHub Actions and Workflows used across the Wazuh Indexer repositories.

Naming convention

Both Actions and Workflows follow the same pattern:

<major>_<prefix>_<target>
ComponentDescription
MajorProduct major version (e.g. 4, 5).
PrefixCategory prefix from the use cases below.
TargetThe action target: a component, module, subsystem, tool, language, etc.

The prefix is drawn from the following set of use cases:

Use casePrefixTargetExample
Code analysis (static/dynamic)codeanalysisCode analysis tool4_codeanalysis_coverity
Linter / auto-docscodelinterLinter5_codelinter_clangformat
Code quality (groups codeanalysis + codelinter)codequalityRepository5_codequality_changelog
Unit teststestunitModule5_testunit_engine
Component teststestcomponentComponent/module5_testcomponent_indexerconnector
Integration teststestintegrationModule4_testintegration_cluster
Package builderbuilderpackageSubsystem4_builderpackage_server
Precompiled object builderbuilderprecompiledSubsystem5_builderprecompiled_agent
Version bumpingbumperRepository5_bumper_repository

For workflows triggered on PR or push events, append _onpush to the name to distinguish them from their workflow_dispatch counterparts:

5_builderpackage_indexer.yml          ← workflow_dispatch (manual)
5_builderpackage_indexer_onpush.yml   ← PR / push trigger (automatic)

When composing jobs from Actions, a single job step cannot mix Actions with different prefixes, and steps must use matrices whenever possible.

Runners

Two types of runners are available:

  • Default (GitHub-hosted) — used for all workflows unless there is a justified reason to use the dedicated runner.
  • Dedicated (self-hosted) — reserved for resource-intensive workflows only. Currently used exclusively by 5_builderpackage_indexer (the full package builder).

Always prefer the default runner. The dedicated runner is a shared, limited resource — use it only when the workflow genuinely requires the extra capacity (e.g. the full product builder).

Draft PR enforcement

All PR workflows must be configured to skip Draft PRs, so that no CI minutes are consumed on work-in-progress PRs. This is enforced by adding the following condition to every PR-triggered workflow:

on:
  pull_request:
    types: [opened, synchronize, ready_for_review]

jobs:
  <job_name>:
    if: ${{ !github.event.pull_request.draft }}