One Repo to rule them all, One Repo to find them, One Repo to bring them all and in the darkness bind them.
This codebase contains all public code written by Jack Bradshaw from 2022 onwards. It is structured as a monorepo and uses Bazel as the build tool. Everything is covered by the LICENSE, except the contents of 3P which are explicitly exempt.
After cloning the repository you must complete the following steps:
- Install the latest version of the Android SDK and set
ANDROID_HOMEto point at it. More detailed instructions are available in the [rules_android] repository. - TODO(jack-bradshaw): Understand and document xcode setup requirements.
Once these steps are complete you will be able to build and test code on macOS, Linux, and Windows.
All code is divided into two root directories, 1P and 3P. All code originating from this repository lives in 1P, and all code belonging to another repository/person/organisation belongs in 3P. This maintains a clear and unambiguous division for licensing and maintenance purposes. A few files exist outside these directories for core repository/build setup.
Bazel is used as the build tool across the repository.
- Build all code by running
bazel build //.... - Test all code by running
bazel test //....
View the granular package documentation for more more focused build/test instructions.
Submissions to main are automatically checked by a presubmit system which build all code, runs all tests, and ensures all code is formatted correctly. On Github it automatically runs on each PR, and it must pass before code can be submitted. Exceptions are granted only when the presubmit system itself is broken.
Presubmit is run locally with source first_party/presubmit/presubmit.sh; run_presubmit.
WARNING: Presubmit may modify the working directory during execution, so commit/stash all changes before running to avoid lost work.
Autoformatting is available for all supported languages and file types with a single command.
- Format all files by running
bazel run //first_party/formatting:autoformat. - Format specific files by running
bazel run //first_party/formatting:autoformat -- $paths.
All files must be in their formatted state before submission (enforced by presubmit).
TODO(jack-bradshaw): Add instructions for formatting only the files in the last commit and staging area.
The repository is versioned by the current date, with the version defined in the MODULE.bazel file, and since the repository contains multiple projects, the version is updated whenever any project is released in any way.
TODO(jack-bradshaw): Create an automatic version update system.
View the granular packages for release information.
TODO(jack-bradshaw) create a repository wide release system.
Package managers are used to manage external deps without building them from source. Various package managers and indexes are used across the repo, including Maven, NPM, and PyPI. They all follow a general pattern for integration and use, with minor differences in the exact details.
Each package managers generally has:
- A registry where deps are declared once for the entire repository.
- A lock file where deps are secured against supply chain attacks.
- A syntax for referencing deps across the entire repository.
To use a new dep:
- Declare it in the registry.
- Regenerate the lock file.
- Reference it in build targets.
To remove an existing dep:
- Delete references in build targets.
- Remove the declaration from the registry.
- Regenerate the lock file.
To update an existing dep:
- Update the version in the registry.
- Regenerate the lock file.
The exact details for each package manger are provided below.
To manage Maven deps:
- Declare in the JVM section of MODULES.bazel.
- Lock by running
REPIN=1 bazel run @com_jackbradshaw_maven//:pin. - Reference as
@com_jackbradshaw_maven//:$depGroupId_depArtefactId, with all non-alphanumeric characters in the identifiers replaced with_.
Example: Google Flogger is
registered as com.google.flogger:flogger:1.0.0 and referenced as
@com_jackbradshaw_maven//:com_google_flogger_flogger.
To manage NPM deps:
- Declare in package.json.
- Lock by running
bazel run -- @pnpm//:pnpm --dir $(pwd) install --lockfile-only(pwd must be the repo root). - Reference as
//:node_modules/$packageName.
Example: babel-plugin-minify-infinity
is registered as "babel-plugin-minify-infinity": "0.4.3" and referenced as
//:node_modules/babel-plugin-minify-infinity.
To manage PIP deps:
- Declare in pip_requirements.in.
- Lock by running
bazel run :requirements.update &> /dev/null. - Reference as
@pypi//$packageName.
Example: mdformat is registered as mdformat==0.7.22
and referenced as @pypi//mdformat.
To manage crate deps:
- Declare in the Rust section of MODULES.bazel.
- There is no locking.
- Reference as
@crate//:$packageName.
Example: serde is registered as:
crate.spec(
package = "serde",
version = "1.0",
)and referenced as @crate//:serde
All required external dependencies are vendored for hermetic security and reliability, with the
exception of all that cannot be uploaded to GitHub due to the 100MB file size limit. Whenever you
change the deps (including Bazel deps and package-manager deps), revendor by running
bazel vendor //.... Any oversized deps are ignored via .gitignore, and large files
can be found by running find third_party/bazel_vendor -type f -size +100M.
TODO(jack-bradshaw): Migrate off GitHub and delete the large file limit.
All documentation is stored in the repository itself, including design docs, one-pagers, guides, and all other ancillatory paperwork. This ensures the codebase itself is the authorative source of truth for all related materials, and ensures code does not become separted from related documentation.
This repository exclusively uses trunk-based development to the degree that all alternative forms of branch management are banned. This is essential for monorepo development and generally means:
- No collaborative branches: You may create private branches off main for your own work, but do not collaborate on them with others.
- Rebase, don't merge: You should rebase onto HEAD locally to get updates from others, and when your code is ready for submission, rebase it onto HEAD (with a PR) instead of merging.
- Make small, atomic commits: Each commit must change only the files required for that change and nothing more. If multiple commits serve a shared purpose, link them together by tagging an issue in the commit description.
- Keep HEAD green: PRs may only be submitted when CI passes. This is enforced automatically.
- Integrate frequently: Submit your changes as soon as they are ready, and locally rebase your branches onto HEAD multiple times a day to reduce the severity of merge conflicts.
- Use feature flags: Incomplete features at HEAD are unavoidable with trunk-based development, so use feature flagging to guard production behavior.
- One commit per PR: Each PR must have exactly one commit to ensure code-review is focused, simplify CI, and create a 1:1 mapping between changes and review. This is enforced automatically.
Overall this approach creates a single, shared, linear history in the main branch and creates an unambiguous shared HEAD.
All files must be stored directly in the repository and not in supplementary storage, meaning Git LFS, Git Annex, and all other such tools are banned. So far this has only results in two large vendored deps being ignored, and migration to a self-hosted Git repository is in progress to work around GitHub's 100MB limit.
TODO(jack-bradshaw): Migrate off GitHub and delete the above comment.
There is currently no CLA.
TODO(jack-bradshaw): Create a CLA.
Bugs? Look mate, you know who has a lot of bugs? Blokes who bludgeon their products to death with vibe coding. Professionals have standards. Be polite. Be efficient. Have a plan to kill every bug you meet.
TODO(jack-bradshaw): Formalize high level engineering standards.
Prioritise the following:
- Code quality.
- User experience.
Prioritizing code quality generally means providing documentation, optimising for maintainability and readability, always writing tests, taking time to refactor when code has grown beyond its original scope, following language/platform/framework conventions, and adhering to engineering best practices. If you are unsure about a change, simply consider the experience of the maintainer after you have moved on, and if you wouldn't want to be that person, improve the code now.
TODO(jack-bradshaw): Explain what prioritising the user experience means.