Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de92f675ed | ||
|
|
b5803a8611 | ||
|
|
ec22d20a15 | ||
|
|
e96012af7f | ||
|
|
addef7500c | ||
|
|
8a0d2c428b | ||
|
|
d68fb6d272 | ||
|
|
6721864b87 | ||
|
|
06471d1403 |
@@ -178,9 +178,9 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
. .env 2>/dev/null || true
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.12.0" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.12.0" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.12.0" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.14.1" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.14.1" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.14.1" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
- name: Run automated PR review
|
||||
env:
|
||||
REPO_TOKEN: ${{ secrets.REPO_TOKEN }}
|
||||
@@ -213,9 +213,9 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
. .env 2>/dev/null || true
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.12.0" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.12.0" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.12.0" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.14.1" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.14.1" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.14.1" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
- name: Squash merge with task ID
|
||||
env:
|
||||
REPO_TOKEN: ${{ secrets.REPO_TOKEN }}
|
||||
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
. .env 2>/dev/null || true
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.12.0" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.14.1" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
- name: Check if this is a release commit
|
||||
id: check
|
||||
env:
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
. .env 2>/dev/null || true
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.12.0" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.14.1" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
- name: Validate latest commit message
|
||||
env:
|
||||
PYTHONPATH: src
|
||||
@@ -112,13 +112,8 @@ jobs:
|
||||
echo "No tag found — skipping publish"
|
||||
exit 0
|
||||
fi
|
||||
HEAD_MSG=$(git log -1 --format=%s)
|
||||
if echo "$HEAD_MSG" | grep -q "^release: ${TAG}"; then
|
||||
echo "Publishing release $TAG..."
|
||||
python3 -m devx.ci.publish "$TAG" "${{ github.repository }}"
|
||||
else
|
||||
echo "HEAD is not a release commit for $TAG — skipping publish"
|
||||
fi
|
||||
echo "Publishing release $TAG (idempotent — skips if already published)..."
|
||||
python3 -m devx.ci.publish "$TAG" "${{ github.repository }}"
|
||||
- name: Notify on failure
|
||||
if: failure()
|
||||
env:
|
||||
@@ -219,7 +214,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
. .env 2>/dev/null || true
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.12.0" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.14.1" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
- name: Update Vikunja task
|
||||
env:
|
||||
VIKUNJA_TOKEN: ${{ secrets.VIKUNJA_TOKEN }}
|
||||
@@ -251,7 +246,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
. .env 2>/dev/null || true
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.12.0" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
python3 -m pip install --break-system-packages --target=src "devx==0.14.1" --extra-index-url "https://emil:${{ secrets.REPO_TOKEN }}@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
- name: Ensure branch protection and labels
|
||||
env:
|
||||
REPO_TOKEN: ${{ secrets.REPO_TOKEN }}
|
||||
|
||||
@@ -17,11 +17,10 @@ make workflow-check # workflow-lint + workflow-dryrun
|
||||
```
|
||||
|
||||
`make setup` automatically installs all development tools:
|
||||
- **Python deps** via `devx.tools.setup` (pip install -e .[dev], ansible-galaxy, pre-commit hooks)
|
||||
- **devx package** via `make install-devx` (installs the devx package from git, providing all CI/CD tools)
|
||||
- **Python deps** via `pip install -e .[dev]` (includes devx from Gitea PyPI registry, configured by `make configure-gitea-pypi`)
|
||||
- **Post-install setup** via `devx.tools.setup --skip-install` (ansible-galaxy, pre-commit hooks, tea CLI login)
|
||||
- **checkmake** via `devx.tools.install_checkmake` (Makefile linter)
|
||||
- **actionlint, git-cliff, act_runner, tea** via `devx.tools.install_tools` (CI/CD tools to ~/.local/bin)
|
||||
- **tea CLI login** via `devx.tools.setup` (configures `tea login` from `.env` `REPO_TOKEN`)
|
||||
|
||||
## Workflow Verification (Before Push)
|
||||
|
||||
@@ -69,7 +68,7 @@ The auto-merge workflow enforces the APPROVE review check programmatically
|
||||
as a defense-in-depth measure, but branch protection is the primary gate.
|
||||
|
||||
### 1. Create Vikunja Task
|
||||
Create a task in Vikunja project 6 to get a `GRM-N` identifier.
|
||||
Create a task in Vikunja project 6 via `make create-task -- --title "Task title" --description "<h2>...</h2>"` (requires `VIKUNJA_TOKEN` in `.env`). This prints the `GRM-N` identifier and next-step instructions.
|
||||
|
||||
### 2. Create Branch
|
||||
```bash
|
||||
@@ -91,7 +90,9 @@ docs: update README
|
||||
```
|
||||
|
||||
### 5. Push and Create PR
|
||||
- **PR title format**: `GRM-N: <vikunja task title>` (must match the Vikunja task title exactly)
|
||||
- Push: `git push -u origin HEAD` (pre-push hook validates Vikunja task existence via `devx.tools.pre_push_check`)
|
||||
- Create PR: `make create-pr` (creates a PR with title `GRM-N: <vikunja task title>`, auto-derived from the branch name and Vikunja task)
|
||||
- Or both in one step: `make push-with-pr`
|
||||
- PR body: summary of changes, `Closes GRM-N`
|
||||
- Add `ready-to-merge` label **only after review is complete**
|
||||
|
||||
@@ -160,13 +161,13 @@ Then add the `ready-to-merge` label. The auto-merge workflow will:
|
||||
1. **Validate** PR title format (`GRM-N: <vikunja task title>`) and match against Vikunja task title
|
||||
2. **Check** that at least one substantive APPROVE review exists (body > 20 chars or has inline comments)
|
||||
3. Wait for all CI checks to pass (including the `pr-review` job)
|
||||
4. Squash-merge with title: `GRM-N <conventional commit message>` (space-separated, no colon after GRM-N)
|
||||
4. Squash-merge with title: `GRM-N: <conventional commit message>`
|
||||
5. The post-merge workflow marks the Vikunja task as done
|
||||
6. The release workflow automatically versions, tags, and publishes (see below)
|
||||
|
||||
> **IMPORTANT**: Never manually merge PRs via the API. Always use the auto-merge
|
||||
> workflow by adding the `ready-to-merge` label. Manual merges bypass the
|
||||
> `GRM-N <conventional>` format enforcement, producing incorrectly named commits.
|
||||
> `GRM-N: <conventional>` format enforcement, producing incorrectly named commits.
|
||||
> The auto-merge script validates the PR title matches the Vikunja task ID
|
||||
> and conventional commit format before merging.
|
||||
|
||||
@@ -361,8 +362,8 @@ avoids dev tools importing directly from CI modules.
|
||||
|
||||
### git-cliff Commit Preprocessing
|
||||
|
||||
Merge commits on master have the format `GRM-N <conventional commit>`. The
|
||||
`GRM-N ` prefix is not a valid conventional commit prefix, so `cliff.toml`
|
||||
Merge commits on master have the format `GRM-N: <conventional commit>`. The
|
||||
`GRM-N: ` prefix is not a valid conventional commit prefix, so `cliff.toml`
|
||||
includes a `commit_preprocessors` entry that strips it before parsing. This
|
||||
ensures all merged work appears in the changelog.
|
||||
|
||||
@@ -384,7 +385,7 @@ The version source is `__version__` in `src/gitea_runner_manager/__init__.py`, r
|
||||
| Branch name | `GRM-N-short-description` | `GRM-33-add-pr-review-step` |
|
||||
| Branch commits | `<conventional commit>` | `feat: add review script` |
|
||||
| PR title | `GRM-N: <vikunja task title>` | `GRM-33: Add mandatory PR review step` |
|
||||
| Merge commit | `GRM-N <conventional commit>` | `GRM-33 feat: add review script` |
|
||||
| Merge commit | `GRM-N: <conventional commit>` | `GRM-33: feat: add review script` |
|
||||
|
||||
### Configuration
|
||||
|
||||
|
||||
@@ -2,6 +2,16 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [0.10.0] - 2026-06-26
|
||||
|
||||
### Features
|
||||
|
||||
- Adopt devx tools, devx.mak fragment, ci extra, remove legacy install-devx
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- Always run publish in post-merge (idempotent)
|
||||
|
||||
## [0.9.0] - 2026-06-24
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
.PHONY: all setup setup-ci setup-quality setup-molecule setup-release install-devx install update lint ansible-lint makefile-lint lint-all 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 install update lint ansible-lint makefile-lint lint-all test test-unit pytest-cov molecule molecule-all test-all clean workflow-lint workflow-dryrun workflow-check install-tools
|
||||
.PHONY: configure-gitea-pypi
|
||||
.PHONY: create-task create-pr push-with-pr git-push
|
||||
|
||||
PYTHON := python3
|
||||
VENV := .venv
|
||||
@@ -7,45 +9,57 @@ CHECKMAKE := $(shell command -v checkmake 2>/dev/null || echo $(HOME)/go/bin/che
|
||||
|
||||
all: setup
|
||||
|
||||
# Pinned devx version — update this when upgrading devx.
|
||||
# All workflow files (.gitea/workflows/*.yml) must be updated to match.
|
||||
DEVX_VERSION := v0.12.0
|
||||
# Helper: run pip install with Gitea registry configured
|
||||
# Usage: $(PIP_INSTALL) install -e '.[ci,lint]'
|
||||
PIP_INSTALL := if [ -z "$$REPO_TOKEN" ]; then . ./.env 2>/dev/null; fi; \
|
||||
REPO_TOKEN="$${REPO_TOKEN:-$$GITEA_REGISTRY_TOKEN}"; \
|
||||
if [ -n "$$REPO_TOKEN" ]; then export PIP_EXTRA_INDEX_URL="https://emil:$$REPO_TOKEN@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"; fi; \
|
||||
$(BIN)/pip
|
||||
|
||||
install-devx: $(VENV)/bin/activate
|
||||
@# REPO_TOKEN may come from .env (local) or environment (CI secrets)
|
||||
# Configure Gitea private PyPI registry so pip can find devx and other
|
||||
# private packages. In CI, REPO_TOKEN is set as a secret. Locally, it's in .env.
|
||||
configure-gitea-pypi:
|
||||
@if [ -z "$$REPO_TOKEN" ]; then . ./.env 2>/dev/null; fi; \
|
||||
if [ -z "$$REPO_TOKEN" ]; then echo "REPO_TOKEN not set (check .env or environment)"; exit 1; fi; \
|
||||
$(BIN)/pip install "devx==$(shell echo $(DEVX_VERSION) | sed 's/^v//')" \
|
||||
--extra-index-url "https://emil:$$REPO_TOKEN@git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple/"
|
||||
REPO_TOKEN="$${REPO_TOKEN:-$$GITEA_REGISTRY_TOKEN}"; \
|
||||
if [ -z "$$REPO_TOKEN" ]; then echo "[configure-gitea-pypi] REPO_TOKEN not set — skipping (devx must be on public PyPI)"; exit 0; fi; \
|
||||
echo "[configure-gitea-pypi] Gitea PyPI registry configured (REPO_TOKEN present)."
|
||||
|
||||
# Full setup for local development (all deps, tools, collections, hooks)
|
||||
# install-devx must run before install-tools (which uses devx modules)
|
||||
setup: $(VENV)/bin/activate .env activate-scripts install-devx checkmake install-tools
|
||||
# devx is installed via pip install -e .[dev] (devx is in dev extra)
|
||||
setup: $(VENV)/bin/activate .env activate-scripts configure-gitea-pypi
|
||||
@$(PIP_INSTALL) install -e '.[dev]'
|
||||
@$(BIN)/python -m devx.tools.install_checkmake
|
||||
@$(BIN)/python -m devx.tools.install_tools
|
||||
@export PATH="$(HOME)/.local/bin:$$PATH"; \
|
||||
$(BIN)/python -m devx.tools.setup --bin "$(BIN)"
|
||||
$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --skip-install
|
||||
|
||||
# Lean setup for CI jobs that need pytest + lint tools + runtime deps
|
||||
# (detect-changes, discover-runners, pr-review, sync-wiki, badges)
|
||||
# badges job runs generate_badges.py which needs ruff, pyright, bandit
|
||||
setup-ci: $(VENV)/bin/activate .env install-devx
|
||||
@$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --extras "ci,lint" --no-ansible-collections --no-pre-commit --no-tea-login
|
||||
setup-ci: $(VENV)/bin/activate .env configure-gitea-pypi
|
||||
@$(PIP_INSTALL) install -e '.[ci,lint]'
|
||||
@$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --skip-install --no-ansible-collections --no-pre-commit --no-tea-login
|
||||
|
||||
# Setup for the quality job (lint + test deps, actionlint tool)
|
||||
# install-devx must run before install-tools (which uses devx modules)
|
||||
setup-quality: $(VENV)/bin/activate .env install-devx install-tools
|
||||
setup-quality: $(VENV)/bin/activate .env configure-gitea-pypi
|
||||
@$(PIP_INSTALL) install -e '.[ci,lint]'
|
||||
@$(BIN)/python -m devx.tools.install_tools
|
||||
@export PATH="$(HOME)/.local/bin:$$PATH"; \
|
||||
$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --extras "ci,lint" --no-ansible-collections --no-pre-commit --no-tea-login
|
||||
$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --skip-install --no-ansible-collections --no-pre-commit --no-tea-login
|
||||
|
||||
# Full setup for molecule testing (needs ansible, molecule, collections)
|
||||
setup-molecule: $(VENV)/bin/activate .env install-devx install-tools
|
||||
setup-molecule: $(VENV)/bin/activate .env configure-gitea-pypi
|
||||
@$(PIP_INSTALL) install -e '.[ci,molecule]'
|
||||
@$(BIN)/python -m devx.tools.install_tools
|
||||
@export PATH="$(HOME)/.local/bin:$$PATH"; \
|
||||
$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --extras "ci,molecule" --no-pre-commit --no-tea-login
|
||||
$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --skip-install --no-pre-commit --no-tea-login
|
||||
|
||||
# Setup for release jobs (needs git-cliff, tea, and lint tools for release.py)
|
||||
setup-release: $(VENV)/bin/activate .env install-devx
|
||||
setup-release: $(VENV)/bin/activate .env configure-gitea-pypi
|
||||
@$(PIP_INSTALL) install -e '.[ci,lint]'
|
||||
@$(BIN)/python -m devx.tools.install_tools --tool git-cliff --tool tea
|
||||
@export PATH="$(HOME)/.local/bin:$$PATH"; \
|
||||
$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --extras "ci,lint" --no-ansible-collections --no-pre-commit
|
||||
$(BIN)/python -m devx.tools.setup --bin "$(BIN)" --skip-install --no-ansible-collections --no-pre-commit
|
||||
|
||||
.env:
|
||||
@if [ ! -f .env ]; then \
|
||||
@@ -64,14 +78,14 @@ activate-scripts: $(VENV)/bin/activate
|
||||
@test -f activate.zsh || (echo '#!/usr/bin/env zsh' > activate.zsh && echo '0="$${ZERO:-$${0:#$$ZSH_ARGZERO}}"' >> activate.zsh && echo '0="$${$${(M)0:#/*}:-$$PWD/$$0}"' >> activate.zsh && echo 'source "$${0:A:h}/.venv/bin/activate"' >> activate.zsh && chmod +x activate.zsh)
|
||||
|
||||
install-hooks:
|
||||
@cp hooks/pre-commit .git/hooks/pre-commit && chmod +x .git/hooks/pre-commit
|
||||
@cp hooks/pre-push .git/hooks/pre-push && chmod +x .git/hooks/pre-push
|
||||
@echo "Git hooks installed."
|
||||
@git config core.hooksPath hooks
|
||||
@chmod +x hooks/pre-commit hooks/pre-push 2>/dev/null || true
|
||||
@echo "core.hooksPath set to hooks/ — tracked hooks are now live."
|
||||
|
||||
checkmake: install-devx
|
||||
checkmake:
|
||||
@$(BIN)/python -m devx.tools.install_checkmake
|
||||
|
||||
install-tools: install-devx
|
||||
install-tools:
|
||||
@$(BIN)/python -m devx.tools.install_tools
|
||||
|
||||
install:
|
||||
@@ -181,3 +195,21 @@ clean:
|
||||
find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true
|
||||
find . -type f -name "*.pyc" -delete 2>/dev/null || true
|
||||
rm -rf .coverage htmlcov/ .molecule/
|
||||
|
||||
# --- Vikunja task and PR management (via devx.mak fragment) -------------------
|
||||
# Project config (task prefix, Vikunja project ID, repo owner/name) is read
|
||||
# from [tool.devx] in pyproject.toml by devx.config — no Makefile variables needed.
|
||||
DEVX_PYTHON := $(BIN)/python
|
||||
|
||||
# Include shared targets from devx package (create-task, create-pr, push-with-pr, check-config)
|
||||
# Silent if devx not installed yet — run 'make setup' first.
|
||||
DEVX_MAK := $(shell $(BIN)/python -c \
|
||||
"from pathlib import Path; import devx; print(Path(devx.__file__).parent / 'make' / 'devx.mak')" \
|
||||
2>/dev/null)
|
||||
-include $(DEVX_MAK)
|
||||
|
||||
# Aliases for project-specific target names
|
||||
create-task: devx-create-task
|
||||
create-pr: devx-create-pr
|
||||
push-with-pr: devx-push-with-pr
|
||||
git-push: devx-push
|
||||
|
||||
@@ -8,12 +8,12 @@ Each runner runs in an isolated **rootless Docker** environment under a dedicate
|
||||
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/src/branch/master/LICENSE)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
|
||||
[](https://www.python.org/downloads/)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
|
||||
[](https://www.python.org/downloads/)
|
||||
|
||||
## Why GRM?
|
||||
|
||||
|
||||
+6
-6
@@ -8,12 +8,12 @@ Each runner runs in an isolated **rootless Docker** environment under a dedicate
|
||||
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/src/branch/master/LICENSE)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
|
||||
[](https://www.python.org/downloads/)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
|
||||
[](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
|
||||
[](https://www.python.org/downloads/)
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
+60
-5
@@ -1,6 +1,61 @@
|
||||
#!/usr/bin/env bash
|
||||
# pre-push hook: fail if unit tests are too slow.
|
||||
# Checks both total suite time (10s) and per-test time (0.5s).
|
||||
# Aligned with CI (ci.yml uses same thresholds).
|
||||
set -e
|
||||
python3 -m devx.tools.check_test_speed --max-seconds 4 --max-single-seconds 0.5
|
||||
# pre-push hook: validate Vikunja task exists and tests are fast.
|
||||
#
|
||||
# This catches issues that would otherwise only surface in CI:
|
||||
# - Branch name missing task ID (e.g., GRM-N)
|
||||
# - Vikunja task does not exist for the task ID in the branch name
|
||||
# - Unit tests too slow (total > 4s, per-test > 0.5s)
|
||||
#
|
||||
# Uses devx.tools.pre_push_check for reusable validation logic.
|
||||
# Project config (task prefix, Vikunja project ID) is read from
|
||||
# [tool.devx] in pyproject.toml by devx.config — no hardcoded values here.
|
||||
#
|
||||
# Bootstrap resilience: if devx is not importable (e.g., during devx
|
||||
# upgrades), the hook prints a warning and allows the push.
|
||||
|
||||
# Determine the branch being pushed
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")
|
||||
|
||||
if [ -z "$BRANCH" ] || [ "$BRANCH" = "master" ] || [ "$BRANCH" = "main" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Load .env if present (for VIKUNJA_TOKEN)
|
||||
if [ -f .env ]; then
|
||||
set -a
|
||||
# shellcheck disable=SC1091
|
||||
. .env
|
||||
set +a
|
||||
fi
|
||||
|
||||
# Find the Python interpreter with devx installed
|
||||
if [ -f .venv/bin/python ]; then
|
||||
PY=.venv/bin/python
|
||||
elif [ -x "${HOME}/.pyenv/bin/pyenv" ]; then
|
||||
export PYENV_ROOT="${HOME}/.pyenv"
|
||||
export PATH="${PYENV_ROOT}/bin:${PYENV_ROOT}/shims:${PATH}"
|
||||
eval "$("${PYENV_ROOT}/bin/pyenv" init -)" 2>/dev/null || true
|
||||
eval "$("${PYENV_ROOT}/bin/pyenv" virtualenv-init -)" 2>/dev/null || true
|
||||
pyenv activate gitea-runner-manager 2>/dev/null || true
|
||||
PY=python3
|
||||
else
|
||||
PY=python3
|
||||
fi
|
||||
|
||||
# Bootstrap resilience: if devx is not importable, warn but allow the push
|
||||
if ! $PY -c "import devx.tools.pre_push_check" 2>/dev/null; then
|
||||
echo "WARNING: devx not installed — pre-push check skipped."
|
||||
echo "Run 'make setup' to install devx."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Run pre-push validation via devx
|
||||
$PY -m devx.tools.pre_push_check --branch "$BRANCH" || {
|
||||
echo ""
|
||||
echo "Pre-push validation failed. Fix the issues above before pushing."
|
||||
echo "To bypass (NOT recommended): git push --no-verify"
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check test speed (aligned with CI thresholds)
|
||||
$PY -m devx.tools.check_test_speed --max-seconds 4 --max-single-seconds 0.5
|
||||
|
||||
@@ -34,6 +34,8 @@ ci = [
|
||||
"pytest-cov>=7.1.0",
|
||||
"build>=1.5.0",
|
||||
"twine>=6.2.0",
|
||||
# Reusable CI/CD and dev tools (auto-merge, pr-review, pre-push checks, etc.)
|
||||
"devx>=0.15.0",
|
||||
]
|
||||
# Lint and type-checking tools (quality job)
|
||||
lint = [
|
||||
@@ -52,6 +54,8 @@ molecule = [
|
||||
# Full dev environment (local development, includes everything)
|
||||
dev = [
|
||||
"gitea-runner-manager[ci,lint,molecule]",
|
||||
# Reusable CI/CD and dev tools (pre-push hooks, create-task, create-pr)
|
||||
"devx>=0.15.0",
|
||||
# Non-Python dev dependency: checkmake (Makefile linter)
|
||||
# Install via: go install github.com/checkmake/checkmake/cmd/checkmake@latest
|
||||
]
|
||||
@@ -91,6 +95,13 @@ strict = ["src/gitea_runner_manager"]
|
||||
# Change classification — determines which changes trigger a release
|
||||
# ---------------------------------------------------------------------------
|
||||
# The framework provides DEFAULT_INFRASTRUCTURE (CI workflows, tests, docs,
|
||||
# Project-specific devx configuration (read by devx.config)
|
||||
[tool.devx]
|
||||
task_prefix = "GRM"
|
||||
vikunja_project_id = 6
|
||||
repo_owner = "oblachno-oss"
|
||||
repo_name = "gitea-runner-manager"
|
||||
|
||||
# lint config, etc.) that applies to any Python project. We only specify
|
||||
# what's different about GRM.
|
||||
[tool.devx.classify]
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
"""Gitea Runner Manager — lean CLI for managing Gitea Actions runners."""
|
||||
|
||||
__version__ = "0.9.0"
|
||||
__version__ = "0.10.0"
|
||||
|
||||
Reference in New Issue
Block a user