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
28 changes: 15 additions & 13 deletions .github/instructions/bug-fixing.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,21 @@ If the report is incomplete, do not guess. Review the relevant module(s) to loca

Use the module map in `AGENTS.md` to identify where the bug likely lives:

| Symptom | Look in |
| -------------------------------------- | ---------------------------------- |
| Wrong grouping / filtering of results | `src/aggregate.ts`, `src/group.ts` |
| Incorrect markdown / JSON output | `src/output.ts` |
| Wrong syntax highlighting | `src/render/highlight.ts` |
| Bad row navigation or visibility | `src/render/rows.ts` |
| Incorrect select-all / select-none | `src/render/selection.ts` |
| Wrong stats / summary line | `src/render/summary.ts` |
| Filter stats incorrect | `src/render/filter.ts` |
| API pagination or rate-limit issue | `src/api.ts` |
| TUI keyboard handling / display glitch | `src/tui.ts` |
| Upgrade failure | `src/upgrade.ts` |
| CLI option parsing / defaults | `github-code-search.ts` |
| Symptom | Look in |
| -------------------------------------------------- | -------------------------------------- |
| Wrong grouping / filtering of results | `src/aggregate.ts`, `src/group.ts` |
| Incorrect markdown / JSON output | `src/output.ts` |
| Wrong syntax highlighting | `src/render/highlight.ts` |
| Bad row navigation or visibility | `src/render/rows.ts` |
| Incorrect select-all / select-none | `src/render/selection.ts` |
| Wrong stats / summary line | `src/render/summary.ts` |
| Filter stats incorrect | `src/render/filter.ts` |
| API pagination or rate-limit issue | `src/api.ts` |
| TUI keyboard handling / display glitch | `src/tui.ts` |
| Upgrade failure | `src/upgrade.ts` |
| CLI option parsing / defaults | `github-code-search.ts` |
| Completion script wrong / not refreshed on upgrade | `src/completions.ts`, `src/upgrade.ts` |
| Completion file written to wrong path | `src/completions.ts` |

## 3. Write a failing test before fixing

Expand Down
45 changes: 25 additions & 20 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
name: CI

on:
push:
branches: ["**"]
pull_request:
branches: ["main"]

jobs:
test:
name: Unit tests
name: Test · Format · Lint · Dead code
runs-on: ubuntu-latest
permissions:
pull-requests: write
Expand All @@ -30,28 +28,12 @@ jobs:

- name: Post LCOV coverage comment
if: always() && github.event_name == 'pull_request'
uses: romeovs/lcov-reporter-action@v0.3.1
uses: romeovs/lcov-reporter-action@87a815f34ec27a5826abba44ce09bbc688da58fd # v0.4.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
lcov-file: coverage/lcov.info
continue-on-error: true

quality:
name: Format · Lint · Dead code
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Bun
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2.1.2
with:
bun-version: latest

- name: Install dependencies
run: bun install --frozen-lockfile

- name: Check formatting (oxfmt)
run: bun run format:check

Expand All @@ -60,3 +42,26 @@ jobs:

- name: Dead code detection (knip)
run: bun run knip

test-bats:
name: Shell tests (bats)
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Setup Bats
uses: bats-core/bats-action@77d6fb60505b4d0d1d73e48bd035b55074bbfb43 # v4.0.0
with:
support-install: false
assert-install: false
detik-install: false
file-install: false
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Run install.sh shell tests
shell: bash
run: bats install.test.bats
16 changes: 13 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,14 @@ The build script (`build.ts`) injects the git commit SHA, target OS and architec
## Running tests

```bash
bun test # run the whole test suite
bun test # run the whole TypeScript test suite
bun test --watch # re-run on file changes (development)
bun run test:bats # run the shell-integration tests for install.sh (requires bats-core)
```

All tests use Bun's built-in test runner (`@jest/globals`-compatible API: `describe`, `it`, `expect`). No additional testing library is needed. The setup file is `src/test-setup.ts` (referenced in `bunfig.toml`).
All TypeScript tests use Bun's built-in test runner (`@jest/globals`-compatible API: `describe`, `it`, `expect`). No additional testing library is needed. The setup file is `src/test-setup.ts` (referenced in `bunfig.toml`).

