# DEVX-162: Fix Gitea repo-variable read contract and fail closed on unknown nightly status ## Problem `GiteaClient.get_repo_variable()` reads `body["value"]`, but the deployed Gitea returns the variable payload in the `data` field: ```json {"owner_id":0,"repo_id":1,"name":"NIGHTLY_STATUS","data":"passed:5842","description":""} ``` Every read therefore returns `None`. `devx.ci.nightly_gate --action check` interprets `None` as "bootstrap — allow deploy," so a real `failed:` status is invisible and the gate is permanently fail-open. Infra nightly run 5800 set `NIGHTLY_STATUS=passed:5800` while platform/customer integration tests were still failing — and even a correct `failed` value would have been ignored. Additionally, an unrecognized non-empty status currently allows deploys (fail-open instead of fail-closed). Verified against the live API: `POST`/`PUT` accept `{"value": ...}` and work; only the GET response uses `data`. The earlier `DEVX-162` spec (registry push race) is preserved as `DEVX-162-registry-push-race-historical.md`. ## Approach REQ-1: `src/devx/api_clients.py` — `get_repo_variable` reads `data` first and falls back to `value` for older server/fixture compatibility. Write path unchanged (PUT/POST `{"value": ...}` verified live: 201/204). REQ-2: `src/devx/ci/nightly_gate.py` — unknown non-empty status blocks the deploy (fail closed) instead of allowing it. Unset (bootstrap) still allows. REQ-3: Tests cover the `data` field, the `value` fallback, and fail-closed unknown status. ## Test Plan - `pytest tests/unit/test_api_clients.py tests/unit/test_nightly_gate.py` - `make lint-all` (ruff, pyright, bandit, translations) ## Deploy Plan Merge via auto-merge; post-merge workflow publishes a new devx package to the Gitea PyPI registry and opens the infra dependency-bump PR automatically. ## Rollback Plan Revert the commit; infra's pinned devx version keeps the previous behavior until the dependency PR lands. ## Acceptance Criteria - [x] `get_repo_variable` returns the `data` field and falls back to `value`. - [x] Unknown nightly status exits non-zero and writes `nightly-gate-passed=false`. - [x] Unit tests cover `data`, `value` fallback and fail-closed unknown status. - [x] `make lint-all` and unit tests pass.