Skip to content
Open
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
9 changes: 6 additions & 3 deletions .claude/commands/commit.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Create a git commit following project standards and safety protocols
allowed-tools: Bash(git status:*), Bash(git log:*), Bash(git add:*), Bash(git diff:*), Bash(git commit:*), Bash(make test:*), Read, Edit
allowed-tools: Bash(git *), Bash(make test*), Bash(make foundation*), Read, Edit, Task
---

# commit
Expand Down Expand Up @@ -34,8 +34,11 @@ Create a git commit following all project standards and safety protocols for pgx
- Run in background so we can continue with analysis
- Tests will be checked before committing

2. **While tests run**, gather information in parallel:
- `git status`, `git diff --stat`, `git log -10 --oneline` for both repos
2. **While tests run**, gather repo state:
- Combine all git queries into a single Bash call per repo to minimize approvals:
`git status && git diff --stat && git log -10 --oneline`
- If conversation context already makes clear that only one repo has changes
(e.g., "test-only change", no pgxntool files modified), skip the unchanged repo entirely

3. **Check if HISTORY.asc needs updating** (for pgxntool changes only):
- Read `../pgxntool/HISTORY.asc`
Expand Down
11 changes: 11 additions & 0 deletions test/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,17 @@ cd "$TEST_REPO" || error "Failed to cd to TEST_REPO" # Error visible immediatel

## Shell Error Handling Rules

### BATS Runs With `set -eET`

BATS executes test files via `bats-exec-file`, which starts with `set -eET` (errexit, errtrace, trace). This means:

- **All functions** — `setup_file()`, `setup()`, `@test` blocks, `teardown()`, `teardown_file()` — run under errexit.
- **Any failing command** will abort the current function. In `setup_file`, this causes BATS to report `"setup_file failed"` with a stack trace and skip all tests in the file.
- **Subshells** `( ... )` also run under errexit. A failure inside a subshell exits the subshell non-zero, which errexit in the parent catches.
- **`local var=$(cmd)` masks exit status** — the `local` builtin always returns 0, hiding failures in the command substitution. Split these into two lines: `local var` then `var=$(cmd)`.

**Implication for setup code**: You do not need explicit exit status checks on every command in `setup_file` — errexit handles that. But if this isn't obvious in a given context, add a comment explaining the reliance on `set -e`.

### Never Use BATS `skip` Unless Explicitly Told

**CRITICAL RULE:** You should never use BATS `skip` unless explicitly told to do so by the user.
Expand Down
138 changes: 138 additions & 0 deletions test/standard/pgxntool-sync.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/usr/bin/env bats

# Test: make pgxntool-sync end-to-end
#
# This test validates the full `make pgxntool-sync` flow:
# git subtree pull → update-setup-files.sh
#
# Unlike the unit tests in update-setup-files.bats (which test 3-way merge
# scenarios in isolation), this test exercises the complete sync pipeline
# including the Makefile target and git subtree pull mechanics.
#
# A dedicated source repo is needed because git subtree pull requires the
# initial add to have been done via `git subtree add`. During normal test
# runs, pgxntool may be dirty (uncommitted changes), causing
# build_test_repo_from_template to use rsync instead. This test creates
# its own clean source repo to guarantee git subtree add is used.

load ../lib/helpers
load ../lib/assertions

setup_file() {
# Note: BATS runs with set -eET, so any command failure here (including
# inside subshells) will abort setup_file and BATS will report the failure.
setup_topdir

# Always start fresh - this test creates its own repos from scratch
clean_env "pgxntool-sync"
load_test_env "pgxntool-sync"

# =========================================================================
# Step 1: Create a clean pgxntool source repo
# =========================================================================
local source_repo="$TEST_DIR/pgxntool-source"
mkdir "$source_repo"
(
cd "$source_repo"
git init
# Copy current pgxntool files (excluding .git)
rsync -a --exclude='.git' "$PGXNREPO/" ./
git add .
git commit -m "Initial pgxntool"
git tag v1

# Modify _.gitignore with a marker line for sync detection
echo "# pgxntool-sync-test-marker" >> _.gitignore
git add _.gitignore
git commit -m "Update gitignore"
git tag v2
)

# =========================================================================
# Step 2: Create test extension repo using subtree add from source at v1
# =========================================================================
mkdir "$TEST_REPO"
(
cd "$TEST_REPO"
git init

# Copy template files and commit
rsync -a --exclude='.DS_Store' "$TEST_TEMPLATE"/ ./
git add .
git commit -m "Initial extension files"

# Add pgxntool via git subtree (forces subtree path, not rsync)
git subtree add -P pgxntool --squash "$source_repo" v1

# Run setup.sh to generate Makefile, .gitignore, etc.
./pgxntool/setup.sh

# Fix META.in.json placeholders
sed -i.bak -e 's/DISTRIBUTION_NAME/pgxntool-test/g' -e 's/EXTENSION_NAME/pgxntool-test/g' META.in.json
rm -f META.in.json.bak

# Regenerate META.json from updated META.in.json (make auto-rebuilds this
# as an included file prerequisite, which would dirty the tree during sync)
./pgxntool/build_meta.sh META.in.json META.json

# Ignore generated files so repo stays clean
echo "*.html" >> .gitignore
echo "meta.mk" >> .gitignore

# Commit everything
git add .
git commit -m "Add pgxntool setup"
)

# Store source repo path in env file for test access
echo "export SOURCE_REPO=\"$source_repo\"" >> "$TEST_DIR/.env"

# Wait for filesystem timestamps to settle, then refresh git index cache.
# git subtree pull internally uses 'git diff-index --quiet HEAD' which can
# fail due to filesystem timestamp granularity causing stale index entries.
(cd "$TEST_REPO" && sleep 1 && git update-index --refresh)
}

setup() {
load_test_env "pgxntool-sync"
cd "$TEST_REPO"
}

# =============================================================================
# Tests
# =============================================================================

@test "pgxntool subtree was added correctly" {
assert_file_exists "pgxntool/base.mk"

# Verify git log shows the subtree merge commit
run git log --oneline -- pgxntool/
assert_success
assert_contains "$output" "pgxntool"
}

@test ".gitignore does not have v2 marker before sync" {
! grep -q "pgxntool-sync-test-marker" .gitignore
}

@test "make pgxntool-sync pulls new changes" {
run make pgxntool-sync-test "pgxntool-sync-test=$SOURCE_REPO v2"
assert_success
assert_contains "$output" "Checking setup files for updates"
}

@test ".gitignore was auto-updated after sync" {
grep -q "pgxntool-sync-test-marker" .gitignore
}

@test "pgxntool files reflect v2 after sync" {
grep -q "pgxntool-sync-test-marker" pgxntool/_.gitignore
}

@test "sync created a merge commit" {
run git log --oneline -1
assert_success
assert_contains "$output" "Pull pgxntool from"
}

# vi: expandtab sw=2 ts=2