chore: migrate from Nix to mise for dev environment management
Replace Nix flake with mise for toolchain management, treefmt for formatting, prek for pre-commit hooks, and a Dockerfile for container builds. Update CI workflows to use jdx/mise-action instead of Nix. Add system dependency instructions to README.md and CLAUDE.md.
This commit is contained in:
parent
edffb1679d
commit
527358b695
13 changed files with 249 additions and 489 deletions
9
.djlintrc
Normal file
9
.djlintrc
Normal file
|
|
@ -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
|
||||
}
|
||||
1
.envrc
1
.envrc
|
|
@ -1 +0,0 @@
|
|||
use flake
|
||||
67
.github/workflows/deploy.yml
vendored
67
.github/workflows/deploy.yml
vendored
|
|
@ -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 }}
|
||||
|
|
|
|||
37
.github/workflows/push.yml
vendored
37
.github/workflows/push.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -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
|
||||
|
|
|
|||
41
.mise.toml
Normal file
41
.mise.toml
Normal file
|
|
@ -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"
|
||||
|
|
@ -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
|
||||
|
|
|
|||
43
Dockerfile
Normal file
43
Dockerfile
Normal file
|
|
@ -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"]
|
||||
33
README.md
33
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
|
||||
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
|
||||
cargo clippy --allow-dirty --fix # Lint
|
||||
cargo fmt # Format
|
||||
cargo test # Test
|
||||
```
|
||||
|
||||
See [CLAUDE.md](CLAUDE.md) for architecture, code patterns, and development conventions.
|
||||
|
|
|
|||
179
flake.lock
179
flake.lock
|
|
@ -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
|
||||
}
|
||||
244
flake.nix
244
flake.nix
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
52
prek.toml
Normal file
52
prek.toml
Normal file
|
|
@ -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"],
|
||||
},
|
||||
]
|
||||
25
treefmt.toml
Normal file
25
treefmt.toml
Normal file
|
|
@ -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"]
|
||||
Loading…
Reference in a new issue