build(nix): add nix flake

This commit is contained in:
dusk 2024-12-21 04:12:58 +09:00 committed by alyssa
parent 2d564535af
commit be0c11d672
4 changed files with 581 additions and 16 deletions

6
.gitignore vendored
View file

@ -20,12 +20,18 @@ node_modules/
# User configuration # User configuration
.env .env
.envrc
pluralkit.conf pluralkit.conf
pluralkit.*.conf pluralkit.*.conf
*.DotSettings.user *.DotSettings.user
# Generated # Generated
.direnv
logs/ logs/
.version .version
recipe.json recipe.json
.docker-bin/ .docker-bin/
# nix
.nix-process-compose
result

329
flake.lock generated Normal file
View file

@ -0,0 +1,329 @@
{
"nodes": {
"crane": {
"flake": false,
"locked": {
"lastModified": 1727316705,
"narHash": "sha256-/mumx8AQ5xFuCJqxCIOFCHTVlxHkMT21idpbgbm/TIE=",
"owner": "ipetkov",
"repo": "crane",
"rev": "5b03654ce046b5167e7b0bccbd8244cb56c16f0e",
"type": "github"
},
"original": {
"owner": "ipetkov",
"ref": "v0.19.0",
"repo": "crane",
"type": "github"
}
},
"d2n": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"purescript-overlay": "purescript-overlay",
"pyproject-nix": "pyproject-nix"
},
"locked": {
"lastModified": 1734729217,
"narHash": "sha256-UaBik0h7veLw+VqsK5EP2ucC68BEkHLDJkcfmY+wEuY=",
"owner": "nix-community",
"repo": "dream2nix",
"rev": "98c1c2e934995a2c6ce740d4ff43ce0daa19b79f",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "dream2nix",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"locked": {
"lastModified": 1696426674,
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"revCount": 57,
"type": "tarball",
"url": "https://api.flakehub.com/f/pinned/edolstra/flake-compat/1.0.1/018afb31-abd1-7bff-a5e4-cff7e18efb7a/source.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz"
}
},
"mk-naked-shell": {
"flake": false,
"locked": {
"lastModified": 1681286841,
"narHash": "sha256-3XlJrwlR0nBiREnuogoa5i1b4+w/XPe0z8bbrJASw0g=",
"owner": "yusdacra",
"repo": "mk-naked-shell",
"rev": "7612f828dd6f22b7fb332cc69440e839d7ffe6bd",
"type": "github"
},
"original": {
"owner": "yusdacra",
"repo": "mk-naked-shell",
"type": "github"
}
},
"nci": {
"inputs": {
"crane": "crane",
"dream2nix": [
"d2n"
],
"mk-naked-shell": "mk-naked-shell",
"nixpkgs": [
"nixpkgs"
],
"parts": [
"parts"
],
"rust-overlay": "rust-overlay",
"treefmt": [
"treefmt"
]
},
"locked": {
"lastModified": 1734953472,
"narHash": "sha256-zWPAJFo7NNhSXbOc6YRAXbrWzcJGxNPtutKTTZz46Bs=",
"owner": "yusdacra",
"repo": "nix-cargo-integration",
"rev": "e71c873cf3b0dfa52e9550d580531e41eb4b4c6a",
"type": "github"
},
"original": {
"owner": "yusdacra",
"repo": "nix-cargo-integration",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1734435836,
"narHash": "sha256-kMBQ5PRiFLagltK0sH+08aiNt3zGERC2297iB6vrvlU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4989a246d7a390a859852baddb1013f825435cee",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixpkgs-unstable",
"type": "indirect"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1733096140,
"narHash": "sha256-1qRH7uAUsyQI7R1Uwl4T+XvdNv778H0Nb5njNrqvylY=",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/5487e69da40cbd611ab2cadee0b4637225f7cfae.tar.gz"
}
},
"parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1733312601,
"narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"process-compose": {
"locked": {
"lastModified": 1733325752,
"narHash": "sha256-79tzPuXNRo1NUllafYW6SjeLtjqfnLGq7tHCM7cAXNg=",
"owner": "Platonic-Systems",
"repo": "process-compose-flake",
"rev": "1012530b582f1bd3b102295c799358d95abf42d7",
"type": "github"
},
"original": {
"owner": "Platonic-Systems",
"repo": "process-compose-flake",
"type": "github"
}
},
"purescript-overlay": {
"inputs": {
"flake-compat": "flake-compat",
"nixpkgs": [
"d2n",
"nixpkgs"
],
"slimlock": "slimlock"
},
"locked": {
"lastModified": 1728546539,
"narHash": "sha256-Sws7w0tlnjD+Bjck1nv29NjC5DbL6nH5auL9Ex9Iz2A=",
"owner": "thomashoneyman",
"repo": "purescript-overlay",
"rev": "4ad4c15d07bd899d7346b331f377606631eb0ee4",
"type": "github"
},
"original": {
"owner": "thomashoneyman",
"repo": "purescript-overlay",
"type": "github"
}
},
"pyproject-nix": {
"flake": false,
"locked": {
"lastModified": 1702448246,
"narHash": "sha256-hFg5s/hoJFv7tDpiGvEvXP0UfFvFEDgTdyHIjDVHu1I=",
"owner": "davhau",
"repo": "pyproject.nix",
"rev": "5a06a2697b228c04dd2f35659b4b659ca74f7aeb",
"type": "github"
},
"original": {
"owner": "davhau",
"ref": "dream2nix",
"repo": "pyproject.nix",
"type": "github"
}
},
"root": {
"inputs": {
"d2n": "d2n",
"flake-compat": "flake-compat_2",
"nci": "nci",
"nixpkgs": "nixpkgs",
"parts": "parts",
"process-compose": "process-compose",
"services": "services",
"systems": "systems",
"treefmt": "treefmt"
}
},
"rust-overlay": {
"inputs": {
"nixpkgs": [
"nci",
"nixpkgs"
]
},
"locked": {
"lastModified": 1734834660,
"narHash": "sha256-bm8V+Cu8rWJA+vKQnc94mXTpSDgvedyoDKxTVi/uJfw=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "b070e6030118680977bc2388868c4b3963872134",
"type": "github"
},
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
"services": {
"locked": {
"lastModified": 1734242477,
"narHash": "sha256-u+fkdD8+0/0J8k0/YKDc3ReUcYZZGiftGL+Sz2wdRqM=",
"owner": "juspay",
"repo": "services-flake",
"rev": "acc7f3f9f30621b469ca3ee511592a68a4437312",
"type": "github"
},
"original": {
"owner": "juspay",
"repo": "services-flake",
"type": "github"
}
},
"slimlock": {
"inputs": {
"nixpkgs": [
"d2n",
"purescript-overlay",
"nixpkgs"
]
},
"locked": {
"lastModified": 1688756706,
"narHash": "sha256-xzkkMv3neJJJ89zo3o2ojp7nFeaZc2G0fYwNXNJRFlo=",
"owner": "thomashoneyman",
"repo": "slimlock",
"rev": "cf72723f59e2340d24881fd7bf61cb113b4c407c",
"type": "github"
},
"original": {
"owner": "thomashoneyman",
"repo": "slimlock",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1680978846,
"narHash": "sha256-Gtqg8b/v49BFDpDetjclCYXm8mAnTrUzR0JnE2nv5aw=",
"owner": "nix-systems",
"repo": "x86_64-linux",
"rev": "2ecfcac5e15790ba6ce360ceccddb15ad16d08a8",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "x86_64-linux",
"type": "github"
}
},
"treefmt": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1734704479,
"narHash": "sha256-MMi74+WckoyEWBRcg/oaGRvXC9BVVxDZNRMpL+72wBI=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "65712f5af67234dad91a5a4baee986a8b62dbf8f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

233
flake.nix Normal file
View file

@ -0,0 +1,233 @@
{
description = "flake for pluralkit";
inputs = {
nixpkgs.url = "nixpkgs/nixpkgs-unstable";
parts.url = "github:hercules-ci/flake-parts";
systems.url = "github:nix-systems/x86_64-linux";
# process compose
process-compose.url = "github:Platonic-Systems/process-compose-flake";
services.url = "github:juspay/services-flake";
# rust
d2n.url = "github:nix-community/dream2nix";
d2n.inputs.nixpkgs.follows = "nixpkgs";
nci.url = "github:yusdacra/nix-cargo-integration";
nci.inputs.parts.follows = "parts";
nci.inputs.nixpkgs.follows = "nixpkgs";
nci.inputs.dream2nix.follows = "d2n";
nci.inputs.treefmt.follows = "treefmt";
# misc
treefmt.url = "github:numtide/treefmt-nix";
treefmt.inputs.nixpkgs.follows = "nixpkgs";
flake-compat.url = "https://flakehub.com/f/edolstra/flake-compat/1.tar.gz";
};
outputs =
inp:
inp.parts.lib.mkFlake { inputs = inp; } {
systems = import inp.systems;
imports = [
inp.process-compose.flakeModule
inp.nci.flakeModule
inp.treefmt.flakeModule
];
perSystem =
{
config,
self',
pkgs,
lib,
system,
...
}:
let
# this is used as devshell for bot, and in the process-compose processes as environment
mkBotEnv =
cmd:
pkgs.buildFHSEnv {
name = "env";
targetPkgs =
pkgs: with pkgs; [
coreutils
git
dotnet-sdk_8
gcc
protobuf
omnisharp-roslyn
bashInteractive
];
runScript = cmd;
};
rustOutputs = config.nci.outputs;
composeCfg = config.process-compose."dev";
in
{
# _module.args.pkgs = import inp.nixpkgs {
# inherit system;
# config.permittedInsecurePackages = [ "dotnet-sdk-6.0.428" ];
# };
treefmt = {
projectRootFile = "flake.nix";
programs.nixfmt.enable = true;
};
nci.toolchainConfig = {
channel = "nightly";
};
nci.projects."pluralkit-services" = {
path = ./.;
export = false;
};
nci.crates."gateway" = {
depsDrvConfig.mkDerivation = {
nativeBuildInputs = [ pkgs.protobuf ];
};
drvConfig.mkDerivation = {
nativeBuildInputs = [ pkgs.protobuf ];
};
};
# TODO: expose other rust packages after it's verified they build and work properly
packages = lib.genAttrs ["gateway"] (name: rustOutputs.${name}.packages.release);
# TODO: package the bot itself (dotnet)
devShells = {
services = rustOutputs."pluralkit-services".devShell;
bot = (mkBotEnv "bash").env;
};
process-compose."dev" = let
dataDir = ".nix-process-compose";
pluralkitConfCheck = ''
[[ -f "pluralkit.conf" ]] || (echo "pluralkit config not found, please copy pluralkit.conf.example to pluralkit.conf and edit it" && exit 1)
'';
sourceDotenv = ''
[[ -f ".env" ]] && echo "sourcing .env file..." && export "$(xargs < .env)"
'';
in {
imports = [ inp.services.processComposeModules.default ];
settings.log_location = "${dataDir}/log";
settings.environment = {
DOTNET_CLI_TELEMETRY_OPTOUT = "1";
NODE_OPTIONS = "--openssl-legacy-provider";
};
services.redis."redis" = {
enable = true;
dataDir = "${dataDir}/redis";
};
services.postgres."postgres" = {
enable = true;
dataDir = "${dataDir}/postgres";
initialScript.before = ''
CREATE DATABASE pluralkit;
CREATE USER postgres WITH password 'postgres';
GRANT ALL PRIVILEGES ON DATABASE pluralkit TO postgres;
ALTER DATABASE pluralkit OWNER TO postgres;
'';
};
settings.processes =
let
procCfg = composeCfg.settings.processes;
mkServiceInitProcess =
{
name,
inputs ? [ ],
...
}:
let
shell = rustOutputs.${name}.devShell;
in
{
command = pkgs.writeShellApplication {
name = "pluralkit-${name}-init";
runtimeInputs =
(with pkgs; [
coreutils
shell.stdenv.cc
])
++ shell.nativeBuildInputs
++ inputs;
text = ''
${sourceDotenv}
set -x
${pluralkitConfCheck}
exec cargo build --package ${name}
'';
};
};
in
{
### bot ###
pluralkit-bot-init = {
command = pkgs.writeShellApplication {
name = "pluralkit-bot-init";
runtimeInputs = [
pkgs.coreutils
pkgs.git
];
text = ''
${sourceDotenv}
set -x
${pluralkitConfCheck}
exec ${mkBotEnv "dotnet build -c Release -o obj/"}/bin/env
'';
};
};
pluralkit-bot = {
command = pkgs.writeShellApplication {
name = "pluralkit-bot";
runtimeInputs = [ pkgs.coreutils ];
text = ''
${sourceDotenv}
set -x
exec ${mkBotEnv "dotnet obj/PluralKit.Bot.dll"}/bin/env
'';
};
depends_on.pluralkit-bot-init.condition = "process_completed_successfully";
depends_on.postgres.condition = "process_healthy";
depends_on.redis.condition = "process_healthy";
depends_on.pluralkit-gateway.condition = "process_healthy";
# TODO: add liveness check
ready_log_line = "Received Ready";
};
### gateway ###
pluralkit-gateway-init = mkServiceInitProcess {
name = "gateway";
};
pluralkit-gateway = {
command = pkgs.writeShellApplication {
name = "pluralkit-gateway";
runtimeInputs = with pkgs; [
coreutils
curl
gnugrep
];
text = ''
${sourceDotenv}
set -x
exec target/debug/gateway
'';
};
depends_on.postgres.condition = "process_healthy";
depends_on.redis.condition = "process_healthy";
depends_on.pluralkit-gateway-init.condition = "process_completed_successfully";
# configure health checks
# TODO: don't assume port?
liveness_probe.exec.command = ''curl -s -o /dev/null -w "%{http_code}" http://localhost:5000/stats | grep "302"'';
liveness_probe.period_seconds = 5;
readiness_probe.exec.command = procCfg.pluralkit-gateway.liveness_probe.exec.command;
readiness_probe.period_seconds = 5;
readiness_probe.initial_delay_seconds = 3;
};
# TODO: add the rest of the services
};
};
};
};
}

View file

@ -1,15 +1,12 @@
{ pkgs ? import <nixpkgs> {} }: (import (
let
pkgs.mkShellNoCC { lock = builtins.fromJSON (builtins.readFile ./flake.lock);
packages = with pkgs; [ nodeName = lock.nodes.root.inputs.flake-compat;
cargo rust-analyzer rustfmt in
gcc fetchTarball {
protobuf url =
dotnet-sdk_8 lock.nodes.${nodeName}.locked.url
omnisharp-roslyn or "https://github.com/edolstra/flake-compat/archive/${lock.nodes.${nodeName}.locked.rev}.tar.gz";
go sha256 = lock.nodes.${nodeName}.locked.narHash;
nodejs yarn
];
NODE_OPTIONS = "--openssl-legacy-provider";
} }
) { src = ./.; }).shellNix