Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d348738
delphi: refresh ws/software/application-software/argos/argos-dev from…
github-actions[bot] Oct 11, 2026
243787e
delphi: sync .delphi/ from main
github-actions[bot] Oct 11, 2026
f71f26a
delphi: refresh ws/software/application-software/argos/argos-dev from…
github-actions[bot] Oct 11, 2026
f1d42ec
delphi: refresh ws/software/application-software/argos/argos-dev from…
github-actions[bot] Oct 11, 2026
c497e8c
delphi: refresh ws/software/application-software/argos/argos-dev from…
github-actions[bot] Oct 11, 2026
58c5c40
delphi: refresh ws/software/application-software/argos/argos-dev from…
github-actions[bot] Oct 11, 2026
a175b60
delphi: refresh ws/software/application-software/argos/argos-dev from…
github-actions[bot] Oct 12, 2026
ecb1dd0
delphi: sync .delphi/ from main
github-actions[bot] Oct 12, 2026
a2455a0
delphi: refresh ws/software/application-software/argos/argos-dev from…
github-actions[bot] Oct 12, 2026
28f6b61
delphi: sync .delphi/ from main
github-actions[bot] Oct 12, 2026
4872d5c
delphi: sync inherited files from main
github-actions[bot] Oct 12, 2026
d7e5106
delphi: refresh ws/software/application-software/argos/argos-dev from…
github-actions[bot] Oct 12, 2026
f773ada
delphi: sync .delphi/ from main
github-actions[bot] Oct 12, 2026
8626de3
delphi: sync inherited files from main
github-actions[bot] Oct 12, 2026
94384ca
delphi: refresh ws/software/application-software/argos/argos-dev from…
github-actions[bot] Oct 12, 2026
9af858e
delphi: sync .delphi/ from main
github-actions[bot] Oct 12, 2026
377135a
delphi: refresh ws/software/application-software/argos/argos-dev from…
github-actions[bot] Oct 12, 2026
625748f
delphi: sync .delphi/ from main
github-actions[bot] Oct 12, 2026
b58d4f4
delphi: sync inherited files from main
github-actions[bot] Oct 12, 2026
4db2ed1
delphi: refresh ws/software/application-software/argos/argos-dev from…
github-actions[bot] Oct 12, 2026
2101beb
delphi: sync .delphi/ from main
github-actions[bot] Oct 12, 2026
60a4b54
delphi: sync inherited files from main
github-actions[bot] Oct 12, 2026
7412f74
delphi: refresh ws/software/application-software/argos/argos-dev from…
github-actions[bot] Oct 13, 2026
4f98c97
delphi: sync .delphi/ from main
github-actions[bot] Oct 13, 2026
b0be0c8
argos-dev: dependabot-cleanup skill: scripts list, validate, merge, d…
bracyw Oct 15, 2026
7740f79
Merge pull request #59 from Northeastern-Electric-Racing/argos-dev-de…
bracyw Oct 16, 2026
866bac0
delphi: refresh ws/software/application-software/argos/argos-dev from…
github-actions[bot] Oct 16, 2026
66c0f3b
delphi: sync inherited files from main
github-actions[bot] Oct 16, 2026
35fc121
delphi: propose ws/software/application-software/argos/argos-dev to main
github-actions[bot] Oct 16, 2026
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
name: dependabot-cleanup
description: Validate, merge, and clean up open Dependabot PRs on Argos (Angular upgrades excluded). Use when asked to go through, merge, or clean up Dependabot PRs.
---

Run the scripts from the workspace root. Don't write gh, git, npm or cargo commands yourself, and read a log only when a step fails.

