Run a request on a schedule
A Schedule runs one of your requests at set times, such as every day, on weekdays, or on a day of the month, at a time in your timezone. A Schedule can also run your request for every new issue of a GitHub repository, as Run a request on every new issue describes. Whenever the Schedule fires, devboxes takes the request as a new message from you in the thread where you set it up, and posts its reply there. When the request needs work in a Project, devboxes starts that work as it would for your message, and a Run started this way is billed like any other Run. Scheduled work can't take actions that need a person's approval, such as merging.
You need Chat turned on and a chat workspace connected: Slack, Microsoft Teams, Google Chat, Discord, or Telegram.
Set up a Schedule in Chat
Ask @devboxes in a channel assigned to Projects, with the request and when it should run:
@devboxes every weekday at 8:00, send me the pull requests that wait for my reviewdevboxes replies with the next fire times in your timezone. Check that they are what you meant. When devboxes doesn't know your timezone, it asks you for it.
Whenever the Schedule fires, its reply appears in the same thread. To change a Schedule, ask in that thread, for example "pause the morning briefing" or "delete the weekly report". In Chat, devboxes lists the Schedules of the current thread and changes those you set up. Issue trackers such as Linear and Jira keep no Schedules.
Set up a Schedule from the CLI
A Schedule always runs in a chat thread as you, so you set it up only in a thread where your linked chat account has written.
-
Link your chat account, as Link your chat account describes.
-
Find the thread with
devboxes invoke chat.conversations --input @organization.json. Use theidof an open conversation where you have written. Any other thread fails withTHREAD_PARTICIPANT_REQUIRED, also for owners and admins, and an unlinked chat account fails withCHAT_ACCOUNT_REQUIRED. In your own direct conversation, devboxes answers but can't start work. -
Create the Schedule:
schedule.json { "organizationId": "<organization id>", "conversationId": "<conversation id>", "title": "Competitor check", "request": "Check what our competitors shipped this week and summarize it.", "cron": "0 9 * * 1", "timezone": "Europe/Berlin" }devboxes invoke schedules.create --input @schedule.jsonThe result contains the Schedule's
id, itsnextFireAt, andnextFireTimes, the next three fire times in the Schedule's timezone.
Write the cron pattern
cron has five fields: minute, hour, day of month, month, and day of week. Sunday is 0. timezone is an IANA timezone name, and daylight saving time follows it.
| When | cron |
|---|---|
| Every day at 18:00 | 0 18 * * * |
| Weekdays at 8:00 | 0 8 * * 1-5 |
| Mondays and Thursdays at 9:30 | 30 9 * * 1,4 |
| Monthly on the 1st at 9:00 | 0 9 1 * * |
| The first Monday of the month at 9:00 | 0 9 * * 1#1 |
| The first and third Wednesday of the month at 9:00 | 0 9 * * 3#1,3#3 |
| The last Friday of the month at 9:00 | 0 9 * * 5#L |
| The last weekday of the month at 9:00 | 0 9 LW * * |
A Schedule fires on the hour, or at quarter past, half past, or quarter to. devboxes refuses a pattern with any other minute with SCHEDULE_INVALID. When a pattern names both a day of month and a day of week, it fires on either; to require both, put + before the day of week, as in 0 9 1-7 * +1. A Schedule on the 31st fires only in months that have a 31st. A weekday Schedule also fires on public holidays.
For every other Monday at 9:00, add "biweekly": true to the pattern 0 9 * * 1. A biweekly Schedule fires only in every second calendar week: the weeks whose ISO week number is even, or odd, like the week of its first fire.
Run a request on every new issue
A Schedule can fire on new GitHub issues in place of a cron pattern. Whenever someone opens an issue in the GitHub repository bound to a Project, devboxes takes your request as a new message from you in the thread. The message ends with the issue's link and the reporter's title and description, quoted as the reporter's words. Give the Schedule a label, such as bug, and it fires only for new issues with that label, including issues that get the label after they open. A Schedule fires once per issue.
The Project needs a GitHub repository bound with issues.configure, as Connect GitHub Issues describes, and the thread's channel must be assigned to that Project. Otherwise schedules.create fails with SCHEDULE_ISSUES_UNSUPPORTED or SCHEDULE_PROJECT_UNROUTED. The issue's author needs no devboxes account: the work runs as you, and every issue's work is billed like any other Run. A burst of new issues starts one Run per issue, and managed work starts only while your Organization has money left, as How managed work is charged describes.
@devboxes whenever someone opens an issue labelled bug in acme/app, reproduce itFrom the CLI, put issues in place of cron and timezone:
{
"organizationId": "<organization id>",
"conversationId": "<conversation id>",
"title": "Reproduce bug reports",
"request": "Reproduce this bug report.",
"issues": { "projectId": "<project id>", "label": "bug", "blueprint": "Reproduce a bug report" }
}blueprint names the Blueprint that the issue's work uses. It can't be a Blueprint that publishes a pull request: schedules.create refuses one with SCHEDULE_BLUEPRINT_PUBLISHES. The work that a new issue starts, with every reply, continuation and follow-up task that comes from that work, is linked to the issue and keeps to these rules, also when a person continues it from the CLI or the dashboard:
- It may post the code and files your request asks for, such as a reproduction script.
- It may comment on that issue and change the issue's labels. Writing to any other issue fails with
ISSUE_NOT_AUTHORIZED. - It may start only the Blueprint that the Schedule names, in the Schedule's Project. Another Blueprint fails with
BLUEPRINT_NOT_AUTHORIZED, and another Project withPROJECT_NOT_AUTHORIZED. - It may follow up only on the work that the issue started. Another Session fails with
SESSION_NOT_AUTHORIZED. - It may read issues and reply in its thread, and post files only there. Any other command, such as
issues.configureorschedules.create, fails withISSUE_WORK_FORBIDDEN. - Its replies start fresh: they don't read the thread's earlier conversation, and later replies in the thread don't read theirs or report its results.
schedules.run refuses a Schedule on new issues with SCHEDULE_FIRES_ON_ISSUES, because only a new issue fires it.
Manage Schedules
| Operation | Input | Result |
|---|---|---|
schedules.list | organizationId | Every Schedule of the Organization, with nextFireAt, lastOutcome, and pausedReason. |
schedules.pause | organizationId, scheduleId | The Schedule stops firing. |
schedules.resume | organizationId, scheduleId | The Schedule fires again from its next fire time. Fire times it missed don't fire. A Schedule on new issues fires for issues opened after it resumes. |
schedules.run | organizationId, scheduleId | The request runs once now. The next fire time stays as it was. When the previous fire's reply is still queued, that reply starts instead. A Schedule on new issues fails with SCHEDULE_FIRES_ON_ISSUES. |
schedules.delete | organizationId, scheduleId | The Schedule is deleted. Replies and work it started stay in the thread. |
The person who set up a Schedule changes it. An owner or admin changes any Schedule of the Organization. An Organization has at most 50 Schedules that are not paused; one more fails with SCHEDULE_LIMIT_REACHED.
What happens at a fire time
lastOutcome in schedules.list shows what the latest fire time did:
started: devboxes posted the request in the thread.skipped: the previous fire's reply was still waiting or running, or work it started was still running, so devboxes didn't post the request again. A reply that was still waiting starts then. The next fire time runs as usual. A Schedule on new issues fires once per matching issue, so its outcome is neverskipped.refused: the thread no longer accepts the request, and the Schedule is paused.pausedReasonsays why: the thread was closed, Chat was turned off, your chat account was unlinked, or the chat workspace refused the previous reply, as it does when someone deletes the channel. Fix the cause, then resume the Schedule. If a Schedule's timing can no longer be read, devboxes pauses it and says why. Delete it and set it up again.
Erasing a conversation deletes its Schedules. When devboxes was unavailable at a fire time, the Schedule fires once when devboxes is back, and then continues at its next fire time.