Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SPDX-FileCopyrightText: 2026 Andrew Zhang <whisper67265@outlook.com>
#
# SPDX-License-Identifier: BSL-1.0

* @whisper67265 @AuraMindNest
65 changes: 65 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# SPDX-FileCopyrightText: 2026 Andrew Zhang <whisper67265@outlook.com>
#
# SPDX-License-Identifier: BSL-1.0

name: Bug report
description: Report something that is broken or incorrect
title: '[Bug]: '
labels:
- bug
body:
- type: markdown
attributes:
value: |
Thanks for reporting a bug. Please include versions and reproduction steps.
For local test setup, see CONTRIBUTING.md in the repository root.
- type: textarea
id: description
attributes:
label: What happened?
description: Describe the bug and what you expected instead.
placeholder: When I POST to /boost-endpoint/add-or-update/, I get a 500...
validations:
required: true
- type: textarea
id: reproduction
attributes:
label: Steps to reproduce
description: Minimal steps to reproduce the behavior.
placeholder: |
1. docker compose -f docker/docker-compose.ci.yml up -d
2. curl ...
3. See error
validations:
required: true
- type: dropdown
id: environment
attributes:
label: Environment
description: Where did you observe the bug?
options:
- Local unit tests (pytest, no Docker)
- Local Docker CI stack (docker-compose.ci.yml)
- Staging deployment
- Production deployment
- Other
validations:
required: true
- type: input
id: plugin-version
attributes:
label: Plugin version
description: Version from pyproject.toml, git tag, or commit SHA
placeholder: 1.0.0 or abc1234
- type: input
id: weblate-version
attributes:
label: Weblate version
description: PyPI or Docker tag if using the Weblate stack
placeholder: 2026.5 / weblate/weblate:2026.5.0.0
- type: textarea
id: logs
attributes:
label: Relevant logs or stack traces
description: Paste error output, container logs, or pytest failure snippets.
render: shell
12 changes: 12 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# SPDX-FileCopyrightText: 2026 Andrew Zhang <whisper67265@outlook.com>
#
# SPDX-License-Identifier: BSL-1.0

blank_issues_enabled: false
contact_links:
- name: Contributing guide
url: https://github.com/cppalliance/cppa-weblate-plugin/blob/develop/CONTRIBUTING.md
about: Local dev setup, tests, and pull request expectations
- name: Maintainer handoff
url: https://github.com/cppalliance/cppa-weblate-plugin/blob/develop/docs/maintainer-handoff.md
about: Weblate coupling points and first-change walkthrough
57 changes: 57 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# SPDX-FileCopyrightText: 2026 Andrew Zhang <whisper67265@outlook.com>
#
# SPDX-License-Identifier: BSL-1.0

name: Feature request
description: Suggest a new capability or improvement
title: '[Feature]: '
labels:
- enhancement
body:
- type: markdown
attributes:
value: |
Describe the problem and proposed solution. Note whether the change belongs
in this plugin or upstream Weblate.
- type: textarea
id: problem
attributes:
label: Problem
description: What problem does this solve? Who is affected?
placeholder: Boost translators need ...
validations:
required: true
- type: textarea
id: solution
attributes:
label: Proposed solution
description: How should the plugin address this?
validations:
required: true
- type: dropdown
id: scope
attributes:
label: Scope
description: Where should this change live?
options:
- Plugin only (formats, endpoint, settings_override)
- Upstream Weblate (file an issue there instead)
- Both (plugin workaround until upstream lands)
- Documentation / tooling only
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives considered
description: Other approaches you considered and why they were rejected.
- type: checkboxes
id: areas
attributes:
label: Affected areas
description: Which parts of the plugin might this touch?
options:
- label: QuickBook format (formats/, utils/)
- label: Boost endpoint API (endpoint/)
- label: settings_override / Docker deployment
- label: CI/CD or Weblate version pin
193 changes: 193 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
<!--
SPDX-FileCopyrightText: 2026 Andrew Zhang <whisper67265@outlook.com>

SPDX-License-Identifier: BSL-1.0
-->

# Contributing

Thank you for contributing to **cppa-weblate-plugin**. This guide covers local setup, testing, and pull-request expectations so you can build and verify changes without tribal knowledge.

For maintainer roster and escalation, see [MAINTAINERS.md](MAINTAINERS.md). For non-obvious Weblate coupling points, see [docs/maintainer-handoff.md](docs/maintainer-handoff.md).

## Prerequisites

