DEVX-104: feat: auto-rebase in auto-merge, new rebase tools, CLI registration
Post-merge / detect-type (push) Successful in 9s
Post-merge / validate-commit-msg (push) Successful in 10s
Post-merge / vikunja (push) Successful in 24s
Post-merge / configure-repo (push) Successful in 21s
Post-merge / sync-wiki (push) Successful in 38s
Post-merge / release (push) Successful in 44s
Post-merge / badges (push) Successful in 50s
Post-merge / publish (push) Successful in 20s
Build Images / detect-type (push) Successful in 1m26s
Build Images / build-and-push (push) Successful in 5m35s
Build Images / cleanup (push) Successful in 3m32s

This commit was merged in pull request #161.
This commit is contained in:
2026-07-01 00:50:23 +00:00
parent 66554657f2
commit 621b051793
16 changed files with 922 additions and 32 deletions
+13
View File
@@ -194,6 +194,19 @@ class GiteaClient:
payload = {"Do": "squash", "MergeTitleField": merge_title}
self._request("POST", f"/pulls/{pr_number}/merge", json=payload)
def update_pr_branch(self, pr_number: str | int, style: str = "rebase") -> None:
"""Update PR head branch by merging/rebasing the base branch into it.
Uses the Gitea API ``POST /pulls/{index}/update?style=rebase`` endpoint.
This rebases the PR's head branch onto the latest base branch server-side,
triggering a ``pull_request synchronize`` event that starts a new CI run.
Args:
pr_number: PR number.
style: Update method — ``"rebase"`` (default) or ``"merge"``.
"""
self._request("POST", f"/pulls/{pr_number}/update", params={"style": style})
def get_commit_status(self, sha: str) -> list[dict[str, Any]]:
"""Fetch all status check contexts reported for a commit.
+27 -9
View File
@@ -231,17 +231,35 @@ def main(branch: str, pr_title: str, repo: str, pr_number: str) -> None:
client.merge_pr(pr_num, merge_title)
except APIError as e:
if e.status == 405 and "behind" in e.message.lower():
# Head branch is behind master — do NOT auto-rebase.
# Auto-rebasing creates a feedback loop: the force-push triggers
# a new pull_request synchronize event, which starts a new CI run,
# which runs auto-merge again, which rebases again, etc.
raise click.ClickException(
# Head branch is behind master. Auto-rebase via Gitea API.
# This triggers a new pull_request synchronize event → new CI run.
# The next auto-merge attempt will find the branch up-to-date and
# merge successfully. This is NOT an infinite loop: the rebase
# resolves the "behind" condition, so the next run merges.
# If another PR merges in between, the branch may fall behind
# again, but the process converges as PRs stop merging.
click.echo(
_(
"Branch is behind master. Rebase manually:\n"
" git fetch origin master && git rebase origin/master && git push --force-with-lease\n"
"Then re-add the ready-to-merge label.",
"Branch is behind master. Auto-rebasing via Gitea API...\n"
"A new CI run will start automatically after the rebase.\n"
"The next auto-merge attempt will merge this PR.",
)
) from None
)
try:
client.update_pr_branch(pr_num, style="rebase")
except APIError as rebase_err:
raise click.ClickException(
_(
"Auto-rebase failed with HTTP {status}: {message}\n"
"Rebase manually:\n"
" git fetch origin master && git rebase origin/master && git push --force-with-lease\n"
"Then re-add the ready-to-merge label.",
status=rebase_err.status,
message=rebase_err.message,
)
) from None
# Exit cleanly — the rebase triggers a new CI run that will retry.
return
else:
raise click.ClickException(
_(
+14
View File
@@ -226,6 +226,20 @@ def tools_setup(args: tuple[str, ...]) -> None:
_run_module("devx.tools.setup", list(args))
@tools.command("rebase")
@click.argument("args", nargs=-1)
def tools_rebase(args: tuple[str, ...]) -> None:
"""Rebase current branch onto origin/master and force-push."""
_run_module("devx.tools.rebase", list(args))
@tools.command("pr-rebase")
@click.argument("args", nargs=-1)
def tools_pr_rebase(args: tuple[str, ...]) -> None:
"""Rebase a PR's head branch onto master via Gitea API (server-side)."""
_run_module("devx.tools.pr_rebase", list(args))
@cli.group()
def molecule() -> None:
"""Molecule testing commands (requires devx[molecule])."""
+15 -1
View File
@@ -63,7 +63,7 @@ DEVX_PIP_INSTALL := if [ -z "$$CI_GITEA_TOKEN" ]; then . ./.env 2>/dev/null; fi;
$(DEVX_BIN)/pip
.PHONY: devx-create-task devx-create-pr devx-push devx-push-with-pr devx-check-config
.PHONY: devx-pr-status devx-pr-logs devx-pr-label devx-pr-review
.PHONY: devx-pr-status devx-pr-logs devx-pr-label devx-pr-review devx-rebase devx-pr-rebase
.PHONY: devx-configure-gitea-pypi devx-install-tools devx-install-checkmake devx-checkmake
.PHONY: devx-workflow-lint devx-workflow-dryrun devx-workflow-dryrun-safe devx-workflow-check
.PHONY: devx-notify-failure devx-install-hooks devx-activate-scripts
@@ -134,6 +134,20 @@ devx-pr-review:
$(if $(BODY),--body "$(BODY)") \
$(if $(CHECKLIST),--checklist-confirmed --checklist-categories $(CHECKLIST))
# Rebase current branch onto origin/master and force-push
# Usage: make devx-rebase
# make devx-rebase NO_PUSH=1
devx-rebase:
@$(DEVX_PYTHON) -m devx.tools.rebase \
$(if $(NO_PUSH),--no-push)
# Rebase a PR's head branch via Gitea API (server-side, no local git needed)
# Usage: make devx-pr-rebase
# make devx-pr-rebase PR=42
devx-pr-rebase:
@$(DEVX_PYTHON) -m devx.tools.pr_rebase \
$(if $(PR),--pr $(PR))
# ── Environment setup ─────────────────────────────────────────────────────────
# Configure Gitea private PyPI registry so pip can find devx and other
+51
View File
@@ -2,7 +2,9 @@
from __future__ import annotations
import os
import platform
import subprocess # nosec B404
import click
@@ -22,3 +24,52 @@ def arch_string() -> str:
if machine in {"aarch64", "arm64"}:
return "arm64"
raise click.ClickException(f"Unsupported architecture: {machine}")
def detect_pr_number() -> int | None:
"""Detect the PR number for the current git branch.
Returns the PR number if the current branch has an open PR, or None
if no PR is found. Does NOT raise — callers decide how to handle None.
Best-effort: returns None on any failure (no token, API down, etc.).
"""
result = subprocess.run( # nosec B603, B607
["git", "rev-parse", "--abbrev-ref", "HEAD"],
capture_output=True,
text=True,
check=False,
)
if result.returncode != 0:
return None
branch = result.stdout.strip()
if branch == "HEAD":
return None
token = os.environ.get("CI_GITEA_TOKEN", "")
if not token:
return None
owner = os.environ.get("DEVX_REPO_OWNER", "")
repo = os.environ.get("DEVX_REPO_NAME", "")
if not owner or not repo:
github_repo = os.environ.get("GITHUB_REPOSITORY", "")
if "/" in github_repo:
owner, repo = github_repo.split("/", 1)
if not owner or not repo:
return None
# Lazy import to avoid circular dependency
from devx.api_clients import APIError, GiteaClient # noqa: PLC0415
from devx.config import GITEA_API_URL # noqa: PLC0415
client = GiteaClient(GITEA_API_URL, token, owner, repo)
try:
prs = client.list_prs(state="open")
except APIError:
# Best-effort: API down or auth failure → no PR detected
return None
for pr in prs:
if pr.get("head", {}).get("ref") == branch:
return int(pr["number"])
return None
+97
View File
@@ -0,0 +1,97 @@
#!/usr/bin/env python3
"""Rebase a pull request's head branch onto master via Gitea API.
Uses the Gitea ``POST /pulls/{index}/update?style=rebase`` endpoint to
rebase the PR's head branch server-side. This triggers a new
``pull_request synchronize`` event, which starts a new CI run.
This is useful when:
- You don't have the branch checked out locally
- You want to rebase a PR from another machine
- You want to trigger the auto-merge retry without local git operations
Usage::
# Rebase PR #42
python -m devx.tools.pr_rebase --pr 42
# Rebase current branch's PR (auto-detected)
python -m devx.tools.pr_rebase
The repository is auto-detected from ``DEVX_REPO_OWNER`` /
``DEVX_REPO_NAME`` or ``GITHUB_REPOSITORY`` environment variables.
"""
from __future__ import annotations
import os
import click
from dotenv import load_dotenv # pyright: ignore[reportMissingImports,reportUnknownVariableType]
from devx.api_clients import APIError, GiteaClient
from devx.config import GITEA_API_URL
from devx.i18n import _
from devx.tools._shared import detect_pr_number
@click.command()
@click.option("--pr", type=int, help="PR number (auto-detected if omitted).")
def main(pr: int | None) -> None:
"""Rebase a pull request's head branch onto master via Gitea API."""
load_dotenv()
token = os.environ.get("CI_GITEA_TOKEN", "")
if not token:
raise click.ClickException(_("CI_GITEA_TOKEN is not set. Add it to .env or export it."))
pr_num = pr or detect_pr_number()
if not pr_num:
raise click.ClickException(
_(
"Could not detect PR number. Use --pr to specify it explicitly,\n"
"or run this command from a branch with an open PR.",
)
)
owner = os.environ.get("DEVX_REPO_OWNER", "")
repo = os.environ.get("DEVX_REPO_NAME", "")
if not owner or not repo:
github_repo = os.environ.get("GITHUB_REPOSITORY", "")
if "/" in github_repo:
owner, repo = github_repo.split("/", 1)
if not owner or not repo:
raise click.ClickException(
_(
"Could not determine repository. Set DEVX_REPO_OWNER and DEVX_REPO_NAME\n"
"or GITHUB_REPOSITORY environment variables.",
)
)
client = GiteaClient(GITEA_API_URL, token, owner, repo)
click.echo(_("Rebasing PR #{pr} via Gitea API...", pr=pr_num))
try:
client.update_pr_branch(pr_num, style="rebase")
except APIError as e:
raise click.ClickException(
_(
"Rebase failed with HTTP {status}: {message}",
status=e.status,
message=e.message,
)
) from None
click.echo(
_(
"PR #{pr} rebased successfully. A new CI run will start automatically.\n"
"If auto-merge is enabled (ready-to-merge label), the next CI run\n"
"will attempt to merge this PR.",
pr=pr_num,
)
)
if __name__ == "__main__": # pragma: no cover
main()
+97
View File
@@ -0,0 +1,97 @@
#!/usr/bin/env python3
"""Rebase current branch onto origin/master and force-push.
Fetches origin/master, rebases the current branch, and force-pushes with
``--force-with-lease``. This is the manual equivalent of what
``auto_merge.py`` does automatically via the Gitea API.
Usage::
# Rebase current branch onto master and force-push
python -m devx.tools.rebase
# Rebase without pushing (local only)
python -m devx.tools.rebase --no-push
The tool fails if:
- The rebase encounters conflicts (exits with rebase in progress)
- The force-push is rejected (remote has unexpected commits)
- Not on a branch (detached HEAD)
"""
from __future__ import annotations
import subprocess # nosec B404
import click
from devx.i18n import _
def _run_git(args: list[str], check: bool = True) -> subprocess.CompletedProcess[str]:
"""Run a git command and return the result."""
return subprocess.run( # nosec B603, B607
["git", *args],
capture_output=True,
text=True,
check=check,
)
@click.command()
@click.option("--no-push", is_flag=True, help="Rebase locally without pushing.")
def main(no_push: bool) -> None:
"""Rebase current branch onto origin/master and force-push."""
# Ensure we're on a branch (check=False — we handle errors ourselves)
branch_result = _run_git(["rev-parse", "--abbrev-ref", "HEAD"], check=False)
if branch_result.returncode != 0:
raise click.ClickException(_("Could not detect current branch: {error}", error=branch_result.stderr.strip()))
branch = branch_result.stdout.strip()
if branch == "HEAD":
raise click.ClickException(_("Cannot rebase: not on a branch (detached HEAD)."))
click.echo(_("Fetching origin/master..."))
fetch = _run_git(["fetch", "origin", "master"], check=False)
if fetch.returncode != 0:
raise click.ClickException(_("Fetch failed: {error}", error=fetch.stderr.strip()))
# Check if behind master
behind = _run_git(
["rev-list", "--count", "HEAD..origin/master"],
check=False,
)
behind_count = int(behind.stdout.strip()) if behind.stdout.strip().isdigit() else 0
if behind_count == 0:
click.echo(_("Branch is already up-to-date with origin/master."))
if not no_push:
click.echo(_("Nothing to push."))
return
click.echo(_("Branch is {count} commit(s) behind master. Rebasing...", count=behind_count))
rebase = _run_git(["rebase", "origin/master"], check=False)
if rebase.returncode != 0:
raise click.ClickException(
_(
"Rebase failed (conflicts or other error):\n{error}\nResolve conflicts and run: git rebase --continue",
error=rebase.stderr.strip() or rebase.stdout.strip(),
)
)
click.echo(_("Rebase successful."))
if not no_push:
click.echo(_("Force-pushing..."))
push = _run_git(["push", "--force-with-lease", "origin", branch], check=False)
if push.returncode != 0:
raise click.ClickException(
_(
"Force-push failed:\n{error}\nThe remote may have unexpected commits. Fetch and try again.",
error=push.stderr.strip(),
)
)
click.echo(_("Pushed {branch} to origin.", branch=branch))
if __name__ == "__main__": # pragma: no cover
main()
+152 -8
View File
@@ -775,14 +775,6 @@
"ru": "Ветка '{branch}' не содержит ID задачи.\n Ожидаемый формат: {prefix}-N-краткое-описание\n Пример: {prefix}-42-add-feature\n Исправление: переименуйте ветку или создайте задачу Vikunja:\n python -m devx.tools.create_task --title \"Заголовок задачи\"",
"zh": "分支 '{branch}' 不包含任务 ID。\n 预期格式: {prefix}-N-简短描述\n 示例: {prefix}-42-add-feature\n 修复: 重命名分支或先创建 Vikunja 任务:\n python -m devx.tools.create_task --title \"任务标题\""
},
"Branch is behind master. Rebase manually:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nThen re-add the ready-to-merge label.": {
"bg": "Branch is behind master. Rebase manually:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nThen re-add the ready-to-merge label.",
"de": "Branch is behind master. Rebase manually:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nThen re-add the ready-to-merge label.",
"en": "Branch is behind master. Rebase manually:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nThen re-add the ready-to-merge label.",
"pl": "Gałąź jest w tyle za master. Wykonaj rebase ręcznie:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nNastępnie dodaj ponownie etykietę ready-to-merge.",
"ru": "Branch is behind master. Rebase manually:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nThen re-add the ready-to-merge label.",
"zh": "Branch is behind master. Rebase manually:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nThen re-add the ready-to-merge label."
},
"Branch is behind origin/master. Rebase first: git fetch origin master && git rebase origin/master": {
"bg": "Branch is behind origin/master. Rebase first: git fetch origin master && git rebase origin/master",
"de": "Branch is behind origin/master. Rebase first: git fetch origin master && git rebase origin/master",
@@ -2926,5 +2918,157 @@
"pl": "Rebase attempt {n}/3 failed: {err}",
"ru": "Rebase attempt {n}/3 failed: {err}",
"zh": "Rebase attempt {n}/3 failed: {err}"
},
"Auto-rebase failed with HTTP {status}: {message}\nRebase manually:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nThen re-add the ready-to-merge label.": {
"bg": "Auto-rebase failed with HTTP {status}: {message}\nRebase manually:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nThen re-add the ready-to-merge label.",
"de": "Auto-rebase failed with HTTP {status}: {message}\nRebase manually:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nThen re-add the ready-to-merge label.",
"en": "Auto-rebase failed with HTTP {status}: {message}\nRebase manually:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nThen re-add the ready-to-merge label.",
"pl": "Auto-rebase failed with HTTP {status}: {message}\nRebase manually:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nThen re-add the ready-to-merge label.",
"ru": "Auto-rebase failed with HTTP {status}: {message}\nRebase manually:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nThen re-add the ready-to-merge label.",
"zh": "Auto-rebase failed with HTTP {status}: {message}\nRebase manually:\n git fetch origin master && git rebase origin/master && git push --force-with-lease\nThen re-add the ready-to-merge label."
},
"Branch is already up-to-date with origin/master.": {
"bg": "Branch is already up-to-date with origin/master.",
"de": "Branch is already up-to-date with origin/master.",
"en": "Branch is already up-to-date with origin/master.",
"pl": "Branch is already up-to-date with origin/master.",
"ru": "Branch is already up-to-date with origin/master.",
"zh": "Branch is already up-to-date with origin/master."
},
"Branch is behind master. Auto-rebasing via Gitea API...\nA new CI run will start automatically after the rebase.\nThe next auto-merge attempt will merge this PR.": {
"bg": "Branch is behind master. Auto-rebasing via Gitea API...\nA new CI run will start automatically after the rebase.\nThe next auto-merge attempt will merge this PR.",
"de": "Branch is behind master. Auto-rebasing via Gitea API...\nA new CI run will start automatically after the rebase.\nThe next auto-merge attempt will merge this PR.",
"en": "Branch is behind master. Auto-rebasing via Gitea API...\nA new CI run will start automatically after the rebase.\nThe next auto-merge attempt will merge this PR.",
"pl": "Branch is behind master. Auto-rebasing via Gitea API...\nA new CI run will start automatically after the rebase.\nThe next auto-merge attempt will merge this PR.",
"ru": "Branch is behind master. Auto-rebasing via Gitea API...\nA new CI run will start automatically after the rebase.\nThe next auto-merge attempt will merge this PR.",
"zh": "Branch is behind master. Auto-rebasing via Gitea API...\nA new CI run will start automatically after the rebase.\nThe next auto-merge attempt will merge this PR."
},
"Branch is {count} commit(s) behind master. Rebasing...": {
"bg": "Branch is {count} commit(s) behind master. Rebasing...",
"de": "Branch is {count} commit(s) behind master. Rebasing...",
"en": "Branch is {count} commit(s) behind master. Rebasing...",
"pl": "Branch is {count} commit(s) behind master. Rebasing...",
"ru": "Branch is {count} commit(s) behind master. Rebasing...",
"zh": "Branch is {count} commit(s) behind master. Rebasing..."
},
"CI_GITEA_TOKEN is not set. Add it to .env or export it.": {
"bg": "CI_GITEA_TOKEN is not set. Add it to .env or export it.",
"de": "CI_GITEA_TOKEN is not set. Add it to .env or export it.",
"en": "CI_GITEA_TOKEN is not set. Add it to .env or export it.",
"pl": "CI_GITEA_TOKEN is not set. Add it to .env or export it.",
"ru": "CI_GITEA_TOKEN is not set. Add it to .env or export it.",
"zh": "CI_GITEA_TOKEN is not set. Add it to .env or export it."
},
"Cannot rebase: not on a branch (detached HEAD).": {
"bg": "Cannot rebase: not on a branch (detached HEAD).",
"de": "Cannot rebase: not on a branch (detached HEAD).",
"en": "Cannot rebase: not on a branch (detached HEAD).",
"pl": "Cannot rebase: not on a branch (detached HEAD).",
"ru": "Cannot rebase: not on a branch (detached HEAD).",
"zh": "Cannot rebase: not on a branch (detached HEAD)."
},
"Could not detect PR number. Use --pr to specify it explicitly,\nor run this command from a branch with an open PR.": {
"bg": "Could not detect PR number. Use --pr to specify it explicitly,\nor run this command from a branch with an open PR.",
"de": "Could not detect PR number. Use --pr to specify it explicitly,\nor run this command from a branch with an open PR.",
"en": "Could not detect PR number. Use --pr to specify it explicitly,\nor run this command from a branch with an open PR.",
"pl": "Could not detect PR number. Use --pr to specify it explicitly,\nor run this command from a branch with an open PR.",
"ru": "Could not detect PR number. Use --pr to specify it explicitly,\nor run this command from a branch with an open PR.",
"zh": "Could not detect PR number. Use --pr to specify it explicitly,\nor run this command from a branch with an open PR."
},
"Could not determine repository. Set DEVX_REPO_OWNER and DEVX_REPO_NAME\nor GITHUB_REPOSITORY environment variables.": {
"bg": "Could not determine repository. Set DEVX_REPO_OWNER and DEVX_REPO_NAME\nor GITHUB_REPOSITORY environment variables.",
"de": "Could not determine repository. Set DEVX_REPO_OWNER and DEVX_REPO_NAME\nor GITHUB_REPOSITORY environment variables.",
"en": "Could not determine repository. Set DEVX_REPO_OWNER and DEVX_REPO_NAME\nor GITHUB_REPOSITORY environment variables.",
"pl": "Could not determine repository. Set DEVX_REPO_OWNER and DEVX_REPO_NAME\nor GITHUB_REPOSITORY environment variables.",
"ru": "Could not determine repository. Set DEVX_REPO_OWNER and DEVX_REPO_NAME\nor GITHUB_REPOSITORY environment variables.",
"zh": "Could not determine repository. Set DEVX_REPO_OWNER and DEVX_REPO_NAME\nor GITHUB_REPOSITORY environment variables."
},
"Fetch failed: {error}": {
"bg": "Fetch failed: {error}",
"de": "Fetch failed: {error}",
"en": "Fetch failed: {error}",
"pl": "Fetch failed: {error}",
"ru": "Fetch failed: {error}",
"zh": "Fetch failed: {error}"
},
"Fetching origin/master...": {
"bg": "Fetching origin/master...",
"de": "Fetching origin/master...",
"en": "Fetching origin/master...",
"pl": "Fetching origin/master...",
"ru": "Fetching origin/master...",
"zh": "Fetching origin/master..."
},
"Force-push failed:\n{error}\nThe remote may have unexpected commits. Fetch and try again.": {
"bg": "Force-push failed:\n{error}\nThe remote may have unexpected commits. Fetch and try again.",
"de": "Force-push failed:\n{error}\nThe remote may have unexpected commits. Fetch and try again.",
"en": "Force-push failed:\n{error}\nThe remote may have unexpected commits. Fetch and try again.",
"pl": "Force-push failed:\n{error}\nThe remote may have unexpected commits. Fetch and try again.",
"ru": "Force-push failed:\n{error}\nThe remote may have unexpected commits. Fetch and try again.",
"zh": "Force-push failed:\n{error}\nThe remote may have unexpected commits. Fetch and try again."
},
"Force-pushing...": {
"bg": "Force-pushing...",
"de": "Force-pushing...",
"en": "Force-pushing...",
"pl": "Force-pushing...",
"ru": "Force-pushing...",
"zh": "Force-pushing..."
},
"Nothing to push.": {
"bg": "Nothing to push.",
"de": "Nothing to push.",
"en": "Nothing to push.",
"pl": "Nothing to push.",
"ru": "Nothing to push.",
"zh": "Nothing to push."
},
"PR #{pr} rebased successfully. A new CI run will start automatically.\nIf auto-merge is enabled (ready-to-merge label), the next CI run\nwill attempt to merge this PR.": {
"bg": "PR #{pr} rebased successfully. A new CI run will start automatically.\nIf auto-merge is enabled (ready-to-merge label), the next CI run\nwill attempt to merge this PR.",
"de": "PR #{pr} rebased successfully. A new CI run will start automatically.\nIf auto-merge is enabled (ready-to-merge label), the next CI run\nwill attempt to merge this PR.",
"en": "PR #{pr} rebased successfully. A new CI run will start automatically.\nIf auto-merge is enabled (ready-to-merge label), the next CI run\nwill attempt to merge this PR.",
"pl": "PR #{pr} rebased successfully. A new CI run will start automatically.\nIf auto-merge is enabled (ready-to-merge label), the next CI run\nwill attempt to merge this PR.",
"ru": "PR #{pr} rebased successfully. A new CI run will start automatically.\nIf auto-merge is enabled (ready-to-merge label), the next CI run\nwill attempt to merge this PR.",
"zh": "PR #{pr} rebased successfully. A new CI run will start automatically.\nIf auto-merge is enabled (ready-to-merge label), the next CI run\nwill attempt to merge this PR."
},
"Pushed {branch} to origin.": {
"bg": "Pushed {branch} to origin.",
"de": "Pushed {branch} to origin.",
"en": "Pushed {branch} to origin.",
"pl": "Pushed {branch} to origin.",
"ru": "Pushed {branch} to origin.",
"zh": "Pushed {branch} to origin."
},
"Rebase failed (conflicts or other error):\n{error}\nResolve conflicts and run: git rebase --continue": {
"bg": "Rebase failed (conflicts or other error):\n{error}\nResolve conflicts and run: git rebase --continue",
"de": "Rebase failed (conflicts or other error):\n{error}\nResolve conflicts and run: git rebase --continue",
"en": "Rebase failed (conflicts or other error):\n{error}\nResolve conflicts and run: git rebase --continue",
"pl": "Rebase failed (conflicts or other error):\n{error}\nResolve conflicts and run: git rebase --continue",
"ru": "Rebase failed (conflicts or other error):\n{error}\nResolve conflicts and run: git rebase --continue",
"zh": "Rebase failed (conflicts or other error):\n{error}\nResolve conflicts and run: git rebase --continue"
},
"Rebase failed with HTTP {status}: {message}": {
"bg": "Rebase failed with HTTP {status}: {message}",
"de": "Rebase failed with HTTP {status}: {message}",
"en": "Rebase failed with HTTP {status}: {message}",
"pl": "Rebase failed with HTTP {status}: {message}",
"ru": "Rebase failed with HTTP {status}: {message}",
"zh": "Rebase failed with HTTP {status}: {message}"
},
"Rebase successful.": {
"bg": "Rebase successful.",
"de": "Rebase successful.",
"en": "Rebase successful.",
"pl": "Rebase successful.",
"ru": "Rebase successful.",
"zh": "Rebase successful."
},
"Rebasing PR #{pr} via Gitea API...": {
"bg": "Rebasing PR #{pr} via Gitea API...",
"de": "Rebasing PR #{pr} via Gitea API...",
"en": "Rebasing PR #{pr} via Gitea API...",
"pl": "Rebasing PR #{pr} via Gitea API...",
"ru": "Rebasing PR #{pr} via Gitea API...",
"zh": "Rebasing PR #{pr} via Gitea API..."
}
}