Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 78 additions & 2 deletions .github/workflows/build-image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ on:
required: true
type: string
image_name:
description: "Full image name (e.g. ghcr.io/mctlhq/mctl-api)"
description: "Full image name; for a direct dispatch it must be ghcr.io/mctlhq/<component_name>"
required: true
type: string
image_tag:
Expand Down Expand Up @@ -100,6 +100,79 @@ jobs:
# OIDC JWT for Vault JWT auth (ROADMAP 3.3). No long-lived VAULT_TOKEN.
id-token: write
steps:
# --- Image name: build only names owned by the requesting team ---
# A direct dispatch is how tenant builds arrive (Argo's deploy-service
# and preview-deploy) and how platform images under
# platform-gitops/images/ are built by hand (team platform). Every
# other dispatcher in the organisation calls release-deploy.yaml. For a
# direct dispatch the pushed name must be exactly
# <registry>/<component_name>, and that name must be one the team may
# build (platform-gitops/argo-workflows/config/image-names.txt, read
# from main, not from anything the caller chose).
#
# Argo's validation (tpl-validate-tenant) is the boundary for tenants:
# it also binds team_name to an existing tenant, which this workflow
# cannot, because it never sees who asked. This step is a backstop at
# the push, for whoever holds actions:write on this repository, and it
# has two known gaps that only such a holder can use:
# * release-deploy.yaml takes a free-text image_name and calls this
# workflow (workflow_call), which is not checked here: release
# images are named by their release and may differ from the
# component name (mctl-telegram-preview pushes mctl-telegram).
# * a dispatch at a ref other than main runs that ref's copy of this
# file. The policy data is read from main either way.
# github.workflow_ref names the top-level (caller's) workflow in a
# called run, so it tells a direct dispatch from a workflow_call. It is
# bound explicitly rather than read from the implicit
# GITHUB_WORKFLOW_REF. github.event_name cannot make this distinction:
# in a called run it is the caller's event, so a dispatched
# release-deploy.yaml would also read workflow_dispatch.
- name: Classify caller
id: caller
env:
CALLER_WORKFLOW_REF: ${{ github.workflow_ref }}
run: |
case "$CALLER_WORKFLOW_REF" in
"${GITHUB_REPOSITORY}/.github/workflows/build-image.yaml@"*) direct=true ;;
*) direct=false ;;
esac
echo "direct=${direct}" >> "$GITHUB_OUTPUT"
echo "direct dispatch: ${direct} (${CALLER_WORKFLOW_REF})"

- name: Check out image-name policy
if: steps.caller.outputs.direct == 'true'
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
repository: ${{ github.repository }}
ref: main
path: .image-name-policy
persist-credentials: false
sparse-checkout: |
platform-gitops/services
platform-gitops/argo-workflows/config
platform-gitops/argo-workflows/scripts

- name: Check image name
if: steps.caller.outputs.direct == 'true'
env:
INPUT_IMAGE_NAME: ${{ inputs.image_name }}
INPUT_TEAM_NAME: ${{ inputs.team_name }}
INPUT_COMPONENT_NAME: ${{ inputs.component_name }}
run: |
set -euo pipefail
expected="${REGISTRY}/${GITHUB_REPOSITORY_OWNER}/${INPUT_COMPONENT_NAME}"
if [ "$INPUT_IMAGE_NAME" != "$expected" ]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 — this pin is newly mandatory for dispatchers that live outside this repo, and nothing here verifies they satisfy it.

direct == true covers every workflow_dispatch, not just the two Argo templates. Per docs/runbooks/github-app-scope-audit.md:86-87, mctl-telegram/.github/workflows/preview-deploy.yml and the release-please.yml dispatch steps in mctl-api, mctl-agent, mctl-agents, mctl-portal, mctl-docs, mctl-academy, mctl-telegram, mctl-design and pfeifenpatenschaft-backend all hold actions:write on mctl-gitops. Any of them that dispatches build-image.yaml (rather than release-deploy.yaml) now has to pass image_name == ghcr.io/mctlhq/<component_name> exactly.

