Skip to content

Instantly share code, notes, and snippets.

@yajo
Last active May 13, 2023 06:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yajo/3f935292a326ff22192b4b497a8b6d86 to your computer and use it in GitHub Desktop.
Save yajo/3f935292a326ff22192b4b497a8b6d86 to your computer and use it in GitHub Desktop.
Copier template with extensions

Copier template with extensions

This is just a sample template that includes a flake.nix file to help template designers know how to leverage Nix to provide a reproducible Copier build for their template consumers.

How to test it

Of course, the purpose is to show you how you can use Nix for this, so I expect you to have Nix installed on your system. Instructions here.

Now, check that the template cannot render with standard Copier:

➤ nix run github:copier-org/copier/v7.1.0 -- git+https://gist.github.com/3f935292a326ff22192b4b497a8b6d86.git ./result
No git tags found in template; using HEAD as ref
Copier could not load some Jinja extensions:
No module named 'jinja2_time'
Make sure to install these extensions alongside Copier itself.
See the docs at https://copier.readthedocs.io/en/latest/configuring/#jinja_extensions

However, you can render it with the Copier app packaged within the template, which includes the required extension:

➤ nix run git+https://gist.github.com/3f935292a326ff22192b4b497a8b6d86.git -- git+https://gist.github.com/3f935292a326ff22192b4b497a8b6d86.git ./result
No git tags found in template; using HEAD as ref

Copying from template version 0.0.0.post3.dev0+cb34a4b
    create  .
    create  now.txt

The above command could seem redundant because you're repeating the Gist URL twice. What's happening? You will understand it better now:

➤ nix run git+https://gist.github.com/3f935292a326ff22192b4b497a8b6d86.git -- --version
copier 7.1.0.dev20230407161614+nix.git.91f21c7

So 1st time you're telling Nix where's the flake it has to run. The 2nd time (after --), you're already running Copier, so you're telling Copier where's the template source and destination. It turns out both URLs are the same, but have different meaning.

Nix details

We're using flakes in this example, so your nix installation should have them enabled. Although flakes is an experimental feature, it is quite stable at the time of writing. If you don't have it enabled, make sure to add these flags to all commands:

nix --extra-experimental-features 'nix-command flakes' [the rest of commands]

The template requires Jinja2 Time extension. I picked this one because it is available in Nixpkgs. If you need to include an extension that isn't packaged for Nix, you'd have a slightly more complex use case because it involves packaging it. It's not very hard, once you understand Nix. Tools like poetry2nix or dream2nix can help you get landed fast by combining with Poetry.

You can use also buildPythonPackage from Nixpkgs. FWIW that's how the Jinja2-Time extension is packaged currently.

The flake.lock file is generated automatically by running nix flake lock, and ensures 100% build reproducibility.

