aboutsummaryrefslogtreecommitdiff
path: root/scripts/tests/sweep-gitignore-tooling.bats
blob: f18eac531ec1a184c9d12af7169097cef41f28bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#!/usr/bin/env bats
#
# Tests for scripts/sweep-gitignore-tooling.sh — backfill the personal-tooling
# gitignore set across existing gitignore-mode AI projects.
#
# Strategy: scaffold fake AI projects (a .ai/protocols.org marker + a git repo)
# under a temp root, run the sweep against that root, and assert on each
# project's .gitignore.

REAL_REPO="$(cd "$(dirname "$BATS_TEST_FILENAME")/../.." && pwd)"
SWEEP="$REAL_REPO/scripts/sweep-gitignore-tooling.sh"

setup() {
  ROOT="$(mktemp -d -t sweep-bats.XXXXXX)"
}

teardown() {
  rm -rf "$ROOT"
}

# Scaffold a project: $1 = name, $2 = initial .gitignore content (may be empty),
# $3 = "git" to init a repo (default), "nogit" to skip.
make_project() {
  local name="$1" gitignore="${2-}" git="${3-git}"
  mkdir -p "$ROOT/$name/.ai"
  echo "marker" > "$ROOT/$name/.ai/protocols.org"
  [ -n "$gitignore" ] && printf '%s' "$gitignore" > "$ROOT/$name/.gitignore"
  [ "$git" = "git" ] && (cd "$ROOT/$name" && git init -q)
  return 0
}

@test "sweep: gitignore-mode project missing all three gets them appended" {
  make_project gimode $'# tooling\n.ai/\n'

  run bash "$SWEEP" "$ROOT"

  [ "$status" -eq 0 ]
  grep -qFx ".claude/" "$ROOT/gimode/.gitignore"
  grep -qFx "CLAUDE.md" "$ROOT/gimode/.gitignore"
  grep -qFx "AGENTS.md" "$ROOT/gimode/.gitignore"
}

@test "sweep: is idempotent — a second run adds nothing" {
  make_project gimode $'.ai/\n'
  bash "$SWEEP" "$ROOT" >/dev/null

  run bash "$SWEEP" "$ROOT"

  [ "$status" -eq 0 ]
  [[ "$output" == *"already complete"* ]]
  # No line is duplicated.
  [ "$(grep -cFx '.claude/' "$ROOT/gimode/.gitignore")" -eq 1 ]
  [ "$(grep -cFx 'CLAUDE.md' "$ROOT/gimode/.gitignore")" -eq 1 ]
  [ "$(grep -cFx 'AGENTS.md' "$ROOT/gimode/.gitignore")" -eq 1 ]
}

@test "sweep: track-mode project (.ai/ not ignored) is skipped untouched" {
  make_project trackmode $'# build\nout/\n'

  run bash "$SWEEP" "$ROOT"

  [ "$status" -eq 0 ]
  [[ "$output" == *"track-mode"* ]]
  # .gitignore is untouched — none of the tooling lines were added.
  ! grep -qFx ".claude/" "$ROOT/trackmode/.gitignore"
  ! grep -qFx "CLAUDE.md" "$ROOT/trackmode/.gitignore"
}

@test "sweep: partial project gets only the missing lines" {
  make_project partial $'.ai/\n.claude/\n'

  run bash "$SWEEP" "$ROOT"

  [ "$status" -eq 0 ]
  [ "$(grep -cFx '.claude/' "$ROOT/partial/.gitignore")" -eq 1 ]
  grep -qFx "CLAUDE.md" "$ROOT/partial/.gitignore"
  grep -qFx "AGENTS.md" "$ROOT/partial/.gitignore"
}

@test "sweep: --dry-run reports without writing" {
  make_project gimode $'.ai/\n'

  run bash "$SWEEP" --dry-run "$ROOT"

  [ "$status" -eq 0 ]
  [[ "$output" == *"would add"* ]]
  [[ "$output" == *"no files written"* ]]
  # Nothing was actually written.
  ! grep -qFx ".claude/" "$ROOT/gimode/.gitignore"
}

