-
Notifications
You must be signed in to change notification settings - Fork 1
fix(skills): preserve local lock during sync #179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| if (($# == 0)); then | ||
| echo "Usage: $0 <command> [args...]" >&2 | ||
| exit 2 | ||
| fi | ||
|
|
||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| DOTAGENTS_ROOT="${DOTAGENTS_ROOT:-$(cd "$SCRIPT_DIR/.." && pwd)}" | ||
| CURRENT_LOCK="${SKILLS_LOCK_FILE:-$DOTAGENTS_ROOT/skills-lock.json}" | ||
| TEMP_LOCK="$(mktemp "${TMPDIR:-/tmp}/dotagents-skills-lock.XXXXXX")" | ||
|
|
||
| cleanup() { | ||
| local status=$? | ||
| trap - EXIT | ||
| rm -f "$TEMP_LOCK" "$TEMP_LOCK.tmp" | ||
| exit "$status" | ||
| } | ||
| trap cleanup EXIT | ||
|
|
||
| if git -C "$DOTAGENTS_ROOT" show HEAD:skills-lock.json >"$TEMP_LOCK" 2>/dev/null; then | ||
| echo "Using committed skills-lock.json for synchronization." | ||
| else | ||
| echo "Git metadata unavailable; using the current skills lock for synchronization." | ||
| cp -f "$CURRENT_LOCK" "$TEMP_LOCK" | ||
| fi | ||
|
|
||
| SKILLS_LOCK_FILE="$TEMP_LOCK" "$@" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| #!/usr/bin/env bash | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" | ||
| SCRIPT="$REPO_ROOT/scripts/with-committed-skills-lock.sh" | ||
| TEST_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/dotagents-lock-test.XXXXXX")" | ||
|
|
||
| cleanup() { | ||
| rm -rf "$TEST_ROOT" | ||
| } | ||
| trap cleanup EXIT | ||
|
|
||
| fail() { | ||
| echo "not ok - $1" >&2 | ||
| exit 1 | ||
| } | ||
|
|
||
| assert_eq() { | ||
| local expected=$1 | ||
| local actual=$2 | ||
| local message=$3 | ||
|
|
||
| [[ "$actual" == "$expected" ]] || fail "$message: expected '$expected', got '$actual'" | ||
| } | ||
|
|
||
| FIXTURE="$TEST_ROOT/repo" | ||
| CAPTURE="$TEST_ROOT/capture" | ||
| MOCK_COMMAND="$TEST_ROOT/capture-lock" | ||
| mkdir -p "$FIXTURE" | ||
| git -C "$FIXTURE" init --quiet | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: The three scenarios (direct command, make, failure) all run against the committed-git fixture, so the script's fallback path (git show failing → copy CURRENT_LOCK) is never exercised. Consider adding a case where DOTAGENTS_ROOT has no git metadata (or a repo without a committed skills-lock) and assert the temporary lock then mirrors the working lock while the working file is still left untouched. Prompt for AI agents |
||
| git -C "$FIXTURE" config user.email test@example.com | ||
| git -C "$FIXTURE" config user.name 'Dotagents Test' | ||
| printf 'committed\n' >"$FIXTURE/skills-lock.json" | ||
| git -C "$FIXTURE" add skills-lock.json | ||
| git -C "$FIXTURE" commit --quiet -m initial | ||
| printf 'user-owned\n' >"$FIXTURE/skills-lock.json" | ||
|
|
||
| cat >"$MOCK_COMMAND" <<'EOF' | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| printf '%s\n' "$SKILLS_LOCK_FILE" >"$CAPTURE.path" | ||
| cat "$SKILLS_LOCK_FILE" >"$CAPTURE.contents" | ||
| printf 'generated\n' >"$SKILLS_LOCK_FILE" | ||
| exit "${MOCK_STATUS:-0}" | ||
| EOF | ||
| chmod +x "$MOCK_COMMAND" | ||
|
|
||
| DOTAGENTS_ROOT="$FIXTURE" \ | ||
| CAPTURE="$CAPTURE" \ | ||
| "$SCRIPT" "$MOCK_COMMAND" | ||
|
|
||
| assert_eq 'committed' "$(cat "$CAPTURE.contents")" 'sync command should receive committed lock' | ||
| assert_eq 'user-owned' "$(cat "$FIXTURE/skills-lock.json")" 'working lock should remain unchanged' | ||
| TEMP_LOCK="$(cat "$CAPTURE.path")" | ||
| [[ ! -e "$TEMP_LOCK" ]] || fail 'temporary lock should be removed after success' | ||
|
|
||
| cat >"$FIXTURE/Makefile" <<'EOF' | ||
| SKILLS_LOCK_FILE ?= missing | ||
|
|
||
| .PHONY: capture | ||
| capture: | ||
| @printf '%s\n' "$(SKILLS_LOCK_FILE)" >"$$CAPTURE.path" | ||
| @cat "$(SKILLS_LOCK_FILE)" >"$$CAPTURE.contents" | ||
| @printf 'generated\n' >"$(SKILLS_LOCK_FILE)" | ||
| EOF | ||
|
|
||
| DOTAGENTS_ROOT="$FIXTURE" \ | ||
| CAPTURE="$CAPTURE" \ | ||
| "$SCRIPT" make -C "$FIXTURE" capture | ||
|
|
||
| assert_eq 'committed' "$(cat "$CAPTURE.contents")" 'make should inherit temporary lock override' | ||
| assert_eq 'user-owned' "$(cat "$FIXTURE/skills-lock.json")" 'make should preserve working lock' | ||
| TEMP_LOCK="$(cat "$CAPTURE.path")" | ||
| [[ ! -e "$TEMP_LOCK" ]] || fail 'make temporary lock should be removed' | ||
|
|
||
| set +e | ||
| DOTAGENTS_ROOT="$FIXTURE" \ | ||
| CAPTURE="$CAPTURE" \ | ||
| MOCK_STATUS=42 \ | ||
| "$SCRIPT" "$MOCK_COMMAND" | ||
| status=$? | ||
| set -e | ||
|
|
||
| assert_eq '42' "$status" 'sync failure should propagate' | ||
| assert_eq 'user-owned' "$(cat "$FIXTURE/skills-lock.json")" 'failure should preserve working lock' | ||
| TEMP_LOCK="$(cat "$CAPTURE.path")" | ||
| [[ ! -e "$TEMP_LOCK" ]] || fail 'temporary lock should be removed after failure' | ||
|
|
||
| echo 'ok - committed skills lock isolation' | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P3:
make -f /path/to/Makefile syncfails outside the checkout because this wrapper is resolved from the caller’s working directory. Resolve the script relative to the Makefile, matching the other project paths.Prompt for AI agents