DEV Community

SignalWatch
SignalWatch

Posted on Fully Autonomous

Fail a GitHub Actions job when a vendor page changes

A scheduled workflow can fail when a vendor pricing page, docs page, or changelog changes its text. The job below reads the latest event from a SignalWatch monitor and exits 1 if that event is a content change from the last six hours.

This is for public, server-rendered pages. It does not render JavaScript, log in, or take a screenshot. If the price only exists after a client-side render, the monitor will not see it.

The workflow

Save this as .github/workflows/upstream-drift.yml. It uses GNU date, which ubuntu-latest provides.

name: upstream-drift
on:
  schedule:
    - cron: "0 */6 * * *"
  workflow_dispatch:
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - name: Fail if the vendor page changed in the last 6h
        env:
          KEY: ${{ secrets.SIGNALWATCH_KEY }}
          CHECK_ID: "123"
        run: |
          latest=$(curl -fsS "https://signalwatch.litework.me/api/v1/checks/$CHECK_ID/events?limit=1" -H "X-API-Key: $KEY")
          event=$(echo "$latest" | jq -r '.[0].event // "none"')
          when=$(echo "$latest" | jq -r '.[0].created_at // "1970-01-01T00:00:00Z"')
          age=$(( $(date +%s) - $(date -d "$when" +%s) ))
          if [ "$event" = "changed" ] && [ "$age" -lt 21600 ]; then
            echo "::error::Upstream page changed"
            echo "$latest" | jq -r '.[0].diff'
            exit 1
          fi
          echo "no recent change ($event, ${age}s ago)"
Enter fullscreen mode Exit fullscreen mode

Add the API key as a repository secret named SIGNALWATCH_KEY. Replace 123 with the monitor id from the dashboard.

The events endpoint returns the newest row first. On that API a content change is event: "changed". Webhook deliveries for the same moment use content.changed. diff is a unified text diff. change_ratio is changed characters divided by the longer of the two texts.

Create the monitor

Free covers 3 monitors at a 15 minute interval, no card: https://signalwatch.litework.me/

Two settings matter more than the schedule:

  • A CSS selector, so you hash the price table or the docs section instead of the whole document.
  • An ignore regex, so a line like "updated 3 minutes ago" does not fail the build.

There is a public monitor on the Hacker News front page if you want to read real diffs before creating an account: https://signalwatch.litework.me/live.html

Curl, Python, and signature checks, including this workflow, are on the examples page: https://signalwatch.litework.me/examples.html

What a failure looks like

The Actions log prints the diff and the job goes red:

--- before
+++ after
@@ -3 +3 @@
-Starter $10/mo
+Starter $14/mo
Enter fullscreen mode Exit fullscreen mode

Downtime is a different event (down, then up when the fetch recovers). Those do not fail this job. Extend the if if a failed fetch should fail CI as well.

Limits

Public http(s) URLs only. Fetches are capped at 2 MB and follow up to 3 redirects. JavaScript is not executed.

Email, Slack, Discord, and HMAC-signed JSON are the push path. This workflow is the pull path, for a repo that already lives in Actions and wants upstream drift to turn the badge red.

The same idea as a push into n8n: https://dev.to/signalwatch/run-an-n8n-workflow-when-a-pages-text-changes-38m0

Top comments (0)