1. `bash scripts/list.sh` lists the PRs.
2. Run `bash scripts/validate.sh <pr>` for each PR, in the background. Show the user a table of the results.
3. After the user approves, run `bash scripts/merge.sh <pr>...`.
4. If a PR is blocked by CI, run `bash scripts/ci.sh <pr>`.
- If develop has the same failure, draft a ticket (`create-ticket`) and fix it first.
- Once develop has the fix, run `bash scripts/rebase.sh <pr>`, then `merge.sh` again.
5. Ask the user which PRs to clean up, then run `bash scripts/cleanup.sh <pr>...`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
# ci.sh <pr>: why a PR's CI is red. Prints each failing check, the step and first error lines of each failing job
# (gates skipped), how far develop has moved since the PR's base, and develop's latest result per
# workflow. A failure develop shares, or one develop has fixed since, is not the PR's.
set -euo pipefail
# shellcheck source=lib.sh
. "$(dirname "$0")/lib.sh"
pr=${1:?usage: ci.sh <pr>}
branch=$(pr_branch "$pr")
checks=$(gh pr checks "$pr" -R "$R" --json name,bucket,link -q '.[] | select(.bucket == "fail") | "\(.name)\t\(.link)"' || true)
[ -n "$checks" ] || { echo "#$pr no failing checks" && exit 0; }
while IFS=$'\t' read -r name link; do echo "FAIL $name $link"; done <<<"$checks"
# gate jobs only repeat another job's result, so show the jobs they gate (the rest if all are gates)
jobs=$(grep -v -- $'-gate\t' <<<"$checks" || true) && jobs=${jobs:-$checks}
while IFS=$'\t' read -r name link; do
echo "--- $name"
job=${link##*/}
gh run view -R "$R" --job "$job" --log-failed 2>/dev/null | cut -f3- | sed -E 's/^[0-9T:.-]+Z //' |
awk '/##\[group\]Run / { step = $0; n = 0; next } /##\[error\]/ { print step; for (i = 0; i < n; i++) print m[i]; print; exit }
tolower($0) ~ /error|fail|panick/ && $0 !~ /^npm error *$/ && n < 10 { m[n++] = $0 }' | cut -c1-200
done <<<"$jobs"
g() { git -C "$DELPHI_REPOS/argos" "$@"; }
g fetch -q origin develop "$branch"
echo "--- develop is $(g rev-list --count "$(g merge-base origin/develop "origin/$branch")..origin/develop") commits past this PR's base"
gh run list -R "$R" -b develop -L 20 --json workflowName,conclusion \
-q 'unique_by(.workflowName)[] | "develop \(.workflowName): \(.conclusion)"'
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
# cleanup.sh <pr>...: for each merged or closed Dependabot PR, remove worktrees/argos/<its branch>,
# the local branch and the branch on GitHub, then empty folders left under worktrees/argos/.
# Refuses open PRs. Prints one line per PR.
set -euo pipefail
# shellcheck source=lib.sh
. "$(dirname "$0")/lib.sh"
[ $# -gt 0 ] || { echo "usage: cleanup.sh <pr>..." >&2 && exit 2; }
g() { git -C "$DELPHI_REPOS/argos" "$@"; }
for pr in "$@"; do
read -r state branch author < <(gh pr view "$pr" -R "$R" --json state,headRefName,author -q '"\(.state) \(.headRefName) \(.author.login)"')
case $author in *dependabot*) ;; *) echo "#$pr skipped: author is $author" && continue ;; esac
[ "$state" != OPEN ] || { echo "#$pr skipped: still open" && continue; }
wt=$DELPHI_WORKTREES/argos/$branch
[ ! -d "$wt" ] || g worktree remove --force "$wt"
g branch -q -D "$branch" 2>/dev/null || true
gh api -X DELETE "repos/$R/git/refs/heads/$branch" >/dev/null 2>&1 && remote="remote deleted" || remote="no remote branch"
echo "#$pr cleaned $branch ($remote)"
done
find "$DELPHI_WORKTREES/argos/dependabot" -name .DS_Store -delete 2>/dev/null || true
find "$DELPHI_WORKTREES/argos/dependabot" -depth -type d -empty -delete 2>/dev/null || true
g worktree prune && g fetch -q --prune origin
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# lib.sh: sourced by dependabot-cleanup's scripts. Sets R (the Argos repo on GitHub), loads the
# workspace layout from $DELPHI_ROOT, and puts each PR's logs in $LOGS/<pr>/.
# shellcheck shell=bash source=/dev/null
. "${DELPHI_ROOT:?unset: start the session at the workspace root, on Delphi 0.2.0+ (pull its ws/ branch), or source <root>/.delphi/paths.sh}/.delphi/paths.sh"
R=Northeastern-Electric-Racing/Argos
LOGS=${TMPDIR:-/tmp} && export LOGS=${LOGS%/}/argos-dependabot
# pr_branch <pr>: the PR's head branch
pr_branch() { gh pr view "$1" -R "$R" --json headRefName -q .headRefName; }
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash
# list.sh: open Dependabot PRs on Argos, Angular upgrades left out (they need their own migration
# work). Prints one line per PR: #<n> <ecosystem> <branch> <title>.
set -euo pipefail
# shellcheck source=lib.sh
. "$(dirname "$0")/lib.sh"
gh pr list -R "$R" --author app/dependabot --state open --limit 100 --json number,headRefName,title \
-q '.[] | select((.title + .headRefName) | test("angular"; "i") | not)
| "#\(.number) \(.headRefName | split("/")[1]) \(.headRefName) \(.title)"'
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash
# merge.sh <pr>...: for each Dependabot PR in turn, approve it as you, wait for CI, and merge it
# (merge commit). Waits out GitHub's UNKNOWN mergeability after the previous merge. Prints one line
# per PR: merged, or blocked <why>; exits 1 if any is blocked.
set -euo pipefail
# shellcheck source=lib.sh
. "$(dirname "$0")/lib.sh"
[ $# -gt 0 ] || { echo "usage: merge.sh <pr>..." >&2 && exit 2; }
rc=0
for pr in "$@"; do
blocked() { echo "#$pr blocked: $1" && rc=1; }
author=$(gh pr view "$pr" -R "$R" --json author -q .author.login)
case $author in *dependabot*) ;; *) blocked "author is $author, not Dependabot" && continue ;; esac
gh pr review "$pr" -R "$R" --approve -b "Validated locally (dependabot-cleanup)." >/dev/null 2>&1 || true
if ! gh pr checks "$pr" -R "$R" --watch --fail-fast >/dev/null 2>&1; then blocked "CI failing (ci.sh $pr)" && continue; fi
state=UNKNOWN
for _ in $(seq 20); do
state=$(gh pr view "$pr" -R "$R" --json mergeable -q .mergeable)
[ "$state" = UNKNOWN ] || break
sleep 5
done
case $state in
MERGEABLE) if out=$(gh pr merge "$pr" -R "$R" --merge 2>&1); then echo "#$pr merged"; else blocked "${out##*$'\n'}"; fi ;;
CONFLICTING) blocked "conflicts with develop (rebase.sh $pr)" ;;
*) blocked "mergeable still $state" ;;
esac
done
exit $rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
# rebase.sh <pr>...: ask Dependabot to rebase each PR onto develop, so CI reruns with develop's fixes
# (rerunning a check reuses the old merge commit).
set -euo pipefail
# shellcheck source=lib.sh
. "$(dirname "$0")/lib.sh"
[ $# -gt 0 ] || { echo "usage: rebase.sh <pr>..." >&2 && exit 2; }
for pr in "$@"; do gh pr comment "$pr" -R "$R" -b "@dependabot rebase" >/dev/null && echo "#$pr rebase requested"; done
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# validate.sh <pr>: check a Dependabot PR locally in worktrees/argos/<its branch> (made or reset to
# the PR's head). The diff may only touch manifests, lockfiles and workflows; then it runs CI's
# checks for each folder whose manifest changed: angular-client (npm ci, build, tests, lint,
# prettier) or scylla-server (build, clippy, unit tests; integration tests need Postgres, so CI runs
# them). Prints one line, PASS or FAIL <step>, with its log; exits 1 on FAIL.
set -euo pipefail
# shellcheck source=lib.sh
. "$(dirname "$0")/lib.sh"
pr=${1:?usage: validate.sh <pr>}
branch=$(pr_branch "$pr")
log=$LOGS/$pr && rm -rf "$log" && mkdir -p "$log"
wt=$(bash "$DELPHI_ROOT/.delphi/new-worktree.sh" argos "$branch")
fail() { echo "#$pr FAIL $1 log=$log${2:+/$2.log}" && exit 1; }
[ -z "$(git -C "$wt" status --porcelain)" ] || fail "worktree has local changes ($wt)"
git -C "$wt" fetch -q origin develop "$branch" && git -C "$wt" reset -q --hard "origin/$branch" # Dependabot force-pushes

files=$(git -C "$wt" diff --name-only origin/develop...HEAD)
other=$(echo "$files" | grep -Ev '(^|/)(package(-lock)?\.json|Cargo\.(toml|lock))$|^\.github/workflows/' || true)
[ -z "$other" ] || fail "scope: touches $(echo "$other" | paste -sd, -)"

run() { # run <step> <dir> <cmd...>: log to $log/<step>.log, fail on error
local step=$1 dir=$2 && shift 2
(cd "$wt/$dir" && "$@") >"$log/$step.log" 2>&1 || fail "$step" "$step"
}
ran=""
for dir in $(echo "$files" | grep -E '(package(-lock)?\.json|Cargo\.(toml|lock))$' | xargs -n1 dirname | sort -u); do
case $dir in
angular-client)
run npm-ci "$dir" npm ci
run ng-build "$dir" npm run build
run ng-test "$dir" npm run test:ci
run ng-lint "$dir" npm run lint -- --max-warnings=0
run prettier "$dir" npm run prettier-check ;;
scylla-server)
run cargo-build "$dir" cargo build --locked
run clippy "$dir" cargo clippy --all-targets --locked
run cargo-test "$dir" cargo test --locked ;;
*) run "npm-ci-${dir//\//-}" "$dir" npm ci ;;
esac
ran="$ran $dir"
done
echo "#$pr PASS${ran:- scope only (CI checks workflows)} log=$log"