That pairing is not universal in this platform today: platform-gitops/services/labs/mctl-telegram-preview/values.yaml:17 runs ghcr.io/mctlhq/mctl-telegram, i.e. the component and the image genuinely differ for the preview service that the external preview-deploy.yml feeds. tests/test_check_image_name.py asserts the pin exists (line 183) but cannot assert that real callers match it, and grant labs mctl-telegram-preview in image-names.txt:57 is there only to satisfy "every existing service passes" — it does not tell us which component_name that dispatcher sends.

So the failure mode is: merge lands, the next mctl-telegram preview build fails at this step with image_name must be ghcr.io/mctlhq/mctl-telegram-preview, and there is no warn-only period to catch it. Worth confirming each external dispatcher's (image_name, component_name) pair before merge — or landing this half as a warning first (echo "::warning::" and no exit 1) and flipping it once the logs are clean.

The Argo-side pair is fine: wft-deploy-service.yaml:144 builds {{container_registry}}/{{component_name}} and wft-preview-deploy.yaml:166 builds ghcr.io/{GITOPS_ORG}/{component_name}, both matching.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified on every mctlhq repository's default branch.

Only two kinds of caller dispatch build-image.yaml directly:

Dispatcher team component image_name Passes
mctl-openclaw upstream-sync-release.yml labs openclaw ghcr.io/mctlhq/openclaw yes (grant labs openclaw)
hand dispatch, platform-gitops/images/* platform grafana-iac, mc, vault-iac, zitadel-iac, mctl-agent ghcr.io/mctlhq/ yes (grant platform ...)

Every other dispatcher calls release-deploy.yaml, which reaches build-image.yaml as a workflow_call. The pin does not apply there:

  • release-please.yml: mctl-api, mctl-agent, mctl-agents, mctl-portal, mctl-docs, mctl-academy, mctl-telegram, mctl-web, portfolio, seerrsense;
  • deploy.yml: mctl-design;
  • release-deploy.yml: mctl-alice, pfeifenpatenschaft-backend;
  • preview-deploy.yml: mctl-telegram. This one also covers the mctl-telegram-preview → ghcr.io/mctlhq/mctl-telegram case you mention.

The test now pins both direct dispatchers: each of their (team, component) pairs must pass in --build mode against the real tree.

echo "::error::image_name must be ${expected} for a direct dispatch, got: ${INPUT_IMAGE_NAME}"
exit 1
fi
if ! sh .image-name-policy/platform-gitops/argo-workflows/scripts/check-image-name.sh --build \
.image-name-policy "${REGISTRY}/${GITHUB_REPOSITORY_OWNER}" \
"$INPUT_TEAM_NAME" "$INPUT_COMPONENT_NAME"; then
echo "::error::component_name ${INPUT_COMPONENT_NAME} is not available to team ${INPUT_TEAM_NAME}"
exit 1
fi
rm -rf .image-name-policy

# --- Tier 1: Vault PAT via GitHub OIDC -> Vault JWT ---
- name: Fetch Vault PAT
id: vault_pat
Expand Down Expand Up @@ -329,9 +402,12 @@ jobs:
# the PAT.
secrets: |
github_token=${{ contains(fromJSON('["mctlhq/mctl-web","mctlhq/mctl-docs","mctlhq/mctl-academy"]'), inputs.repo) && secrets.GH_PACKAGES_TOKEN || '' }}
# :latest only for release builds. Nothing in this repository or the
# cluster pulls ghcr.io/mctlhq/*:latest, and a direct dispatch moving
# it would repoint the tag at whatever was built last.
tags: |
${{ inputs.image_name }}:${{ inputs.image_tag }}
${{ inputs.image_name }}:latest
${{ steps.caller.outputs.direct != 'true' && format('{0}:latest', inputs.image_name) || '' }}

- name: Summary
# Same reason as the Vault step: these land in a shell command, so
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/validate-manifests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,17 @@ jobs:
# nobody watches, so it is tested here instead.
run: python3 tests/test_rotate_github_token_scope.py

- name: Unit-test the image-name ownership check
# Tenant builds push, and tenant services run, ghcr.io/mctlhq/<component
# name>. check-image-name.sh decides which team may use a name; this
# runs it against fixtures and this tree, keeps image-names.txt
# complete (every platform image reserved, every existing service
# passing), and checks that validate, preview-deploy and build-image
# call it before anything is built or pushed.
run: |
python3 -m pip install --quiet pyyaml
python3 tests/test_check_image_name.py

- name: Unit-test tpl-git-commit's yq handling
# The static check above proves no yq expression interpolates a shell
# variable. This proves the shape that replaced it actually resists
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ metadata:
workflows.argoproj.io/description: |
Reusable template: validates tenant and service naming conventions,
checks team exists in Git tenants/ directory.
`image-name` checks only that a team may use a component name as its
image name (config/image-names.txt), for workflows that build without
running `validate`.
spec:
templates:
- name: validate
Expand All @@ -31,6 +34,10 @@ spec:
- name: service_template
default: "default"
# when not "default", dockerfile_repo is not required
- name: container_registry
default: "ghcr.io/mctlhq"
# where deploy-service pushes and services pull; must be the
# registry config/image-names.txt governs
outputs:
parameters:
- name: service_dir
Expand All @@ -42,6 +49,12 @@ spec:
- name: image_tag
valueFrom:
path: /tmp/image_tag
- name: builds
valueFrom:
path: /tmp/builds
# "true" when deploy-service will build and push
# <registry>/<component_name>; its build-image step runs on this
# alone, so the check below and the build cannot disagree.
script:
image: alpine/git:2.43.0
command: [sh]
Expand All @@ -64,6 +77,8 @@ spec:
value: "{{inputs.parameters.git_tag}}"
- name: PARAM_SERVICE_TEMPLATE
value: "{{inputs.parameters.service_template}}"
- name: PARAM_CONTAINER_REGISTRY
value: "{{inputs.parameters.container_registry}}"
envFrom:
- configMapRef:
name: mctl-platform-config
Expand Down Expand Up @@ -130,6 +145,77 @@ spec:
git clone --depth=1 "git@github.com:${GITOPS_ORG}/${GITOPS_REPO}.git" /tmp/mctl-gitops
cd /tmp/mctl-gitops

# ── 3b. Image name: the component name is the image name ───────────
# Services run, and builds push, <registry>/<component_name>, so a
# team may only use a name it owns. Rule and reviewed grants:
# config/image-names.txt. --tenant: TEAM is requester-supplied here,
# so it must be an existing tenant (never "platform"). --build when
# deploy-service will build (the `builds` output, which is the only
# thing its build-image step runs on). Any non-zero exit (refused,
# or could not decide) stops here, for every action.
#
# This is check-then-act: two teams onboarding the same free name
# at the same moment can both pass. The build-image.yaml check at
# the push sees the first team's services/ commit only once it has
# landed; closing the window fully needs the claim and the check
# in one commit.
#
# Whether it builds: never for update-config or without a
# dockerfile_repo. Otherwise the values the service runs decide:
# on onboard, the service template tpl-git-commit will render
# (selected the same way, __SERVICE_NAME__ and __TEAM_NAME__
# substituted, the placeholders an image name can use); on any
# other action, the existing values.yaml. If they name an image and
# none of them is <registry>/<component_name>, the service runs
# another image (e.g. the openclaw template's mctl-openclaw), and

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 — the only worked example in this comment block is a template the merge removed, and it is also the one place where the merge changed behaviour.

bdc83a67 brings in main's deletion of service-templates/openclaw/values.yaml.tpl, so on onboard with service_template: openclaw the -d guard at line 179 now misses and selection falls through to default/values.yaml.tpl — which renders ghcr.io/mctlhq/<component_name>, giving BUILDS=true where this comment says the openclaw case is the canonical false. The same example appears in wft-deploy-service.yaml:133.

The logic is unaffected and still correct: the decision reads the rendered template rather than its name, which is precisely why nothing broke when the template vanished. That is worth saying instead — the rule holds for any template that pins a fixed image, and the test now exercises it through the synthetic runs-fixed fixture (tests/test_check_image_name.py:263) rather than through openclaw, so the code and the fixtures already moved on while these two comments did not.

Fix this →

# building this name would push one nothing runs. Values naming no
# image, or a deploy with no values.yaml, build as before (deploy
# then fails at step 6). The images are read by values-images.sh,
# the reader check-image-name.sh uses too; a repository line it
# cannot read fails here rather than guessing "no build", which
# would bump image.tag to a tag nothing pushed. So does an image
# still holding a __PLACEHOLDER__: a template using one this step
# does not substitute would otherwise read as "another image".
BUILDS=false
if [ "$ACTION" != "update-config" ] && [ -n "$REPO" ]; then
TPLS="platform-gitops/argo-workflows/service-templates"
if [ "$ACTION" = "onboard" ]; then
# tpl-git-commit.yaml's template selection, step 4.
if [ "$SERVICE_TEMPLATE" != "default" ] && [ -d "${TPLS}/${SERVICE_TEMPLATE}" ]; then
TPL="${TPLS}/${SERVICE_TEMPLATE}/values.yaml.tpl"
elif [ "$TYPE" = "worker-service" ]; then
TPL="${TPLS}/worker/values.yaml.tpl"
else
TPL="${TPLS}/default/values.yaml.tpl"
fi
VALUES=/tmp/onboard-values.yaml
sed -e "s|__SERVICE_NAME__|${SERVICE}|g" -e "s|__TEAM_NAME__|${TEAM}|g" "$TPL" > "$VALUES"
else
VALUES="platform-gitops/services/${TEAM}/${SERVICE}/values.yaml"
fi
if [ ! -f "$VALUES" ]; then
BUILDS=true
elif ! IMAGES=$(sh platform-gitops/argo-workflows/scripts/values-images.sh "$VALUES"); then
echo "❌ cannot read the images ${VALUES} runs; not deciding whether to build"
exit 1
elif printf '%s\n' "$IMAGES" | grep -q '__[A-Z][A-Z_]*__'; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 — the placeholder guard is the right answer to the last round, but its character class excludes digits, so it does not cover every placeholder shape tpl-git-commit could grow.

__[A-Z][A-Z_]*__ matches all eight placeholders that exist today (tpl-git-commit.yaml:370-377). It does not match one containing a digit — __PORT2__ gets as far as __PORT and then needs __, finds 2, and fails everywhere in the string. A template rendering repository: ghcr.io/mctlhq/__REGION1__-__SERVICE_NAME__ therefore slips past the guard, compares unequal to <registry>/<component_name>, and lands back in the silent BUILDS=false this guard exists to prevent: an onboard that builds nothing and then bumps image.tag to a tag nothing pushed.

__[A-Z][A-Z0-9_]*__ closes it, and the value regex in values-images.sh:79 already admits digits, so nothing upstream filters them out first.

Worth noting what I checked around this, because the pairing is what makes the guard sound: the two substitutions here (__SERVICE_NAME__, __TEAM_NAME__) are exactly the ones that appear in a repository: value in any current template, $TEAM and $SERVICE have both passed the [a-z0-9-] grammar at step 1 before reaching sed, and the other six placeholders (__IMAGE_TAG__, __PORT__, __HOST__, __DEFAULT_MODEL__, __TELEGRAM_OWNER_ID__, __TELEGRAM_OWNER_IDS_JSON__) only ever appear outside image.repository, so leaving them unsubstituted costs nothing — values-images.sh reads one key and ignores the rest of the file.

Fix this →

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 — carried over from the 0c8ce302 review, still open: the placeholder guard excludes digits.

__[A-Z][A-Z_]*__ catches all five placeholders tpl-git-commit.yaml:346-350 substitutes today (__TEAM_NAME__, __SERVICE_NAME__, __IMAGE_TAG__, __PORT__, __HOST__), all digit-free. It does not catch one containing a digit: in __REGION1__ the match needs __ after __REGION, finds 1, and fails. A future template rendering repository: ghcr.io/mctlhq/__REGION1__-__SERVICE_NAME__ therefore passes the guard, compares unequal at line 203, and lands in the silent BUILDS=false this guard exists to prevent — an onboard that builds nothing and then bumps image.tag to a tag nothing pushed.

__[A-Z][A-Z0-9_]*__ closes it. Nothing upstream filters digits out first: values-images.sh:79's value class is [A-Za-z0-9._\/:@-], which admits both digits and _, so such a value reaches this line intact.

Fix this →

echo "❌ ${VALUES} names an image with an unsubstituted placeholder; not deciding whether to build"
exit 1
elif [ -z "$IMAGES" ] || printf '%s\n' "$IMAGES" | grep -qxF "${PARAM_CONTAINER_REGISTRY}/${SERVICE}"; then
BUILDS=true
else
echo "ℹ️ ${TEAM}/${SERVICE} runs another image; not building ${PARAM_CONTAINER_REGISTRY}/${SERVICE}"
fi
fi
echo "$BUILDS" > /tmp/builds
BUILD_FLAG=""
[ "$BUILDS" = true ] && BUILD_FLAG="--build"
if ! sh platform-gitops/argo-workflows/scripts/check-image-name.sh --tenant $BUILD_FLAG \
. "$PARAM_CONTAINER_REGISTRY" "$TEAM" "$SERVICE"; then
echo "❌ component_name '${SERVICE}' is not available to team '${TEAM}'"
exit 1
fi

# ── 4. Verify service exists for deploy/update-config ────────────────
if [ "$ACTION" = "deploy" ] || [ "$ACTION" = "update-config" ]; then
if [ ! -d "platform-gitops/services/${TEAM}/${SERVICE}" ]; then
Expand Down Expand Up @@ -175,10 +261,62 @@ spec:
echo "latest" > /tmp/image_tag
fi
echo "🏷 Image tag: $(cat /tmp/image_tag)"
resources:
requests:
memory: 32Mi
cpu: 10m
limits:
memory: 128Mi
cpu: 200m
volumeMounts:
- name: deploy-key
mountPath: /secrets/deploy-key
volumes:
- name: deploy-key
secret:
secretName: mctl-gitops-deploy-key

# Image-name check alone, for preview-deploy (which builds without
# running `validate`). mctl-gitops is public, so an anonymous HTTPS clone
# of main is enough: no deploy key in this pod. Parameters arrive as env,
# never interpolated into the script text.
- name: image-name
inputs:
parameters:
- name: team_name
- name: component_name
- name: git_ref
default: ""
# non-empty: preview-deploy will build, so the check is --build
script:
image: alpine/git:2.43.0
command: [sh]
envFrom:
- configMapRef:
name: mctl-platform-config
env:
- name: PARAM_TEAM_NAME
value: "{{inputs.parameters.team_name}}"
- name: PARAM_COMPONENT_NAME
value: "{{inputs.parameters.component_name}}"
- name: PARAM_GIT_REF
value: "{{inputs.parameters.git_ref}}"
source: |
set -e
git clone --depth=1 "https://github.com/${GITOPS_ORG}/${GITOPS_REPO}.git" /tmp/mctl-gitops
BUILD_FLAG=""
[ -n "$PARAM_GIT_REF" ] && BUILD_FLAG="--build"
# preview-deploy builds ghcr.io/<org>/<component_name>.
if ! sh /tmp/mctl-gitops/platform-gitops/argo-workflows/scripts/check-image-name.sh --tenant $BUILD_FLAG \
/tmp/mctl-gitops "ghcr.io/${GITOPS_ORG}" "$PARAM_TEAM_NAME" "$PARAM_COMPONENT_NAME"; then
echo "❌ component_name '${PARAM_COMPONENT_NAME}' is not available to team '${PARAM_TEAM_NAME}'"
exit 1
fi
echo "✅ image name ${PARAM_COMPONENT_NAME} is available to ${PARAM_TEAM_NAME}"
resources:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 — requests without limits, unlike the other pods in this directory.

Every other cluster template that declares resources pairs the two: cronworkflow-labs-claude-remote-restart.yaml:59-64, cwft-mctl-agents-approve.yaml:167-168, cwft-mctl-agents-implement.yaml:360-361, cwft-mctl-agents-investigate.yaml:338-339. A git clone --depth=1 of mctl-gitops is not free either — the repo is large enough that a burstable-with-no-ceiling pod is the one thing standing between a slow clone and node pressure.

        resources:
          requests:
            memory: 32Mi
            cpu: 10m
          limits:
            memory: 128Mi
            cpu: 200m

Fix this →

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in be70817. Both the new image-name pod and the existing validate pod now have limits: {memory: 128Mi, cpu: 200m} next to their requests. validate had no resources block at all before. The test asserts limits on both, and a mutation removing them is caught.

requests:
memory: 32Mi
cpu: 10m
limits:
memory: 128Mi
cpu: 200m
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,13 @@ spec:
# reserved because the tenant chart's argocd Role and RoleBinding,
# argo-workflow-argocd-<tenant>, would take the platform tier's own
# argo-workflow-argocd-sync (argo-workflow-* is already under argo*).
# platform is the team image-names.txt grants the platform's own images
# to. It is never a tenant, which keeps those grants unreachable from
# tenant workflows (check-image-name.sh --tenant).
tenant_name_reserved() {
case "$1" in
argocd|argo-workflows|argo-events|kube-system|kube-public|kube-node-lease|\
default|cert-manager|traefik|vault|external-secrets|monitoring|\
default|cert-manager|traefik|vault|external-secrets|monitoring|platform|\
temporal|backstage|minio|database|forgejo|zitadel|\
local-path-storage|system-upgrade|observability-eval|\
kube-*|argo*|*-system|platform-*|mctl-*|grafana-*|vault*)
Expand Down Expand Up @@ -357,10 +360,13 @@ spec:
# reserved because the tenant chart's argocd Role and RoleBinding,
# argo-workflow-argocd-<tenant>, would take the platform tier's own
# argo-workflow-argocd-sync (argo-workflow-* is already under argo*).
# platform is the team image-names.txt grants the platform's own images
# to. It is never a tenant, which keeps those grants unreachable from
# tenant workflows (check-image-name.sh --tenant).
tenant_name_reserved() {
case "$1" in
argocd|argo-workflows|argo-events|kube-system|kube-public|kube-node-lease|\
default|cert-manager|traefik|vault|external-secrets|monitoring|\
default|cert-manager|traefik|vault|external-secrets|monitoring|platform|\
temporal|backstage|minio|database|forgejo|zitadel|\
local-path-storage|system-upgrade|observability-eval|\
kube-*|argo*|*-system|platform-*|mctl-*|grafana-*|vault*)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,13 @@ spec:
# reserved because the tenant chart's argocd Role and RoleBinding,
# argo-workflow-argocd-<tenant>, would take the platform tier's own
# argo-workflow-argocd-sync (argo-workflow-* is already under argo*).
# platform is the team image-names.txt grants the platform's own images
# to. It is never a tenant, which keeps those grants unreachable from
# tenant workflows (check-image-name.sh --tenant).
tenant_name_reserved() {
case "$1" in
argocd|argo-workflows|argo-events|kube-system|kube-public|kube-node-lease|\
default|cert-manager|traefik|vault|external-secrets|monitoring|\
default|cert-manager|traefik|vault|external-secrets|monitoring|platform|\
temporal|backstage|minio|database|forgejo|zitadel|\
local-path-storage|system-upgrade|observability-eval|\
kube-*|argo*|*-system|platform-*|mctl-*|grafana-*|vault*)
Expand Down Expand Up @@ -788,10 +791,13 @@ spec:
# reserved because the tenant chart's argocd Role and RoleBinding,
# argo-workflow-argocd-<tenant>, would take the platform tier's own
# argo-workflow-argocd-sync (argo-workflow-* is already under argo*).
# platform is the team image-names.txt grants the platform's own images
# to. It is never a tenant, which keeps those grants unreachable from
# tenant workflows (check-image-name.sh --tenant).
tenant_name_reserved() {
case "$1" in
argocd|argo-workflows|argo-events|kube-system|kube-public|kube-node-lease|\
default|cert-manager|traefik|vault|external-secrets|monitoring|\
default|cert-manager|traefik|vault|external-secrets|monitoring|platform|\
temporal|backstage|minio|database|forgejo|zitadel|\
local-path-storage|system-upgrade|observability-eval|\
kube-*|argo*|*-system|platform-*|mctl-*|grafana-*|vault*)
Expand Down
Loading
Loading