diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml new file mode 100644 index 0000000..8e2134f --- /dev/null +++ b/.github/workflows/nix.yml @@ -0,0 +1,65 @@ +name: Nix + +on: + push: + branches: [main] + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +permissions: + contents: read + +jobs: + build: + if: github.event_name == 'push' || github.event.pull_request.draft == false + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest] + steps: + - uses: actions/checkout@v4 + + - uses: cachix/install-nix-action@v31 + + - name: Build + run: nix build --print-build-logs + + - name: Smoke test + run: | + ./result/bin/lc --version + ./result/bin/astra --version + ./result/bin/git-annex version + cd "$RUNNER_TEMP" + "$GITHUB_WORKSPACE/result/bin/lc" init demo + "$GITHUB_WORKSPACE/result/bin/lc" init demo --check + + version: + if: github.event_name == 'push' || github.event.pull_request.draft == false + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: cachix/install-nix-action@v31 + + - name: Set up uv + uses: astral-sh/setup-uv@v6 + + - name: Flake evaluates on every system + run: nix flake check --all-systems + + - name: lastRelease is the latest tag + run: | + expected=$(uvx --from setuptools-scm python -m setuptools_scm) + name=$(nix eval --raw .#packages.x86_64-linux.default.name) + actual=${name#lightcone-} + echo "hatch-vcs: $expected" + echo "nix: $actual" + if [ "${expected%%.dev*}" != "${actual%%.dev*}" ]; then + tag=$(git describe --tags --abbrev=0) + echo "::error file=flake.nix::set lastRelease = \"${tag#v}\";" + exit 1 + fi diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..bd3498c --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1790652569, + "narHash": "sha256-641r7xrlSOHYoktL9/aArPIYNgZJ9eM5URzSEOtPJDY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b6c8664de9b6cc07fe5666a29f91884ba81197c4", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..8677f6d --- /dev/null +++ b/flake.nix @@ -0,0 +1,125 @@ +{ + description = "Lightcone Research: lc and astra"; + + inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + + outputs = + { self, nixpkgs }: + let + inherit (nixpkgs) lib; + forAllSystems = lib.genAttrs [ + "x86_64-linux" + "aarch64-linux" + "aarch64-darwin" + ]; + lastRelease = "0.5.0rc5"; + nextVersion = + let + parts = builtins.match "(.*[^0-9])([0-9]+)" lastRelease; + in + "${builtins.elemAt parts 0}${toString (lib.toInt (builtins.elemAt parts 1) + 1)}"; + commit = if self ? rev then builtins.substring 0 9 self.rev else self.dirtyShortRev or "unknown"; + version = "${nextVersion}.dev0+g${commit}.nix"; + excludeNewer = + let + at = start: length: builtins.substring start length self.lastModifiedDate; + in + "${at 0 4}-${at 4 2}-${at 6 2}T${at 8 2}:${at 10 2}:${at 12 2}Z"; + in + { + packages = forAllSystems ( + system: + let + pkgs = nixpkgs.legacyPackages.${system}; + in + rec { + default = pkgs.callPackage ( + { + lib, + python3Packages, + runCommand, + makeWrapper, + uv, + git, + }: + let + wheel = python3Packages.buildPythonPackage { + pname = "lightcone-cli"; + inherit version; + pyproject = true; + src = ./.; + build-system = [ + python3Packages.hatchling + python3Packages.hatch-vcs + ]; + env.SETUPTOOLS_SCM_PRETEND_VERSION = version; + dontCheckRuntimeDeps = true; + }; + in + runCommand "lightcone-${version}" + { + nativeBuildInputs = [ makeWrapper ]; + passthru = { + inherit uv git; + dist = wheel.dist; + }; + meta.mainProgram = "lc"; + } + '' + mkdir -p $out/bin + ln -s ${uv}/bin/* ${git}/bin/* $out/bin/ + whl=$(echo ${wheel.dist}/*.whl) + for exe in lc astra git-annex git-annex-shell git-remote-annex git-remote-tor-annex; do + makeWrapper ${lib.getExe uv} $out/bin/$exe \ + --prefix PATH : $out/bin \ + --add-flags "tool run --quiet --managed-python --exclude-newer ${excludeNewer} --from $whl $exe" + done + '' + ) { }; + lc = default; + } + ); + + nixosModules.default = + { + config, + lib, + pkgs, + ... + }: + let + cfg = config.programs.lightcone; + in + { + options.programs.lightcone = { + enable = lib.mkEnableOption "the Lightcone Research tools (lc, astra)"; + package = lib.mkOption { + type = lib.types.package; + default = self.packages.${pkgs.stdenv.hostPlatform.system}.default; + defaultText = lib.literalExpression "lightcone.packages.\${system}.default"; + description = "The package providing lc, astra, git-annex, uv and git."; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + assertion = lib.versionAtLeast cfg.package.uv.version "0.12"; + message = "programs.lightcone needs uv 0.12 or later, got ${cfg.package.uv.version}."; + } + ]; + programs.nix-ld.enable = true; + programs.git = { + enable = true; + package = lib.mkDefault cfg.package.git; + }; + environment = { + systemPackages = [ cfg.package ]; + etc."uv/uv.toml".text = lib.mkDefault '' + python-preference = "only-managed" + ''; + }; + }; + }; + }; +}