tutorial

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

Use Vigilmon heartbeat monitors to detect silent AppVeyor failures — scheduled build drift, stuck Windows jobs, and pipelines that stop running entirely.

Your nightly Windows build stopped running three weeks ago. Nobody noticed until a customer reported a broken installer. AppVeyor had no errors to report — the scheduled build 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 build 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 AppVeyor pipelines with Vigilmon heartbeat monitors to catch failures before your team does.

What You'll Cover

  • Heartbeat monitoring for scheduled AppVeyor builds
  • Catching Windows CI builds that stop triggering entirely
  • Alerting on long-running or stuck jobs
  • Multi-environment monitoring (staging and production artifacts)
  • Detecting scheduled build drift on Windows CI

Prerequisites

  • An AppVeyor project with at least one build configuration
  • A free account at vigilmon.online

The Problem: What Standard AppVeyor Monitoring Misses

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

  • A scheduled build trigger is disabled in the AppVeyor UI
  • A on_success deploy step silently skips because a condition isn't met
  • An artifact upload succeeds but the publish step to your package feed is skipped
  • AppVeyor's Windows build queue is congested and a scheduled run is dropped

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 Windows Build — master.
  3. Set the Expected interval to match your build 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 Build

Store the heartbeat URL as an AppVeyor encrypted environment variable. In your project on appveyor.com, go to Settings → Environment → Add variable:

  • Name: VIGILMON_NIGHTLY_HEARTBEAT_URL
  • Value: the ping URL from Step 1
  • Check Encrypt to mask it in build logs

Here's a complete appveyor.yml example with Vigilmon instrumentation using PowerShell:

# appveyor.yml
image: Visual Studio 2022

environment:
  VIGILMON_NIGHTLY_HEARTBEAT_URL:
    secure: <your-encrypted-value-here>

build_script:
  - msbuild MyApp.sln /configuration:Release

test_script:
  - vstest.console MyApp.Tests\bin\Release\MyApp.Tests.dll

on_success:
  - ps: |
      Invoke-WebRequest -Uri $env:VIGILMON_NIGHTLY_HEARTBEAT_URL `
        -Method POST `
        -UseBasicParsing `
        -TimeoutSec 10 | Out-Null

Alternatively, use curl if it is available on your build image:

on_success:
  - curl -fsS -X POST "%VIGILMON_NIGHTLY_HEARTBEAT_URL%" --max-time 10 --retry 3 --retry-delay 2

Key points about this setup:

  • on_success — this block only runs when all build_script and test_script steps exit successfully. If tests fail, on_success is skipped and no ping is sent.
  • UseBasicParsing — avoids IE engine dependency on headless Windows Server.
  • | Out-Null — suppresses response body output in the build log.

Step 3: Monitor Your Deployment Pipeline

Heartbeats are even more valuable for deployment pipelines — a silently stuck NuGet publish or installer release leaves your users on stale versions.

# appveyor.yml (with deployment)
image: Visual Studio 2022

environment:
  VIGILMON_DEPLOY_PROD_HEARTBEAT_URL:
    secure: <your-encrypted-value-here>

build_script:
  - msbuild MyApp.sln /configuration:Release /p:Platform=x64

test_script:
  - vstest.console MyApp.Tests\bin\Release\x64\MyApp.Tests.dll

after_test:
  - cmd: 7z a MyApp-installer.zip .\MyApp\bin\Release\x64\*

deploy:
  - provider: NuGet
    api_key:
      secure: <your-nuget-key>
    on:
      branch: master
      appveyor_repo_tag: true

on_success:
  - ps: |
      Invoke-WebRequest -Uri $env:VIGILMON_DEPLOY_PROD_HEARTBEAT_URL `
        -Method POST `
        -UseBasicParsing `
        -TimeoutSec 10 | Out-Null

Create a separate heartbeat monitor for deployment builds with an interval of 48 hours (or however often you expect to release). If no successful release is published within that window, Vigilmon pages you.


Step 4: Detect Scheduled Build Drift

AppVeyor supports Scheduled builds configured in the project settings UI. These scheduled runs are fragile: if a project is deactivated or the schedule is removed, builds stop firing silently. There's no built-in alerting for a schedule that just disappears.

Vigilmon's heartbeat monitor catches this automatically — if the scheduled build misses a run for any reason, no ping arrives, and you get alerted.

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

on_success:
  - ps: |
      $body = @{
        project  = $env:APPVEYOR_PROJECT_SLUG
        build_id = $env:APPVEYOR_BUILD_ID
        branch   = $env:APPVEYOR_REPO_BRANCH
      } | ConvertTo-Json -Compress
      Invoke-WebRequest -Uri $env:VIGILMON_NIGHTLY_HEARTBEAT_URL `
        -Method POST `
        -Body $body `
        -ContentType "application/json" `
        -UseBasicParsing `
        -TimeoutSec 10 | Out-Null

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 release pipelines, create one heartbeat monitor per environment:

| Build type | Environment | Monitor name | Interval | |---|---|---|---| | Tagged release build | Production | Release Build → Production | 48 h | | Branch build | Staging | Build → Staging | 24 h | | Nightly installer | master | Nightly Windows Build — master | 25 h | | Weekly code signing | — | Weekly Code Sign | 8 days |

Use conditional logic to select the correct heartbeat URL per branch:

on_success:
  - ps: |
      if ($env:APPVEYOR_REPO_TAG -eq "true") {
        $url = $env:VIGILMON_RELEASE_HEARTBEAT_URL
      } else {
        $url = $env:VIGILMON_STAGING_HEARTBEAT_URL
      }
      Invoke-WebRequest -Uri $url -Method POST -UseBasicParsing -TimeoutSec 10 | Out-Null

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 build stops pinging:

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

When it resumes:

✅ HEARTBEAT RECOVERED: Nightly Windows Build — master
Gap: 26 hours

Step 7: Protect Against NuGet Publish Silently Stopping

One failure mode unique to Windows CI: a NuGet publish or artifact upload can silently succeed without actually reaching the feed (e.g., version already exists, wrong API endpoint, feed quota hit). The deploy block exits 0 and on_success still fires — but no package was published.

For this scenario, add a separate heartbeat that verifies the artifact exists downstream rather than just pinging at the end of the on_success block. But at minimum, the heartbeat pattern still catches the case where the build stops running entirely.


Complete Build Template

Here's a reusable snippet you can copy into any appveyor.yml:

# Add this to any build you want heartbeat monitoring on
on_success:
  - ps: |
      Invoke-WebRequest -Uri $env:VIGILMON_HEARTBEAT_URL `
        -Method POST `
        -UseBasicParsing `
        -TimeoutSec 10 | Out-Null

Or using curl (cross-platform images):

on_success:
  - curl -fsS -X POST "%VIGILMON_HEARTBEAT_URL%" --max-time 10 --retry 3 --retry-delay 2

Replace VIGILMON_HEARTBEAT_URL with the specific environment variable name for that build's monitor (use one heartbeat monitor per build configuration).


What You're Now Catching

| Silent failure mode | How Vigilmon detects it | |---|---| | Scheduled AppVeyor build disabled or deleted | No ping arrives → alert after grace period | | Project deactivated, builds stopped queuing | No ping arrives → alert after grace period | | Deploy block skipped due to branch condition | No ping on deploy build → alert | | Build hung on MSBuild or test runner | Build timeout → no ping → alert | | NuGet publish succeeds but package feed stale | Heartbeat interval reveals missing releases | | Windows build queue congestion drops scheduled run | No ping on missed run → alert |


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

Add heartbeat monitoring to your AppVeyor builds 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 →