@mtakla/cronops 0.1.1-rc2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ # ISC License
2
+
3
+ Copyright (c) 2026 Michael Takla @ nevereven
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,391 @@
1
+ # CronOps
2
+
3
+ [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://github.com/mtakla/cronops/blob/master/LICENSE)
4
+ [![Coverage Status](https://img.shields.io/badge/coverage-95%25-green)](https://img.shields.io/badge/coverage-95%25-green)
5
+ [![Buy Me A Coffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-Donate-orange.svg)](https://www.buymeacoffee.com/nevereven)
6
+
7
+ **CronOps** is a lightweight, cron-based file management and system task scheduler for containerized environments. It automates copying, moving, archiving, and cleaning up files across mounted volumes — keeping your storage tidy, enabling seamless file exchange between containerized services, and triggering regular tasks in your development, integration or production environments.
8
+
9
+ > [!WARNING]
10
+ > Early BETA. Not recommended for use in a production environment!
11
+
12
+ ## 💡 Why CronOps?
13
+
14
+ In containerized workflows, files often accumulate in volumes: downloads, logs, temporary exports, backups. CronOps acts as your **digital janitor**, running scheduled jobs that:
15
+
16
+ - **Execute** OS commands
17
+ - **Select** files using powerful **glob patterns** and
18
+ - **delete** them on a regular basis
19
+ - **copy** or **move** them to specific target path
20
+ - **archive** them automatically using date/time bases archive name patterns
21
+ - **process** them with OS commands (e.g. awk/sed, curl, untar/unzip, ...)
22
+ - **execute** scripts on them (sh/bash/cmd/powershell/node/lua, ...)
23
+
24
+ All configured via simple, version-controllable ***.yml** based **job definition** files — no coding required.
25
+
26
+ ## Top Features
27
+
28
+ - ✅ **Cron-like scheduling** – Flexible job timing using familiar cron syntax
29
+ - ✅ **Glob-based filtering** – Precisely select source files to be processed
30
+ - ✅ **File operations** – Copy, move, delete, or archive files
31
+ - ✅ **Command execution** – Process files with OS commands or custom scripts
32
+ - ✅ **Permission management** – Change uid, gid, and file permissions on processed target files
33
+ - ✅ **Automatic cleanup** – Remove target files after a configurable retention period
34
+ - ✅ **Incremental processing** – Only process changed or new files since last run
35
+ - ✅ **Dry-run mode** – Test jobs and execute scripts safely before applying changes
36
+ - ✅ **Detailed logging** – Detailed job execution logs with stdout/stderr aggregation
37
+ - ✅ **Hot reload** – Change job configs without restarting the service
38
+ - ✅ **Admin API** – Trigger jobs, check status, pause/resume scheduling via secured REST-API
39
+ - ✅ **OpenAPI Web UI** – Interactive API documentation and execution
40
+ - ✅ **Easy setup** – Runs with zero configuration. All config via environment variables
41
+
42
+ ## Installation
43
+
44
+ ### Install & run with Docker
45
+
46
+ CronOps is built and optimized to run as a Docker container itself:
47
+
48
+ ```
49
+ docker run \
50
+ --name cronops \
51
+ -v ./config:/config \
52
+ -v /home/docker/data:/io/source \
53
+ -v /home/docker/archive:/io/target \
54
+ --restart unless-stopped \
55
+ ghcr.io/mtakla/cronops:latest
56
+ ```
57
+
58
+ The following docker volumes can be configured:
59
+
60
+ - `/config` : The exposed config directory where job configuration files and scripts are stored
61
+ - `/data/temp` : Temp directory used for dry-run mode simulations
62
+ - `/data/logs` : Directory where job logs and file history are stored
63
+ - `/io/source` : Primary source directory (CROPS_SOURCE_ROOT), referenced as `$1` in source paths
64
+ - `/io/target` : Primary target directory (CROPS_TARGET_ROOT), referenced as `$1` in target paths
65
+ - `/io/source2` : Secondary source directory (CROPS_SOURCE_2_ROOT), referenced as `$2` in source paths
66
+ - `/io/target2` : Secondary target directory (CROPS_TARGET_2_ROOT), referenced as `$2` in target paths
67
+ - `/io/source3` : Third source directory (CROPS_SOURCE_2_ROOT), referenced as `$2` in source paths
68
+ - `/io/target3` : Third target directory (CROPS_TARGET_2_ROOT), referenced as `$2` in target paths
69
+
70
+ ### Install & run with Docker compose
71
+
72
+ Create the following `compose.yaml` file:
73
+
74
+ ```yaml
75
+ services:
76
+ cronops:
77
+ image: ghcr.io/mtakla/cronops:latest
78
+ container_name: cronops
79
+ restart: unless-stopped
80
+ volumes:
81
+ - /home/docker/data:/io/source
82
+ - /home/docker/archive:/io/target
83
+ - ./config:/config
84
+ - ./temp:/data/temp
85
+ - ./logs:/data/logs
86
+ environment:
87
+ CROPS_API_KEY: 54bad6e77cf8cbc3c65ca76d127138d50e63adc29fb14450f1d60f2693b8676c # <-- change me!
88
+ TZ: Europe/UTC
89
+ ```
90
+
91
+ In same directory, type `docker compose up -d` to install and start the cronops service.
92
+
93
+ To check if the server is running, just action:
94
+
95
+ ```sh
96
+ docker logs -f cronops
97
+ ```
98
+
99
+ After your first start you should see the following output:
100
+ ```text
101
+ ____ ___
102
+ / ___| _ __ ___ _ __ / _ \ _ __ ___
103
+ | | | '__|/ _ \ | '_ \ | | | || '_ \ / __|
104
+ | |___ | | | (_) || | | || |_| || |_) |\__ \
105
+ \____||_| \___/ |_| |_| \___/ | .__/ |___/
106
+ |_|
107
+
108
+ ☰ CronOps v0.1.1-rc2.4 »Omnia coniuncta sunt«
109
+ Monitoring job configs in /config/workspace/cronops/config/jobs ...
110
+
111
+ Web API enabled. HTTP Server is listening on port 8118 ...
112
+ ⎆ API endpoint http://127.0.0.1:8118/api (secured)
113
+ ⎆ OpenAPI docs http://127.0.0.1:8118/docs
114
+ ⎆ Health check http://127.0.0.1:8118/health
115
+
116
+ Job config loaded (1 active job)
117
+ 🕔 [example-job3] scheduled (*/5 * * * *)
118
+ ```
119
+
120
+ Now you can add your job configuration files to the `./config/jobs/` directory. Each YAML file in this directory can contain one or more job definitions. Details, see below.
121
+
122
+ > [!NOTE]
123
+ > You do not need to restart the server after changing job files. The server identifies any changes and will hot reload the configuration. If a job configuration is invalid, an appropriate message will appear in the docker logs and the specific job will not be scheduled.
124
+
125
+
126
+ ### Updating using Docker compose
127
+
128
+ When using docker compose, to update to the latest version of CronOps, just type
129
+
130
+ ```sh
131
+ docker compose pull && docker compose up -d
132
+ ```
133
+
134
+ in the same directoy where `compose.yaml` has been created.
135
+
136
+
137
+
138
+ ### Install & run in server environment
139
+
140
+ This requires [node.js](https://nodejs.org/) (v24 ++) to be installed on your server.
141
+
142
+ First step is to create an empty app directory with a `.env` file that contains your configuration settings, e.g.:
143
+
144
+ ```ini
145
+ NODE_ENV=production
146
+ CROPS_SOURCE_ROOT=/var/lib/docker/volumes # change as you like
147
+ CROPS_TARGET_ROOT=/var/opt/backups # change as you like
148
+ CROPS_CONFIG_DIR=/home/cronops/config # optional. Default is ./config
149
+ CROPS_LOG_DIR=/home/cronops/logs # optional. Default is ~/.cronops
150
+ ```
151
+
152
+ To install and start CronOps, type in bash shell:
153
+
154
+ ```bash
155
+ npx dotenvx run -- npx @mtakla/cronops &> /var/log/cronops.log
156
+ ```
157
+ This will ...
158
+
159
+ - download the latest version of cronops (and dotenvx)
160
+ - load the environment settings defined in the `.env` file
161
+ - start the cronops service with the loaded environment settings
162
+ - create jobs directory in `/home/cronops/config/jobs` if it doesn't exist
163
+ - switch to idle mode as no active jobs are configured
164
+
165
+ You can add job configuration files to `/home/cronops/config/jobs/` directory. Each YAML file in this directory defines a job. The server will hot reload when job files are added, modified, or removed.
166
+
167
+
168
+ ## Configuration
169
+
170
+ The CronOps service can be configured with the following environment variables:
171
+
172
+ | ENV | Description | Docker defaults |
173
+ | --------------------- | ------------------------------------------------------------------------------ | --------------- |
174
+ | `CROPS_SOURCE_ROOT` | Path to primary source directory | `/io/source` |
175
+ | `CROPS_TARGET_ROOT` | Path to primary target directory | `/io/target` |
176
+ | `CROPS_SOURCE_2_ROOT` | Path to secondary source directory | `/io/source2` |
177
+ | `CROPS_TARGET_2_ROOT` | Path to secondary target directory | `/io/target2` |
178
+ | `CROPS_SOURCE_3_ROOT` | Path to tertiary source directory | `/io/source3` |
179
+ | `CROPS_TARGET_3_ROOT` | Path to tertiary target directory | `/io/target3` |
180
+ | `CROPS_CONFIG_DIR` | Path to the config directory where job files are located | `/config` |
181
+ | `CROPS_TEMP_DIR` | Path to temporary folder used for dry-run mode | `/data/temp` |
182
+ | `CROPS_LOG_DIR` | Path to directory where job logs and file history are stored | `/data/logs` |
183
+ | `CROPS_HOST` | Host address for the Admin API server | `0.0.0.0` |
184
+ | `CROPS_PORT` | Port for the Admin API server | `8083` |
185
+ | `CROPS_EXEC_SHELL` | (*Optional*) Default shell for `exec` actions. Can be `false`, `true`, or path | `false` |
186
+ | `CROPS_API_KEY` | (*Optional*) API key for securing the Admin API endpoints | - |
187
+ | `CROPS_BASE_URL` | (*Optional*) Base URL for admin API and OpenAPI docs | - |
188
+ | `TZ` | (*Optional*) Timezone for cron scheduling (standard timezone format) | `UTC` |
189
+
190
+
191
+ ## Job Configuration
192
+
193
+ Jobs are configured as YAML files in the `CROPS_CONFIG_DIR/jobs` directory. Each YAML file can contain one or more job definitions. .
194
+
195
+ Example job config `./config/jobs/example.yaml`
196
+
197
+ ```yaml
198
+ action: move # exec|call|copy|move|delete|archive
199
+ cron: "*/5 * * * * *"
200
+ source:
201
+ dir: $1/nzbget/config/data/download
202
+ includes:
203
+ - "**/*.mp4"
204
+ target:
205
+ dir: $1/filegator/micha/downloads
206
+ permissions:
207
+ owner: "1000:1000"
208
+ file_mode: "444"
209
+ dir_mode: "711"
210
+ retention: 12h
211
+ dry_run: true
212
+ enabled: false
213
+ ```
214
+
215
+ > [!NOTE]
216
+ You can change the job configuration at any time and the server will hot reload and schedule the new job configuration.
217
+ Be aware that once the job config has been changed, active running tasks will be terminated and the job will be rescheduled
218
+
219
+
220
+ ### Job Actions
221
+
222
+ CronOps supports 5 different job actions:
223
+
224
+ #### File based actions
225
+
226
+ - **`copy`** - Copy files from source to target directory while preserving originals
227
+ - **`move`** - Move files from source to target directory (removes originals after successful copy)
228
+ - **`delete`** - Delete files matching the source patterns
229
+ - **`archive`** - Create a compressed tar.gz archive of matched files in the target directory
230
+
231
+ #### Command execution action
232
+
233
+ - **`exec`** - Execute a command or script. Use with `command`, `args`, `shell`, and `env` properties
234
+
235
+
236
+ > [!TIP]
237
+ > **Path References**: Use `$1`, `$2`, or `$3` in job paths to reference configured root directories.
238
+ > For source paths, these map to `CROPS_SOURCE_ROOT`, `CROPS_SOURCE_2_ROOT`, and `CROPS_SOURCE_3_ROOT`.
239
+ > For target paths, they map to `CROPS_TARGET_ROOT`, `CROPS_TARGET_2_ROOT`, and `CROPS_TARGET_3_ROOT`.
240
+
241
+ ### Job Configuration examples
242
+
243
+ #### Copy Files with Pattern Matching
244
+
245
+ ```yaml
246
+ action: copy
247
+ cron: "0 2 * * *" # Daily at 2 AM
248
+ source:
249
+ dir: $1/downloads
250
+ includes:
251
+ - "**/*.pdf"
252
+ - "**/*.doc"
253
+ excludes:
254
+ - "**/*.tmp"
255
+ target:
256
+ dir: $1/archive/documents
257
+ permissions:
258
+ owner: "1000:1000"
259
+ file_mode: "644"
260
+ dir_mode: "755"
261
+ retention: "30d"
262
+ enabled: true
263
+ ```
264
+
265
+ #### Create an archive
266
+
267
+ ```yaml
268
+ action: archive
269
+ cron: "0 0 * * 0" # Weekly on Sunday at midnight
270
+ source:
271
+ dir: $1/logs
272
+ includes:
273
+ - "**/*.log"
274
+ excludes:
275
+ - ".git/**"
276
+ - "node_modules/**"
277
+ target:
278
+ dir: $1/backups
279
+ archive_name: "logs-{{yyyy-MM-dd}}.tgz"
280
+ enabled: true
281
+ ```
282
+
283
+ #### Execute Custom Command
284
+
285
+ ```yaml
286
+ action: exec
287
+ cron: "*/15 * * * *" # Every 15 minutes
288
+ command: "node"
289
+ args:
290
+ - "--experimental-vm-modules"
291
+ - "{scriptDir}/cleanup.js"
292
+ env:
293
+ LOG_LEVEL: "info"
294
+ API_TOKEN: "secret123"
295
+ enabled: true
296
+ ```
297
+
298
+ ### Command execution parameters
299
+
300
+ For jobs of action type `exec`, you can use dynamic parameters in your `command`, `args` or custom `env` entries that will be resolved before the system command is executed:
301
+
302
+ | Parameter | Description |
303
+ | ------------- | ---------------------------------------------------------------- |
304
+ | `{jobId}` | job identifier |
305
+ | `{sourceDir}` | absolute path to the job source directory |
306
+ | `{targetDir}` | absolute path to the job target directory (or CROPS_TARGET_ROOT) |
307
+ | `{scriptDir}` | absolute path to the configured script directory |
308
+ | `{tempDir}` | absolute path to the configured temp directory |
309
+ | `{logDir}` | absolute path to the configured log directory |
310
+
311
+
312
+ If the exec action is configured to run on selected `source` files:
313
+
314
+ | Parameter | Description |
315
+ | ------------ | ---------------------------------------------------------------------------- |
316
+ | `{file}` | absolute path to the processed file, e.g. `/io/source/foo/bar.txt` |
317
+ | `{fileDir}` | absolute path to the parent dir of the processed file, e.g. `/io/source/foo` |
318
+ | `{fileName}` | name of the processed file, e.g. `bar.txt` |
319
+ | `{fileBase}` | base name of the processed file without extension, e.g. `bar` |
320
+ | `{fileExt}` | extension of the processed file, e.g. `.txt` |
321
+
322
+ ### Command execution ENV defaults
323
+
324
+ For jobs of action type `exec` the following environment variables are available by default when the os command is executed.
325
+
326
+ | Parameter | Description |
327
+ | ------------------ | ---------------------------------------------------------------- |
328
+ | `CROPS_JOB_ID` | job identifier |
329
+ | `CROPS_SOURCE_DIR` | absolute path to the job source directory |
330
+ | `CROPS_TARGET_DIR` | absolute path to the job target directory (or CROPS_TARGET_ROOT) |
331
+ | `CROPS_SCRIPT_DIR` | absolute path to the configured script directory |
332
+ | `CROPS_TEMP_DIR` | absolute path to the configured temp directory |
333
+ | `CROPS_LOG_DIR` | absolute path to the configured log directory |
334
+ | `CROPS_DRY_RUN` | "true", if dry_run mode is enabled |
335
+ | `CROPS_VERBOSE` | "true", if dry_run mode is enabled |
336
+
337
+
338
+ If the exec action is configured to run on selected `source` files:
339
+
340
+ | Parameter | Description |
341
+ | ----------------- | ----------------------------------------------------------------------------------- |
342
+ | `CROPS_FILE` | absolute path to the processed source file, e.g. `/io/source/foo/bar.txt` |
343
+ | `CROPS_FILE_DIR` | absolute path to the parent dir of the processed source file, e.g. `/io/source/foo` |
344
+ | `CROPS_FILE_NAME` | file name of the processed source file, e.g. `bar.txt` |
345
+ | `CROPS_FILE_BASE` | base name of the processed source file without extension, e.g. `bar` |
346
+ | `CROPS_FILE_EXT` | extension of the processed source file, e.g. `.txt` |
347
+
348
+
349
+
350
+ ### Job properties
351
+
352
+ | Property | Description |
353
+ | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
354
+ | `action` | **Required**. The action to perform. One of: `exec`, `call`, `copy`, `move`, `delete`, `archive` |
355
+ | `cron` | (*Optional*) Cron-like scheduling string, e.g., `*/2 * * * *`. See [node-cron](https://nodecron.com/cron-syntax.html) documentation for details. If omitted, job runs once. |
356
+ | `command` | (*For `exec`/`call` actions*) Command to execute, e.g., `"node"`, `"/bin/bash"` |
357
+ | `shell` | (*Optional*) Shell to use for command execution. Can be `true` (use default shell) or a path to a shell binary |
358
+ | `args` | (*Optional*) Array of command arguments for `exec`/`call` actions |
359
+ | `env` | (*Optional*) Environment variables to pass to the command. Object with uppercase keys and string values |
360
+ | `source.dir` | Source directory path. Can be absolute or use `$1` (CROPS_SOURCE_ROOT), `$2` (CROPS_SOURCE_2_ROOT), or `$3` (CROPS_SOURCE_3_ROOT), e.g., `"$1/downloads"` |
361
+ | `source.includes` | (*Optional*) Array of glob patterns to include files, relative to `source.dir`. Default: `["**/*"]` |
362
+ | `source.excludes` | (*Optional*) Array of glob patterns to exclude files from processing |
363
+ | `target.dir` | Target directory path. Can be absolute or use `$1` (CROPS_TARGET_ROOT), `$2` (CROPS_TARGET_2_ROOT), or `$3` (CROPS_TARGET_3_ROOT) |
364
+ | `target.archive_name` | (*For `archive` action*) Archive file name pattern with date placeholders, e.g., `"backup-{{yyyy-MM-dd}}.tgz"` |
365
+ | `target.permissions.owner` | (*Optional*) Change user/group ownership to `"uid:gid"` for all target files. Default: process owner unless `PUID` or `PGID` environment is set |
366
+ | `target.permissions.file_mode` | (*Optional*) Change file permissions using octal (e.g., `"644"`) or symbolic mode (e.g., `"ugo+r"`). Default: "660" |
367
+ | `target.permissions.dir_mode` | (*Optional*) Change directory permissions using octal (e.g., `"755"`) or symbolic mode (e.g., `"ugo+rx"`). Default: "770" |
368
+ | `target.retention` | (*Optional*) Time period after which target files will be deleted, e.g., `"10d"`, `"12h"`. Uses [ms](https://www.npmjs.com/package/ms) format. Default: files are kept |
369
+ | `dry_run` | (*Optional*) If `true`, simulate the operation without making actual changes. Source files are never modified in dry-run mode. Default: `false` |
370
+ | `verbose` | (*Optional*) Enable verbose logging for this job. Default: `false` |
371
+ | `enabled` | (*Optional*) If `false`, the job will not be scheduled. Default: `true` |
372
+
373
+
374
+
375
+ ## Security considerations & Trouble shooting
376
+
377
+ > [!NOTE]
378
+ > It is strongly advised against accessing or modifying the data directly on the host system within Docker's internal volume storage path (typically `/var/lib/docker/volumes/`).
379
+
380
+ > [!WARNING]
381
+ > **Hazardous Misconfiguration**
382
+ >
383
+ > If your CronOps docker container is running with Root Privileges and the persistent volumes (source/target directories) are mounted to critical system directories of the hosting operating system (e.g., `/etc`, `/var`, etc.), this creates an extremely high **security risk**:
384
+ >
385
+ > - **System File Overwrite**: The container can access, modify, or delete crucial files and directories on the host machine via the exposed volume paths.
386
+ > - **Host System Damage**: If the volume mounts are not correctly configured (e.g., if a Bind Mount unintentionally exposes the wrong host directory), the root user inside the container can potentially modify or delete system-critical data on the host.
387
+
388
+
389
+ ## License
390
+
391
+ CronOps is under [ISC License](https://github.com/mtakla/cronops/blob/master/LICENSE). Made with ❤ in EU
@@ -0,0 +1,17 @@
1
+ action: copy # exec | copy | move | delete | archive
2
+ cron: "*/5 * * * * *"
3
+ source:
4
+ dir: /src
5
+ includes:
6
+ - "**/*.ts"
7
+ excludes:
8
+ - "**/*test.ts"
9
+ target:
10
+ dir: $1/build/example/backup
11
+ permissions:
12
+ owner: "1000:1000"
13
+ file_mode: "664"
14
+ dir_mode: "774"
15
+ retention: "10d"
16
+ verbose: false
17
+ enabled: false
@@ -0,0 +1,7 @@
1
+ action: exec
2
+ cron: "*/5 * * * * *"
3
+ command: "node"
4
+ args:
5
+ - "--experimental-vm-modules"
6
+ - "{scriptDir}/example-script.js"
7
+ enabled: false
@@ -0,0 +1,14 @@
1
+ action: archive
2
+ cron: "*/5 * * * *"
3
+ source:
4
+ dir: /
5
+ includes:
6
+ - "**/*.ts"
7
+ excludes:
8
+ - ".git/**"
9
+ - "node_modules/**"
10
+ - "dist/**"
11
+ - "build/**"
12
+ target:
13
+ dir: /build/bulk
14
+ archive_name: "backup-{{MM-dd}}.tgz"
@@ -0,0 +1,27 @@
1
+ # THIS FILE MAY BE OBSOLETE!
2
+ # WHY? Use env vars for config
3
+ # - CROPS_SOURCE_EXCLUDES: "[**/*~, **/*~]"
4
+ # - CROPS_EXEC_ENVIRONMENT: "[CI_API_TOKEN:'10f23f2efasdfsevrew']"
5
+ # - CROPS_EXEC_SHELL: "/bin/bash"
6
+ # - CROPS_DEFAULT_ARCHIVE_NAME
7
+
8
+ # Altenatively:
9
+ # - any environment will be routed to the sub process
10
+ # - CROPS_EXEC_APPLY_PARENT_ENVIRONMENT
11
+ #
12
+ # Notes:
13
+ # - Needs a server restart if changes to this file are made
14
+ useShell: false
15
+ environment:
16
+ - CI_API_TOKEN=""
17
+ source:
18
+ excludes:
19
+ - "**/*~"
20
+ - "**/*.git"
21
+ - "**/*.svn"
22
+ - "**/*.part"
23
+ - "**/*.download"
24
+ - "**/*.crdownload"
25
+ - "**/*.tmp"
26
+ target:
27
+ archive_name: "backup-{{yyyy-MM-dd_HH-mm}}.tgz"
@@ -0,0 +1 @@
1
+ console.log("To the moon!");