repoactive 0.3.1.dev3__tar.gz → 0.4.0.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.3.1.dev3 → repoactive-0.4.0.dev1}/PKG-INFO +345 -178
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/README.md +341 -175
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/pyproject.toml +4 -3
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/boxquote.py +14 -15
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/cli.py +13 -11
- repoactive-0.4.0.dev1/src/repoactive/command.py +171 -0
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/config.py +172 -56
- repoactive-0.4.0.dev1/src/repoactive/constants.py +43 -0
- repoactive-0.4.0.dev1/src/repoactive/generator.py +171 -0
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/graph.py +3 -3
- repoactive-0.4.0.dev1/src/repoactive/human_commits.py +114 -0
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/jj.py +235 -70
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/jobtree.py +9 -9
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/lock.py +6 -6
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/platforms/base.py +9 -0
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/platforms/github.py +17 -0
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/platforms/gitlab.py +21 -5
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/progress.py +14 -14
- repoactive-0.4.0.dev1/src/repoactive/runner.py +1298 -0
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/selection.py +30 -23
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/settings.py +7 -7
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/trailers.py +7 -7
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/ui.py +11 -11
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/updates.py +32 -9
- repoactive-0.3.1.dev3/src/repoactive/constants.py +0 -10
- repoactive-0.3.1.dev3/src/repoactive/runner.py +0 -1392
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/.gitignore +0 -0
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/LICENSE +0 -0
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/__init__.py +0 -0
- {repoactive-0.3.1.dev3 → repoactive-0.4.0.dev1}/src/repoactive/platforms/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: repoactive
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0.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
|
|
@@ -8,15 +8,16 @@ Classifier: Development Status :: 3 - Alpha
|
|
|
8
8
|
Classifier: Environment :: Console
|
|
9
9
|
Classifier: Intended Audience :: Developers
|
|
10
10
|
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
11
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
12
|
+
Classifier: Operating System :: POSIX
|
|
11
13
|
Classifier: Programming Language :: Python :: 3
|
|
12
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
13
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
14
15
|
Classifier: Programming Language :: Python :: 3.13
|
|
15
16
|
Classifier: Programming Language :: Python :: 3.14
|
|
16
17
|
Classifier: Topic :: Software Development
|
|
17
18
|
Classifier: Topic :: Software Development :: Version Control
|
|
18
19
|
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
19
|
-
Requires-Python: >=3.
|
|
20
|
+
Requires-Python: >=3.12
|
|
20
21
|
Requires-Dist: pydantic-settings>=2.14.2
|
|
21
22
|
Requires-Dist: pydantic<3.0.0,>=2.13.4
|
|
22
23
|
Requires-Dist: pygithub<3.0.0,>=2.9.1
|
|
@@ -27,28 +28,40 @@ Description-Content-Type: text/markdown
|
|
|
27
28
|
|
|
28
29
|
# repoactive - Script-driven code changes with automated merge requests
|
|
29
30
|
|
|
31
|
+
[](https://pypi.org/project/repoactive/)
|
|
32
|
+
[](https://github.com/schmir/repoactive/actions/workflows/ci.yml)
|
|
33
|
+
[](https://pypi.org/project/repoactive/)
|
|
34
|
+
[](LICENSE)
|
|
35
|
+
|
|
30
36
|
> **Warning:** This project is in an early stage of development. Use at your
|
|
31
37
|
> own risk.
|
|
32
38
|
|
|
33
39
|
`repoactive` runs your scripts against a git repository and optionally keeps
|
|
34
40
|
the corresponding merge requests up to date. You write the scripts that
|
|
35
41
|
produce the code changes; `repoactive` handles the rest - branches, commits,
|
|
36
|
-
and (with `--mode publish`) the full MR lifecycle.
|
|
42
|
+
and (with `--mode publish`) the full MR lifecycle. This document says merge
|
|
43
|
+
request (MR) throughout; on GitHub, read that as pull request (PR).
|
|
37
44
|
|
|
38
45
|
## Contents
|
|
39
46
|
|
|
40
47
|
- [Use cases](#use-cases)
|
|
48
|
+
- [How it compares](#how-it-compares)
|
|
41
49
|
- [Installation](#installation)
|
|
42
50
|
- [Quick start](#quick-start)
|
|
43
51
|
- [How it works](#how-it-works)
|
|
52
|
+
- [What a run produces](#what-a-run-produces)
|
|
44
53
|
- [Keeping the local clone current](#keeping-the-local-clone-current)
|
|
45
|
-
- [
|
|
54
|
+
- [Undoing a run](#undoing-a-run)
|
|
55
|
+
- [Commands](#commands)
|
|
56
|
+
- [`repoactive run`](#repoactive-run)
|
|
57
|
+
- [`repoactive recent-commits`](#repoactive-recent-commits)
|
|
58
|
+
- [`repoactive validate-config`](#repoactive-validate-config)
|
|
59
|
+
- [`repoactive dump-schema`](#repoactive-dump-schema)
|
|
60
|
+
- [`repoactive info jobs`](#repoactive-info-jobs)
|
|
61
|
+
- [`repoactive info tags`](#repoactive-info-tags)
|
|
46
62
|
- [Environment variables](#environment-variables)
|
|
47
|
-
- [Inspecting repoactive commits](#inspecting-repoactive-commits)
|
|
48
|
-
- [Validating configuration](#validating-configuration)
|
|
49
|
-
- [Listing jobs](#listing-jobs)
|
|
50
|
-
- [Listing tags](#listing-tags)
|
|
51
63
|
- [Configuration](#configuration)
|
|
64
|
+
- [Editor support](#editor-support)
|
|
52
65
|
- [`[job-defaults]`](#job-defaults)
|
|
53
66
|
- [`[job.<name>]`](#jobname)
|
|
54
67
|
- [Stacking MRs](#stacking-mrs)
|
|
@@ -58,19 +71,20 @@ and (with `--mode publish`) the full MR lifecycle.
|
|
|
58
71
|
- [Variables passed to job commands](#variables-passed-to-job-commands)
|
|
59
72
|
- [Passing secrets to commands with `secret_env`](#passing-secrets-to-commands-with-secret_env)
|
|
60
73
|
- [Overriding values on the command line](#overriding-values-on-the-command-line)
|
|
61
|
-
- [
|
|
62
|
-
- [
|
|
63
|
-
- [Disabling jobs](#disabling-jobs)
|
|
64
|
-
- [Running a job on a schedule](#running-a-job-on-a-schedule)
|
|
65
|
-
- [
|
|
66
|
-
- [
|
|
67
|
-
- [Throttling
|
|
68
|
-
- [
|
|
69
|
-
- [
|
|
70
|
-
- [Generating jobs dynamically](#generating-jobs-dynamically)
|
|
74
|
+
- [Run control](#run-control)
|
|
75
|
+
- [Selecting jobs with tags](#selecting-jobs-with-tags)
|
|
76
|
+
- [Disabling jobs](#disabling-jobs)
|
|
77
|
+
- [Running a job on a schedule](#running-a-job-on-a-schedule)
|
|
78
|
+
- [Gating jobs with `run_only_if_changed`](#gating-jobs-with-run_only_if_changed)
|
|
79
|
+
- [Throttling jobs with `cooldown_period`](#throttling-jobs-with-cooldown_period)
|
|
80
|
+
- [Throttling a job when a superset lands with `cooldown_on`](#throttling-a-job-when-a-superset-lands-with-cooldown_on)
|
|
81
|
+
- [Limiting job runtime with `timeout`](#limiting-job-runtime-with-timeout)
|
|
82
|
+
- [Generating jobs dynamically](#generating-jobs-dynamically)
|
|
71
83
|
- [Requirements](#requirements)
|
|
72
84
|
- [Appendix](#appendix)
|
|
73
85
|
- [jj revset aliases](#jj-revset-aliases)
|
|
86
|
+
- [Changelog](#changelog)
|
|
87
|
+
- [License](#license)
|
|
74
88
|
|
|
75
89
|
## Use cases
|
|
76
90
|
|
|
@@ -81,6 +95,23 @@ and (with `--mode publish`) the full MR lifecycle.
|
|
|
81
95
|
- Automating any periodic code transformation that should go through a
|
|
82
96
|
review process
|
|
83
97
|
|
|
98
|
+
### How it compares
|
|
99
|
+
|
|
100
|
+
[Renovate](https://docs.renovatebot.com/) and
|
|
101
|
+
[Dependabot](https://docs.github.com/en/code-security/dependabot) are built
|
|
102
|
+
around dependency updates; repoactive runs whatever script you write, so the
|
|
103
|
+
change can be anything the repository generates - a lock-file upgrade is
|
|
104
|
+
just the simplest case.
|
|
105
|
+
[multi-gitter](https://github.com/lindell/multi-gitter) also runs your
|
|
106
|
+
script and opens the MR, but as a one-shot bulk operation across
|
|
107
|
+
repositories; repoactive is built for re-running against one repository: an
|
|
108
|
+
unchanged diff leaves the MR untouched, a changed one updates it, branches
|
|
109
|
+
are rebased onto the moving base branch, cooldowns keep a landed change from
|
|
110
|
+
immediately reopening, and jobs can stack their MRs on one another. And it
|
|
111
|
+
is a plain CLI working against your local clone - no hosted service and
|
|
112
|
+
nothing to install into the repository - that talks to GitHub and GitLab,
|
|
113
|
+
including self-hosted instances.
|
|
114
|
+
|
|
84
115
|
## Installation
|
|
85
116
|
|
|
86
117
|
`repoactive` is published on [PyPI](https://pypi.org/project/repoactive/).
|
|
@@ -125,13 +156,25 @@ needs a GitHub or GitLab API token in the environment. See
|
|
|
125
156
|
4. **Run the job locally.** In the default `local` mode nothing is pushed
|
|
126
157
|
and no MR is created - repoactive just records the diff your script
|
|
127
158
|
produced on the branch `repoactive/uv-lock-upgrade` and prints a
|
|
128
|
-
`jj op restore` command to undo the run:
|
|
159
|
+
`jj op restore` command to [undo the run](#undoing-a-run):
|
|
129
160
|
|
|
130
161
|
```bash
|
|
131
162
|
repoactive run
|
|
132
163
|
```
|
|
133
164
|
|
|
134
|
-
5. **
|
|
165
|
+
5. **Look at what it produced.** The change lives on the job's branch, so
|
|
166
|
+
your own working copy still looks untouched:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
repoactive recent-commits # every repoactive commit, newest first
|
|
170
|
+
jj diff -r repoactive/uv-lock-upgrade # the diff the script produced
|
|
171
|
+
git show repoactive/uv-lock-upgrade # the same, through colocated git
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
The appendix has [jj revset aliases](#jj-revset-aliases) for querying
|
|
175
|
+
repoactive's commits directly.
|
|
176
|
+
|
|
177
|
+
6. **Publish it.** Put the API token your platform uses in the environment
|
|
135
178
|
(`GITHUB_TOKEN` for GitHub.com, `GITLAB_TOKEN` for GitLab.com by
|
|
136
179
|
default), fetch the latest base branch, then let repoactive push the
|
|
137
180
|
branch and open - or update - the merge request:
|
|
@@ -148,9 +191,9 @@ needs a GitHub or GitLab API token in the environment. See
|
|
|
148
191
|
## How it works
|
|
149
192
|
|
|
150
193
|
You configure one or more **jobs**, each with a script (any shell command or
|
|
151
|
-
executable) that modifies the repository's
|
|
152
|
-
|
|
153
|
-
|
|
194
|
+
executable) that modifies the repository's files. `repoactive` runs each
|
|
195
|
+
script, captures the resulting diff, and records the change locally. With
|
|
196
|
+
`--mode publish` it also:
|
|
154
197
|
|
|
155
198
|
- opens a new merge request if one does not already exist for that job, or
|
|
156
199
|
- updates the existing merge request branch if the diff has changed.
|
|
@@ -158,17 +201,18 @@ With `--mode publish` it also:
|
|
|
158
201
|
Branches and MR descriptions are managed automatically - the only code you
|
|
159
202
|
need to write is the script that produces the change.
|
|
160
203
|
|
|
161
|
-
```
|
|
162
|
-
[your script] → diff → repoactive → branch
|
|
163
|
-
↓ (with --mode push or --mode publish)
|
|
164
|
-
git push → merge request
|
|
165
|
-
↑ (with --mode publish)
|
|
166
|
-
(create or update)
|
|
167
|
-
```
|
|
168
|
-
|
|
169
204
|
1. `repoactive` creates a new commit on top of the base branch or on top of
|
|
170
|
-
other repoactive managed branches
|
|
171
|
-
|
|
205
|
+
other repoactive managed branches, and checks that commit out into a
|
|
206
|
+
temporary jj workspace.
|
|
207
|
+
2. It runs the job's script in that workspace, which is also the script's
|
|
208
|
+
working directory. **Your own working copy is never touched** - a run is
|
|
209
|
+
safe with uncommitted changes in your checkout, and the script sees a
|
|
210
|
+
clean tree at the base branch rather than whatever you have lying around.
|
|
211
|
+
The workspace is a full checkout, so paths relative to the repository
|
|
212
|
+
root resolve normally; [`RA_WORKSPACE_DIR`](#ra_workspace_dir) names it
|
|
213
|
+
for scripts that change directory, and
|
|
214
|
+
[`RA_CONFIG_SOURCE_DIR`](#ra_config_source_dir) reaches helper files kept
|
|
215
|
+
beside the config. The workspace is discarded when the job finishes.
|
|
172
216
|
3. If the script produced a diff, it records the change. With `--mode push`
|
|
173
217
|
or `--mode publish`, it pushes the branch; with `--mode publish`, it also
|
|
174
218
|
creates or updates the merge request. On a re-run, if the diff matches
|
|
@@ -183,20 +227,63 @@ need to write is the script that produces the change.
|
|
|
183
227
|
is now stale, so it is deleted; with `--mode push` or `--mode publish`,
|
|
184
228
|
the deletion is pushed to the remote.
|
|
185
229
|
|
|
186
|
-
> **jj commits the whole
|
|
187
|
-
> new file your script creates inside the
|
|
188
|
-
>
|
|
189
|
-
>
|
|
190
|
-
>
|
|
191
|
-
>
|
|
230
|
+
> **jj commits the whole workspace.** Because `repoactive` uses jj, every
|
|
231
|
+
> new file your script creates inside the workspace is added to the commit
|
|
232
|
+
> unless it is git-ignored. There is no way to select which of the script's
|
|
233
|
+
> changes become part of the commit - they all will. Keep `.gitignore` up to
|
|
234
|
+
> date so build artifacts, caches, and other stray files your script
|
|
235
|
+
> produces do not end up in the diff.
|
|
236
|
+
|
|
237
|
+
### What a run produces
|
|
238
|
+
|
|
239
|
+
For the quick-start job above, a `--mode publish` run pushes the branch
|
|
240
|
+
`repoactive/uv-lock-upgrade` and opens an MR titled
|
|
241
|
+
`[repoactive] build: upgrade dependencies`. Its description holds the job's
|
|
242
|
+
`description` (when set), the command and its captured output in a code
|
|
243
|
+
block, and - for [stacked jobs](#stacking-mrs) - links to the parent MRs
|
|
244
|
+
([a real example](https://github.com/schmir/repoactive/pull/7)):
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
$ uv lock --upgrade
|
|
248
|
+
Using CPython 3.14.1
|
|
249
|
+
Resolved 51 packages in 4.19s
|
|
250
|
+
Updated annotated-types v0.7.0 -> v0.8.0
|
|
251
|
+
Updated nox v2026.4.10 -> v2026.7.11
|
|
252
|
+
Updated ruff v0.15.21 -> v0.16.0
|
|
253
|
+
Updated ty v0.0.58 -> v0.0.63
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
The commit carries the same output (unless `output_in_commit` is disabled)
|
|
257
|
+
plus the `Repoactive-Job` trailer that
|
|
258
|
+
[`recent-commits`](#repoactive-recent-commits), the
|
|
259
|
+
[cooldown check](#throttling-jobs-with-cooldown_period), and the
|
|
260
|
+
[unmerged-branch refresh](#keeping-unmerged-branches-current) all key on:
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
[repoactive] build: upgrade dependencies
|
|
264
|
+
|
|
265
|
+
,----[ uv lock --upgrade ]
|
|
266
|
+
| Using CPython 3.14.1
|
|
267
|
+
| Resolved 51 packages in 4.19s
|
|
268
|
+
| Updated annotated-types v0.7.0 -> v0.8.0
|
|
269
|
+
| Updated nox v2026.4.10 -> v2026.7.11
|
|
270
|
+
| Updated ruff v0.15.21 -> v0.16.0
|
|
271
|
+
| Updated ty v0.0.58 -> v0.0.63
|
|
272
|
+
`----
|
|
273
|
+
|
|
274
|
+
Repoactive-Job: uv-lock-upgrade
|
|
275
|
+
```
|
|
192
276
|
|
|
193
277
|
### Keeping the local clone current
|
|
194
278
|
|
|
195
279
|
`repoactive` works entirely from the **local** repository view and never
|
|
196
|
-
fetches from the remote on its own.
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
280
|
+
fetches from the remote on its own. Jobs target `trunk()` unless they set a
|
|
281
|
+
`base_branch` - that is jj's built-in revset for the tip of the repository's
|
|
282
|
+
main branch (`main@origin`, `master@origin`, and friends), as the local
|
|
283
|
+
clone last saw it. Rebasing onto `trunk()`, cooldown throttling, and the
|
|
284
|
+
unmerged-branch refresh all read the local `trunk()` / base branches, so a
|
|
285
|
+
merge that happened on the remote is invisible until the local clone
|
|
286
|
+
advances past it.
|
|
200
287
|
|
|
201
288
|
**Fetch before each run.** Run `jj git fetch` (or `git fetch --prune`) in
|
|
202
289
|
the same cron job or CI pipeline that invokes `repoactive`, before it. If
|
|
@@ -206,13 +293,42 @@ because the commit that would trigger it has not reached the local base
|
|
|
206
293
|
branch. See
|
|
207
294
|
[ADR 0005](docs/adr/0005-local-repository-is-the-source-of-truth.md).
|
|
208
295
|
|
|
209
|
-
|
|
296
|
+
### Undoing a run
|
|
297
|
+
|
|
298
|
+
Every `run` captures the jj operation id beforehand and prints a
|
|
299
|
+
`jj op restore <id>` command at the end of the run (last, since a run can
|
|
300
|
+
produce a lot of output). Run it to roll the local repository - commits,
|
|
301
|
+
bookmarks and colocated git refs - back to the state it was in before the
|
|
302
|
+
run. It only undoes local changes: a branch already pushed or an MR already
|
|
303
|
+
created by a `--mode push`/`--mode publish` run is not affected, as the hint
|
|
304
|
+
panel itself points out.
|
|
305
|
+
|
|
306
|
+
## Commands
|
|
210
307
|
|
|
211
308
|
```bash
|
|
212
309
|
# Print the installed version and exit
|
|
213
310
|
repoactive --version
|
|
214
311
|
```
|
|
215
312
|
|
|
313
|
+
Every command that works against a repository accepts `--repo`/`-r` and
|
|
314
|
+
`--debug`/`-d`. The commands that read configuration - `run`,
|
|
315
|
+
`validate-config`, `info jobs`, and `info tags` - also accept the same
|
|
316
|
+
`--config`/`-c` and `--set`/`-s` options, described in the
|
|
317
|
+
[`repoactive run`](#repoactive-run) table below. `recent-commits` works from
|
|
318
|
+
the repository alone and reads no configuration;
|
|
319
|
+
[`dump-schema`](#repoactive-dump-schema) touches no repository at all and
|
|
320
|
+
takes only `--output`.
|
|
321
|
+
|
|
322
|
+
All commands exit with these status codes:
|
|
323
|
+
|
|
324
|
+
| Code | Meaning |
|
|
325
|
+
| ---- | ------------------------------------------------------------------------------------------ |
|
|
326
|
+
| 0 | Success |
|
|
327
|
+
| 1 | Failure (invalid configuration, a failed job, ...) |
|
|
328
|
+
| 2 | `run` only: another run holds the [per-repository lock](#one-run-at-a-time-per-repository) |
|
|
329
|
+
|
|
330
|
+
### `repoactive run`
|
|
331
|
+
|
|
216
332
|
```
|
|
217
333
|
repoactive run [OPTIONS] [JOBS]...
|
|
218
334
|
```
|
|
@@ -249,64 +365,7 @@ repoactive run --debug
|
|
|
249
365
|
| `--tag TAG` | `-t` | Run jobs carrying any of these tags (repeatable). With no tags/jobs the default run targets the `enabled` tag |
|
|
250
366
|
| `--debug` | `-d` | Enable debug logging |
|
|
251
367
|
|
|
252
|
-
###
|
|
253
|
-
|
|
254
|
-
Besides the command-line options, repoactive reads a few `REPOACTIVE_*`
|
|
255
|
-
environment variables that tune how it presents itself in the current
|
|
256
|
-
environment (as opposed to the [configuration](#configuration), which
|
|
257
|
-
describes the jobs to run). They are handled uniformly: all of them go
|
|
258
|
-
through a single settings model and are validated together at startup, so a
|
|
259
|
-
misconfigured variable fails immediately with a one-line error naming it
|
|
260
|
-
instead of surfacing mid-run or being silently ignored. Values are
|
|
261
|
-
case-insensitive.
|
|
262
|
-
|
|
263
|
-
#### `REPOACTIVE_UI`
|
|
264
|
-
|
|
265
|
-
`interactive` (default) or `noninteractive`.
|
|
266
|
-
|
|
267
|
-
Every `run` captures the jj operation id beforehand and prints a
|
|
268
|
-
`jj op restore <id>` command at the end of the run (last, since a run can
|
|
269
|
-
produce a lot of output). Run it to roll the local repository - commits,
|
|
270
|
-
bookmarks and colocated git refs - back to the state it was in before the
|
|
271
|
-
run. It only undoes local changes: a branch already pushed or an MR already
|
|
272
|
-
created by a `--mode push`/`--mode publish` run is not affected, as the hint
|
|
273
|
-
panel itself points out.
|
|
274
|
-
|
|
275
|
-
`noninteractive` suppresses these "how to undo" hint panels. Set it where
|
|
276
|
-
nobody is at the keyboard, say an unattended CI job. This is an explicit
|
|
277
|
-
switch rather than CI auto-detection, because a CI container someone has
|
|
278
|
-
logged in to _is_ interactive.
|
|
279
|
-
|
|
280
|
-
#### `REPOACTIVE_LOG_LEVEL`
|
|
281
|
-
|
|
282
|
-
`debug`, `info`, `warning`, `error`, or `critical`; unset by default
|
|
283
|
-
(logging off).
|
|
284
|
-
|
|
285
|
-
Enables logging at that level without passing `--debug` on every invocation;
|
|
286
|
-
an explicit `--debug` takes precedence.
|
|
287
|
-
|
|
288
|
-
#### `REPOACTIVE_LOG_HANDLER`
|
|
289
|
-
|
|
290
|
-
`rich` or `plain`; defaults to `rich`, or `plain` when `REPOACTIVE_UI` is
|
|
291
|
-
`noninteractive`.
|
|
292
|
-
|
|
293
|
-
How log records are rendered: a colorized column layout via
|
|
294
|
-
[rich](https://github.com/Textualize/rich), or the stdlib's plain stream
|
|
295
|
-
handler (e.g. when the output is collected by a log aggregator).
|
|
296
|
-
|
|
297
|
-
#### `REPOACTIVE_PROGRESS_LINES`
|
|
298
|
-
|
|
299
|
-
An integer (default: `8`).
|
|
300
|
-
|
|
301
|
-
While a job's command runs in an interactive terminal, repoactive shows a
|
|
302
|
-
live, scrolling block of its most recent output lines. The block stays on
|
|
303
|
-
screen once the command finishes, with the job's status line printed below
|
|
304
|
-
it. `REPOACTIVE_PROGRESS_LINES` sets how many lines that live tail shows;
|
|
305
|
-
`0` or less disables the live block entirely. When output is not a terminal
|
|
306
|
-
(piped or in CI) the block is disabled and the command's output is left
|
|
307
|
-
untouched.
|
|
308
|
-
|
|
309
|
-
## Inspecting repoactive commits
|
|
368
|
+
### `repoactive recent-commits`
|
|
310
369
|
|
|
311
370
|
```
|
|
312
371
|
repoactive recent-commits [OPTIONS] [JOBS]...
|
|
@@ -339,7 +398,7 @@ repoactive recent-commits --status unmerged
|
|
|
339
398
|
| `--status [all\|merged\|unmerged]` | `-s` | Filter by merge status into trunk (default: `all`) |
|
|
340
399
|
| `--debug` | `-d` | Enable debug logging |
|
|
341
400
|
|
|
342
|
-
|
|
401
|
+
### `repoactive validate-config`
|
|
343
402
|
|
|
344
403
|
```
|
|
345
404
|
repoactive validate-config [OPTIONS]
|
|
@@ -366,10 +425,29 @@ code 1.
|
|
|
366
425
|
Validation checks include unknown keys, missing required fields, invalid
|
|
367
426
|
`depends_on` references, and circular job dependencies.
|
|
368
427
|
|
|
369
|
-
|
|
370
|
-
|
|
428
|
+
### `repoactive dump-schema`
|
|
429
|
+
|
|
430
|
+
```
|
|
431
|
+
repoactive dump-schema --output PATH
|
|
432
|
+
```
|
|
371
433
|
|
|
372
|
-
|
|
434
|
+
Write the JSON schema of the TOML config to a file. Use it to pin the schema
|
|
435
|
+
your editor validates against to the version you have installed, rather than
|
|
436
|
+
the published one:
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
repoactive dump-schema -o config-schema.json
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
See [Editor support](#editor-support) for wiring it up. Unlike the other
|
|
443
|
+
commands this one only reads the installed models, so it takes neither
|
|
444
|
+
`--repo` nor `--debug`.
|
|
445
|
+
|
|
446
|
+
| Option | Short | Description |
|
|
447
|
+
| --------------- | ----- | -------------------------------------- |
|
|
448
|
+
| `--output PATH` | `-o` | File to write the schema to (required) |
|
|
449
|
+
|
|
450
|
+
### `repoactive info jobs`
|
|
373
451
|
|
|
374
452
|
```
|
|
375
453
|
repoactive info jobs [OPTIONS]
|
|
@@ -393,10 +471,7 @@ build Build the project enabled
|
|
|
393
471
|
└── deploy Deploy to staging nightly, risky
|
|
394
472
|
```
|
|
395
473
|
|
|
396
|
-
|
|
397
|
-
options as [`repoactive run`](#usage).
|
|
398
|
-
|
|
399
|
-
## Listing tags
|
|
474
|
+
### `repoactive info tags`
|
|
400
475
|
|
|
401
476
|
```
|
|
402
477
|
repoactive info tags [OPTIONS]
|
|
@@ -428,8 +503,54 @@ nightly:
|
|
|
428
503
|
benchmark Run nightly benchmarks nightly
|
|
429
504
|
```
|
|
430
505
|
|
|
431
|
-
|
|
432
|
-
|
|
506
|
+
### Environment variables
|
|
507
|
+
|
|
508
|
+
Besides the command-line options, repoactive reads a few `REPOACTIVE_*`
|
|
509
|
+
environment variables that tune how it presents itself in the current
|
|
510
|
+
environment (as opposed to the [configuration](#configuration), which
|
|
511
|
+
describes the jobs to run). They are handled uniformly: all of them go
|
|
512
|
+
through a single settings model and are validated together at startup, so a
|
|
513
|
+
misconfigured variable fails immediately with a one-line error naming it
|
|
514
|
+
instead of surfacing mid-run or being silently ignored. Values are
|
|
515
|
+
case-insensitive.
|
|
516
|
+
|
|
517
|
+
#### `REPOACTIVE_UI`
|
|
518
|
+
|
|
519
|
+
`interactive` (default) or `noninteractive`.
|
|
520
|
+
|
|
521
|
+
`noninteractive` suppresses the ["how to undo" hint panels](#undoing-a-run)
|
|
522
|
+
printed after each run. Set it where nobody is at the keyboard, say an
|
|
523
|
+
unattended CI job. This is an explicit switch rather than CI auto-detection,
|
|
524
|
+
because a CI container someone has logged in to _is_ interactive.
|
|
525
|
+
|
|
526
|
+
#### `REPOACTIVE_LOG_LEVEL`
|
|
527
|
+
|
|
528
|
+
`debug`, `info`, `warning`, `error`, or `critical`; unset by default
|
|
529
|
+
(logging off).
|
|
530
|
+
|
|
531
|
+
Enables logging at that level without passing `--debug` on every invocation;
|
|
532
|
+
an explicit `--debug` takes precedence.
|
|
533
|
+
|
|
534
|
+
#### `REPOACTIVE_LOG_HANDLER`
|
|
535
|
+
|
|
536
|
+
`rich` or `plain`; defaults to `rich`, or `plain` when `REPOACTIVE_UI` is
|
|
537
|
+
`noninteractive`.
|
|
538
|
+
|
|
539
|
+
How log records are rendered: a colorized column layout via
|
|
540
|
+
[rich](https://github.com/Textualize/rich), or the stdlib's plain stream
|
|
541
|
+
handler (e.g. when the output is collected by a log aggregator).
|
|
542
|
+
|
|
543
|
+
#### `REPOACTIVE_PROGRESS_LINES`
|
|
544
|
+
|
|
545
|
+
An integer (default: `8`).
|
|
546
|
+
|
|
547
|
+
While a job's command runs in an interactive terminal, repoactive shows a
|
|
548
|
+
live, scrolling block of its most recent output lines. The block stays on
|
|
549
|
+
screen once the command finishes, with the job's status line printed below
|
|
550
|
+
it. `REPOACTIVE_PROGRESS_LINES` sets how many lines that live tail shows;
|
|
551
|
+
`0` or less disables the live block entirely. When output is not a terminal
|
|
552
|
+
(piped or in CI) the block is disabled and the command's output is left
|
|
553
|
+
untouched.
|
|
433
554
|
|
|
434
555
|
## Configuration
|
|
435
556
|
|
|
@@ -450,16 +571,37 @@ Every key in `[job-defaults]` supplies the default for the matching per-job
|
|
|
450
571
|
key; any job may override it by setting the same key in its `[job.<name>]`
|
|
451
572
|
block.
|
|
452
573
|
|
|
574
|
+
### Editor support
|
|
575
|
+
|
|
576
|
+
`repoactive` publishes a JSON schema for the config format, so an editor
|
|
577
|
+
with TOML schema support (Even Better TOML in VS Code, Taplo, the JetBrains
|
|
578
|
+
TOML plugin) can complete field names, show what each one does, and flag
|
|
579
|
+
typos as you type - useful given how many optional keys a job accepts. Point
|
|
580
|
+
the `"$schema"` key at the published schema:
|
|
581
|
+
|
|
582
|
+
```toml
|
|
583
|
+
"$schema" = "https://raw.githubusercontent.com/schmir/repoactive/refs/heads/main/config-schema.json"
|
|
584
|
+
|
|
585
|
+
[job.uv-lock-upgrade]
|
|
586
|
+
command = "uv lock --upgrade"
|
|
587
|
+
title = "build: upgrade dependencies"
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
`"$schema"` is part of the config format: `repoactive` accepts it and
|
|
591
|
+
ignores it. The URL above tracks `main`; to validate against the version you
|
|
592
|
+
actually have installed, write the schema out with
|
|
593
|
+
[`repoactive dump-schema`](#repoactive-dump-schema) and point `"$schema"` at
|
|
594
|
+
that file instead.
|
|
595
|
+
|
|
453
596
|
### `[job-defaults]`
|
|
454
597
|
|
|
455
|
-
**MR
|
|
598
|
+
**MR options:**
|
|
456
599
|
|
|
457
|
-
- **`labels`** (default: `[]`) - Labels applied to every MR
|
|
600
|
+
- **`labels`** (default: `[]`) - Labels applied to every MR. Per-job
|
|
458
601
|
`labels` are merged with, not replaced by, this list.
|
|
459
602
|
- **`auto_merge`** (default: `false`) - When `true`, enable auto-merge on
|
|
460
|
-
every MR
|
|
461
|
-
|
|
462
|
-
settings.
|
|
603
|
+
every MR so it merges automatically once its pipeline passes. On GitHub,
|
|
604
|
+
the repository must have "Allow auto-merge" enabled in its settings.
|
|
463
605
|
- **`required_approvals`** (default: none) - Minimum number of approvals
|
|
464
606
|
required before the MR can be merged. **GitLab only** - this sets the
|
|
465
607
|
per-MR approval requirement. GitHub has no per-PR equivalent (required
|
|
@@ -474,12 +616,13 @@ block.
|
|
|
474
616
|
no job is named after your base branch (e.g. a job named `main`) - the two
|
|
475
617
|
branches would otherwise collide.
|
|
476
618
|
- **`mr_title_prefix`** (default: `"[repoactive] "`) - Prefix prepended to
|
|
477
|
-
every MR
|
|
619
|
+
every MR title. Set to `""` to disable.
|
|
478
620
|
- **`commit_title_prefix`** (default: `"[repoactive] "`) - Prefix prepended
|
|
479
621
|
to every commit title. Set to `""` to disable.
|
|
480
|
-
- **`base_branch`** (default:
|
|
481
|
-
|
|
482
|
-
`trunk()`, `root()`,
|
|
622
|
+
- **`base_branch`** (default: `trunk()`, the repository's main branch as the
|
|
623
|
+
local clone last saw it) - Target branch for all jobs that do not set
|
|
624
|
+
their own. May also be a jj revset expression such as `trunk()`, `root()`,
|
|
625
|
+
or a user-defined revset alias.
|
|
483
626
|
|
|
484
627
|
**Run control:**
|
|
485
628
|
|
|
@@ -511,37 +654,38 @@ underscores.
|
|
|
511
654
|
|
|
512
655
|
**Required:**
|
|
513
656
|
|
|
514
|
-
- **`command`** - Shell command (or executable path) run in the
|
|
515
|
-
|
|
516
|
-
|
|
657
|
+
- **`command`** - Shell command (or executable path) run in the job's
|
|
658
|
+
temporary workspace, not in your checkout (see
|
|
659
|
+
[How it works](#how-it-works)). A non-zero exit is a failure.
|
|
660
|
+
- **`title`** - MR title (also the commit subject, after
|
|
517
661
|
`commit_title_prefix`).
|
|
518
662
|
|
|
519
|
-
**MR
|
|
663
|
+
**MR options:**
|
|
520
664
|
|
|
521
|
-
- **`description`** - Body text of the MR
|
|
522
|
-
- **`labels`** (default: `[]`) - Extra labels for this job's MR
|
|
523
|
-
|
|
524
|
-
- **`draft`** (default: `false`) - Open the MR
|
|
525
|
-
|
|
526
|
-
- **`create_mr`** (default: `true`) - Whether to create an MR
|
|
665
|
+
- **`description`** - Body text of the MR.
|
|
666
|
+
- **`labels`** (default: `[]`) - Extra labels for this job's MR, merged with
|
|
667
|
+
`job-defaults.labels`.
|
|
668
|
+
- **`draft`** (default: `false`) - Open the MR as a draft. On GitHub, draft
|
|
669
|
+
state cannot be changed after creation.
|
|
670
|
+
- **`create_mr`** (default: `true`) - Whether to create an MR: `true`
|
|
527
671
|
(always), `false` (push the branch but skip the MR), or
|
|
528
672
|
`"unless-superseded"` (skip when a dependent's MR from the same run
|
|
529
673
|
already contains this job's changes - see [Stacking MRs](#stacking-mrs)).
|
|
530
674
|
- **`auto_merge`** (default: inherited from `job-defaults`) - When `true`,
|
|
531
|
-
enable auto-merge on this job's MR
|
|
675
|
+
enable auto-merge on this job's MR.
|
|
532
676
|
- **`required_approvals`** (default: inherited from `job-defaults`) -
|
|
533
677
|
Minimum number of approvals required before this job's MR can be merged.
|
|
534
678
|
GitLab only; see `job-defaults.required_approvals`.
|
|
535
679
|
|
|
536
680
|
**Branch and commit options:**
|
|
537
681
|
|
|
538
|
-
- **`base_branch`** (default: inherited) - Target
|
|
539
|
-
MR
|
|
540
|
-
a user-defined revset alias.
|
|
682
|
+
- **`base_branch`** (default: inherited, ultimately `trunk()`) - Target
|
|
683
|
+
branch for this job's MR. May also be a jj revset expression such as
|
|
684
|
+
`trunk()`, `root()`, or a user-defined revset alias.
|
|
541
685
|
- **`branch_prefix`** (default: inherited) - Override the branch-name prefix
|
|
542
686
|
for this job only.
|
|
543
|
-
- **`mr_title_prefix`** (default: inherited) - Override the MR
|
|
544
|
-
|
|
687
|
+
- **`mr_title_prefix`** (default: inherited) - Override the MR title prefix
|
|
688
|
+
for this job only.
|
|
545
689
|
- **`commit_title_prefix`** (default: inherited) - Override the commit title
|
|
546
690
|
prefix for this job only.
|
|
547
691
|
- **`output_in_commit`** (default: `true`) - Append the job's command and
|
|
@@ -599,14 +743,13 @@ Because a dependent's MR already contains its dependencies' changes, a
|
|
|
599
743
|
dependency chain normally opens one MR per job that produced a diff. Setting
|
|
600
744
|
`create_mr = "unless-superseded"` on the earlier jobs collapses that: such a
|
|
601
745
|
job skips its MR when a dependent job produced an MR in the same run, so the
|
|
602
|
-
chain yields a single MR on the topmost job that actually changed
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
limitations.
|
|
746
|
+
chain yields a single MR on the topmost job that actually changed
|
|
747
|
+
something - falling back to the job below it when the jobs above came up
|
|
748
|
+
empty. The branch is still pushed either way. Only the current run counts: a
|
|
749
|
+
dependent that is empty, failed, on cooldown, or not selected does not
|
|
750
|
+
suppress anything. See
|
|
751
|
+
[ADR 0009](docs/adr/0009-unless-superseded-mr-creation.md) for details and
|
|
752
|
+
limitations.
|
|
610
753
|
|
|
611
754
|
### Example
|
|
612
755
|
|
|
@@ -718,9 +861,8 @@ title = "run the shared check script for this job"
|
|
|
718
861
|
|
|
719
862
|
#### `RA_WORKSPACE_DIR`
|
|
720
863
|
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
that changes directory can still find its way back:
|
|
864
|
+
`RA_WORKSPACE_DIR` names the job's [temporary workspace](#how-it-works)
|
|
865
|
+
explicitly, so a command that changes directory can still find its way back:
|
|
724
866
|
|
|
725
867
|
```toml
|
|
726
868
|
[job.build]
|
|
@@ -882,7 +1024,13 @@ job across several flags - put a new job's required fields in one expression
|
|
|
882
1024
|
unknown key or malformed value is reported with the offending `--set`
|
|
883
1025
|
argument named.
|
|
884
1026
|
|
|
885
|
-
##
|
|
1027
|
+
## Run control
|
|
1028
|
+
|
|
1029
|
+
The sections below cover the run-control options from the
|
|
1030
|
+
[configuration reference](#jobname) in detail: which jobs a run selects, how
|
|
1031
|
+
to schedule and throttle them, and how to generate jobs dynamically.
|
|
1032
|
+
|
|
1033
|
+
### Selecting jobs with tags
|
|
886
1034
|
|
|
887
1035
|
Which jobs a `repoactive run` touches is decided by **tags**. Every job has
|
|
888
1036
|
a set of tags, with a smart default:
|
|
@@ -917,8 +1065,8 @@ mistyped one.
|
|
|
917
1065
|
Because assigning a tag removes the implicit `enabled` tag, **tags are
|
|
918
1066
|
load-bearing, not free-form labels**: tagging a job takes it out of the bare
|
|
919
1067
|
`repoactive run`. If you want a job to stay in the default run _and_ belong
|
|
920
|
-
to a group, list both: `tags = ["enabled", "weekly"]`. (For MR
|
|
921
|
-
|
|
1068
|
+
to a group, list both: `tags = ["enabled", "weekly"]`. (For MR labels, use
|
|
1069
|
+
`labels` - a separate concept.)
|
|
922
1070
|
|
|
923
1071
|
Tag selection is _explicit_ selection, so - like naming a job - it ignores
|
|
924
1072
|
the `enabled`/`disabled` defaults and force-includes dependencies. The bare
|
|
@@ -926,7 +1074,7 @@ the `enabled`/`disabled` defaults and force-includes dependencies. The bare
|
|
|
926
1074
|
itself selected is dropped
|
|
927
1075
|
(`==> [name] skipped (dependency not in default run)`).
|
|
928
1076
|
|
|
929
|
-
|
|
1077
|
+
#### Keeping unmerged branches current
|
|
930
1078
|
|
|
931
1079
|
The bare `repoactive run` additionally refreshes **any job that currently
|
|
932
1080
|
has an unmerged branch**, regardless of its tags. A branch is "unmerged"
|
|
@@ -945,7 +1093,7 @@ don't have to wait for the next weekly run to resolve a conflict with
|
|
|
945
1093
|
disabled job's unmerged branch is refreshed too: it was most likely created
|
|
946
1094
|
by an explicit run, and letting it drift out of date helps no one.)
|
|
947
1095
|
|
|
948
|
-
|
|
1096
|
+
### Disabling jobs
|
|
949
1097
|
|
|
950
1098
|
Set `disabled = true` on a `[job.<name>]` to keep it in the config but leave
|
|
951
1099
|
it out of normal runs; it is exactly sugar for `tags = ["disabled"]` (so the
|
|
@@ -966,7 +1114,7 @@ disabled = true
|
|
|
966
1114
|
`repoactive run --tag disabled`, which runs everything currently turned
|
|
967
1115
|
off.
|
|
968
1116
|
|
|
969
|
-
|
|
1117
|
+
### Running a job on a schedule
|
|
970
1118
|
|
|
971
1119
|
`repoactive` is not a daemon and has no built-in scheduler - the cadence of
|
|
972
1120
|
a job is whatever cadence you invoke it with. To run a job on a fixed
|
|
@@ -994,7 +1142,7 @@ inferring a schedule from `repoactive`'s own history: real cron is stateful
|
|
|
994
1142
|
and excludes the other days, whereas `repoactive` only ever sees what has
|
|
995
1143
|
_landed_ (see `cooldown_period` below).
|
|
996
1144
|
|
|
997
|
-
|
|
1145
|
+
#### One run at a time per repository
|
|
998
1146
|
|
|
999
1147
|
A `repoactive run` takes an exclusive per-repository lock for its duration,
|
|
1000
1148
|
so two runs against the same repository never interleave (and corrupt each
|
|
@@ -1012,7 +1160,7 @@ The lock is an advisory `flock` on `.jj/repoactive.lock`; the OS releases it
|
|
|
1012
1160
|
automatically if a run is killed, so a crashed run never leaves the
|
|
1013
1161
|
repository locked.
|
|
1014
1162
|
|
|
1015
|
-
|
|
1163
|
+
### Gating jobs with `run_only_if_changed`
|
|
1016
1164
|
|
|
1017
1165
|
`run_only_if_changed` lets a job declare that it should only run when
|
|
1018
1166
|
specific upstream jobs actually produced a diff. If none of the named jobs
|
|
@@ -1046,12 +1194,15 @@ Key behaviour:
|
|
|
1046
1194
|
- **Dependents are unaffected.** A skipped job records a no-op result (like
|
|
1047
1195
|
a job on cooldown), so any job that `depends_on` it still runs on the base
|
|
1048
1196
|
branch - the skip does not cascade.
|
|
1049
|
-
- **
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
in the
|
|
1197
|
+
- **Watched jobs must run first.** A watched job does not have to appear in
|
|
1198
|
+
`depends_on`, but it must be ordered before this one so its result is
|
|
1199
|
+
known when the gate is evaluated - either as a (direct or transitive)
|
|
1200
|
+
`depends_on` ancestor, or simply earlier in the config file. Listing a job
|
|
1201
|
+
that runs later (or alongside, with no `depends_on` edge) is rejected at
|
|
1202
|
+
config load. In practice most usages name a direct dependency, as in the
|
|
1203
|
+
example above.
|
|
1053
1204
|
|
|
1054
|
-
|
|
1205
|
+
### Throttling jobs with `cooldown_period`
|
|
1055
1206
|
|
|
1056
1207
|
Every commit `repoactive` creates carries a `Repoactive-Job: <name>` trailer
|
|
1057
1208
|
identifying the job that produced it. When a job sets `cooldown_period`,
|
|
@@ -1074,7 +1225,14 @@ runs: `repoactive` does not fetch, so a clone that has not pulled the merge
|
|
|
1074
1225
|
will not see the cooldown and will re-run the job. See
|
|
1075
1226
|
[Keeping the local clone current](#keeping-the-local-clone-current).
|
|
1076
1227
|
|
|
1077
|
-
|
|
1228
|
+
Naming a job explicitly on the command line (`repoactive run <name>`)
|
|
1229
|
+
overrides its cooldown: the job runs now regardless of when it last landed,
|
|
1230
|
+
as if its `cooldown_period` were unset. The cooldown only ever gates the
|
|
1231
|
+
_default_ run and `--tag` selection, the automated paths it exists to
|
|
1232
|
+
throttle. Jobs pulled in only as dependencies of a named job are not
|
|
1233
|
+
themselves named, so they keep their own cooldowns.
|
|
1234
|
+
|
|
1235
|
+
### Throttling a job when a superset lands with `cooldown_on`
|
|
1078
1236
|
|
|
1079
1237
|
Some jobs are strict supersets of others. `uv lock --upgrade` refreshes
|
|
1080
1238
|
every dependency group, so its diff already contains everything
|
|
@@ -1114,7 +1272,7 @@ has an open, unmerged branch is always refreshed regardless of cooldown (see
|
|
|
1114
1272
|
its branch is rebased and, if the change is now redundant, self-closes on
|
|
1115
1273
|
the next run.
|
|
1116
1274
|
|
|
1117
|
-
|
|
1275
|
+
### Limiting job runtime with `timeout`
|
|
1118
1276
|
|
|
1119
1277
|
A job's `command` can hang or run away. Setting `timeout` caps how long the
|
|
1120
1278
|
command may run; when the limit is reached `repoactive` kills the command's
|
|
@@ -1144,7 +1302,7 @@ title = "chore: fix lint"
|
|
|
1144
1302
|
timeout = "0s" # opt out of the timeout entirely
|
|
1145
1303
|
```
|
|
1146
1304
|
|
|
1147
|
-
|
|
1305
|
+
### Generating jobs dynamically
|
|
1148
1306
|
|
|
1149
1307
|
Sometimes the useful set of jobs depends on the repository's contents - one
|
|
1150
1308
|
job per package in a monorepo, one per entry in a manifest - and you don't
|
|
@@ -1175,7 +1333,7 @@ title = "build: upgrade pkg-a"
|
|
|
1175
1333
|
|
|
1176
1334
|
Fragments may only contain `[job.<name>]` tables; anything else (e.g.
|
|
1177
1335
|
`[job-defaults]`) fails the generator. To set defaults for the emitted jobs,
|
|
1178
|
-
set them on the generator itself
|
|
1336
|
+
set them on the generator itself - they are inherited (see below).
|
|
1179
1337
|
|
|
1180
1338
|
Key points:
|
|
1181
1339
|
|
|
@@ -1184,10 +1342,10 @@ Key points:
|
|
|
1184
1342
|
it emits.
|
|
1185
1343
|
- **Inheritance with override.** Each emitted job inherits the generator's
|
|
1186
1344
|
`tags`, `cooldown_period`, `base_branch`, `timeout`, `labels`,
|
|
1187
|
-
`branch_prefix`/title prefixes, `draft` and `
|
|
1188
|
-
fragment sets them. It also defaults to
|
|
1189
|
-
(i.e. built flat on `trunk()`); override
|
|
1190
|
-
job to stack them into an MR chain.
|
|
1345
|
+
`branch_prefix`/title prefixes, `draft`, `create_mr` and `auto_merge`
|
|
1346
|
+
unless its own fragment sets them. It also defaults to
|
|
1347
|
+
`depends_on = ["<generator>"]` (i.e. built flat on `trunk()`); override
|
|
1348
|
+
`depends_on` to a sibling emitted job to stack them into an MR chain.
|
|
1191
1349
|
- **Stable names are your responsibility.** Cooldown, branches and the
|
|
1192
1350
|
`Repoactive-Job` trailer all key on a job's `name`, so derive emitted
|
|
1193
1351
|
names deterministically from repository state (`upgrade-pkg-a`, not a
|
|
@@ -1218,17 +1376,17 @@ design.
|
|
|
1218
1376
|
|
|
1219
1377
|
## Requirements
|
|
1220
1378
|
|
|
1221
|
-
-
|
|
1379
|
+
- A Unix-like operating system (Linux, macOS, BSD). `repoactive` uses POSIX
|
|
1380
|
+
process groups to enforce [`timeout`](#limiting-job-runtime-with-timeout)
|
|
1381
|
+
and `flock` for the
|
|
1382
|
+
[per-repository run lock](#one-run-at-a-time-per-repository); Windows is
|
|
1383
|
+
not supported.
|
|
1384
|
+
- Python 3.12 or later
|
|
1222
1385
|
- [jj (Jujutsu)](https://github.com/jj-vcs/jj) - `repoactive` uses jj to
|
|
1223
1386
|
manage branches and commits in the target repository
|
|
1224
1387
|
- A configured jj user name and email - jj records them as the commit
|
|
1225
|
-
author. Set them once with
|
|
1226
|
-
|
|
1227
|
-
```bash
|
|
1228
|
-
jj config set --user user.name "My Name"
|
|
1229
|
-
jj config set --user user.email "me@example.com"
|
|
1230
|
-
```
|
|
1231
|
-
|
|
1388
|
+
author. Set them once with the `jj config set` commands shown in
|
|
1389
|
+
[Quick start](#quick-start) step 1.
|
|
1232
1390
|
- A GitLab or GitHub API token exposed via the environment variable named in
|
|
1233
1391
|
`platform.token_env` (default: `GITHUB_TOKEN` for GitHub.com,
|
|
1234
1392
|
`GITLAB_TOKEN` for GitLab.com)
|
|
@@ -1256,3 +1414,12 @@ jj log -r 'repoactive_unmerged()'
|
|
|
1256
1414
|
jj log -r 'repoactive() & committer_date(after:"2025-01-01")'
|
|
1257
1415
|
jj log -r 'repoactive() & description(regex:"(?m)^Repoactive-Job: uv-lock-upgrade$")'
|
|
1258
1416
|
```
|
|
1417
|
+
|
|
1418
|
+
## Changelog
|
|
1419
|
+
|
|
1420
|
+
User-facing changes are recorded in [CHANGELOG.md](CHANGELOG.md).
|
|
1421
|
+
|
|
1422
|
+
## License
|
|
1423
|
+
|
|
1424
|
+
`repoactive` is licensed under the
|
|
1425
|
+
[GNU General Public License v3.0 or later](LICENSE).
|