{"id":13771903,"url":"https://github.com/joshuarubin/zb","last_synced_at":"2026-01-25T23:24:03.727Z","repository":{"id":141675617,"uuid":"72893053","full_name":"joshuarubin/zb","owner":"joshuarubin","description":"an opinionated repo based tool for linting, testing and building go source","archived":false,"fork":false,"pushed_at":"2017-07-21T13:34:37.000Z","size":1310,"stargazers_count":110,"open_issues_count":12,"forks_count":4,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-05-11T04:32:02.054Z","etag":null,"topics":["build","go","golang","lint","test","tools"],"latest_commit_sha":null,"homepage":"https://jrubin.io/zb","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/joshuarubin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-11-04T23:33:52.000Z","updated_at":"2023-09-25T21:27:59.000Z","dependencies_parsed_at":null,"dependency_job_id":"a3f9337e-fd71-4fcb-bc08-44801aa13153","html_url":"https://github.com/joshuarubin/zb","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/joshuarubin/zb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuarubin%2Fzb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuarubin%2Fzb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuarubin%2Fzb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuarubin%2Fzb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joshuarubin","download_url":"https://codeload.github.com/joshuarubin/zb/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joshuarubin%2Fzb/sbom","scorecard":{"id":534514,"data":{"date":"2025-08-11","repo":{"name":"github.com/joshuarubin/zb","commit":"83f582a5e646eb40514832d3ba261144dabaa877"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T06:36:37.440Z","repository_id":141675617,"created_at":"2025-08-20T06:36:37.440Z","updated_at":"2025-08-20T06:36:37.440Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28761814,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-25T23:06:19.311Z","status":"ssl_error","status_checked_at":"2026-01-25T23:03:50.555Z","response_time":113,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build","go","golang","lint","test","tools"],"created_at":"2024-08-03T17:00:57.378Z","updated_at":"2026-01-25T23:24:03.708Z","avatar_url":"https://github.com/joshuarubin.png","language":"Go","funding_links":[],"categories":["Linters Helper Tools"],"sub_categories":["Misc"],"readme":"# zb — an opinionated repo based tool for linting, testing and building go source\n\n[![GoDoc](https://godoc.org/jrubin.io/zb?status.svg)](https://godoc.org/jrubin.io/zb) [![Go Report Card](https://goreportcard.com/badge/jrubin.io/zb)](https://goreportcard.com/report/jrubin.io/zb)\n\n\u003cpre\u003e\n███████╗██████╗     ██████╗  ██████╗ ███████╗███████╗    ██╗████████╗\n╚══███╔╝██╔══██╗    ██╔══██╗██╔═══██╗██╔════╝██╔════╝    ██║╚══██╔══╝\n  ███╔╝ ██████╔╝    ██║  ██║██║   ██║█████╗  ███████╗    ██║   ██║\n ███╔╝  ██╔══██╗    ██║  ██║██║   ██║██╔══╝  ╚════██║    ██║   ██║\n███████╗██████╔╝    ██████╔╝╚██████╔╝███████╗███████║    ██║   ██║\n╚══════╝╚═════╝     ╚═════╝  ╚═════╝ ╚══════╝╚══════╝    ╚═╝   ╚═╝\n\u003c/pre\u003e\n\n[[Help! your logo here](https://github.com/joshuarubin/zb/issues/1)]\n\n## Benefits\n\n* Faster builds (by defaulting to `go install` except for `main` packages, and by running concurrent `go install` commands when the dependency tree allows)\n* Faster testing (by caching test results and not retesting except when necessary)\n* Faster linting (by caching lint results from [`gometalinter`](https://github.com/alecthomas/gometalinter))\n* Did I mention _fast_!\n* Automatically runs `go generate` if its dependency calculation determines it's required\n* Operates on all packages in a repository (by default) with intelligent support for vendored packages\n* Can complement other build tools like `make`\n* Does not interfere with tools like [`govendor`](https://github.com/kardianos/govendor) or [`gb`](https://getgb.io/)\n\n## Installation\n\nSimply run `go get jrubin.io/zb`\n\n## Rationale\n\nMany go repositories have multiple packages. It is often necessary to build/install, test, lint, etc. across all packages within the repository. Go \"ellipsis\" wildcards (`...`) can be used to select all subdirectories of a given repository, but don't exclude vendored packages which makes running tests and linting complicated. Some operations should be aware of vendored packages (e.g. build/install), while others should ignore them (e.g. lint). Yet others need to be aware of changes in vendored packages, but should not operate directly on them (e.g. test). Traditional build tools, like `make`, can be used to supplement the `go` command to work only on the intended packages. Building dependency lists for make targets, which are required, for example, to dynamically identify modified `.go` files and what would need to be rebuilt as a result, is at the very least complicated (consider `.go` files modified outside the repo) and at best slow.\n\n### `zb` fixes all of this\n\n## Packages → Repositories\n\n`zb` is aware of the directory it is called from. If any of its commands is called without a package argument, it will use the current working directory.\n\n`zb` can also be passed packages just like the `go` command. Both package names (e.g. `fmt`, `jrubin.io/zb`) and relative package names (e.g. `./jrubin.io/zb`) are supported, as are ellipsis (`...`).\n\n`zb` will identify the repository associated with each package by locating the directory and walking up the directory tree to find the repository directory (containing `.git` [only `git` is supported at present]). It will then execute the command for all packages in each repository it identified.\n\n## go generate\n\n`go generate` is great, but sometimes it needs to be executed before a build. Forgetting to execute `go generate` can be a major problem if, for example, new values were added to a `stringer`.\n\n`zb` does its own dependency calculation and can identify `go generate` dependencies provided an additional annotation is also present.\n\nThe following formats are available to define dependencies of `go generate`\n\n### `zb:generate` formats\n\n* `//zb:generate glob glob...`\n  Causes `go generate` to be executed on the go file with the annotation if the go file itself is newer than the files expanded from the globs. This is useful with commands like stringer:\n\n    ```go\n    //go:generate stringer -type=YourType\n    //zb:generate yourtype_string.go\n    ```\n\n* `//zb:generate -patsubst %pattern %replacement glob glob...`\n  Works like `make`'s [patsubst](https://www.gnu.org/software/make/manual/html_node/Text-Functions.html).\n  Causes `go generate` to be executed on the go file with the annotation if any of the files expanded from the globs is newer than any of the filenames generated through the pattern substitution.\n\n    ```go\n    //go:generate make proto\n    //zb:generate -patsubst %.proto %.pb.go *.proto\n    ```\n\n    This command first matches all files matching `*.proto` and then performs the substitution by extracting the part of each of those file names before `.proto` (identified with the `%` in `%.proto`) and taking that extracted pattern and inserting it into the `%` part of `%.pb.go`.\n\n    So if there were files `message.proto` and `types.proto`, `go generate` would be executed if either of those files were newer than `message.pb.go` or `types.pb.go` (including if the `.pb.go` files did not yet exist).\n\n* `//zb:generate -target file glob glob...`\n  Basically a simplified `-patsubst`. Causes `go generate` to be executed if any of the files expanded from the globs is newer than `file`\n  Can also be written as `//zb:generate -patsubst % file glob glob...`\n\n## Commands\n\n### install\n\nInitially, `zb install` appears to do the same things as `go install` (just for all packages in the repositories). In fact, `zb install` just calls `go install` under the hood and supports all of its flags. There are a few differences though.\n\n* `go generate` may be called before building the package according to the `//go:generate` and `//zb:generate` annotations\n* `main` packages (commands) are built with extra linker flags that cause `main.gitCommit` and `main.buildDate` variables to be set if they exist. See [`zb/main.go`](https://github.com/joshuarubin/zb/blob/master/main.go) as an example of how to utilize this.\n* Executes `go install` for each stale package it finds and will execute concurrent `go install` processes when the dependency tree allows. Concurrency can be limited with `$GOMAXPROCS`.\n* If any of the non-vendored `.go` files in the repository contain `TODO` or `FIXME` these lines will be emitted to the console as warnings (unless the global `-n` flag is enabled).\n\n### build\n\n`zb build` differs from `go build` in that non `main` packages will be installed with `go install`. Commands, however, will not be installed (to `$GOPATH/bin`), they are built with the binary being placed in the root of the repository tree. If there is already a directory in the root of the repository with the same name as the command, the command will be placed in that directory instead.\n\nOtherwise, `zb build` is identical to `zb install`.\n\n### lint\n\nDelegates functionality to [`gometalinter`](https://github.com/alecthomas/gometalinter) but with more useful defaults and caching of results.\n\n* The `--concurrency, -j` flag is dynamically calculated to be `1` less than half the number of CPU cores (but at least `1`) [`gometalinter` default is `16`]\n* `--tests` is enabled by default\n* `--deadline` is set to `30s` [`gometalinter` default is `5s`]\n* `--enable-gc` is enabled by default\n* `alighcheck`, `dupl`, `gocyclo` and `structcheck` are disabled by default\n* `errcheck`, `gofmt`, `goimports` and `unused` are enabled (in addition to all other default enabled checkers) by default\n\nThe `-n` flag can be used to hide `golint` warnings about missing comments.\n\nSince dependency calculation can sometimes add a non-trivial amount of time to the `zb lint` command, `go generate` will not be executed.\n\nFiles matching certain suffixes will be excluded from the results. This list can be modified with the `--ignore-suffix` flag. By default files with the following suffixes will be excluded:\n\n* `.pb.go`\n* `.pb.gw.go`\n* `_string.go`\n* `bindata.go`\n* `bindata_assetfs.go`\n* `static.go`\n\nAll other [`gometalinter`](https://github.com/alecthomas/gometalinter) flags will be honored as defined.\n\n### test\n\nDelegates functionality to `go test` but caches the results (like [`gt`](https://godoc.org/rsc.io/gt)).\nHonors all other flags just like `go test` except those intended to be passed directly to the test binary.\n\nUse the `-f` flag to treat the test results as uncached, forcing the tests to be executed (and cached) again.\n\nTo see which tests would be executed (because their results are not-cached or the `-f` flag was provided), use the `-l` flag.\n\nSince dependency calculation can sometimes add a non-trivial amount of time to the `zb test` command, `go generate` will not be executed.\n\n### complete\n\n`zb` has full support for shell autocompletion in both `bash` and `zsh`.\nSimply execute `eval \"$(zb complete)\"` (or put in your init files) to enable.\n\n### clean\n\nRemoves the executables produced by `zb build`\n\n### commands\n\nLists the absolute paths where each of the commands (from `main` packages) will be placed with `zb build`\n\n### list\n\nSimilar to `go list` (and takes the same flags) but will list all of the packages in each of the repositories. Use the `--vendor` flag to exclude vendored packages.\n\n### help\n\n`zb` contains a built-in, comprehensive help system. Running `zb` by itself (or with the `-h` or `--help` flags) will list the commands and global flags. `zb help \u003ccommand\u003e`, `zb \u003ccommand\u003e -h` and `zb \u003ccommand\u003e --help` will show contextual help for the given command.\n\n## Global Flags\n\n### `--log-level, -l, $LOG_LEVEL`\n\nDefaults to `info`. Available levels are:\n\n* `error`\n* `warn`\n* `info`\n* `debug`\n\n### `--no-warn-todo-fixme, -n, $NO_WARN_TODO_FIXME`\n\nDo not warn when finding WARN or FIXME in `.go` files\n\n### `--cache, $CACHE`\n\nModify the base directory used for storing results of commands that cache their results (`test` and `lint`).\nDefaults to `$HOME/Library/Caches/zb` on mac and `$HOME/.cache/zb` elsewhere.\n\n### `--package, -p`\n\nCauses `zb` to execute only on the explicitly listed packages and not on all packages in their repositories.\n\n## Still Planned\n\n* Support for other version control systems [[#2](https://github.com/joshuarubin/zb/issues/2)]\n* Complete all `godoc` documentation [[#3](https://github.com/joshuarubin/zb/issues/3)]\n* Add comprehensive testing [[#4](https://github.com/joshuarubin/zb/issues/4)]\n* Detect import cycles in dependency calculation [[#5](https://github.com/joshuarubin/zb/issues/5)]\n* Wrap [`govendor`](https://github.com/kardianos/govendor) in an opinionated way [[#6](https://github.com/joshuarubin/zb/issues/5)]\n* Setup continuous integration [[#7](https://github.com/joshuarubin/zb/issues/7)]\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshuarubin%2Fzb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoshuarubin%2Fzb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoshuarubin%2Fzb/lists"}