diff --git a/.env.example b/.env.example index c786353..98ea7b6 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ # Gitea API token (required for CI scripts that interact with Gitea) # Create at: https://git.oblachno.oblachno.fyi/user/settings/applications -REPO_TOKEN= +CI_GITEA_TOKEN= # Vikunja API token (required for post-merge task updates) # Create at: https://work.oblachno.oblachno.fyi/settings/tokens diff --git a/.gitea/workflows/build-images.yml b/.gitea/workflows/build-images.yml index 870bbae..2cd9af1 100644 --- a/.gitea/workflows/build-images.yml +++ b/.gitea/workflows/build-images.yml @@ -54,19 +54,19 @@ jobs: fetch-depth: 0 - name: Set up environment env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} run: make setup-release - name: Docker registry login env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} - REGISTRY_USERNAME: ${{ vars.REGISTRY_USERNAME }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} + CI_GITEA_USERNAME: ${{ vars.CI_GITEA_USERNAME }} run: | . .venv/bin/activate - echo "$REPO_TOKEN" | docker login git.oblachno.oblachno.fyi -u "$REGISTRY_USERNAME" --password-stdin + echo "$CI_GITEA_TOKEN" | docker login git.oblachno.oblachno.fyi -u "$CI_GITEA_USERNAME" --password-stdin - name: Build and push tier images env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} - REGISTRY_USERNAME: ${{ vars.REGISTRY_USERNAME }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} + CI_GITEA_USERNAME: ${{ vars.CI_GITEA_USERNAME }} PYTHONPATH: src run: | . .venv/bin/activate @@ -95,7 +95,7 @@ jobs: - name: Notify on failure if: failure() env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} PYTHONPATH: src run: | . .venv/bin/activate 2>/dev/null || true @@ -119,7 +119,7 @@ jobs: run: make setup-ci - name: Clean up old image versions env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} PYTHONPATH: src run: | . .venv/bin/activate diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 202bc9d..2d17cf2 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -103,7 +103,7 @@ jobs: fetch-depth: 0 - name: Set up environment env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} run: make setup-image - name: Release dry-run validation env: @@ -127,7 +127,7 @@ jobs: run: make setup-image - name: Run automated PR review env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} PYTHONPATH: src run: | set -euo pipefail @@ -157,12 +157,12 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - token: ${{ secrets.REPO_TOKEN }} + token: ${{ secrets.CI_GITEA_TOKEN }} - name: Set up environment run: make setup-image - name: Squash merge with task ID env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} VIKUNJA_TOKEN: ${{ secrets.VIKUNJA_TOKEN }} DEVX_VIKUNJA_PROJECT_ID: "8" PYTHONPATH: src diff --git a/.gitea/workflows/post-merge.yml b/.gitea/workflows/post-merge.yml index 55cd278..1c19987 100644 --- a/.gitea/workflows/post-merge.yml +++ b/.gitea/workflows/post-merge.yml @@ -93,10 +93,10 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - token: ${{ secrets.REPO_TOKEN }} + token: ${{ secrets.CI_GITEA_TOKEN }} - name: Set up environment env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} run: make setup-image - name: Configure git run: | @@ -113,7 +113,7 @@ jobs: - name: Notify on failure if: failure() env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} PYTHONPATH: src run: | . .venv/bin/activate 2>/dev/null || true @@ -141,7 +141,7 @@ jobs: run: make setup-image EXTRAS=release - name: Build and publish release env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} PYTHONPATH: src run: | . .venv/bin/activate @@ -150,7 +150,7 @@ jobs: - name: Notify on failure if: failure() env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} PYTHONPATH: src run: | . .venv/bin/activate 2>/dev/null || true @@ -178,7 +178,7 @@ jobs: run: make setup-image - name: Sync documentation to wiki env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} PYTHONPATH: src run: | . .venv/bin/activate @@ -186,7 +186,7 @@ jobs: - name: Notify on failure if: failure() env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} PYTHONPATH: src run: | export PATH="$HOME/.local/bin:$PATH" @@ -210,7 +210,7 @@ jobs: with: fetch-depth: 0 ref: master - token: ${{ secrets.REPO_TOKEN }} + token: ${{ secrets.CI_GITEA_TOKEN }} - name: Fetch latest master run: | git fetch origin master @@ -226,7 +226,7 @@ jobs: - name: Notify on failure if: failure() env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} PYTHONPATH: src run: | export PATH="$HOME/.local/bin:$PATH" @@ -262,7 +262,7 @@ jobs: - name: Notify on failure if: failure() env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} PYTHONPATH: src run: | export PATH="$HOME/.local/bin:$PATH" @@ -287,7 +287,7 @@ jobs: run: make setup-image - name: Ensure branch protection and labels env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} PYTHONPATH: src run: | . .venv/bin/activate @@ -295,7 +295,7 @@ jobs: - name: Notify on failure if: failure() env: - REPO_TOKEN: ${{ secrets.REPO_TOKEN }} + CI_GITEA_TOKEN: ${{ secrets.CI_GITEA_TOKEN }} PYTHONPATH: src run: | export PATH="$HOME/.local/bin:$PATH" diff --git a/AGENTS.md b/AGENTS.md index b4e6dba..6acba32 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -17,7 +17,7 @@ make clean # Remove caches, build artifacts, coverage data `make setup` automatically installs all development tools: - **Python deps** via `python -m devx.tools.setup` (pip install -e .[dev], pre-commit hooks) - **actionlint, git-cliff, act_runner, tea** via `python -m devx.tools.install_tools` (CI/CD tools to ~/.local/bin) -- **tea CLI login** via `python -m devx.tools.setup` (configures `tea login` from `.env` `REPO_TOKEN`) +- **tea CLI login** via `python -m devx.tools.setup` (configures `tea login` from `.env` `CI_GITEA_TOKEN`) ## Workflow Verification (Before Push) @@ -263,7 +263,7 @@ so `.:src` is not needed. The `src` directory is the sole import root. The `tea` Gitea CLI tool is used for Gitea API interactions. It is installed by `python -m devx.tools.install_tools` and configured by -`python -m devx.tools.setup` (login profile from `.env` `REPO_TOKEN`). +`python -m devx.tools.setup` (login profile from `.env` `CI_GITEA_TOKEN`). **`devx.gitea_cli.TeaCLI`** — Python wrapper around `tea` CLI with JSON output parsing: - `create_issue()` — Create issues with labels @@ -358,7 +358,7 @@ devx uses environment variables with `.env` file fallback for configuration. | `DEVX_TASK_PREFIX` | `DEVX` | Task ID prefix (GRM, OBL-INFRA, etc.) | | `DEVX_VIKUNJA_PROJECT_ID` | `6` | Vikunja project ID | | `DEVX_LANG` | `en` | Language for i18n (en, bg) | -| `REPO_TOKEN` | (from .env) | Gitea API token | +| `CI_GITEA_TOKEN` | (from .env) | Gitea API token | | `VIKUNJA_TOKEN` | (from .env) | Vikunja API token | ### Per-Project Overrides diff --git a/README.md b/README.md index d405e66..16befaf 100644 --- a/README.md +++ b/README.md @@ -326,7 +326,7 @@ The config system loads `.env` automatically via `python-dotenv`. | `DEVX_DOCS_DIR` | `docs` | Documentation directory (used by sync_wiki) | | `DEVX_STATUS_CHECKS` | `CI / quality (pull_request)` | Comma-separated status check contexts | | `DEVX_PYPI_REGISTRY_URL` | — | Gitea PyPI registry URL (used by publish) | -| `REPO_TOKEN` | — | Gitea API token | +| `CI_GITEA_TOKEN` | — | Gitea API token | | `VIKUNJA_TOKEN` | — | Vikunja API token | | `PYPI_TOKEN` | — | Standard PyPI token (takes precedence over Gitea registry) | diff --git a/docs/index.md b/docs/index.md index d1df218..23de29e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -149,7 +149,7 @@ fallback. Key variables: | `DEVX_REPO_NAME` | **(must be set)** | Repository name | | `DEVX_TASK_PREFIX` | `DEVX` | Task ID prefix (GRM, OBL-INFRA, etc.) | | `DEVX_LANG` | `en` | Language for i18n (en, bg, de, ru, zh, pl) | -| `REPO_TOKEN` | — | Gitea API token | +| `CI_GITEA_TOKEN` | — | Gitea API token | | `VIKUNJA_TOKEN` | — | Vikunja API token | See [AGENTS.md](https://git.oblachno.oblachno.fyi/oblachno-oss/devx/src/branch/master/AGENTS.md) diff --git a/docs/tech/architecture.md b/docs/tech/architecture.md index a9a57d0..ed7d12f 100644 --- a/docs/tech/architecture.md +++ b/docs/tech/architecture.md @@ -245,7 +245,7 @@ for retrying on git push failures. Creates a Gitea issue when a CI workflow fails. Uses the `tea` CLI for issue creation with failure labels. Supports `--auto-login` to configure the tea -CLI login profile from `REPO_TOKEN` and `DEVX_GITEA_API_URL` before creating +CLI login profile from `CI_GITEA_TOKEN` and `DEVX_GITEA_API_URL` before creating the issue. ### `post_merge.py` @@ -569,7 +569,7 @@ push_badges.py: The `tea` Gitea CLI tool is used for Gitea API interactions where tea provides reliable, official support. It is installed by `python -m devx.tools.install_tools` and configured by -`python -m devx.tools.setup` (login profile from `.env` `REPO_TOKEN`). +`python -m devx.tools.setup` (login profile from `.env` `CI_GITEA_TOKEN`). `devx.gitea_cli.TeaCLI` wraps tea with JSON output parsing. Operations that tea does not support (wiki management, commit status, runner discovery, diff --git a/docs/tech/ci-cd-workflow.md b/docs/tech/ci-cd-workflow.md index 96a2d47..326f518 100644 --- a/docs/tech/ci-cd-workflow.md +++ b/docs/tech/ci-cd-workflow.md @@ -305,7 +305,7 @@ post-merge workflow when it creates and pushes a new version tag. and the project itself 2. **Install CI tools** — git-cliff and tea via `python -m devx.tools.install_tools` -3. **Configure tea login** — `tea login add` using `REPO_TOKEN` +3. **Configure tea login** — `tea login add` using `CI_GITEA_TOKEN` 4. **Build and publish** — `python -m devx.ci.publish `: - Build the package with `python -m build` - Publish to the Gitea PyPI registry (default) using `twine upload @@ -377,7 +377,7 @@ python -m devx.ci.pr_review Creates a Gitea issue when a CI workflow fails. Uses the tea CLI for issue creation with failure labels. Supports `--auto-login` to configure the tea -CLI login profile from `REPO_TOKEN`. +CLI login profile from `CI_GITEA_TOKEN`. ```bash python -m devx.ci.notify_failure --repo --run-id \ diff --git a/docs/user/cli-commands.md b/docs/user/cli-commands.md index 16351e2..27f54f8 100644 --- a/docs/user/cli-commands.md +++ b/docs/user/cli-commands.md @@ -148,7 +148,7 @@ devx ci integration-guard -- -x -v --tb=short test_a.py Environment variables: - `GITEA_URL` — base URL of the Gitea instance -- `REPO_TOKEN` — API token with repo access +- `CI_GITEA_TOKEN` — API token with repo access - `RUN_ID` — workflow run ID (`GITHUB_RUN_ID`) - `JOB_NAME` — base job name (`GITHUB_JOB`) - `MATRIX_INDEX` — current matrix index (runner-index) @@ -171,7 +171,7 @@ Options: - `--run-id ` — CI run ID (required) - `--workflow ` — workflow name (required) - `--commit ` — commit SHA (required) -- `--auto-login` — configure tea CLI login from `REPO_TOKEN` before creating +- `--auto-login` — configure tea CLI login from `CI_GITEA_TOKEN` before creating the issue ### `devx ci post-merge` @@ -462,7 +462,7 @@ Options: Environment variables: - `GITEA_URL` — base URL of the Gitea instance -- `REPO_TOKEN` — API token with repo access +- `CI_GITEA_TOKEN` — API token with repo access - `RUN_ID` — workflow run ID (`GITHUB_RUN_ID`) - `JOB_NAME` — base job name (`GITHUB_JOB`) - `MATRIX_INDEX` — current matrix index (runner-index) diff --git a/src/devx/ci/auto_merge.py b/src/devx/ci/auto_merge.py index 1ecc218..e9ba114 100644 --- a/src/devx/ci/auto_merge.py +++ b/src/devx/ci/auto_merge.py @@ -17,7 +17,7 @@ This allows the PR title to be a human-friendly Vikunja task title while the squashed commit follows conventional commits. Usage: - REPO_TOKEN= python3 -m devx.ci.auto_merge + CI_GITEA_TOKEN= python3 -m devx.ci.auto_merge """ import os @@ -196,9 +196,9 @@ def extract_conventional_msg(commits: list[dict[str, Any]]) -> str: @click.argument("repo") @click.argument("pr_number") def main(branch: str, pr_title: str, repo: str, pr_number: str) -> None: - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") if not token: - raise click.ClickException(_("ERROR: REPO_TOKEN is not set.")) + raise click.ClickException(_("ERROR: CI_GITEA_TOKEN is not set.")) # Validate PR number is an integer try: diff --git a/src/devx/ci/check_auto_merge_ready.py b/src/devx/ci/check_auto_merge_ready.py index 0e6ad2f..7d73a58 100644 --- a/src/devx/ci/check_auto_merge_ready.py +++ b/src/devx/ci/check_auto_merge_ready.py @@ -15,7 +15,7 @@ Exit code 1 = NOT ready — fix issues before pushing. Usage:: - # CI (with VIKUNJA_TOKEN and REPO_TOKEN): + # CI (with VIKUNJA_TOKEN and CI_GITEA_TOKEN): python3 -m devx.ci.check_auto_merge_ready \\ --branch "$HEAD_REF" \\ --pr-title "$PR_TITLE" \\ @@ -34,7 +34,7 @@ skipped (with a warning) — this allows local pre-push hooks to run without CI secrets. In CI, the token is always set and the check is mandatory. -If ``REPO_TOKEN`` is not set and ``--pr-number`` is not provided, only +If ``CI_GITEA_TOKEN`` is not set and ``--pr-number`` is not provided, only branch-name and PR-title-format checks run (local mode). """ @@ -98,9 +98,9 @@ def is_branch_behind_master(branch: str) -> bool: def get_pr_title_from_gitea(repo: str, pr_number: int) -> str | None: """Fetch the PR title from the Gitea API. - Returns ``None`` if ``REPO_TOKEN`` is not set or the PR cannot be fetched. + Returns ``None`` if ``CI_GITEA_TOKEN`` is not set or the PR cannot be fetched. """ - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") if not token or "/" not in repo: return None owner, repo_name = repo.split("/", 1) @@ -189,7 +189,9 @@ def cli( if pr_title is None: # Local mode without PR — only validate branch name if pr_number is not None: - raise click.ClickException(_("Could not fetch PR title from Gitea (REPO_TOKEN not set or PR not found).")) + raise click.ClickException( + _("Could not fetch PR title from Gitea (CI_GITEA_TOKEN not set or PR not found).") + ) click.echo("[pre-merge-check] No PR title provided — running branch-name-only check (local mode).") click.echo("[pre-merge-check] Branch name OK. Push to create PR, then CI will validate the title.") return diff --git a/src/devx/ci/discover_runners.py b/src/devx/ci/discover_runners.py index 4a68b1d..7ab703d 100644 --- a/src/devx/ci/discover_runners.py +++ b/src/devx/ci/discover_runners.py @@ -148,7 +148,7 @@ def main( output_indices: bool, github_output: bool, ) -> None: - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") if owner is None: owner = os.environ.get("DEVX_REPO_OWNER", "oblachno-oss") diff --git a/src/devx/ci/integration_guard.py b/src/devx/ci/integration_guard.py index 457281a..42bd0ad 100644 --- a/src/devx/ci/integration_guard.py +++ b/src/devx/ci/integration_guard.py @@ -17,7 +17,7 @@ Usage:: Environment variables: GITEA_URL Base URL of the Gitea instance. - REPO_TOKEN API token with repo access. + CI_GITEA_TOKEN API token with repo access. RUN_ID Workflow run ID (GITHUB_RUN_ID). JOB_NAME Base job name (GITHUB_JOB), e.g. "integration-tests". MATRIX_INDEX Current matrix index (runner-index). @@ -49,7 +49,7 @@ POLL_INTERVAL = 10 def cli(pytest_args: tuple[str, ...]) -> None: """Run pytest with cross-runner failure detection.""" gitea_url = os.environ.get("GITEA_URL", "") - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") run_id = int(os.environ.get("RUN_ID", "0")) job_name = os.environ.get("JOB_NAME", "integration-tests") current_index = int(os.environ.get("MATRIX_INDEX", "0")) @@ -59,7 +59,7 @@ def cli(pytest_args: tuple[str, ...]) -> None: owner, repo = "oblachno-oss", "devx" if not all([gitea_url, token, run_id]): - click.echo(_("GITEA_URL/REPO_TOKEN/RUN_ID not set; running without cross-runner cancellation.")) + click.echo(_("GITEA_URL/CI_GITEA_TOKEN/RUN_ID not set; running without cross-runner cancellation.")) stop_event = threading.Event() failed_event = threading.Event() diff --git a/src/devx/ci/notify_failure.py b/src/devx/ci/notify_failure.py index 797fe43..242e501 100644 --- a/src/devx/ci/notify_failure.py +++ b/src/devx/ci/notify_failure.py @@ -6,7 +6,7 @@ otherwise go unnoticed in the Actions tab. Uses the ``tea`` Gitea CLI for issue creation — tea must be installed and configured. Usage: - REPO_TOKEN= python3 -m devx.ci.notify_failure \ + CI_GITEA_TOKEN= python3 -m devx.ci.notify_failure \ --repo \ --run-id \ --workflow \ @@ -14,7 +14,7 @@ Usage: --auto-login With ``--auto-login``, the script configures the tea CLI login profile -from ``REPO_TOKEN`` and ``DEVX_GITEA_API_URL`` before creating the issue, +from ``CI_GITEA_TOKEN`` and ``DEVX_GITEA_API_URL`` before creating the issue, eliminating the need for a separate ``tea login add`` step in the workflow. """ @@ -71,12 +71,12 @@ def _create_issue_via_tea(repo: str, title: str, body: str) -> int: "--auto-login", is_flag=True, default=False, - help="Configure tea CLI login from REPO_TOKEN before creating the issue.", + help="Configure tea CLI login from CI_GITEA_TOKEN before creating the issue.", ) def main(repo: str, run_id: str, workflow: str, commit: str, auto_login: bool) -> None: - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") if not token: - raise click.ClickException(_("ERROR: REPO_TOKEN is not set.")) + raise click.ClickException(_("ERROR: CI_GITEA_TOKEN is not set.")) if auto_login: configure_tea_login() diff --git a/src/devx/ci/pr_review.py b/src/devx/ci/pr_review.py index 15eae60..071383c 100644 --- a/src/devx/ci/pr_review.py +++ b/src/devx/ci/pr_review.py @@ -17,7 +17,7 @@ Checks performed: 8. Commit conventions — conventional commit format on branch commits Usage: - REPO_TOKEN= python3 -m devx.ci.pr_review + CI_GITEA_TOKEN= python3 -m devx.ci.pr_review """ from __future__ import annotations @@ -526,9 +526,9 @@ def post_review(client: GiteaClient, pr_number: str, result: ReviewResult) -> di @click.option("--dry-run", is_flag=True, default=False, help="Print review without posting.") def main(pr_number: str, repo: str, dry_run: bool) -> None: """Run automated PR review and post results to Gitea.""" - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") if not token: - raise click.ClickException(_("ERROR: REPO_TOKEN is not set.")) + raise click.ClickException(_("ERROR: CI_GITEA_TOKEN is not set.")) owner, repo_name = repo.split("/") client = GiteaClient(GITEA_API_URL, token, owner, repo_name) diff --git a/src/devx/ci/publish.py b/src/devx/ci/publish.py index 39e0c33..d0a5621 100644 --- a/src/devx/ci/publish.py +++ b/src/devx/ci/publish.py @@ -9,14 +9,14 @@ Publishing destinations (checked in order): ``DEVX_PYPI_REGISTRY_URL`` env var is set, or ``GITEA_API_URL`` is converted to a packages URL). Uses ``twine upload --repository-url -u -p `` with the - ``REPO_TOKEN`` as both username and password. + ``CI_GITEA_TOKEN`` as both username and password. 2. **Standard PyPI** — if ``PYPI_TOKEN`` is set. Uses the standard ``twine upload -u __token__ -p `` flow. 3. **Skip** — if neither is configured, only the Gitea release is created. Usage: - REPO_TOKEN= [PYPI_TOKEN=] python3 -m devx.ci.publish - REPO_TOKEN= python3 -m devx.ci.publish --registry-url https://git.example.com/api/packages/owner/pypi + CI_GITEA_TOKEN= [PYPI_TOKEN=] python3 -m devx.ci.publish + CI_GITEA_TOKEN= python3 -m devx.ci.publish --registry-url https://git.example.com/api/packages/owner/pypi """ import os @@ -225,7 +225,7 @@ def is_release_commit(tag: str) -> bool: "--auto-login", is_flag=True, default=False, - help="Configure tea CLI login from REPO_TOKEN before creating the Gitea release. " + help="Configure tea CLI login from CI_GITEA_TOKEN before creating the Gitea release. " "Eliminates the need for a separate tea login step in containerized CI jobs.", ) def main( @@ -253,9 +253,9 @@ def main( if not tag: raise click.ClickException(_("Tag is required (or use --from-tag).")) - gitea_token = os.environ.get("REPO_TOKEN", "") + gitea_token = os.environ.get("CI_GITEA_TOKEN", "") if not gitea_token: - raise click.ClickException(_("ERROR: REPO_TOKEN is not set.")) + raise click.ClickException(_("ERROR: CI_GITEA_TOKEN is not set.")) pypi_token = os.environ.get("PYPI_TOKEN", "") diff --git a/src/devx/ci/release.py b/src/devx/ci/release.py index 31b7db0..c723235 100644 --- a/src/devx/ci/release.py +++ b/src/devx/ci/release.py @@ -29,7 +29,7 @@ version. This prevents duplicate release commits (a common issue when CI checkouts don't fetch tags) and ensures tag/version/commit alignment. Usage: - REPO_TOKEN= python3 -m devx.ci.release [--dry-run] [--skip-tests] + CI_GITEA_TOKEN= python3 -m devx.ci.release [--dry-run] [--skip-tests] python3 -m devx.ci.release --verify # Check tag/version/release alignment """ diff --git a/src/devx/ci/sync_wiki.py b/src/devx/ci/sync_wiki.py index e66fa45..6c6d9ab 100644 --- a/src/devx/ci/sync_wiki.py +++ b/src/devx/ci/sync_wiki.py @@ -14,7 +14,7 @@ Gitea 1.26 wiki API endpoints (all use content_base64, NOT content): - Delete: DELETE /repos/{owner}/{repo}/wiki/page/{sub_url} Usage: - REPO_TOKEN= python3 -m devx.ci.sync_wiki [--dry-run] [--repo owner/repo] + CI_GITEA_TOKEN= python3 -m devx.ci.sync_wiki [--dry-run] [--repo owner/repo] """ from __future__ import annotations @@ -225,9 +225,9 @@ def verify_wiki_integrity( help="Full integrity check: verify page count, missing pages, stale pages, and content. Implies --verify.", ) def main(dry_run: bool, repo: str | None, verify: bool, strict: bool) -> None: - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") if not token: - raise click.ClickException(_("ERROR: REPO_TOKEN is not set.")) + raise click.ClickException(_("ERROR: CI_GITEA_TOKEN is not set.")) if repo is None: owner = os.environ.get("DEVX_REPO_OWNER", "oblachno-oss") diff --git a/src/devx/gitea_cli.py b/src/devx/gitea_cli.py index 12185dd..96989a4 100644 --- a/src/devx/gitea_cli.py +++ b/src/devx/gitea_cli.py @@ -56,10 +56,10 @@ class TeaCLIError(Exception): def configure_tea_login(login_name: str = "devx") -> None: - """Configure tea CLI login from REPO_TOKEN and DEVX_GITEA_API_URL. + """Configure tea CLI login from CI_GITEA_TOKEN and DEVX_GITEA_API_URL. Idempotent: if a login with the same name already exists, it is not re-added. - Skips silently if tea is not installed or REPO_TOKEN is not set. + Skips silently if tea is not installed or CI_GITEA_TOKEN is not set. Used by CI scripts (publish, notify_failure) that need tea login but run in containerized environments where ``make setup`` was not called. @@ -69,9 +69,9 @@ def configure_tea_login(login_name: str = "devx") -> None: click.echo(_("tea not installed — skipping login configuration.")) return - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") if not token: - click.echo(_("REPO_TOKEN not set — skipping login configuration.")) + click.echo(_("CI_GITEA_TOKEN not set — skipping login configuration.")) return gitea_url = GITEA_API_URL.replace("/api/v1", "") diff --git a/src/devx/make/devx.mak b/src/devx/make/devx.mak index f3302a5..521af07 100644 --- a/src/devx/make/devx.mak +++ b/src/devx/make/devx.mak @@ -54,11 +54,11 @@ DEVX_WORKFLOW_DIR ?= .gitea/workflows # PIP_INSTALL — helper to run pip with Gitea private PyPI registry configured. # Usage: $(DEVX_PIP_INSTALL) install -e '.[ci,lint]' -# GITEA_PYPI_USER can be set in .env, as an env var, or as a Make variable. -DEVX_PIP_INSTALL := if [ -z "$$REPO_TOKEN" ]; then . ./.env 2>/dev/null; fi; \ - REPO_TOKEN="$${REPO_TOKEN:-$$GITEA_REGISTRY_TOKEN}"; \ - _PYPI_USER="$${DEVX_GITEA_PYPI_USER:-$${GITEA_PYPI_USER}}"; \ - if [ -n "$$REPO_TOKEN" ] && [ -n "$$_PYPI_USER" ]; then export PIP_EXTRA_INDEX_URL="https://$$_PYPI_USER:$$REPO_TOKEN@$(DEVX_GITEA_PYPI_HOST)/api/packages/$(DEVX_GITEA_PYPI_ORG)/pypi/simple/"; fi; \ +# CI_GITEA_USERNAME can be set in .env, as an env var, or as a Make variable. +DEVX_PIP_INSTALL := if [ -z "$$CI_GITEA_TOKEN" ]; then . ./.env 2>/dev/null; fi; \ + CI_GITEA_TOKEN="$$CI_GITEA_TOKEN"; \ + _PYPI_USER="$${CI_GITEA_USERNAME:-emil}"; \ + if [ -n "$$CI_GITEA_TOKEN" ] && [ -n "$$_PYPI_USER" ]; then export PIP_EXTRA_INDEX_URL="https://$$_PYPI_USER:$$CI_GITEA_TOKEN@$(DEVX_GITEA_PYPI_HOST)/api/packages/$(DEVX_GITEA_PYPI_ORG)/pypi/simple/"; fi; \ $(DEVX_BIN)/pip .PHONY: devx-create-task devx-create-pr devx-push devx-push-with-pr devx-check-config @@ -96,12 +96,12 @@ devx-push-with-pr: devx-push devx-create-pr # ── Environment setup ───────────────────────────────────────────────────────── # 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. +# private packages. In CI, CI_GITEA_TOKEN is set as a secret. Locally, it's in .env. devx-configure-gitea-pypi: - @if [ -z "$$REPO_TOKEN" ]; then . ./.env 2>/dev/null; fi; \ - 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)." + @if [ -z "$$CI_GITEA_TOKEN" ]; then . ./.env 2>/dev/null; fi; \ + CI_GITEA_TOKEN="$$CI_GITEA_TOKEN"; \ + if [ -z "$$CI_GITEA_TOKEN" ]; then echo "[configure-gitea-pypi] CI_GITEA_TOKEN not set — skipping (devx must be on public PyPI)"; exit 0; fi; \ + echo "[configure-gitea-pypi] Gitea PyPI registry configured (CI_GITEA_TOKEN present)." # Create .env from .env.example if it doesn't exist devx-env: @@ -174,7 +174,7 @@ devx-workflow-check: devx-workflow-lint devx-workflow-dryrun # Notify on CI failure — creates a Gitea issue via devx.ci.notify_failure. # Usage: make devx-notify-failure WORKFLOW=post-merge/release -# Requires: REPO_TOKEN, GITHUB_REPOSITORY, GITHUB_RUN_ID, GITHUB_SHA +# Requires: CI_GITEA_TOKEN, GITHUB_REPOSITORY, GITHUB_RUN_ID, GITHUB_SHA devx-notify-failure: @. $(DEVX_VENV)/bin/activate 2>/dev/null || true; \ export PATH="$(HOME)/.local/bin:$$PATH"; \ @@ -268,8 +268,8 @@ devx-clean: devx-setup-image: @if [ -d /opt/venv ]; then ln -sf /opt/venv $(DEVX_VENV); . $(DEVX_BIN)/activate; \ - _U="$${DEVX_GITEA_PYPI_USER:-$${GITEA_PYPI_USER:-emil}}"; \ - if [ -n "$$REPO_TOKEN" ]; then export PIP_EXTRA_INDEX_URL="https://$$_U:$$REPO_TOKEN@$(DEVX_GITEA_PYPI_HOST)/api/packages/$(DEVX_GITEA_PYPI_ORG)/pypi/simple/"; fi; \ + _U="$${CI_GITEA_USERNAME:-emil}"; \ + if [ -n "$$CI_GITEA_TOKEN" ]; then export PIP_EXTRA_INDEX_URL="https://$$_U:$$CI_GITEA_TOKEN@$(DEVX_GITEA_PYPI_HOST)/api/packages/$(DEVX_GITEA_PYPI_ORG)/pypi/simple/"; fi; \ pip install -e .$(if $(EXTRAS),[$(EXTRAS)],); \ echo "[devx-setup-image] Linked /opt/venv$(if $(EXTRAS), with [$(EXTRAS)],)."; \ else echo "[devx-setup-image] /opt/venv not found — falling back to setup-ci"; $(MAKE) setup-ci; fi diff --git a/src/devx/molecule/discover_runners.py b/src/devx/molecule/discover_runners.py index 8d387f0..b61c7b4 100644 --- a/src/devx/molecule/discover_runners.py +++ b/src/devx/molecule/discover_runners.py @@ -142,7 +142,7 @@ def main( output_indices: bool, github_output: bool, ) -> None: - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") if owner is None: owner = os.environ.get("DEVX_REPO_OWNER", "oblachno-oss") diff --git a/src/devx/molecule/molecule_ci_guard.py b/src/devx/molecule/molecule_ci_guard.py index 6bfee34..e043a3b 100644 --- a/src/devx/molecule/molecule_ci_guard.py +++ b/src/devx/molecule/molecule_ci_guard.py @@ -22,7 +22,7 @@ Usage:: Environment variables: GITEA_URL Base URL of the Gitea instance. - REPO_TOKEN API token with repo access. + CI_GITEA_TOKEN API token with repo access. RUN_ID Workflow run ID (GITHUB_RUN_ID). JOB_NAME Base job name (GITHUB_JOB), e.g. "molecule-tests". MATRIX_INDEX Current matrix index (runner-index). @@ -163,7 +163,7 @@ def resolve_role_dir(role: str, roles_root: Path | None, repo_root: Path) -> Pat def cli(pairs: tuple[str, ...], roles_root: Path | None) -> None: """Run molecule pairs sequentially, stop if another CI runner fails.""" gitea_url = os.environ.get("GITEA_URL", "") - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") run_id = int(os.environ.get("RUN_ID", "0")) job_name = os.environ.get("JOB_NAME", "molecule-tests") current_index = int(os.environ.get("MATRIX_INDEX", "0")) @@ -173,7 +173,7 @@ def cli(pairs: tuple[str, ...], roles_root: Path | None) -> None: owner, repo = "oblachno-oss", "devx" if not all([gitea_url, token, run_id]): - click.echo(_("GITEA_URL/REPO_TOKEN/RUN_ID not set; running without cross-runner cancellation.")) + click.echo(_("GITEA_URL/CI_GITEA_TOKEN/RUN_ID not set; running without cross-runner cancellation.")) # When devx is installed as a pip package, __file__ resolves to the # site-packages directory, not the repo root. Use GITHUB_WORKSPACE diff --git a/src/devx/tools/build_image.py b/src/devx/tools/build_image.py index db211c6..82839bc 100644 --- a/src/devx/tools/build_image.py +++ b/src/devx/tools/build_image.py @@ -34,9 +34,8 @@ The manifest file is a JSON list of dicts, each with: - ``context``: build context directory (optional, defaults to repo root) - ``tags``: list of tags (optional, defaults to ``["latest"]``) -Registry authentication uses ``REPO_TOKEN`` (or ``GITEA_REGISTRY_TOKEN``) -and ``REGISTRY_USERNAME`` (or ``GITEA_REGISTRY_USERNAME``) environment -variables, matching the existing CI workflow patterns. +Registry authentication uses ``CI_GITEA_TOKEN`` and ``CI_GITEA_USERNAME`` +environment variables, matching the existing CI workflow patterns. """ from __future__ import annotations @@ -221,13 +220,9 @@ def push_image( def _get_registry_creds() -> tuple[str, str]: - """Get registry credentials from environment variables. - - Supports both REPO_TOKEN/GITEA_REGISTRY_TOKEN and - REGISTRY_USERNAME/GITEA_REGISTRY_USERNAME patterns. - """ - token = os.environ.get("REPO_TOKEN") or os.environ.get("GITEA_REGISTRY_TOKEN", "") - username = os.environ.get("REGISTRY_USERNAME") or os.environ.get("GITEA_REGISTRY_USERNAME", "") + """Get registry credentials from environment variables.""" + token = os.environ.get("CI_GITEA_TOKEN", "") + username = os.environ.get("CI_GITEA_USERNAME", "") return username, token @@ -312,7 +307,7 @@ def main( username, token = _get_registry_creds() if not token or not username: raise click.ClickException( - _("Registry credentials required: set REPO_TOKEN and REGISTRY_USERNAME env vars") + _("Registry credentials required: set CI_GITEA_TOKEN and CI_GITEA_USERNAME env vars") ) if not registry_login(registry, username, token, dry_run=dry_run): raise click.ClickException(_("Registry login failed")) diff --git a/src/devx/tools/clean_images.py b/src/devx/tools/clean_images.py index 9c6da0a..5225c50 100644 --- a/src/devx/tools/clean_images.py +++ b/src/devx/tools/clean_images.py @@ -28,7 +28,7 @@ Usage:: --keep 2 \\ --dry-run -Authentication uses ``REPO_TOKEN`` environment variable. +Authentication uses ``CI_GITEA_TOKEN`` environment variable. """ from __future__ import annotations @@ -164,9 +164,9 @@ def main( api_url: str | None, ) -> None: """Clean up old Docker image versions from a Gitea registry.""" - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") if not token: - raise click.ClickException(_("REPO_TOKEN environment variable required")) + raise click.ClickException(_("CI_GITEA_TOKEN environment variable required")) base_url = api_url or GITEA_API_URL total_deleted = 0 diff --git a/src/devx/tools/configure_repo.py b/src/devx/tools/configure_repo.py index cf40cb7..1db27c2 100644 --- a/src/devx/tools/configure_repo.py +++ b/src/devx/tools/configure_repo.py @@ -6,8 +6,8 @@ The ``tea`` CLI is used for label creation if available, with a fallback to ``GiteaClient`` if tea is not installed. Usage: - REPO_TOKEN= python3 -m devx.tools.configure_repo --repo my-repo - REPO_TOKEN= python3 -m devx.tools.configure_repo --repo my-repo --owner my-org + CI_GITEA_TOKEN= python3 -m devx.tools.configure_repo --repo my-repo + CI_GITEA_TOKEN= python3 -m devx.tools.configure_repo --repo my-repo --owner my-org """ from __future__ import annotations @@ -102,7 +102,7 @@ def configure_repo( api_url: Gitea API base URL. If None, uses ``GITEA_API_URL`` from config. """ if not token: - raise click.ClickException(_("ERROR: REPO_TOKEN is not set.")) + raise click.ClickException(_("ERROR: CI_GITEA_TOKEN is not set.")) url = api_url or GITEA_API_URL client = GiteaClient(url, token, owner, repo) @@ -148,7 +148,7 @@ def configure_repo( ) def main(repo: str | None, owner: str | None, branch: str, api_url: str | None) -> None: """Configure branch protection and repository settings via the Gitea API.""" - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") if repo is None: repo = os.environ.get("DEVX_REPO_NAME", "") diff --git a/src/devx/tools/create_pr.py b/src/devx/tools/create_pr.py index 497abab..3e68f46 100644 --- a/src/devx/tools/create_pr.py +++ b/src/devx/tools/create_pr.py @@ -123,9 +123,9 @@ def create_pr( ), ) - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") if not token: - raise click.ClickException(_("REPO_TOKEN is not set. Required to create a PR.")) + raise click.ClickException(_("CI_GITEA_TOKEN is not set. Required to create a PR.")) vikunja_title = get_vikunja_task_title(task_id) pr_title = f"{task_id}: {vikunja_title}" diff --git a/src/devx/tools/setup.py b/src/devx/tools/setup.py index be6aafb..b4e4bb1 100644 --- a/src/devx/tools/setup.py +++ b/src/devx/tools/setup.py @@ -64,19 +64,19 @@ def _install_ansible_collections(bin_dir: str) -> None: def _configure_tea_login() -> None: - """Configure tea CLI login from .env if REPO_TOKEN is set. + """Configure tea CLI login from .env if CI_GITEA_TOKEN is set. Idempotent: if a login with the same name already exists, it is not re-added. - Skips if tea is not installed or REPO_TOKEN is not set. + Skips if tea is not installed or CI_GITEA_TOKEN is not set. """ tea_bin = shutil.which("tea") if tea_bin is None: click.echo("tea: not installed — run 'make install-tools' to install it.") return - token = os.environ.get("REPO_TOKEN", "") + token = os.environ.get("CI_GITEA_TOKEN", "") if not token: - click.echo("tea: REPO_TOKEN not set — skipping login configuration.") + click.echo("tea: CI_GITEA_TOKEN not set — skipping login configuration.") return api_url = os.environ.get("DEVX_GITEA_API_URL", "https://git.oblachno.oblachno.fyi/api/v1") diff --git a/src/devx/translations.json b/src/devx/translations.json index b67bd5a..f3460cf 100644 --- a/src/devx/translations.json +++ b/src/devx/translations.json @@ -535,13 +535,13 @@ "ru": "Could not extract conventional commit message from PR commits.", "zh": "Could not extract conventional commit message from PR commits." }, - "Could not fetch PR title from Gitea (REPO_TOKEN not set or PR not found).": { - "bg": "Could not fetch PR title from Gitea (REPO_TOKEN not set or PR not found).", - "de": "Could not fetch PR title from Gitea (REPO_TOKEN not set or PR not found).", - "en": "Could not fetch PR title from Gitea (REPO_TOKEN not set or PR not found).", - "pl": "Could not fetch PR title from Gitea (REPO_TOKEN not set or PR not found).", - "ru": "Could not fetch PR title from Gitea (REPO_TOKEN not set or PR not found).", - "zh": "Could not fetch PR title from Gitea (REPO_TOKEN not set or PR not found)." + "Could not fetch PR title from Gitea (CI_GITEA_TOKEN not set or PR not found).": { + "bg": "Could not fetch PR title from Gitea (CI_GITEA_TOKEN not set or PR not found).", + "de": "Could not fetch PR title from Gitea (CI_GITEA_TOKEN not set or PR not found).", + "en": "Could not fetch PR title from Gitea (CI_GITEA_TOKEN not set or PR not found).", + "pl": "Could not fetch PR title from Gitea (CI_GITEA_TOKEN not set or PR not found).", + "ru": "Could not fetch PR title from Gitea (CI_GITEA_TOKEN not set or PR not found).", + "zh": "Could not fetch PR title from Gitea (CI_GITEA_TOKEN not set or PR not found)." }, "Could not find Vikunja task {task_id} in project {project_id}.": { "bg": "Не е намерена Vikunja задача {task_id} в проект {project_id}.", @@ -655,13 +655,13 @@ "ru": "Dry-run mode: on branch '{branch}' (not master). Some checks may behave differently.", "zh": "Dry-run mode: on branch '{branch}' (not master). Some checks may behave differently." }, - "ERROR: REPO_TOKEN is not set.": { - "bg": "ГРЕШКА: REPO_TOKEN не е зададен.", - "de": "FEHLER: REPO_TOKEN ist nicht gesetzt.", - "en": "ERROR: REPO_TOKEN is not set.", - "pl": "BŁĄD: REPO_TOKEN nie jest ustawiony.", - "ru": "ОШИБКА: REPO_TOKEN не задан.", - "zh": "错误:未设置 REPO_TOKEN。" + "ERROR: CI_GITEA_TOKEN is not set.": { + "bg": "ГРЕШКА: CI_GITEA_TOKEN не е зададен.", + "de": "FEHLER: CI_GITEA_TOKEN ist nicht gesetzt.", + "en": "ERROR: CI_GITEA_TOKEN is not set.", + "pl": "BŁĄD: CI_GITEA_TOKEN nie jest ustawiony.", + "ru": "ОШИБКА: CI_GITEA_TOKEN не задан.", + "zh": "错误:未设置 CI_GITEA_TOKEN。" }, "ERROR: Repository name not specified. Use --repo or set DEVX_REPO_NAME.": { "bg": "ГРЕШКА: Името на хранилището не е указано. Използвайте --repo или задайте DEVX_REPO_NAME.", @@ -759,13 +759,13 @@ "ru": "Found {count} stale documentation reference(s)", "zh": "Found {count} stale documentation reference(s)" }, - "GITEA_URL/REPO_TOKEN/RUN_ID not set; running without cross-runner cancellation.": { - "bg": "GITEA_URL/REPO_TOKEN/RUN_ID not set; running without cross-runner cancellation.", - "de": "GITEA_URL/REPO_TOKEN/RUN_ID not set; running without cross-runner cancellation.", - "en": "GITEA_URL/REPO_TOKEN/RUN_ID not set; running without cross-runner cancellation.", - "pl": "GITEA_URL/REPO_TOKEN/RUN_ID nie ustawione; uruchamianie bez anulowania między runnerami.", - "ru": "GITEA_URL/REPO_TOKEN/RUN_ID not set; running without cross-runner cancellation.", - "zh": "GITEA_URL/REPO_TOKEN/RUN_ID not set; running without cross-runner cancellation." + "GITEA_URL/CI_GITEA_TOKEN/RUN_ID not set; running without cross-runner cancellation.": { + "bg": "GITEA_URL/CI_GITEA_TOKEN/RUN_ID not set; running without cross-runner cancellation.", + "de": "GITEA_URL/CI_GITEA_TOKEN/RUN_ID not set; running without cross-runner cancellation.", + "en": "GITEA_URL/CI_GITEA_TOKEN/RUN_ID not set; running without cross-runner cancellation.", + "pl": "GITEA_URL/CI_GITEA_TOKEN/RUN_ID nie ustawione; uruchamianie bez anulowania między runnerami.", + "ru": "GITEA_URL/CI_GITEA_TOKEN/RUN_ID not set; running without cross-runner cancellation.", + "zh": "GITEA_URL/CI_GITEA_TOKEN/RUN_ID not set; running without cross-runner cancellation." }, "Generated {file} with prefix '{prefix}'.": { "bg": "Generated {file} with prefix '{prefix}'.", @@ -1383,29 +1383,29 @@ "ru": "REPO argument is required (or set GITHUB_REPOSITORY env var).", "zh": "REPO argument is required (or set GITHUB_REPOSITORY env var)." }, - "REPO_TOKEN environment variable required": { - "bg": "REPO_TOKEN environment variable required", - "de": "REPO_TOKEN environment variable required", - "en": "REPO_TOKEN environment variable required", - "pl": "REPO_TOKEN environment variable required", - "ru": "REPO_TOKEN environment variable required", - "zh": "REPO_TOKEN environment variable required" + "CI_GITEA_TOKEN environment variable required": { + "bg": "CI_GITEA_TOKEN environment variable required", + "de": "CI_GITEA_TOKEN environment variable required", + "en": "CI_GITEA_TOKEN environment variable required", + "pl": "CI_GITEA_TOKEN environment variable required", + "ru": "CI_GITEA_TOKEN environment variable required", + "zh": "CI_GITEA_TOKEN environment variable required" }, - "REPO_TOKEN is not set. Required to create a PR.": { - "bg": "REPO_TOKEN не е зададен. Необходим за създаване на PR.", - "de": "REPO_TOKEN nicht gesetzt. Erforderlich zum Erstellen eines PR.", - "en": "REPO_TOKEN is not set. Required to create a PR.", - "pl": "REPO_TOKEN nie jest ustawiony. Wymagany do utworzenia PR.", - "ru": "REPO_TOKEN не установлен. Требуется для создания PR.", - "zh": "REPO_TOKEN 未设置。创建 PR 所需。" + "CI_GITEA_TOKEN is not set. Required to create a PR.": { + "bg": "CI_GITEA_TOKEN не е зададен. Необходим за създаване на PR.", + "de": "CI_GITEA_TOKEN nicht gesetzt. Erforderlich zum Erstellen eines PR.", + "en": "CI_GITEA_TOKEN is not set. Required to create a PR.", + "pl": "CI_GITEA_TOKEN nie jest ustawiony. Wymagany do utworzenia PR.", + "ru": "CI_GITEA_TOKEN не установлен. Требуется для создания PR.", + "zh": "CI_GITEA_TOKEN 未设置。创建 PR 所需。" }, - "Registry credentials required: set REPO_TOKEN and REGISTRY_USERNAME env vars": { - "bg": "Registry credentials required: set REPO_TOKEN and REGISTRY_USERNAME env vars", - "de": "Registry credentials required: set REPO_TOKEN and REGISTRY_USERNAME env vars", - "en": "Registry credentials required: set REPO_TOKEN and REGISTRY_USERNAME env vars", - "pl": "Registry credentials required: set REPO_TOKEN and REGISTRY_USERNAME env vars", - "ru": "Registry credentials required: set REPO_TOKEN and REGISTRY_USERNAME env vars", - "zh": "Registry credentials required: set REPO_TOKEN and REGISTRY_USERNAME env vars" + "Registry credentials required: set CI_GITEA_TOKEN and CI_GITEA_USERNAME env vars": { + "bg": "Registry credentials required: set CI_GITEA_TOKEN and CI_GITEA_USERNAME env vars", + "de": "Registry credentials required: set CI_GITEA_TOKEN and CI_GITEA_USERNAME env vars", + "en": "Registry credentials required: set CI_GITEA_TOKEN and CI_GITEA_USERNAME env vars", + "pl": "Registry credentials required: set CI_GITEA_TOKEN and CI_GITEA_USERNAME env vars", + "ru": "Registry credentials required: set CI_GITEA_TOKEN and CI_GITEA_USERNAME env vars", + "zh": "Registry credentials required: set CI_GITEA_TOKEN and CI_GITEA_USERNAME env vars" }, "Registry login failed": { "bg": "Registry login failed", @@ -2007,13 +2007,13 @@ "ru": "tea not installed — skipping login configuration.", "zh": "tea not installed — skipping login configuration." }, - "REPO_TOKEN not set — skipping login configuration.": { - "bg": "REPO_TOKEN not set — skipping login configuration.", - "de": "REPO_TOKEN not set — skipping login configuration.", - "en": "REPO_TOKEN not set — skipping login configuration.", - "pl": "REPO_TOKEN not set — skipping login configuration.", - "ru": "REPO_TOKEN not set — skipping login configuration.", - "zh": "REPO_TOKEN not set — skipping login configuration." + "CI_GITEA_TOKEN not set — skipping login configuration.": { + "bg": "CI_GITEA_TOKEN not set — skipping login configuration.", + "de": "CI_GITEA_TOKEN not set — skipping login configuration.", + "en": "CI_GITEA_TOKEN not set — skipping login configuration.", + "pl": "CI_GITEA_TOKEN not set — skipping login configuration.", + "ru": "CI_GITEA_TOKEN not set — skipping login configuration.", + "zh": "CI_GITEA_TOKEN not set — skipping login configuration." }, "tea login '{name}' already configured.": { "bg": "tea login '{name}' already configured.", diff --git a/tests/unit/test_auto_merge.py b/tests/unit/test_auto_merge.py index e129b83..6451e44 100644 --- a/tests/unit/test_auto_merge.py +++ b/tests/unit/test_auto_merge.py @@ -217,7 +217,7 @@ class TestRunCmd: class TestMain: - @patch.dict("os.environ", {"REPO_TOKEN": "tok", "VIKUNJA_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok", "VIKUNJA_TOKEN": "tok"}, clear=True) @patch("devx.ci.auto_merge.validate_pr_title_matches_vikunja") @patch("devx.ci.auto_merge.GiteaClient") def test_full_merge_flow( @@ -239,14 +239,14 @@ class TestMain: assert result.exit_code == 0, result.output mock_client.merge_pr.assert_called_once_with(7, "DEVX-19: fix: resolve timeout") - @patch.dict("os.environ", {"REPO_TOKEN": ""}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": ""}, clear=True) def test_no_token_raises(self) -> None: runner = CliRunner() result = runner.invoke(main, ["DEVX-19-fix", "DEVX-19: test", "owner/repo", "7"]) assert result.exit_code != 0 - assert "REPO_TOKEN" in result.output + assert "CI_GITEA_TOKEN" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.ci.auto_merge.GiteaClient") def test_no_task_id_raises(self, mock_client_cls: MagicMock, tmp_path, monkeypatch) -> None: # type: ignore[no-untyped-def] monkeypatch.chdir(tmp_path) @@ -256,7 +256,7 @@ class TestMain: assert result.exit_code != 0 assert "No task ID" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.ci.auto_merge.GiteaClient") def test_invalid_pr_title_raises(self, mock_client_cls: MagicMock, tmp_path, monkeypatch) -> None: # type: ignore[no-untyped-def] monkeypatch.chdir(tmp_path) @@ -266,7 +266,7 @@ class TestMain: assert result.exit_code != 0 assert "format" in result.output.lower() - @patch.dict("os.environ", {"REPO_TOKEN": "tok", "VIKUNJA_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok", "VIKUNJA_TOKEN": "tok"}, clear=True) @patch("devx.ci.auto_merge.validate_pr_title_matches_vikunja") @patch("devx.ci.auto_merge.GiteaClient") def test_merge_behind_master_raises_no_rebase( @@ -298,7 +298,7 @@ class TestMain: # Must NOT have called merge_pr twice (no retry after rebase) assert mock_client.merge_pr.call_count == 1 - @patch.dict("os.environ", {"REPO_TOKEN": "tok", "VIKUNJA_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok", "VIKUNJA_TOKEN": "tok"}, clear=True) @patch("devx.ci.auto_merge.validate_pr_title_matches_vikunja") @patch("devx.ci.auto_merge.GiteaClient") def test_merge_failure_raises( @@ -321,7 +321,7 @@ class TestMain: assert result.exit_code != 0 assert "Merge failed" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok", "VIKUNJA_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok", "VIKUNJA_TOKEN": "tok"}, clear=True) @patch("devx.ci.auto_merge.validate_pr_title_matches_vikunja") @patch("devx.ci.auto_merge.GiteaClient") def test_no_conventional_msg_raises( @@ -342,7 +342,7 @@ class TestMain: assert result.exit_code != 0 assert "conventional commit" in result.output.lower() - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) def test_invalid_pr_number_raises(self, tmp_path, monkeypatch) -> None: """Non-integer PR number should raise.""" monkeypatch.chdir(tmp_path) @@ -351,7 +351,7 @@ class TestMain: assert result.exit_code != 0 assert "PR number must be an integer" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) def test_invalid_repo_format_raises(self, tmp_path, monkeypatch) -> None: """Repo without owner/name should raise.""" monkeypatch.chdir(tmp_path) @@ -360,7 +360,7 @@ class TestMain: assert result.exit_code != 0 assert "owner/name" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok", "VIKUNJA_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok", "VIKUNJA_TOKEN": "tok"}, clear=True) @patch("devx.ci.auto_merge.validate_pr_title_matches_vikunja") @patch("devx.ci.auto_merge.GiteaClient") def test_merge_behind_master_does_not_force_push( diff --git a/tests/unit/test_build_image.py b/tests/unit/test_build_image.py index 624b9ec..c948135 100644 --- a/tests/unit/test_build_image.py +++ b/tests/unit/test_build_image.py @@ -442,7 +442,7 @@ class TestCLIBuildImage: dockerfile.touch() runner = CliRunner() login_result = MagicMock(returncode=1, stderr="auth failed", stdout="") - with patch.dict("os.environ", {"REPO_TOKEN": "fake", "REGISTRY_USERNAME": "user"}): + with patch.dict("os.environ", {"CI_GITEA_TOKEN": "fake", "CI_GITEA_USERNAME": "user"}): with patch("devx.tools.build_image.subprocess.run", return_value=login_result): result = runner.invoke( build_image.main, @@ -458,7 +458,7 @@ class TestCLIBuildImage: build_result = MagicMock(returncode=0) login_result = MagicMock(returncode=0, stderr="", stdout="") push_result = MagicMock(returncode=1, stderr="push failed", stdout="") - with patch.dict("os.environ", {"REPO_TOKEN": "fake", "REGISTRY_USERNAME": "user"}): + with patch.dict("os.environ", {"CI_GITEA_TOKEN": "fake", "CI_GITEA_USERNAME": "user"}): with patch( "devx.tools.build_image.subprocess.run", side_effect=[login_result, build_result, push_result], @@ -482,7 +482,7 @@ class TestCLICleanImages: {"version": "0.3.0", "created_at": "2025-03-01"}, ] mock_resp.raise_for_status = MagicMock() - with patch.dict("os.environ", {"REPO_TOKEN": "fake"}): + with patch.dict("os.environ", {"CI_GITEA_TOKEN": "fake"}): with patch("devx.tools.clean_images.requests.get", return_value=mock_resp): result = runner.invoke( clean_main, @@ -511,7 +511,7 @@ class TestCLICleanImages: mock_resp = MagicMock() mock_resp.json.return_value = [] mock_resp.raise_for_status = MagicMock() - with patch.dict("os.environ", {"REPO_TOKEN": "fake"}): + with patch.dict("os.environ", {"CI_GITEA_TOKEN": "fake"}): with patch("devx.tools.clean_images.requests.get", return_value=mock_resp): result = runner.invoke( clean_main, @@ -532,7 +532,7 @@ class TestCLICleanImages: ] list_resp.raise_for_status = MagicMock() delete_resp = MagicMock(status_code=204) - with patch.dict("os.environ", {"REPO_TOKEN": "fake"}): + with patch.dict("os.environ", {"CI_GITEA_TOKEN": "fake"}): with patch("devx.tools.clean_images.requests.get", return_value=list_resp): with patch("devx.tools.clean_images.requests.delete", return_value=delete_resp): result = runner.invoke( @@ -548,7 +548,7 @@ class TestCLICleanImages: from devx.tools.clean_images import main as clean_main runner = CliRunner() - with patch.dict("os.environ", {"REPO_TOKEN": "fake"}): + with patch.dict("os.environ", {"CI_GITEA_TOKEN": "fake"}): with patch( "devx.tools.clean_images.requests.get", side_effect=req.ConnectionError("network down"), @@ -572,7 +572,7 @@ class TestCLICleanImages: ] list_resp.raise_for_status = MagicMock() delete_resp = MagicMock(status_code=500) - with patch.dict("os.environ", {"REPO_TOKEN": "fake"}): + with patch.dict("os.environ", {"CI_GITEA_TOKEN": "fake"}): with patch("devx.tools.clean_images.requests.get", return_value=list_resp): with patch("devx.tools.clean_images.requests.delete", return_value=delete_resp): result = runner.invoke( diff --git a/tests/unit/test_check_auto_merge_ready.py b/tests/unit/test_check_auto_merge_ready.py index 9b10936..ecc9244 100644 --- a/tests/unit/test_check_auto_merge_ready.py +++ b/tests/unit/test_check_auto_merge_ready.py @@ -78,7 +78,7 @@ class TestGetPrTitleFromGitea: assert get_pr_title_from_gitea("owner/repo", 1) is None def test_returns_none_with_invalid_repo(self) -> None: - with patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True): + with patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True): assert get_pr_title_from_gitea("invalid", 1) is None @patch("devx.ci.check_auto_merge_ready.GiteaClient") @@ -86,7 +86,7 @@ class TestGetPrTitleFromGitea: mock_client = MagicMock() mock_client.get_pr.return_value = {"title": "DEVX-1: Fix bug"} mock_client_cls.return_value = mock_client - with patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True): + with patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True): result = get_pr_title_from_gitea("owner/repo", 1) assert result == "DEVX-1: Fix bug" @@ -95,7 +95,7 @@ class TestGetPrTitleFromGitea: mock_client = MagicMock() mock_client.get_pr.side_effect = Exception("API error") mock_client_cls.return_value = mock_client - with patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True): + with patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True): result = get_pr_title_from_gitea("owner/repo", 1) assert result is None diff --git a/tests/unit/test_check_translations.py b/tests/unit/test_check_translations.py index fe67ae6..009d4fc 100644 --- a/tests/unit/test_check_translations.py +++ b/tests/unit/test_check_translations.py @@ -248,8 +248,8 @@ class TestDevxI18n: import devx.i18n importlib.reload(devx.i18n) - # "ERROR: REPO_TOKEN is not set." has a German translation - result = devx.i18n._("ERROR: REPO_TOKEN is not set.") + # "ERROR: CI_GITEA_TOKEN is not set." has a German translation + result = devx.i18n._("ERROR: CI_GITEA_TOKEN is not set.") assert "FEHLER" in result # Restore diff --git a/tests/unit/test_configure_repo.py b/tests/unit/test_configure_repo.py index ebd3863..24d8e50 100644 --- a/tests/unit/test_configure_repo.py +++ b/tests/unit/test_configure_repo.py @@ -47,7 +47,7 @@ class TestDefaultConfigs: class TestConfigureRepo: - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.tools.configure_repo.GiteaClient") def test_configure_repo_success(self, mock_client_cls: MagicMock) -> None: mock_client = MagicMock() @@ -58,7 +58,7 @@ class TestConfigureRepo: mock_client.ensure_branch_protection.assert_called_once() mock_client.update_repo_settings.assert_called_once() - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.tools.configure_repo.GiteaClient") def test_configure_repo_api_error(self, mock_client_cls: MagicMock) -> None: mock_client = MagicMock() @@ -69,10 +69,10 @@ class TestConfigureRepo: configure_repo(token="tok", owner="owner", repo="repo") def test_configure_repo_no_token(self) -> None: - with pytest.raises(click.ClickException, match="REPO_TOKEN"): + with pytest.raises(click.ClickException, match="CI_GITEA_TOKEN"): configure_repo(token="", owner="owner", repo="repo") - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.tools.configure_repo.GiteaClient") def test_configure_repo_custom_configs(self, mock_client_cls: MagicMock) -> None: mock_client = MagicMock() @@ -102,7 +102,7 @@ class TestConfigureRepo: class TestMain: - @patch.dict("os.environ", {"REPO_TOKEN": "tok", "DEVX_REPO_NAME": "myrepo"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok", "DEVX_REPO_NAME": "myrepo"}, clear=True) @patch("devx.tools.configure_repo.GiteaClient") def test_main_success_with_env_repo(self, mock_client_cls: MagicMock) -> None: mock_client = MagicMock() @@ -114,7 +114,7 @@ class TestMain: mock_client.ensure_branch_protection.assert_called_once() mock_client.update_repo_settings.assert_called_once() - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.tools.configure_repo.GiteaClient") def test_main_success_with_cli_repo(self, mock_client_cls: MagicMock) -> None: mock_client = MagicMock() @@ -125,7 +125,7 @@ class TestMain: assert result.exit_code == 0 mock_client.ensure_branch_protection.assert_called_once() - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.tools.configure_repo.GiteaClient") def test_main_api_error(self, mock_client_cls: MagicMock) -> None: mock_client = MagicMock() @@ -142,16 +142,16 @@ class TestMain: runner = CliRunner() result = runner.invoke(main, ["--repo", "myrepo"]) assert result.exit_code != 0 - assert "REPO_TOKEN" in result.output + assert "CI_GITEA_TOKEN" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) def test_main_no_repo(self) -> None: runner = CliRunner() result = runner.invoke(main, []) assert result.exit_code != 0 assert "Repository name not specified" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.tools.configure_repo.GiteaClient") def test_main_custom_branch(self, mock_client_cls: MagicMock) -> None: mock_client = MagicMock() @@ -164,7 +164,7 @@ class TestMain: args = mock_client.ensure_branch_protection.call_args assert args[0][0] == "develop" - @patch.dict("os.environ", {"REPO_TOKEN": "tok", "DEVX_REPO_NAME": "oblachno/infra"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok", "DEVX_REPO_NAME": "oblachno/infra"}, clear=True) @patch("devx.tools.configure_repo.GiteaClient") def test_main_parses_owner_repo_from_env(self, mock_client_cls: MagicMock) -> None: """DEVX_REPO_NAME with 'owner/repo' format should be split.""" @@ -181,7 +181,7 @@ class TestMain: @patch.dict( "os.environ", - {"REPO_TOKEN": "tok", "DEVX_REPO_NAME": "infra", "DEVX_REPO_OWNER": "oblachno"}, + {"CI_GITEA_TOKEN": "tok", "DEVX_REPO_NAME": "infra", "DEVX_REPO_OWNER": "oblachno"}, clear=True, ) @patch("devx.tools.configure_repo.REPO_OWNER", "oblachno") diff --git a/tests/unit/test_create_pr.py b/tests/unit/test_create_pr.py index e5dd5b2..a6f0f56 100644 --- a/tests/unit/test_create_pr.py +++ b/tests/unit/test_create_pr.py @@ -95,7 +95,7 @@ class TestCreatePr: @patch("devx.tools.create_pr.GiteaClient") @patch("devx.tools.create_pr.get_vikunja_task_title", return_value="Add feature") @patch("devx.tools.create_pr.find_existing_pr", return_value=None) - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) def test_creates_new_pr(self, mock_find: MagicMock, mock_title: MagicMock, mock_gitea: MagicMock) -> None: mock_client = MagicMock() mock_client.create_pr.return_value = {"number": 15, "html_url": "https://git.example.com/pr/15"} @@ -112,7 +112,7 @@ class TestCreatePr: @patch("devx.tools.create_pr.GiteaClient") @patch("devx.tools.create_pr.get_vikunja_task_title", return_value="Add feature") @patch("devx.tools.create_pr.find_existing_pr") - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) def test_existing_pr_idempotent(self, mock_find: MagicMock, mock_title: MagicMock, mock_gitea: MagicMock) -> None: mock_find.return_value = {"number": 10, "html_url": "https://git.example.com/pr/10"} mock_client = MagicMock() @@ -123,10 +123,10 @@ class TestCreatePr: @patch.dict("os.environ", {}, clear=True) def test_no_repo_token(self) -> None: - with pytest.raises(click.ClickException, match="REPO_TOKEN"): + with pytest.raises(click.ClickException, match="CI_GITEA_TOKEN"): create_pr("DEVX-42-fix", "master", "", "owner", "repo") - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) def test_no_task_id_in_branch(self) -> None: with pytest.raises(click.ClickException, match="does not contain a task ID"): create_pr("feature-branch", "master", "", "owner", "repo") diff --git a/tests/unit/test_gitea_cli.py b/tests/unit/test_gitea_cli.py index 802dee6..8bc87ea 100644 --- a/tests/unit/test_gitea_cli.py +++ b/tests/unit/test_gitea_cli.py @@ -362,19 +362,19 @@ class TestWhoami: class TestConfigureTeaLogin: - @patch.dict("os.environ", {"REPO_TOKEN": ""}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": ""}, clear=True) @patch("devx.gitea_cli.shutil.which", return_value="/usr/bin/tea") def test_no_token_skips(self, mock_which: MagicMock) -> None: """configure_tea_login with no token prints skip message and returns.""" configure_tea_login() - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.gitea_cli.shutil.which", return_value=None) def test_no_tea_skips(self, mock_which: MagicMock) -> None: """configure_tea_login with no tea binary prints skip message and returns.""" configure_tea_login() - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.gitea_cli.shutil.which", return_value="/usr/bin/tea") @patch("devx.gitea_cli.subprocess.run") def test_configures_login_when_not_present(self, mock_subprocess: MagicMock, mock_which: MagicMock) -> None: @@ -384,7 +384,7 @@ class TestConfigureTeaLogin: configure_tea_login() assert mock_subprocess.call_count >= 2 # login list + login add + login default - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.gitea_cli.shutil.which", return_value="/usr/bin/tea") @patch("devx.gitea_cli.subprocess.run") def test_skips_when_already_configured(self, mock_subprocess: MagicMock, mock_which: MagicMock) -> None: diff --git a/tests/unit/test_integration_guard.py b/tests/unit/test_integration_guard.py index 584749a..2448379 100644 --- a/tests/unit/test_integration_guard.py +++ b/tests/unit/test_integration_guard.py @@ -101,7 +101,7 @@ class TestCli: os.environ, { "GITEA_URL": "https://gitea.example", - "REPO_TOKEN": "token", + "CI_GITEA_TOKEN": "token", "RUN_ID": "123", "JOB_NAME": "integration-tests", "MATRIX_INDEX": "0", @@ -148,7 +148,7 @@ class TestCli: os.environ, { "GITEA_URL": "https://gitea.example", - "REPO_TOKEN": "token", + "CI_GITEA_TOKEN": "token", "RUN_ID": "123", "JOB_NAME": "integration-tests", "MATRIX_INDEX": "0", @@ -193,7 +193,7 @@ class TestCli: os.environ, { "GITEA_URL": "https://gitea.example", - "REPO_TOKEN": "token", + "CI_GITEA_TOKEN": "token", "RUN_ID": "123", "JOB_NAME": "integration-tests", "MATRIX_INDEX": "0", @@ -239,7 +239,7 @@ class TestCli: assert "without cross-runner cancellation" in result.output def test_partial_env_vars_runs_without_polling(self) -> None: - """Only GITEA_URL set (missing REPO_TOKEN and RUN_ID) — should skip polling.""" + """Only GITEA_URL set (missing CI_GITEA_TOKEN and RUN_ID) — should skip polling.""" with ( patch.dict( os.environ, diff --git a/tests/unit/test_molecule_ci_guard.py b/tests/unit/test_molecule_ci_guard.py index 299be3c..b2ad6dc 100644 --- a/tests/unit/test_molecule_ci_guard.py +++ b/tests/unit/test_molecule_ci_guard.py @@ -220,7 +220,7 @@ class TestCli: os.environ, { "GITEA_URL": "https://gitea.example", - "REPO_TOKEN": "token", + "CI_GITEA_TOKEN": "token", "RUN_ID": "123", "JOB_NAME": "molecule-tests", "MATRIX_INDEX": "0", @@ -288,7 +288,7 @@ class TestCli: os.environ, { "GITEA_URL": "https://gitea.example", - "REPO_TOKEN": "token", + "CI_GITEA_TOKEN": "token", "RUN_ID": "123", "JOB_NAME": "molecule-tests", "MATRIX_INDEX": "0", @@ -325,7 +325,7 @@ class TestCli: os.environ, { "GITEA_URL": "https://gitea.example", - "REPO_TOKEN": "token", + "CI_GITEA_TOKEN": "token", "RUN_ID": "123", "JOB_NAME": "molecule-tests", "MATRIX_INDEX": "0", @@ -371,7 +371,7 @@ class TestCli: os.environ, { "GITEA_URL": "https://gitea.example", - "REPO_TOKEN": "token", + "CI_GITEA_TOKEN": "token", "RUN_ID": "123", "JOB_NAME": "molecule-tests", "MATRIX_INDEX": "0", @@ -418,7 +418,7 @@ class TestCli: os.environ, { "GITEA_URL": "https://gitea.example", - "REPO_TOKEN": "token", + "CI_GITEA_TOKEN": "token", "RUN_ID": "123", "JOB_NAME": "molecule-tests", "MATRIX_INDEX": "0", diff --git a/tests/unit/test_notify_failure.py b/tests/unit/test_notify_failure.py index c59f71e..39d1361 100644 --- a/tests/unit/test_notify_failure.py +++ b/tests/unit/test_notify_failure.py @@ -9,7 +9,7 @@ from devx.gitea_cli import TeaCLIError, configure_tea_login class TestNotifyFailure: - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.ci.notify_failure.TeaCLI") def test_creates_issue_with_tea(self, mock_tea_cls: MagicMock) -> None: mock_tea = MagicMock() @@ -36,7 +36,7 @@ class TestNotifyFailure: mock_tea.create_issue.assert_called_once() mock_tea.add_label.assert_called_once_with("owner/repo", 42, ["bug"]) - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.ci.notify_failure.TeaCLI") def test_tea_creates_issue_without_bug_label(self, mock_tea_cls: MagicMock) -> None: mock_tea = MagicMock() @@ -53,7 +53,7 @@ class TestNotifyFailure: assert "issue #43" in result.output mock_tea.add_label.assert_not_called() - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.ci.notify_failure.TeaCLI") def test_tea_error_raises(self, mock_tea_cls: MagicMock) -> None: """When tea fails, the workflow fails — no fallback.""" @@ -70,7 +70,7 @@ class TestNotifyFailure: assert result.exit_code != 0 assert "tea" in result.output.lower() - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.ci.notify_failure.TeaCLI") def test_tea_list_labels_error_continues_without_labels(self, mock_tea_cls: MagicMock) -> None: """If listing labels fails via tea, issue is still created without labels.""" @@ -87,7 +87,7 @@ class TestNotifyFailure: assert result.exit_code == 0 assert "issue #50" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.ci.notify_failure.TeaCLI") def test_tea_add_label_error_is_ignored(self, mock_tea_cls: MagicMock) -> None: """If adding label fails via tea, issue is still reported as created.""" @@ -105,7 +105,7 @@ class TestNotifyFailure: assert result.exit_code == 0 assert "issue #51" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": ""}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": ""}, clear=True) def test_missing_token_exits(self) -> None: runner = CliRunner() result = runner.invoke( @@ -113,9 +113,9 @@ class TestNotifyFailure: ["--repo", "owner/repo", "--run-id", "1", "--workflow", "release", "--commit", "abc"], ) assert result.exit_code != 0 - assert "REPO_TOKEN" in result.output + assert "CI_GITEA_TOKEN" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.gitea_cli.shutil.which", return_value=None) @patch("devx.ci.notify_failure.TeaCLI") def test_auto_login_no_tea_skips(self, mock_tea_cls: MagicMock, mock_which: MagicMock) -> None: @@ -133,11 +133,11 @@ class TestNotifyFailure: assert result.exit_code == 0 assert "issue #60" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": ""}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": ""}, clear=True) @patch("devx.gitea_cli.shutil.which", return_value="/usr/bin/tea") @patch("devx.ci.notify_failure.TeaCLI") def test_auto_login_no_token_skips_login(self, mock_tea_cls: MagicMock, mock_which: MagicMock) -> None: - """--auto-login with no REPO_TOKEN skips login but raises before creating issue.""" + """--auto-login with no CI_GITEA_TOKEN skips login but raises before creating issue.""" mock_tea = MagicMock() mock_tea_cls.return_value = mock_tea @@ -147,23 +147,23 @@ class TestNotifyFailure: ["--repo", "owner/repo", "--run-id", "1", "--workflow", "release", "--commit", "abc", "--auto-login"], ) assert result.exit_code != 0 - assert "REPO_TOKEN" in result.output + assert "CI_GITEA_TOKEN" in result.output class TestConfigureTeaLogin: - @patch.dict("os.environ", {"REPO_TOKEN": ""}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": ""}, clear=True) @patch("devx.gitea_cli.shutil.which", return_value="/usr/bin/tea") def test_no_token_skips(self, mock_which: MagicMock) -> None: """configure_tea_login with no token prints skip message and returns.""" configure_tea_login() - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.gitea_cli.shutil.which", return_value=None) def test_no_tea_skips(self, mock_which: MagicMock) -> None: """configure_tea_login with no tea binary prints skip message and returns.""" configure_tea_login() - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.gitea_cli.shutil.which", return_value="/usr/bin/tea") @patch("devx.gitea_cli.subprocess.run") @patch("devx.ci.notify_failure.TeaCLI") @@ -191,7 +191,7 @@ class TestConfigureTeaLogin: # tea login add was called assert mock_subprocess.call_count >= 2 - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.gitea_cli.shutil.which", return_value="/usr/bin/tea") @patch("devx.gitea_cli.subprocess.run") @patch("devx.ci.notify_failure.TeaCLI") diff --git a/tests/unit/test_pr_review.py b/tests/unit/test_pr_review.py index 257b16e..d25fbc7 100644 --- a/tests/unit/test_pr_review.py +++ b/tests/unit/test_pr_review.py @@ -683,7 +683,7 @@ class TestMain: def test_dry_run_does_not_post(self, mock_client_class: MagicMock, mock_run: MagicMock) -> None: mock_run.return_value = ReviewResult() runner = CliRunner() - result = runner.invoke(main, ["42", "oblachno-oss/grm", "--dry-run"], env={"REPO_TOKEN": "fake"}) + result = runner.invoke(main, ["42", "oblachno-oss/grm", "--dry-run"], env={"CI_GITEA_TOKEN": "fake"}) assert result.exit_code == 0 assert "[dry-run]" in result.output mock_client_class.return_value.create_review.assert_not_called() @@ -694,7 +694,7 @@ class TestMain: mock_run.return_value = ReviewResult() mock_client_class.return_value.create_review.return_value = {"id": 123} runner = CliRunner() - result = runner.invoke(main, ["42", "oblachno-oss/grm"], env={"REPO_TOKEN": "fake"}) + result = runner.invoke(main, ["42", "oblachno-oss/grm"], env={"CI_GITEA_TOKEN": "fake"}) assert result.exit_code == 0 assert "Review #123" in result.output mock_client_class.return_value.create_review.assert_called_once() @@ -710,7 +710,7 @@ class TestMain: {"id": 124}, ] runner = CliRunner() - result = runner.invoke(main, ["42", "oblachno-oss/grm"], env={"REPO_TOKEN": "fake"}) + result = runner.invoke(main, ["42", "oblachno-oss/grm"], env={"CI_GITEA_TOKEN": "fake"}) assert result.exit_code == 0 assert "Review #124" in result.output assert client.create_review.call_count == 2 @@ -723,14 +723,14 @@ class TestMain: client = mock_client_class.return_value client.create_review.side_effect = APIError(500, "Internal server error") runner = CliRunner() - result = runner.invoke(main, ["42", "oblachno-oss/grm"], env={"REPO_TOKEN": "fake"}) + result = runner.invoke(main, ["42", "oblachno-oss/grm"], env={"CI_GITEA_TOKEN": "fake"}) assert result.exit_code != 0 def test_no_token_raises(self) -> None: runner = CliRunner() - result = runner.invoke(main, ["42", "oblachno-oss/grm"], env={"REPO_TOKEN": ""}) + result = runner.invoke(main, ["42", "oblachno-oss/grm"], env={"CI_GITEA_TOKEN": ""}) assert result.exit_code != 0 - assert "REPO_TOKEN" in result.output + assert "CI_GITEA_TOKEN" in result.output def test_main_module_block() -> None: diff --git a/tests/unit/test_publish.py b/tests/unit/test_publish.py index 2d1068d..028a838 100644 --- a/tests/unit/test_publish.py +++ b/tests/unit/test_publish.py @@ -165,7 +165,7 @@ class TestDefaultGiteaRegistryUrl: class TestMain: - @patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"}) @patch("devx.ci.publish.generate_release_notes", return_value="Release notes") @patch("devx.ci.publish.TeaCLI") @patch("devx.ci.publish.publish_to_pypi") @@ -190,7 +190,7 @@ class TestMain: "owner/repo", tag="v1.0.0", title="v1.0.0", body="Release notes" ) - @patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "gitea-tok"}, clear=True) @patch("devx.ci.publish.generate_release_notes", return_value="Release notes") @patch("devx.ci.publish.TeaCLI") @patch("devx.ci.publish.publish_to_gitea_registry") @@ -213,7 +213,7 @@ class TestMain: mock_gitea_publish.assert_called_once() mock_tea.create_release.assert_called_once() - @patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "gitea-tok"}, clear=True) @patch("devx.ci.publish.generate_release_notes", return_value="Release notes") @patch("devx.ci.publish.TeaCLI") @patch("devx.ci.publish.publish_to_gitea_registry") @@ -239,7 +239,7 @@ class TestMain: @patch.dict( "os.environ", - {"REPO_TOKEN": "gitea-tok", "DEVX_PYPI_REGISTRY_URL": "https://env.registry.com/pypi"}, + {"CI_GITEA_TOKEN": "gitea-tok", "DEVX_PYPI_REGISTRY_URL": "https://env.registry.com/pypi"}, clear=True, ) @patch("devx.ci.publish.generate_release_notes", return_value="Release notes") @@ -262,7 +262,7 @@ class TestMain: assert result.exit_code == 0 mock_gitea_publish.assert_called_once_with("https://env.registry.com/pypi", "gitea-tok") - @patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "gitea-tok"}, clear=True) @patch("devx.ci.publish.generate_release_notes", return_value="Release notes") @patch("devx.ci.publish.TeaCLI") @patch("devx.ci.publish.build_package") @@ -284,14 +284,14 @@ class TestMain: assert "PYPI_TOKEN not set" in result.output mock_tea.create_release.assert_called_once() - @patch.dict("os.environ", {"REPO_TOKEN": ""}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": ""}, clear=True) def test_missing_repo_token_exits(self) -> None: runner = CliRunner() result = runner.invoke(main, ["v1.0.0", "owner/repo"]) assert result.exit_code == 1 - assert "REPO_TOKEN" in result.output + assert "CI_GITEA_TOKEN" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"}) @patch("devx.ci.publish.generate_release_notes", return_value="Release notes") @patch("devx.ci.publish.TeaCLI") @patch("devx.ci.publish.publish_to_pypi") @@ -305,7 +305,7 @@ class TestMain: assert result.exit_code == 1 assert "build" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"}) @patch("devx.ci.publish.generate_release_notes", return_value="Release notes") @patch("devx.ci.publish.TeaCLI") @patch("devx.ci.publish.publish_to_pypi") @@ -326,7 +326,7 @@ class TestMain: "owner/repo", tag="v1.0.0", title="v1.0.0", body="Release notes" ) - @patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"}) @patch("devx.ci.publish.generate_release_notes", return_value="Release notes") @patch("devx.ci.publish.TeaCLI") @patch("devx.ci.publish.publish_to_pypi") @@ -343,7 +343,7 @@ class TestMain: assert result.exit_code == 1 assert "Release creation failed" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "gitea-tok"}) @patch("devx.ci.publish.generate_release_notes", return_value="Release notes") @patch("devx.ci.publish.TeaCLI") @patch("devx.ci.publish.build_package") @@ -361,7 +361,7 @@ class TestMain: mock_build.assert_not_called() mock_tea.create_release.assert_called_once() - @patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"}) @patch("devx.ci.publish.generate_release_notes", return_value="Release notes") @patch("devx.ci.publish.TeaCLI") @patch("devx.ci.publish.publish_to_pypi") @@ -379,7 +379,7 @@ class TestMain: assert "already exists" in result.output mock_tea.create_release.assert_not_called() - @patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "gitea-tok", "PYPI_TOKEN": "pypi-tok"}) @patch("devx.ci.publish.generate_release_notes", return_value="Release notes") @patch("devx.ci.publish.TeaCLI") @patch("devx.ci.publish.publish_to_pypi") @@ -395,7 +395,7 @@ class TestMain: result = runner.invoke(main, ["v1.0.0", "owner/repo"]) assert result.exit_code == 0 - @patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "gitea-tok"}) @patch("devx.ci.publish.generate_release_notes", return_value="Release notes") @patch("devx.ci.publish.TeaCLI") @patch("devx.ci.publish.publish_to_gitea_registry") @@ -419,7 +419,7 @@ class TestMain: assert result.exit_code == 0 assert "already exists" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "gitea-tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "gitea-tok"}) @patch("devx.ci.publish.generate_release_notes", return_value="Release notes") @patch("devx.ci.publish.TeaCLI") @patch("devx.ci.publish.publish_to_gitea_registry") @@ -521,7 +521,7 @@ class TestFromTag: @patch("devx.ci.publish.is_release_commit", return_value=True) @patch("devx.ci.publish.get_latest_tag", return_value="v1.0.0") def test_from_tag_publishes(self, _mock_tag: MagicMock, _mock_rel: MagicMock) -> None: - with patch.dict("os.environ", {"REPO_TOKEN": "fake"}): + with patch.dict("os.environ", {"CI_GITEA_TOKEN": "fake"}): with patch("devx.ci.publish.TeaCLI") as mock_tea_cls: mock_tea = MagicMock() mock_tea.list_releases.return_value = [] @@ -535,7 +535,7 @@ class TestFromTag: @patch("devx.ci.publish.is_release_commit", return_value=True) @patch("devx.ci.publish.get_latest_tag", return_value="v1.0.0") def test_from_tag_publishes_no_repo_arg(self, _mock_tag: MagicMock, _mock_rel: MagicMock) -> None: - with patch.dict("os.environ", {"REPO_TOKEN": "fake", "GITHUB_REPOSITORY": "owner/repo"}): + with patch.dict("os.environ", {"CI_GITEA_TOKEN": "fake", "GITHUB_REPOSITORY": "owner/repo"}): with patch("devx.ci.publish.TeaCLI") as mock_tea_cls: mock_tea = MagicMock() mock_tea.list_releases.return_value = [] @@ -556,7 +556,7 @@ class TestFromTag: class TestPublishAutoLogin: """Tests for --auto-login flag in publish.""" - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.ci.publish.configure_tea_login") @patch("devx.ci.publish.TeaCLI") def test_auto_login_calls_configure(self, mock_tea_cls: MagicMock, mock_login: MagicMock) -> None: @@ -571,7 +571,7 @@ class TestPublishAutoLogin: assert result.exit_code == 0 mock_login.assert_called_once() - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.ci.publish.configure_tea_login") @patch("devx.ci.publish.TeaCLI") def test_no_auto_login_skips_configure(self, mock_tea_cls: MagicMock, mock_login: MagicMock) -> None: diff --git a/tests/unit/test_setup.py b/tests/unit/test_setup.py index 87df4cb..edb340a 100644 --- a/tests/unit/test_setup.py +++ b/tests/unit/test_setup.py @@ -120,7 +120,7 @@ class TestConfigureTeaLogin: @patch("devx.tools.setup.subprocess.run") @patch("devx.tools.setup.shutil.which", return_value="/usr/local/bin/tea") - @patch.dict("os.environ", {"REPO_TOKEN": "tok123"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok123"}, clear=True) def test_login_already_exists(self, mock_which: MagicMock, mock_run: MagicMock) -> None: mock_run.return_value = MagicMock(returncode=0, stdout="devx\ngrm\n", stderr="") _configure_tea_login() @@ -130,7 +130,7 @@ class TestConfigureTeaLogin: @patch("devx.tools.setup.subprocess.run") @patch("devx.tools.setup.shutil.which", return_value="/usr/local/bin/tea") - @patch.dict("os.environ", {"REPO_TOKEN": "tok123"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok123"}, clear=True) def test_login_add_success(self, mock_which: MagicMock, mock_run: MagicMock) -> None: list_result = MagicMock(returncode=0, stdout="", stderr="") add_result = MagicMock(returncode=0, stdout="", stderr="") @@ -143,7 +143,7 @@ class TestConfigureTeaLogin: @patch("devx.tools.setup.subprocess.run") @patch("devx.tools.setup.shutil.which", return_value="/usr/local/bin/tea") - @patch.dict("os.environ", {"REPO_TOKEN": "tok123"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok123"}, clear=True) def test_login_add_failure(self, mock_which: MagicMock, mock_run: MagicMock) -> None: list_result = MagicMock(returncode=0, stdout="", stderr="") add_result = MagicMock(returncode=1, stdout="", stderr="auth failed") @@ -155,7 +155,7 @@ class TestConfigureTeaLogin: @patch("devx.tools.setup.shutil.which", return_value="/usr/local/bin/tea") @patch.dict( "os.environ", - {"REPO_TOKEN": "tok123", "DEVX_GITEA_API_URL": "https://custom.example.com/api/v1"}, + {"CI_GITEA_TOKEN": "tok123", "DEVX_GITEA_API_URL": "https://custom.example.com/api/v1"}, clear=True, ) def test_custom_gitea_url(self, mock_which: MagicMock, mock_run: MagicMock) -> None: diff --git a/tests/unit/test_sync_wiki.py b/tests/unit/test_sync_wiki.py index 3e21328..6fbb00b 100644 --- a/tests/unit/test_sync_wiki.py +++ b/tests/unit/test_sync_wiki.py @@ -286,7 +286,7 @@ class TestVerifyWikiIntegrity: class TestMain: - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}) @patch("devx.ci.sync_wiki.MAPPING_FILE") @patch("devx.ci.sync_wiki.DOCS_DIR") @patch("devx.ci.sync_wiki.GiteaClient") @@ -301,14 +301,16 @@ class TestMain: assert result.exit_code == 0 assert "dry-run" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": ""}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": ""}, clear=True) def test_missing_token_exits(self) -> None: runner = CliRunner() result = runner.invoke(main, ["--repo", "owner/repo"]) assert result.exit_code == 1 - assert "REPO_TOKEN" in result.output + assert "CI_GITEA_TOKEN" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok", "DEVX_REPO_OWNER": "me", "DEVX_REPO_NAME": "myrepo"}, clear=True) + @patch.dict( + "os.environ", {"CI_GITEA_TOKEN": "tok", "DEVX_REPO_OWNER": "me", "DEVX_REPO_NAME": "myrepo"}, clear=True + ) @patch("devx.ci.sync_wiki.GiteaClient") def test_auto_detect_repo(self, mock_client_cls: MagicMock) -> None: """Test that repo is auto-detected from env vars when --repo is not passed.""" @@ -322,7 +324,7 @@ class TestMain: assert result.exit_code == 0 mock_client_cls.assert_called_once() - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.ci.sync_wiki.GiteaClient") def test_missing_mapping_file(self, mock_client_cls: MagicMock) -> None: """Test that missing mapping.json exits with error.""" @@ -333,7 +335,7 @@ class TestMain: assert result.exit_code == 1 assert "mapping.json" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.ci.sync_wiki.GiteaClient") def test_existing_pages_message(self, mock_client_cls: MagicMock) -> None: """Test that existing wiki pages are reported.""" @@ -347,7 +349,7 @@ class TestMain: assert result.exit_code == 0 assert "existing wiki pages" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.ci.sync_wiki.GiteaClient") def test_file_not_found_fails(self, mock_client_cls: MagicMock) -> None: """Test that missing doc files cause an error, not a warning.""" @@ -361,7 +363,7 @@ class TestMain: assert result.exit_code != 0 assert "not found" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.ci.sync_wiki.GiteaClient") def test_empty_doc_file_fails(self, mock_client_cls: MagicMock) -> None: """Test that empty doc files cause an error, not a warning.""" @@ -375,7 +377,7 @@ class TestMain: assert result.exit_code != 0 assert "empty" in result.output.lower() - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.ci.sync_wiki.GiteaClient") def test_create_and_update(self, mock_client_cls: MagicMock) -> None: """Test that pages are created and updated correctly (non-dry-run).""" @@ -393,7 +395,7 @@ class TestMain: assert "Created: 1" in result.output assert "Updated: 1" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.ci.sync_wiki.GiteaClient") def test_verify_passes(self, mock_client_cls: MagicMock) -> None: """Test that --verify passes when content matches.""" @@ -413,7 +415,7 @@ class TestMain: assert result.exit_code == 0 assert "Verification passed" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.ci.sync_wiki.GiteaClient") def test_verify_fails_on_empty_content(self, mock_client_cls: MagicMock) -> None: """Test that --verify fails when wiki pages have empty content.""" @@ -430,7 +432,7 @@ class TestMain: assert result.exit_code == 1 assert "FAIL" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.ci.sync_wiki.GiteaClient") def test_verify_skipped_in_dry_run(self, mock_client_cls: MagicMock) -> None: """Test that --verify is skipped during dry-run.""" @@ -444,7 +446,7 @@ class TestMain: assert result.exit_code == 0 assert "Verification" not in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.ci.sync_wiki.GiteaClient") def test_strict_passes(self, mock_client_cls: MagicMock) -> None: """Test that --strict passes when integrity check succeeds.""" @@ -461,7 +463,7 @@ class TestMain: assert result.exit_code == 0 assert "Integrity check passed" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.ci.sync_wiki.GiteaClient") def test_strict_fails_on_integrity_issues(self, mock_client_cls: MagicMock) -> None: """Test that --strict fails when integrity check finds issues.""" @@ -483,7 +485,7 @@ class TestMain: assert "Missing page: FAQ" in result.output assert "Stale page: Old-Page" in result.output - @patch.dict("os.environ", {"REPO_TOKEN": "tok"}, clear=True) + @patch.dict("os.environ", {"CI_GITEA_TOKEN": "tok"}, clear=True) @patch("devx.ci.sync_wiki.GiteaClient") def test_strict_skipped_in_dry_run(self, mock_client_cls: MagicMock) -> None: """Test that --strict verification is skipped during dry-run."""