Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion config/roborev/config.template.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,12 @@ enabled = true
poll_interval = "1m"
# Never cancel a running CI review just to post an early result.
batch_timeout = "0"
repos = ["__ROBOREV_CI_REPOS__"]
repos = ["__ROBOREV_REPOS__"]

[agent_hook]
# Surface any open failed review without automatically invoking a fixer.
# Keep turn and commit triggers explicitly disabled.
turn_threshold = 0
commit_threshold = 0
Comment thread
shunkakinoki marked this conversation as resolved.
failed_review_threshold = 1
instruction = "Inspect open RoboRev findings read-only. Report proposed changes and ask the user for explicit approval. Do not edit files, run a fixer, commit, or close reviews before approval."
58 changes: 49 additions & 9 deletions config/roborev/hydrate.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Hydrate roborev config from .env secrets
# ROBOREV_CI_REPOS: comma-separated list of repos (e.g. "org/repo1,org/repo2")
# ROBOREV_REPOS: comma-separated list of repos (e.g. "org/repo1,org/repo2")
# shellcheck source=/dev/null
set -euo pipefail

Expand All @@ -15,29 +15,69 @@ if [ -f "$ENV_FILE" ]; then
set +a
fi

ROBOREV_CI_REPOS="${ROBOREV_CI_REPOS:-}"
ROBOREV_REPOS="${ROBOREV_REPOS:-}"
if [ -z "$ROBOREV_REPOS" ] && [ -n "${ROBOREV_CI_REPOS:-}" ]; then
ROBOREV_REPOS="$ROBOREV_CI_REPOS"
echo "Warning: ROBOREV_CI_REPOS is deprecated; rename it to ROBOREV_REPOS" >&2
fi

if [ -z "$ROBOREV_CI_REPOS" ]; then
echo "Warning: ROBOREV_CI_REPOS not set, skipping roborev hydration" >&2
if [ -z "$ROBOREV_REPOS" ]; then
echo "Warning: ROBOREV_REPOS not set, skipping roborev hydration" >&2
exit 0
fi

# Build TOML array from comma-separated list
IFS=',' read -ra REPOS <<<"$ROBOREV_CI_REPOS"
IFS=',' read -ra REPOS <<<"$ROBOREV_REPOS"
Comment thread
shunkakinoki marked this conversation as resolved.
VALID_REPOS=()
TOML_REPOS=""
for i in "${!REPOS[@]}"; do
repo="$(echo "${REPOS[$i]}" | xargs)"
if [ "$i" -gt 0 ]; then
for value in "${REPOS[@]}"; do
repo="$(echo "$value" | xargs)"
owner="${repo%%/*}"
name="${repo#*/}"
if [[ ! $repo =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]] ||
[ "$owner" = "." ] || [ "$owner" = ".." ] ||
[ "$name" = "." ] || [ "$name" = ".." ]; then
echo "Warning: ignoring invalid RoboRev repository: $repo" >&2
continue
fi
if [ "${#VALID_REPOS[@]}" -gt 0 ]; then
TOML_REPOS+=", "
fi
TOML_REPOS+="\"${repo}\""
VALID_REPOS+=("$repo")
done

if [ "${#VALID_REPOS[@]}" -eq 0 ]; then
echo "Warning: ROBOREV_REPOS contains no valid repositories, skipping roborev hydration" >&2
exit 0
fi

mkdir -p "$CONFIG_DIR"

@sed@ \
-e "s|\"__ROBOREV_CI_REPOS__\"|${TOML_REPOS}|g" \
-e "s|\"__ROBOREV_REPOS__\"|${TOML_REPOS}|g" \
"$TEMPLATE" >"$CONFIG"
chmod 600 "$CONFIG"

echo "Generated roborev config at $CONFIG" >&2

ROBOREV_BIN="${HOME}/.local/bin/roborev"
if [ ! -x "$ROBOREV_BIN" ]; then
echo "Warning: RoboRev binary not found; skipping Git hook installation" >&2
exit 0
fi

for repo in "${VALID_REPOS[@]}"; do
repo_path="${HOME}/ghq/github.com/${repo}"
if [ ! -d "$repo_path" ]; then
echo "Warning: RoboRev repository checkout not found: $repo_path" >&2
continue
fi

if ! (
cd "$repo_path"
"$ROBOREV_BIN" install-hook --binary "$ROBOREV_BIN"
); then
echo "Warning: failed to install RoboRev Git hook in $repo_path" >&2
fi
done
65 changes: 51 additions & 14 deletions spec/roborev_hydrate_spec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ When run bash -c "grep 'TEMPLATE=' '$SCRIPT'"
The output should include '@template@'
End

It 'sources ROBOREV_CI_REPOS from dotfiles .env'
When run bash -c "grep -E 'ROBOREV_CI_REPOS|ENV_FILE=' '$SCRIPT'"
The output should include 'ROBOREV_CI_REPOS'
It 'sources ROBOREV_REPOS from dotfiles .env'
When run bash -c "grep -E 'ROBOREV_REPOS|ENV_FILE=' '$SCRIPT'"
The output should include 'ROBOREV_REPOS'
The output should include 'dotfiles/.env'
End

