Compare commits

...
27 Commits
Author SHA1 Message Date
grm-ci-bot de92f675ed release: v0.10.0
Post-merge / detect-type (push) Successful in 13s
Post-merge / validate-commit-msg (push) Has been skipped
Post-merge / release (push) Has been skipped
Post-merge / configure-repo (push) Has been skipped
Post-merge / sync-wiki (push) Has been skipped
Post-merge / vikunja (push) Has been skipped
Publish Release / publish (push) Failing after 16s
Post-merge / badges (push) Successful in 1m55s
2026-06-26 17:16:19 +02:00
emil b5803a8611 GRM-91: feat: adopt devx tools, devx.mak fragment, ci extra, remove legacy install-devx
Post-merge / detect-type (push) Successful in 10s
Post-merge / validate-commit-msg (push) Successful in 10s
Post-merge / configure-repo (push) Successful in 12s
Post-merge / release (push) Successful in 1m41s
Post-merge / vikunja (push) Successful in 12s
Post-merge / badges (push) Successful in 1m37s
Post-merge / sync-wiki (push) Successful in 2m0s
2026-06-26 15:14:33 +00:00
gitea-actions-bot ec22d20a15 chore: update badge URLs to commit 47c7e239 [skip ci] 2026-06-26 12:03:12 +02:00
emil e96012af7f GRM-90: ci: bump devx version to v0.14.1
Post-merge / detect-type (push) Successful in 9s
Post-merge / validate-commit-msg (push) Successful in 6s
Post-merge / configure-repo (push) Successful in 7s
Post-merge / release (push) Successful in 1m29s
Post-merge / vikunja (push) Successful in 13s
Post-merge / badges (push) Successful in 1m23s
Post-merge / sync-wiki (push) Successful in 2m0s
2026-06-26 10:00:03 +00:00
gitea-actions-bot addef7500c chore: update badge URLs to commit dd820c3d [skip ci] 2026-06-26 00:13:49 +02:00
emil 8a0d2c428b GRM-88: docs: fix AGENTS.md squash-merge format to use colon after task ID
Post-merge / detect-type (push) Successful in 10s
Post-merge / validate-commit-msg (push) Successful in 12s
Post-merge / configure-repo (push) Successful in 10s
Post-merge / release (push) Failing after 1m16s
Post-merge / sync-wiki (push) Has been skipped
Post-merge / vikunja (push) Has been skipped
Post-merge / badges (push) Successful in 1m8s
2026-06-25 22:11:11 +00:00
gitea-actions-bot d68fb6d272 chore: update badge URLs to commit 9b029d3a [skip ci] 2026-06-25 23:17:41 +02:00
emil 6721864b87 GRM-87: fix: always run publish in post-merge (idempotent) 2026-06-25 21:15:03 +00:00
gitea-actions-bot 06471d1403 chore: update badge URLs to commit c61f4cb6 [skip ci] 2026-06-25 01:23:53 +02:00
grm-ci-bot 1a04971622 release: v0.9.0 [skip ci] 2026-06-25 01:22:18 +02:00
emil 91440c1b0a GRM-86: feat: add Polish as officially supported language 2026-06-24 23:20:59 +00:00
gitea-actions-bot 3bb8d75748 chore: update badge URLs to commit ea0b5002 [skip ci] 2026-06-24 22:53:41 +00:00
emil d4a8172a25 GRM-85: docs: add Gitea PyPI registry instructions for pip install 2026-06-24 22:51:10 +00:00
gitea-actions-bot 2199ec0bfe chore: update badge URLs to commit b70a95f6 [skip ci] 2026-06-25 00:42:14 +02:00
emil 9ae9a76b11 GRM-84: feat: adopt devx v0.11.1 across Makefile and workflows 2026-06-24 22:39:35 +00:00
gitea-actions-bot 31d0eeae98 chore: update badge URLs to commit eaa85dd7 [skip ci] 2026-06-25 00:31:14 +02:00
grm-ci-bot acc768eaea release: v0.8.1 [skip ci] 2026-06-25 00:29:27 +02:00
emil cf2314c20f GRM-83: fix: add build/twine to ci deps, activate venv in notify_failure 2026-06-24 22:28:08 +00:00
gitea-actions-bot aac47e3472 chore: update badge URLs to commit a7a72d7d [skip ci] 2026-06-25 00:14:31 +02:00
emil 811e7a2309 GRM-82: fix: repair publish workflow and add publish step to post-merge 2026-06-24 22:11:48 +00:00
gitea-actions-bot cb68c85bb5 chore: update badge URLs to commit 123065d0 [skip ci] 2026-06-24 21:06:40 +00:00
emil 0ba30e09ea GRM-81: ci: update devx to v0.10.2 for badge testpaths fix 2026-06-24 21:03:53 +00:00
gitea-actions-bot 6a02581687 chore: update badge URLs to commit e32f1c05 [skip ci] 2026-06-24 22:45:35 +02:00
grm-ci-bot 4679473183 release: v0.8.0 [skip ci] 2026-06-24 22:44:06 +02:00
emil 6359eab962 GRM-80: ci: update devx to v0.10.1 for badge generation fix 2026-06-24 20:42:27 +00:00
emil 2017a5ee3e GRM-79: feat: remove .taskid file, use branch name only for task ID 2026-06-24 20:15:59 +00:00
emil 465e9bd484 GRM-78: fix: add workflow_dispatch to publish workflow and update devx to 0.9.12 2026-06-24 20:05:54 +00:00
18 changed files with 433 additions and 161 deletions
+11 -8
View File
@@ -24,6 +24,10 @@ jobs:
run: |
. .venv/bin/activate
make pytest-cov
- name: Translation completeness check
run: |
. .venv/bin/activate
python3 -m devx.ci.check_translations --translations src/gitea_runner_manager/translations.json
- name: Check unit test speed
env:
PYTHONPATH: src
@@ -174,9 +178,9 @@ jobs:
- name: Install dependencies
run: |
. .env 2>/dev/null || true
python3 -m pip install --break-system-packages --target=src "devx==0.9.11" --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.9.11" --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.9.11" --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 }}
@@ -189,8 +193,7 @@ jobs:
auto-merge:
# Auto-merge runs after all CI checks pass. It reads the task ID
# from the branch name (falling back to .taskid file), validates
# the PR title, and squash-merges.
# from the branch name, validates the PR title, and squash-merges.
# Uses always() so it evaluates even when molecule-tests is skipped
# (Gitea Actions skips dependent jobs of skipped jobs by default).
needs: [quality, detect-changes, pr-review, molecule-tests]
@@ -210,9 +213,9 @@ jobs:
- name: Install dependencies
run: |
. .env 2>/dev/null || true
python3 -m pip install --break-system-packages --target=src "devx==0.9.11" --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.9.11" --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.9.11" --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 }}
+20 -13
View File
@@ -43,9 +43,7 @@ jobs:
- name: Install dependencies
run: |
. .env 2>/dev/null || true
python3 -m pip install --break-system-packages --target=src "devx==0.9.11" --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.9.11" --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.9.11" --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:
@@ -64,9 +62,7 @@ jobs:
- name: Install dependencies
run: |
. .env 2>/dev/null || true
python3 -m pip install --break-system-packages --target=src "devx==0.9.11" --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.9.11" --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.9.11" --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
@@ -80,7 +76,7 @@ jobs:
needs: [detect-type]
if: needs.detect-type.outputs.is-release == 'false'
runs-on: docker
timeout-minutes: 10
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
with:
@@ -104,12 +100,27 @@ jobs:
. .venv/bin/activate
export PATH="$HOME/.local/bin:$PATH"
python3 -m devx.ci.release
- name: Publish release
env:
REPO_TOKEN: ${{ secrets.REPO_TOKEN }}
PYTHONPATH: src
run: |
. .venv/bin/activate
export PATH="$HOME/.local/bin:$PATH"
TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -z "$TAG" ]; then
echo "No tag found — skipping publish"
exit 0
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:
REPO_TOKEN: ${{ secrets.REPO_TOKEN }}
PYTHONPATH: src
run: |
. .venv/bin/activate 2>/dev/null || true
export PATH="$HOME/.local/bin:$PATH"
python3 -m devx.tools.install_tools --tool tea
python3 -m devx.ci.notify_failure --auto-login \
@@ -203,9 +214,7 @@ jobs:
- name: Install dependencies
run: |
. .env 2>/dev/null || true
python3 -m pip install --break-system-packages --target=src "devx==0.9.11" --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.9.11" --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.9.11" --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 }}
@@ -237,9 +246,7 @@ jobs:
- name: Install dependencies
run: |
. .env 2>/dev/null || true
python3 -m pip install --break-system-packages --target=src "devx==0.9.11" --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.9.11" --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.9.11" --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 }}
+10 -5
View File
@@ -4,6 +4,12 @@ on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to publish (e.g. v0.7.0)'
required: true
type: string
jobs:
publish:
@@ -16,9 +22,7 @@ jobs:
- name: Install CI tools
run: |
. .env 2>/dev/null || true
python3 -m pip install --break-system-packages --target=src "devx==0.9.11" --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.9.11" --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.9.11" --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 devx.tools.install_tools --tool git-cliff --tool tea
- name: Install build tools
run: python3 -m pip install --break-system-packages build twine
@@ -27,15 +31,16 @@ jobs:
REPO_TOKEN: ${{ secrets.REPO_TOKEN }}
run: |
export PATH="$HOME/.local/bin:$PATH"
tea login add --name grm --url "${{ github.server_url }}" --token "$REPO_TOKEN" || true
tea login default grm || true
- name: Build and publish release
env:
REPO_TOKEN: ${{ secrets.REPO_TOKEN }}
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
PYTHONPATH: src
run: |
export PATH="$HOME/.local/bin:$PATH"
python3 -m devx.ci.publish \
"${{ github.ref_name }}" \
"${{ github.event.inputs.tag || github.ref_name }}" \
"${{ github.repository }}"
- name: Notify on failure
if: failure()
+3
View File
@@ -38,3 +38,6 @@ activate.zsh
# Generated badges (CI pushes to badges branch)
.badges/
# Deprecated CI task tracking (branch name is the sole source of truth)
.taskid
-1
View File
@@ -1 +0,0 @@
GRM-75
+11 -11
View File
@@ -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.
@@ -254,7 +255,6 @@ via `[tool.devx.classify]` in `pyproject.toml`.
- `.devin/**` — Agent/CI tooling config
- `hooks/**` — Git hooks
- `activate.sh`, `activate.fish`, `activate.zsh` — Generated venv scripts
- `.taskid` — CI task tracking file
**User-facing paths** (tool changes → release needed) — everything else:
- `src/gitea_runner_manager/**` — Python CLI source (except `__init__.py` and `api_clients.py`)
@@ -362,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.
@@ -385,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
+34
View File
@@ -2,6 +2,40 @@
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
- Adopt devx v0.11.1 across Makefile and workflows
- Add Polish as officially supported language
## [0.8.1] - 2026-06-24
### Bug Fixes
- Repair publish workflow and add publish step to post-merge
- Add build/twine to ci deps, activate venv in notify_failure
## [0.8.0] - 2026-06-24
### Features
- Remove .taskid file, use branch name only for task ID
### Bug Fixes
- Add workflow_dispatch to publish workflow and update devx to 0.9.12
## [0.7.0] - 2026-06-24
### Features
+58 -26
View File
@@ -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.9.11
# 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
+33 -9
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/branch/badges/coverage.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Tests](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/branch/badges/tests.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Docs](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/branch/badges/docs.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
[![Code Quality](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/branch/badges/quality.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Version](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/branch/badges/version.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
[![Python](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/branch/badges/python.svg)](https://www.python.org/downloads/)
[![Coverage](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/47c7e239b2bb0f47217277a6498e53069aab94f3/coverage.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Tests](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/47c7e239b2bb0f47217277a6498e53069aab94f3/tests.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Docs](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/47c7e239b2bb0f47217277a6498e53069aab94f3/docs.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
[![Code Quality](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/47c7e239b2bb0f47217277a6498e53069aab94f3/quality.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Version](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/47c7e239b2bb0f47217277a6498e53069aab94f3/version.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
[![Python](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/47c7e239b2bb0f47217277a6498e53069aab94f3/python.svg)](https://www.python.org/downloads/)
## Why GRM?
@@ -35,7 +35,7 @@ Key problems GRM solves:
- **Automatic integration testing** — Every installation runs an integration test that verifies the `.runner` registration file and systemd service state.
- **Docker prune automation** — A systemd user timer automatically prunes old Docker images and volumes on a daily schedule.
- **Local runner registry** — Connection details are stored in `~/.local/share/grm/runners.json`, so lifecycle commands work by runner name alone.
- **Internationalisation** — Console messages support English, Bulgarian, German, Russian, and Chinese via the `GRM_LANG` environment variable.
- **Internationalisation** — Console messages support English, Bulgarian, German, Russian, Chinese, and Polish via the `GRM_LANG` environment variable.
- **Security-conscious** — Secrets (registration tokens) are passed via temporary JSON files with `0600` permissions, never on the command line (CWE-214).
- **Comprehensive CI/CD** — 100% test coverage, automated releases via conventional commits and git-cliff, Molecule tests across 4 OS platforms.
@@ -92,11 +92,35 @@ source .venv/bin/activate
### Option 2: Via pip (for using GRM without the full repo)
GRM is published to the Gitea PyPI registry at
`https://git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple`.
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
```
**Persistent configuration (recommended):**
Add the registry to `~/.pip/pip.conf` so future `pip install` commands find
GRM automatically:
```ini
[global]
extra-index-url = https://git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple
```
Then install normally:
```bash
pip install gitea-runner-manager
```
This installs the `grm` CLI and its Python dependencies. Note that the Ansible playbooks and role are bundled with the package, so `grm install` will work out of the box. However, for development or access to Make targets, clone the repository.
This installs the `grm` CLI and its Python dependencies. The Ansible playbooks
and role are bundled with the package, so `grm install` works out of the box.
For development or access to Make targets, clone the repository (Option 1).
### Post-install configuration
@@ -268,7 +292,7 @@ grm install <host>
| `runner_manager.py` | Ansible orchestration + registry integration |
| `executor.py` | Ansible subprocess execution with log capture |
| `registry.py` | Local JSON runner registry at `~/.local/share/grm/runners.json` |
| `i18n.py` | Internationalisation (en, bg, de, ru, zh) |
| `i18n.py` | Internationalisation (en, bg, de, ru, zh, pl) |
| `exceptions.py` | Custom exceptions (`GRMError`, `AnsibleError`, `APIError`) |
| `config.py` | Configuration constants (API URLs, repo owner/name) |
| `logging_config.py` | Logging to `~/.local/state/grm/logs/grm.log` |
+7 -7
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/branch/badges/coverage.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Tests](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/branch/badges/tests.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Docs](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/branch/badges/docs.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
[![Code Quality](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/branch/badges/quality.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Version](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/branch/badges/version.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
[![Python](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/branch/badges/python.svg)](https://www.python.org/downloads/)
[![Coverage](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/47c7e239b2bb0f47217277a6498e53069aab94f3/coverage.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Tests](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/47c7e239b2bb0f47217277a6498e53069aab94f3/tests.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Docs](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/47c7e239b2bb0f47217277a6498e53069aab94f3/docs.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/wiki)
[![Code Quality](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/47c7e239b2bb0f47217277a6498e53069aab94f3/quality.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/actions)
[![Version](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/47c7e239b2bb0f47217277a6498e53069aab94f3/version.svg)](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/releases)
[![Python](https://git.oblachno.oblachno.fyi/oblachno-oss/grm/raw/commit/47c7e239b2bb0f47217277a6498e53069aab94f3/python.svg)](https://www.python.org/downloads/)
## Overview
@@ -27,7 +27,7 @@ GRM is a two-layer tool: a Python CLI (built with Click) that delegates to an id
- **Idempotent Ansible role** — Safe to re-run; second run produces zero changes.
- **Automatic integration testing** — Every installation verifies the `.runner` registration file and systemd service state.
- **Local runner registry** — Connection details stored locally; manage runners by name after installation.
- **Internationalisation** — Console messages in English, Bulgarian, German, Russian, and Chinese.
- **Internationalisation** — Console messages in English, Bulgarian, German, Russian, Chinese, and Polish.
- **Security-conscious** — Secrets passed via temporary JSON files with `0600` permissions (CWE-214).
### Supported operating systems
+1 -1
View File
@@ -209,7 +209,7 @@ The Python CLI layer (`src/gitea_runner_manager/`) consists of the following mod
| `runner_manager.py` | Ansible orchestration + registry integration — delegates to executor and manages runner lifecycle |
| `executor.py` | Ansible subprocess execution — runs `ansible-playbook` with extra-vars via temp JSON files, streams output to log files |
| `registry.py` | Local JSON runner registry at `~/.local/share/grm/runners.json` — stores connection metadata |
| `i18n.py` | Internationalisation translations (en, bg, de, ru, zh) — opt-in via `GRM_LANG` environment variable |
| `i18n.py` | Internationalisation translations (en, bg, de, ru, zh, pl) — opt-in via `GRM_LANG` environment variable |
| `exceptions.py` | Custom exceptions (`GRMError`, `AnsibleError`, `APIError`) |
| `config.py` | Configuration constants (API URLs, repo owner/name, project IDs) — overridable via environment variables |
| `logging_config.py` | Logging configuration — writes all messages to `~/.local/state/grm/logs/grm.log` at DEBUG level |
+1 -1
View File
@@ -9,7 +9,7 @@
│ ├── runner_manager.py # Ansible orchestration + registry integration
│ ├── executor.py # Ansible subprocess execution
│ ├── registry.py # Local JSON runner registry
│ ├── i18n.py # Translations (en, bg, de, ru, zh)
│ ├── i18n.py # Translations (en, bg, de, ru, zh, pl)
│ ├── exceptions.py # Custom exceptions
│ ├── config.py # Configuration constants
│ ├── logging_config.py # Logging to ~/.local/state/grm/logs/
+24 -1
View File
@@ -51,11 +51,34 @@ source .venv/bin/activate
### Method 2: Via pip
GRM is published to the Gitea PyPI registry at
`https://git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple`.
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
```
**Persistent configuration (recommended):**
Add the registry to `~/.pip/pip.conf`:
```ini
[global]
extra-index-url = https://git.oblachno.oblachno.fyi/api/packages/oblachno-oss/pypi/simple
```
Then install normally:
```bash
pip install gitea-runner-manager
```
This installs the `grm` CLI and its Python dependencies. The Ansible playbooks and role are bundled with the package, so `grm install` will work out of the box. However, for development or access to Make targets, clone the repository.
This installs the `grm` CLI and its Python dependencies. The Ansible playbooks
and role are bundled with the package, so `grm install` works out of the box.
For development or access to Make targets, clone the repository (Method 1).
### Post-install configuration
+60 -5
View File
@@ -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
+13
View File
@@ -32,6 +32,10 @@ version = {attr = "gitea_runner_manager.__version__"}
ci = [
"pytest>=9.1.0",
"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 = [
@@ -50,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
]
@@ -89,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 -1
View File
@@ -1,3 +1,3 @@
"""Gitea Runner Manager — lean CLI for managing Gitea Actions runners."""
__version__ = "0.7.0"
__version__ = "0.10.0"
+2 -2
View File
@@ -1,7 +1,7 @@
"""Simple i18n for GRM console messages.
Set GRM_LANG environment variable to override the default English.
Supported: en, bg, de, ru, zh.
Supported: en, bg, de, ru, zh, pl.
"""
from __future__ import annotations
@@ -22,7 +22,7 @@ def _(key: str, **kwargs: object) -> str:
If unset, English is always returned regardless of system locale.
"""
lang = os.getenv("GRM_LANG", "en")
if lang not in ("en", "bg", "de", "ru", "zh"):
if lang not in ("en", "bg", "de", "ru", "zh", "pl"):
lang = "en"
template = TRANSLATIONS.get(key, {}).get(lang, key)
return template.format(**kwargs)
+144 -70
View File
@@ -1,487 +1,561 @@
{
"=== Operation Report ===": {
"en": "=== Operation Report ===",
"bg": "=== Отчет за операцията ===",
"de": "=== Operationsbericht ===",
"en": "=== Operation Report ===",
"pl": "=== Raport operacji ===",
"ru": "=== Отчет об операции ===",
"zh": "=== 操作报告 ==="
},
"Ad-hoc command failed on {host}: {stderr}": {
"en": "Ad-hoc command failed on {host}: {stderr}",
"bg": "Ad-hoc командата неуспешна на {host}: {stderr}",
"de": "Ad-hoc-Befehl auf {host} fehlgeschlagen: {stderr}",
"en": "Ad-hoc command failed on {host}: {stderr}",
"pl": "Polecenie ad-hoc nie powiodło się na {host}: {stderr}",
"ru": "Ad-hoc команда не удалась на {host}: {stderr}",
"zh": "Ad-hoc 命令在 {host} 上失败: {stderr}"
},
"Ansible failed with exit code {code}. See full log: {log_file}": {
"en": "Ansible failed with exit code {code}. See full log: {log_file}",
"bg": "Ansible е неуспешен с код {code}. Вижте пълния лог: {log_file}",
"de": "Ansible fehlgeschlagen mit Exit-Code {code}. Siehe Log: {log_file}",
"en": "Ansible failed with exit code {code}. See full log: {log_file}",
"pl": "Ansible zakończone niepowodzeniem z kodem {code}. Pełny log: {log_file}",
"ru": "Ansible завершился с кодом {code}. См. лог: {log_file}",
"zh": "Ansible 失败,退出码 {code}。查看日志: {log_file}"
},
"Check the status of a registered Gitea Runner.": {
"en": "Check the status of a registered Gitea Runner.",
"bg": "Проверка на състоянието на регистриран Gitea Runner.",
"de": "Status eines registrierten Gitea Runners prüfen.",
"en": "Check the status of a registered Gitea Runner.",
"pl": "Sprawdź status zarejestrowanego Gitea Runner.",
"ru": "Проверить состояние зарегистрированного Gitea Runner.",
"zh": "检查已注册的 Gitea Runner 状态。"
},
"Checking status of Gitea Runner {name} on {host}": {
"en": "Checking status of Gitea Runner {name} on {host}",
"bg": "Проверка на състоянието на Gitea Runner {name} на {host}",
"de": "Prüfe Status von Gitea Runner {name} auf {host}",
"en": "Checking status of Gitea Runner {name} on {host}",
"pl": "Sprawdzanie statusu Gitea Runner {name} na {host}",
"ru": "Проверка состояния Gitea Runner {name} на {host}",
"zh": "正在检查 {host} 上 Gitea Runner {name} 的状态"
},
"Checking status of Gitea Runner {name} on {host} as {user} (sudo required)": {
"en": "Checking status of Gitea Runner {name} on {host} as {user} (sudo required)",
"bg": "Проверка на състоянието на Gitea Runner {name} на {host} като {user} (необходим е sudo)",
"de": "Prüfe Status von Gitea Runner {name} auf {host} als {user} (sudo erforderlich)",
"en": "Checking status of Gitea Runner {name} on {host} as {user} (sudo required)",
"pl": "Sprawdzanie statusu Gitea Runner {name} na {host} jako {user} (wymagane sudo)",
"ru": "Проверка состояния Gitea Runner {name} на {host} как {user} (требуется sudo)",
"zh": "正在检查 {host} 上 Gitea Runner {name} 的状态(用户 {user},需要 sudo"
},
"Command: {cmd}": {
"en": "Command: {cmd}",
"bg": "Команда: {cmd}",
"de": "Befehl: {cmd}",
"en": "Command: {cmd}",
"pl": "Polecenie: {cmd}",
"ru": "Команда: {cmd}",
"zh": "命令: {cmd}"
},
"Disable a registered Gitea Runner and deregister it.": {
"en": "Disable a registered Gitea Runner and deregister it.",
"bg": "Деактивиране на регистриран Gitea Runner и дерегистриране.",
"de": "Einen registrierten Gitea Runner deaktivieren und abmelden.",
"en": "Disable a registered Gitea Runner and deregister it.",
"pl": "Wyłącz zarejestrowanego Gitea Runner i wyrejestruj go.",
"ru": "Отключить и дерегистрировать зарегистрированный Gitea Runner.",
"zh": "禁用并注销已注册的 Gitea Runner。"
},
"Disable failed: {error}": {
"en": "Disable failed: {error}",
"bg": "Деактивирането неуспешно: {error}",
"de": "Deaktivierung fehlgeschlagen: {error}",
"en": "Disable failed: {error}",
"pl": "Wyłączanie nie powiodło się: {error}",
"ru": "Отключение не удалось: {error}",
"zh": "禁用失败: {error}"
},
"Disabling Gitea Runner {name} on {host}": {
"en": "Disabling Gitea Runner {name} on {host}",
"bg": "Деактивиране на Gitea Runner {name} на {host}",
"de": "Deaktiviere Gitea Runner {name} auf {host}",
"en": "Disabling Gitea Runner {name} on {host}",
"pl": "Wyłączanie Gitea Runner {name} na {host}",
"ru": "Отключение Gitea Runner {name} на {host}",
"zh": "正在 {host} 上禁用 Gitea Runner {name}"
},
"Done. See full log: {log_file}": {
"en": "Done. See full log: {log_file}",
"bg": "Готово. Вижте пълния лог: {log_file}",
"de": "Fertig. Siehe vollständiges Log: {log_file}",
"en": "Done. See full log: {log_file}",
"pl": "Gotowe. Pełny log: {log_file}",
"ru": "Готово. См. полный лог: {log_file}",
"zh": "完成。查看完整日志: {log_file}"
},
"Enable a registered Gitea Runner to start on boot.": {
"en": "Enable a registered Gitea Runner to start on boot.",
"bg": "Разрешаване на регистриран Gitea Runner да стартира при зареждане.",
"de": "Einen registrierten Gitea Runner für den Autostart aktivieren.",
"en": "Enable a registered Gitea Runner to start on boot.",
"pl": "Włącz zarejestrowanego Gitea Runner, aby startował przy uruchomieniu.",
"ru": "Включить автозапуск зарегистрированного Gitea Runner.",
"zh": "启用已注册的 Gitea Runner 开机自启。"
},
"Enable failed: {error}": {
"en": "Enable failed: {error}",
"bg": "Активирането неуспешно: {error}",
"de": "Aktivierung fehlgeschlagen: {error}",
"en": "Enable failed: {error}",
"pl": "Włączanie nie powiodło się: {error}",
"ru": "Включение не удалось: {error}",
"zh": "启用失败: {error}"
},
"Enabling Gitea Runner {name} on {host}": {
"en": "Enabling Gitea Runner {name} on {host}",
"bg": "Активиране на Gitea Runner {name} на {host}",
"de": "Aktiviere Gitea Runner {name} auf {host}",
"en": "Enabling Gitea Runner {name} on {host}",
"pl": "Włączanie Gitea Runner {name} na {host}",
"ru": "Включение Gitea Runner {name} на {host}",
"zh": "正在 {host} 上启用 Gitea Runner {name}"
},
"Full log: {log_file}": {
"en": "Full log: {log_file}",
"bg": "Пълен лог: {log_file}",
"de": "Vollständiges Log: {log_file}",
"en": "Full log: {log_file}",
"pl": "Pełny log: {log_file}",
"ru": "Полный лог: {log_file}",
"zh": "完整日志: {log_file}"
},
"GITEA_REGISTRATION_TOKEN must be set (or pass --token)": {
"en": "GITEA_REGISTRATION_TOKEN must be set (or pass --token)",
"bg": "GITEA_REGISTRATION_TOKEN трябва да е зададен (или подайте --token)",
"de": "GITEA_REGISTRATION_TOKEN muss gesetzt sein (oder --token übergeben)",
"en": "GITEA_REGISTRATION_TOKEN must be set (or pass --token)",
"pl": "GITEA_REGISTRATION_TOKEN musi być ustawiony (lub podaj --token)",
"ru": "GITEA_REGISTRATION_TOKEN должен быть задан (или передайте --token)",
"zh": "必须设置 GITEA_REGISTRATION_TOKEN(或传递 --token"
},
"GITEA_URL must be set (or pass --url)": {
"en": "GITEA_URL must be set (or pass --url)",
"bg": "GITEA_URL трябва да е зададен (или подайте --url)",
"de": "GITEA_URL muss gesetzt sein (oder --url übergeben)",
"en": "GITEA_URL must be set (or pass --url)",
"pl": "GITEA_URL musi być ustawiony (lub podaj --url)",
"ru": "GITEA_URL должен быть задан (или передайте --url)",
"zh": "必须设置 GITEA_URL(或传递 --url"
},
"Gitea Runner Manager — manage Gitea Actions runners.": {
"en": "Gitea Runner Manager — manage Gitea Actions runners.",
"bg": "Gitea Runner Manager — управление на Gitea Actions runners.",
"de": "Gitea Runner Manager — Gitea Actions Runner verwalten.",
"en": "Gitea Runner Manager — manage Gitea Actions runners.",
"pl": "Gitea Runner Manager — zarządzaj runnerami Gitea Actions.",
"ru": "Gitea Runner Manager — управление Gitea Actions runners.",
"zh": "Gitea Runner Manager — 管理 Gitea Actions runners。"
},
"Gitea Runner name (default: host)": {
"en": "Gitea Runner name (default: host)",
"bg": "Име на Gitea Runner (по подразбиране: host)",
"de": "Gitea Runner-Name (Standard: host)",
"en": "Gitea Runner name (default: host)",
"pl": "Nazwa Gitea Runner (domyślnie: host)",
"ru": "Имя Gitea Runner (по умолчанию: host)",
"zh": "Gitea Runner 名称(默认: host"
},
"Gitea URL (env: GITEA_URL)": {
"en": "Gitea URL (env: GITEA_URL)",
"bg": "Gitea URL (env: GITEA_URL)",
"de": "Gitea-URL (env: GITEA_URL)",
"en": "Gitea URL (env: GITEA_URL)",
"pl": "URL Gitea (env: GITEA_URL)",
"ru": "URL Gitea (env: GITEA_URL)",
"zh": "Gitea URL(环境变量: GITEA_URL"
},
"Gitea admin API token for integration test (env: REPO_TOKEN)": {
"en": "Gitea admin API token for integration test (env: REPO_TOKEN)",
"bg": "Gitea admin API токен за интеграционен тест (env: REPO_TOKEN)",
"de": "Gitea-Admin-API-Token für Integrationstest (env: REPO_TOKEN)",
"en": "Gitea admin API token for integration test (env: REPO_TOKEN)",
"pl": "Token API administratora Gitea do testów integracyjnych (env: REPO_TOKEN)",
"ru": "Токен админ API Gitea для интеграционного теста (env: REPO_TOKEN)",
"zh": "Gitea 管理员 API 令牌,用于集成测试(环境变量: REPO_TOKEN"
},
"HOST": {
"en": "HOST",
"bg": "ХОСТ",
"de": "HOST",
"en": "HOST",
"pl": "HOST",
"ru": "ХОСТ",
"zh": "主机"
},
"Install and configure a Gitea Runner on a remote host.": {
"en": "Install and configure a Gitea Runner on a remote host.",
"bg": "Инсталиране и конфигуриране на Gitea Runner на отдалечен хост.",
"de": "Gitea Runner auf einem Remote-Host installieren und konfigurieren.",
"en": "Install and configure a Gitea Runner on a remote host.",
"pl": "Zainstaluj i skonfiguruj Gitea Runner na zdalnym hoście.",
"ru": "Установить и настроить Gitea Runner на удалённом хосте.",
"zh": "在远程主机上安装并配置 Gitea Runner。"
},
"Installation failed: {error}": {
"en": "Installation failed: {error}",
"bg": "Инсталацията неуспешна: {error}",
"de": "Installation fehlgeschlagen: {error}",
"en": "Installation failed: {error}",
"pl": "Instalacja nie powiodła się: {error}",
"ru": "Установка не удалась: {error}",
"zh": "安装失败: {error}"
},
"Installing Gitea Runner on {host}": {
"en": "Installing Gitea Runner on {host}",
"bg": "Инсталиране на Gitea Runner на {host}",
"de": "Gitea Runner wird auf {host} installiert",
"en": "Installing Gitea Runner on {host}",
"pl": "Instalowanie Gitea Runner na {host}",
"ru": "Установка Gitea Runner на {host}",
"zh": "正在 {host} 上安装 Gitea Runner"
},
"Integration test API retries (default: 3, env: GITEA_INTEGRATION_RETRIES)": {
"en": "Integration test API retries (default: 3, env: GITEA_INTEGRATION_RETRIES)",
"bg": "Повторни опити за интеграционен тест API (по подразбиране: 3, env: GITEA_INTEGRATION_RETRIES)",
"de": "API-Wiederholungen für Integrationstest (Standard: 3, env: GITEA_INTEGRATION_RETRIES)",
"en": "Integration test API retries (default: 3, env: GITEA_INTEGRATION_RETRIES)",
"pl": "Powtórzenia API testów integracyjnych (domyślnie: 3, env: GITEA_INTEGRATION_RETRIES)",
"ru": "Повторы API интеграционного теста (по умолчанию: 3, env: GITEA_INTEGRATION_RETRIES)",
"zh": "集成测试 API 重试次数(默认: 3,环境变量: GITEA_INTEGRATION_RETRIES"
},
"LABELS": {
"en": "LABELS",
"bg": "ЕТИКЕТИ",
"de": "LABELS",
"en": "LABELS",
"pl": "ETYKIETY",
"ru": "МЕТКИ",
"zh": "标签"
},
"List all registered runners with live status.": {
"en": "List all registered runners with live status.",
"bg": "Списък на всички регистрирани runners с актуално състояние.",
"de": "Alle registrierten Runner mit Live-Status auflisten.",
"en": "List all registered runners with live status.",
"pl": "Wyświetl wszystkie zarejestrowane runnery z aktualnym statusem.",
"ru": "Список всех зарегистрированных runners с текущим статусом.",
"zh": "列出所有已注册 runners 的实时状态。"
},
"List failed: {error}": {
"en": "List failed: {error}",
"bg": "Списъкът неуспешен: {error}",
"de": "Auflistung fehlgeschlagen: {error}",
"en": "List failed: {error}",
"pl": "Wyświetlanie nie powiodło się: {error}",
"ru": "Ошибка списка: {error}",
"zh": "列表失败: {error}"
},
"NAME": {
"en": "NAME",
"bg": "ИМЕ",
"de": "NAME",
"en": "NAME",
"pl": "NAZWA",
"ru": "ИМЯ",
"zh": "名称"
},
"No runners registered. Use 'grm install' to add one.": {
"en": "No runners registered. Use 'grm install' to add one.",
"bg": "Няма регистрирани runners. Използвайте 'grm install', за да добавите.",
"de": "Keine Runner registriert. Verwenden Sie 'grm install', um einen hinzuzufügen.",
"en": "No runners registered. Use 'grm install' to add one.",
"pl": "Brak zarejestrowanych runnerów. Użyj 'grm install', aby dodać jeden.",
"ru": "Нет зарегистрированных runners. Используйте 'grm install' чтобы добавить.",
"zh": "没有已注册的 runners。使用 'grm install' 添加一个。"
},
"Override SSH key from registry": {
"en": "Override SSH key from registry",
"bg": "Замяна на SSH ключа от регистъра",
"de": "SSH-Schlüssel aus Registrierung überschreiben",
"en": "Override SSH key from registry",
"pl": "Nadpisz klucz SSH z rejestru",
"ru": "Переопределить SSH ключ из реестра",
"zh": "覆盖注册表中的 SSH 密钥"
},
"Override host from registry": {
"en": "Override host from registry",
"bg": "Замяна на хоста от регистъра",
"de": "Host aus Registrierung überschreiben",
"en": "Override host from registry",
"pl": "Nadpisz host z rejestru",
"ru": "Переопределить хост из реестра",
"zh": "覆盖注册表中的主机"
},
"Override user from registry": {
"en": "Override user from registry",
"bg": "Замяна на потребителя от регистъра",
"de": "Benutzer aus Registrierung überschreiben",
"en": "Override user from registry",
"pl": "Nadpisz użytkownika z rejestru",
"ru": "Переопределить пользователя из реестра",
"zh": "覆盖注册表中的用户"
},
"Path to SSH private key": {
"en": "Path to SSH private key",
"bg": "Път към SSH частен ключ",
"de": "Pfad zum SSH-Private-Key",
"en": "Path to SSH private key",
"pl": "Ścieżka do klucza prywatnego SSH",
"ru": "Путь к SSH приватному ключу",
"zh": "SSH 私钥路径"
},
"Playbook not found: {playbook}": {
"en": "Playbook not found: {playbook}",
"bg": "Playbook не е намерен: {playbook}",
"de": "Playbook nicht gefunden: {playbook}",
"en": "Playbook not found: {playbook}",
"pl": "Playbook nie znaleziony: {playbook}",
"ru": "Playbook не найден: {playbook}",
"zh": "未找到 Playbook: {playbook}"
},
"Prompt for sudo password (default)": {
"en": "Prompt for sudo password (default)",
"bg": "Подканване за sudo парола (по подразбиране)",
"de": "Nach sudo-Passwort fragen (Standard)",
"en": "Prompt for sudo password (default)",
"pl": "Zapytaj o hasło sudo (domyślnie)",
"ru": "Запросить пароль sudo (по умолчанию)",
"zh": "提示输入 sudo 密码(默认)"
},
"Registration token (env: GITEA_REGISTRATION_TOKEN)": {
"en": "Registration token (env: GITEA_REGISTRATION_TOKEN)",
"bg": "Регистрационен токен (env: GITEA_REGISTRATION_TOKEN)",
"de": "Registrierungstoken (env: GITEA_REGISTRATION_TOKEN)",
"en": "Registration token (env: GITEA_REGISTRATION_TOKEN)",
"pl": "Token rejestracji (env: GITEA_REGISTRATION_TOKEN)",
"ru": "Токен регистрации (env: GITEA_REGISTRATION_TOKEN)",
"zh": "注册令牌(环境变量: GITEA_REGISTRATION_TOKEN"
},
"Remove a registered Gitea Runner completely.": {
"en": "Remove a registered Gitea Runner completely.",
"bg": "Пълно премахване на регистриран Gitea Runner.",
"de": "Einen registrierten Gitea Runner vollständig entfernen.",
"en": "Remove a registered Gitea Runner completely.",
"pl": "Usuń zarejestrowanego Gitea Runner całkowicie.",
"ru": "Полностью удалить зарегистрированный Gitea Runner.",
"zh": "完全移除已注册的 Gitea Runner。"
},
"Remove failed: {error}": {
"en": "Remove failed: {error}",
"bg": "Премахването неуспешно: {error}",
"de": "Entfernung fehlgeschlagen: {error}",
"en": "Remove failed: {error}",
"pl": "Usuwanie nie powiodło się: {error}",
"ru": "Удаление не удалось: {error}",
"zh": "移除失败: {error}"
},
"Remove runner '{name}' from local registry": {
"en": "Remove runner '{name}' from local registry",
"bg": "Премахване на runner '{name}' от локалния регистър",
"de": "Runner '{name}' aus lokaler Registrierung entfernen",
"en": "Remove runner '{name}' from local registry",
"pl": "Usuń runner '{name}' z lokalnego rejestru",
"ru": "Удалить runner '{name}' из локального реестра",
"zh": "从本地注册表移除 runner '{name}'"
},
"Removing Gitea Runner {name} from {host}": {
"en": "Removing Gitea Runner {name} from {host}",
"bg": "Премахване на Gitea Runner {name} от {host}",
"de": "Entferne Gitea Runner {name} von {host}",
"en": "Removing Gitea Runner {name} from {host}",
"pl": "Usuwanie Gitea Runner {name} z {host}",
"ru": "Удаление Gitea Runner {name} с {host}",
"zh": "正在从 {host} 移除 Gitea Runner {name}"
},
"Runner '{name}' not found in registry.": {
"en": "Runner '{name}' not found in registry."
"bg": "Runner '{name}' не е намерен в регистъра.",
"de": "Runner '{name}' nicht in der Registrierung gefunden.",
"en": "Runner '{name}' not found in registry.",
"pl": "Runner '{name}' nie znaleziony w rejestrze.",
"ru": "Runner '{name}' не найден в реестре.",
"zh": "在注册表中未找到运行器 '{name}'。"
},
"Runner '{name}' not found in registry. Use 'grm install' first or provide --host and --user.": {
"en": "Runner '{name}' not found in registry. Use 'grm install' first or provide --host and --user.",
"bg": "Runner '{name}' не е намерен в регистъра. Използвайте 'grm install' първо или подайте --host и --user.",
"de": "Runner '{name}' nicht in Registrierung gefunden. Verwenden Sie zuerst 'grm install' oder geben Sie --host und --user an.",
"en": "Runner '{name}' not found in registry. Use 'grm install' first or provide --host and --user.",
"pl": "Runner '{name}' nie znaleziony w rejestrze. Użyj najpierw 'grm install' lub podaj --host i --user.",
"ru": "Runner '{name}' не найден в реестре. Сначала используйте 'grm install' или укажите --host и --user.",
"zh": "注册表中未找到 Runner '{name}'。请先使用 'grm install' 或提供 --host 和 --user。"
},
"Runner labels for Gitea Actions (env: GITEA_RUNNER_LABELS). Example: docker:docker://alpine:latest": {
"en": "Runner labels for Gitea Actions (env: GITEA_RUNNER_LABELS). Example: docker:docker://alpine:latest",
"bg": "Етикети на runner за Gitea Actions (env: GITEA_RUNNER_LABELS). Пример: docker:docker://alpine:latest",
"de": "Runner-Labels für Gitea Actions (env: GITEA_RUNNER_LABELS). Beispiel: docker:docker://alpine:latest",
"en": "Runner labels for Gitea Actions (env: GITEA_RUNNER_LABELS). Example: docker:docker://alpine:latest",
"pl": "Etykiety runnera dla Gitea Actions (env: GITEA_RUNNER_LABELS). Przykład: docker:docker://alpine:latest",
"ru": "Метки runner для Gitea Actions (env: GITEA_RUNNER_LABELS). Пример: docker:docker://alpine:latest",
"zh": "Gitea Actions 的 runner 标签(环境变量: GITEA_RUNNER_LABELS)。示例: docker:docker://alpine:latest"
},
"Running Ansible playbook": {
"en": "Running Ansible playbook",
"bg": "Изпълнение на Ansible playbook",
"de": "Ansible-Playbook wird ausgeführt",
"en": "Running Ansible playbook",
"pl": "Uruchamianie playbook Ansible",
"ru": "Выполнение Ansible playbook",
"zh": "正在运行 Ansible playbook"
},
"SSH user": {
"en": "SSH user",
"bg": "SSH потребител",
"de": "SSH-Benutzer",
"en": "SSH user",
"pl": "Użytkownik SSH",
"ru": "SSH пользователь",
"zh": "SSH 用户"
},
"STATUS": {
"en": "STATUS",
"bg": "СТАТУС",
"de": "STATUS",
"en": "STATUS",
"pl": "STATUS",
"ru": "СТАТУС",
"zh": "状态"
},
"Save runner '{name}' to local registry": {
"en": "Save runner '{name}' to local registry",
"bg": "Запазване на runner '{name}' в локалния регистър",
"de": "Runner '{name}' in lokaler Registrierung speichern",
"en": "Save runner '{name}' to local registry",
"pl": "Zapisz runner '{name}' do lokalnego rejestru",
"ru": "Сохранить runner '{name}' в локальном реестре",
"zh": "将 runner '{name}' 保存到本地注册表"
},
"Skip remote cleanup and only remove the local registry entry": {
"en": "Skip remote cleanup and only remove the local registry entry",
"bg": "Пропуснете отдалеченото почистване и премахнете само локалния запис",
"de": "Remote-Bereinigung überspringen und nur den lokalen Registrierungseintrag entfernen",
"en": "Skip remote cleanup and only remove the local registry entry",
"pl": "Pomiń zdalne czyszczenie i usuń tylko wpis w lokalnym rejestrze",
"ru": "Пропустить удаленную очистку и удалить только локальную запись реестра",
"zh": "跳过远程清理,仅删除本地注册表条目"
},
"Specific Gitea Runner version": {
"en": "Specific Gitea Runner version",
"bg": "Конкретна версия на Gitea Runner",
"de": "Spezifische Gitea Runner-Version",
"en": "Specific Gitea Runner version",
"pl": "Konkretna wersja Gitea Runner",
"ru": "Конкретная версия Gitea Runner",
"zh": "指定 Gitea Runner 版本"
},
"Start a registered Gitea Runner.": {
"en": "Start a registered Gitea Runner.",
"bg": "Стартиране на регистриран Gitea Runner.",
"de": "Einen registrierten Gitea Runner starten.",
"en": "Start a registered Gitea Runner.",
"pl": "Uruchom zarejestrowanego Gitea Runner.",
"ru": "Запустить зарегистрированный Gitea Runner.",
"zh": "启动已注册的 Gitea Runner。"
},
"Start failed: {error}": {
"en": "Start failed: {error}",
"bg": "Стартирането неуспешно: {error}",
"de": "Start fehlgeschlagen: {error}",
"en": "Start failed: {error}",
"pl": "Uruchamianie nie powiodło się: {error}",
"ru": "Запуск не удался: {error}",
"zh": "启动失败: {error}"
},
"Starting Gitea Runner {name} on {host}": {
"en": "Starting Gitea Runner {name} on {host}",
"bg": "Стартиране на Gitea Runner {name} на {host}",
"de": "Starte Gitea Runner {name} auf {host}",
"en": "Starting Gitea Runner {name} on {host}",
"pl": "Uruchamianie Gitea Runner {name} na {host}",
"ru": "Запуск Gitea Runner {name} на {host}",
"zh": "正在 {host} 上启动 Gitea Runner {name}"
},
"Status check failed: {error}": {
"en": "Status check failed: {error}",
"bg": "Проверката на състоянието неуспешна: {error}",
"de": "Statusprüfung fehlgeschlagen: {error}",
"en": "Status check failed: {error}",
"pl": "Sprawdzanie statusu nie powiodło się: {error}",
"ru": "Проверка состояния не удалась: {error}",
"zh": "状态检查失败: {error}"
},
"Stop a registered Gitea Runner.": {
"en": "Stop a registered Gitea Runner.",
"bg": "Спиране на регистриран Gitea Runner.",
"de": "Einen registrierten Gitea Runner stoppen.",
"en": "Stop a registered Gitea Runner.",
"pl": "Zatrzymaj zarejestrowanego Gitea Runner.",
"ru": "Остановить зарегистрированный Gitea Runner.",
"zh": "停止已注册的 Gitea Runner。"
},
"Stop failed: {error}": {
"en": "Stop failed: {error}",
"bg": "Спирането неуспешно: {error}",
"de": "Stop fehlgeschlagen: {error}",
"en": "Stop failed: {error}",
"pl": "Zatrzymywanie nie powiodło się: {error}",
"ru": "Остановка не удалась: {error}",
"zh": "停止失败: {error}"
},
"Stopping Gitea Runner {name} on {host}": {
"en": "Stopping Gitea Runner {name} on {host}",
"bg": "Спиране на Gitea Runner {name} на {host}",
"de": "Stoppe Gitea Runner {name} auf {host}",
"en": "Stopping Gitea Runner {name} on {host}",
"pl": "Zatrzymywanie Gitea Runner {name} na {host}",
"ru": "Остановка Gitea Runner {name} на {host}",
"zh": "正在 {host} 上停止 Gitea Runner {name}"
},
"USER": {
"en": "USER",
"bg": "ПОТРЕБИТЕЛ",
"de": "BENUTZER",
"en": "USER",
"pl": "UŻYTKOWNIK",
"ru": "ПОЛЬЗОВАТЕЛЬ",
"zh": "用户"
},
"Update failed: {error}": {
"en": "Update failed: {error}",
"bg": "Актуализацията неуспешна: {error}",
"de": "Update fehlgeschlagen: {error}",
"en": "Update failed: {error}",
"pl": "Aktualizacja nie powiodła się: {error}",
"ru": "Обновление не удалось: {error}",
"zh": "更新失败: {error}"
},
"Update the Gitea Runner binary on a remote host.": {
"en": "Update the Gitea Runner binary on a remote host.",
"bg": "Актуализиране на Gitea Runner двоичния файл на отдалечен хост.",
"de": "Gitea Runner-Binary auf einem Remote-Host aktualisieren.",
"en": "Update the Gitea Runner binary on a remote host.",
"pl": "Zaktualizuj binaria Gitea Runner na zdalnym hoście.",
"ru": "Обновить бинарный файл Gitea Runner на удалённом хосте.",
"zh": "在远程主机上更新 Gitea Runner 二进制文件。"
},
"Updating Gitea Runner on {host}": {
"en": "Updating Gitea Runner on {host}",
"bg": "Актуализиране на Gitea Runner на {host}",
"de": "Gitea Runner wird auf {host} aktualisiert",
"en": "Updating Gitea Runner on {host}",
"pl": "Aktualizowanie Gitea Runner na {host}",
"ru": "Обновление Gitea Runner на {host}",
"zh": "正在 {host} 上更新 Gitea Runner"
},
"active": {
"en": "active",
"bg": "активен",
"de": "aktiv",
"en": "active",
"pl": "aktywny",
"ru": "активен",
"zh": "活跃"
},
"completed": {
"en": "completed",
"bg": "завършено",
"de": "abgeschlossen",
"en": "completed",
"pl": "ukończony",
"ru": "завершено",
"zh": "已完成"
},
"exit code {code}": {
"en": "exit code {code}",
"bg": "код за изход {code}",
"de": "Exit-Code {code}",
"en": "exit code {code}",
"pl": "kod wyjścia {code}",
"ru": "код выхода {code}",
"zh": "退出代码 {code}"
},
"failed": {
"en": "failed",
"bg": "неуспешен",
"de": "fehlgeschlagen",
"en": "failed",
"pl": "nieudany",
"ru": "сбой",
"zh": "失败"
},
"in_progress": {
"en": "in progress",
"bg": "в процес",
"de": "in Bearbeitung",
"en": "in progress",
"pl": "w toku",
"ru": "в процессе",
"zh": "进行中"
},
"inactive": {
"en": "inactive",
"bg": "неактивен",
"de": "inaktiv",
"en": "inactive",
"pl": "nieaktywny",
"ru": "неактивен",
"zh": "不活跃"
},
"pending": {
"en": "pending",
"bg": "чакащо",
"de": "ausstehend",
"en": "pending",
"pl": "oczekujący",
"ru": "в ожидании",
"zh": "待处理"
},
"unknown": {
"en": "unknown",
"bg": "неизвестен",
"de": "unbekannt",
"en": "unknown",
"pl": "nieznany",
"ru": "неизвестно",
"zh": "未知"
}