DEVELOPMENT.md
Rama master · réplica de lectura del repositorio original.
# How to Hack on GitButler
Alrighty, you want to get compiling. We love you already. Your parents raised
you right. Let's get started.
---
## Table of Contents
- [Overview](#overview)
- [CLI-only development](#cli-only-development)
- [The Basics](#the-basics)
- [Prerequisites](#prerequisites)
- [Install JavaScript dependencies](#install-javascript-dependencies)
- [Run the app](#run-the-app)
- [Lint & format](#lint--format)
- [Debugging](#debugging)
- [Logs](#logs)
- [Repository](#Repository)
- [Tokio](#tokio)
- [Troubleshooting](#troubleshooting)
- [Building](#building)
- [Building on Windows](#building-on-windows)
- [Perl](#perl)
- [Crosscompilation](#crosscompilation)
- [Design](#design)
- [Contributing](#contributing)
- [Some Other Random Notes](#some-other-random-notes)
- [Icon generation](#icon-generation)
- [Release](#release)
- [Versioning](#versioning)
- [Publishing](#publishing)
- [Development mode OAuth login](#development-mode-oauth-login)
- [Joining the GitButler Team](#joining-the-gitbutler-team)
---
## Overview
So how does this whole thing work?
It's a [Tauri app](https://tauri.app/), which is basically like an Electron app,
in that we can develop a desktop app from one source with multiple OS targets
and write the UI in HTML and Javascript. Except instead of Node for the
filesystem access part, Tauri uses [Rust](https://www.rust-lang.org/).
So everything that hits disk is in Rust, everything that the
user sees is in HTML/JS. Specifically we use [Svelte](https://svelte.dev/)
in Typescript for that layer.
For a deep dive into the architecture, see [DEEPWIKI](https://deepwiki.com/gitbutlerapp/gitbutler).
---
## CLI-only development
The easiest way to get started is by hacking on the `but` CLI.
You only need Rust installed…[^cli-build-prereqs]
```bash
$ cd gitbutler-repo
$ curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
```
…to build and run the CLI:
```bash
$ cargo build -p but
$ cargo run -p but -- --help
$ cargo run -p but -- -C /path/to/git-repo status
```
To test only the CLI:
```bash
$ cargo test -p but
```
Useful locations in the source tree:
- `crates/but/src/args` for CLI argument parsing and help text
- `crates/but/src/command` for command implementations
- `crates/but/tests` for integration tests
[^cli-build-prereqs]:
In practice, `cargo build -p but` also builds native
dependencies such as `git2` with vendored `openssl` and `libgit2`, so you
still need a working C toolchain. On Linux, that commonly means tools such
as `build-essential`, `make`, `perl`, `cmake`, and `pkg-config`; on macOS,
install Xcode Command Line Tools. On Windows, you’ll need a working
MSVC-based toolchain and related native dependencies; see
[Building on Windows](#building-on-windows) below for details (including
`perl` for `openssl-sys`). If you already completed the desktop
prerequisites in [The Basics](#the-basics), you already have the stricter setup.
If you already completed the desktop prerequisites in [The Basics](#the-basics) below,
you already have the stricter setup.
## The Basics
OK, let's get it running.
### Prerequisites
First of all, this is a Tauri app, which uses Rust for the backend and Javascript for the frontend. So let's make sure you have all the prerequisites installed.
1. Tauri Dev Deps (https://tauri.app/start/prerequisites/#system-dependencies)
On Mac OS, ensure you've installed XCode and `cmake`. On Linux, if you're on Debian or one of its derivatives like Ubuntu, you can use the following command.
<details>
<summary>Linux Tauri dependencies</summary>
```bash
$ sudo apt update
$ sudo apt install libwebkit2gtk-4.1-dev \
build-essential \
curl \
wget \
file \
libxdo-dev \
libssl-dev \
libayatana-appindicator3-dev \
librsvg2-dev \
cmake
```
</details>
2. Rust
For both Mac OS and Linux, you can use the following `rustup` quick install script to get all the necessary tools.
```bash
$ cd gitbutler-repo
$ curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
```
3. pnpm
Install standalone pnpm using the [pnpm installation instructions](https://pnpm.io/installation#using-a-standalone-script).
It provides Node.js.
### Install JavaScript dependencies
From the repository root, install the JavaScript dependencies. This also installs the project's Node.js runtime:
```bash
$ pnpm install
```
Re-run it when dependencies change.
Run project commands through `pnpm` scripts or `pnpm exec` to use that runtime.
> [!NOTE]
> We use [turborepo](https://turbo.build/repo) as our monorepo tooling and by default Vercel collects some [basic telemetry](https://turbo.build/repo/docs/telemetry). If you'd like to disable this, please run `pnpm exec turbo telemetry disable` once in the project's root directory after installing dependencies.
### Run the app
First, run cargo build such that supplementary bins such as `gitbutler-git-askpass` are created (Note the default folder (`target`) will be used for the build):
```bash
$ cargo build
```
Now you should be able to run the app in development mode:
```bash
$ pnpm dev:desktop
```
By default it will not print debug logs to console. If you want debug logs, set `LOG_LEVEL` environment variable:
```bash
$ LOG_LEVEL=debug pnpm dev:desktop
```
### Lint & format
In order to have a PR accepted, you need to make sure everything passes our
Linters, so make sure to run these before submitting. Our CI will shame you
if you don't.
Javascript:
```bash
$ pnpm lint
$ pnpm format
```
Rust:
```bash
$ cargo clippy # see linting errors
$ cargo fmt # format code
```
---
## Debugging
Now that you have the app running, here are some hints for debugging whatever
it is that you're working on.
### Logs
The app writes logs into:
1. `stdout` in development mode
2. The Tauri [logs](https://tauri.app/v1/api/js/path/#platform-specific) directory
One can get performance log when launching the application locally as follows:
```bash
GITBUTLER_PERFORMANCE_LOG=1 LOG_LEVEL=debug pnpm tauri dev
```
For more realistic performance logging, use local release builds with `--release`.
```bash
GITBUTLER_PERFORMANCE_LOG=1 LOG_LEVEL=debug pnpm tauri dev --release
```
### Repository
Often the behaviour depends on the current context: the repository being displayed. Next to _logs_, it's useful to learn how it's structured.
To do that, _launch the application from a terminal_ as shown in the paragraph above this one, or right below, but with `graphviz` installed.
The `dot` program should be available in `PATH` so it can run from the terminal.
Doing so can look like this on macOS, for example:
###### For the stable build
```shell
GITBUTLER_PERFORMANCE_LOG=1 /Applications/GitButler/Contents/MacOS/gitbutler-tauri
```
###### For the nightly build
```shell
GITBUTLER_PERFORMANCE_LOG=1 /Applications/GitButler\ Nightly.app/Contents/MacOS/gitbutler-tauri
```
###### Producing a commit-graph visualization
Then, within the application, type `dot` in any non-editable portion of the GUI, like the cheat code that it is.
This will pop open an SVG version of the graph that GitButler uses to create the workspace projection.
### Tokio
We are also collecting tokio's runtime tracing information that could be viewed using [tokio-console](https://github.com/tokio-rs/console#tokio-console-prototypes):
- development:
```bash
$ tokio-console
```
- nightly:
```bash
$ tokio-console http://127.0.0.1:6668
```
- production:
```bash
$ tokio-console http://127.0.0.1:6667
```
---
## Troubleshooting
Common issues and solutions when developing GitButler.
### Turbo/build issues
#### Case-sensitive volume problems
If you're experiencing issues with the `dev:desktop` target failing to start, especially on macOS with case-sensitive filesystems, this may be related to Turborepo's handling of case-sensitive volumes.
**Solution:** See the related issue at [vercel/turborepo#8491](https://github.com/vercel/turborepo/issues/8491) for current workarounds.
#### Turbo daemon issues
If builds are hanging or behaving unexpectedly:
```bash
# Stop the turbo daemon
pnpm exec turbo daemon stop
# Clear turbo cache
pnpm exec turbo daemon clean
# Restart development
pnpm dev:desktop
```
### Cache issues
If you're seeing stale builds or unexpected behavior:
```bash
rm -rf .turbo node_modules
pnpm install
# Optional (Rust artifacts):
cargo clean
```
### Additional resources
For issues specific to our toolchain components:
- [Turborepo issues](https://github.com/vercel/turborepo/issues)
- [Tauri issues](https://github.com/tauri-apps/tauri/issues)
If none of these solutions work, please check our [GitHub Issues](https://github.com/gitbutlerapp/gitbutler/issues) or create a new issue with detailed information about your system and the error you're encountering.
---
## Building
To build the app in production mode, run:
```bash
$ pnpm tauri build --features devtools,builtin-but,disable-auto-updates,nightly --config crates/gitbutler-tauri/tauri.conf.nightly-local.json
```
This will make an asset similar to our nightly build.
### Building on Windows
Building on Windows is a bit of a tricky process. Here are some helpful tips.
#### Perl
A Perl interpreter is required to be installed in order to configure the `openssl-sys`
crate. We've used [Strawberry Perl](https://strawberryperl.com/) without issue.
Make sure it's installed and `perl` is available on the `PATH` (it is by default
after installation, just make sure to restart the terminal after installing).
[Scoop](https://scoop.sh/) users can install this via `scoop install perl`.
Note that it might appear that the build has hung or frozen on the `openssl-sys` crate.
It's not, it's just that Cargo can't report the status of a C/C++ build happening
under the hood, and openssl is _large_. It'll take a while to compile.
#### OpenSSL
To build it, one needs to export the path to the perl installation to use.
The line below will do the trick in a git-bash.
```bash
export OPENSSL_SRC_PERL="c:/Strawberry/perl/bin/perl.exe"
```
To make this change permanent, one would one can add this change (and others) to the `~/.bash_profile`.
```bash
echo 'export OPENSSL_SRC_PERL="c:/Strawberry/perl/bin/perl.exe"' >> ~/.bash_profile
```
#### Crosscompilation
This paragraph is about crosscompilation to x86_64-MSVC from ARM Windows,
a configuration typical for people with Apple Silicon and Parallels VMs,
which only allow ARM Windows to be used.
The `windows` dependency on `gitbutler-git` doesn't currently compile on ARM,
which means cross-compilation to x86-64 is required to workaround that. Besides,
most users will probably still be on INTEL machines, making this capability
a common requirement.
In a Git `bash`, _with MSVC for x86-64 installed on the system_, run the following
to prepare the environment.
```bash
export TRIPLE_OVERRIDE=x86_64-pc-windows-msvc
export CARGO_BUILD_TARGET=x86_64-pc-windows-msvc
# for good measure
export OPENSSL_SRC_PERL="c:/Strawberry/perl/bin/perl.exe"
```
Here is how to produce a nightly release build:
```
pnpm tauri build --features windows,devtools,nightly --config crates/gitbutler-tauri/tauri.conf.nightly.json
```
And this is how to get a local developer debug build:
```bash
pnpm tauri dev --features windows --target x86_64-pc-windows-msvc
```
Note that it's necessary to repeat the `--target` specification as otherwise the final copy operation doesn't work,
triggered by `tauri` itself.
---
## Design
We use [Figma](https://www.figma.com/) for our design work.
If you're a designer (and even if you're not), you want to contribute to the
design of GitButler, or your work involves UI, you could duplicate our design file.
GitButler design: [Figma file](https://www.figma.com/file/FbeLt0yjY9RiNn8MXUXsYs/Client-Design?type=design&node-id=0%3A1&mode=design&t=MUDQhR3iOM3DpI9m-1) 🎨
---
## Contributing
Now that you're up and running, if you want to change something and open a PR
for us, make sure to read [CONTRIBUTING.md](CONTRIBUTING.md) to make sure you're
not wasting your time.
---
## Some Other Random Notes
Most of this is for internal GitButler use, but maybe everyone else will find
it interesting too.
---
### Icon generation
I always forget how to do this, but when we update our app icon, run this to
import it.
```bash
$ pnpm tauri icon path/to/icon.png
```
### Release
Building is done via [GitHub Action](https://github.com/gitbutlerapp/gitbutler/actions/workflows/publish.yaml).
Go to the link and select `Run workflow` from the desired branch.
### Versioning
When running the [release action](https://github.com/gitbutlerapp/gitbutler/actions/workflows/publish.yaml),
you will have to choose one of `major`, `minor`, or `patch` release type. Action will generate a new version based on your input and current
version found at `https://app.gitbutler.com/releases`.
### Publishing
To publish a version that you've just build, use [Release Manager](https://gitbutler.retool.com/apps/cb9cbed6-ae0a-11ed-918c-736c4335d3af/Release%20Manager).
---
## Development mode OAuth login
By default, you will not be able to log into GitButler using Github/Google because the base url does not match. To be able to do this add ( or update ) the following line to your `.env.development` file. You will need to create the file if it does not exist.
```
PUBLIC_API_BASE_URL=https://app.gitbutler.com/
```
The desktop frontend and local backend both honor `PUBLIC_API_BASE_URL`. If you
need a backend-only override while debugging, `GITBUTLER_API_URL` still takes
precedence on the Rust side.
When you start the desktop app with `pnpm dev:desktop`, the Tauri launcher now
loads `apps/desktop/.env`, `.env.local`, `.env.development`, and
`.env.development.local` into the Rust process as well, so the frontend and
backend see the same local overrides by default.
---
## Joining the GitButler Team
If you are interested in joining our small but tightly knit engineering team, we are currently looking for the following roles:
- [Senior Rust developer](https://jobs.gitbutler.com/jobs/backend-rust) (SF, Berlin or Remote)
- [Senior TypeScript developer](https://jobs.gitbutler.com/jobs/frontend-typescript) (SF, Berlin or Remote)
- [Gerrit developer](https://jobs.gitbutler.com/jobs/gerrit-developer) (SF, Berlin or Remote)
## Code Hitlist
This is a list of crates/modules that we want to eliminate or split into smaller crates:
- [gitbutler-reference](crates/gitbutler-reference/) (just bad)
- [gitbutler-branch-actions](crates/gitbutler-branch-actions/) (contains functionality outside of the virtual branch domain (e.g. commit actions etc.))
- [gitbutler-branch](crates/gitbutler-branch/) (contains `diff` and `branch` contexts due to a cyclic dependency)
- [gitbutler_repo::config](crates/gitbutler-repo/src/config.rs) (seems like the wrong abstraction)