- Contains a
nixmodule innix/flake-modules/actions-nix/that convertsnixconfiguration into GitHub/Gitea action syntaxyaml - Module contains definition of a
pre-commithook, usinggit-hooks.nix, that convertsactions-nixconfiguration into respective workflow files in the path defined in configuration
-
Write your action logic in
nixand transform that intoyamlactions -
Use the full capabilities of
nixto generate logic rather than writing it in plainyamlnixis a programming language rather than just a configuration language likeyaml- Consequently, it can be used to generate configuration more succinctly using functions
- Examples and reusable definitions will be added to this project
-
Reuse action definitions you have written in
nixacross repositories by using flakes rather than copy-pastingyamlacross repositories
See nix/ci/default.nix for action configuration in nix. This is turned by the
pre-commit hook, or by running nix run .#render-workflows, into the workflow file
in .github/workflows/main.yaml.
Add the module exposed by this repository and configure your workflows.
inputs.flake-parts.lib.mkFlake { inherit inputs; }
({ ... }: {
imports = [
inputs.actions-nix.flakeModules.default
# Module config for your repository (replace with your own below)
# ./ci
];
});You can also use the plain library API: write an actions-nix config module
and evaluate it yourself.
{
inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
actions-nix.url = "github:nialov/actions.nix";
};
outputs = { self, nixpkgs, actions-nix }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
actionsEval = actions-nix.lib.evalModule pkgs ./ci.nix;
in
{
packages.${system}.render-workflows = actionsEval.config.build.renderWorkflows;
checks.${system}.actions = actionsEval.config.build.check self;
};
}config.build.check self verifies that the workflow files already
committed in the flake source match what actions-nix would generate.
Example ci.nix:
{
defaultValues.jobs.runs-on = "ubuntu-latest";
workflows.".github/workflows/main.yaml".jobs.nix-flake-check.steps = [
{ uses = "actions/checkout@v4"; }
{ uses = "cachix/install-nix-action@v31"; }
{
name = "Check flake";
run = "nix -Lv flake check";
}
];
}Then run:
nix run .#render-workflowsrender-workflows then creates or overwrites files in the git root
according to ci.nix.
The flake.parts website hosts the module option documentation:
The actions-nix module automatically imports git-hooks. If you also
explicitly import git-hooks in your downstream project, and the versions
differ, this can cause an import collision due to the module options being
defined twice.
Example of collision potential in your flake:
imports = [
inputs.actions-nix.flakeModules.default
inputs.git-hooks.flakeModule # Import may conflict as it is already implemented by actions-nix
];How to avoid collisions:
You do not have to import git-hooks in your flake if you imported the
actions-nix module. Alternatively, configure your flake inputs so that
both your project and actions-nix use the same version of git-hooks.
For example, you can set your git-hooks input to follow the one used
by actions-nix, or vice versa:
actions-nix = {
url = "github:nialov/actions.nix";
};
git-hooks.follows = "actions-nix/git-hooks";or
git-hooks = {
url = "github:cachix/git-hooks.nix";
};
actions-nix = {
url = "github:nialov/actions.nix";
inputs.git-hooks.follows = "nix-extra/pre-commit-hooks";
};Recommended:
Let actions-nix handle the import, and avoid importing git-hooks
directly.
A convenience is provided in the form of flake.actions-nix.defaultValues.
Setting these options sets the defaults for those value options across
workflows and jobs. For example, by setting
flake.actions-nix.defaultValues.jobs.runs-on = "ubuntu-latest", all
workflows (flake.actions-nix.workflows.<name>) will have the runs-on
property set to that default. Overriding individually will still work normally
without, e.g., lib.mkForce as defaultValues only sets the default
option value. Note that defaultValues have themselves opinionated default
values which you should override to fit your needs.
GitHub/Gitea Actions secret references (e.g. ${{ secrets.MY_SECRET }}) must be
escaped in Nix strings to prevent Nix from interpreting the ${{...}}
syntax. Prefix the $ with a backslash. E.g.
env = {
API_TOKEN_GITHUB = "\${{ secrets.WEBSITE_DEPLOY }}";
};This produces the correct literal string ${{ secrets.WEBSITE_DEPLOY }} in the
rendered yaml. See nix/lib/steps.nix for examples of this escaping in use.
By default, workflow files will be rendered relative to the git repo root. To
write workflow files relative to the process working directory, run:
nix run .#render-workflows -- --no-prepend-git-rootThis is useful when you want files output somewhere other than the git root (e.g., when scripting or testing in a subdirectory).
If you need to add arguments (such as --no-prepend-git-root) to the
pre-commit hook invocation, you can do so, e.g., using the raw.args
option in your Nix flake configuration:
pre-commit.settings.hooks.render-actions = {
raw.args = [
"--no-prepend-git-root"
];
};There is built-in, optional support for Jujutsu VCS via the option:
flake.actions-nix.useJJ = true # default: `false`If enabled, locating the repo root will be tried with jj first and fallback to the usual approach git.
This is useful if you use jj workspaces where there isn't a git root available or if you don't use git-backed repos.
The --no-prepend-git-root flag also affects this option.
This is a work-in-progress project. My plan is to implement all functionality I need for minimizing action code repetition across my own various projects.
The aim is to be minimal and allow free-form configuration by users instead of
trying to generate it using logic in this project. Main purpose of this project
is to enable writing action logic in nix rather than yaml. The
opportunities opened by using nix are then mainly left for users to exploit.
Format code:
nix develop -c pre-commit run --all-filesCheck flake and evaluate tests:
nix flake checkTest workflow rendering locally:
nix run .#render-workflowsCheck past commit conventions:
git log --oneline