Banjo API 1.0.0-rc.2
Low-level C99 game development API
Loading...
Searching...
No Matches
Contributing to Banjo

Conventions for contributing to Banjo.

Where to file things

Versioning

Banjo uses Semantic Versioning (SemVer). A version number looks like MAJOR.MINOR.PATCH:

  • MAJOR: incremented when changes break backward compatibility (existing code using Banjo may need modifications).
  • MINOR: incremented when new features are added in a backward-compatible way (existing code continues to work, new capabilities available).
  • PATCH: incremented for backward-compatible bug fixes only.

Pre-release stages

Before a stable release, versions go through pre-release stages:

Stage Meaning
alpha Development version. New features expected. Stable only by CI/CD.
beta More mature. Can still add new features.
preview Feature freeze. Bug fixes only.
rc Release candidate. Only critical fixes.
(none) Stable release.

Pre-release versions look like 1.2.0-alpha, 1.2.0-beta, 1.2.0-preview, 1.2.0-rc. When multiple iterations are needed, they can be numbered: 1.2.0-rc.1, 1.2.0-rc.2.

The version is defined in inc/banjo/version.h: this is the single source of truth.

Branching strategy

Banjo uses Trunk-Based Development, a simple branching model where all development flows through a single main branch.

Branches at a glance

Branch Purpose Version
main Active development. Always deployable. X.Y.0-alpha
release/X.Y Stabilization and maintenance of version X.Y X.Y.0-alphabetapreviewrcX.Y.0

How it works

The main branch is the trunk. It always contains the latest development code, always passes CI, and is always at an -alpha version. All new work lands here first.

Release branches (release/X.Y) are created when it's time to stabilize a version. Once a release branch is cut:

  • The release branch progresses through alpha → beta → preview → rc → stable.
  • The main branch immediately bumps to the next minor version (still alpha).

Example timeline:

main (1.2.0-alpha)
├──► cut release/1.2 ──► 1.2.0-alpha → beta → preview → rc → 1.2.0 (tag: v1.2.0)
│ │
│ main bumps to 1.3.0-alpha ├──► 1.2.1 (maintenance)
│ │
▼ ▼
main (1.3.0-alpha) ──────────────────────────────────────────────► continues...

Maintenance releases

Release branches stick around after the stable release. If a bug is found in 1.2.0 while main is at 1.3.0-alpha:

  1. Fix the bug on release/1.2.
  2. Release 1.2.1 (tag: v1.2.1).
  3. Cherry-pick the fix to main.

This allows shipping fixes to older versions without forcing users to upgrade.

Contributor workflow

This section explains how to contribute code to Banjo day-to-day.

The golden rule

Nobody pushes directly to main. All changes go through a pull request.

Making a change

  1. Create a branch from main:
    git checkout main
    git pull
    git checkout -b my-feature
  2. Make your changes and commit them. Keep commits focused and atomic.
  3. Push your branch and open a pull request:
    git push -u origin my-feature
  4. CI runs automatically. Your PR must pass all checks before merging.
  5. Once approved and green, the PR is merged to main.

For maintainers: cutting a release

When main is ready to stabilize for version X.Y:

  1. Create the release branch:
    git checkout main
    git pull
    git checkout -b release/X.Y
    git push -u origin release/X.Y
  2. Bump main to the next version (e.g., 1.3.0-alpha):
    git checkout main
    # Edit inc/banjo/version.h
    git commit -am "Bump version to 1.3.0-alpha"
    git push
  3. On the release branch, progress through stages as stability improves:
    • Update version.h to -beta, -preview, -rc, then remove the pre-release suffix for stable.
    • Tag stable releases: git tag v1.2.0 && git push --tags

Language

The code is entirely in C99.

Header files and includes

Public headers live in inc/banjo/, with no subdirectories. Every header must parse standalone, with no other header required to precede it. A header must only include the headers it actually needs to parse.

Include order, each block alphabetically sorted and separated by a blank line:

  1. The header corresponding to the current implementation file (if any).
  2. Internal Banjo headers, with quotes ("").
  3. Public Banjo headers, with angle brackets (<>).
  4. Third-party headers.
  5. Standard library headers.

Doxygen

Use backslash directives only: \file, \brief, \param, \see, \snippet, never the @ form.

API conventions

  • Single namespace: every public symbol/type is prefixed bj_ / BJ_.
  • Booleans are bj_bool (a 32-bit unsigned).
  • Fallible functions take struct bj_error** as their last parameter (see Error Management).
  • Don't (void)-suppress a returned status: CERT-ERR33-C forbids it. Fold the return value into control flow.
  • Prefer bj_set_error_fmt over snprintf + bj_set_error.

Changelog

The changelog format is based on Keep a Changelog. Versioning follows Semantic Versioning.