BLOG/TEAM CI/CD
THEME
TEAM CI/CD

Scheduled CI jobs and nightly pipelines

The nightly build is the most fragile job you own — it only runs when you're asleep, so it breaks in silence. Keep the cron in your runner, but make the work a workflow you can run by hand and always get a report from.

May 20, 2026 OrchStep Team 5 minROLE: DevOps EngineerSCALE: Any
RUNNABLE DEMO
Full source for this post: blog/scheduled-nightly-pipeline
VIEW SOURCE

The nightly pipeline is the job you trust the least. It only runs at 2am, so when it breaks it breaks in silence, and you find out three days later that the last green nightly was Tuesday. The logic is usually trapped inside a scheduled CI definition you can't run on your laptop — so debugging a nightly means pushing a commit, waiting for the cron, and reading job logs the next morning.

The split that fixes this: let your CI runner own the schedule, but put the work in a workflow you can run by hand. The cron becomes a one-liner that calls OrchStep; everything it does is local, runnable, and previewable.

The work the schedule triggers

orchstep.yml
name: nightly
# The pipeline a nightly schedule calls. The cron lives in your CI runner;
# this is the work it triggers, plus a summary that always runs.
defaults:
  run_id: "nightly"

tasks:
  # `orchstep run nightly`
  nightly:
    steps:
      - name: fetch
        func: shell
        do: echo "pulling latest main for the {{ vars.run_id }} build"

      - name: build
        func: shell
        do: echo "building the {{ vars.run_id }} artifact"

      - name: regression
        func: shell
        do: echo "running the full regression suite"
        retry:
          max_attempts: 2
          interval: "1s"

      - name: report
        func: shell
        do: echo "{{ vars.run_id }} pipeline complete"
        finally:
          - name: summary
            func: shell
            do: echo "posting the {{ vars.run_id }} summary to the team channel"

The win is in the last step. Its finally: block runs whether the regression passed or blew up — so the team channel gets a summary every single night. A nightly that fails silently is the dangerous one; a nightly that always reports, pass or fail, is just information.

- name: report
  func: shell
  do: echo "{{ vars.run_id }} pipeline complete"
  finally:
    - name: summary
      func: shell
      do: echo "posting the {{ vars.run_id }} summary to the team channel"

The regression step gets a small retry so a single flaky run doesn't page anyone, and fetch / build / regression are your real commands once you swap out the echo.

The schedule is a one-liner

The cron stays where crons belong — in the CI runner. It installs OrchStep and calls the task. Here's the shape on GitHub Actions:

name: nightly
on:
  schedule:
    - cron: "0 2 * * *"   # 02:00 UTC every day
jobs:
  nightly:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # Manual install alternative:
      #   - run: curl -fsSL https://orchstep.dev/install.sh | sh
      #   - run: orchstep run nightly
      - uses: orchstep/run-orchstep@v1
        with:
          workflow: orchstep.yml
          task: nightly

That's the entire integration. The schedule triggers; OrchStep does the work. Because the work is a plain task, the thing that runs at 2am is the same thing you run at your desk:

orchstep run nightly

No more "I can't reproduce the nightly." You are the nightly when you run that line. And before you trust it on a schedule, dry-run it to confirm the steps and order:

orchstep run nightly --dry-run

What you gained

ConcernCron-only jobOrchStep
Run it locallypush and waitorchstep run nightly
Always get a reportsilent on failurefinally: summary
Flaky regressionred nightly, pagersmall retry:
Reuse the stepstrapped in CI YAMLa task you can call
Rescheduleedit CI logicchange the cron line

OrchStep isn't a scheduler and doesn't try to be — your runner's cron is fine. It's the runnable, reportable body that the schedule calls, so the most fragile job you own stops being a black box.

Where to go next

Install with curl -fsSL https://orchstep.dev/install.sh | sh, then orchstep run nightly to run tonight's pipeline right now.

#CI#SCHEDULING#NIGHTLY#AUTOMATION
Try it in two minutes — one binary, no signup.
curl -fsSL https://orchstep.dev/install.sh | sh

RELATED — TEAM CI/CD