diff --git a/docs/source/dev/README.rst b/docs/source/dev/README.rst index 3722ebd03b10bacaf459820d1f59bc7ccb07396b..14d2de31f932a0aa50545643e30c679c36696e19 100644 --- a/docs/source/dev/README.rst +++ b/docs/source/dev/README.rst @@ -39,6 +39,24 @@ Inside that is bin/nixos-test-driver which gives you a kind of REPL for interact The kind of `Python in this testScript <https://whetstone.privatestorage.io/privatestorage/PrivateStorageio/-/blob/78881a3/nixos/modules/tests/private-storage.nix#L180>`_ is what you can enter into this REPL. Consult the `official documentation on NixOS Tests <https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests>`_ for more information. +Updatings Pins +-------------- + +Nixpkgs +``````` + +To update the version of NixOS we deploy with, run: + +.. code: shell + + nix-shell --run 'update-nixpkgs' + +That will update ``nixpkgs-2015.json`` to the latest release on the nixos-21.05 channel. + +To update the channel, the script will need to be updated, +along with the filenames that have the channel in them. + + Architecture overview --------------------- diff --git a/nixpkgs-2105.json b/nixpkgs-2105.json index 76950db1870cb62d68e655f5ca4be90f3fcbf6be..f79aa88bc0bb97b26c4668ac1d2c4efcdb25b9fb 100644 --- a/nixpkgs-2105.json +++ b/nixpkgs-2105.json @@ -1,4 +1,5 @@ -{ "name": "release2105" -, "url": "https://releases.nixos.org/nixos/21.05/nixos-21.05.804.5de44c15758/nixexprs.tar.xz" -, "sha256": "002zvc16hyrbs0icx1qj255c9dqjpdxx4bhhfjndlj3kwn40by0m" +{ + "name": "release2105", + "url": "https://releases.nixos.org/nixos/21.05/nixos-21.05.3065.b3083bc6933/nixexprs.tar.xz", + "sha256": "186vni8rij8bhd6n5n9h55jf2x78v9zdy2gn9v4cpjhajp4pvzm0" } diff --git a/shell.nix b/shell.nix index fe76c1e7878628cff2a5a1fcdd8d027b2c817a7a..a5741377eec5ebd4b8862a0ea47e15edfdac2731 100644 --- a/shell.nix +++ b/shell.nix @@ -1,7 +1,10 @@ let release2105 = import ./nixpkgs-2105.nix { }; in -{ pkgs ? release2105 }: +{ pkgs ? release2105, lib ? pkgs.lib, python ? pkgs.python3 }: +let + tools = pkgs.callPackage ./tools {}; +in pkgs.mkShell { # When a path (such as `pkgs.path`) is interpolated into a string then nix # first adds that path to the store, and then interpolates the store path @@ -15,7 +18,10 @@ pkgs.mkShell { shellHook = '' export NIX_PATH="nixpkgs=${builtins.toString pkgs.path}"; ''; + # Run the shellHook from tools + inputsFrom = [tools]; buildInputs = [ + tools pkgs.morph pkgs.jp ]; diff --git a/tools/default.nix b/tools/default.nix new file mode 100644 index 0000000000000000000000000000000000000000..f9a0b1ff8d902f3072886939ad11e1e223ffbb7e --- /dev/null +++ b/tools/default.nix @@ -0,0 +1,49 @@ +{ pkgs, lib, makeWrapper, ... }: +let + python = pkgs.python3; + # This is a python envionment that has the dependencies + # for the development python scripts we use, and the + # helper library. + python-env = python.buildEnv.override { + extraLibs = [ python.pkgs.httpx ]; + # Add `.pth` file pointing at the directory containg our helper library. + # This will get added to `sys.path` by `site.py`. + # See https://docs.python.org/3/library/site.html + postBuild = '' + echo ${lib.escapeShellArg ./pylib} > $out/${lib.escapeShellArg python.sitePackages}/tools.pth + ''; + }; + python-commands = [ + ./update-nixpkgs + ]; +in + # This derivation creates a package that wraps our tools to setup an environment + # with there dependencies available. +pkgs.runCommand "ps_tools" { + nativeBuildInputs = [ makeWrapper ]; + shellHook = '' + # Only display the help if we are running an interactive shell. + if [[ $- == *i* ]]; then + cat <<MOTD + Tools (pass --help for details): + ${lib.concatStringsSep "\n" (map (path: + "- ${baseNameOf path}" + ) python-commands)} + MOTD + fi + ''; + } '' + mkdir -p $out/bin + ${lib.concatStringsSep "\n" (map (path: + let + baseName = baseNameOf path; + # We use toString so that we wrap the in-tree scripts, rather than copying + # them to the nix-store. This means that we don't need to run nix-shell again + # to pick up changes. + sourcePath = toString path; + in + # makeWrapper <executable> <wrapperfile> <args> + # See https://nixos.org/manual/nixpkgs/stable/#fun-makeWrapper + "makeWrapper ${python-env}/bin/python $out/bin/${baseName} --add-flags ${sourcePath}" + ) python-commands)} + '' diff --git a/tools/pylib/README.rst b/tools/pylib/README.rst new file mode 100644 index 0000000000000000000000000000000000000000..083f6620d93ac30303b805cb4098e93804323aef --- /dev/null +++ b/tools/pylib/README.rst @@ -0,0 +1,2 @@ +This directory contains a python package of helper functions used by the scripts in ``tools/``. +To get this on the python path, run ``nix-shell`` in the root of the repository. diff --git a/tools/pylib/ps_tools/__init__.py b/tools/pylib/ps_tools/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..278ef0f1a765a39f5e8a46adf99621b6b238dc5e --- /dev/null +++ b/tools/pylib/ps_tools/__init__.py @@ -0,0 +1,35 @@ +""" +Helpers for development and CI scripts. +""" +from __future__ import annotations + +import subprocess + + +def get_url_hash(hash_type, name, url) -> dict[str, str]: + """ + Get the nix hash of the given URL. + + :returns: Dictionary of arguments suitable to pass to :nix:`pkgs.fetchzip` + or a function derived from it (such as :nix:`pkgs.fetchFromGitLab`) + to specify the hash. + """ + output = subprocess.run( + [ + "nix-prefetch-url", + "--type", + hash_type, + "--unpack", + "--name", + name, + url, + ], + capture_output=True, + check=True, + encoding="utf-8", + ) + + return { + "outputHashAlgo": hash_type, + "outputHash": output.stdout.strip(), + } diff --git a/tools/update-nixpkgs b/tools/update-nixpkgs new file mode 100755 index 0000000000000000000000000000000000000000..09c823b0a419b5937d4953337b94a26c4b502e32 --- /dev/null +++ b/tools/update-nixpkgs @@ -0,0 +1,66 @@ +#!/usr/bin/env python + +import argparse +import json +from pathlib import Path + +import httpx +from ps_tools import get_url_hash + +# We pass this to builtins.fetchTarball which only supports sha256 +HASH_TYPE = "sha256" + +DEFAULT_CHANNEL = "nixos-21.05" +CHANNEL_URL_TEMPLATE = "https://channels.nixos.org/{channel}/nixexprs.tar.xz" + + +def get_nixos_channel_url(*, channel): + """ + Get the URL for the current release of the given nixos channel. + + `https://channels.nixos.org/<channel>` redirects to the path on + `https://releases.nixos.org` that corresponds to the current release + of that channel. This captures that redirect, so we can pin against + the release. + """ + response = httpx.head( + CHANNEL_URL_TEMPLATE.format(channel=channel), allow_redirects=False + ) + response.raise_for_status() + assert response.is_redirect + return str(response.next_request.url) + + +def main(): + parser = argparse.ArgumentParser(description="Update a pinned nixos repository.") + parser.add_argument( + "repo_file", + metavar="repo-file", + nargs="?", + default=Path(__file__).parent.with_name("nixpkgs-2105.json"), + type=Path, + help="JSON file with pinned configuration.", + ) + parser.add_argument( + "--dry-run", + action="store_true", + ) + parser.set_defaults(channel=DEFAULT_CHANNEL) + args = parser.parse_args() + + repo_file = args.repo_file + config = json.loads(repo_file.read_text()) + + config["url"] = get_nixos_channel_url(channel=args.channel) + hash_data = get_url_hash(HASH_TYPE, name=config["name"], url=config["url"]) + config["sha256"] = hash_data["outputHash"] + + output = json.dumps(config, indent=2) + if args.dry_run: + print(output) + else: + repo_file.write_text(output) + + +if __name__ == "__main__": + main()