When you need this
A red workflow is visible in GitHub. A run that never existed is harder to notice. GitHub documents that schedule events can be delayed or dropped under load. An external monitor expects a result whether or not Actions created a run.
How to connect
- 1
Create a monitor for 0 2 * * * in UTC, or put your own schedule in both the YAML and monitor.
- 2
Save the ping URL in an Actions secret named TICKWATCH_URL. The workflow must be present on the default branch.
- 3
Replace ./job.sh with your command, run the workflow manually to verify it and allow for schedule delays.
Ready-to-use example
This example uses a Linux runner with Bash and curl. Store TICKWATCH_URL in secrets, not repository code. Use a separate monitor for each independent job.
name: Scheduled job
on:
workflow_dispatch:
schedule:
- cron: '0 2 * * *' # UTC; match the schedule in TickWatch.
jobs:
job:
runs-on: ubuntu-latest
env:
TICKWATCH_URL: ${{ secrets.TICKWATCH_URL }}
steps:
- uses: actions/checkout@v4
- name: Signal start
id: monitor
shell: bash
run: |
RID=$(cat /proc/sys/kernel/random/uuid)
echo "rid=$RID" >> "$GITHUB_OUTPUT"
curl -fsS --connect-timeout 3 --max-time 5 --retry 2 --retry-max-time 12 \
-X POST "$TICKWATCH_URL/start?rid=$RID" >/dev/null 2>&1 || true
- name: Run job
id: task
run: ./job.sh
- name: Signal result
if: ${{ always() && steps.monitor.outputs.rid != '' }}
env:
RID: ${{ steps.monitor.outputs.rid }}
RESULT: ${{ steps.task.outcome }}
shell: bash
run: |
suffix=fail
if [ "$RESULT" = success ]; then suffix=""; fi
curl -fsS --connect-timeout 3 --max-time 5 --retry 2 --retry-max-time 12 \
-X POST "$TICKWATCH_URL/$suffix?rid=$RID" >/dev/null 2>&1 || trueCheck before going live
Do not allow only a few seconds of grace: schedule is not an exact-time guarantee. Measure normal scheduling delays and workflow duration.
Cancellation or runner loss can prevent the final step from running. A missing completion is still checked against the deadline or runtime limit.
In public repositories, schedules can be disabled after 60 days without activity. Check the workflow state as well as its YAML.
Common questions
Why monitor this if GitHub sends failure notifications?
Failure notifications need an actual run. An external schedule also lets you detect the absence of a run.
Can monitoring downtime break my build?
The example bounds requests with timeouts and keeps their failures from changing the job step outcome. It reports steps.task.outcome.