@test "sweep: warns when a now-ignored path is already tracked" {
  make_project tracked $'.ai/\n'
  echo "# project rules" > "$ROOT/tracked/CLAUDE.md"
  (cd "$ROOT/tracked" && git add CLAUDE.md && git -c user.email=t@t -c user.name=t commit -qm seed)

  run bash "$SWEEP" "$ROOT"

  [ "$status" -eq 0 ]
  [[ "$output" == *"WARN"* ]]
  [[ "$output" == *"CLAUDE.md is currently tracked"* ]]
}

@test "sweep: non-git project with .ai/ marker is skipped" {
  make_project nogit $'.ai/\n' "" nogit

  run bash "$SWEEP" "$ROOT"

  [ "$status" -eq 0 ]
  [[ "$output" == *"not a git checkout"* ]]
}

@test "sweep: anchored /.ai/ is recognized as gitignore-mode, appends anchored" {
  make_project anchored $'/.ai/\n'

  run bash "$SWEEP" "$ROOT"

  [ "$status" -eq 0 ]
  [[ "$output" != *"anchored — track-mode"* ]]
  grep -qFx "/.claude/" "$ROOT/anchored/.gitignore"
  grep -qFx "/CLAUDE.md" "$ROOT/anchored/.gitignore"
  grep -qFx "/AGENTS.md" "$ROOT/anchored/.gitignore"
}

@test "sweep: anchored partial project gets only the missing lines" {
  make_project anchoredpartial $'/.ai/\n/.claude/\n'

  run bash "$SWEEP" "$ROOT"

  [ "$status" -eq 0 ]
  # /.claude/ already present in anchored form — not re-added in either form.
  [ "$(grep -cFx '/.claude/' "$ROOT/anchoredpartial/.gitignore")" -eq 1 ]
  ! grep -qFx ".claude/" "$ROOT/anchoredpartial/.gitignore"
  grep -qFx "/CLAUDE.md" "$ROOT/anchoredpartial/.gitignore"
  grep -qFx "/AGENTS.md" "$ROOT/anchoredpartial/.gitignore"
}

@test "sweep: anchored gitignore-mode is idempotent" {
  make_project anchored2 $'/.ai/\n'
  bash "$SWEEP" "$ROOT" >/dev/null

  run bash "$SWEEP" "$ROOT"

  [ "$status" -eq 0 ]
  [[ "$output" == *"already complete"* ]]
  [ "$(grep -cFx '/.claude/' "$ROOT/anchored2/.gitignore")" -eq 1 ]
}

@test "sweep: track-mode with tracked tooling and a non-cjennings.net remote warns" {
  make_project publictrack $'out/\n'
  echo "# project rules" > "$ROOT/publictrack/CLAUDE.md"
  (cd "$ROOT/publictrack" \
     && git add CLAUDE.md \
     && git -c user.email=t@t -c user.name=t commit -qm seed \
     && git remote add origin git@github.com:someone/publictrack.git)

  run bash "$SWEEP" "$ROOT"

  [ "$status" -eq 0 ]
  [[ "$output" == *"WARN"* ]]
  [[ "$output" == *"publicly reachable"* ]]
  # Still track-mode: nothing written to its .gitignore.
  ! grep -qFx ".claude/" "$ROOT/publictrack/.gitignore"
}

@test "sweep: track-mode with tracked tooling on a cjennings.net remote stays quiet" {
  make_project privatetrack $'out/\n'
  echo "# project rules" > "$ROOT/privatetrack/CLAUDE.md"
  (cd "$ROOT/privatetrack" \
     && git add CLAUDE.md \
     && git -c user.email=t@t -c user.name=t commit -qm seed \
     && git remote add origin git@cjennings.net:privatetrack.git)

  run bash "$SWEEP" "$ROOT"

  [ "$status" -eq 0 ]
  [[ "$output" != *"publicly reachable"* ]]
}

@test "sweep: the bare cjennings ssh-alias remote counts as private too" {
  make_project aliastrack $'out/\n'
  echo "# project rules" > "$ROOT/aliastrack/CLAUDE.md"
  (cd "$ROOT/aliastrack" \
     && git add CLAUDE.md \
     && git -c user.email=t@t -c user.name=t commit -qm seed \
     && git remote add origin git@cjennings:aliastrack.git)

  run bash "$SWEEP" "$ROOT"

  [ "$status" -eq 0 ]
  [[ "$output" != *"publicly reachable"* ]]
}