{ inputs, ... }:
{
perSystem =
{
self',
pkgs,
lib,
...
}:
let
craneLib = (inputs.crane.mkLib pkgs).overrideToolchain (_: self'.packages.buildToolchain);
craneLibFull = (inputs.crane.mkLib pkgs).overrideToolchain (_: self'.packages.devToolchain);
src = craneLib.cleanCargoSource inputs.self;
commonArgs = rec {
inherit src;
strictDeps = true;
nativeBuildInputs = [ pkgs.pkg-config ];
buildInputs = [
pkgs.openssl
];
env = {
# this approach should be favored over LD_LIBRARY_PATH as it is more precise
RUSTFLAGS = "-C link-args=-Wl,-rpath,${lib.makeLibraryPath buildInputs}";
};
};
in
{
packages = {
default = self'.packages.berg;
# Build *just* the cargo dependencies, so we can reuse
# all of that work (e.g. via cachix) when running in CI
berg-deps = craneLib.buildDepsOnly commonArgs;
# Build the actual crate itself, reusing the dependency
# artifacts from above.
berg = craneLib.buildPackage (
commonArgs
// {
cargoArtifacts = self'.packages.berg-deps;
nativeBuildInputs = commonArgs.nativeBuildInputs ++ [
pkgs.installShellFiles # includes installShellCompletion
];
# allow for auto completion
postInstall = lib.optionalString (pkgs.stdenv.buildPlatform.canExecute pkgs.stdenv.hostPlatform) ''
installShellCompletion --cmd berg \
--bash <($out/bin/berg completion bash) \
--fish <($out/bin/berg completion fish) \
--zsh <($out/bin/berg completion zsh)
'';
meta = {
description = "CLI Tool for Codeberg similar to gh and glab";
homepage = "https://codeberg.org/Aviac/codeberg-cli";
license = [ lib.licenses.agpl3Plus ];
maintainers = [ lib.maintainers.robwalt ];
mainProgram = "berg";
};
}
);
};
checks = {
# Build the crate as part of `nix flake check` for convenience
berg = self'.packages.berg;
# Run clippy (and deny all warnings) on the crate source,
# again, reusing the dependency artifacts from above.
#
# Note that this is done as a separate derivation so that
# we can block the CI if there are issues here, but not
# prevent downstream consumers from building our crate by itself.
berg-clippy = craneLibFull.cargoClippy (
commonArgs
// {
cargoArtifacts = self'.packages.berg-deps;
cargoClippyExtraArgs = "--all-targets -- --deny warnings";
}
);
berg-doc = craneLibFull.cargoDoc (
commonArgs
// {
cargoArtifacts = self'.packages.berg-deps;
# This can be commented out or tweaked as necessary, e.g. set to
# `--deny rustdoc::broken-intra-doc-links` to only enforce that lint
env.RUSTDOCFLAGS = "--deny warnings";
}
);
# Check formatting
berg-fmt = craneLibFull.cargoFmt {
inherit src;
};
berg-toml-fmt =
let
taploConfigToml = pkgs.writeTextFile {
name = "config.toml";
text = ''
[formatting]
align_entries = true # Align entries vertically. Entries that have table headers, comments, or blank lines between them are not aligned.
reorder_keys = true # Alphabetically reorder keys that are not separated by blank lines.
reorder_arrays = true # Alphabetically reorder array values that are not separated by blank lines.
reorder_inline_tables = true # Alphabetically reorder inline tables.
'';
};
in
craneLibFull.taploFmt {
src = pkgs.lib.sources.sourceFilesBySuffices src [ ".toml" ];
# taplo arguments can be further customized below as needed
taploExtraArgs = "--config ${taploConfigToml}";
};
# Audit dependencies
berg-audit = craneLibFull.cargoAudit {
inherit (inputs) advisory-db;
inherit src;
};
# Audit licenses
berg-deny =
let
cargoDenyConfig = pkgs.writeTextFile {
name = "cargo-deny.toml";
text = ''
# .cargo-deny.toml
[licenses]
# Require high confidence in license detection
confidence-threshold = 0.8
# Explicitly list allowed SPDX licenses
allow = [
"AGPL-3.0-or-later",
"MIT",
"Apache-2.0",
"BSD-3-Clause",
"MPL-2.0",
"Unicode-3.0",
"CDLA-Permissive-2.0",
"ISC"
]
[bans]
# Warn about multiple versions of the same crate
multiple-versions = "warn"
skip = []
[sources]
# Forbid unknown git sources (optional for security)
allow-git = []
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
'';
};
in
craneLibFull.cargoDeny {
inherit src;
cargoDenyChecks = "-c ${cargoDenyConfig} bans licenses sources";
};
# Run tests with cargo-nextest
# Consider setting `doCheck = false` on `berg` if you do not want
# the tests to run twice
berg-nextest = craneLibFull.cargoNextest (
commonArgs
// {
cargoArtifacts = self'.packages.berg-deps;
partitions = 1;
partitionType = "count";
cargoNextestPartitionsExtraArgs = "--no-tests=pass";
}
);
};
};
}