{ description = "itsybitsy - serve folders of Markdown over HTTP, Gemini, Spartan, Nex and Gopher"; inputs = { # Pinned independently of any consumer, and deliberately not `follows`-ed. # Every crate here declares rust-version = "1.97"; nixos-25.11 ships 1.91.1, # so a consumer's nixpkgs cannot build this. Nothing needs to: bucur fetches # the release asset that `apps.release-static` publishes. nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; }; outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem ( system: let pkgs = nixpkgs.legacyPackages.${system}; common = { pname = "itsybitsy"; version = "0.1.0"; src = ./.; cargoLock.lockFile = ./Cargo.lock; # The workspace root is virtual, and cargo refuses `--features` there # without a package selector, so name the binary crate outright. cargoBuildFlags = [ "--package" "itsybitsy" ]; # WML is opt-in upstream and the bundled itsybitsy.toml lists it, so a # default build refuses to boot that config at all. The deployment # wants it too: WAP handsets are the only client that asks for it, and # they are exactly the audience a WML face exists for. buildFeatures = [ "wml" ]; meta = { description = "Serve folders of Markdown to several domains"; license = pkgs.lib.licenses.asl20; mainProgram = "itsybitsy"; }; }; in { # Native build, and where the test suite runs. The integration tests # bind 127.0.0.1 on port 0, which the Nix sandbox allows: it has its own # network namespace with loopback up, so there is nothing to collide # with and no fixed port to claim. packages.default = pkgs.rustPlatform.buildRustPackage ( common // { cargoTestFlags = [ "--workspace" ]; } ); # The published artifact. Fully static against musl, so the consumer # needs neither autoPatchelfHook nor a matching glibc: there is no C # dependency anywhere in the tree, not even a TLS library, so unlike # bunshin's sqlite there is nothing to cross-provide. packages.static = pkgs.pkgsStatic.rustPlatform.buildRustPackage ( common // { doCheck = false; } ); apps.default = flake-utils.lib.mkApp { drv = self.packages.${system}.default; name = "itsybitsy"; }; # Builds packages.static and publishes it as a Forgejo release tagged by # short commit hash, creating the release if absent and replacing the # asset if present. Needs FORGEJO_TOKEN (write:repository) in the # environment or in .env. Same shape as bunshin's. # # Note the asymmetry that bit bunshin: assets are *uploaded* to # /releases//assets but *downloaded* from /releases/download// # . The generic package-registry path 404s; the consumer must use # the download form. apps.release-static = flake-utils.lib.mkApp { drv = pkgs.writeShellApplication { name = "itsybitsy-release-static"; runtimeInputs = [ pkgs.nix pkgs.curl pkgs.git pkgs.jq ]; text = '' if [ -f .env ]; then set -a # shellcheck disable=SC1091 . ./.env set +a fi : "''${FORGEJO_TOKEN:?set FORGEJO_TOKEN (env or .env) to a Forgejo token with write:repository scope}" rev=$(git rev-parse --short HEAD) sha=$(git rev-parse HEAD) out=$(nix build .#static --no-link --print-out-paths) bin="$out/bin/itsybitsy" api="https://code.randogoth.com/api/v1/repos/randogoth/itsybitsy" auth=(-H "Authorization: token ''${FORGEJO_TOKEN}") release_id=$(curl -sS "''${auth[@]}" "$api/releases/tags/$rev" | jq -r '.id // empty') if [ -z "$release_id" ]; then release_id=$(curl -sSf "''${auth[@]}" -H "Content-Type: application/json" \ -d "$(jq -n --arg tag "$rev" --arg sha "$sha" \ '{tag_name:$tag, target_commitish:$sha, name:$tag, body:"Static musl build.", draft:false, prerelease:false}')" \ "$api/releases" | jq -r '.id') fi asset_id=$(curl -sSf "''${auth[@]}" "$api/releases/$release_id/assets" | jq -r '.[] | select(.name=="itsybitsy") | .id' | head -1) if [ -n "$asset_id" ]; then curl -sSf -X DELETE "''${auth[@]}" "$api/releases/$release_id/assets/$asset_id" >/dev/null fi curl -sSf "''${auth[@]}" -F "attachment=@$bin;filename=itsybitsy" "$api/releases/$release_id/assets?name=itsybitsy" >/dev/null echo "released: https://code.randogoth.com/randogoth/itsybitsy/releases/tag/$rev" echo "fetch at: https://code.randogoth.com/randogoth/itsybitsy/releases/download/$rev/itsybitsy" ''; }; }; devShells.default = pkgs.mkShell { packages = with pkgs; [ cargo rustc rustfmt clippy ]; }; } ); }