Files
flake-hub/flake.nix
T
Oleks 0fd4cfe83d
ci/woodpecker/push/amd64 Pipeline failed
ci/woodpecker/push/arm64 Pipeline failed
style: auto-format from pre-push hooks
2026-06-02 09:22:45 +03:00

416 lines
15 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
description = "oleks's personal Flake hub a place to publish custom packages and overlays";
inputs = {
fleet-pins.url = "git+https://git.oleks.space/oleks/fleet-pins?ref=main";
nixpkgs.follows = "fleet-pins/nixpkgs-projects";
flake-utils.url = "github:numtide/flake-utils";
# Hyprspace source; no flake.nix in the repo so we consume it as raw src.
# Pin tracks the last v0.52-compatible commit of Hyprspace.
hyprspace = {
url = "github:KZDKM/Hyprspace/0467be86b18cfc324fab04afbd40fe9ef80f7fa9";
flake = false;
};
# Google Antigravity packaging. Upstream auto-updates daily; we re-expose
# the overlay and build into our attic cache so emmett pulls from there.
antigravity-nix = {
url = "github:jacopone/antigravity-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
# nix-deps: "see the real cost of installing packages on NixOS".
# Re-exposed through our overlay so CI builds it into attic.
nix-deps = {
url = "github:manelinux/nix-deps";
inputs.nixpkgs.follows = "nixpkgs";
};
# stalewood — find/reap merged git worktrees. Ships its own flake;
# re-expose its package (mirrors the nix-deps pattern).
stalewood = {
url = "github:retif/stalewood";
inputs.nixpkgs.follows = "nixpkgs";
};
# woodpecker-peek — tray app for Woodpecker CI (on git.oleks.space).
# Re-exposed so flake-hub CI warms attic and emmett pulls cached.
woodpecker-peek = {
url = "git+https://git.oleks.space/oleks/woodpecker-peek?ref=main";
inputs.nixpkgs.follows = "nixpkgs";
};
# mcp-chrome — Chrome MCP server + extension (English-localized fork of
# hangwin/mcp-chrome). Re-exposes the from-source wasm-simd worker (proven
# green, ~22 s) and the full chrome-mcp-extension build. The extension
# target is KNOWN-BROKEN under nix-daemon at this pin (see oleks/mcp-chrome
# issue #1 close comment); expect attic to miss it until that's resolved.
mcp-chrome = {
url = "git+https://git.oleks.space/oleks/mcp-chrome?ref=main";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
self,
nixpkgs,
fleet-pins,
flake-utils,
hyprspace,
antigravity-nix,
nix-deps,
stalewood,
woodpecker-peek,
mcp-chrome,
...
}:
let
# Systems that have native builders
buildSystems = [
"x86_64-linux"
"aarch64-linux"
];
# Cross-compilation targets from x86_64-linux
crossTargets = {
"s390x-linux" = "s390x-linux";
};
mkPackages =
pkgs:
let
sys = pkgs.stdenv.hostPlatform.system;
# Antigravity ships a Google-provided x86_64/aarch64 Linux binary.
# Skip it for cross targets (e.g. s390x) where it can't run anyway.
supportsAntigravity = sys == "x86_64-linux" || sys == "aarch64-linux";
xontribs = import ./packages/xontribs.nix {
inherit (pkgs) python3Packages fetchurl;
};
in
{
hello-world = pkgs.callPackage ./packages/hello-world.nix { };
geesefs = pkgs.callPackage ./packages/geesefs.nix { };
metamcp = pkgs.callPackage ./packages/metamcp.nix { };
xonsh = pkgs.callPackage ./packages/xonsh.nix {
xonsh-unwrapped = import ./packages/xonsh-unwrapped.nix {
inherit (pkgs) lib python3Packages fetchFromGitHub;
};
};
}
# Native-only packages — skip on s390x cross (gitea's pnpm step and
# cgo+sqlite link don't cross-compile cleanly).
// nixpkgs.lib.optionalAttrs (sys == "x86_64-linux" || sys == "aarch64-linux") {
gitea-local-fork =
let
# Our fork's go.mod requires Go 1.26.3; nixpkgs at this pin has
# only 1.26.0 (and unstable has 1.26.2). Bump the package's src.
go = pkgs.go_1_26.overrideAttrs (_: rec {
version = "1.26.3";
src = pkgs.fetchurl {
url = "https://go.dev/dl/go${version}.src.tar.gz";
hash = "sha256-HGRoddCqh5kTMYTtV895/yS97+jIggRwYCqdPW2Rkrg=";
};
});
in
pkgs.callPackage ./packages/gitea-local-fork.nix {
buildGoModule = pkgs.buildGoModule.override { inherit go; };
};
}
# Xontribs: pass into `programs.xonsh.extraPackages` or
# `pkgs.xonsh.override { extraPackages = ps: [...]; }`.
// xontribs
# Antigravity: re-expose jacopone/antigravity-nix's outputs so emmett
# consumes a single flake-hub input and our CI builds into attic.
// nixpkgs.lib.optionalAttrs supportsAntigravity {
inherit (antigravity-nix.packages.${sys})
google-antigravity
google-antigravity-no-fhs
;
# nix-deps' flake only outputs eachDefaultSystem (no s390x), so
# gate it on the same native x86_64/aarch64 condition.
nix-deps = nix-deps.packages.${sys}.default;
# stalewood — re-exposed from its own flake. No s390x output,
# so it rides the same native-only gate.
stalewood = stalewood.packages.${sys}.default;
# woodpecker-peek — same pattern; consumers (emmett) read the
# attic-cached binary via flake-hub's overlay, then set
# services.woodpecker-peek.package = pkgs.woodpecker-peek;.
woodpecker-peek = woodpecker-peek.packages.${sys}.default;
# mcp-chrome — Rust→wasm worker (proven green) plus the full
# chrome-mcp-extension build. The latter is KNOWN-BROKEN under
# nix-daemon at this pin; flake-hub CI will miss the cache on it
# until upstream resolves that. wasm-simd alone is what consumers
# actually pull cached today (commits 9534234, b276465 in
# oleks/mcp-chrome sync the built wasm back into the tree).
mcp-chrome-wasm-simd = mcp-chrome.packages.${sys}.wasm-simd;
mcp-chrome-extension = mcp-chrome.packages.${sys}.chrome-mcp-extension;
};
# Overlay providing Hyprspace. Requires `pkgs.hyprland` to be present
# (consumer applies the Hyprland flake's overlay first). Kept out of
# `mkPackages` because standalone `nix build .#hyprspace` has no
# Hyprland in scope.
hyprspaceOverlay = final: _prev: {
hyprspace = final.callPackage ./packages/hyprspace.nix {
src = hyprspace;
};
};
# Overlays needed for s390x cross-compilation of attic-client
s390xOverlays = [
# OpenSSL s390x assembly uses z10 instructions (cijne) that the
# nix-bootstrapped assembler doesn't recognize
(final: prev: {
openssl = prev.openssl.overrideAttrs (old: {
configureFlags = (old.configureFlags or [ ]) ++ [ "no-asm" ];
});
})
# musl doesn't support s390x long double (IBM double-double format:
# LDBL_MANT_DIG=106, sizeof=16). Make musl appear unavailable so
# busybox-sandbox-shell uses glibc static instead.
(final: prev: {
busybox-sandbox-shell = prev.busybox-sandbox-shell.override {
musl = prev.musl // {
meta = prev.musl.meta // {
platforms = [ ];
};
};
};
})
# libarchive tests fail in k8s pod sandboxes
(final: prev: {
libarchive = prev.libarchive.overrideAttrs (_: {
doCheck = false;
});
})
# nix 2.28 is a direct dependency of attic-client — disable tests
# and fix missing RPATH for boost/zstd/libarchive
(final: prev: {
nixVersions = prev.nixVersions // {
nix_2_28 = prev.nixVersions.nix_2_28.overrideAttrs (old: {
doCheck = false;
doInstallCheck = false;
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ final.patchelf ];
postFixup = (old.postFixup or "") + ''
for rpath in ${final.boost}/lib ${final.zstd.out}/lib ${final.libarchive.out}/lib; do
patchelf --add-rpath "$rpath" $out/bin/nix
for lib in $out/lib/lib*.so; do
[ -f "$lib" ] && patchelf --add-rpath "$rpath" "$lib"
done
done
'';
});
};
})
# LLVM test failures in CI pod environment — override libllvm
# (not llvm) so it propagates through rustc bootstrap chain
(final: prev: {
llvmPackages = prev.llvmPackages // {
libllvm = prev.llvmPackages.libllvm.overrideAttrs (old: {
doCheck = false;
doInstallCheck = false;
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ prev.gitMinimal ];
});
};
})
# Rustc bootstrap: symlink_file panics with "File exists" during
# s390x cross-compilation. Multiple call sites use t!(symlink_file(...)).
# Patch the symlink_file method body to remove existing dest first.
(
final: prev:
let
patchedRustcUnwrapped = prev.rustc-unwrapped.overrideAttrs (old: {
patches = (old.patches or [ ]) ++ [
./patches/rustc-symlink-file-eexist.patch
];
});
in
{
rustc-unwrapped = patchedRustcUnwrapped;
rustc = prev.rustc.override {
rustc-unwrapped = patchedRustcUnwrapped;
};
}
)
];
# Native builds
native = flake-utils.lib.eachSystem buildSystems (
system:
let
pkgs = import nixpkgs { inherit system; };
packages = mkPackages pkgs;
in
{
packages = packages // {
default = packages.hello-world;
};
devShells.default = pkgs.mkShell {
name = "oleks-hub-shell";
buildInputs = [ self.packages.${system}.default ];
nativeBuildInputs = with pkgs; [
nix
fmt
];
shellHook = ''
echo "Welcome to the oleks Flake hub development shell."
'';
};
}
);
# Cross-compiled builds (built from x86_64-linux)
cross = builtins.listToAttrs (
builtins.map (
target:
let
targetOverlays =
{
"s390x-linux" = s390xOverlays;
}
.${target} or [ ];
pkgs = import nixpkgs {
system = "x86_64-linux";
crossSystem.config =
nixpkgs.lib.systems.examples.${
{
"s390x-linux" = "s390x";
}
.${target}
}.config;
overlays = targetOverlays;
};
packages = mkPackages pkgs;
crossOnlyPackages =
{
"s390x-linux" = {
inherit (pkgs)
attic-client
rustc
cargo
rustfmt
sccache
mold
;
nix = pkgs.nixVersions.nix_2_28;
};
}
.${target} or { };
in
{
name = target;
value =
packages
// crossOnlyPackages
// {
default = packages.hello-world;
};
}
) (builtins.attrNames crossTargets)
);
in
native
// {
packages = (native.packages or { }) // cross;
overlays = {
default = final: _prev: mkPackages final;
gcc15-fixes = import ./overlays/gcc15-fixes.nix;
hyprspace = hyprspaceOverlay;
};
# `nix run .#<app>` — local-parity entrypoints (emmett#44, cluster#192,
# attic-closure archetype). parity-lib has NO attic builder, so this is a
# thin wrap of ci/publish.py (the woodpecker-peek pattern), NOT a parity
# builder conversion. The app IS the shared code: .woodpecker/amd64.yaml
# runs the exact same `ci/publish.py x86_64-linux`, so CI and a local run
# cannot drift.
#
# TWO HALVES (emmett#44): STAGE `nix build`s every package in the arch's
# list into the local /nix store (cluster-independent, runs on emmett);
# PUBLISH additionally `attic push`es each closure to the cache that lives
# next to the cluster. Local runs DRY-RUN (stage + show the pushes) unless
# `--push`/PUBLISH=1.
#
# nix run .#stage-amd64 stage x86_64-linux closures, no publish
# nix run .#publish-amd64 same, then push if `--push` given
# nix run .#publish-amd64 -- --push actually push to attic
# nix run .#publish all locally-buildable arches (amd64)
#
# arm64 BLOCKER: aarch64-linux cannot be built on emmett (linux/amd64) and
# there is no cross path for these native packages, so the arm64 leg MUST
# run on an aarch64 node (.woodpecker/arm64.yaml). It is intentionally
# absent from the apps below.
apps = nixpkgs.lib.genAttrs buildSystems (
system:
let
pkgs = import nixpkgs { inherit system; };
mkApp =
{
name,
arch,
defaultPush ? false,
}:
let
prog = pkgs.writeShellApplication {
inherit name;
runtimeInputs = [
pkgs.python3
pkgs.git
pkgs.nix
];
text = ''
${pkgs.lib.optionalString defaultPush "export PUBLISH=\"\${PUBLISH:-1}\""}
exec python3 ci/publish.py ${arch} "$@"
'';
};
in
{
type = "app";
program = "${prog}/bin/${name}";
meta.description =
"flake-hub ${arch} stage closures then attic push " + "(dry-run unless --push/PUBLISH=1)";
};
in
{
# x86_64-linux: native on emmett.
stage-amd64 = mkApp {
name = "stage-amd64";
arch = "x86_64-linux";
};
publish-amd64 = mkApp {
name = "publish-amd64";
arch = "x86_64-linux";
};
# `publish` = every locally-buildable arch + the arm64 blocker note.
# On emmett that is amd64 only; arm64 is node-bound (see comment above).
publish = {
type = "app";
program =
let
p = pkgs.writeShellApplication {
name = "publish";
runtimeInputs = [
pkgs.python3
pkgs.git
pkgs.nix
];
text = ''
echo "publish: amd64 is the only emmett-buildable arch; arm64 is"
echo " node-bound (run on an aarch64 node via"
echo " .woodpecker/arm64.yaml)."
exec python3 ci/publish.py x86_64-linux "$@"
'';
};
in
"${p}/bin/publish";
meta.description = "flake-hub publish all locally-buildable arches (amd64; arm64 node-bound)";
};
}
);
};
}