Skip to content

Latest commit

 

History

History
190 lines (129 loc) · 9.29 KB

File metadata and controls

190 lines (129 loc) · 9.29 KB

Contributing Guidelines

Thank you for your interest in contributing to this project. Community involvement is highly valued and crucial for the project's growth and success. This project accepts contributions via GitHub pull requests. This document outlines the process to help get your contribution accepted.

To ensure a clear direction and cohesive vision for the project, the project leads have the final decision on all contributions. However, these guidelines outline how you can contribute effectively.

How You Can Contribute

There are several ways you can contribute:

  • Reporting Issues: Help us identify and fix bugs by reporting them clearly and concisely.
  • Suggesting Features: Share your ideas for new features or improvements.
  • Improving Documentation: Help make the project more accessible by enhancing the documentation.
  • Submitting Code Contributions: Code contributions that align with the project's vision are always welcome.

Code of Conduct

This project adheres to the Code of Conduct and Covenant. By participating, you are expected to uphold this code.

Community and Communication

Contributing Process

We follow a lazy consensus approach: changes proposed by people with responsibility for a problem, without disagreement from others, within a bounded time window of review by their peers, should be accepted.

Types of Contributions

1. Features with Public APIs or New Components

All features involving public APIs, behavior between core components, or new core subsystems must be accompanied by an approved project proposal.

Process:

  1. Create a pull request adding a proposal document under ./docs/proposals/ with a descriptive name
  2. Include these sections: Summary, Motivation (Goals/Non-Goals), Proposal, Design Details, Alternatives
  3. Get review from impacted component maintainers
  4. Get approval from project maintainers

2. Fixes, Issues, and Bugs

For changes that fix broken code or add small changes within a component:

  • All bugs and commits must have a clear description of the bug, how to reproduce, and how the change is made
  • Any other changes can be proposed in a pull request — a maintainer must approve the change
  • For moderate size changes, create an RFC issue in GitHub, then engage in Slack

Code Review Requirements

  • All code changes must be submitted as pull requests (no direct pushes)
  • All changes must be reviewed and approved by a maintainer other than the author
  • All repositories must gate merges on compilation and passing tests
  • All experimental features must be off by default and require explicit opt-in

Commit and Pull Request Style

  • Pull requests should describe the problem succinctly
  • Rebase and squash before merging
  • Use minimal commits and break large changes into distinct commits
  • Commit messages should have:
    • Short, descriptive titles
    • Description of why the change was needed
    • Enough detail for someone reviewing git history to understand the scope
  • DCO Sign-off: All commits must include a valid DCO sign-off line (Signed-off-by: Name <email@domain.com>)

Code Organization and Ownership

  • Components are the primary unit of code organization
  • Maintainers own components and approve changes
  • Contributors can become maintainers through sufficient evidence of contribution
  • Code ownership is reflected in OWNERS files consistent with Kubernetes project conventions

Testing Requirements

We use three tiers of testing:

  1. Unit tests: Fast verification of code parts, testing different arguments
  2. Integration tests: Testing protocols between components and built artifacts
  3. End-to-end (e2e) tests: Whole system testing including benchmarking

Strong e2e coverage is required for deployed systems to prevent performance regression. Appropriate test coverage is an important part of code review.

Running Tests Locally

# Unit tests (default, no external dependencies)
make test

# Integration tests (each test spawns its own in-process mock server)
make test-integration

# Both unit and integration tests
make test-all

# E2E tests (requires docker/podman, kind, helm, kubectl)
make test-e2e

Integration tests use the //go:build integration build tag and live in test/integration/. They are excluded from make test and only run when the tag is explicitly passed via make test-integration. Each test spawns its own mock server (miniredis, httptest.Server) — no external services are required.

To add a new integration test, create a *_test.go file in test/integration/ with the build tag:

//go:build integration

package integration_test

Releasing

This repository is a multi-module Go repo. The lightweight sub-modules (api, pipeline, producer) each have their own go.mod so that external consumers can depend on them without pulling in the heavyweight root module.

Preparing a release

  1. Update cross-module version references:
make set-version VERSION=v0.8.0

This rewrites all require directives across go.mod files and runs go mod tidy. Sub-modules are detected automatically from subdirectories containing a go.mod.

  1. Commit the result and push a tag on the root module:
git tag v0.8.0
git push origin v0.8.0
  1. The CI - Tag Go Submodules workflow automatically creates the prefixed tags required by Go modules (e.g. api/v0.8.0, pipeline/v0.8.0, producer/v0.8.0).

Go requires sub-module tags to carry the directory prefix — see Managing module source for details.

Release notes

User-facing changes are recorded as per-PR fragments and assembled into RELEASE-NOTES.md at each release. One fragment file per PR keeps this conflict-free.

  1. Fill the release-note block in the PR description (write NONE if there is no user-facing impact).

  2. For a user-facing change, add a fragment at release-notes.d/unreleased/<PR-number>.md:

    ---
    pr: 123
    url: https://github.com/llm-d-incubation/llm-d-async/pull/123
    author: your-handle
    date: 2026-07-09
    ---
    Short description of the change. Prefix breaking changes with `Breaking:`.
  3. make release-notes-lint validates fragment format (also enforced in CI via pre-commit).

At release time — as part of Preparing a release — a maintainer runs make release-notes VERSION=vX.Y.Z, which moves the unreleased fragments into a new RELEASE vX.Y.Z <date> section at the top of RELEASE-NOTES.md and deletes them. Commit the result with the release.

Go Conventions

These conventions are enforced by linters where possible (see .golangci.yml) and by code review otherwise.

  1. No mutable package globals. Use unexported state with constructors and accessors. Exceptions: Prometheus metric registrations (pkg/metrics/) and build-time version vars (pkg/version/).
  2. Compile-time interface assertions. Every interface implementation (and test fake) must include var _ Interface = (*Impl)(nil) to catch breakage at compile time, not at runtime.
  3. Wrap errors with context. When returning an error from an external package, wrap it: fmt.Errorf("doing X: %w", err). This makes logs actionable.
  4. YAGNI. Don't add exported functions, methods, or types without a caller in this repo. Unused API surface is maintenance burden.
  5. Porting rule. When adapting code from EPP or another repo, strip it to what is actually called and re-fit it to local idioms before opening the PR.

Security

See SECURITY.md for our vulnerability disclosure process.

API Changes and Deprecation

  • No breaking changes: Once an API/protocol is in GA release, it cannot be removed or behavior changed
  • Versioning: All protocols and APIs should be versionable with clear compatibility requirements
  • Documentation: All APIs must have documented specs describing expected behavior
  • Deprecation policy (N+2): A feature deprecated in release N must keep working — with no user-facing or configuration change required — through releases N and N+1, emitting a clear warning, and may be removed no earlier than release N+2. Record the deprecation (and any breaking change) in the PR's release note.