From 36b2a582f3920eea3c44a1e23766f3f0bdeadbbc Mon Sep 17 00:00:00 2001
From: Tom Prince <tom.prince@private.storage>
Date: Tue, 14 Sep 2021 15:28:24 -0600
Subject: [PATCH] Add script to update nixpkgs pin.

---
 docs/source/dev/README.rst | 18 +++++++++++
 tools/update-nixpkgs       | 66 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 84 insertions(+)
 create mode 100755 tools/update-nixpkgs

diff --git a/docs/source/dev/README.rst b/docs/source/dev/README.rst
index 3722ebd0..f72c5f6a 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 --command 'tools/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/tools/update-nixpkgs b/tools/update-nixpkgs
new file mode 100755
index 00000000..09c823b0
--- /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()
-- 
GitLab