flake.nix
Rama main · réplica de lectura del repositorio original.
{
description = "Development environment and pre-commit checks for the workbench apps";
inputs = {
nixpkgs.url = "nixpkgs/nixos-unstable";
# The Android SDK as a flake. Only the catbox-android package and
# the android devShell depend on it.
android-nixpkgs = {
url = "github:tadfisher/android-nixpkgs";
inputs.nixpkgs.follows = "nixpkgs";
};
pre-commit-hooks = {
url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
self,
nixpkgs,
android-nixpkgs,
pre-commit-hooks,
}:
let
goVersion = 27;
# Baked into both catbox binaries via -X main.version.
version = self.shortRev or self.dirtyShortRev or "dev";
# Baked via -X main.buildTime: the commit's unix timestamp.
buildTime = toString (self.lastModified or 0);
supportedSystems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
forEachSupportedSystem =
f:
nixpkgs.lib.genAttrs supportedSystems (
system:
f {
pkgs = import nixpkgs {
inherit system;
overlays = [ self.overlays.default ];
config.allowUnfree = true;
};
}
);
goApps = [
"catbox"
"go-healthcheck"
"grafana-dashboards"
"lastfm-scrobble-deduplicator"
"rangemusique"
];
# Per-app hooks mirroring the pre-commit setups of the original repos
# (gofmt, golangci-lint, govet). Each app is its own Go module, so the
# tools run from the app directory. Staticcheck checks are enforced via
# golangci-lint, which enables the staticcheck linter in .golangci.yaml.
# Entries are absolute store paths so the hooks also work when invoked
# from environments without the dev shell on PATH (e.g. VS Code git).
goAppHooks =
pkgs: app:
let
runInApp = pkgs.writeShellScript "precommit-${app}" ''
export PATH="${pkgs.go}/bin:${pkgs.golangci-lint}/bin:$PATH"
cd workbench/${app}
exec "$@"
'';
in
{
"${app}-golangci-lint" = {
enable = true;
entry = "${runInApp} golangci-lint run";
files = "^workbench/${app}/";
pass_filenames = false;
extraPackages = with pkgs; [
go
golangci-lint
];
};
"${app}-govet" = {
enable = true;
entry = "${runInApp} go vet ./...";
files = "^workbench/${app}/";
pass_filenames = false;
extraPackages = [ pkgs.go ];
};
};
hooks =
pkgs:
{
# Secret detection, replacing the previous .pre-commit-config.yaml.
# Absolute store path so the hook also works outside the dev shell.
gitleaks = {
enable = true;
entry = "${pkgs.gitleaks}/bin/gitleaks protect --staged --redact --verbose";
pass_filenames = false;
extraPackages = [ pkgs.gitleaks ];
};
gofmt = {
enable = true;
files = "^workbench/.*\\.go$";
};
}
// nixpkgs.lib.foldl' (acc: app: acc // goAppHooks pkgs app) { } goApps;
# The .worktrees directory holds full repo copies that would otherwise
# be linted and shadow the real sources in the check build.
src = nixpkgs.lib.cleanSourceWith {
src = ./.;
filter =
path: type:
!(
type == "directory"
&& builtins.elem (baseNameOf path) [
".git"
".worktrees"
]
);
};
in
{
overlays.default = final: prev: {
go = final."go_1_${toString goVersion}";
};
devShells = forEachSupportedSystem (
{ pkgs }:
{
default = pkgs.mkShell {
inherit (self.checks.${pkgs.stdenv.hostPlatform.system}.pre-commit-check) shellHook;
packages = with pkgs; [
gitleaks
go
gotools
golangci-lint
hugo
uv
vault
]
++ self.checks.${pkgs.stdenv.hostPlatform.system}.pre-commit-check.enabledPackages;
};
}
// (
# The Android app shell: nix develop .#android. The SDK
# matches android/app/build.gradle.kts (compileSdk 37,
# build-tools 36.0.0, AGP 9.4.1, JDK 17) — bump them
# together. Hosts without an android-nixpkgs SDK composition
# (aarch64-linux) don't get the shell.
let
system = pkgs.stdenv.hostPlatform.system;
androidSystems = [
"x86_64-linux"
"aarch64-darwin"
];
in
nixpkgs.lib.optionalAttrs (builtins.elem system androidSystems) {
android =
let
sdk = android-nixpkgs.sdk.${system} (
sdkPkgs: with sdkPkgs; [
cmdline-tools-latest
platform-tools
build-tools-36-0-0
platforms-android-37-0
emulator
system-images-android-36-default-arm64-v8a
]
);
in
pkgs.mkShell rec {
packages = [
sdk
pkgs.jdk17
pkgs.gradle_9
pkgs.go
];
ANDROID_HOME = "${sdk}/share/android-sdk";
ANDROID_SDK_ROOT = "${sdk}/share/android-sdk";
# AGP downloads a prebuilt aapt2 from Maven that does not
# run on Nix (unpatched ELF); point it at the SDK's own.
GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${ANDROID_HOME}/build-tools/36.0.0/aapt2";
JAVA_HOME = pkgs.jdk17.home;
};
}
)
);
packages = forEachSupportedSystem (
{ pkgs }:
{
# The peer CLI for laptops: nix build github.com/cterence/homelab-gitops#catbox
catbox = pkgs.buildGo127Module {
pname = "catbox";
version = "unstable";
src = ./workbench/catbox;
vendorHash = "sha256-gATb9AZZjhcEwObWBSiTNc0Cl7C9npM90Oscr2sSOZs=";
ldflags = [
"-s"
"-w"
"-X main.version=${version}"
"-X main.buildTime=${buildTime}"
];
};
}
// (
# The Android APK, hermetically built from
# workbench/catbox/nix/android.nix. Only hosts with an
# android-nixpkgs SDK composition can build it.
let
system = pkgs.stdenv.hostPlatform.system;
androidSystems = [
"x86_64-linux"
"aarch64-darwin"
];
in
nixpkgs.lib.optionalAttrs (builtins.elem system androidSystems) (
let
catboxAndroid = import ./workbench/catbox/nix/android.nix {
inherit pkgs version buildTime;
android-sdk = android-nixpkgs.sdk.${system};
# A path literal, like the catbox package above: the
# git-filtered self.outPath would exclude untracked
# new files and break the cross-build.
src = ./workbench/catbox;
vendorHash = "sha256-gATb9AZZjhcEwObWBSiTNc0Cl7C9npM90Oscr2sSOZs=";
};
in
{
catbox-android = catboxAndroid.catbox-android;
catbox-android-bin = catboxAndroid.catbox-android-bin;
}
)
)
);
checks = forEachSupportedSystem (
{ pkgs }:
{
pre-commit-check = pre-commit-hooks.lib.${pkgs.stdenv.hostPlatform.system}.run {
inherit src;
# prek is the fast Rust reimplementation of pre-commit.
package = pkgs.prek;
hooks = hooks pkgs;
};
}
);
};
}