DEV Community

Cover image for πŸš€ CI/CD Pipelines & YAML Best Practices
YogitaKadam14
YogitaKadam14

Posted on

πŸš€ CI/CD Pipelines & YAML Best Practices

Lessons Learned from Real-World Azure + Bitbucket Deployments
Designing CI/CD pipelines feels straightforward…
until your builds become inconsistent, deployments start failing, and environment management turns messy.

After working extensively with:

  • Bitbucket Pipelines
  • Azure App Service (Linux)
  • Node.js backends
  • React / Angular frontends
  • Monorepos

…I’ve gathered practical lessons that saved hours of debugging and prevented production issues.

This post focuses on real-world patterns, not textbook theory.

🧱 1️⃣ Deterministic Builds Are Non-Negotiable
One of the most common CI/CD mistakes:

npm install
Enter fullscreen mode Exit fullscreen mode

❌ Why this is risky in pipelines

  • Can modify package-lock.json
  • Non-reproducible builds
  • β€œWorks locally, fails in CI”

βœ… Best Practice

npm ci
Enter fullscreen mode Exit fullscreen mode

For deployment bundles:

npm ci --omit=dev
Enter fullscreen mode Exit fullscreen mode

βœ” Benefits

  • Enforces lockfile
  • Faster installs
  • Reproducible builds

πŸ“¦ 2️⃣ Don’t Ship Dev Dependencies to Production
Early pipelines often bundle everything:

node_modules/
Enter fullscreen mode Exit fullscreen mode

❌ Consequences

  • Bloated artifacts
  • Slower deployments
  • Higher memory usage
  • Cold start delays

βœ… Better Strategy
Reinstall only production dependencies:

npm ci --omit=dev
Enter fullscreen mode Exit fullscreen mode

βœ” Result

  • Smaller ZIP
  • Faster startup
  • Cleaner runtime

βš› 3️⃣ Frontend Configuration: The Silent Problem
For React / Angular / Vite apps:

npm run build
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ Environment variables become hardcoded into JS bundles
❌ Symptoms

  • Azure App Settings changes do nothing
  • Rebuild required per environment

βœ… Scalable Solution β†’ Runtime Config
Create an env.js file:

window.__env = {
  API_URL: "https://api.example.com"
};
Enter fullscreen mode Exit fullscreen mode

Load before the app bundle:

<script src="/env.js"></script>
Enter fullscreen mode Exit fullscreen mode

Access in React:

const apiUrl = window.__env?.API_URL;
Enter fullscreen mode Exit fullscreen mode

βœ” Advantages

  • Build once, deploy anywhere
  • No rebuild per environment
  • Easy config updates
  • Customer-specific deployments

πŸ” 4️⃣ Frontend Secrets? They Don’t Exist.
Important reality:
❌ You cannot truly hide secrets in frontend apps
Anything delivered to the browser can be inspected.

🚨 Never expose

  • API keys
  • DB credentials
  • Client secrets

βœ… Correct Architecture

Frontend β†’ Backend β†’ Third-party
Enter fullscreen mode Exit fullscreen mode

Secrets live only in:

  • Backend
  • Azure App Settings
  • Key Vault

🌱 5️⃣ One YAML vs Multiple YAML Files
As projects grow:
πŸ‘‰ Should we create separate YAML per branch?

❌ Why this becomes painful

  • Pipeline drift
  • Duplication
  • Maintenance overhead

βœ… Recommended
Use one common YAML with branch logic:

branches:
  dev:
  test:
  main:
Enter fullscreen mode Exit fullscreen mode

πŸ” 6️⃣ Repeated Steps? Use YAML Anchors
Avoid copy-paste pipelines.
βœ… Use Anchors

definitions:
  steps:
    - step: &build_step
Enter fullscreen mode Exit fullscreen mode

Reuse:

- step: *build_step
Enter fullscreen mode Exit fullscreen mode

βœ” Benefits

  • Cleaner YAML
  • Easier updates
  • Less duplication

☁️ 7️⃣ Azure Deployment: Pipe vs CLI
Two popular approaches:

βœ… Atlassian Azure Pipe (Preferred)

pipe: atlassian/azure-web-apps-deploy
Enter fullscreen mode Exit fullscreen mode

βœ” Why it’s great

  • Minimal scripting
  • Cleaner pipelines
  • Fewer failure points

🧰 Azure CLI (Use When Needed)

Best for:

  • Slot swaps
  • Infra provisioning
  • Advanced automation

❌ Avoid installing CLI manually

curl InstallAzureCLIDeb
Enter fullscreen mode Exit fullscreen mode

βœ… Use Azure CLI image instead

image: mcr.microsoft.com/azure-cli
Enter fullscreen mode Exit fullscreen mode

🚨 8️⃣ Dangerous Commands to Avoid (Unless Justified)

Examples:

az resource update ... allow=true
PORT=8080 hardcoding
sleep 30 hacks
Enter fullscreen mode Exit fullscreen mode

βœ… Only acceptable when

  • Legacy constraints
  • Debugging scenarios
  • Platform requirements
  • Always document the reason.

πŸ” 9️⃣ Repository vs Deployment Variables
Misusing variables causes many CI/CD issues.
βœ… Repository Variables

Use for:

  • Shared config
  • Build constants

Examples:

  • NODE_VERSION
  • LINT_FLAGS

βœ… Deployment Variables
Use for:

  • Environment-specific values
  • Secrets

Examples:

  • API_URL
  • Azure credentials

πŸ† Final Takeaways

βœ… Pipelines must be deterministic
βœ… Use npm ci, not npm install
βœ… Install prod dependencies only
βœ… Artifacts should be environment-agnostic
βœ… Never store secrets in frontend
βœ… Prefer runtime config for SPAs
βœ… Use one YAML with branch logic
βœ… Use YAML anchors to avoid duplication
βœ… Prefer deployment pipes over complex scripts
βœ… Use Azure CLI only when flexibility required

πŸ† Conclusion: CI/CD is Easy… Until It Isn’t

Setting up a pipeline that β€œworks” is not difficult.

But designing a pipeline that is:

  • Deterministic
  • Environment-agnostic
  • Secure
  • Scalable

Easy to maintain
πŸ‘‰ requires deliberate engineering decisions.

Small shortcuts like:
❌ Using npm install
❌ Embedding secrets in frontend
❌ Duplicating YAML per branch
❌ Shipping devDependencies
…may work initially but create serious friction as projects scale.

πŸ”₯ Final Thought

Your CI/CD pipeline is not just automation…
πŸ‘‰ It is part of your system architecture.
Treat it with the same care as application code.

Top comments (0)