Compare commits

..
7 Commits
Author SHA1 Message Date
grm-ci-bot 3538eb0803 release: v0.14.2 [skip ci] 2026-07-05 15:09:04 +00:00
emil 5a93559b79 GRM-132: ci: bump devx to 0.33.0, use devx-check-api-identity-checks
Post-merge / detect-type (push) Successful in 50s
Post-merge / validate-commit-msg (push) Successful in 1m5s
Post-merge / release (push) Successful in 1m11s
Post-merge / vikunja (push) Successful in 1m3s
Post-merge / badges (push) Successful in 1m17s
Post-merge / configure-repo (push) Successful in 1m3s
Post-merge / publish (push) Successful in 1m2s
Post-merge / sync-wiki (push) Successful in 2m38s
2026-07-05 15:07:03 +00:00
gitea-actions-bot e30acbe213 chore: update badge URLs to commit bdbbfb7b [skip ci] 2026-07-02 17:01:50 +00:00
emil 386f3a88c6 GRM-131: ci: remove redundant devx reinstall in doc lint step
Post-merge / detect-type (push) Successful in 1m3s
Post-merge / publish (push) Has been skipped
Post-merge / release (push) Successful in 57s
Post-merge / validate-commit-msg (push) Successful in 1m5s
Post-merge / sync-wiki (push) Successful in 2m42s
Post-merge / vikunja (push) Successful in 1m3s
Post-merge / configure-repo (push) Successful in 1m1s
Post-merge / badges (push) Successful in 1m13s
2026-07-02 16:58:01 +00:00
gitea-actions-bot e99e9d0ac8 chore: update badge URLs to commit 7e626586 [skip ci] 2026-07-01 23:40:46 +00:00
emil ca1d8e5cc0 GRM-130: fix: add pre-commit hooks for quality gates matching CI
Post-merge / detect-type (push) Successful in 1m8s
Post-merge / release (push) Successful in 1m15s
Post-merge / vikunja (push) Successful in 1m38s
Post-merge / validate-commit-msg (push) Successful in 1m44s
Post-merge / publish (push) Has been skipped
Post-merge / badges (push) Successful in 1m49s
Post-merge / sync-wiki (push) Successful in 2m28s
Post-merge / configure-repo (push) Successful in 1m21s
2026-07-01 23:37:28 +00:00
gitea-actions-bot 83e800c900 chore: update badge URLs to commit b0888676 [skip ci] 2026-07-01 23:14:33 +00:00
10 changed files with 96 additions and 23 deletions
@@ -69,3 +69,24 @@ source activate.zsh # zsh
```
If `.venv` doesn't exist, run `make setup` first.
## Common Pitfalls
### Coverage Verification Before Push
**Always run `make pytest-cov` before pushing** — CI enforces 100%
coverage and will fail the PR if any lines are uncovered. This is the
most common cause of CI quality job failures after code changes. The
pre-push git hook only validates Vikunja task existence, not tests.
### API Response Type Checking
Never use `is True`/`is False` identity checks on API response values.
Many APIs return boolean values as strings (`"true"`/`"false"`). Use
string comparison or truthy/falsy helpers instead.
### Time Mocking in Tests
Always mock `time.sleep` and `time.monotonic` in unit tests using
`@patch` decorators. Real sleep calls make tests slow and exceed test
speed limits.
+1 -6
View File
@@ -20,7 +20,7 @@ jobs:
env:
CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }}
CI_GITEA_USERNAME: ${{ vars.CI_GITEA_USERNAME }}
run: make setup-image EXTRAS=lint
run: make setup-image EXTRAS=ci,lint
- name: Lint all
run: |
. .venv/bin/activate 2>/dev/null || true
@@ -33,13 +33,8 @@ jobs:
- name: Documentation lint check
env:
PYTHONPATH: src
CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }}
CI_GITEA_USERNAME: ${{ vars.CI_GITEA_USERNAME }}
run: |
. .venv/bin/activate 2>/dev/null || true
pip install --upgrade devx \
--index-url "https://${CI_GITEA_USERNAME}:${CI_GITEA_TOKEN}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/" \
--no-deps
python3 -m devx.ci.lint_docs --root .
- name: Translation completeness check
run: |
+31
View File
@@ -57,6 +57,37 @@ repos:
pass_filenames: false
stages: [pre-commit]
- id: checkmake
name: checkmake Makefile linter
entry: make checkmake
language: system
files: ^Makefile$
pass_filenames: false
stages: [pre-commit]
- id: check-test-speed
name: unit test speed check
entry: .venv/bin/python -m devx.tools.check_test_speed --max-seconds 4 --max-single-seconds 0.5
language: system
types: [python]
pass_filenames: false
stages: [pre-commit]
- id: check-translations
name: translation completeness check
entry: env PYTHONPATH=src .venv/bin/python -m devx.ci.check_translations --translations src/gitea_runner_manager/translations.json
language: system
files: ^src/gitea_runner_manager/translations\.json$
pass_filenames: false
stages: [pre-commit]
- id: lint-docs
name: documentation lint check
entry: env PYTHONPATH=src .venv/bin/python -m devx.ci.lint_docs --root .
language: system
pass_filenames: false
stages: [pre-commit]
- id: pytest-cov
name: pytest with 100% coverage
entry: make pytest-cov
+17
View File
@@ -433,6 +433,23 @@ Change classification is config-driven via `[tool.devx.classify]` in `pyproject.
- Secrets are passed via temp JSON files, never on the command line (CWE-214)
- CI triggers only on `opened` and `synchronize` PR events (not `labeled`)
### Testing Conventions
- **Always run `make pytest-cov` before pushing** — CI enforces 100%
coverage and will fail the PR if any lines are uncovered. The pre-push
hook only validates Vikunja task existence, not tests.
- **Never use `is True`/`is False` identity checks on API response
values** — many APIs return boolean values as strings (`"true"`/
`"false"`). Use string comparison or truthy/falsy helpers instead.
- **Always mock `time.sleep` and `time.monotonic` in unit tests** — real
sleep calls make tests slow and exceed test speed limits. Use
`@patch("time.sleep")` and `@patch("time.monotonic")` decorators.
- **Extract complex inline shell from workflows to tested Python tools**
— SSH loops, curl polling, docker exec chains, and multi-line
if/then/else shell blocks should be Python scripts in `scripts/`
with unit tests. Simple variable checks and venv activation are fine
as inline shell.
### Container-Level Fix Verification (Mandatory)
**Rule:** Before pushing any fix that modifies container state (CA certs,
+6
View File
@@ -2,6 +2,12 @@
All notable changes to this project will be documented in this file.
## [0.14.2] - 2026-07-05
### Bug Fixes
- Add pre-commit hooks for quality gates matching CI
## [0.14.1] - 2026-07-01
### Refactor
+5 -2
View File
@@ -1,4 +1,4 @@
.PHONY: all setup setup-ci setup-quality setup-molecule setup-release setup-image install update lint ansible-lint makefile-lint lint-all lint-ruff lint-format lint-bandit lint-deps typecheck checkmake install-hooks test test-unit pytest-cov molecule molecule-all test-all clean workflow-lint workflow-dryrun workflow-check install-tools
.PHONY: all setup setup-ci setup-quality setup-molecule setup-release setup-image install update lint ansible-lint makefile-lint lint-all lint-ruff lint-format lint-bandit lint-deps typecheck checkmake install-hooks test test-unit pytest-cov molecule molecule-all test-all clean workflow-lint workflow-dryrun workflow-check install-tools check-api-identity-checks
.PHONY: configure-gitea-pypi
.PHONY: create-task create-pr push-with-pr git-push
@@ -173,7 +173,10 @@ makefile-lint:
echo "checkmake not found, skipping Makefile lint"; \
fi
lint-all: lint ansible-lint makefile-lint workflow-lint
lint-all: lint ansible-lint makefile-lint workflow-lint check-api-identity-checks
check-api-identity-checks:
@$(BIN)/python -m devx.tools.check_api_identity_checks
test-integration:
$(BIN)/pytest tests/integration/ -v --no-cov
+6 -6
View File
@@ -8,12 +8,12 @@ Each runner runs in an isolated **rootless Docker** environment under a dedicate
[![CI](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions/workflows/ci.yml/badge.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![License: GPL-3.0](https://img.shields.io/badge/license-GPL--3.0-blue)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/src/branch/master/LICENSE)
[![Coverage](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/627be1f191b334de9f4f83426ae3cbe6810ff69a/coverage.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Tests](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/627be1f191b334de9f4f83426ae3cbe6810ff69a/tests.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Docs](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/627be1f191b334de9f4f83426ae3cbe6810ff69a/docs.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
[![Code Quality](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/627be1f191b334de9f4f83426ae3cbe6810ff69a/quality.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Version](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/627be1f191b334de9f4f83426ae3cbe6810ff69a/version.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
[![Python](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/627be1f191b334de9f4f83426ae3cbe6810ff69a/python.svg)](https://www.python.org/downloads/)
[![Coverage](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/bdbbfb7b82a9721d5d103a1008dde317d19a82b8/coverage.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Tests](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/bdbbfb7b82a9721d5d103a1008dde317d19a82b8/tests.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Docs](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/bdbbfb7b82a9721d5d103a1008dde317d19a82b8/docs.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
[![Code Quality](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/bdbbfb7b82a9721d5d103a1008dde317d19a82b8/quality.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Version](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/bdbbfb7b82a9721d5d103a1008dde317d19a82b8/version.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
[![Python](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/bdbbfb7b82a9721d5d103a1008dde317d19a82b8/python.svg)](https://www.python.org/downloads/)
## Why GRM?
+6 -6
View File
@@ -8,12 +8,12 @@ Each runner runs in an isolated **rootless Docker** environment under a dedicate
[![CI](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions/workflows/ci.yml/badge.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![License: GPL-3.0](https://img.shields.io/badge/license-GPL--3.0-blue)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/src/branch/master/LICENSE)
[![Coverage](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/627be1f191b334de9f4f83426ae3cbe6810ff69a/coverage.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Tests](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/627be1f191b334de9f4f83426ae3cbe6810ff69a/tests.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Docs](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/627be1f191b334de9f4f83426ae3cbe6810ff69a/docs.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
[![Code Quality](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/627be1f191b334de9f4f83426ae3cbe6810ff69a/quality.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Version](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/627be1f191b334de9f4f83426ae3cbe6810ff69a/version.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
[![Python](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/627be1f191b334de9f4f83426ae3cbe6810ff69a/python.svg)](https://www.python.org/downloads/)
[![Coverage](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/bdbbfb7b82a9721d5d103a1008dde317d19a82b8/coverage.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Tests](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/bdbbfb7b82a9721d5d103a1008dde317d19a82b8/tests.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Docs](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/bdbbfb7b82a9721d5d103a1008dde317d19a82b8/docs.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
[![Code Quality](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/bdbbfb7b82a9721d5d103a1008dde317d19a82b8/quality.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Version](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/bdbbfb7b82a9721d5d103a1008dde317d19a82b8/version.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
[![Python](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/bdbbfb7b82a9721d5d103a1008dde317d19a82b8/python.svg)](https://www.python.org/downloads/)
## Overview
+2 -2
View File
@@ -34,7 +34,7 @@ ci = [
"build==1.5.0",
"twine==6.2.0",
# Reusable CI/CD and dev tools (auto-merge, pr-review, pre-push checks, etc.)
"devx==0.32.0",
"devx==0.33.1",
]
# Lint and type-checking tools (quality job)
lint = [
@@ -54,7 +54,7 @@ molecule = [
dev = [
"gitea-runner-manager[ci,lint,molecule]",
# Reusable CI/CD and dev tools (pre-push hooks, create-task, create-pr)
"devx==0.32.0",
"devx==0.33.1",
# Non-Python dev dependency: checkmake (Makefile linter)
# Install via: go install github.com/checkmake/checkmake/cmd/checkmake@latest
]
+1 -1
View File
@@ -1,3 +1,3 @@
"""Gitea Runner Manager — lean CLI for managing Gitea Actions runners."""
__version__ = "0.14.1"
__version__ = "0.14.2"