All Projects → akirak → elinter

akirak / elinter

Licence: GPL-3.0 License
Nix-based CI and local testing framework for Emacs Lisp projects

Programming Languages

emacs lisp
2029 projects
Nix
1067 projects
shell
77523 projects
sed
78 projects

Projects that are alternatives of or similar to elinter

prosesitter.nvim
A (work in progress) grammar, spelling and style plugin for Neovim
Stars: ✭ 23 (+21.05%)
Mutual labels:  linting
flake8-broken-line
🚨 Flake8 plugin to forbid backslashes (\) for line breaks
Stars: ✭ 85 (+347.37%)
Mutual labels:  linting
ue5-style-guide
An attempt to make Unreal Engine 4 projects more consistent
Stars: ✭ 2,892 (+15121.05%)
Mutual labels:  linting
polymer-linter
Moved to Polymer/tools monorepo
Stars: ✭ 34 (+78.95%)
Mutual labels:  linting
liquibase-linter
Quality control for your Liquibase scripts
Stars: ✭ 15 (-21.05%)
Mutual labels:  linting
nix-new-rails-app
Initialize Rails applications using Nix and development environments (nix-shell)
Stars: ✭ 27 (+42.11%)
Mutual labels:  nix
React-Native-Web-TypeScript-Prettier-Boilerplate
A starterkit to work with nextjs, react-native, storybook… all with prettified typescript and in a monorepo
Stars: ✭ 16 (-15.79%)
Mutual labels:  linting
dotfiles
My NixOS dotfiles
Stars: ✭ 21 (+10.53%)
Mutual labels:  nix
codeclimate-eslint
Code Climate Engine for ESLint
Stars: ✭ 86 (+352.63%)
Mutual labels:  linting
django-nixos
NixOS/NixOps configuration for Django
Stars: ✭ 21 (+10.53%)
Mutual labels:  nix
dockerfile-utils
A library and command line interface for formatting and linting Dockerfiles.
Stars: ✭ 17 (-10.53%)
Mutual labels:  linting
stackage2nix
Generate Nix build instructions from a Stack file
Stars: ✭ 48 (+152.63%)
Mutual labels:  nix
nix-bash-completions
Bash completion for the Nix command line tools
Stars: ✭ 39 (+105.26%)
Mutual labels:  nix
docker-nix
Docker image for nix [maintainer=@zimbatm] [status=deprecated]
Stars: ✭ 38 (+100%)
Mutual labels:  nix
microvm.nix
NixOS MicroVMs
Stars: ✭ 136 (+615.79%)
Mutual labels:  nix
nixos-on-arm
Cross Compiling NixOS to ARM as a replacement for Yocto
Stars: ✭ 129 (+578.95%)
Mutual labels:  nix
makes
A DevSecOps framework powered by Nix.
Stars: ✭ 158 (+731.58%)
Mutual labels:  nix
addlint
An example linter written with go/analysis for tutorial purposes
Stars: ✭ 49 (+157.89%)
Mutual labels:  linting
nixexprs
nix stuff
Stars: ✭ 13 (-31.58%)
Mutual labels:  nix
nix-prefetch-github
Prefetch sources from github for nix build tool
Stars: ✭ 25 (+31.58%)
Mutual labels:  nix

elinter

This project is soon to be replaced by nomake. I won’t develop elinter any more. Please consider nomake if you are looking for an alternative.

This is a complete rewrite of my Emacs Lisp package checker, formerly called emacs-package-checker or melpa-check. It is still currently at an alpha stage.

Build Status Build Status

Table of contents

Project goals

This project aims at the following goals:

  • Support both local use and CI
  • Comprehensive linting using various backends (trying to produce the same result as melpazoid, which is created and used by the official reviewer on MELPA)
  • Use Nix to support dependencies that involve specific build procedures and/or native dependencies, e.g. emacsql-sqlite, vterm, etc.
  • Support projects containing multiple packages in the same repository
  • Allow ease of setup for new projects and ease of migration for existing projects, e.g. from Cask
  • Minimal configuration and minimal maintenance

Planned features [72%]

The following is a list of features that should be supported by this project. Maybe I’ll announce this project officially when the progress reaches around 80%.

