repoactive 0.2.4.dev2__tar.gz → 0.2.5.dev1__tar.gz
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.
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/PKG-INFO +298 -169
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/README.md +297 -168
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/pyproject.toml +1 -1
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/config.py +49 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/jj.py +32 -44
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/runner.py +79 -41
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/.gitignore +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/LICENSE +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/__init__.py +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/cli.py +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/constants.py +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/graph.py +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/jobtree.py +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/lock.py +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/platforms/__init__.py +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/platforms/base.py +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/platforms/github.py +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/platforms/gitlab.py +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/progress.py +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/settings.py +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/ui.py +0 -0
- {repoactive-0.2.4.dev2 → repoactive-0.2.5.dev1}/src/repoactive/updates.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: repoactive
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5.dev1
|
|
4
4
|
Summary: Script-driven code changes with automated merge requests
|
|
5
5
|
License-Expression: GPL-3.0-or-later
|
|
6
6
|
License-File: LICENSE
|
|
@@ -37,10 +37,11 @@ and (with `--mode publish`) the full MR lifecycle.
|
|
|
37
37
|
|
|
38
38
|
## Contents
|
|
39
39
|
|
|
40
|
+
- [Use cases](#use-cases)
|
|
40
41
|
- [Installation](#installation)
|
|
41
42
|
- [Quick start](#quick-start)
|
|
42
43
|
- [How it works](#how-it-works)
|
|
43
|
-
- [
|
|
44
|
+
- [Keeping the local clone current](#keeping-the-local-clone-current)
|
|
44
45
|
- [Usage](#usage)
|
|
45
46
|
- [Environment variables](#environment-variables)
|
|
46
47
|
- [Inspecting repoactive commits](#inspecting-repoactive-commits)
|
|
@@ -48,13 +49,35 @@ and (with `--mode publish`) the full MR lifecycle.
|
|
|
48
49
|
- [Listing jobs](#listing-jobs)
|
|
49
50
|
- [Listing tags](#listing-tags)
|
|
50
51
|
- [Configuration](#configuration)
|
|
52
|
+
- [`[job-defaults]`](#job-defaults)
|
|
53
|
+
- [`[job.<name>]`](#jobname)
|
|
54
|
+
- [Stacking MRs](#stacking-mrs)
|
|
55
|
+
- [Example](#example)
|
|
56
|
+
- [`[platform.<name>]`](#platformname)
|
|
57
|
+
- [Config file locations](#config-file-locations)
|
|
58
|
+
- [Overriding values on the command line](#overriding-values-on-the-command-line)
|
|
51
59
|
- [Selecting jobs with tags](#selecting-jobs-with-tags)
|
|
60
|
+
- [Keeping unmerged branches current](#keeping-unmerged-branches-current)
|
|
52
61
|
- [Disabling jobs](#disabling-jobs)
|
|
62
|
+
- [Running a job on a schedule](#running-a-job-on-a-schedule)
|
|
63
|
+
- [One run at a time per repository](#one-run-at-a-time-per-repository)
|
|
53
64
|
- [Gating jobs with `run_only_if_changed`](#gating-jobs-with-run_only_if_changed)
|
|
54
65
|
- [Throttling jobs with `cooldown_period`](#throttling-jobs-with-cooldown_period)
|
|
66
|
+
- [Throttling a job when a superset lands with `cooldown_on`](#throttling-a-job-when-a-superset-lands-with-cooldown_on)
|
|
55
67
|
- [Limiting job runtime with `timeout`](#limiting-job-runtime-with-timeout)
|
|
56
68
|
- [Generating jobs dynamically](#generating-jobs-dynamically)
|
|
57
69
|
- [Requirements](#requirements)
|
|
70
|
+
- [Appendix](#appendix)
|
|
71
|
+
- [jj revset aliases](#jj-revset-aliases)
|
|
72
|
+
|
|
73
|
+
## Use cases
|
|
74
|
+
|
|
75
|
+
- Keeping generated files (API clients, protobuf bindings, lock files) in
|
|
76
|
+
sync with their sources
|
|
77
|
+
- Applying organization-wide refactors or policy changes across many
|
|
78
|
+
repositories
|
|
79
|
+
- Automating any periodic code transformation that should go through a
|
|
80
|
+
review process
|
|
58
81
|
|
|
59
82
|
## Installation
|
|
60
83
|
|
|
@@ -98,7 +121,7 @@ needs a GitHub or GitLab API token in the environment. See
|
|
|
98
121
|
```
|
|
99
122
|
|
|
100
123
|
4. **Run the job locally.** In the default `local` mode nothing is pushed
|
|
101
|
-
and no MR is created
|
|
124
|
+
and no MR is created - repoactive just records the diff your script
|
|
102
125
|
produced on the branch `repoactive/uv-lock-upgrade` and prints a
|
|
103
126
|
`jj op restore` command to undo the run:
|
|
104
127
|
|
|
@@ -109,7 +132,7 @@ needs a GitHub or GitLab API token in the environment. See
|
|
|
109
132
|
5. **Publish it.** Put the API token your platform uses in the environment
|
|
110
133
|
(`GITHUB_TOKEN` for GitHub.com, `GITLAB_TOKEN` for GitLab.com by
|
|
111
134
|
default), fetch the latest base branch, then let repoactive push the
|
|
112
|
-
branch and open
|
|
135
|
+
branch and open - or update - the merge request:
|
|
113
136
|
|
|
114
137
|
```bash
|
|
115
138
|
jj git fetch # repoactive never fetches on its own
|
|
@@ -147,7 +170,7 @@ need to write is the script that produces the change.
|
|
|
147
170
|
3. If the script produced a diff, it records the change. With `--mode push`
|
|
148
171
|
or `--mode publish`, it pushes the branch; with `--mode publish`, it also
|
|
149
172
|
creates or updates the merge request. On a re-run, if the diff matches
|
|
150
|
-
what is already on the branch, the commit and branch are left untouched
|
|
173
|
+
what is already on the branch, the commit and branch are left untouched -
|
|
151
174
|
avoiding an unnecessary push that would re-trigger CI pipelines. The
|
|
152
175
|
commit is updated (and the branch pushed) only when the diff itself
|
|
153
176
|
changes or when `title`/`commit_title_prefix` changed. Command output
|
|
@@ -161,7 +184,7 @@ need to write is the script that produces the change.
|
|
|
161
184
|
> **jj commits the whole working tree.** Because `repoactive` uses jj, every
|
|
162
185
|
> new file your script creates inside the working directory is added to the
|
|
163
186
|
> commit unless it is git-ignored. There is no way to select which
|
|
164
|
-
> working-tree changes become part of the commit
|
|
187
|
+
> working-tree changes become part of the commit - they all will. Keep
|
|
165
188
|
> `.gitignore` up to date so build artifacts, caches, and other stray files
|
|
166
189
|
> your script produces do not end up in the diff.
|
|
167
190
|
|
|
@@ -175,21 +198,12 @@ local clone advances past it.
|
|
|
175
198
|
|
|
176
199
|
**Fetch before each run.** Run `jj git fetch` (or `git fetch --prune`) in
|
|
177
200
|
the same cron job or CI pipeline that invokes `repoactive`, before it. If
|
|
178
|
-
you do not, jobs rebase onto a stale base and
|
|
201
|
+
you do not, jobs rebase onto a stale base and - most importantly -
|
|
179
202
|
[`cooldown_period`](#throttling-jobs-with-cooldown_period) never engages,
|
|
180
203
|
because the commit that would trigger it has not reached the local base
|
|
181
204
|
branch. See
|
|
182
205
|
[ADR 0005](docs/adr/0005-local-repository-is-the-source-of-truth.md).
|
|
183
206
|
|
|
184
|
-
## Use cases
|
|
185
|
-
|
|
186
|
-
- Keeping generated files (API clients, protobuf bindings, lock files) in
|
|
187
|
-
sync with their sources
|
|
188
|
-
- Applying organization-wide refactors or policy changes across many
|
|
189
|
-
repositories
|
|
190
|
-
- Automating any periodic code transformation that should go through a
|
|
191
|
-
review process
|
|
192
|
-
|
|
193
207
|
## Usage
|
|
194
208
|
|
|
195
209
|
```bash
|
|
@@ -323,28 +337,6 @@ repoactive recent-commits --status unmerged
|
|
|
323
337
|
| `--status [all\|merged\|unmerged]` | `-s` | Filter by merge status into trunk (default: `all`) |
|
|
324
338
|
| `--debug` | `-d` | Enable debug logging |
|
|
325
339
|
|
|
326
|
-
### jj revset aliases
|
|
327
|
-
|
|
328
|
-
To query repoactive commits directly in jj, add these aliases to your
|
|
329
|
-
repository config (`jj config set --repo`) or your global config
|
|
330
|
-
(`jj config set --user`):
|
|
331
|
-
|
|
332
|
-
```toml
|
|
333
|
-
[revset-aliases]
|
|
334
|
-
'repoactive()' = 'description(regex:"(?m)^Repoactive-Job: ")'
|
|
335
|
-
'repoactive_merged()' = 'repoactive() & ::trunk()'
|
|
336
|
-
'repoactive_unmerged()' = 'repoactive() & ~(::trunk())'
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
Then use them directly in jj:
|
|
340
|
-
|
|
341
|
-
```bash
|
|
342
|
-
jj log -r 'repoactive()'
|
|
343
|
-
jj log -r 'repoactive_unmerged()'
|
|
344
|
-
jj log -r 'repoactive() & committer_date(after:"2025-01-01")'
|
|
345
|
-
jj log -r 'repoactive() & description(regex:"(?m)^Repoactive-Job: uv-lock-upgrade$")'
|
|
346
|
-
```
|
|
347
|
-
|
|
348
340
|
## Validating configuration
|
|
349
341
|
|
|
350
342
|
```
|
|
@@ -372,12 +364,8 @@ code 1.
|
|
|
372
364
|
Validation checks include unknown keys, missing required fields, invalid
|
|
373
365
|
`depends_on` references, and circular job dependencies.
|
|
374
366
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
| `--config PATH` | `-c` | Config file or directory of `*.toml` files; repeat to merge. Default: `.repoactive.d/` and `.repoactive.toml` under `--repo` |
|
|
378
|
-
| `--set NAME=VALUE` | `-s` | Override a config value (repeatable); `NAME` is a dotted TOML key, `VALUE` a TOML expression. Wins over `--config` |
|
|
379
|
-
| `--repo PATH` | `-r` | jj repository path (default: `.`) |
|
|
380
|
-
| `--debug` | `-d` | Enable debug logging |
|
|
367
|
+
The command accepts the same `--config`, `--set`, `--repo`, and `--debug`
|
|
368
|
+
options as [`repoactive run`](#usage).
|
|
381
369
|
|
|
382
370
|
## Listing jobs
|
|
383
371
|
|
|
@@ -403,12 +391,8 @@ build Build the project enabled
|
|
|
403
391
|
└── deploy Deploy to staging nightly, risky
|
|
404
392
|
```
|
|
405
393
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
| `--config PATH` | `-c` | Config file or directory of `*.toml` files; repeat to merge. Default: `.repoactive.d/` and `.repoactive.toml` under `--repo` |
|
|
409
|
-
| `--set NAME=VALUE` | `-s` | Override a config value (repeatable); `NAME` is a dotted TOML key, `VALUE` a TOML expression. Wins over `--config` |
|
|
410
|
-
| `--repo PATH` | `-r` | jj repository path (default: `.`) |
|
|
411
|
-
| `--debug` | `-d` | Enable debug logging |
|
|
394
|
+
The command accepts the same `--config`, `--set`, `--repo`, and `--debug`
|
|
395
|
+
options as [`repoactive run`](#usage).
|
|
412
396
|
|
|
413
397
|
## Listing tags
|
|
414
398
|
|
|
@@ -417,7 +401,7 @@ repoactive info tags [OPTIONS]
|
|
|
417
401
|
```
|
|
418
402
|
|
|
419
403
|
Group the configured jobs by tag and print each tag with the jobs carrying
|
|
420
|
-
it. Jobs are grouped by their effective tags
|
|
404
|
+
it. Jobs are grouped by their effective tags - the tags driving job
|
|
421
405
|
selection: a job's explicit `tags`, or the implicit `enabled`/`disabled` tag
|
|
422
406
|
when it has none. Within each tag, jobs are shown as a dependency tree in
|
|
423
407
|
topological order: a job is nested under its `depends_on` targets carrying
|
|
@@ -442,12 +426,8 @@ nightly:
|
|
|
442
426
|
benchmark Run nightly benchmarks nightly
|
|
443
427
|
```
|
|
444
428
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
| `--config PATH` | `-c` | Config file or directory of `*.toml` files; repeat to merge. Default: `.repoactive.d/` and `.repoactive.toml` under `--repo` |
|
|
448
|
-
| `--set NAME=VALUE` | `-s` | Override a config value (repeatable); `NAME` is a dotted TOML key, `VALUE` a TOML expression. Wins over `--config` |
|
|
449
|
-
| `--repo PATH` | `-r` | jj repository path (default: `.`) |
|
|
450
|
-
| `--debug` | `-d` | Enable debug logging |
|
|
429
|
+
The command accepts the same `--config`, `--set`, `--repo`, and `--debug`
|
|
430
|
+
options as [`repoactive run`](#usage).
|
|
451
431
|
|
|
452
432
|
## Configuration
|
|
453
433
|
|
|
@@ -456,135 +436,200 @@ passed via `--config`). See [Config file locations](#config-file-locations)
|
|
|
456
436
|
for how the defaults are discovered and how to split the config across
|
|
457
437
|
several files.
|
|
458
438
|
|
|
439
|
+
A minimal config with a single job:
|
|
440
|
+
|
|
441
|
+
```toml
|
|
442
|
+
[job.uv-lock-upgrade]
|
|
443
|
+
command = "uv lock --upgrade"
|
|
444
|
+
title = "build: upgrade dependencies"
|
|
445
|
+
```
|
|
446
|
+
|
|
459
447
|
Every key in `[job-defaults]` supplies the default for the matching per-job
|
|
460
448
|
key; any job may override it by setting the same key in its `[job.<name>]`
|
|
461
449
|
block.
|
|
462
450
|
|
|
451
|
+
### `[job-defaults]`
|
|
452
|
+
|
|
453
|
+
**MR/PR options:**
|
|
454
|
+
|
|
455
|
+
- **`labels`** (default: `[]`) - Labels applied to every MR/PR. Per-job
|
|
456
|
+
`labels` are merged with, not replaced by, this list.
|
|
457
|
+
- **`auto_merge`** (default: `false`) - When `true`, enable auto-merge on
|
|
458
|
+
every MR/PR so it merges automatically once its pipeline passes. On
|
|
459
|
+
GitHub, the repository must have "Allow auto-merge" enabled in its
|
|
460
|
+
settings.
|
|
461
|
+
|
|
462
|
+
**Branch and commit options:**
|
|
463
|
+
|
|
464
|
+
- **`branch_prefix`** (default: `"repoactive/"`) - Prefix prepended to the
|
|
465
|
+
job name to form the branch name.
|
|
466
|
+
- **`mr_title_prefix`** (default: `"[repoactive] "`) - Prefix prepended to
|
|
467
|
+
every MR/PR title. Set to `""` to disable.
|
|
468
|
+
- **`commit_title_prefix`** (default: `"[repoactive] "`) - Prefix prepended
|
|
469
|
+
to every commit title. Set to `""` to disable.
|
|
470
|
+
- **`base_branch`** (default: repo default) - Target branch for all jobs
|
|
471
|
+
that do not set their own.
|
|
472
|
+
|
|
473
|
+
**Run control:**
|
|
474
|
+
|
|
475
|
+
- **`cooldown_period`** (default: none) - Minimum time between a landed
|
|
476
|
+
change and the next run for any job. Format: `<number><unit>` where unit
|
|
477
|
+
is `s`, `m`, `h`, `d`, or `w` (e.g. `"7d"`). See
|
|
478
|
+
[Throttling jobs with `cooldown_period`](#throttling-jobs-with-cooldown_period).
|
|
479
|
+
- **`timeout`** (default: `"2m"`) - Maximum runtime for a job's command.
|
|
480
|
+
Same format as `cooldown_period`. See
|
|
481
|
+
[Limiting job runtime with `timeout`](#limiting-job-runtime-with-timeout).
|
|
482
|
+
|
|
483
|
+
### `[job.<name>]`
|
|
484
|
+
|
|
485
|
+
The table key is the job's unique name; the branch is always
|
|
486
|
+
`branch_prefix + name`. Job names may contain letters, digits, hyphens, and
|
|
487
|
+
underscores.
|
|
488
|
+
|
|
489
|
+
**Required:**
|
|
490
|
+
|
|
491
|
+
- **`command`** - Shell command (or executable path) run in the repository
|
|
492
|
+
working directory. A non-zero exit is a failure.
|
|
493
|
+
- **`title`** - MR/PR title (also the commit subject, after
|
|
494
|
+
`commit_title_prefix`).
|
|
495
|
+
|
|
496
|
+
**MR/PR options:**
|
|
497
|
+
|
|
498
|
+
- **`description`** - Body text of the MR/PR.
|
|
499
|
+
- **`labels`** (default: `[]`) - Extra labels for this job's MR/PR, merged
|
|
500
|
+
with `job-defaults.labels`.
|
|
501
|
+
- **`draft`** (default: `false`) - Open the MR/PR as a draft. On GitHub,
|
|
502
|
+
draft state cannot be changed after creation.
|
|
503
|
+
- **`create_mr`** (default: `true`) - Whether to create an MR/PR: `true`
|
|
504
|
+
(always), `false` (push the branch but skip the MR), or
|
|
505
|
+
`"unless-superseded"` (skip when a dependent's MR from the same run
|
|
506
|
+
already contains this job's changes - see [Stacking MRs](#stacking-mrs)).
|
|
507
|
+
- **`auto_merge`** (default: inherited from `job-defaults`) - When `true`,
|
|
508
|
+
enable auto-merge on this job's MR/PR.
|
|
509
|
+
|
|
510
|
+
**Branch and commit options:**
|
|
511
|
+
|
|
512
|
+
- **`base_branch`** (default: inherited) - Target branch for this job's
|
|
513
|
+
MR/PR.
|
|
514
|
+
- **`branch_prefix`** (default: inherited) - Override the branch-name prefix
|
|
515
|
+
for this job only.
|
|
516
|
+
- **`mr_title_prefix`** (default: inherited) - Override the MR/PR title
|
|
517
|
+
prefix for this job only.
|
|
518
|
+
- **`commit_title_prefix`** (default: inherited) - Override the commit title
|
|
519
|
+
prefix for this job only.
|
|
520
|
+
- **`output_in_commit`** (default: `true`) - Append the job's command and
|
|
521
|
+
its captured output to the commit message. Set to `false` to keep the
|
|
522
|
+
commit message clean.
|
|
523
|
+
|
|
524
|
+
**Run control:**
|
|
525
|
+
|
|
526
|
+
- **`disabled`** (default: `false`) - Exclude this job from the bare
|
|
527
|
+
`repoactive run`. Sugar for `tags = ["disabled"]`; mutually exclusive with
|
|
528
|
+
`tags`. See [Disabling jobs](#disabling-jobs).
|
|
529
|
+
- **`tags`** (default: none) - Tags for job selection. A job with no tags
|
|
530
|
+
carries the implicit `enabled` tag and runs in the bare `repoactive run`;
|
|
531
|
+
setting any explicit tag removes `enabled`. See
|
|
532
|
+
[Selecting jobs with tags](#selecting-jobs-with-tags).
|
|
533
|
+
- **`depends_on`** (default: `[]`) - Jobs whose output this job builds on.
|
|
534
|
+
See [Stacking MRs](#stacking-mrs).
|
|
535
|
+
- **`run_only_if_changed`** (default: `[]`) - Only run this job if at least
|
|
536
|
+
one listed job produced a diff in the current run. See
|
|
537
|
+
[Gating jobs with `run_only_if_changed`](#gating-jobs-with-run_only_if_changed).
|
|
538
|
+
- **`cooldown_period`** (default: inherited) - Minimum time between a landed
|
|
539
|
+
change and the next run. See
|
|
540
|
+
[Throttling jobs with `cooldown_period`](#throttling-jobs-with-cooldown_period).
|
|
541
|
+
- **`cooldown_on`** (default: `[]`) - Broader jobs that subsume this one; a
|
|
542
|
+
recent landing of any of them also throttles this job. Requires a
|
|
543
|
+
`cooldown_period`. See
|
|
544
|
+
[Throttling a job when a superset lands with `cooldown_on`](#throttling-a-job-when-a-superset-lands-with-cooldown_on).
|
|
545
|
+
- **`timeout`** (default: inherited) - Maximum runtime for this job's
|
|
546
|
+
command. Set to `"0s"` to disable the timeout entirely. See
|
|
547
|
+
[Limiting job runtime with `timeout`](#limiting-job-runtime-with-timeout).
|
|
548
|
+
- **`emits_jobs`** (default: `false`) - Generator job: the command writes
|
|
549
|
+
`*.toml` job fragments into `$REPOACTIVE_JOBS_DIR` instead of producing a
|
|
550
|
+
diff. See [Generating jobs dynamically](#generating-jobs-dynamically).
|
|
551
|
+
|
|
552
|
+
### Stacking MRs
|
|
553
|
+
|
|
554
|
+
When `depends_on` is set, `repoactive` starts the job's script from a
|
|
555
|
+
working tree that already contains all listed dependencies' diffs, rather
|
|
556
|
+
than from the plain base branch. The resulting MR branch includes both the
|
|
557
|
+
dependency changes and the new job's changes on top, and links to the parent
|
|
558
|
+
MRs are automatically added to the MR description.
|
|
559
|
+
|
|
560
|
+
Because a dependent's MR already contains its dependencies' changes, a
|
|
561
|
+
dependency chain normally opens one MR per job that produced a diff. Setting
|
|
562
|
+
`create_mr = "unless-superseded"` on the earlier jobs collapses that: such a
|
|
563
|
+
job skips its MR when a dependent job produced an MR in the same run, so the
|
|
564
|
+
chain yields a single MR on the topmost job that actually changed something
|
|
565
|
+
|
|
566
|
+
- falling back to the job below it when the jobs above came up empty. The
|
|
567
|
+
branch is still pushed either way. Only the current run counts: a
|
|
568
|
+
dependent that is empty, failed, on cooldown, or not selected does not
|
|
569
|
+
suppress anything. See
|
|
570
|
+
[ADR 0009](docs/adr/0009-unless-superseded-mr-creation.md) for details and
|
|
571
|
+
limitations.
|
|
572
|
+
|
|
573
|
+
### Example
|
|
574
|
+
|
|
463
575
|
```toml
|
|
464
576
|
[job-defaults]
|
|
465
|
-
# Prefix prepended to job.name to form the branch name
|
|
466
|
-
branch_prefix = "repoactive/"
|
|
467
|
-
# Prefix prepended to every MR/PR title (set to "" to disable)
|
|
468
|
-
mr_title_prefix = "[repoactive] "
|
|
469
|
-
# Prefix prepended to every commit title (set to "" to disable)
|
|
470
|
-
commit_title_prefix = "[repoactive] "
|
|
471
|
-
# Labels applied to every MR/PR unless overridden per job
|
|
472
|
-
labels = ["repoactive"]
|
|
473
|
-
# Optional: default target branch for jobs that do not set their own
|
|
474
|
-
# (default: repo default branch)
|
|
475
577
|
base_branch = "main"
|
|
476
|
-
|
|
477
|
-
# (default: none). See "Throttling jobs with cooldown_period" below.
|
|
578
|
+
labels = ["repoactive"]
|
|
478
579
|
cooldown_period = "7d"
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
580
|
+
auto_merge = true
|
|
581
|
+
branch_prefix = "bot/"
|
|
582
|
+
commit_title_prefix = "[bot] "
|
|
583
|
+
timeout = "10m"
|
|
482
584
|
|
|
483
|
-
# The table key is the job's unique name; the branch is always
|
|
484
|
-
# <branch_prefix><name>.
|
|
485
585
|
[job.regenerate-api-client]
|
|
486
|
-
# Script run in the repo working directory; non-zero exit = failure
|
|
487
586
|
command = "python scripts/regen_api.py"
|
|
488
|
-
# MR/PR title
|
|
489
587
|
title = "api: regenerate API client"
|
|
490
|
-
# Optional: MR description
|
|
491
588
|
description = "Automated regeneration of the API client from the OpenAPI spec."
|
|
492
|
-
|
|
493
|
-
labels = ["automated", "api"]
|
|
494
|
-
# Optional: target branch (default: repo default branch)
|
|
495
|
-
base_branch = "main"
|
|
496
|
-
# Optional: open the MR/PR as a draft (default: false)
|
|
497
|
-
draft = false
|
|
498
|
-
# Optional: create an MR/PR for this job (default: true). Set to false to
|
|
499
|
-
# push the branch without opening an MR/PR, or to "unless-superseded" to skip
|
|
500
|
-
# the MR/PR when a dependent job's MR from the same run already contains this
|
|
501
|
-
# job's changes (see the notes on depends_on below).
|
|
502
|
-
create_mr = true
|
|
503
|
-
# Optional: append the job's command and its output to the commit message
|
|
504
|
-
# (default: true). Set to false to keep the commit message clean.
|
|
505
|
-
output_in_commit = true
|
|
506
|
-
# Optional: skip this job on "run all" invocations (default: false). Sugar for
|
|
507
|
-
# tags = ["disabled"]; mutually exclusive with tags. See "Disabling jobs" below.
|
|
508
|
-
disabled = false
|
|
509
|
-
# Optional: tags for job selection (default: none -> the job carries the
|
|
510
|
-
# implicit "enabled" tag and runs in the bare `repoactive run`). Setting any tag
|
|
511
|
-
# removes "enabled", so the job runs only via `repoactive run --tag <tag>`. See
|
|
512
|
-
# "Selecting jobs with tags" below.
|
|
513
|
-
# tags = ["nightly"]
|
|
514
|
-
# Optional: override branch_prefix/mr_title_prefix/commit_title_prefix from
|
|
515
|
-
# job-defaults for this job only.
|
|
589
|
+
labels = ["api"]
|
|
516
590
|
mr_title_prefix = "[api] "
|
|
517
|
-
|
|
518
|
-
# diff in the current run. If none of them changed anything, this job is
|
|
519
|
-
# skipped (with a no-op result so dependents still run). Names need not be
|
|
520
|
-
# in depends_on; any job that ran before this one can be listed.
|
|
521
|
-
# run_only_if_changed = ["other-job"]
|
|
522
|
-
# Optional: minimum time between landed changes for this job. If a commit
|
|
523
|
-
# from this job landed on the base branch within this window, the job is
|
|
524
|
-
# skipped. Format: <number><unit>, unit one of s, m, h, d, w (e.g. "7d").
|
|
525
|
-
cooldown_period = "7d"
|
|
526
|
-
# Optional: maximum runtime for this job's command. When it expires the
|
|
527
|
-
# command's process group is killed and the job fails. Same format as
|
|
528
|
-
# cooldown_period.
|
|
529
|
-
timeout = "30m"
|
|
591
|
+
create_mr = "unless-superseded"
|
|
530
592
|
|
|
531
593
|
[job.sync-license-headers]
|
|
532
594
|
command = "./scripts/add_license_headers.sh"
|
|
533
595
|
title = "sync license headers"
|
|
596
|
+
draft = true
|
|
534
597
|
|
|
535
598
|
[job.integration-tests-update]
|
|
536
599
|
command = "./scripts/update_integration_tests.py"
|
|
537
600
|
title = "tests: update integration tests"
|
|
538
|
-
# Optional: run this job on top of the merged output of the listed jobs
|
|
539
601
|
depends_on = ["regenerate-api-client", "sync-license-headers"]
|
|
602
|
+
timeout = "30m"
|
|
540
603
|
```
|
|
541
604
|
|
|
605
|
+
### `[platform.<name>]`
|
|
606
|
+
|
|
542
607
|
For public GitHub.com or GitLab.com repositories no platform declaration is
|
|
543
|
-
needed
|
|
608
|
+
needed - `repoactive` detects the remote URL automatically. To use a
|
|
544
609
|
self-hosted instance, add a `[platform.<name>]` section (the name is a label
|
|
545
610
|
of your choosing; platforms are matched to a repository by their `url`):
|
|
546
611
|
|
|
612
|
+
- **`url`** - Base URL of the platform instance (e.g.
|
|
613
|
+
`"https://gitlab.example.com"`).
|
|
614
|
+
- **`type`** - `"github"` or `"gitlab"`.
|
|
615
|
+
- **`token_env`** - Name of the environment variable holding the API token.
|
|
616
|
+
|
|
547
617
|
```toml
|
|
548
618
|
[platform.company-gitlab]
|
|
549
|
-
# Base URL of the platform instance
|
|
550
619
|
url = "https://gitlab.example.com"
|
|
551
|
-
# Name of the env var holding the API token
|
|
552
620
|
token_env = "GITLAB_TOKEN"
|
|
553
|
-
# type must be either "github" or "gitlab"
|
|
554
621
|
type = "gitlab"
|
|
555
622
|
```
|
|
556
623
|
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
to push and create MRs. A job that needs its own credential must be given a
|
|
565
|
-
separate one. `repoactive` otherwise trusts job commands — they run
|
|
566
|
-
arbitrary code against the working tree — so the trust boundary is the
|
|
567
|
-
config that defines them; see
|
|
624
|
+
Secrets are kept out of the config file by referencing environment variable
|
|
625
|
+
names rather than inline values. The token named by `token_env` is
|
|
626
|
+
**stripped from the environment job commands run in**, so a script cannot
|
|
627
|
+
read the credential `repoactive` uses to push and create MRs. A job that
|
|
628
|
+
needs its own credential must be given a separate one. `repoactive`
|
|
629
|
+
otherwise trusts job commands - they run arbitrary code against the working
|
|
630
|
+
tree - so the trust boundary is the config that defines them; see
|
|
568
631
|
[ADR 0006](docs/adr/0006-job-commands-are-trusted.md).
|
|
569
632
|
|
|
570
|
-
When `depends_on` is set, `repoactive` starts the job's script from a
|
|
571
|
-
working tree that has all listed dependency branches merged together, rather
|
|
572
|
-
than from the plain base branch. The resulting MR branch will therefore
|
|
573
|
-
include both the dependency jobs and the new job on top. Links to the parent
|
|
574
|
-
MRs are automatically added to the MR description.
|
|
575
|
-
|
|
576
|
-
Because a dependent's MR already contains its dependencies' changes, a
|
|
577
|
-
dependency chain normally opens one MR per job that produced a diff. Setting
|
|
578
|
-
`create_mr = "unless-superseded"` on the earlier jobs collapses that: such a
|
|
579
|
-
job skips its MR whenever a dependent job produced an MR in the same run, so
|
|
580
|
-
the chain yields a single MR on the topmost job that actually changed
|
|
581
|
-
something — falling back to the job below it when the jobs above came up
|
|
582
|
-
empty. The branch is still pushed either way. Only the current run counts: a
|
|
583
|
-
dependent that is empty, failed, on cooldown, or not selected does not
|
|
584
|
-
suppress anything. See
|
|
585
|
-
[ADR 0009](docs/adr/0009-unless-superseded-mr-creation.md) for details and
|
|
586
|
-
limitations.
|
|
587
|
-
|
|
588
633
|
### Config file locations
|
|
589
634
|
|
|
590
635
|
When no `--config`/`-c` option is given, `repoactive` looks for
|
|
@@ -609,8 +654,8 @@ directory, not `--repo`.
|
|
|
609
654
|
|
|
610
655
|
`--set NAME=VALUE`/`-s` tweaks individual config values without editing a
|
|
611
656
|
file. It is merged as the last, highest-priority source, so it wins over
|
|
612
|
-
everything discovered or passed with `--config`. `NAME` is a TOML key
|
|
613
|
-
dotted keys reach into tables
|
|
657
|
+
everything discovered or passed with `--config`. `NAME` is a TOML key -
|
|
658
|
+
dotted keys reach into tables - and `VALUE` is a TOML expression, so strings
|
|
614
659
|
need quoting:
|
|
615
660
|
|
|
616
661
|
```bash
|
|
@@ -635,7 +680,7 @@ which then needs the full set of fields (`url`, `type`, `token_env`).
|
|
|
635
680
|
`--set` is available on `run`, `validate-config`, `info jobs`, and
|
|
636
681
|
`info tags`. Each `--set` is validated as its own source (like a separate
|
|
637
682
|
config file), so it can amend existing jobs but cannot introduce a brand-new
|
|
638
|
-
job across several flags
|
|
683
|
+
job across several flags - put a new job's required fields in one expression
|
|
639
684
|
(e.g. `--set 'job.x = {command = "…", title = "…"}'`) or a config file. An
|
|
640
685
|
unknown key or malformed value is reported with the offending `--set`
|
|
641
686
|
argument named.
|
|
@@ -648,14 +693,14 @@ a set of tags, with a smart default:
|
|
|
648
693
|
- a plain job (no `tags`, not `disabled`) carries the implicit `enabled`
|
|
649
694
|
tag;
|
|
650
695
|
- `disabled = true` is sugar for `tags = ["disabled"]`;
|
|
651
|
-
- setting `tags = [...]` uses exactly those tags
|
|
696
|
+
- setting `tags = [...]` uses exactly those tags - and, importantly, **drops
|
|
652
697
|
the implicit `enabled` tag** unless you list it yourself.
|
|
653
698
|
|
|
654
699
|
`repoactive run` with no arguments is shorthand for
|
|
655
700
|
`repoactive run --tag enabled`: it runs every job carrying `enabled`. Pass
|
|
656
701
|
`--tag`/`-t` (repeatable) to select a different set; a job runs if it
|
|
657
702
|
carries **any** of the requested tags. Naming jobs and passing tags can be
|
|
658
|
-
combined
|
|
703
|
+
combined - the selection is the union of the two.
|
|
659
704
|
|
|
660
705
|
```bash
|
|
661
706
|
# Run all jobs tagged "weekly" (regardless of whether they also have "enabled")
|
|
@@ -666,7 +711,7 @@ repoactive run --tag nightly regenerate-api-client
|
|
|
666
711
|
```
|
|
667
712
|
|
|
668
713
|
Requesting a tag that no job carries is an error, exactly like naming an
|
|
669
|
-
unknown job
|
|
714
|
+
unknown job - a typo in a crontab's `--tag` fails loudly instead of silently
|
|
670
715
|
running zero jobs. This also means a scheduled entry whose tag has lost its
|
|
671
716
|
last member fails until you remove the entry (or re-tag a job); a tag only
|
|
672
717
|
exists as a value on jobs, so an empty tag is indistinguishable from a
|
|
@@ -676,9 +721,9 @@ Because assigning a tag removes the implicit `enabled` tag, **tags are
|
|
|
676
721
|
load-bearing, not free-form labels**: tagging a job takes it out of the bare
|
|
677
722
|
`repoactive run`. If you want a job to stay in the default run _and_ belong
|
|
678
723
|
to a group, list both: `tags = ["enabled", "weekly"]`. (For MR/PR labels,
|
|
679
|
-
use `labels`
|
|
724
|
+
use `labels` - a separate concept.)
|
|
680
725
|
|
|
681
|
-
Tag selection is _explicit_ selection, so
|
|
726
|
+
Tag selection is _explicit_ selection, so - like naming a job - it ignores
|
|
682
727
|
the `enabled`/`disabled` defaults and force-includes dependencies. The bare
|
|
683
728
|
`repoactive run` is _implicit_ selection: a job whose dependency is not
|
|
684
729
|
itself selected is dropped
|
|
@@ -696,7 +741,7 @@ latest `trunk()` and the command is re-run against it. (With
|
|
|
696
741
|
`--mode push` it is just a branch.)
|
|
697
742
|
|
|
698
743
|
This means a job's schedule tag governs when a _new_ branch is created,
|
|
699
|
-
while the default run keeps an existing branch rebased and current
|
|
744
|
+
while the default run keeps an existing branch rebased and current - you
|
|
700
745
|
don't have to wait for the next weekly run to resolve a conflict with
|
|
701
746
|
`trunk()`. Once the branch lands, its commit becomes an ancestor of
|
|
702
747
|
`trunk()`, so the job drops back to its normal tag-driven cadence. (A
|
|
@@ -710,6 +755,13 @@ it out of normal runs; it is exactly sugar for `tags = ["disabled"]` (so the
|
|
|
710
755
|
two are mutually exclusive). The flag only affects the bare
|
|
711
756
|
`repoactive run`:
|
|
712
757
|
|
|
758
|
+
```toml
|
|
759
|
+
[job.experimental-refactor]
|
|
760
|
+
command = "./scripts/refactor.sh"
|
|
761
|
+
title = "chore: apply experimental refactor"
|
|
762
|
+
disabled = true
|
|
763
|
+
```
|
|
764
|
+
|
|
713
765
|
- On `repoactive run`, disabled jobs are skipped, along with any job that
|
|
714
766
|
`depends_on` one (its dependency would not be produced).
|
|
715
767
|
- Naming a job explicitly overrides it: `repoactive run my-job` runs
|
|
@@ -717,13 +769,13 @@ two are mutually exclusive). The flag only affects the bare
|
|
|
717
769
|
`repoactive run --tag disabled`, which runs everything currently turned
|
|
718
770
|
off.
|
|
719
771
|
|
|
720
|
-
|
|
772
|
+
## Running a job on a schedule
|
|
721
773
|
|
|
722
|
-
`repoactive` is not a daemon and has no built-in scheduler
|
|
774
|
+
`repoactive` is not a daemon and has no built-in scheduler - the cadence of
|
|
723
775
|
a job is whatever cadence you invoke it with. To run a job on a fixed
|
|
724
776
|
schedule, tag it and have an OS cron job select that tag. The tag keeps the
|
|
725
777
|
job out of the bare `repoactive run`, and the crontab decides the membership
|
|
726
|
-
in one place
|
|
778
|
+
in one place - add or remove `weekly` jobs by editing the config, not the
|
|
727
779
|
crontab:
|
|
728
780
|
|
|
729
781
|
```toml
|
|
@@ -740,18 +792,18 @@ tags = ["weekly"]
|
|
|
740
792
|
```
|
|
741
793
|
|
|
742
794
|
Because the cron is the sole trigger, the command runs exactly when cron
|
|
743
|
-
fires
|
|
795
|
+
fires - once, whether or not it produces a diff. This is more reliable than
|
|
744
796
|
inferring a schedule from `repoactive`'s own history: real cron is stateful
|
|
745
797
|
and excludes the other days, whereas `repoactive` only ever sees what has
|
|
746
798
|
_landed_ (see `cooldown_period` below).
|
|
747
799
|
|
|
748
|
-
|
|
800
|
+
### One run at a time per repository
|
|
749
801
|
|
|
750
802
|
A `repoactive run` takes an exclusive per-repository lock for its duration,
|
|
751
803
|
so two runs against the same repository never interleave (and corrupt each
|
|
752
804
|
other's branches and temporary workspaces). If a run is started while
|
|
753
|
-
another is still in progress
|
|
754
|
-
say
|
|
805
|
+
another is still in progress - a slow run overrunning the next cron tick,
|
|
806
|
+
say - the second one **exits immediately with status code 2** instead of
|
|
755
807
|
waiting or racing. That code is distinct from the generic failure code (1),
|
|
756
808
|
so a wrapper can treat "already running" as benign:
|
|
757
809
|
|
|
@@ -786,7 +838,7 @@ tags = ["weekly"]
|
|
|
786
838
|
Here `prek-run-all` is only useful when `prek-autoupdate` changed something:
|
|
787
839
|
if `prek-autoupdate` found no hooks to update, running `prek-run-all` would
|
|
788
840
|
produce an empty diff anyway. With `run_only_if_changed`, the skip is
|
|
789
|
-
explicit and immediate
|
|
841
|
+
explicit and immediate - `prek-run-all` never even starts.
|
|
790
842
|
|
|
791
843
|
Key behaviour:
|
|
792
844
|
|
|
@@ -796,7 +848,7 @@ Key behaviour:
|
|
|
796
848
|
skipped, it is treated as having produced no diff.
|
|
797
849
|
- **Dependents are unaffected.** A skipped job records a no-op result (like
|
|
798
850
|
a job on cooldown), so any job that `depends_on` it still runs on the base
|
|
799
|
-
branch
|
|
851
|
+
branch - the skip does not cascade.
|
|
800
852
|
- **No ordering constraint.** Names in `run_only_if_changed` do not have to
|
|
801
853
|
appear in `depends_on`. Any job that runs before this one in topological
|
|
802
854
|
order can be listed; in practice most usages name a direct dependency, as
|
|
@@ -825,6 +877,44 @@ runs: `repoactive` does not fetch, so a clone that has not pulled the merge
|
|
|
825
877
|
will not see the cooldown and will re-run the job. See
|
|
826
878
|
[Keeping the local clone current](#keeping-the-local-clone-current).
|
|
827
879
|
|
|
880
|
+
## Throttling a job when a superset lands with `cooldown_on`
|
|
881
|
+
|
|
882
|
+
Some jobs are strict supersets of others. `uv lock --upgrade` refreshes
|
|
883
|
+
every dependency group, so its diff already contains everything
|
|
884
|
+
`uv lock --upgrade-group=dev` would produce. Re-running the narrower job
|
|
885
|
+
right after the broad one landed just opens a redundant MR.
|
|
886
|
+
|
|
887
|
+
Listing the broader jobs in `cooldown_on` widens the narrow job's cooldown
|
|
888
|
+
check: it is throttled when **its own trailer or any listed job's trailer**
|
|
889
|
+
last landed within its `cooldown_period`. So once the full upgrade lands,
|
|
890
|
+
the group-scoped job stays quiet for the cooldown window instead of
|
|
891
|
+
re-running.
|
|
892
|
+
|
|
893
|
+
```toml
|
|
894
|
+
[job.full-lock]
|
|
895
|
+
command = "uv lock --upgrade"
|
|
896
|
+
title = "chore: update all dependencies"
|
|
897
|
+
cooldown_period = "7d"
|
|
898
|
+
|
|
899
|
+
[job.dev-lock]
|
|
900
|
+
command = "uv lock --upgrade-group=dev"
|
|
901
|
+
title = "chore: update dev dependencies"
|
|
902
|
+
cooldown_period = "7d"
|
|
903
|
+
cooldown_on = ["full-lock"]
|
|
904
|
+
```
|
|
905
|
+
|
|
906
|
+
`cooldown_on` requires a `cooldown_period` on the same job (its own or one
|
|
907
|
+
inherited from `[job-defaults]`); without a window there is nothing to
|
|
908
|
+
throttle against, so a config that sets one without the other is rejected.
|
|
909
|
+
The relationship is one-directional and needs no change to the broad job -
|
|
910
|
+
it still writes only its own trailer.
|
|
911
|
+
|
|
912
|
+
This only suppresses _starting_ a redundant run. A narrow job that already
|
|
913
|
+
has an open, unmerged branch is always refreshed regardless of cooldown (see
|
|
914
|
+
[Keeping unmerged branches current](#keeping-unmerged-branches-current)), so
|
|
915
|
+
its branch is rebased and, if the change is now redundant, self-closes on
|
|
916
|
+
the next run.
|
|
917
|
+
|
|
828
918
|
## Limiting job runtime with `timeout`
|
|
829
919
|
|
|
830
920
|
A job's `command` can hang or run away. Setting `timeout` caps how long the
|
|
@@ -840,10 +930,25 @@ zero duration (`timeout = "0s"`) disables the timeout entirely; since TOML
|
|
|
840
930
|
has no null value, this is how a job opts out of a timeout set in
|
|
841
931
|
`job-defaults`.
|
|
842
932
|
|
|
933
|
+
```toml
|
|
934
|
+
[job-defaults]
|
|
935
|
+
timeout = "10m" # raise the built-in 2m default for all jobs
|
|
936
|
+
|
|
937
|
+
[job.slow-codegen]
|
|
938
|
+
command = "./scripts/slow_codegen.sh"
|
|
939
|
+
title = "chore: regenerate bindings"
|
|
940
|
+
timeout = "30m" # this job needs extra time
|
|
941
|
+
|
|
942
|
+
[job.quick-lint]
|
|
943
|
+
command = "ruff check ."
|
|
944
|
+
title = "chore: fix lint"
|
|
945
|
+
timeout = "0s" # opt out of the timeout entirely
|
|
946
|
+
```
|
|
947
|
+
|
|
843
948
|
## Generating jobs dynamically
|
|
844
949
|
|
|
845
|
-
Sometimes the useful set of jobs depends on the repository's contents
|
|
846
|
-
job per package in a monorepo, one per entry in a manifest
|
|
950
|
+
Sometimes the useful set of jobs depends on the repository's contents - one
|
|
951
|
+
job per package in a monorepo, one per entry in a manifest - and you don't
|
|
847
952
|
want to hand-maintain them. A **generator** is an ordinary `[job.<name>]`
|
|
848
953
|
with `emits_jobs = true`. Instead of producing a diff, its command writes
|
|
849
954
|
one or more `*.toml` job fragments into the directory named by the
|
|
@@ -895,7 +1000,7 @@ Key points:
|
|
|
895
1000
|
> only re-run when the generator re-emits it, and the generator is gated by
|
|
896
1001
|
> the same landed commits (via the shared trailer). So overriding an emitted
|
|
897
1002
|
> job's `cooldown_period` only matters when you make it **longer** than the
|
|
898
|
-
> generator's
|
|
1003
|
+
> generator's - then the job stays throttled even after the generator has
|
|
899
1004
|
> run again. Making it **shorter** has no effect: while the generator is on
|
|
900
1005
|
> its own cooldown the job is never re-emitted, and by the time the
|
|
901
1006
|
> generator runs again the job's shorter window has long since elapsed
|
|
@@ -924,3 +1029,27 @@ design.
|
|
|
924
1029
|
- A GitLab or GitHub API token exposed via the environment variable named in
|
|
925
1030
|
`platform.token_env` (default: `GITHUB_TOKEN` for GitHub.com,
|
|
926
1031
|
`GITLAB_TOKEN` for GitLab.com)
|
|
1032
|
+
|
|
1033
|
+
## Appendix
|
|
1034
|
+
|
|
1035
|
+
### jj revset aliases
|
|
1036
|
+
|
|
1037
|
+
To query repoactive commits directly in jj, add these aliases to your
|
|
1038
|
+
repository config (`jj config set --repo`) or your global config
|
|
1039
|
+
(`jj config set --user`):
|
|
1040
|
+
|
|
1041
|
+
```toml
|
|
1042
|
+
[revset-aliases]
|
|
1043
|
+
'repoactive()' = 'description(regex:"(?m)^Repoactive-Job: ")'
|
|
1044
|
+
'repoactive_merged()' = 'repoactive() & ::trunk()'
|
|
1045
|
+
'repoactive_unmerged()' = 'repoactive() & ~(::trunk())'
|
|
1046
|
+
```
|
|
1047
|
+
|
|
1048
|
+
Then use them directly in jj:
|
|
1049
|
+
|
|
1050
|
+
```bash
|
|
1051
|
+
jj log -r 'repoactive()'
|
|
1052
|
+
jj log -r 'repoactive_unmerged()'
|
|
1053
|
+
jj log -r 'repoactive() & committer_date(after:"2025-01-01")'
|
|
1054
|
+
jj log -r 'repoactive() & description(regex:"(?m)^Repoactive-Job: uv-lock-upgrade$")'
|
|
1055
|
+
```
|