Skip to content

Commit b192ae8

Browse files
committed
jj-run: add JJ_CHANGE_ID, JJ_COMMIT_ID, JJ_COMMIT_TIMESTAMP env vars
When running commands, jj-run now sets environment variables with metadata about the current change being processed: - JJ_CHANGE_ID: The change ID (jj's unique identifier) - JJ_COMMIT_ID: The full commit hash - JJ_COMMIT_TIMESTAMP: ISO 8601 timestamp of the commit These variables are available in all modes (workspace, direct, readonly) and are useful for logging, sorting results, and correlating output when running commands in parallel.
1 parent ecc9e03 commit b192ae8

2 files changed

Lines changed: 52 additions & 9 deletions

File tree

jj-run/README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,30 @@ jj x --readonly -r '::@' 'cargo build'
117117
jj x --readonly -r 'recent(5)' 'cargo llvm-cov --html'
118118
```
119119

120+
## Environment Variables
121+
122+
When running commands, jj-run sets the following environment variables with metadata about the current change being processed:
123+
124+
| Variable | Description | Example |
125+
|----------|-------------|---------|
126+
| `JJ_CHANGE_ID` | The change ID (jj's unique identifier) | `plupmpozpuunnxwmxvsussklkvqlsmul` |
127+
| `JJ_COMMIT_ID` | The full commit hash | `162b3b24f7088209c33630ec56deefebc70c2128` |
128+
| `JJ_COMMIT_TIMESTAMP` | ISO 8601 timestamp of the commit | `2026-01-18T02:55:02+01:00` |
129+
130+
These variables are available in all modes (workspace, direct, and readonly).
131+
132+
**Example usage:**
133+
```sh
134+
# Print change info for each commit
135+
jj x --readonly -r 'mutable()' 'echo "$JJ_COMMIT_TIMESTAMP $JJ_CHANGE_ID"'
136+
137+
# Run tests and log results with timestamps (useful when results arrive out of order)
138+
jj x --readonly -j4 -r 'ancestors(@, 20)' '
139+
echo "=== $JJ_COMMIT_TIMESTAMP $JJ_CHANGE_ID ==="
140+
cargo test 2>&1 | grep -E "(Passed|Failed|Total)"
141+
'
142+
```
143+
120144
## Working with Remote Repositories
121145

122146
**⚠️ EXPERIMENTAL: This feature is AI-written and untested. Use at your own risk.**

jj-run/main.go

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,20 @@ import (
1616
"github.com/spf13/cobra"
1717
)
1818

19+
// Signature represents author/committer information
20+
type Signature struct {
21+
Name string `json:"name"`
22+
Email string `json:"email"`
23+
Timestamp string `json:"timestamp"`
24+
}
25+
1926
// Change represents a jj change with its metadata
2027
type Change struct {
21-
CommitID string `json:"commit_id"`
22-
ChangeID string `json:"change_id"`
23-
Description string `json:"description"`
24-
Parents []string `json:"parents"`
28+
CommitID string `json:"commit_id"`
29+
ChangeID string `json:"change_id"`
30+
Description string `json:"description"`
31+
Parents []string `json:"parents"`
32+
Committer Signature `json:"committer"`
2533
}
2634

2735
// Job represents a change processing job
@@ -303,7 +311,7 @@ func runDirectMode(command string, strategy ErrorStrategy, beforeOp string, repo
303311
}
304312

305313
// Run the command in the repository
306-
err := runShellCommand(command, repoDir)
314+
err := runShellCommand(command, repoDir, change)
307315
printCommandResult(err)
308316

309317
if err != nil {
@@ -394,7 +402,7 @@ func runReadonlyMode(command string, strategy ErrorStrategy, repoDir string) err
394402
}
395403

396404
// Run the command in the workspace
397-
err = runShellCommand(command, workspacePath)
405+
err = runShellCommand(command, workspacePath, change)
398406
printCommandResult(err)
399407

400408
// After command execution, use --ignore-working-copy for all jj commands
@@ -607,7 +615,7 @@ func processChanges(workspacePath string, changes []*Change, command string, str
607615
}
608616

609617
// Run the command
610-
err := runShellCommand(command, workspacePath)
618+
err := runShellCommand(command, workspacePath, change)
611619
printCommandResult(err)
612620

613621
if err != nil {
@@ -693,7 +701,7 @@ func processChangesParallel(changes []*Change, command string, strategy ErrorStr
693701
}
694702

695703
// Run the command
696-
err := runShellCommand(command, workspacePath)
704+
err := runShellCommand(command, workspacePath, change)
697705
printCommandResult(err)
698706

699707
if err != nil {
@@ -855,12 +863,23 @@ func printCommandResult(err error) {
855863
fmt.Println()
856864
}
857865

858-
func runShellCommand(command string, cwd string) error {
866+
// runShellCommand runs a shell command in the given directory.
867+
// If change is provided, it sets JJ_CHANGE_ID, JJ_COMMIT_ID, and JJ_COMMIT_TIMESTAMP env vars.
868+
func runShellCommand(command string, cwd string, change *Change) error {
859869
cmd := exec.Command("sh", "-c", command)
860870
cmd.Dir = cwd
861871
cmd.Stdout = os.Stdout
862872
cmd.Stderr = os.Stderr
863873

874+
// Set environment variables if change metadata is provided
875+
if change != nil {
876+
cmd.Env = append(os.Environ(),
877+
"JJ_CHANGE_ID="+change.ChangeID,
878+
"JJ_COMMIT_ID="+change.CommitID,
879+
"JJ_COMMIT_TIMESTAMP="+change.Committer.Timestamp,
880+
)
881+
}
882+
864883
return cmd.Run()
865884
}
866885

0 commit comments

Comments
 (0)