| Tool | Version / notes |
|------|-----------------|
| Python | **3.12+** (CI runs 3.12, 3.13, and 3.14) |
| [uv](https://docs.astral.sh/uv/) | Package and venv management |
| Docker + Compose | Required for plugin integration tests (`tests/plugin/`) |
| `GH_TEST_REPO_TOKEN` | Optional classic PAT with `repo` scope for GitHub-backed functional tests |

## Clone and install

```bash
git clone https://github.com/cppalliance/cppa-weblate-plugin.git
cd cppa-weblate-plugin
uv venv
source .venv/bin/activate
uv pip install -e '.[dev]'
```

## Pre-commit hooks (prek)

CI lint job runs the same hooks as [`.pre-commit-config.yaml`](.pre-commit-config.yaml) via **prek** (a pre-commit-compatible runner):

```bash
prek install
prek run --all-files --show-diff-on-failure
```

Hooks include Ruff (lint + format), YAML/TOML checks, REUSE license compliance, actionlint, and a default pytest run. Local runs should match [`.github/workflows/ci-lint.yml`](.github/workflows/ci-lint.yml).

## Unit tests

Default pytest excludes slow or environment-specific markers (`plugin`, `benchmark`, `fuzz`, `weblate_contract`) — see markers in [`pyproject.toml`](pyproject.toml):

```bash
pytest
```

Run a focused file:

```bash
pytest tests/test_settings_override.py -v
```

### Coverage gate

CI enforces **90%** coverage on `boost_weblate`:

```bash
pytest -v --tb=short \
--cov=boost_weblate \
--cov-report=term-missing \
--cov-report=xml:coverage.xml \
--cov-report=html:htmlcov \
--cov-fail-under=90
```

Open `htmlcov/index.html` locally to browse line coverage (`coverage.xml`, `htmlcov/`, and `.coverage` are gitignored).

### Test layout

| Directory | What it tests |
|-----------|---------------|
| `tests/formats/` | Format adapters and registry |
| `tests/utils/` | QuickBook parse/serialize logic |
| `tests/endpoint/` | HTTP API, serializers, services |
| `tests/plugin/` | Live Weblate Docker stack (see below) |

Add tests next to the code you touch. Keep `django.setup()`-friendly patterns; the bundled Django test settings intentionally avoid heavy DB or migration suites.

## Plugin and Docker tests

Plugin tests require a running Weblate stack built from [`docker/docker-compose.ci.yml`](docker/docker-compose.ci.yml).

### How settings-override reaches Weblate

The Docker image copies the plugin settings fragment at build time:

```dockerfile
# docker/Dockerfile.weblate-plugin
COPY src/boost_weblate/settings_override.py /app/data/settings-override.py
```

Weblate's official image `exec()`s `/app/data/settings-override.py` into the same namespace as `weblate.settings_docker`. That file registers `WEBLATE_FORMATS`, appends the endpoint Django app to `INSTALLED_APPS`, and merges throttle rates. See [docs/maintainer-handoff.md](docs/maintainer-handoff.md) for why this coupling exists.

### Running plugin tests locally

```bash
# Smoke (P0 — container boot, format registration, URL registration):
bash scripts/plugin-smoke.sh

# Auth (token auth on protected routes; ping stays public):
bash scripts/plugin-auth.sh

# Functional (QuickBook round-trip, BoostComponentService E2E, Celery flow):
export GH_TEST_REPO_TOKEN=ghp_... # optional; skips GitHub tests if unset
bash scripts/plugin-functional.sh
```

Each script builds the CI Compose stack, waits for health, runs its pytest suite, and tears down. See [`docker/README.md`](docker/README.md) and [`scripts/README.md`](scripts/README.md) for details.

### Manual Docker stack

```bash
docker compose -f docker/docker-compose.ci.yml build
docker compose -f docker/docker-compose.ci.yml up -d
# Weblate at http://localhost:8080 (admin / admin) once healthcheck passes
```

## Weblate version pin workflow

PyPI and Docker Weblate versions must stay in sync:

| File | Pin |
|------|-----|
| [`pyproject.toml`](pyproject.toml) | `Weblate[postgres]==…` |
| [`docker/Dockerfile.weblate-plugin`](docker/Dockerfile.weblate-plugin) | `FROM weblate/weblate:…` |

Verify locally:

```bash
bash scripts/check-weblate-pin-sync.sh
```

CI runs this in [`.github/workflows/ci-weblate-pin.yml`](.github/workflows/ci-weblate-pin.yml). Scheduled bumps via [`.github/workflows/weblate-pin-bump.yml`](.github/workflows/weblate-pin-bump.yml) also run [`scripts/check-weblate-internal-contract.sh`](scripts/check-weblate-internal-contract.sh) against upstream internals before opening a PR.

## Parser benchmarks

QuickBook benchmarks live in [`tests/utils/test_quickbook.py`](tests/utils/test_quickbook.py) (`@pytest.mark.benchmark`). They are excluded from default pytest and pre-commit:

```bash
uv run --group dev pytest -m benchmark --benchmark-only -v tests/utils/test_quickbook.py
```

Compare against the committed baseline and fail on regression (default 30% mean):

```bash
uv run --group dev pytest -m benchmark --benchmark-only -v \
-k "not peak_memory" \
--benchmark-compare=0001 \
--benchmark-compare-fail=mean:30% \
tests/utils/test_quickbook.py
```

Refresh the baseline after an intentional parser change. **Capture on `ubuntu-latest` (GitHub Actions)** — local machines are often faster and will not match CI. Download the `benchmark-*` artifact from a green `ci-benchmark` run, or re-run on a GitHub-hosted runner:

```bash
uv run --group dev pytest -m benchmark --benchmark-only \
-k "not peak_memory" \
--benchmark-save=baseline tests/utils/test_quickbook.py
```

Commit the updated `.benchmarks/Linux-CPython-3.14-64bit/0001_baseline.json`. If CI Python changes, regenerate the baseline (the platform directory name changes).

CI sets `BENCHMARK_COMPARE_FAIL` (default `mean:30%`) and `BENCHMARK_COMPARE_ENABLED` (default `true`; set `false` for record-only runs). See [`.github/WORKFLOWS.md`](.github/WORKFLOWS.md).

## Pull request expectations

1. Branch from **`develop`** (staging integration branch).
2. Keep changes focused; one logical change per PR.
3. Ensure CI is green (lint, test, package, Weblate pin sync, and plugin jobs as applicable).
4. Add **REUSE SPDX headers** to new source files (see existing files for format).
5. Link related issues in the PR description.
6. Respond to review feedback on the PR thread.

For your first change, follow the [first verified change walkthrough](docs/maintainer-handoff.md#first-verified-change-walkthrough) in the maintainer handoff doc.

## Where to learn more

| Topic | Location |
|-------|----------|
| Architecture overview | [README.md](README.md) |
| Weblate coupling / handoff | [docs/maintainer-handoff.md](docs/maintainer-handoff.md) |
| Refactor rationale and plan | [docs/boost-weblate-plugin-refactor-plan.md](docs/boost-weblate-plugin-refactor-plan.md) |
| Staging/production deploy | [docs/deployment-runbook.md](docs/deployment-runbook.md) |
| Boost endpoint API | [docs/boost-endpoint-api.md](docs/boost-endpoint-api.md) |
| HTTP route registration | [docs/plugin-http-routes.md](docs/plugin-http-routes.md) |
| QuickBook grammar coverage | [docs/quickbook-grammar.md](docs/quickbook-grammar.md) |
| CI/CD workflows | [`.github/WORKFLOWS.md`](.github/WORKFLOWS.md) |
| Changelog and SemVer policy | [CHANGELOG.md](CHANGELOG.md) |
| Maintainers and escalation | [MAINTAINERS.md](MAINTAINERS.md) |
53 changes: 53 additions & 0 deletions MAINTAINERS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<!--
SPDX-FileCopyrightText: 2026 Andrew Zhang <whisper67265@outlook.com>

SPDX-License-Identifier: BSL-1.0
-->

# Maintainers

## Current maintainers

Andrew Zhang and William Jin are **co-maintainers** with identical qualifications: merge rights, releases, Weblate pin decisions, and production promotion.

| Name | GitHub | Email |
|------|--------|-------|
| Andrew Zhang | [@whisper67265](https://github.com/whisper67265) | whisper67265@outlook.com |
| William Jin | [@AuraMindNest](https://github.com/AuraMindNest) | william.connects@outlook.com |

Default code review is configured in [`.github/CODEOWNERS`](.github/CODEOWNERS).

Technical coupling points for handoff are documented in [docs/maintainer-handoff.md](docs/maintainer-handoff.md).

## Escalation

If you need maintainer attention and do not receive a timely response:

1. Open a [GitHub issue](https://github.com/cppalliance/cppa-weblate-plugin/issues) and mention `@whisper67265` or `@AuraMindNest`.
2. Email either maintainer (`whisper67265@outlook.com` or `william.connects@outlook.com`).
3. If there is no response within **5 business days**, contact [C++ Alliance](https://github.com/cppalliance) org administrators through GitHub (org Settings → Members, or a private security advisory if the matter is sensitive).

## Community channels

| Channel | URL | Purpose |
|---------|-----|---------|
| Issues | [github.com/cppalliance/cppa-weblate-plugin/issues](https://github.com/cppalliance/cppa-weblate-plugin/issues) | Bug reports, feature requests |
| Pull requests | [github.com/cppalliance/cppa-weblate-plugin/pulls](https://github.com/cppalliance/cppa-weblate-plugin/pulls) | Code contributions |
| Discussions | *(enable in repo Settings)* | Design questions, announcements |
| Contributing guide | [CONTRIBUTING.md](CONTRIBUTING.md) | Local dev setup, tests, PR expectations |

### Enabling GitHub Discussions (repo admin)

Discussions cannot be turned on from committed files. A repository administrator should:

1. Go to **Settings → General → Features** and enable **Discussions**.
2. Create an **Announcements** category (maintainer-only posts) for release and Weblate pin-bump notices.
3. Optionally add a **General** category for design questions.

Point contributors to Discussions once enabled; until then, use Issues for design discussion.

## Related documentation

- [CONTRIBUTING.md](CONTRIBUTING.md) — end-to-end local dev and test setup
- [docs/maintainer-handoff.md](docs/maintainer-handoff.md) — Weblate coupling points and onboarding walkthrough
- [README.md](README.md) — architecture, CI/CD, configuration reference
Loading
Loading