Skip to content

Scheduling

Arian Omrani edited this page Oct 11, 2026 · 6 revisions

Scheduling

Language: English · فارسی

pulsecheck runs once and exits. Something else starts it every few minutes. Pick one.

GitHub Actions

The quickest way is the minimal template, arian24b/pulsecheck-template. It has only four files: pulsecheck.yml, one workflow, a short README and a .gitignore. The workflow installs pulsecheckcli from PyPI, so no source code is copied into your repository.

  1. Click Use this template → Create a new repository, and choose Private (your pulsecheck.yml lists your hosts).
  2. Edit pulsecheck.yml: put your sites under sites: and keep tokens as ${VARS}.
  3. Add each variable as a secret (Settings → Secrets and variables → Actions) and list it under env: in .github/workflows/monitor.yml. The template already lists TG_TOKEN and TG_CHAT.
  4. Run it once with Actions → monitor → Run workflow.

Notes

  • The workflow runs every 5 minutes. In the template repository itself it only runs when started by hand, so your copy is the only one that is scheduled.
  • It installs pulsecheckcli>=0.1,<1 with uvx on every run. To pin an exact version, change PULSECHECK: in the workflow's env:.
  • shoutrrr runs from its docker image (Docker is preinstalled on GitHub's Ubuntu runners), so there is nothing to install.
  • The workflow also writes pulsecheck status --md to the run summary, so each run shows the current state without a dashboard.
  • State is stored with actions/cache (restored from the newest entry, saved after each run). No commits are made.
  • GitHub may delay scheduled runs by several minutes and disables schedules in repositories with no activity for 60 days.
  • The main pulsecheck repository also contains a monitor.yml that uses the checked-out source (uv run); use it only if you cloned the whole project.

If the schedule never fires: use an external cron

GitHub's own schedule trigger is best effort. New or quiet repositories may get no scheduled runs for hours, and */5 runs are often delayed or skipped. The template's workflow also accepts repository_dispatch (event type pulsecheck), so any external scheduler (cron-job.org, a server's crontab, Cloudflare Cron) can start it:

curl -X POST \
  -H "Authorization: Bearer $GITHUB_PAT" \
  -H "Accept: application/vnd.github+json" \
  https://api.github.com/repos/OWNER/REPO/dispatches \
  -d '{"event_type":"pulsecheck"}'

The token needs repo scope (classic) or Contents: write (fine-grained, that repository only). Run it every 5 minutes; concurrency: monitor stops overlapping runs. You can keep the built-in schedule as well.

GitLab CI

  1. Push the repository to GitLab and commit your pulsecheck.yml.
  2. Build → Pipeline schedules → New schedule, cron */5 * * * *.
  3. The job image has no Docker, so shoutrrr_bin: auto uses the binary the job downloads (SHOUTRRR_VERSION in .gitlab-ci.yml).
  4. Settings → CI/CD → Variables: add every ${VAR} your file uses (mask the secrets).
  5. The job only runs for scheduled pipelines and caches pulsecheck.db under one key. If your runners do not share a cache, state is lost between runs (see Troubleshooting).

Vercel and Cloudflare Workers

Both have their own cron and their own limits (Vercel Hobby: one run per day; Cloudflare Free: 10 ms CPU per run). Setup and every limit are on the Serverless page.

Linux cron

The easy way: pulsecheck init adds the cron job for you (see Commands). By hand, in crontab -e:

# crontab -e
*/5 * * * * PATH="$HOME/.local/bin:/usr/local/bin:/usr/bin:/bin" flock -n /tmp/pulsecheck.lock pulsecheck run >> $HOME/pulsecheck.log 2>&1

pulsecheck finds ~/.config/pulsecheck/pulsecheck.yml and the .env file next to it, so no secrets go into the crontab. State lives in state_file on disk. flock -n prevents overlapping runs.

Clone this wiki locally