ywai/skills/devops/SKILL.md
Azure DevOps YAML pipelines and Helm Umbrella chart conventions for multi-service projects. Concrete actions: create multi-stage pipeline YAML for Docker build/push to ACR, generate Umbrella Helm charts with sub-charts, configure values.yaml environment contracts, set up tag-triggered versioning strategy. Trigger: When the user asks to create or modify Azure DevOps pipelines, generate or maintain Helm Umbrella charts, configure values.yaml service nodes, set up Docker-to-ACR image tagging, or scaffold the DevOps directory for a new project.
npx skillsauth add Yoizen/dev-ai-workflow devopsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Chart.yaml, sub-charts, values.yaml)values.yaml environment variable contracts for servicesAll version management uses a single mechanism: the {{chartversion}} placeholder.
Chart.yaml (version + appVersion), sub-chart Chart.yaml (version), and values.yaml (global.appVersion)helm-acr-build-and-push template runs find ... -exec sed to replace {{chartversion}} in ALL files recursively before packagingrefs/tags/version/* → $(Build.SourceBranchName))appVersion: 0.1.1){{chartversion}}Each project has two pipeline files: production (tag-triggered) and dev (branch-triggered). Both consume shared templates from a central pipeline-templates repo via @pipelines-templates.
| Pipeline | Trigger | Version Source |
|----------|---------|----------------|
| azure-pipelines.yml | refs/tags/version/* only | $(Build.SourceBranchName) from tag |
| azure-pipelines-dev.yml | Branch pushes (dev, feature) | Static variable (e.g. 0.1.1) |
NEVER trigger production builds on branch pushes — only tags.
| Template | Purpose |
|----------|---------|
| docker-acr-build-and-push.yml | Build Docker image → push to ACR |
| helm-acr-build-and-push.yml | Replace {{chartversion}} → package → push Helm chart to ACR |
| restart-deployment.yml | Restart K8s deployments in AKS (optional, dev only) |
Full pipeline YAML examples and template parameter tables: references/PIPELINES.md
The project uses an Umbrella Helm chart pattern. The umbrella declares common-helpers as its only explicit dependency. Sub-charts live inside charts/ and are auto-discovered by Helm.
DevOps/Helm/
├── Chart.yaml # apiVersion v2 — common-helpers dependency only
├── values.yaml # Unified values: global + one node per service
├── templates/
│ └── utils.yaml # ConfigMap, Secret, PV, PVC (umbrella-level)
└── charts/
├── service1/
│ ├── Chart.yaml # apiVersion v1 — no dependencies
│ └── templates/
│ ├── deployment.yaml # {{ include "common-helpers.deploymenttemplate" . }}
│ └── utils.yaml # Service, Ingress, PDB, HPA via common-helpers
└── service2/ # Same structure — copy for each service
Chart.yaml — they are auto-discovered from charts/apiVersion: v1 and declare no dependencies — common-helpers is inherited from the umbrella{productName}-{client}-{environment}-{appName}Full chart YAML templates, common-helpers reference, and deployment features: references/HELM-STRUCTURE.md
One top-level node per service (key MUST match sub-chart directory name and appName). global holds shared config.
| Scope | Key Fields |
|-------|------------|
| Global | productName, appVersion ({{chartversion}}), client, environment, registry |
| Service identity | appName (must match node key + chart dir) |
| Deployment | replicas, containerPort, image, healthcheck |
| Resources | requestsCPU, requestsMEM, limitsCPU, limitMEM |
| Networking | enableIngress, IngressUrl, IngressClassName |
| Scaling | enableHPA, minReplicas, maxReplicas, enablePDB |
| Environment | requiredConfigMapEnv, optionalConfigMapEnv, requiredSecretEnv, optionalSecretEnv |
Full field tables, global section details, and values.yaml template: references/VALUES-REFERENCE.md
Run these checks before committing changes or after generating new files:
# Lint the chart (catches schema errors, missing required values)
helm lint DevOps/Helm/
# Render templates locally to verify output (without deploying)
helm template my-release DevOps/Helm/ --debug
# Verify dependency resolution works
helm dependency update DevOps/Helm/
# Check that {{chartversion}} placeholder exists in all expected files
grep -r '{{chartversion}}' DevOps/Helm/
# Verify YAML syntax
python -c "import yaml; yaml.safe_load(open('DevOps/azure-pipelines.yml'))"
# Check that shared template references are correct
grep -n '@pipelines-templates' DevOps/azure-pipelines*.yml
# Verify service names are in sync across values.yaml nodes, chart dirs, and appName values
# Each sub-chart dir name must match its Chart.yaml 'name' and its values.yaml node key + appName
ls DevOps/Helm/charts/
grep 'appName:' DevOps/Helm/values.yaml
grep '^name:' DevOps/Helm/charts/*/Chart.yaml
| Symptom | Cause | Fix |
|---------|-------|-----|
| {{chartversion}} appears in deployed resources | Pipeline did not run sed replacement | Verify helm-acr-build-and-push template innerPath points to DevOps/Helm |
| helm dependency update fails | common-helpers version mismatch or ACR auth issue | Check umbrella Chart.yaml dependency version matches published chart; verify ACR login |
| Pod stuck in CreateContainerConfigError | Missing requiredConfigMapEnv or requiredSecretEnv values | Ensure all required keys exist as global.* values or are injected by CD pipeline Variable Group |
| Ingress not created | enableIngress not set to true in service node | Add enableIngress: true and IngressUrl to the service's values.yaml node |
| HPA ignoring replicas field | Expected behavior when enableHPA: true | HPA manages replica count — replicas is ignored. Set minReplicas/maxReplicas instead |
| Sub-chart not rendered | Directory missing from charts/ or Chart.yaml malformed | Verify sub-chart dir exists and its Chart.yaml has valid apiVersion: v1 + name matching dir |
| Resources not appearing in deployment | No resource fields set | At least one of requestsCPU/requestsMEM/limitsCPU/limitMEM must be set to render resources block |
{{chartversion}} for all versions — never hardcode (see Versioning Strategy)appName value, and sub-chart directory name in syncvalues.yaml defaults at deploy time — only extend with new keyspipelines-templates repo — never inline Docker or Helm commandscommon-helpers is resolved at the umbrella level only{productName}-{client}-{environment}-{appName} — never deviateglobal.environment and global.client are populated by the CD pipeline from Variable Groups{appName}-{clientName}-{environment} — keys use __ as level separatorglobal.* — any key in requiredConfigMapEnv/optionalConfigMapEnv MUST exist as global.{key}helm lint and helm template --debug before committing chart changesdocumentation
Yoizen UI design system guidelines and resources. Trigger: When working on Yoizen UI components, styling, colors, typography, or icons.
development
TypeScript strict patterns and best practices. Trigger: When writing TypeScript code - types, interfaces, generics.
development
Tailwind CSS 4 patterns and best practices. Trigger: When styling with Tailwind - cn(), theme variables, no var() in className.
data-ai
name: skill-sync description: > Sync skill metadata with the Auto-invoke sections in AGENTS.md. Trigger: When you change a skill's metadata (metadata.scope/metadata.auto_invoke), regenerate the Auto-invoke tables, or run ./skills/skill-sync/assets/sync.sh. metadata: author: Yoizen version: "1.0" scope: [root] auto_invoke: - "skill operations" - "workflow" - "sdd" author: Yoizen version: "1.0" scope: [root] auto_invoke: - "skill operations" - "workflow"