CI/CD · GitHub Actions

Monitor GitHub Actions scheduled workflows

Detect a scheduled workflow that never started, ran late or failed. Copy a YAML example using a ping URL secret and outcome reporting.

Free: 5 monitors, Telegram and email.

Example alert

● scheduled-workflow

The expected workflow result did not arrive by its deadline.

Open monitor

Demo data. Message appearance and fields depend on the channel and event type.

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. 1

    Create a monitor for 0 2 * * * in UTC, or put your own schedule in both the YAML and monitor.

  2. 2

    Save the ping URL in an Actions secret named TICKWATCH_URL. The workflow must be present on the default branch.

  3. 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.

.github/workflows/nightly.yml
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 || true

Check 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.

Verify your first run while the job still works

Create a monitor, insert your ping URL and check that signals and notifications arrive.

Monitor GitHub Actions scheduled workflows · Tickwatch