# A simple Copier configuration file that requires an extension
_jinja_extensions:
- jinja2_time.TimeExtension
# Exclude all but now.txt
_exclude:
- '*'
- '!now.txt'
{
"nodes": {
"copier": {
"inputs": {
"devenv": "devenv",
"flake-compat": "flake-compat_2",
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_2",
"poetry2nix": "poetry2nix"
},
"locked": {
"lastModified": 1680884174,
"narHash": "sha256-ZSPBvj1vUCls5NM8uNBOzFM66IkHSax78eExegvk7sI=",
"owner": "copier-org",
"repo": "copier",
"rev": "91f21c738cfcef2b47f6e58a308e94f062e2c9ea",
"type": "github"
},
"original": {
"owner": "copier-org",
"ref": "v7.1.0",
"repo": "copier",
"type": "github"
}
},
"devenv": {
"inputs": {
"flake-compat": "flake-compat",
"nix": "nix",
"nixpkgs": "nixpkgs",
"pre-commit-hooks": "pre-commit-hooks"
},
"locked": {
"lastModified": 1671716968,
"narHash": "sha256-LThNtwAXH/0KVMgyTFBwl93ktuWpWTZhCh6NBlydBbQ=",
"owner": "cachix",
"repo": "devenv",
"rev": "ba6818f4c39fd95aebdb6dc441401f2b60484652",
"type": "github"
},
"original": {
"owner": "cachix",
"ref": "v0.5",
"repo": "devenv",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1668681692,
"narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "009399224d5e398d03b22badca40a37ac85412a1",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1668681692,
"narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "009399224d5e398d03b22badca40a37ac85412a1",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"locked": {
"lastModified": 1676283394,
"narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"copier",
"devenv",
"pre-commit-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1660459072,
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"lowdown-src": {
"flake": false,
"locked": {
"lastModified": 1633514407,
"narHash": "sha256-Dw32tiMjdK9t3ETl5fzGrutQTzh2rufgZV4A/BbxuD4=",
"owner": "kristapsdz",
"repo": "lowdown",
"rev": "d2c2b44ff6c27b936ec27358a2653caaef8f73b8",
"type": "github"
},
"original": {
"owner": "kristapsdz",
"repo": "lowdown",
"type": "github"
}
},
"nix": {
"inputs": {
"lowdown-src": "lowdown-src",
"nixpkgs": [
"copier",
"devenv",
"nixpkgs"
],
"nixpkgs-regression": "nixpkgs-regression"
},
"locked": {
"lastModified": 1671638174,
"narHash": "sha256-FeEmVix8l/HglWtRgeHOfjqEm2etvp+MLYd1C/raq3Y=",
"owner": "domenkozar",
"repo": "nix",
"rev": "51b770e985f9e1b84fb5e03a983ef1e19f18c3e9",
"type": "github"
},
"original": {
"owner": "domenkozar",
"ref": "relaxed-flakes",
"repo": "nix",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1671458120,
"narHash": "sha256-2+k/OONN4OF21TeoNjKB5sXVZv6Zvm/uEyQIW9OYCg8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e37ef84b478fa8da0ced96522adfd956fde9047a",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-regression": {
"locked": {
"lastModified": 1643052045,
"narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1671271954,
"narHash": "sha256-cSvu+bnvN08sOlTBWbBrKaBHQZq8mvk8bgpt0ZJ2Snc=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "d513b448cc2a6da2c8803e3c197c9fc7e67b19e3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-22.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1677000517,
"narHash": "sha256-MuXkSRYw/sa46V6mSKp/2lRY0AkhZawGUSxB2WImx7c=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "ffdae3d38630564a8578143a2e66353f3b44f291",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1676994812,
"narHash": "sha256-JXBIqJzzza1D30Dz6e5WBsVe6gWh9gMnifBjL5k70I0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "3a558d658f59ac4ed95edeae20409fc936bbcf47",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"poetry2nix": {
"inputs": {
"flake-utils": "flake-utils_3",
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1674917871,
"narHash": "sha256-0dLfkWyWWeKDZhupteyBNlastcEzrCmCTdFGtcj7F10=",
"owner": "nix-community",
"repo": "poetry2nix",
"rev": "860530598f2ab9a9a0e89dc79851d14b0aed3bf7",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "poetry2nix",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-compat": [
"copier",
"devenv",
"flake-compat"
],
"flake-utils": "flake-utils",
"gitignore": "gitignore",
"nixpkgs": [
"copier",
"devenv",
"nixpkgs"
],
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1671452357,
"narHash": "sha256-HqzXiQEegpRQ4VEl9pEPgHSIxhJrNJ27HfN1wOc7w2E=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "200790e9c77064c53eaf95805b013d96615ecc27",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"root": {
"inputs": {
"copier": "copier"
}
}
},
"root": "root",
"version": 7
}
{
description = "A template with a customized Copier package";
# Config copied from Copier's flake, as a workaround for
# https://github.com/NixOS/nix/issues/6771 until that's fixed.
# This will allow consumers to use binary caches and speed up builds.
nixConfig = {
extra-trusted-public-keys = [
"copier.cachix.org-1:sVkdQyyNXrgc53qXPCH9zuS91zpt5eBYcg7JQSmTBG4="
"devenv.cachix.org-1:w1cLUi8dv3hnoSPGAuibQv+f9TZLr6cv/Hm9XgU50cw="
];
extra-substituters = [
"https://copier.cachix.org"
"https://devenv.cachix.org"
];
};
inputs = {
copier.url = github:copier-org/copier/v7.1.0;
};
outputs = {
self,
copier,
}: let
# Get Copier package from the input.
copierPkg = copier.packages.x86_64-linux.default;
# Reuse the same Python interpreter as Copier to create a Python
# environment with both packages.
env = copierPkg.python.withPackages (ps: [
# I picked the time extension for this example because it is already
# available in Nixpkgs. Just to keep the example simpler.
ps.jinja2-time
# Since we're creating a new Python environment, we need to include
# Copier again.
copier.packages.x86_64-linux.default
]);
in {
# Allow running Copier from our custom environment with `nix run`.
apps.x86_64-linux.default = {
type = "app";
program = "${env}/bin/copier";
};
};
}
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>
This is your time: {% now 'local' %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment