GRM-136: refactor: rename PyPI package from gitea-runner-manager to grm

This commit is contained in:
emil
2026-07-06 06:06:13 +00:00
parent d3dbb17cc2
commit 34742bab40
43 changed files with 178 additions and 178 deletions
+3 -3
View File
@@ -2,7 +2,7 @@
GRM consists of two layers:
1. **Python CLI** (`src/gitea_runner_manager/`) — built with Click, handles argument parsing, environment loading, i18n translations, and delegates to Ansible via the `ansible-playbook` subprocess.
1. **Python CLI** (`src/grm/`) — built with Click, handles argument parsing, environment loading, i18n translations, and delegates to Ansible via the `ansible-playbook` subprocess.
2. **Ansible Role** (`ansible/roles/gitea-runner/`) — idempotent role that creates a dedicated system user, sets up rootless Docker, installs the runner binary, creates a systemd user service, and registers the runner with Gitea.
## High-Level Design
@@ -95,7 +95,7 @@ Lingering is enabled via `loginctl enable-linger` so the user's systemd services
```mermaid
flowchart TD
CLI["Python CLI<br/>src/gitea_runner_manager/<br/>(Click)"]
CLI["Python CLI<br/>src/grm/<br/>(Click)"]
RM["RunnerManager<br/>runner_manager.py"]
EXEC["Executor<br/>executor.py"]
REG["Registry<br/>registry.py<br/>~/.local/share/grm/runners.json"]
@@ -207,7 +207,7 @@ From `AGENTS.md`, the project also includes:
## Python Modules
The Python CLI layer (`src/gitea_runner_manager/`) consists of the following modules:
The Python CLI layer (`src/grm/`) consists of the following modules:
| Module | Description |
|--------|-------------|
+3 -3
View File
@@ -158,7 +158,7 @@ After a PR is merged to master, the release pipeline runs automatically.
- Runs `devx.ci.release` which uses **git-cliff** to:
- **Checks for user-facing changes** via `devx.ci.classify_changes` — if only workflow/infrastructure files changed, the release is **skipped entirely** — no version bump, no tag, no publish
- Calculate the next semver version from conventional commits since the last tag
- Update `__version__` in `src/gitea_runner_manager/__init__.py` (single source of truth)
- Update `__version__` in `src/grm/__init__.py` (single source of truth)
- Update `CHANGELOG.md` with the new version section
- **Run `make lint-ruff` and `make pytest-cov`** to verify the release is healthy
- If lint or tests fail, **abort immediately** — no commit, no tag
@@ -208,7 +208,7 @@ from accidentally skipping releases. Classification is config-driven via
`[tool.devx.classify]` in `pyproject.toml`.
**User-facing paths** (tool changes → release needed):
- `src/gitea_runner_manager/**` — Python CLI source
- `src/grm/**` — Python CLI source
- `ansible/**` — Ansible role
- `pyproject.toml` — Package metadata
@@ -322,7 +322,7 @@ From `cliff.toml` `[bump]` section:
- `breaking_always_bump_major = false`
- `initial_tag = "0.1.0"`
The version source is `__version__` in `src/gitea_runner_manager/__init__.py`, read by setuptools via `dynamic = ["version"]` in `pyproject.toml`. The release script only updates `__init__.py` — no need to touch `pyproject.toml`. `grm --version` reports this version.
The version source is `__version__` in `src/grm/__init__.py`, read by setuptools via `dynamic = ["version"]` in `pyproject.toml`. The release script only updates `__init__.py` — no need to touch `pyproject.toml`. `grm --version` reports this version.
## Title Format Summary
+3 -3
View File
@@ -27,9 +27,9 @@
- **Secrets handling**: Secrets are passed via temp JSON files with `0600` permissions, never on the command line (CWE-214). Extra-vars are written to a temporary JSON file and passed via `--extra-vars @tempfile`, which is deleted after execution. This prevents secrets from being visible in the process list (`ps aux`).
- **Linting**: `make lint-all` runs ruff + pyright + bandit + ansible-lint + checkmake + actionlint
- **Formatting**: `ruff format` with double quotes and space indentation
- **Type checking**: `pyright` in strict mode for `src/gitea_runner_manager/`
- **Type checking**: `pyright` in strict mode for `src/grm/`
- **Security scanning**: `bandit -r src/` on every PR
- **Import rules**: `src/gitea_runner_manager/` NEVER imports from devx — the GRM tool is self-contained
- **Import rules**: `src/grm/` NEVER imports from devx — the GRM tool is self-contained
## Commit Rules
@@ -216,7 +216,7 @@ Not all changes require a new release. The project classifies changes using `dev
- Lint config files, `.env.example`, `.gitignore`
**User-facing paths** (release needed):
- `src/gitea_runner_manager/**` (except `__init__.py`)
- `src/grm/**` (except `__init__.py`)
- `ansible/**`
- `pyproject.toml`
+5 -5
View File
@@ -8,7 +8,7 @@ Key technical decisions for the GRM project, extracted from `CHANGELOG.md` and `
**Date:** 2026-06-21 (v0.2.0 unreleased)
**Decision:** Use `dynamic = ["version"]` in `pyproject.toml` with setuptools `attr` to source the version from `__version__` in `src/gitea_runner_manager/__init__.py`.
**Decision:** Use `dynamic = ["version"]` in `pyproject.toml` with setuptools `attr` to source the version from `__version__` in `src/grm/__init__.py`.
**Rationale:** `__init__.py` is the single source of truth for the version. The release script (`devx.ci.release`) only updates `__init__.py` — there is no need to touch `pyproject.toml`. `grm --version` reports this version directly. This eliminates version duplication across files and ensures the runtime version always matches the tagged release.
@@ -84,7 +84,7 @@ Key technical decisions for the GRM project, extracted from `CHANGELOG.md` and `
**Rationale:** Passing secrets as command-line arguments (e.g., `--extra-vars '{"token": "..."}'`) makes them visible in the process list (`ps aux`), which is a known security weakness (CWE-214). The `RunnerManager._extra_vars_file()` context manager writes extra-vars to a temporary file via `tempfile.mkstemp()`, sets permissions to `0600`, passes the file to Ansible via `--extra-vars @tempfile`, and deletes the file in a `finally` block — even if an exception occurs. This ensures secrets are never visible in the process list.
**Source:** `AGENTS.md` (Key Conventions), `src/gitea_runner_manager/runner_manager.py` (`_extra_vars_file` method)
**Source:** `AGENTS.md` (Key Conventions), `src/grm/runner_manager.py` (`_extra_vars_file` method)
---
@@ -94,7 +94,7 @@ Key technical decisions for the GRM project, extracted from `CHANGELOG.md` and `
**Decision:** Classify changed files into user-facing and workflow-only categories using `devx.ci.classify_changes`. Only user-facing changes trigger a release; workflow-only changes (CI, docs, tests, lint config) do not.
**Rationale:** Not all changes require a new release. CI workflow updates, documentation improvements, and test additions should not produce a new version tag. The classification is config-driven via `[tool.devx.classify]` in `pyproject.toml`. The strategy is safe-by-default: any file NOT in the explicit workflow-only allowlist is treated as user-facing, preventing new file types from accidentally skipping releases. User-facing paths include `src/gitea_runner_manager/**` (except `__init__.py`) and `ansible/**`. Workflow-only paths include `.gitea/**`, `docs/**`, `tests/**`, `scripts/**`, and various config files.
**Rationale:** Not all changes require a new release. CI workflow updates, documentation improvements, and test additions should not produce a new version tag. The classification is config-driven via `[tool.devx.classify]` in `pyproject.toml`. The strategy is safe-by-default: any file NOT in the explicit workflow-only allowlist is treated as user-facing, preventing new file types from accidentally skipping releases. User-facing paths include `src/grm/**` (except `__init__.py`) and `ansible/**`. Workflow-only paths include `.gitea/**`, `docs/**`, `tests/**`, `scripts/**`, and various config files.
**Source:** `AGENTS.md` (Smart CI: User-Facing vs Workflow-Only Changes), `pyproject.toml` (`[tool.devx.classify]`)
@@ -104,9 +104,9 @@ Key technical decisions for the GRM project, extracted from `CHANGELOG.md` and `
**Date:** 2026-06-21 (v0.6.2)
**Decision:** Separate CI/CD and development tooling into the `devx` package (installed from git), keeping the GRM tool itself self-contained in `src/gitea_runner_manager/`.
**Decision:** Separate CI/CD and development tooling into the `devx` package (installed from git), keeping the GRM tool itself self-contained in `src/grm/`.
**Rationale:** The GRM CLI tool must be self-contained — it never imports from devx. This ensures the installed package has no dependency on CI infrastructure. devx MAY import from `gitea_runner_manager` (one-way dependency), as it uses the tool's API clients, config, and i18n for CI automation. Cross-module imports within devx are allowed. This separation was formalised when scripts were migrated from the `scripts/` directory to the devx package in GRM-64.
**Rationale:** The GRM CLI tool must be self-contained — it never imports from devx. This ensures the installed package has no dependency on CI infrastructure. devx MAY import from `grm` (one-way dependency), as it uses the tool's API clients, config, and i18n for CI automation. Cross-module imports within devx are allowed. This separation was formalised when scripts were migrated from the `scripts/` directory to the devx package in GRM-64.
**Source:** `AGENTS.md` (Source Code Separation and devx Integration), `CHANGELOG.md` (0.6.2 — Refactor: "Migrate from scripts/ to devx package")
+2 -2
View File
@@ -4,7 +4,7 @@
```
.
├── src/gitea_runner_manager/ # Python CLI source
├── src/grm/ # Python CLI source
│ ├── cli.py # Click commands
│ ├── runner_manager.py # Ansible orchestration + registry integration
│ ├── executor.py # Ansible subprocess execution
@@ -172,7 +172,7 @@ make test-unit # Without coverage
make pytest-cov # With 100% coverage enforcement
```
The coverage requirement is `--cov-fail-under=100` — 100% test coverage is required for all code in `src/gitea_runner_manager/`.
The coverage requirement is `--cov-fail-under=100` — 100% test coverage is required for all code in `src/grm/`.
### Integration tests
+2 -2
View File
@@ -14,9 +14,9 @@ Runs pytest with 100% coverage requirement.
From the `Makefile`:
- `test-unit` — `pytest tests/unit/ -v --no-cov` (unit tests without coverage)
- `pytest-cov` — `pytest tests/ -v --cov=src/gitea_runner_manager --cov-report=term-missing --cov-fail-under=100` (unit tests with 100% coverage enforcement)
- `pytest-cov` — `pytest tests/ -v --cov=src/grm --cov-report=term-missing --cov-fail-under=100` (unit tests with 100% coverage enforcement)
The coverage requirement is `--cov-fail-under=100` — 100% test coverage is required for all code in `src/gitea_runner_manager/`. The CI quality job runs `make pytest-cov` on every PR, and the release workflow runs it again before tagging a release.
The coverage requirement is `--cov-fail-under=100` — 100% test coverage is required for all code in `src/grm/`. The CI quality job runs `make pytest-cov` on every PR, and the release workflow runs it again before tagging a release.
### Test speed verification
+1 -1
View File
@@ -374,7 +374,7 @@ Show the installed GRM version.
grm --version
```
This reports the version from `__version__` in `src/gitea_runner_manager/__init__.py`, which is the single source of truth set by the automated release pipeline.
This reports the version from `__version__` in `src/grm/__init__.py`, which is the single source of truth set by the automated release pipeline.
## Environment Variables
+1 -1
View File
@@ -156,7 +156,7 @@ Yes. GRM is designed with security as a first-class concern:
Yes:
```bash
pip install gitea-runner-manager
pip install grm
```
This installs the `grm` CLI and its Python dependencies. The Ansible playbooks and role are bundled with the package. For development or access to Make targets, clone the repository instead.
+2 -2
View File
@@ -58,7 +58,7 @@ The registry is publicly readable — no authentication required to install.
**Quick install (one-off):**
```bash
pip install gitea-runner-manager --index-url https://git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple
pip install grm --index-url https://git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple
```
**Persistent configuration (recommended):**
@@ -73,7 +73,7 @@ extra-index-url = https://git.oblachno.oblachno.fyi/api/packages/oblachno-oss/py
Then install normally:
```bash
pip install gitea-runner-manager
pip install grm
```
This installs the `grm` CLI and its Python dependencies. The Ansible playbooks