fix(drone-dep): correct gitea admin create flag + dep deploy counter
Some checks failed
continuous-integration/drone/push Build is failing

Two issues found during first manual harness run:

1. gitea `--must-change-password false` (space form) leaves a pending
   password-change for the ci_admin user, blocking the OAuth2 API call.
   Fix: use `--must-change-password=false` (equals form, required by
   gitea's BoolFlag with default=true).

2. dep deploy_app() calls incremented the DG4.1 "one deploy per run"
   counter, causing a false violation when gitea dep + drone both deploy.
   Fix: lifecycle.deploy_app gains _count_deploy=True param (default
   backward-compat); deps_mod.deploy_deps passes _count_deploy=False so
   only the recipe-under-test counts toward DG4.1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
autonomic-bot
2026-06-11 21:37:45 +00:00
parent 51c3280163
commit 1adfbd70cb
3 changed files with 13 additions and 7 deletions

View File

@ -80,9 +80,10 @@ def deploy_deps(
for dep in deps: for dep in deps:
domain = dep_domain(parent_recipe, pr, ref, dep) domain = dep_domain(parent_recipe, pr, ref, dep)
print(f" dep: deploying {dep} -> {domain}", flush=True) print(f" dep: deploying {dep} -> {domain}", flush=True)
# NB: each dep_app gets a fresh deploy_count entry only on `_record_deploy` which fires # Dep deploys do NOT count toward the DG4.1 "one deploy per run" invariant — that
# inside `lifecycle.deploy_app`. For Phase 2 the deploy-count guard (DG4.1) counts the # contract covers the recipe-under-test only; each dep is a supporting service, not the
# parent + its deps as distinct install events — by design, since each is a separate app. # subject of the test. Pass _count_deploy=False so the main recipe's single-deploy
# assertion isn't distorted by the number of deps declared.
dm = meta_for.get(dep) or meta_mod.load(dep) dm = meta_for.get(dep) or meta_mod.load(dep)
lifecycle.deploy_app( lifecycle.deploy_app(
dep, dep,
@ -90,6 +91,7 @@ def deploy_deps(
secrets=True, secrets=True,
deploy_timeout=int(dm.DEPLOY_TIMEOUT), deploy_timeout=int(dm.DEPLOY_TIMEOUT),
meta=dm, meta=dm,
_count_deploy=False,
) )
try: try:
lifecycle.wait_healthy( lifecycle.wait_healthy(

View File

@ -238,6 +238,7 @@ def deploy_app(
install_steps_hook: tuple[str, str] | None = None, install_steps_hook: tuple[str, str] | None = None,
deploy_timeout: int = 900, deploy_timeout: int = 900,
meta=None, meta=None,
_count_deploy: bool = True,
) -> None: ) -> None:
"""Create + configure + deploy an app. Forces LETS_ENCRYPT_ENV='' so traefik serves the """Create + configure + deploy an app. Forces LETS_ENCRYPT_ENV='' so traefik serves the
wildcard cert via the file provider and NEVER attempts ACME (adversary finding A1). Applies any wildcard cert via the file provider and NEVER attempts ACME (adversary finding A1). Applies any
@ -251,10 +252,14 @@ def deploy_app(
`deploy_timeout` is the subprocess timeout for `abra app deploy`. Caller (orchestrator) passes `deploy_timeout` is the subprocess timeout for `abra app deploy`. Caller (orchestrator) passes
`recipe_meta.DEPLOY_TIMEOUT` so heavy recipes (ghost, matrix-synapse, lasuite-meet) can extend `recipe_meta.DEPLOY_TIMEOUT` so heavy recipes (ghost, matrix-synapse, lasuite-meet) can extend
past the 900s default. abra's INTERNAL TIMEOUT (recipe's TIMEOUT env, default 300s) is set via past the 900s default. abra's INTERNAL TIMEOUT (recipe's TIMEOUT env, default 300s) is set via
EXTRA_ENV; this is the Python subprocess wrapper's timeout so abra doesn't get SIGKILLed mid-deploy.""" EXTRA_ENV; this is the Python subprocess wrapper's timeout so abra doesn't get SIGKILLed mid-deploy.
`_count_deploy`: set False for dep deployments — the DG4.1 "one deploy per run" invariant
counts ONLY the recipe-under-test, not its install-time deps (deps_mod.deploy_deps)."""
if meta is None: if meta is None:
meta = meta_mod.load(recipe) meta = meta_mod.load(recipe)
_record_deploy() if _count_deploy:
_record_deploy()
# Lock BEFORE the app exists: a concurrent run's janitor must never see this app without a # Lock BEFORE the app exists: a concurrent run's janitor must never see this app without a
# held app lock (it would probe it as an orphan and reap an in-flight deploy). Also the # held app lock (it would probe it as an orphan and reap an in-flight deploy). Also the
# double-!testme serialisation point: a second run of the same domain blocks here. # double-!testme serialisation point: a second run of the same domain blocks here.

View File

@ -444,8 +444,7 @@ def setup_gitea_oauth(provider_domain: str, parent_domain: str) -> dict:
admin_password, admin_password,
"--email", "--email",
admin_email, admin_email,
"--must-change-password", "--must-change-password=false", # equals-form required; gitea BoolFlag default=true
"false",
], ],
timeout=120, timeout=120,
) )