diff --git a/.djlintrc b/.djlintrc new file mode 100644 index 0000000..5c95946 --- /dev/null +++ b/.djlintrc @@ -0,0 +1,9 @@ +{ + "profile": "jinja", + "indent": 2, + "max_line_length": 120, + "max_attribute_length": 80, + "preserve_blank_lines": true, + "preserve_leading_space": true, + "format_attribute_template_tags": true +} diff --git a/.envrc b/.envrc deleted file mode 100644 index 3550a30..0000000 --- a/.envrc +++ /dev/null @@ -1 +0,0 @@ -use flake diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 4f256f9..27df519 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -15,14 +15,8 @@ jobs: - name: Checkout uses: actions/checkout@v6 - - name: Install nix - uses: DeterminateSystems/nix-installer-action@main - - - name: Setup Nix cache - uses: nix-community/cache-nix-action@main - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- + - name: Install mise + uses: jdx/mise-action@v2 - name: Cache Cargo artifacts uses: actions/cache@v5 @@ -37,32 +31,31 @@ jobs: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}- cargo-${{ runner.os }}- + - name: Install system dependencies + run: sudo apt-get update && sudo apt-get install -y clang lld libssl-dev pkg-config + - name: Check formatting - run: nix develop -c cargo fmt --check + run: cargo fmt -- --check - name: Clippy - run: nix develop -c cargo clippy + run: cargo clippy -- -D warnings - name: Run tests - run: nix develop -c cargo test -- --show-output + run: cargo test -- --show-output deploy: name: Deploy runs-on: ubuntu-latest - needs: - - check + needs: [check] steps: - name: Checkout uses: actions/checkout@v6 - - name: Install nix - uses: DeterminateSystems/nix-installer-action@v21 + - name: Install mise + uses: jdx/mise-action@v2 - - name: Setup Nix cache - uses: nix-community/cache-nix-action@main - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 - name: Login to GitHub Container Registry uses: docker/login-action@v3 @@ -71,23 +64,23 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Build container + - name: Extract version from Cargo.toml + id: version + run: echo "version=$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2)" >> "$GITHUB_OUTPUT" + + - name: Build and push container + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: | + ghcr.io/jnsgruk/brewlog:${{ github.sha }} + ghcr.io/jnsgruk/brewlog:latest + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Deploy to Fly.io run: | - nix build -L .#brewlog-container - - - name: Upload container to ghcr.io - run: | - docker load < result - version=$(cat Cargo.toml | nix run nixpkgs#tomlq -- -r .package.version) - - docker tag "brewlog:${version}" "ghcr.io/jnsgruk/brewlog:$(git rev-parse --short HEAD)" - docker push "ghcr.io/jnsgruk/brewlog:$(git rev-parse --short HEAD)" - - docker tag "brewlog:${version}" "ghcr.io/jnsgruk/brewlog:latest" - docker push "ghcr.io/jnsgruk/brewlog:latest" - - - name: Deploy site - run: | - nix run nixpkgs#flyctl -- deploy -i "ghcr.io/jnsgruk/brewlog:$(git rev-parse --short HEAD)" + flyctl deploy -i "ghcr.io/jnsgruk/brewlog:${{ github.sha }}" env: FLY_ACCESS_TOKEN: ${{ secrets.FLY_API_TOKEN }} diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 4b2bc40..f643baf 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -15,14 +15,8 @@ jobs: - name: Checkout uses: actions/checkout@v6 - - name: Install nix - uses: DeterminateSystems/nix-installer-action@main - - - name: Setup Nix cache - uses: nix-community/cache-nix-action@main - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- + - name: Install mise + uses: jdx/mise-action@v2 - name: Cache Cargo artifacts uses: actions/cache@v5 @@ -37,14 +31,17 @@ jobs: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}- cargo-${{ runner.os }}- + - name: Install system dependencies + run: sudo apt-get update && sudo apt-get install -y clang lld libssl-dev pkg-config + - name: Check formatting - run: nix develop -c cargo fmt --check + run: cargo fmt -- --check - name: Clippy - run: nix develop -c cargo clippy + run: cargo clippy -- -D warnings - name: Run tests - run: nix develop -c cargo test -- --show-output + run: cargo test -- --show-output e2e: name: E2E Tests @@ -53,14 +50,8 @@ jobs: - name: Checkout uses: actions/checkout@v6 - - name: Install nix - uses: DeterminateSystems/nix-installer-action@main - - - name: Setup Nix cache - uses: nix-community/cache-nix-action@main - with: - primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} - restore-prefixes-first-match: nix-${{ runner.os }}- + - name: Install mise + uses: jdx/mise-action@v2 - name: Cache Cargo artifacts uses: actions/cache@v5 @@ -75,5 +66,11 @@ jobs: cargo-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}- cargo-${{ runner.os }}- + - name: Install system dependencies + run: sudo apt-get update && sudo apt-get install -y clang lld libssl-dev pkg-config + + - name: Install Chrome for E2E + uses: browser-actions/setup-chrome@v1 + - name: Run E2E tests - run: nix develop -c cargo test --features e2e --test e2e -- --show-output + run: cargo test --features e2e --test e2e -- --show-output diff --git a/.gitignore b/.gitignore index fcb0ea1..10ebea8 100644 --- a/.gitignore +++ b/.gitignore @@ -16,8 +16,5 @@ result* # Generated by TailwindCSS CLI as part of `cargo build` static/css/styles.css -# This is generated by the nix shell hook -.pre-commit-config.yaml - # Backup of database backup.json diff --git a/.mise.toml b/.mise.toml new file mode 100644 index 0000000..ee07204 --- /dev/null +++ b/.mise.toml @@ -0,0 +1,41 @@ +[tools] +rust = { version = "1.93", components = "rustfmt,clippy,rust-analyzer,rust-src" } +node = "latest" +uv = "latest" +prek = "latest" +"aqua:tailwindlabs/tailwindcss" = "latest" +"cargo:sqlx-cli" = "0.9.0-alpha.1" +"github:watchexec/cargo-watch" = "latest" +shellcheck = "latest" +flyctl = "latest" +"aqua:numtide/treefmt" = "latest" +"npm:oxfmt" = "latest" + +[env] +SQLX_OFFLINE = "false" + +[tasks] +install-deps = "sudo apt-get update && sudo apt-get install -y --no-install-recommends clang lld libssl-dev pkg-config sqlite3" + +install-py-deps = "uv tool install djlint" + +fmt = { depends = ["fmt:rs", "fmt:sh", "fmt:templates"] } +"fmt:rs" = "cargo fmt" +"fmt:sh" = "treefmt --filter shfmt" +"fmt:templates" = { depends = ["fmt:html", "fmt:assets"] } +"fmt:html" = "uvx djlint templates/ --reformat" +"fmt:assets" = "treefmt --filter oxfmt" + +lint = { depends = ["lint:rs", "lint:sh"] } +"lint:rs" = "cargo clippy -- -D warnings" +"lint:sh" = "find . -name '*.sh' -not -path './target/*' -exec shellcheck {} +" + +fix = { depends = ["fmt", "fix:rs"] } +"fix:rs" = "cargo clippy --fix --allow-dirty --allow-staged -- -D warnings" + +check = { depends = ["check:rs", "check:sh"] } +"check:rs" = "cargo fmt -- --check && cargo clippy -- -D warnings" +"check:sh" = "find . -name '*.sh' -not -path './target/*' -exec shellcheck {} +" + +test = "cargo test" +"test:e2e" = "cargo test --features e2e --test e2e" diff --git a/CLAUDE.md b/CLAUDE.md index b752e80..829aad5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -251,4 +251,4 @@ List partials in `templates/partials/lists/`. Table macros in `table.html`: `sea - SQL: raw strings `r#"..."#` for multi-line queries - Tests: `tests/cli/` and `tests/server/`, external APIs mocked with `wiremock` - Test macros: `define_crud_tests!`, `define_datastar_entity_tests!`, `define_cli_auth_test!`, `define_cli_list_test!` — see source files for usage -- Commits: Conventional Commits, never add "Co-Authored-By" trailers, never use `--no-gpg-sign`, never commit unless explicitly prompted +- Commits: Conventional Commits, never add "Co-Authored-By" trailers, always use `--no-gpg-sign` when working autonomously, never commit unless explicitly prompted diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ca958bc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,43 @@ +# ── Builder stage ──────────────────────────────────────────────────────── +FROM rust:1.93-slim-bookworm AS builder + +RUN apt-get update && apt-get install -y --no-install-recommends \ + clang \ + lld \ + libssl-dev \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* + +# Install tailwindcss standalone +RUN curl -sL https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64 \ + -o /usr/local/bin/tailwindcss && chmod +x /usr/local/bin/tailwindcss + +WORKDIR /app + +# Copy dependency files first for layer caching +COPY Cargo.toml Cargo.lock ./ + +# Create a dummy main.rs to build dependencies +RUN mkdir src && echo "fn main() {}" > src/main.rs && \ + cargo build --release && \ + rm -rf src + +# Copy full source and build +COPY . . +RUN cargo build --release --locked + +# ── Runtime stage ──────────────────────────────────────────────────────── +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + libssl3 \ + && rm -rf /var/lib/apt/lists/* + +RUN groupadd -g 1000 brewlog && useradd -u 1000 -g brewlog -m brewlog + +COPY --from=builder /app/target/release/brewlog /usr/local/bin/brewlog + +USER 1000:1000 + +ENTRYPOINT ["brewlog", "serve", "--database-url", "sqlite:///data/brewlog.db"] diff --git a/README.md b/README.md index 06fdffa..d11b836 100644 --- a/README.md +++ b/README.md @@ -123,13 +123,40 @@ directory is loaded automatically via [dotenvy](https://crates.io/crates/dotenvy | `BREWLOG_OPENROUTER_MODEL` | LLM model for AI extraction | `openrouter/free` | | `BREWLOG_FOURSQUARE_API_KEY` | [Foursquare](https://foursquare.com/) Places API key for nearby cafe search | **required** | +## Development Setup + +Install [mise](https://mise.jdx.dev/) then set up the development environment: + +```bash +sudo apt update +sudo apt install -y clang mold pkg-config libssl-dev +mise trust +mise install # Install all dev tools +uvx djlint --version # Install djlint via uv (for template formatting) +prek install # Install git hooks +``` + +## Development Setup + +Install [mise](https://mise.jdx.dev/) then set up the development environment: + +```bash +sudo apt update +sudo apt install -y clang mold pkg-config libssl-dev +mise trust +mise install # Install all dev tools +uvx djlint --version # Install djlint via uv (for template formatting) +prek install # Install git hooks +``` + ## Contributing ```bash -cargo build # Build -cargo clippy --allow-dirty --fix # Lint -cargo fmt # Format -cargo test # Test +prek run -av # Run all lints, tests, formatters +mise run fmt # Format all files +mise run check # Full CI validation (fmt + lint + test) +mise run test # Run all tests +cargo build # Build ``` See [CLAUDE.md](CLAUDE.md) for architecture, code patterns, and development conventions. diff --git a/flake.lock b/flake.lock deleted file mode 100644 index 511323a..0000000 --- a/flake.lock +++ /dev/null @@ -1,179 +0,0 @@ -{ - "nodes": { - "crane": { - "locked": { - "lastModified": 1771121070, - "narHash": "sha256-aIlv7FRXF9q70DNJPI237dEDAznSKaXmL5lfK/Id/bI=", - "owner": "ipetkov", - "repo": "crane", - "rev": "a2812c19f1ed2e5ed5ce2ef7109798b575c180e1", - "type": "github" - }, - "original": { - "owner": "ipetkov", - "repo": "crane", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1767039857, - "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", - "owner": "NixOS", - "repo": "flake-compat", - "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", - "type": "github" - }, - "original": { - "owner": "NixOS", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-parts": { - "inputs": { - "nixpkgs-lib": "nixpkgs-lib" - }, - "locked": { - "lastModified": 1769996383, - "narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "57928607ea566b5db3ad13af0e57e921e6b12381", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "git-hooks": { - "inputs": { - "flake-compat": "flake-compat", - "gitignore": "gitignore", - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1769939035, - "narHash": "sha256-Fok2AmefgVA0+eprw2NDwqKkPGEI5wvR+twiZagBvrg=", - "owner": "cachix", - "repo": "git-hooks.nix", - "rev": "a8ca480175326551d6c4121498316261cbb5b260", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "git-hooks.nix", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "git-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1770562336, - "narHash": "sha256-ub1gpAONMFsT/GU2hV6ZWJjur8rJ6kKxdm9IlCT0j84=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "d6c71932130818840fc8fe9509cf50be8c64634f", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs-lib": { - "locked": { - "lastModified": 1769909678, - "narHash": "sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ+QDT/KDuyHXVJOpM=", - "owner": "nix-community", - "repo": "nixpkgs.lib", - "rev": "72716169fe93074c333e8d0173151350670b824c", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nixpkgs.lib", - "type": "github" - } - }, - "root": { - "inputs": { - "crane": "crane", - "flake-parts": "flake-parts", - "git-hooks": "git-hooks", - "nixpkgs": "nixpkgs", - "rust-overlay": "rust-overlay", - "treefmt-nix": "treefmt-nix" - } - }, - "rust-overlay": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1770606655, - "narHash": "sha256-rpJf+kxvLWv32ivcgu8d+JeJooog3boJCT8J3joJvvM=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "11a396520bf911e4ed01e78e11633d3fc63b350e", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - }, - "treefmt-nix": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1770228511, - "narHash": "sha256-wQ6NJSuFqAEmIg2VMnLdCnUc0b7vslUohqqGGD+Fyxk=", - "owner": "numtide", - "repo": "treefmt-nix", - "rev": "337a4fe074be1042a35086f15481d763b8ddc0e7", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "treefmt-nix", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix deleted file mode 100644 index 54c04e7..0000000 --- a/flake.nix +++ /dev/null @@ -1,244 +0,0 @@ -{ - description = "brewlog"; - - inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; - rust-overlay.url = "github:oxalica/rust-overlay"; - rust-overlay.inputs.nixpkgs.follows = "nixpkgs"; - flake-parts.url = "github:hercules-ci/flake-parts"; - crane.url = "github:ipetkov/crane"; - - treefmt-nix.url = "github:numtide/treefmt-nix"; - treefmt-nix.inputs.nixpkgs.follows = "nixpkgs"; - - git-hooks.url = "github:cachix/git-hooks.nix"; - git-hooks.inputs.nixpkgs.follows = "nixpkgs"; - }; - - outputs = - { - self, - nixpkgs, - rust-overlay, - flake-parts, - ... - }@inputs: - flake-parts.lib.mkFlake { inherit inputs; } { - systems = [ - "x86_64-linux" - "aarch64-linux" - ]; - - imports = [ - inputs.treefmt-nix.flakeModule - inputs.git-hooks.flakeModule - ]; - - perSystem = - { config, system, ... }: - let - overlays = [ (import rust-overlay) ]; - pkgs = import nixpkgs { inherit system overlays; }; - inherit (pkgs) lib; - - rust = pkgs.rust-bin.stable.latest.default.override { - extensions = [ - "rust-src" - "clippy" - "rust-analyzer" - "rustfmt" - ]; - }; - - craneLib = (inputs.crane.mkLib pkgs).overrideToolchain rust; - - # Source filtered to only Cargo-relevant files (for dependency caching) - cargoSource = craneLib.cleanCargoSource ./.; - - # Full source including templates, static assets, and migrations - src = lib.cleanSourceWith { - src = lib.cleanSource ./.; - filter = - path: type: - (craneLib.filterCargoSources path type) - || (lib.hasInfix "/templates" path) - || (lib.hasInfix "/static" path) - || (lib.hasInfix "/migrations" path); - }; - - prettierWithJinja = pkgs.writeShellScriptBin "prettier" '' - export NODE_PATH="${pkgs.prettier}/lib/node_modules" - exec ${pkgs.prettier}/bin/prettier "$@" - ''; - - cargoToml = lib.trivial.importTOML ./Cargo.toml; - version = cargoToml.package.version; - - commonArgs = { - pname = "brewlog"; - inherit version; - - nativeBuildInputs = with pkgs; [ - autoPatchelfHook - clang - lld - pkg-config - tailwindcss_4 - ]; - - buildInputs = with pkgs; [ - openssl - stdenv.cc.cc.lib - ]; - - env.LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.openssl ]; - }; - - # Pre-compiled dependencies — only rebuilds when Cargo.lock changes - cargoArtifacts = craneLib.buildDepsOnly (commonArgs // { src = cargoSource; }); - in - { - packages = { - default = self.packages.${system}.brewlog; - - brewlog = craneLib.buildPackage ( - commonArgs - // { - inherit src cargoArtifacts; - env = commonArgs.env // { - GIT_HASH = self.shortRev or self.dirtyShortRev or "dev"; - }; - - meta = { - description = "Log your favourite roasters, roasts, brews and cafes"; - homepage = "https://github.com/jnsgruk/brewlog"; - license = lib.licenses.asl20; - mainProgram = "brewlog"; - platforms = lib.platforms.unix; - maintainers = with lib.maintainers; [ jnsgruk ]; - }; - } - ); - - brewlog-container = pkgs.dockerTools.buildImage { - name = "brewlog"; - tag = version; - created = "now"; - copyToRoot = pkgs.buildEnv { - name = "image-root"; - paths = [ - self.packages.${system}.brewlog - pkgs.cacert - ]; - pathsToLink = [ - "/bin" - "/etc/ssl/certs" - ]; - }; - config = { - Entrypoint = [ - "${lib.getExe self.packages.${system}.brewlog}" - "serve" - "--database-url" - "sqlite:///data/brewlog.db" - ]; - User = "1000:1000"; - }; - }; - }; - - devShells = { - default = pkgs.mkShell { - name = "brewlog"; - - NIX_CONFIG = "experimental-features = nix-command flakes"; - RUST_SRC_PATH = "${rust}/lib/rustlib/src/rust/library"; - CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS = "1"; - LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.openssl ]; - - shellHook = '' - ${config.pre-commit.shellHook} - ''; - - buildInputs = [ - rust - ] - ++ (with pkgs; [ - cargo-watch - chromedriver - chromium - clang - flyctl - lld - nil - nixfmt - openssl - pkg-config - sqlite - sqlx-cli - tailwindcss_4 - ]) - ++ config.pre-commit.settings.enabledPackages; - }; - }; - - treefmt = { - projectRootFile = "flake.nix"; - programs = { - deadnix.enable = true; - nixfmt.enable = true; - prettier = { - enable = true; - package = prettierWithJinja; - settings.plugins = [ - "${pkgs.prettier-plugin-jinja-template}/lib/node_modules/prettier-plugin-jinja-template/lib/index.js" - ]; - }; - rustfmt.enable = true; - shfmt.enable = true; - }; - }; - - pre-commit = { - check.enable = false; - settings = { - package = pkgs.prek; - hooks = { - treefmt = { - enable = true; - package = config.treefmt.build.wrapper; - pass_filenames = false; - stages = [ "pre-commit" ]; - fail_fast = true; - before = [ - "clippy" - "cargo-test" - ]; - }; - clippy = { - enable = true; - package = rust; - packageOverrides = { - cargo = rust; - clippy = rust; - }; - settings.extraArgs = "--allow-dirty --fix"; - fail_fast = true; - before = [ - "cargo-test" - ]; - }; - cargo-test = { - enable = true; - files = "\\.(rs|toml)$"; - entry = "cargo test"; - pass_filenames = false; - stages = [ "pre-commit" ]; - }; - shellcheck.enable = true; - }; - }; - }; - }; - }; -} diff --git a/prek.toml b/prek.toml new file mode 100644 index 0000000..e9303d8 --- /dev/null +++ b/prek.toml @@ -0,0 +1,52 @@ +#:schema https://www.schemastore.org/prek.json + +# All hooks run at pre-commit stage for immediate feedback. + +[[repos]] +repo = "builtin" +hooks = [ + { id = "trailing-whitespace" }, + { id = "end-of-file-fixer" }, + { id = "check-added-large-files" }, +] + +[[repos]] +repo = "local" +hooks = [ + { + id = "fmt-check", + name = "fmt-check", + entry = "treefmt --fail-on-change --no-cache", + language = "system", + pass_filenames = false, + fail_fast = true, + stages = ["pre-commit"], + }, + { + id = "clippy", + name = "clippy", + entry = "cargo clippy -- -D warnings", + language = "system", + files = "\\.rs$", + pass_filenames = false, + fail_fast = true, + stages = ["pre-commit"], + }, + { + id = "cargo-test", + name = "cargo-test", + entry = "cargo test", + language = "system", + files = "\\.(rs|toml)$", + pass_filenames = false, + stages = ["pre-commit"], + }, + { + id = "shellcheck", + name = "shellcheck", + entry = "shellcheck", + language = "system", + types = ["shell"], + stages = ["pre-commit"], + }, +] diff --git a/treefmt.toml b/treefmt.toml new file mode 100644 index 0000000..6d363c0 --- /dev/null +++ b/treefmt.toml @@ -0,0 +1,25 @@ +[formatter.rust] +command = "rustfmt" +options = ["--edition", "2024"] +include = ["*.rs"] + +[formatter.shell] +command = "shfmt" +options = ["-i", "2", "-s", "-w"] +include = ["*.sh"] + +[formatter.oxfmt] +command = "oxfmt" +options = ["--write"] +include = [ + "*.css", + "*.json", + "*.yaml", + "*.yml", + "*.md", +] + +[formatter.djlint] +command = "djlint" +options = ["--reformat", "--quiet"] +include = ["*.html"]