tutorial

Monitoring Azure Pipelines with Vigilmon: Catch Silent CI/CD Failures

Use Vigilmon heartbeat monitors to detect silent Azure Pipelines failures — scheduled pipeline drift, stuck agents, and pipelines that stop running entirely.

Your nightly build pipeline stopped running two weeks ago. Nobody noticed until a deployment to a client environment failed because the artifact registry hadn't been updated. Azure Pipelines had no errors to report — the scheduled pipeline simply wasn't being triggered anymore. Build notifications only fire on failures, and you can't fail if you never run.

This is the silent CI/CD failure problem. HTTP monitors can't catch it because there's nothing to ping. The fix is heartbeat monitoring: your pipeline pings a unique URL at the end of every successful run, and if Vigilmon doesn't receive that ping within the expected window, you get alerted.

This tutorial shows you how to instrument Azure Pipelines with Vigilmon heartbeat monitors to catch failures before your team does.

What You'll Cover

  • Heartbeat monitoring for scheduled Azure Pipelines runs
  • Catching pipelines that stop triggering entirely
  • Alerting on long-running or stuck agents
  • Multi-environment monitoring (staging and production)
  • Detecting scheduled pipeline drift in Azure DevOps

Prerequisites

  • An Azure DevOps project with at least one pipeline
  • A free account at vigilmon.online

The Problem: What Standard Azure Pipelines Monitoring Misses

Azure Pipelines has built-in email notifications — but they only fire when a pipeline fails. They won't alert you when:

  • A scheduled trigger is disabled by a pipeline YAML change or UI toggle
  • A pipeline is paused in the Azure DevOps UI and nobody re-enables it
  • A stage is skipped because an approval gate is left pending indefinitely
  • A self-hosted agent goes offline and builds queue forever without running

Vigilmon's heartbeat pattern closes all of these gaps.


Step 1: Create a Heartbeat Monitor in Vigilmon

A heartbeat monitor expects a ping on a regular interval. No ping → alert.

  1. Log in to Vigilmon and click New Monitor → Heartbeat.
  2. Give it a name like Nightly Build — main.
  3. Set the Expected interval to match your pipeline schedule. For a nightly cron, use 24 hours. For hourly CI, use 90 minutes (adds a 50% buffer).
  4. Set the Grace period to 30 minutes for short intervals, or 1 hour for daily jobs. This prevents false alerts from slight schedule drift.
  5. Save and copy the Ping URL — it looks like https://vigilmon.online/api/heartbeat/<unique-id>.

Step 2: Add the Heartbeat Ping to a Scheduled Pipeline

Store the heartbeat URL as a Pipeline secret variable. In Azure DevOps, go to your pipeline → Edit → Variables → New variable:

  • Name: VIGILMON_NIGHTLY_HEARTBEAT_URL
  • Value: the ping URL from Step 1
  • Check Keep this value secret

For variables shared across multiple pipelines, use a Variable group (Library → Variable groups → Add) and link it to the pipeline.

Here's a complete azure-pipelines.yml example with Vigilmon instrumentation:

# azure-pipelines.yml
trigger:
  - none

schedules:
  - cron: "0 2 * * *"     # 02:00 UTC every night
    displayName: Nightly build
    branches:
      include:
        - main
    always: true           # run even when there are no code changes

pool:
  vmImage: ubuntu-latest

variables:
  - group: vigilmon-secrets   # variable group containing VIGILMON_NIGHTLY_HEARTBEAT_URL

steps:
  - task: NodeTool@0
    inputs:
      versionSpec: "20.x"
    displayName: Set up Node.js

  - script: npm ci
    displayName: Install dependencies

  - script: npm test
    displayName: Run tests

  - bash: |
      curl -fsS -X POST "$(VIGILMON_NIGHTLY_HEARTBEAT_URL)" \
        --max-time 10 \
        --retry 3 \
        --retry-delay 2
    displayName: Ping Vigilmon heartbeat
    condition: succeeded()

Key points about this setup:

  • condition: succeeded() — the heartbeat ping is only sent when all previous steps pass. If tests fail, this step is skipped and no ping is sent.
  • --retry 3 — transient network issues won't cause a false "missed heartbeat" alert.
  • --max-time 10 — the ping step won't hang and block the agent.
  • always: true on the schedule — ensures the pipeline runs on schedule even with no code changes, which is the common case for monitoring-style runs.

Step 3: Monitor Your Deployment Pipeline

Heartbeats are even more valuable for deployment pipelines — a silently stalled deploy leaves production or a client environment running stale code.

# azure-pipelines.yml (multi-stage with deployment)
trigger:
  branches:
    include:
      - main

pool:
  vmImage: ubuntu-latest

variables:
  - group: vigilmon-secrets

stages:
  - stage: Build
    jobs:
      - job: BuildAndTest
        steps:
          - script: npm ci
            displayName: Install

          - script: npm run build
            displayName: Build

          - script: npm test
            displayName: Test

          - task: PublishBuildArtifacts@1
            inputs:
              pathToPublish: dist
              artifactName: app

  - stage: Deploy
    dependsOn: Build
    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
    jobs:
      - deployment: DeployProduction
        environment: production
        strategy:
          runOnce:
            deploy:
              steps:
                - script: ./scripts/deploy.sh production
                  displayName: Deploy

                - script: npm run test:smoke
                  displayName: Smoke tests

                - bash: |
                    curl -fsS -X POST "$(VIGILMON_DEPLOY_PROD_HEARTBEAT_URL)" \
                      --max-time 10 \
                      --retry 3
                  displayName: Ping Vigilmon deployment heartbeat
                  condition: succeeded()