Linting (the list mostly extracted from makem.sh + inspiration from elisp-lint):

  • [X] checkdoc
  • [X] package-lint
  • [X] check-declare
  • [X] melpazoid (sharp quotes and other experimental checks)
  • [ ] ELSA
  • [ ] indentation
  • [ ] regular expressions
  • [ ] whitespace

Building packages:

  • [X] Byte-compile
  • [X] Loadability testing
  • [X] Produce a package with *-autoloads.el file

Testing:

  • [X] buttercup
  • [X] ert-runner
  • [X] ert with given test files
  • [X] Run any command in an environment with packages under test

Target project types:

  • [X] Multi-file packages
  • [X] Multi-package repositories
  • [ ] Source files in subdirectories
  • [ ] Native dependencies

Sources:

  • [X] Local repository
  • [X] Remote source repositories

Configuration:

  • [X] Allow specifying an Emacs version available in nix-emacs-ci
  • [X] Determine Emacs versions based on the library headers of individual packages
  • [X] Read development dependencies (used for testing) from Cask file
  • [ ] Allow defining custom Nix package derivations
  • [X] Allow updating Nix dependencies (including emacs-overlay) locally
  • [ ] Add support for better integration with Nix flakes

Integration:

  • [X] CLI for local use
  • [X] Git pre-commit hook (run static checks only on modified files)
  • [X] GitHub Actions
  • [ ] GitHub workflow with the latest set of packages (probably as a Docker image)

Reporting:

  • [X] Colorizing statuses

GitHub Actions:

  • [X] Groups on GitHub Actions
  • [X] Produce annotations that point to concrete error locations on GitHub Actions
  • [ ] Check if recipes are up to date on MELPA
  • [X] Fine-grained settings of linting options

Prerequisites

elinter runs on UNIX-like operating systems that can run Nix (currently Linux and macOS).

Installation

elinter depends on Nix, so you have to install Nix first:

