Removes 5-second wait in autobuild.executor unit tests:
- Adds a write-only channel to Executor and plumbs through to unit tests
- Modifies runOnce to return an executor.RunStats struct and write to statsCh if not nil
* Adds a `bump` command to extend workspace build deadline
* Reduces WARN-level logging spam from autobuild executor
* Modifies `cli/ssh` notifications to read from workspace build deadline and to notify relative time instead (sidestepping the problem of figuring out a user's timezone across multiple OSes)
* Shows workspace extension time in `coder list` output e.g.
```
WORKSPACE TEMPLATE STATUS LAST BUILT OUTDATED AUTOSTART TTL
developer/test1 docker Running 4m false 0 9 * * MON-FRI 15m (+5m)
```
* Adds deadline column to workspace_builds, associated DB/API plumbing
* database: Upon inserting a row into workspace_builds, deadline will
initially be zero.
* autobuild: Executor now checks the Deadline field of the workspace_build
for the purpose of autostop logic.
* coderd: Adds a new route /api/v2/workspaces/:workspace/extend which allows
updating the deadline of the currently active workspace build. The new
deadline must be after the existing deadline, and not the zero time.
* provisionerd: updates workspace_build.deadline upon successful workspace
build completion (equal to now plus workspace TTL, if it exists).
This PR adds a package lifecycle and an Executor implementation that attempts to schedule a build of workspaces with autostart configured.
- lifecycle.Executor takes a chan time.Time in its constructor (e.g. time.Tick(time.Minute))
- Whenever a value is received from this channel, it executes one iteration of looping through the workspaces and triggering lifecycle operations.
- When the context passed to the executor is Done, it exits.
- Only workspaces that meet the following criteria will have a lifecycle operation applied to them:
- Workspace has a valid and non-empty autostart or autostop schedule (either)
- Workspace's last build was successful
- The following transitions will be applied depending on the current workspace state:
- If the workspace is currently running, it will be stopped.
- If the workspace is currently stopped, it will be started.
- Otherwise, nothing will be done.
- Workspace builds will be created with the same parameters and template version as the last successful build (for example, template version)