Create a separate heartbeat monitor for this deployment stage with an interval of 48 hours (or however often you expect to deploy). If no successful deployment reaches production within that window, Vigilmon pages you.


Step 4: Detect Scheduled Pipeline Drift

Azure Pipelines scheduled triggers have a known limitation: always: false (the default) causes pipelines to skip runs when no code has changed. A monitoring pipeline that should run nightly may silently stop if the repo goes quiet.

Setting always: true in the schedule block fixes this for most cases. But Vigilmon's heartbeat monitor provides a second layer — if the pipeline misses a run for any reason (agent outage, schedule misconfiguration, pipeline paused), no ping arrives, and you get alerted.

To make the signal even more reliable, add metadata to the heartbeat payload:

- bash: |
    curl -fsS -X POST "$(VIGILMON_NIGHTLY_HEARTBEAT_URL)" \
      -H "Content-Type: application/json" \
      -d "{\"pipeline\": \"$(Build.DefinitionName)\", \"build_id\": \"$(Build.BuildId)\", \"branch\": \"$(Build.SourceBranch)\"}" \
      --max-time 10 \
      --retry 3
  displayName: Ping Vigilmon heartbeat with metadata
  condition: succeeded()

Vigilmon accepts the body but doesn't require it — it only cares whether the ping arrived within the grace period.


Step 5: Multi-Environment Monitoring

For teams with staging and production pipelines, create one heartbeat monitor per environment per stage:

| Stage | Environment | Monitor name | Interval | |---|---|---|---| | Deploy stage | Production | Deploy → Production | 48 h | | Deploy stage | Staging | Deploy → Staging | 24 h | | Nightly build | main | Nightly Build — main | 25 h | | Weekly security scan | — | Weekly Security Scan | 8 days |

Use pipeline variables or conditions to select the correct heartbeat URL per environment:

- bash: |
    if [ "$(Build.SourceBranch)" = "refs/heads/main" ]; then
      HEARTBEAT_URL="$(VIGILMON_DEPLOY_PROD_HEARTBEAT_URL)"
    else
      HEARTBEAT_URL="$(VIGILMON_DEPLOY_STAGING_HEARTBEAT_URL)"
    fi
    curl -fsS -X POST "$HEARTBEAT_URL" --max-time 10
  displayName: Ping environment heartbeat
  condition: succeeded()

Step 6: Alert Channels

In Vigilmon, go to Notifications → New Channel and configure:

  • Email — immediate alert when a heartbeat is missed
  • Slack webhook — ping your #alerts or #ci-cd channel

When a pipeline stops pinging:

🔴 MISSED HEARTBEAT: Nightly Build — main
Last ping: 26 hours ago
Expected interval: 24 hours

When it resumes:

✅ HEARTBEAT RECOVERED: Nightly Build — main
Gap: 26 hours

Step 7: Protect Against Pending Approval Gates

One failure mode unique to Azure Pipelines: deployment environments with approval gates can stall a pipeline indefinitely when an approver is on leave or the approval notification is missed. The pipeline shows as "waiting" in the UI, which can look like in-progress work rather than a stuck state.

Heartbeat monitoring covers this case automatically: if the deployment stage never completes (because it's waiting forever for approval), no ping arrives, and Vigilmon alerts you after the grace period. This surfaces the stalled approval as an incident rather than letting it silently block deployments.


Complete Step Template

Here's a reusable step you can copy into any Azure Pipelines stage:

# Add this step at the end of any job or deployment you want heartbeat monitoring on
- bash: |
    curl -fsS -X POST "$(VIGILMON_HEARTBEAT_URL)" \
      --max-time 10 \
      --retry 3 \
      --retry-delay 2
  displayName: Ping Vigilmon heartbeat
  condition: succeeded()

Replace VIGILMON_HEARTBEAT_URL with the specific variable name for that pipeline's monitor (use one heartbeat monitor per stage or deployment environment).


What You're Now Catching

| Silent failure mode | How Vigilmon detects it | |---|---| | Scheduled trigger skips run (no code changes) | No ping arrives → alert after grace period | | Pipeline paused or disabled in Azure DevOps UI | No ping arrives → alert after grace period | | Self-hosted agent offline, builds queued forever | No ping arrives → alert after grace period | | Approval gate pending indefinitely | No deployment ping → alert | | Deploy stage skipped due to branch condition | No ping on deploy stage → alert | | Deploy pipeline stopped shipping to production | Deploy heartbeat missed → alert |


Azure Pipelines is reliable — until it quietly stops working. Vigilmon's heartbeat monitors give you the external signal that Azure DevOps itself can't provide: a definitive alert when your CI/CD pipeline hasn't run in longer than expected.

Add heartbeat monitoring to your Azure Pipelines today — register free at vigilmon.online.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →