Skip to content

Commit

Permalink
Merge pull request #1 from emacs-twist/update-api
Browse files Browse the repository at this point in the history
Update the configuration on API changes, add a template
  • Loading branch information
akirak authored Jul 19, 2024
2 parents 7bd5d06 + 3208536 commit 65ba273
Show file tree
Hide file tree
Showing 9 changed files with 250 additions and 23 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/check-template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Check template
on:
push:
paths:
- template/**
workflow_dispatch:
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: cachix/install-nix-action@V27
- name: Install just
run: nix profile install nixpkgs#just
- name: Lint justfile
working-directory: template
run: just -l
48 changes: 38 additions & 10 deletions README.org
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
* Meta Nix Flake for Developing Emacs Lisp Projects
* Nix Meta-Flake for Developing Emacs Lisp Projects
This is a Nix flake that lets you configure checking of Emacs Lisp packages (both locally and on CI).

There are [[#alternatives][several alternatives]] for Emacs Lisp CI, but this project is unique in that it is powered by Nix and provides the following most notable features:
Expand Down Expand Up @@ -63,17 +63,20 @@ You have to add ~flake.nix~ to your individual projects.
While it is possible to use its flake API only with ~nix~ command, the commands are quite verbose and hence your developer experience would be painful.
On your machine, it is recommended to use [[https://just.systems/man/en/][just]] (which is like a modern Make for running commands) for the development workflow.

I have created [[https://github.com/akirak/flake-templates?tab=readme-ov-file#emacs-lisp][a flake template]] that provides a boilerplate with ~flake.nix~, ~justfile~, and some other typical configuration files.
With this template, you can get started with local development and GitHub Actions CI by editing some parameters.
You can add the configuration files to your existing project by running the following command:
I have created [[file:template][a flake template]] that provides a boilerplate with ~flake.nix~, ~justfile~, and some other typical configuration files.
With this template, you can get started with Rice just by editing parameters.

Using the template, you can add the configuration files to your existing project by running the following command:

#+begin_src sh
nix flake init -t github:akirak/flake-templates#emacs-lisp
nix flake init -t "github:emacs-twist/rice-config?dir=template"
#+end_src

The content of ~flake.nix~ in individual projects should be minimal.
If you have initialized the file from the flake template, you only have to set ~elisp-rice.packages~ in the outputs.
An example is as follows:
Because of the ~?~ character, you probably have to quote the URL, though it depends on your shell.

~flake.nix~ in an individual project is just an input to this flake (i.e. ~rice-config~), and it is designed to be minimal.
You can initialize the file from the flake template, you only have to set ~elisp-rice.packages~ in the outputs.
A minimal example is as follows:

#+begin_src nix
{
Expand All @@ -89,7 +92,22 @@ In this example, ~hello~ is the name of your package.
If your package contains multiple source files, you only specify the main library.
If your repository contains multiple packages, you have to specify all of them in ~packages~.

Also, open ~justfile~ to adapt it to your project.
You can also set up tests by setting ~tests~:

#+begin_src nix
{
outputs = {...}: {
elisp-rice = {
packages = ["hello"];
tests = {
buttercup.enable = true;
};
};
};
}
#+end_src

Open ~justfile~ to adapt it to your project.
You only need to edit variables.
You must set ~package~, and you may also have to set ~rice-config~, ~melpa~, and ~emacs-version~ as well.

Expand Down Expand Up @@ -219,7 +237,17 @@ Internally, it uses ~entr~ to watch file changes.
*** Testing (manual/automated)
Testing should be done on all supported Emacs versions, which can be tedious for package authors and maintainers.
This is another area where Rice is trying to improve.

If you have set up a test suite via ~tests~ output of the flake, you can run tests using ~test-*~ recipe:

#+begin_src sh
just test-buttercup
#+end_src

It runs ~test-buttercup-with-emacs-snapshot~ package of the flake with the inputs.
**** Shell with a specific Emacs version
Instead of running the pre-configured test suite for your package, it is also possible to run a given command in a package-enabled Emacs environment.

You can enter a shell with the package(s) available:

#+begin_src sh
Expand All @@ -242,7 +270,7 @@ The following should be covered in the future:

- [[https://github.com/purcell/package-lint][package-lint]]: This requires ~package.el~ to download dependencies, so it requires internet connection, which cannot be run in a pure Nix environment. It should be an application provided under ~packages~ output of the flake.
- ~checkdoc~ and other minor checks that can be run statically: This should be an optional addition to ~checks~. Only one Emacs version (either the latest release or a snapshot version) would be enough.
- Tests (ERT, [[https://github.com/jorgenschaefer/emacs-buttercup/][buttercup]], etc.): The user may depend on a third-party package for testing. Thus the rice-config should allow the user to define extra packages in individual package flakes. The extra packages will be available in the Emacs environments provided from ~packages~ (and its wrapper, ~just shell-emacs~).
- Add support for more test packages, e.g. ERT.

The above tasks are likely to require enhancement of the rice module.
** Alternatives
Expand Down
25 changes: 12 additions & 13 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
outputs = {
flake-parts,
nixpkgs,
self,
...
} @ inputs: let
systems = import inputs.systems;
Expand All @@ -46,16 +47,8 @@
inputs.elisp-rice.flakeModules.default
];

# Configure the Emacs environment in Nix.
elisp-rice = {
localPackages = inputs.rice-src.elisp-rice.packages;
src = inputs.rice-src.outPath;
lockDir = inputs.rice-lock.outPath;
lockInputName = "rice-lock";
github = {
inherit systems;
};
registries = inputs.registries.lib.registries;
elisp-rice = inputs.elisp-rice.lib.configFromInputs {
inherit (inputs) rice-src rice-lock registries systems;
};

perSystem = {
Expand All @@ -76,6 +69,7 @@

# Configure the per-system Emacs package set.
elisp-rice = {
enableElispPackages = true;
emacsPackageSet = inputs.emacs-ci.packages.${system};
defaultEmacsPackage = inputs.emacs-ci.packages.${system}.emacs-snapshot;
};
Expand All @@ -95,9 +89,14 @@
pre-commit.settings.hooks.deadnix.enable = true;

# pre-commit checks for elisp files
pre-commit.settings.hooks.elisp-byte-compile.enable = true;
# You can run byte-compile only in pre-commit.
pre-commit.settings.hooks.elisp-byte-compile.stages = ["push"];
pre-commit.settings.hooks.elisp-byte-compile = {
enable = true;
description = "Byte-compile Emacs Lisp files";
entry = "${self.packages.${system}.byte-compile}/bin/elisp-byte-compile";
files = "\\.el$";
# You can run byte-compile only in pre-push.
stages = ["push"];
};
};
};
}
71 changes: 71 additions & 0 deletions make-lock/flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
inputs = {
flake-parts.url = "github:hercules-ci/flake-parts";
elisp-rice.url = "github:emacs-twist/elisp-rice";

systems.url = "github:nix-systems/default";

emacs-ci.url = "github:purcell/nix-emacs-ci";
twist.url = "github:emacs-twist/twist.nix";

# Inputs that should be overridden for each project.
rice-src.url = "github:emacs-twist/rice-config?dir=example";
# If your project depends only on built-in packages, you don't have to
# override this. Also see https://github.com/NixOS/nix/issues/9339
rice-lock.url = "github:emacs-twist/rice-config?dir=lock";

emacs-builtins.url = "github:emacs-twist/emacs-builtins";

registries.url = "github:emacs-twist/registries";
registries.inputs.melpa.follows = "melpa";

melpa.url = "github:melpa/melpa";
melpa.flake = false;
};

# Use the binary cache of emacs-ci executables.
nixConfig = {
extra-substituters = "https://emacs-ci.cachix.org";
extra-trusted-public-keys = "emacs-ci.cachix.org-1:B5FVOrxhXXrOL0S+tQ7USrhjMT5iOPH+QN9q0NItom4=";
};

outputs = {
nixpkgs,
flake-parts,
...
} @ inputs:
flake-parts.lib.mkFlake {inherit inputs;} ({flake-parts-lib, ...}: let
systems = import inputs.systems;
in {
inherit systems;
imports = [
inputs.elisp-rice.flakeModules.default
];
elisp-rice = inputs.elisp-rice.lib.configFromInputs {
inherit (inputs) rice-src rice-lock registries systems;
};
perSystem = {
system,
config,
pkgs,
...
}: {
# Configure the perSystem environment.
_module.args.pkgs = import nixpkgs {
inherit system;
overlays = [
# This overlay is required to make `emacsTwist` function available
# in the flake-parts module.
inputs.twist.overlays.default
];
};

# Configure the per-system Emacs package set.
elisp-rice = {
# Disable the packages until the lock directory is available.
enableElispPackages = false;
emacsPackageSet = inputs.emacs-ci.packages.${system};
};
};
});
}
2 changes: 2 additions & 0 deletions template/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Copied from the template
justfile linguist-vendored
28 changes: 28 additions & 0 deletions template/.github/workflows/check-emacs-lisp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Check Emacs Lisp

on:
pull_request:
paths-ignore:
- 'README.*'
push:
branches:
- master
paths-ignore:
- 'README.*'
workflow_dispatch:

jobs:
byte-compile:
uses: emacs-twist/elisp-workflows/.github/workflows/byte-compile.yml@master
# with:
# rice-config: github:emacs-twist/rice-config
# melpa: github:akirak/melpa/akirak
# systems: github:nix-systems/x86_64-linux
# lock-dir: .rice-lock/default

melpazoid:
uses: emacs-twist/elisp-workflows/.github/workflows/melpazoid.yml@master
# with:
# rice-config: github:emacs-twist/rice-config
# melpa: github:akirak/melpa/akirak
# lock-dir: .rice-lock/default
9 changes: 9 additions & 0 deletions template/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Emacs Lisp
*.elc

# Optionally generated by Nix git-hooks
.pre-commit-config.yaml

# Nix
result
result-*
16 changes: 16 additions & 0 deletions template/flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
outputs = {...}: {
elisp-rice = {
packages =
builtins.trace
"warning: To use rice-config, please set the package name(s) in flake.nix"
[
(abort "Please set the package name (without .el)")
];
# Configure tests
tests = {
# buttercup.enable = true;
};
};
};
}
57 changes: 57 additions & 0 deletions template/justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Update this if you have forked rice-config
rice-config := "github:emacs-twist/rice-config"

# Specify a flake reference to a repository and branch where the package recipe
# is defined.
melpa := "github:melpa/melpa/master"
# Before it is available on melpa, you need to specify a non-default branch.
# melpa := "github:akirak/melpa/akirak"

# Relative path to the lock directory
lock-dir := ".rice-lock/default"

# This is only to avoid repetition, and you usually don't edit this.
common-options-without-lock := "--override-input rice-src \"path:$PWD\" --override-input melpa " + quote(melpa)

common-options-with-lock := common-options-without-lock + " --override-input rice-lock \"path:$PWD/" + lock-dir + "\""

# The name of an Emacs package from nix-emacs-ci
emacs := "emacs-release-snapshot"

# Name of the package under test
package := error("Please set the package name in justfile")

# Don't edit this
arch := shell('nix eval --expr builtins.currentSystem --impure --raw')

# Show the flake
show *OPTIONS:
nix flake show {{ rice-config }} {{ OPTIONS }} {{ common-options-with-lock }} --override-input systems github:nix-systems/{{ arch }} --allow-import-from-derivation

# Evaluate an attribute on the flake, e.g. just eval melpaRecipes.
eval ATTR *OPTIONS:
nix eval {{rice-config}}\#{{ATTR}} {{OPTIONS}} {{ common-options-with-lock }} --override-input systems github:nix-systems/{{ arch }} --allow-import-from-derivation

# Generate a lock directory.
lock *OPTIONS:
mkdir -p "$(dirname {{ lock-dir }})"
nix run "{{ rice-config }}?dir=make-lock#lock-with-{{ emacs }}" {{ common-options-without-lock }} --impure -- {{ OPTIONS }} {{ lock-dir }}

# Enter a shell for byte-compiling individual source files
shell-compile:
nix develop {{ rice-config }}\#{{ emacs }}-for-{{ package }} {{ common-options-with-lock }}

# Re-run byte-compile every time a file is modified
watch-compile:
nix develop {{ rice-config }}\#{{ emacs }}-for-{{ package }} {{ common-options-with-lock }} -c bash -c 'echo >&2 Watching *.el; ls *.el | entr -p elisp-byte-compile /_'

# Byte-compile the package
check-compile:
nix build {{ rice-config }}\#checks.{{ arch }}.{{ package }}-compile-{{ emacs }} {{ common-options-with-lock }} --print-build-logs

# Enter a shell for running tests
shell-emacs *OPTIONS:
nix shell {{ rice-config }}\#{{ emacs }}-with-packages {{ common-options-with-lock }} {{ OPTIONS }}

test-buttercup *OPTIONS:
nix run {{ rice-config }}\#test-buttercup-with-{{ emacs }} {{ common-options-with-lock }} {{ OPTIONS }}

0 comments on commit 65ba273

Please sign in to comment.