You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: add bats unit tests for lib/github-common.sh (#41)
* feat: add bats unit tests for lib/github-common.sh
15 tests covering the shared library's pure-logic functions and
gh_api sentinel returns — all testable without a real GitHub token.
- validate_slug: valid (alphanumeric/hyphen/underscore) and invalid
(space/slash/dot/metachar) inputs
- require_env_var: unset, empty, and set variable cases
- require_command: found and not-found cases
- gh_api: __404__, __422__ sentinels and 200 body pass-through
(curl is mocked per-test via a temporary PATH-prepended binary)
Also adds a 'test' job to ci.yml that installs bats and runs the suite.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat: expand test suite to 91 tests covering all scripts and lib functions
test_common.bats (29 tests):
- Add err, configure_gh_auth, validate_token, validate_github_token URL
warning, get_repo_page_count (with/without Link header), gh_api_paginate
(404, 422, single-page)
- Upgrade _mock_curl to use universal mock_curl.sh (handles both gh_api
stdout mode and gh_api_paginate/validate_token -o/-D file mode)
tests/mock_curl.sh:
- Universal drop-in curl mock; response data via env vars (MOCK_CURL_CODE,
MOCK_CURL_BODY, MOCK_CURL_LINK) — no quoting issues with JSON bodies
test_script_validation.bats (62 tests):
- Every script: missing required env vars exit 1 in the correct order
- Arg parsing: --help exits 0, unknown args exit 1, recognised flags
(--dry-run, --type) don't trigger Unknown argument errors
- Invalid enum values: --type, DEPENDABOT_REASON, SECRET_SCANNING_RESOLUTION
- github-import-repo: non-GitHub GIT_URL_PREFIX exits 1 (security guard)
- github-repo-permissions-report: missing -r exits 1
ci.yml: run bats tests/ (all bats files)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: mandate bats tests for all new scripts in AGENTS.md and copilot-instructions.md
- Replaced the placeholder Testing section in AGENTS.md with full
bats suite documentation: test files table, what to test per script,
and the mock_curl.sh pattern with a code example
- Added step 7 (write tests) to the Adding a New Script checklist in
AGENTS.md; renumbered subsequent steps
- Updated CI/CD bullet to mention the bats test job
- Updated Maintenance Matrix 'Add a new script' row to include
tests/test_script_validation.bats
- Mirrored all changes in .github/copilot-instructions.md: expanded
Adding New Scripts checklist with mandatory test step, replaced
single-line Testing Approach with table + requirement prose
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* docs: add bats test suite documentation to README.md
- Add Unit Tests subsection after Pre-commit Hooks: install
instructions for macOS/Ubuntu, bats tests/ run command, test-file
table, note that CI runs bats on every PR
- Update Contributing checklist: add 'add test section to
test_script_validation.bats' to step 3, add step 6 'bats tests/'
before the test-on-non-prod-org step
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy file name to clipboardExpand all lines: .github/copilot-instructions.md
+21-3Lines changed: 21 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -227,15 +227,33 @@ Uses API version `2026-03-10` and the new usage-metrics NDJSON endpoints (signed
227
227
3. Source `lib/github-common.sh` for validation and output helpers
228
228
4. Start with the standard boilerplate (see Script Anatomy above)
229
229
5. Create `action.yml` in the same directory — expose every env var as a named input (required inputs without defaults, optional inputs with sensible defaults); map CLI flags such as `--dry-run` and `--type` to boolean/string inputs and build an `ARGS` array in the `run:` step. Mirror the pattern of any existing `action.yml`.
230
-
6. Document in README.md following existing format:
230
+
6.**Add tests to `tests/test_script_validation.bats`** — mandatory. Add a labelled section with tests for every required env var missing (exit 1), unknown CLI args (exit 1), `--help` exits 0, and script-specific validation guards. See existing sections for the pattern.
231
+
7. Document in README.md following existing format:
231
232
- Use case description
232
233
- Required variables table
233
234
- Usage example with exports
234
235
- Output format (if applicable)
235
236
- Add a row to the Available Actions table in the "Using Scripts in GitHub Actions" section
236
237
237
238
### Testing Approach
238
-
-**Always test on a test organization first**
239
+
240
+
The project has a bats unit-test suite in `tests/`. Run the full suite with:
241
+
242
+
```bash
243
+
bats tests/
244
+
```
245
+
246
+
| File | What it covers |
247
+
|------|----------------|
248
+
|`tests/test_common.bats`|`lib/github-common.sh` pure-logic functions and API helpers |
|`tests/mock_curl.sh`| Universal curl mock used by both test files |
251
+
252
+
Every new script **must** include a test section in `tests/test_script_validation.bats` before it is merged. At minimum test: each required env var missing exits 1, unknown CLI args exit 1, and any enum or allowlist validation specific to the script.
253
+
254
+
Additional testing approaches:
255
+
-**Always test on a test organization first** before running against production
256
+
-**Dry-run flags** — several scripts support `--dry-run` to preview changes without applying them
| Add a new script |`action.yml` in the same directory; `README.md` (add use case, env var table, usage example, Available Actions table row) |
306
+
| Add a new script |`tests/test_script_validation.bats` (add a test section for the new script); `action.yml` in the same directory; `README.md` (add use case, env var table, usage example, Available Actions table row) |
289
307
| Add a new domain folder |`README.md` top-level structure description; `AGENTS.md` Repository Structure section |
290
308
|`.github/workflows/ci.yml` — shellcheck flags |`.githooks/pre-commit` shellcheck invocation (keep them in sync) |
|`tests/mock_curl.sh`| Universal drop-in curl mock (used by both test files); response data via env vars `MOCK_CURL_CODE`, `MOCK_CURL_BODY`, `MOCK_CURL_LINK`|
99
+
100
+
### What to test for every new script
101
+
102
+
1.**Missing required env vars** — one `@test` per required variable, in the order the script checks them. Each test asserts `status -eq 1`.
103
+
2.**Invalid CLI args** — unknown flag exits 1 with an "Unknown" message.
104
+
3.**`--help` flag** — exits 0 (for scripts that implement it).
105
+
4.**Recognised flags** — `--dry-run` and other known flags do not trigger the unknown-arg error (test by asserting output does *not* contain "Unknown").
Tests shadow real binaries by prepending a `MOCK_BIN` directory to `PATH`:
111
+
112
+
```bash
113
+
setup() {
114
+
MOCK_BIN="$(mktemp -d)"
115
+
# Fail gh auth so GITHUB_TOKEN is never auto-resolved from a session
116
+
printf'#!/bin/sh\nexit 1\n'>"$MOCK_BIN/gh"
117
+
chmod +x "$MOCK_BIN/gh"
118
+
}
119
+
120
+
teardown() { rm -rf "$MOCK_BIN"; }
121
+
122
+
@test "my-script: exits 1 when GITHUB_TOKEN is not set" {
123
+
run bash -c "export PATH='${MOCK_BIN}:${PATH}'; unset GITHUB_TOKEN; bash '${REPO_ROOT}/domain/my-script/my-script.sh'"
124
+
[ "$status"-eq 1 ]
125
+
}
126
+
```
127
+
128
+
Use `_mock_curl_200` (defined in `test_script_validation.bats`) when a test must reach code that runs after `validate_github_token`.
129
+
130
+
### Dry-run flags and other testing approaches
131
+
132
+
-**`--dry-run`** — several scripts support it to preview changes without applying them.
133
+
-**Test org first** — always run against a non-production GitHub org before production.
90
134
91
135
---
92
136
@@ -185,8 +229,9 @@ done
185
229
4.**Source the shared library** using `SCRIPT_DIR`
186
230
5.**Validate all inputs** before any API calls
187
231
6.**Create `action.yml`** in the same directory — expose every env var as an input (required inputs first, optional inputs with defaults); map CLI flags (`--dry-run`, `--type`, etc.) to boolean/string inputs and construct the `ARGS` array in the `run:` step. See existing `action.yml` files for the pattern.
188
-
7.**Add to README.md** — follow the existing format: use case, env var table, usage example, output format; add a row to the Available Actions table in the "Using Scripts in GitHub Actions" section
189
-
8. Place in the correct domain:
232
+
7.**Add tests to `tests/test_script_validation.bats`** — add a labelled section (`# ═══ github-<name> ═══`) with tests for: every required env var missing (exit 1), unknown CLI args (exit 1), `--help` exits 0, and any script-specific validation (enum guards, URL allowlists, positional args). See existing sections for the pattern.
233
+
8.**Add to README.md** — follow the existing format: use case, env var table, usage example, output format; add a row to the Available Actions table in the "Using Scripts in GitHub Actions" section
-**CI:** shellcheck runs on all `.sh` files on every PR (`.github/workflows/ci.yml`)
247
+
-**CI:** shellcheck runs on all `.sh` files on every PR (`.github/workflows/ci.yml`); bats unit tests run in a dedicated `test` job (`bats tests/`)
203
248
-**Releases:** automated by Release Please (`.github/workflows/release.yml`) — pushes to `main` trigger a release PR; merging it publishes the GitHub Release and tag
|`tests/test_script_validation.bats`| Every script — missing required env vars, invalid CLI args, `--help`, and script-specific guards |
134
+
135
+
CI runs `bats tests/` on every pull request alongside shellcheck.
136
+
115
137
## Scripts
116
138
117
139
Each script is a self-contained utility designed for a specific task. Navigate to the script's directory, set the required environment variables, and execute.
@@ -1159,8 +1181,10 @@ Contributions are welcome! Please follow these steps:
1159
1181
- Start with the `# ===` header and `set -euo pipefail`
1160
1182
- Source `lib/github-common.sh` and validate all inputs
1161
1183
- Create `action.yml` in the same directory (see existing actions for the pattern)
1184
+
- Add a test section for the new script in `tests/test_script_validation.bats`
1162
1185
4. **Update README.md** with the env var table, usage example, and a row in the Available Actions table
6. **Test on a non-production org** before submitting
1187
+
6. **Run the test suite:** `bats tests/`
1188
+
7. **Test on a non-production org** before submitting
1165
1189
7. **Commit using [Conventional Commits](https://www.conventionalcommits.org/)** — `CHANGELOG.md` is auto-generated from commit messages; do not edit it manually
1166
1190
8. **Open a PR** — the PR template will guide you through the checklist
0 commit comments