It 'substitutes __ROBOREV_CI_REPOS__ placeholder via sed'
When run bash -c "grep '__ROBOREV_CI_REPOS__' '$SCRIPT'"
The output should include '__ROBOREV_CI_REPOS__'
It 'substitutes __ROBOREV_REPOS__ placeholder via sed'
When run bash -c "grep '__ROBOREV_REPOS__' '$SCRIPT'"
The output should include '__ROBOREV_REPOS__'
End
End

Expand All @@ -52,19 +52,35 @@ End
Describe 'hydration'
setup_hydrate() {
TEMP_HOME=$(mktemp -d)
mkdir -p "$TEMP_HOME/dotfiles"
mkdir -p \
"$TEMP_HOME/dotfiles" \
"$TEMP_HOME/.local/bin" \
"$TEMP_HOME/ghq/github.com/org/repo1" \
"$TEMP_HOME/ghq/github.com/org/repo2"

cat >"$TEMP_HOME/template.toml" <<'TOML'
[ci]
enabled = true
poll_interval = "5m"
repos = ["__ROBOREV_CI_REPOS__"]
repos = ["__ROBOREV_REPOS__"]

[agent_hook]
turn_threshold = 0
commit_threshold = 0
failed_review_threshold = 1
instruction = "Inspect open RoboRev findings read-only. Report proposed changes and ask the user for explicit approval. Do not edit files, run a fixer, commit, or close reviews before approval."
TOML

cat >"$TEMP_HOME/dotfiles/.env" <<'ENV'
ROBOREV_CI_REPOS=org/repo1,org/repo2
ROBOREV_REPOS=../evil,foo/..,org/repo1,org/repo2
ENV

cat >"$TEMP_HOME/.local/bin/roborev" <<'BASH'
#!/usr/bin/env bash
printf '%s|%s\n' "$PWD" "$*" >>"${HOME}/roborev-hook.log"
BASH
chmod +x "$TEMP_HOME/.local/bin/roborev"

PREPROCESSED_SCRIPT="$TEMP_HOME/hydrate.sh"
sed \
-e 's|@sed@|sed|g' \
Expand All @@ -85,7 +101,28 @@ When run bash -c 'HOME="'"$TEMP_HOME"'" bash "'"$PREPROCESSED_SCRIPT"'" >/dev/nu
The status should be success
The output should include '"org/repo1"'
The output should include '"org/repo2"'
The output should not include '__ROBOREV_CI_REPOS__'
The output should not include '"../evil"'
The output should not include '"foo/.."'
The output should not include '__ROBOREV_REPOS__'
End

It 'hydrates the complete approval gate'
When run bash -c 'HOME="'"$TEMP_HOME"'" bash "'"$PREPROCESSED_SCRIPT"'" >/dev/null 2>&1; cat "'"$TEMP_HOME"'/.roborev/config.toml"'
The status should be success
The output should include 'turn_threshold = 0'
The output should include 'commit_threshold = 0'
The output should include 'failed_review_threshold = 1'
The output should include 'Inspect open RoboRev findings read-only.'
The output should include 'ask the user for explicit approval.'
The output should include 'Do not edit files, run a fixer, commit, or close reviews before approval.'
The output should not include 'roborev-fix'
End

It 'installs native hooks in each configured local checkout'
When run bash -c 'HOME="'"$TEMP_HOME"'" bash "'"$PREPROCESSED_SCRIPT"'" >/dev/null 2>&1; cat "'"$TEMP_HOME"'/roborev-hook.log"'
The status should be success
The output should include "$TEMP_HOME/ghq/github.com/org/repo1|install-hook --binary $TEMP_HOME/.local/bin/roborev"
The output should include "$TEMP_HOME/ghq/github.com/org/repo2|install-hook --binary $TEMP_HOME/.local/bin/roborev"
End

It 'restricts config file permissions to the owner'
Expand All @@ -102,7 +139,7 @@ setup_no_repos() {
[ci]
enabled = true
poll_interval = "5m"
repos = ["__ROBOREV_CI_REPOS__"]
repos = ["__ROBOREV_REPOS__"]
TOML

: >"$TEMP_HOME/dotfiles/.env"
Expand All @@ -122,10 +159,10 @@ cleanup_no_repos() {
Before 'setup_no_repos'
After 'cleanup_no_repos'

It 'skips hydration when ROBOREV_CI_REPOS is unset'
When run bash -c 'unset ROBOREV_CI_REPOS; HOME="'"$TEMP_HOME"'" bash "'"$PREPROCESSED_SCRIPT"'"'
It 'skips hydration when ROBOREV_REPOS is unset'
When run bash -c 'unset ROBOREV_REPOS ROBOREV_CI_REPOS; HOME="'"$TEMP_HOME"'" bash "'"$PREPROCESSED_SCRIPT"'"'
The status should be success
The error should include 'ROBOREV_CI_REPOS not set'
The error should include 'ROBOREV_REPOS not set'
The path "$TEMP_HOME/.roborev/config.toml" should not be exist
End
End
Expand Down
Loading