fix(2): normalize lightweight recipe tags to annotated before pinned deploy (R014)
lasuite-meet upgrade tier failed at the prev-version base deploy: abra's pinned-deploy lint FATA'd on R014 'only annotated tags used for recipe version' because upstream coop-cloud lasuite-meet ships a stray LIGHTWEIGHT tag (0.3.0+v1.16.0). chaos deploys skip lint (so install,custom passed) but the upgrade tier's pinned prev-version deploy lints. New abra.normalize_recipe_tags() re-creates each lightweight version tag as annotated at the SAME commit (no deployed content changes); called in lifecycle.deploy_app after recipe_checkout when version is pinned. Idempotent; no-op for all-annotated recipes (lasuite-drive etc.). Helps any recipe with a stray upstream lightweight tag. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -83,6 +83,50 @@ def recipe_checkout(recipe: str, version: str) -> None:
|
|||||||
subprocess.run(["git", "-C", path, "checkout", "--quiet", version], check=True)
|
subprocess.run(["git", "-C", path, "checkout", "--quiet", version], check=True)
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_recipe_tags(recipe: str) -> int:
|
||||||
|
"""Convert any LIGHTWEIGHT recipe version tags to ANNOTATED in the local checkout, so abra's
|
||||||
|
pinned-deploy lint passes (R014 'only annotated tags used for recipe version'). Some upstream
|
||||||
|
coop-cloud recipes ship a stray lightweight tag (e.g. lasuite-meet's `0.3.0+v1.16.0`), which makes
|
||||||
|
`abra app deploy <pinned-version>` FATA on lint for the whole recipe — blocking the upgrade tier's
|
||||||
|
prev-version base deploy. This re-creates each lightweight tag as annotated pointing at the SAME
|
||||||
|
commit, so NO deployed content changes (only the tag object type). No-op for recipes whose tags are
|
||||||
|
already annotated (most). Returns the count re-annotated."""
|
||||||
|
import os
|
||||||
|
|
||||||
|
path = os.path.expanduser(f"~/.abra/recipes/{recipe}")
|
||||||
|
tags = subprocess.run(
|
||||||
|
["git", "-C", path, "tag", "-l"], capture_output=True, text=True
|
||||||
|
).stdout.split()
|
||||||
|
git_env = dict(
|
||||||
|
os.environ,
|
||||||
|
GIT_COMMITTER_NAME="cc-ci",
|
||||||
|
GIT_COMMITTER_EMAIL="ci@cc-ci.local",
|
||||||
|
GIT_AUTHOR_NAME="cc-ci",
|
||||||
|
GIT_AUTHOR_EMAIL="ci@cc-ci.local",
|
||||||
|
)
|
||||||
|
fixed = 0
|
||||||
|
for t in tags:
|
||||||
|
objtype = subprocess.run(
|
||||||
|
["git", "-C", path, "cat-file", "-t", t], capture_output=True, text=True
|
||||||
|
).stdout.strip()
|
||||||
|
if objtype != "commit": # already annotated (objtype == "tag")
|
||||||
|
continue
|
||||||
|
commit = subprocess.run(
|
||||||
|
["git", "-C", path, "rev-list", "-n", "1", t], capture_output=True, text=True
|
||||||
|
).stdout.strip()
|
||||||
|
if not commit:
|
||||||
|
continue
|
||||||
|
subprocess.run(
|
||||||
|
["git", "-C", path, "tag", "-a", "-f", "-m", f"cc-ci: annotate {t} for R014", t, commit],
|
||||||
|
check=True,
|
||||||
|
env=git_env,
|
||||||
|
)
|
||||||
|
fixed += 1
|
||||||
|
if fixed:
|
||||||
|
print(f" normalize_recipe_tags({recipe}): re-annotated {fixed} lightweight tag(s) for R014", flush=True)
|
||||||
|
return fixed
|
||||||
|
|
||||||
|
|
||||||
def env_set(domain: str, key: str, value: str) -> None:
|
def env_set(domain: str, key: str, value: str) -> None:
|
||||||
"""Set a key in the app's .env (abra has no setter; edit the file directly)."""
|
"""Set a key in the app's .env (abra has no setter; edit the file directly)."""
|
||||||
import os
|
import os
|
||||||
|
|||||||
@ -147,6 +147,10 @@ def deploy_app(
|
|||||||
# checkout). Order matters: checkout before secret_generate (-C) so secrets match the pinned tree.
|
# checkout). Order matters: checkout before secret_generate (-C) so secrets match the pinned tree.
|
||||||
if version:
|
if version:
|
||||||
abra.recipe_checkout(recipe, version)
|
abra.recipe_checkout(recipe, version)
|
||||||
|
# A pinned (non-chaos) deploy runs `abra recipe lint`; normalize any stray lightweight
|
||||||
|
# upstream tags to annotated so R014 doesn't FATA the whole recipe (changes no deployed
|
||||||
|
# content — see abra.normalize_recipe_tags). No-op for recipes with all-annotated tags.
|
||||||
|
abra.normalize_recipe_tags(recipe)
|
||||||
# Pin DOMAIN to the run domain explicitly. `abra app new -D` fills it for recipes whose
|
# Pin DOMAIN to the run domain explicitly. `abra app new -D` fills it for recipes whose
|
||||||
# .env.sample uses a literal placeholder, but NOT for ones using a `{{ .Domain }}` Go-template
|
# .env.sample uses a literal placeholder, but NOT for ones using a `{{ .Domain }}` Go-template
|
||||||
# (this abra version leaves it unexpanded → deploy fails "can't evaluate field Domain"). Setting
|
# (this abra version leaves it unexpanded → deploy fails "can't evaluate field Domain"). Setting
|
||||||
|
|||||||
Reference in New Issue
Block a user