Shell-integration tests use [bats-core](https://github.com/bats-core/bats-core) (`brew install bats-core` or install via your package manager). They cover `install_completions()` from `install.sh` and are located in `install.test.bats`.

## Linting & formatting

Expand All @@ -58,7 +61,7 @@ Always run `bun run lint` and `bun run format:check` before considering a change
## Project layout

```
github-code-search.ts # CLI entry point — Commander subcommands: query, upgrade
github-code-search.ts # CLI entry point — Commander subcommands: query, upgrade, completions
build.ts # Build script (Bun.build)
bunfig.toml # Bun configuration (smol install, test preload)
tsconfig.json # TypeScript configuration
Expand All @@ -74,13 +77,16 @@ src/
cache.ts # Disk cache for the team list (getCacheDir, getCacheKey,
# readCache, writeCache) — performs filesystem I/O
aggregate.ts # Result grouping & filtering (applyFiltersAndExclusions)
completions.ts # Pure shell-completion generators: generateCompletion(),
# detectShell(), getCompletionFilePath() — no I/O
group.ts # groupByTeamPrefix — team-prefix grouping logic
render.ts # Façade re-exporting sub-modules + top-level
# renderGroups() / renderHelpOverlay()
tui.ts # Interactive keyboard-driven UI (navigation, filter mode,
# help overlay, selection)
output.ts # Text (markdown) and JSON output formatters
upgrade.ts # Auto-upgrade logic (fetch latest GitHub release, replace binary)
# + refreshCompletions() — overwrites existing completion file

render/
highlight.ts # Syntax highlighting (language detection + token rules)
Expand Down Expand Up @@ -108,6 +114,7 @@ src/
- Only pure functions need tests; `tui.ts` and `api.ts` are not unit-tested.
`api-utils.ts` is the exception: its helpers are unit-tested by mocking `globalThis.fetch`.
`cache.ts` is also tested: it uses the `GITHUB_CODE_SEARCH_CACHE_DIR` env var override to redirect to a temp directory, so tests have no filesystem side effects on the real cache dir.
`completions.ts` is fully unit-tested (`completions.test.ts`). Tests that exercise `getCompletionFilePath()` must unset `XDG_CONFIG_HOME`, `XDG_DATA_HOME`, and `ZDOTDIR` in `beforeEach` (and restore them in `afterEach`) to avoid contamination from the CI runner environment.
- When adding a function to an existing module, add the corresponding test case in the existing `<module>.test.ts`.
- When creating a new module that contains pure functions, create a companion `<module>.test.ts`.
- Tests must be self-contained: no network calls, no filesystem side effects.
Expand Down Expand Up @@ -229,5 +236,8 @@ For minor/major releases update `docs/blog/index.md` to add a row in the version
- The `--exclude-repositories` and `--exclude-extracts` options accept both short (`repoName`) and long (`org/repoName`) forms — this normalisation happens in `aggregate.ts`.
- The `--group-by-team-prefix` option requires a `read:org` GitHub token scope; this is documented in `README.md`.
- The `upgrade` subcommand replaces the running binary in-place using `src/upgrade.ts`; be careful with filesystem operations there.
- After a successful upgrade, `refreshCompletions()` (in `src/upgrade.ts`) silently overwrites the existing completion file if one is already present. It never creates a file from scratch — installation is the user's responsibility (via `install.sh` or the `completions` subcommand).
- The `completions` subcommand (in `github-code-search.ts`) prints the completion script for the detected (or specified) shell to stdout. It is a thin wrapper around `generateCompletion()` in `src/completions.ts`.
- Shell-integration tests for `install.sh` live in `install.test.bats` and require `bats-core`. Run them with `bun run test:bats`. The CI runs them in a dedicated `test-bats` job using `bats-core/bats-action`.
- `picocolors` is the only styling dependency; do not add `chalk` or similar.
- Keep `knip` clean: every exported symbol must be used; every import must resolve.
20 changes: 16 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ bun install
## Project structure

```
github-code-search.ts # CLI entry point (Commander subcommands: query, upgrade)
github-code-search.ts # CLI entry point (Commander subcommands: query, upgrade, completions)
build.ts # Build script (compiles the standalone binary)
src/
types.ts # Shared TypeScript types (TextMatchSegment, CodeMatch, RepoGroup, Row, FilterTarget, …)
Expand All @@ -30,6 +30,8 @@ src/
cache.test.ts # Unit tests for cache.ts
aggregate.ts # Result grouping and filtering logic
aggregate.test.ts # Unit tests for aggregate.ts
completions.ts # Pure shell-completion generators (generateCompletion, detectShell, getCompletionFilePath)
completions.test.ts # Unit tests for completions.ts
render.ts # Façade: re-exports sub-modules + TUI renderGroups/renderHelpOverlay
render.test.ts # Unit tests for render.ts (rows, filter, selection, rendering)
render/
Expand All @@ -44,18 +46,28 @@ src/
output.ts # Text (markdown) and JSON output formatters
output.test.ts # Unit tests for output.ts
tui.ts # Interactive keyboard-driven UI (navigation, filter mode, help overlay)
upgrade.ts # Auto-upgrade logic (fetch latest release, replace binary)
upgrade.ts # Auto-upgrade logic (fetch latest release, replace binary) + refreshCompletions()
upgrade.test.ts # Unit tests for upgrade.ts
dist/ # Compiled binary (git-ignored)
install.sh # Install script (binary download + shell completions installation)
install.test.bats # Shell-integration tests for install.sh (bats-core)
```

## Running tests

```bash
bun test
bun test # TypeScript unit tests (co-located *.test.ts files)
bun run test:bats # Shell-integration tests for install.sh (requires bats-core)
```

Tests are co-located with their source files and cover the pure functions in `aggregate.ts`, `output.ts`, `render.ts`, `render/highlight.ts`, and `upgrade.ts`.
TypeScript tests are co-located with their source files and cover the pure functions in `aggregate.ts`, `completions.ts`, `output.ts`, `render.ts`, `render/highlight.ts`, and `upgrade.ts`.

Shell-integration tests use [bats-core](https://github.com/bats-core/bats-core). Install it once with:

```bash
brew install bats-core # macOS
# or: sudo apt-get install -y bats # Debian/Ubuntu
```

## Building a self-contained binary

Expand Down
Loading