|
1 |
| -<img src="https://storage.googleapis.com/cheek-scheduler/cheek-64.png" alt="cheek" /> |
| 1 | +<img src="docs/static/cheek-v2.svg" alt="cheek" /> |
2 | 2 |
|
3 | 3 | # cheek
|
4 | 4 |
|
5 | 5 | 
|
6 |
| -[](https://dataroots.io/) [](https://codecov.io/gh/datarootsio/cheek) |
7 | 6 | 
|
8 | 7 | [](https://goreportcard.com/report/github.com/datarootsio/cheek)
|
9 | 8 | [](https://pkg.go.dev/github.com/datarootsio/cheek)
|
|
12 | 11 |
|
13 | 12 | `cheek` is a pico-sized declarative job scheduler designed to excel in a single-node environment. `cheek` aims to be lightweight, stand-alone and simple. It does not compete for robustness.
|
14 | 13 |
|
15 |
| -> 📄 This bump to v1 introduces a storage backend switch, moving from jsonline logs to sqlite. This might introduce the need to adjust your long-term log storage approach. |
| 14 | +## Quick Start |
16 | 15 |
|
17 |
| -## Getting started |
18 |
| - |
19 |
| -Fetch the latest version for your system below. |
| 16 | +Fetch the latest version for your system: |
20 | 17 |
|
21 | 18 | [darwin-arm64](https://github.com/datarootsio/cheek/releases/latest/download/cheek-darwin-arm64) |
|
22 | 19 | [darwin-amd64](https://github.com/datarootsio/cheek/releases/latest/download/cheek-darwin-amd64) |
|
23 | 20 | [linux-386](https://github.com/datarootsio/cheek/releases/latest/download/cheek-linux-386) |
|
24 | 21 | [linux-arm64](https://github.com/datarootsio/cheek/releases/latest/download/cheek-linux-arm64) |
|
25 | 22 | [linux-amd64](https://github.com/datarootsio/cheek/releases/latest/download/cheek-linux-amd64)
|
26 | 23 |
|
27 |
| -You can (for example) fetch it like below, make it executable and run it. Optionally put `cheek` on your `PATH`. |
28 |
| - |
29 | 24 | ```sh
|
30 | 25 | curl -L https://github.com/datarootsio/cheek/releases/latest/download/cheek-darwin-amd64 -o cheek
|
31 | 26 | chmod +x cheek
|
32 |
| -./cheek |
33 |
| -``` |
34 |
| - |
35 |
| -Everything about how you want the scheduler to function is defined in a schedule specification written in YAML. Start by creating this specification using the below example. Note, this structure should be more or less self-explanatory, if it is not, create an [issue](https://github.com/datarootsio/cheek/issues). |
36 |
| - |
37 |
| -```yaml |
38 |
| -tz_location: Europe/Brussels # optionally set timezone to adhere to |
39 |
| -jobs: |
40 |
| - foo: |
41 |
| - command: date |
42 |
| - cron: "* * * * *" # a cron string to specify when to run |
43 |
| - on_success: |
44 |
| - trigger_job: # trigger something on run |
45 |
| - - bar |
46 |
| - bar: |
47 |
| - command: # command to run, use a list if you want to pass args |
48 |
| - - echo |
49 |
| - - $foo |
50 |
| - env: # you can pass env variables |
51 |
| - foo: bar |
52 |
| - other_workingdir: |
53 |
| - command: pwd |
54 |
| - working_directory: ../testdata # specify the working directory of the job |
55 |
| - coffee: |
56 |
| - command: this fails |
57 |
| - cron: "* * * * *" |
58 |
| - retries: 3 |
59 |
| - disable_concurrent_execution: true # prevent concurrent runs of this job (defaults to false) |
60 |
| - on_error: |
61 |
| - notify_webhook: # notify something on error |
62 |
| - - https://webhook.site/4b732eb4-ba10-4a84-8f6b-30167b2f2762 |
63 |
| - notify_slack_webhook: # notify slack via a slack compatible webhook |
64 |
| - - https://webhook.site/048ff47f-9ef5-43fb-9375-a795a8c5cbf5 |
65 |
| - notify_discord_webhook: # notify discord via a discord compatible webhook |
66 |
| - - https://discord.com/api/webhooks/user/token |
67 |
| -``` |
68 |
| -
|
69 |
| -If your `command` requires arguments, please make sure to pass them as an array like in `foo_job`. |
70 |
| - |
71 |
| -Note that you can set `tz_location` if the system time of where you run your service is not to your liking. |
72 |
| - |
73 |
| -## Scheduler |
74 |
| - |
75 |
| -The core of `cheek` consists of a scheduler that uses the schedule specs defined in your `yaml` file to trigger jobs when they are due. |
76 |
| - |
77 |
| -You can launch the scheduler via: |
78 |
| - |
79 |
| -```sh |
80 |
| -cheek run ./path/to/my-schedule.yaml |
81 |
| -``` |
82 |
| - |
83 |
| -Check out `cheek run --help` for configuration options. |
84 |
| - |
85 |
| -## Web UI |
86 |
| - |
87 |
| -`cheek` ships with a web UI that by default gets launched on port `8081`. You can define the port on which it is accessible via the `--port` flag. |
88 |
| - |
89 |
| - |
90 |
| - |
91 |
| - |
92 |
| - |
93 |
| -You can access the UI by navigating to `http://localhost:8081`. When `cheek` is deployed you are recommended to NOT make this port publicly accessible, instead navigate to the UI via an SSH tunnel. |
94 |
| - |
95 |
| -The UI allows to get a quick overview on jobs that have run, that error'd and their logs. It basically does this by fetching the state of the scheduler and by reading the logs that (per job) get written to `$HOME/.cheek/`. Note that you can ignore these logs, output of jobs will always go to stdout as well. |
96 |
| - |
97 |
| -Note, `cheek` prior to version `0.3.0` originally used to boast a TUI, which has since been removed. |
98 |
| - |
99 |
| -## Configuration |
100 |
| - |
101 |
| -All configuration options are available by checking out `cheek --help` or the help of its subcommands (e.g. `cheek run --help`). |
102 |
| - |
103 |
| -Configuration can be passed as flags to the `cheek` CLI directly. All configuration flags are also possible to set via environment variables. The following environment variables are available, they will override the default and/or set value of their similarly named CLI flags (without the prefix): `CHEEK_PORT`, `CHEEK_SUPPRESSLOGS`, `CHEEK_LOGLEVEL`, `CHEEK_PRETTY`, `CHEEK_HOMEDIR`. |
104 |
| - |
105 |
| -## Events & Notifications |
106 |
| - |
107 |
| -There are three types of event you can hook into: `on_success`, `on_error`, and `on_retries_exhausted`. The first two events materialize after an (attempted) job run, while `on_retries_exhausted` fires only once when a job with retries configured fails all attempts. Three types of actions can be taken as a response: `notify_webhook`, `notify_slack_webhook`, `notify_discord_webhook` and `trigger_job`. See the example below. Definition of these event actions can be done on job level or at schedule level, in the latter case it will apply to all jobs. |
108 |
| - |
109 |
| -```yaml |
110 |
| -on_success: |
111 |
| - notify_webhook: |
112 |
| - - https://webhook.site/e33464a3-1a4f-4f1a-99d3-743364c6b10f |
113 |
| -jobs: |
114 |
| - coffee: |
115 |
| - command: this fails # this will create on_error event |
116 |
| - cron: "* * * * *" |
117 |
| - retries: 3 # retry up to 3 times before giving up |
118 |
| - on_error: |
119 |
| - notify_webhook: # fires after each failed attempt |
120 |
| - - https://webhook.site/e33464a3-1a4f-4f1a-99d3-743364c6b10f |
121 |
| - on_retries_exhausted: |
122 |
| - trigger_job: # only fires once when all retries fail |
123 |
| - - cleanup_job |
124 |
| - notify_webhook: |
125 |
| - - https://webhook.site/critical-alerts |
126 |
| - beans: |
127 |
| - command: echo grind # this will create on_success event |
128 |
| - cron: "* * * * *" |
129 |
| -``` |
130 |
| - |
131 |
| -Webhooks are a generic way to push notifications to a plethora of tools. There is a generic way to do this via the `notify_webhook` option or a Slack-compatible one via `notify_slack_webhook` or a Discord-compatible one via `notify_discord_webhook`. |
132 |
| - |
133 |
| -The `notify_webhook` sends a JSON payload to your webhook url with the following structure: |
134 |
| - |
135 |
| -```json |
136 |
| -{ |
137 |
| - "status": 0, |
138 |
| - "log": "I'm a teapot, not a coffee machine!", |
139 |
| - "name": "TeapotTask", |
140 |
| - "triggered_at": "2023-04-01T12:00:00Z", |
141 |
| - "triggered_by": "CoffeeRequestButton", |
142 |
| - "triggered": ["CoffeeMachine"], // this job triggered another one |
143 |
| - "retry_attempt": 2, // which retry attempt this was (0 = first attempt) |
144 |
| - "retries_exhausted": true, // true when all retries have been exhausted |
145 |
| - "triggered_by_job_run": { // parent job context when triggered by another job |
146 |
| - "status": 0, |
147 |
| - "log": "Parent job completed successfully", |
148 |
| - "name": "ParentJob", |
149 |
| - "triggered_at": "2023-04-01T11:59:00Z", |
150 |
| - "triggered_by": "cron" |
151 |
| - } |
152 |
| -} |
153 |
| -``` |
154 |
| - |
155 |
| -When a job is triggered by another job via `trigger_job`, the webhook payload includes a `triggered_by_job_run` field containing the complete context of the parent job that triggered it. This provides full visibility into the job execution chain and allows for more sophisticated workflow tracking and debugging. |
156 |
| - |
157 |
| -The `notify_slack_webhook` sends a JSON payload to your Slack webhook url with the following structure (which is Slack app compatible): |
158 |
| - |
159 |
| -```json |
160 |
| -{ |
161 |
| - "text": "TeapotTask (exitcode 0):\nI'm a teapot, not a coffee machine!" |
162 |
| -} |
| 27 | +./cheek run schedule.yaml |
163 | 28 | ```
|
164 | 29 |
|
165 |
| -The `notify_discord_webhook` sends a JSON payload to your Discord webhook url with the following structure (which is Discord app compatible): |
166 |
| - |
167 |
| -```json |
168 |
| -{ |
169 |
| - "content": "TeapotTask (exitcode 0):\nI'm a teapot, not a coffee machine!" |
170 |
| -} |
171 |
| -``` |
172 |
| - |
173 |
| -## Job Execution Flow |
174 |
| - |
175 |
| -The following diagram illustrates how jobs flow from schedule to execution and how events trigger subsequent actions: |
176 |
| - |
177 |
| -```mermaid |
178 |
| -graph TD |
179 |
| - A[Schedule YAML] --> B[Job Specs] |
180 |
| - |
181 |
| - B --> C[Cron Schedule] |
182 |
| - |
183 |
| - C --> D[JobRun Execution] |
184 |
| - F[Manual Trigger] --> D |
185 |
| - G[Job Trigger] --> D |
186 |
| - |
187 |
| - D --> H{Job Success?} |
188 |
| - |
189 |
| - H -->|Yes| I[on_success Events] |
190 |
| - H -->|No| J{Retries Left?} |
191 |
| - |
192 |
| - J -->|Yes| K[Retry After Delay] |
193 |
| - J -->|No| L[on_retries_exhausted Events] |
194 |
| - |
195 |
| - K --> D |
196 |
| - H -->|No| M[on_error Events] |
197 |
| - |
198 |
| - I --> N[Event Actions] |
199 |
| - M --> N |
200 |
| - L --> N |
201 |
| - |
202 |
| - N --> O[trigger_job] |
203 |
| - N --> P["notify_{type}_webhook"] |
204 |
| - |
205 |
| - O --> Q[New JobRun] |
206 |
| - Q --> R[Parent Context Added] |
207 |
| - R --> S[triggered_by_job_run field populated] |
208 |
| - |
209 |
| - P --> T[Webhook Payload] |
210 |
| - T --> U[Includes parent job data if triggered by job] |
211 |
| - |
212 |
| - G -.-> Q |
213 |
| - S -.-> D |
214 |
| - |
215 |
| - style A fill:#e1f5fe |
216 |
| - style B fill:#e3f2fd |
217 |
| - style D fill:#f3e5f5 |
218 |
| - style Q fill:#f3e5f5 |
219 |
| - style R fill:#e8f5e8 |
220 |
| - style T fill:#fff3e0 |
221 |
| - style U fill:#fff3e0 |
222 |
| -``` |
223 |
| - |
224 |
| -## Docker |
225 |
| - |
226 |
| -Check out the `Dockerfile.example` for an example on how to use `cheek` within the context of a Docker container. Note that this builds upon a published Ubuntu-based image build that you can find in the base [Dockerfile](https://github.com/datarootsio/cheek/blob/main/Dockerfile). |
227 |
| - |
228 |
| -Prebuilt images are available at `ghcr.io/datarootsio/cheek:latest` where `latest` can be replaced by a version tag. Check out the [available images](https://github.com/datarootsio/cheek/pkgs/container/cheek) for an overview on available tags. |
229 |
| - |
230 |
| -## Available versions |
231 |
| - |
232 |
| -If you want to pin your setup to a specific version of `cheek` you can use the following template to fetch your `cheek` binary: |
233 |
| - |
234 |
| -- latest version: https://github.com/datarootsio/cheek/releases/latest/download/cheek-{os}-{arch} |
235 |
| -- tagged version: https://github.com/datarootsio/cheek/releases/download/{tag}/cheek-{os}-{arch} |
| 30 | +## Documentation |
236 | 31 |
|
237 |
| -Where: |
| 32 | +For comprehensive documentation, configuration options, examples, and advanced features, visit: |
238 | 33 |
|
239 |
| -- `os` is one of `linux`, `darwin` |
240 |
| -- `arch` is one of `amd64`, `arm64`, `386` |
241 |
| -- `tag` is one the [available tags](https://github.com/datarootsio/cheek/tags) |
| 34 | +**📚 [cheek.barts.space](https://cheek.barts.space)** |
242 | 35 |
|
243 | 36 | ## Acknowledgements
|
244 | 37 |
|
245 |
| -`cheek` is building on top of many great OSS assets. Noteable thanks goes to: |
| 38 | +`cheek` is building on top of many great OSS assets. Notable thanks goes to: |
246 | 39 |
|
247 | 40 | - [gronx](https://github.com/adhocore/gronx): for allowing me not to worry about CRON strings.
|
248 | 41 |
|
|
0 commit comments