Skip to content

Resolve v1.10 technical debt: gosec gate, integration suite, test hygiene#38

Open
jjuanrivvera99 wants to merge 10 commits into
developfrom
fix/tech-debt-v1.10
Open

Resolve v1.10 technical debt: gosec gate, integration suite, test hygiene#38
jjuanrivvera99 wants to merge 10 commits into
developfrom
fix/tech-debt-v1.10

Conversation

@jjuanrivvera99

Copy link
Copy Markdown
Member

Summary

Resolves all four active items from TECHNICAL_DEBT.md.

gosec: 283 findings → 0, CI now blocking

  • New mustMarkRequired helper checks the 205 previously-ignored MarkFlagRequired errors (G104 bulk)
  • Two real fixes: ReadHeaderTimeout added to the OAuth callback and webhook servers (G112, slowloris hardening); update-state dir perms tightened to 0750
  • Remaining findings resolved with _ = for best-effort cleanups or #nosec annotations carrying written justifications
  • -no-fail removed from the CI gosec step — the scanner now gates merges alongside govulncheck

Binary-level integration tests (new)

  • 12-case suite in test/integration behind the integration build tag: compiles the binary once, drives it via os/exec against a mock Canvas server
  • Covers env-var auth, table/JSON/CSV output, exit codes, required-flag errors, 401 handling, alias expansion end-to-end, context resolution, --dry-run token redaction (asserts zero requests reach the server), and the repl/shell alias
  • Separate ubuntu-only CI job; make test-integration locally; ~2s runtime, flake-checked over three runs

Test hygiene

  • Deleted the old commands/testing framework — it never routed getAPIClient() to its mock server, so its tests looked like integration tests but exercised no HTTP dispatch
  • Added shared newTestClient(t, serverURL) helper in internal/api tests; 201 exact-pattern duplicated constructions migrated by script (variant constructions intentionally left explicit)

Docs

  • TECHNICAL_DEBT.md: all four items moved to Resolved with details; Active section is now empty — the only tracked item is the deliberately dormant cosign v2 pin

Test plan

  • gosec ./... exits 0
  • go test ./... -count=1 green (integration suite correctly excluded without the tag)
  • go test -tags integration ./test/integration/ green, 3 consecutive runs
  • go test -race ./internal/api/ ./commands/ green
  • gofmt / go vet clean

The commands/testing package was never wired to the real getAPIClient()
function, so its mock server was silently bypassed on every invocation.
No Go file outside the package imported it. Delete the dead code and
move the debt item to Resolved in TECHNICAL_DEBT.md.
Add newTestClient(t, serverURL) in internal/api/testhelpers_test.go and
migrate all 201 identical four-line NewClient construction blocks (BaseURL:
server.URL, Token: "test-token", RequestsPerSec: 10) to use it. Migration
was done with a Python regex script; follow-up fixes converted bare
`err =` reuses to `err :=` in functions where the NewClient block was the
only prior declaration of err.

Leaves variant call sites untouched (different tokens, RetryInitialBackoff,
TokenSource, AsUserID, cache, DryRun fields).
Adds test/integration/ with 12 cases exercising the compiled canvas binary
as a product: version, help, unknown command, courses list (table/JSON/CSV),
missing required flag, 401 handling, alias expansion, context propagation,
dry-run token redaction, and repl --help.

Each test gets its own isolated HOME/USERPROFILE temp directory and a per-test
httptest mock Canvas server; no shared state between tests. The suite is
gated behind //go:build integration so go test ./... is unaffected.

Also adds a CI integration job (ubuntu-only), a make test-integration target,
and a docs paragraph explaining the suite and its invocation.
…lper

Introduces mustMarkRequired in commands/helpers.go to replace all 205
cmd.MarkFlagRequired(...) calls that were silently dropping errors (G104).
The new helper panics on a missing flag name — a programmer error caught
by any test that builds the command tree — so the error can never be
silently lost at runtime.

Beyond G104, each remaining gosec rule is addressed:
- G112: add ReadHeaderTimeout to the OAuth callback and webhook HTTP servers
- G117: #nosec on token marshal calls (output goes to keyring/AES-GCM, not logs)
- G122/G304/G306: #nosec in gendocs (developer tool, controlled output dir)
- G204: #nosec on browser-open exec.Command (URL is constructed internally)
- G301: fix update state dir to 0750; #nosec for docs/skills dirs (world-readable by design)
- G302: #nosec on self-update binary chmod (executable bits required)
- G304: #nosec on all file paths that are user-controlled by design (--file, --destination flags)
  or derived from internal app directories (config, cache, token store)
- G401/G501: #nosec on MD5 imports/uses (cache filename hashing, not cryptographic)
- Remaining G104s: use _ = assignment for best-effort cleanup (os.Remove, Close)
  and #nosec for interactive Scanln prompts and viper.BindPFlag calls

All #nosec annotations include rule IDs and one-line justifications.
TECHNICAL_DEBT.md updated to mark the gosec backlog as resolved.
Remove -no-fail from the gosec action args. The previous comment
explaining ~300 open findings is replaced with a note that all findings
have been resolved and gosec now enforces a zero-finding gate on every PR.
@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2f9fe666-0ca9-47b5-9cd8-bd74882798b5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/tech-debt-v1.10

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter

Copy link
Copy Markdown

The stacked '#nosec ... //nolint' comment satisfied gosec but not
golangci-lint's errcheck, which requires nolint to start its own
comment. Explicit discards satisfy both without annotations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants