-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathflake.nix
More file actions
316 lines (265 loc) · 12 KB
/
Copy pathflake.nix
File metadata and controls
316 lines (265 loc) · 12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
{
description = "k8s-cloud-tagger - Kubernetes resources tagged in your cloud provider";
# ============================================================================
# INPUTS
# External dependencies (like package.json or go.mod for Nix)
# ============================================================================
inputs = {
# Nix packages collection - provides pkgs.dockerTools, pkgs.cacert, etc.
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# Crane - best-in-class Nix library for building Rust projects
# Handles cargo workspace caching, incremental builds, etc.
# https://github.com/ipetkov/crane
crane.url = "github:ipetkov/crane";
# Fenix - provides Rust toolchains for Nix (like rustup, but Nix-native)
# https://github.com/nix-community/fenix
fenix = {
url = "github:nix-community/fenix";
inputs.nixpkgs.follows = "nixpkgs"; # Use our nixpkgs, not fenix's
};
# Utility for multi-system support (x86_64-linux, aarch64-darwin, etc.)
flake-utils.url = "github:numtide/flake-utils";
};
# ============================================================================
# OUTPUTS
# What this flake provides: checks, packages, devShells
# ============================================================================
outputs = { self, nixpkgs, crane, fenix, flake-utils, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
# ----------------------------------------------------------------------
# Rust Toolchains
# ----------------------------------------------------------------------
# Standard toolchain with dev tools (fmt, clippy)
# Used for: checks, development, default builds
toolchain = fenix.packages.${system}.stable.withComponents [
"cargo"
"clippy"
"rustc"
"rustfmt"
];
# Musl cross-compilation toolchain
# Used for: static binary builds (no glibc dependency)
# This produces binaries that run on minimal containers (scratch, chainguard/static)
toolchainMusl = with fenix.packages.${system}; combine [
stable.cargo
stable.rustc
targets.x86_64-unknown-linux-musl.stable.rust-std
];
# ----------------------------------------------------------------------
# Crane Build Library
# ----------------------------------------------------------------------
# Standard crane instance for checks and dev builds
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
# Musl-targeting crane instance for release builds
craneLibMusl = (crane.mkLib pkgs).overrideToolchain toolchainMusl;
# ----------------------------------------------------------------------
# Source Filtering
# ----------------------------------------------------------------------
# cleanCargoSource filters out non-Rust files (docs, CI configs, etc.)
# This improves caching - changes to README.md won't trigger rebuilds
src = craneLib.cleanCargoSource ./.;
# Shared arguments for all cargo invocations
commonArgs = {
inherit src;
strictDeps = true; # Prevents impure build dependencies
};
# ----------------------------------------------------------------------
# Build Artifacts
# ----------------------------------------------------------------------
# Pre-build dependencies only (cached separately from source changes)
# This is the key to fast incremental builds:
# - Change Cargo.toml/Cargo.lock -> rebuild deps + source
# - Change src/*.rs -> reuse cached deps, rebuild source only
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
# Cached deps for musl toolchain (used by static binary)
cargoArtifactsMusl = craneLibMusl.buildDepsOnly (commonArgs // {
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
CARGO_BUILD_RUSTFLAGS = "-C target-feature=+crt-static";
});
# Static musl binary for container images
# - No glibc dependency
# - Runs on scratch/distroless/chainguard-static bases
binaryMusl = craneLibMusl.buildPackage (commonArgs // {
cargoArtifacts = cargoArtifactsMusl;
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
CARGO_BUILD_RUSTFLAGS = "-C target-feature=+crt-static";
});
# ----------------------------------------------------------------------
# Chainguard Static Base Image (pinned)
# Update with: nix-prefetch-docker --image-name cgr.dev/chainguard/static --image-tag latest
# ----------------------------------------------------------------------
chainguardStatic = pkgs.dockerTools.pullImage {
imageName = "cgr.dev/chainguard/static";
imageDigest = "sha256:9cef3c6a78264cb7e25923bf1bf7f39476dccbcc993af9f4ffeb191b77a7951e";
hash = "sha256-0/N09XBMjLil6X9yQMczPi3NYEk31/g8Ghmm7TRXsdc=";
finalImageName = "cgr.dev/chainguard/static";
finalImageTag = "latest";
};
# Inline Dockerfile for Docker-based builds (used on Darwin / USE_DOCKER_BUILD)
# Uses cargo-chef to cache dependency builds across source changes
dockerfile = pkgs.writeText "Dockerfile" ''
FROM rust:bookworm AS chef
RUN cargo install cargo-chef
WORKDIR /app
FROM chef AS planner
COPY . .
RUN cargo chef prepare --recipe-path recipe.json
FROM chef AS builder
COPY --from=planner /app/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json
COPY . .
RUN cargo build --release
FROM debian:bookworm-slim
COPY --from=builder /app/target/release/k8s-cloud-tagger /
USER 65532:65532
ENTRYPOINT ["/k8s-cloud-tagger"]
'';
# ----------------------------------------------------------------------
# Common Dev Packages
# ----------------------------------------------------------------------
# Shared by all dev shells
commonDevPackages = with pkgs; [
nix
kind
kubectl
jq
kubernetes-helm # Helm CLI
nix-prefetch-docker # Provides nix-prefetch-docker
skopeo # Push images without Docker daemon
];
in
{
# ======================================================================
# CHECKS
# Run with: nix flake check
# These run in parallel and fail fast
# ======================================================================
checks = {
# cargo fmt --check
fmt = craneLib.cargoFmt { inherit src; };
# cargo clippy -- -D warnings
clippy = craneLib.cargoClippy (commonArgs // {
inherit cargoArtifacts; # Reuse cached deps
cargoClippyExtraArgs = "--all-targets -- -D warnings";
});
# cargo test
test = craneLib.cargoTest (commonArgs // {
inherit cargoArtifacts; # Reuse cached deps
});
};
# ======================================================================
# PACKAGES
# Build with: nix build .#<package-name>
# ======================================================================
packages = {
# Default package (dynamically linked, for local dev)
# Build with: nix build
default = craneLib.buildPackage (commonArgs // {
inherit cargoArtifacts;
});
# Static binary for containers
# Build with: nix build .#binary-static
binary-static = binaryMusl;
# OCI container image (tarball) based on Chainguard static
# Build with: nix build .#image-dev
# Push with: skopeo copy docker-archive:result docker://quay.io/...
image-dev = pkgs.dockerTools.buildImage {
name = "quay.io/upgrades/k8s-cloud-tagger-dev";
tag = "dev";
# Chainguard static base (provides CA certs, tzdata, nonroot user)
fromImage = chainguardStatic;
# Container configuration
config = {
Entrypoint = [ "${binaryMusl}/bin/k8s-cloud-tagger" ];
User = "65532:65532";
};
};
image = pkgs.dockerTools.buildImage {
name = "quay.io/upgrades/k8s-cloud-tagger";
tag = "latest";
fromImage = chainguardStatic;
config = {
Entrypoint = [ "${binaryMusl}/bin/k8s-cloud-tagger" ];
User = "65532:65532";
};
};
};
# ======================================================================
# APPS
# ======================================================================
apps.kind-test = {
type = "app";
program = toString (pkgs.writeShellScript "kind-test" ''
set -euo pipefail
export PATH="${pkgs.lib.makeBinPath (with pkgs; [ kind kubectl kubernetes-helm jq ])}:''$PATH"
export CHART_PATH="${./helm/k8s-cloud-tagger}"
export FIXTURES_PATH="${./tests/fixtures}"
if [ -z "''${IMAGE:-}" ]; then
export IMAGE="quay.io/upgrades/k8s-cloud-tagger-dev:dev"
# USE_DOCKER_BUILD=true: use Docker instead of Nix to build the image.
# On Mac this is necessary. On Linux, useful for debugging the container
# interactively (docker run, exec, etc.) but Nix is generally faster.
if [[ "$(uname)" == "Darwin" || -n "''${USE_DOCKER_BUILD:-}" ]]; then
echo "==> Building image via Docker..."
cat ${dockerfile} | docker build \
-t "$IMAGE" \
-f - .
export IMAGE_SOURCE=docker
else
echo "==> Building image via Nix..."
export IMAGE_ARCHIVE
IMAGE_ARCHIVE=$(nix build .#image-dev --no-link --print-out-paths)
export IMAGE_SOURCE=archive
fi
fi
exec ${./tests/e2e.sh} "$@"
'');
};
# ======================================================================
# DEV SHELLS
# ======================================================================
# Default dev shell for local development
# Enter with: nix develop
devShells.default = craneLib.devShell {
# Include all check inputs (gives you the same tools CI uses)
checks = self.checks.${system};
# Additional packages for development
packages = commonDevPackages;
# Message of the day
shellHook = ''
cat << 'EOF'
__ _____ ________ ___ ___ ________
/ / / / _ \/ ___/ _ \/ _ | / _ \/ __/ __/
/ /_/ / ___/ (_ / , _/ __ |/ // / _/_\ \
\____/_/ \___/_/|_/_/ |_/____/___/___/
EOF
echo "entering k8s-cloud-tagger dev shell..."
'';
};
# AWS dev shell for EKS testing
# Enter with: nix develop .#aws
devShells.aws = craneLib.devShell {
# Include all check inputs (same as default)
checks = self.checks.${system};
# Common packages + AWS-specific tools
packages = commonDevPackages ++ (with pkgs; [
awscli2
eksctl
]);
# Message of the day
shellHook = ''
cat << 'EOF'
__ _____ ________ ___ ___ ________
/ / / / _ \/ ___/ _ \/ _ | / _ \/ __/ __/
/ /_/ / ___/ (_ / , _/ __ |/ // / _/_\ \
\____/_/ \___/_/|_/_/ |_/____/___/___/
(AWS MODE)
EOF
echo "entering k8s-cloud-tagger dev shell (AWS mode)..."
echo "AWS tools available: aws, eksctl"
'';
};
});
}