Forge

Architecture

How one Go binary ships to Go, npm, and PyPI without native builds in each.

GitHub

secretcheck is a single Go binary. Everything else — the npm package, the PyPI package — is a thin wrapper that locates and execs that same binary. Nothing is recompiled per ecosystem.

Project layout

cmd/secretcheck/        CLI entry point
internal/
  rules/                 built-in detection patterns + placeholder/redaction helpers
  gitutil/                git plumbing (staged files, index content, hooks dir)
  ignore/                 .secretcheckignore + default excludes (custom glob matcher, no deps)
  config/                 .secretcheckrc.json loading + rule resolution
  scanner/                runs rules against staged/working-tree files
  hook/                   installs/removes the pre-commit hook (native + Husky)
  prompt/                 interactive y/N confirmation, TTY/CI detection
  colors/                 minimal ANSI helper
  report/                 findings output formatting
packaging/
  npm/                    main npm shim package + 5 per-platform binary packages
  pypi/                   pyproject.toml/setup.py + per-platform wheel build script
.goreleaser.yaml           cross-platform build config

The core Go module has zero third-party dependencies — smaller attack surface for a security tool, no go.sum to audit, and no network access needed to build.

Cross-compiling once

GoReleaser cross-compiles the binary for {linux,darwin,windows} × {amd64,arm64} (windows/arm64 excluded) from a single build step, with the version injected via -X main.version=....

npm: optionalDependencies

The npm side follows the pattern used by esbuild, swc, and turbo: a main secretcheck package with no binary of its own, plus five tiny platform packages (secretcheck-darwin-arm64, secretcheck-darwin-x64, secretcheck-linux-arm64, secretcheck-linux-x64, secretcheck-win32-x64), each scoped to one OS/CPU pair via the os/cpu fields in package.json. They're listed as optionalDependencies of the main package — npm installs only the one matching the current machine and silently skips the rest. The main package's bin/secretcheck.js resolves the installed platform package at runtime and execs its binary, forwarding stdio and the exit code.

PyPI: platform-tagged wheels

PyPI doesn't have an optionalDependencies-style mechanism — instead, one wheel is built per platform, each tagged so pip's platform-compatibility check only offers the right one (macosx_11_0_arm64, manylinux_2_17_x86_64, win_amd64, etc.). Since the binary is already compiled by GoReleaser, the build step doesn't compile anything — it just copies the right binary in and forces the wheel's platform tag via a SECRETCHECK_WHEEL_PLATFORM environment variable read by a custom bdist_wheel override. pip install secretcheck resolves to whichever wheel matches the installing machine automatically.

Go: no separate publish step

The Go module needs nothing beyond the pushed git tag — go install github.com/anukool23/secretcheck/cmd/secretcheck@v1.0.3 resolves directly from the tag via the Go module proxy.

Three independent release pipelines

Pushing a tag (git tag v1.0.3 && git push origin v1.0.3) triggers three separate GitHub Actions workflows in parallel, not one combined job:

  • release-go.yml — runs GoReleaser's real release, cross-compiling and publishing the GitHub Release (this alone is what makes go install work).
  • release-npm.yml — builds its own copy of the binaries (goreleaser build, which has no GitHub Release side effects) and publishes the npm packages.
  • release-pypi.yml — same build-only step, then builds and uploads the wheels.

Each workflow is fully self-contained. A failure in one — say, npm's automated anti-spam scanner flagging a package containing a raw .exe — can't block the other two, and re-running a failed workflow is safe even after a partial success: the npm publish script checks npm view <name>@<version> before publishing each package, so it skips anything already live and only retries what actually failed.

On this page