feat: support custom tag-keys for non-standard YAML layouts

Adds tag-keys input (comma-separated) to update arbitrary YAML keys
instead of just 'tag'. Handles unquoted values, quoted values, and
YAML anchors (e.g. rustImageTag: &rustImageTag "value").

Makes image-repository optional when using custom tag-keys.
This commit is contained in:
2026-06-17 20:06:59 -07:00
parent c11d34400e
commit 248eb37110
2 changed files with 80 additions and 61 deletions
+51 -8
View File
@@ -4,11 +4,23 @@ author: eric
inputs:
image-repository:
description: Full image repository (e.g. git.ericxliu.me/eric/workout)
required: true
description: |
Full image repository (e.g. git.ericxliu.me/eric/workout).
Used to update 'repository:' fields in standard bjw-s app-template format.
Optional when using tag-keys for non-standard layouts.
required: false
default: ""
image-tag:
description: Image tag to deploy (e.g. 2026-06-17-abc1234)
required: true
tag-keys:
description: |
Comma-separated YAML keys whose values should be set to image-tag.
Defaults to 'tag' which matches the standard 'tag: <value>' format.
For non-standard layouts, specify custom keys (e.g. 'rustImageTag,uiImageTag').
Handles both unquoted values and quoted values with optional YAML anchors.
required: false
default: "tag"
gitops-repo:
description: SSH URL of the GitOps repo
default: git@github.com:eric-x-liu/k8s-flux.git
@@ -40,6 +52,7 @@ runs:
env:
IMAGE_REPOSITORY: ${{ inputs.image-repository }}
IMAGE_TAG: ${{ inputs.image-tag }}
TAG_KEYS: ${{ inputs.tag-keys }}
GITOPS_REPO: ${{ inputs.gitops-repo }}
GITOPS_FILE: ${{ inputs.gitops-file }}
DEPLOY_KEY: ${{ inputs.deploy-key }}
@@ -61,23 +74,53 @@ runs:
git clone "$GITOPS_REPO" "$workdir/gitops"
cd "$workdir/gitops"
# ── Update image repository + tag via regex ────────────────
# ── Update image fields via regex ──────────────────────────
python3 -c '
import os, pathlib, re
path = pathlib.Path(os.environ["GITOPS_FILE"])
repo = os.environ["IMAGE_REPOSITORY"]
repo = os.environ.get("IMAGE_REPOSITORY", "")
tag = os.environ["IMAGE_TAG"]
tag_keys = [k.strip() for k in os.environ["TAG_KEYS"].split(",") if k.strip()]
text = path.read_text()
text = re.sub(r"(repository:\s*)\S+", lambda m: m.group(1) + repo, text, count=1)
text = re.sub(r"(tag:\s*)\S+", lambda m: m.group(1) + tag, text, count=1)
# Update repository field (only if image-repository is provided)
if repo:
text = re.sub(r"(repository:\s*)\S+", lambda m: m.group(1) + repo, text, count=1)
# Update each tag key
for key in tag_keys:
# Pattern matches both formats:
# tag: 2026-06-17-abc1234 (unquoted)
# tag: "2026-06-17-abc1234" (quoted)
# rustImageTag: &anchor "value" (YAML anchor with quotes)
# tag: *anchor (YAML alias — left alone by design)
#
# Group 1: everything up to and including the last quote or whitespace before the value
# Replacement: group(1) + new tag (preserving quoting style)
quoted = re.sub(
r"(" + re.escape(key) + r""":\s*(?:&\S+\s+)?)\"[^"]*\"""",
lambda m: m.group(1) + '"' + tag + '"',
text
)
if quoted != text:
text = quoted
else:
# Unquoted value (e.g., tag: 2026-06-17-abc1234)
text = re.sub(
r"(" + re.escape(key) + r":\s*)\S+",
lambda m: m.group(1) + tag,
text,
count=1
)
path.write_text(text)
'
# ── Commit + push (idempotent) ────────────────────────────
if git diff --quiet -- "$GITOPS_FILE"; then
echo "✅ GitOps already points to $IMAGE_REPOSITORY:$IMAGE_TAG — nothing to do"
echo "✅ GitOps already points to ${IMAGE_REPOSITORY:-(custom keys)}:$IMAGE_TAG — nothing to do"
exit 0
fi
@@ -97,4 +140,4 @@ runs:
git commit -m "$COMMIT_MESSAGE"
git push origin main
echo "🚀 Pushed: $IMAGE_REPOSITORY:$IMAGE_TAG → $GITOPS_FILE"
echo "🚀 Pushed: ${APP_NAME} → $IMAGE_TAG"