bash <(curl -L https://nixos.org/nix/install)

elinter can be installed using Nix:

nix-env -if https://github.com/akirak/elinter/archive/v4.tar.gz

Alternatively, you can clone this repository and run

nix-env -if .

Optionally, it is recommended to install cachix and enable cached Emacs binaries:

cachix use emacs-ci

Optionally, you can use cached-nix-shell for improving nix-shell startup time. Install the program in PATH, and elinter will automatically detect it.

Usage

Use case #1: Local source + in-repository recipes

First create package recipes in .recipes directory. The recipe format is the same as you would create for MELPA, and each file should define exactly one package.

You can use elinter.el, which is included in this project, to copy existing recipes from your local copy of MELPA. First set elinter-recipes-dir to the recipes directory inside MELPA, and then use elinter interactive function. It scans source files in the repository, import package recipes, and run lint on source files.

The below describes command line usage but also applies to elinter command inside Emacs.

Without arguments, it lints and compiles source files in the repository:

elinter

To enable experimental checks by melpazoid which you would receive on MELPA PRs, add --experimental flag:

elinter --experimental

With --buttercup or --ert-runner flag, it also runs tests:

elinter --buttercup

To only lint packages and prevent from byte-compiling, add -l flag:

elinter -l

To only byte-compile source files, add -b flag:

elinter -b

To only run tests, run it with -t along with the --buttercup, --ert-runner, etc.:

elinter -t --buttercup

See elinter-demo and its status page for concrete examples.

Use case #2: Local recipes + remote sources

This is like the use case 1, but it clones the remote repository specified in the recipe rather than work on source files in the working directory.

elinter command accepts recipe files as arguments. When -r flag is given, it clones remote Git repositories according to the recipes. This can be easily integrated into the MELPA PR workflow:

cd ~/your-melpa-fork
elinter -r recipes/your-package --experimental

The same flags as #1 applies.

Use case #3: GitHub workflow for package repositories

This repository also provides a GitHub action for checking individual packages on GitHub.

The following is an example workflow. Create a file in .github/workflows. Here is an example output.

name: CI
on:
  push:
jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    # Nix is required
    - uses: cachix/install-nix-action@v10
    # Install elinter and run lint and byte-compile
    - uses: akirak/elinter@v4
    # Optional step for running tests
    - name: 'Run buttercup tests with the latest release of Emacs'
      run: elinter -t --buttercup -e latest

Use case #4: GitHub workflow for batch-linting your packages on MELPA

Since elinter command can take recipe files as arguments and fetch remote repositories, it is possible to add a linting workflow to your copy of MELPA.

Here is an example workflow definition and output.

Use case #5: Git pre-commit hook

This repository also provides a script that can be integrated into Git pre-commit hook.

If you run elinter with -g argument at a repository root, it installs a pre-commit hook that performs static checks based on the recipe(s).

It uses pre-commit, and .pre-commit-config.yaml is created at the repository root.

Note that byte-compilation is not performed by the hook.

Alternatively, you can use cachix/pre-commit-hooks.nix to configure the hook for multiple languages in Nix. The following is an example:

with builtins;
with (import <nixpkgs> {});
with (import (import ./nix/sources.nix).gitignore { });
let
  pre-commit-hooks = import (import ./nix/sources.nix)."pre-commit-hooks.nix";

  elinter = import (fetchTarball "https://github.com/akirak/elinter/archive/v4.tar.gz") { };

  pre-commit-check = pre-commit-hooks.run {
    src = gitignoreSource ../.;
    excludes = [ "^nix/sources\.nix$" ];
    hooks = {
      shellcheck.enable = true;
      nix-linter.enable = true;
      nixpkgs-fmt.enable = true;
      elinter = {
        enable = true;
        name = "elinter";
        description = "Lint Emacs Lisp files";
        entry = "${elinter.file-linter}/bin/elinter-lint-files";
        files = "\\.el$";
      };
    };
  };
in
mkShell {
  shellHook = pre-commit-check.shellHook;
}

That is, file-linter Nix attribute of this repository provides elinter-lint-files executable which performs static checks on given files, so you can integrate it using any Git hooks manager:

# install the script
nix-env -if . -A file-linter
# check source files in your repository
elinter-lint-files hello.el hello-utils.el

Technical details

elinter command

The default Nix derivation provides elinter executable. It takes recipe files as command line arguments.

It can also take package names and it refers to source files linked from the sandbox (described below).

If no recipe file or package name is given as an argument, it looks for ones in .recipes directory in the working directory.

Emacs version syntax

elinter command supports -e option that takes an Emacs version, e.g. 26.3 for Emacs 26.3 and snapshot for the latest snapshot. You can use any single version available in nix-emacs-ci.

It also supports the following abstract version specs:

  • min, the minimum version specified in the library header of each package
  • latest, the latest stable version
  • all, all versions since the minimum version including the snapshot, in descending order

Updating packages

To update dependencies, e.g. emacs-overlay for Emacs packages and nix-emacs-ci for Emacs itself, add -u flag to the elinter command:

elinter -u RECIPES

Sandboxing

elinter creates symbolic links in a cache directory and operates on them, rather than lint and compile source files directly in the repository. This is useful both for simplification and isolation. Once symbolic links are created, they are reused across different runs for performance. Since they are symbolic links, file modifications are reflected, but file additions/deletions are not applied. After you create/delete a source file in the repository, you have to run elinter with -c arguments to recreate the sandbox:

elinter -c

You can use -c with other arguments:

elinter -c -l --experimental

Credits, inspiration sources, and alternatives

elinter was influenced by or depends on the following projects:

  • emacs-overlay from the Nix community, its emacsWithPackagesFromPackageRequires parser by Steve Purcell, and fromElisp parser (used in my Nix library) by Kim Lindberger
  • makem.sh by Adam Porter (alphapapa), for some of its linting code and the idea of extensive use of bash
  • melpazoid by Chris Rayner (riscy), for extra linting features and the idea of sandboxing
  • keg.el by Naoya Yamashita (conao3), for its recipe-oriented configuration API
  • nix-hello-world by Damien Cassou, for configuring Nix projects
  • makel by Damien Cassou, for some linting code

elinter is an improvement upon the previous version, on which I gained help by Eric Dallo and Terje Larsen.

The current version (v4) was contributed by the following people:

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].