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)"
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
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)