testtrim 0.7.2

Intelligently select automated tests to run via code coverage analysis
Documentation
# SPDX-FileCopyrightText: 2024 Mathieu Fenniak <mathieu@fenniak.net>
#
# SPDX-License-Identifier: GPL-3.0-or-later

{
  description = "cargo based nix development";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    rust-overlay.url = "github:oxalica/rust-overlay";
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }:
    flake-utils.lib.eachDefaultSystem (system: let
      overlays = [ (import rust-overlay) ];
      pkgs = import nixpkgs {
        inherit system overlays;
      };
      my-rust-bin = (pkgs.rust-bin.selectLatestNightlyWith( toolchain: toolchain.default.override {
        extensions = [
          "rust-src"
          "rust-analyzer"
          "llvm-tools-preview" # for llvm-profdata & llvm-cov # FIXME: maybe not needed anymore; pretty dated from early development days
        ];
      }));
      rustPlatform = pkgs.makeRustPlatform {
        cargo = my-rust-bin; # .stable.latest.minimal;
        rustc = my-rust-bin; # .stable.latest.minimal;
      };
      myBuildInputs = with pkgs; [
        openssl
        sqlite
      ];
      myNativeBuildInputs = with pkgs; [
        pkg-config
        openssl.dev
      ];
    in {
      devShells.default =
        pkgs.mkShell rec {
          nativeBuildInputs = [ pkgs.pkg-config ];

          buildInputs =  with pkgs; [
          ];

          packages = with pkgs;
            [ my-rust-bin ] ++
            myBuildInputs ++
            myNativeBuildInputs ++
            [
              cargo-binutils # allows access to llvm-profdata # FIXME: maybe not needed anymore; pretty dated from early development days
              cargo-expand # useful for understanding macros, run `cargo expand --lib > tmp.rs` to view intermediate output
              cargo-nextest
              dasel # needed for rust-check.yaml
              diesel-cli
              git-cliff # needed for release.yaml workflow
              jq # needed for release.yaml workflow
              my-rust-bin
              reuse
              rustfilt # LLVM rust demangler
              sqlx-cli
              strace

              # Can locally run the Forgejo action for quicker dev cycles:
              # act --container-daemon-socket unix:///run/podman/podman.sock -W ./.forgejo/workflows -P docker=node:20-bullseye
              act

              # FIXME: integration tests rely on having development tools available for each system that they operate
              # under -- ideally they would load such a thing from the target repo.  But this isn't a critical issue to
              # resolve because when testtrim is being used normally, it would be someone else's responsibility to get dev
              # tools in place that are relevant to the project.
              dotnet-sdk_8  # for dotnet-coverage-specimen
              go_1_23 # for go-coverage-specimen
            ];

          LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath buildInputs;

          shellHook = ''
            export RUST_BACKTRACE=1
          '';
        };

      packages = let
        testtrimVersion = (builtins.fromTOML (builtins.readFile ./Cargo.toml)).package.version;
        appPackage = rustPlatform.buildRustPackage {
          name = "testtrim";

          srcs = [
            ./.sqlx
            ./db
            ./src
            ./tests
            ./build.rs
            ./Cargo.lock
            ./Cargo.toml
          ];
          unpackPhase = ''
            runHook preUnpack

            for _src in $srcs; do
              cp -r "$_src" $(stripHash "$_src")
            done

            runHook postUnpack
          '';

          cargoLock = {
            lockFile = ./Cargo.lock;
          };

          # FIXME: not sure what dependencies are leftover here that might be affecting the binary output -- for
          # example, "cargo" -- that shouldn't be present after build...
          buildInputs = myBuildInputs;
          nativeBuildInputs = myNativeBuildInputs;

          # We'll do tests outside of the build in the CI.
          doCheck = false;

          # FIXME: it might be nicer to have the `cargo sql prepare` occur in this build script.  That'd nicer than
          # having to run it, `git add .sqlx`, but not keep them.  But it would require starting Postgres here and running
          # the SQL migrations, which is pretty awkward in a build script.
          buildPhase = ''
            runHook preBuild

            find .
            find .sqlx
            export CARGO_HOME=$TMPDIR # prevents any output to /homeless-shelter with cargo cache DBs
            cargo build --release

            runHook postBuild
          '';
          installPhase = ''
            runHook preInstall

            mkdir -p $out/bin
            cp target/release/testtrim $out/bin/

            runHook postInstall
          '';
        };
      in
      {
        # nix build --print-build-logs .#testtrim
        testtrim = appPackage;

        # nix build --print-build-logs .#docker && podman load -i result -q && podman run -it --rm -p 127.0.0.1:8080:8080 codeberg.org/testtrim/server:0.2.1
        docker = pkgs.dockerTools.buildLayeredImage {
          name = "codeberg.org/testtrim/server";
          tag = testtrimVersion;

          contents = [
            appPackage
            pkgs.coreutils # typically useful for diagnosing problems in the container
            # pkgs.cacert # may be needed?; not sure, depends on what rust TLS clients are in-use and what their CA strategy is...?
          ];

          config = {
            Cmd = [
              "${appPackage}/bin/testtrim"
              "run-server"
              # Default bind is localhost; but for port forwards to work correctly containers are expected to listen on
              # 0.0.0.0.
              "--bind-socket=0.0.0.0:8080"
              "-vv"
            ];
            Env = [];
            ExposedPorts = {
              "8080/tcp" = {};
            };
          };
        };
      };

    });
}