Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,28 @@ See `nix/ci/default.nix` for action configuration in `nix`. This is turned by th
`pre-commit` hook, or by running `nix run .#render-workflows`, into the workflow file
in `.github/workflows/main.yaml`.

### Advanced: control relative path with `--no-prepend-git-root`

By default, workflow files will be rendered relative to the git repo root. To write workflow files relative to the process working directory (CWD), run:

```
nix run .#render-workflows -- --no-prepend-git-root
```

This is useful when you want files output somewhere *other* than the git root (e.g., when scripting or testing in a subdirectory).

#### Passing the flag in pre-commit configuration

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:

```nix
pre-commit.settings.hooks.render-actions = {
raw.args = [
"--no-prepend-git-root"
];
};
```

## Installation

This project uses `flake-parts`. You need to add the module exposed by this
Expand Down Expand Up @@ -107,3 +129,29 @@ 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.

## Development

**Format code:**

```sh
nix develop -c pre-commit run --all-files
```

**Check flake and evaluate tests:**

```sh
nix flake check
```

**Test workflow rendering locally:**

```sh
nix run .#render-workflows
```

**Check past commit conventions:**

```sh
git log --oneline
```
4 changes: 4 additions & 0 deletions nix/flake-modules/actions-nix/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ _localFlake:
entry =
let
renderCI = self'.packages.render-workflows;
# To override the default behavior of outputting workflow files at the git repo root, pass
# --no-prepend-git-root
# to this script; this will cause workflow files to be written relative to the process working directory instead.
in
"${renderCI}/bin/render-workflows";
};
Expand All @@ -53,6 +56,7 @@ _localFlake:
packages.render-workflows =
(pkgs.writeShellApplication {
name = "render-workflows";
runtimeInputs = [ pkgs.git ];
text =
let
pythonEnv = pkgs.python3.withPackages (p: [ p.pyyaml ]);
Expand Down
29 changes: 26 additions & 3 deletions nix/flake-modules/actions-nix/render.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,18 @@ def yaml_multiline_string_pipe(dumper, data):

yaml.add_representer(str, yaml_multiline_string_pipe)

def main(evaluated_ci_path: Optional[Path]):
def get_git_toplevel() -> Path:
result = subprocess.run(
["git", "rev-parse", "--show-toplevel"],
text=True,
capture_output=True,
check=True,
)
return Path(result.stdout.strip())

def main(evaluated_ci_path: Optional[Path], prepend_git_root: bool = True):
git_toplevel = get_git_toplevel() if prepend_git_root else None

if evaluated_ci_path is None:
eval_process = partial(
subprocess.run,
Expand All @@ -58,7 +69,10 @@ def main(evaluated_ci_path: Optional[Path]):
workflows = json.loads(evaluated_ci_path.read_text())

for key, value in workflows.items():
render_path = Path(key)
if prepend_git_root:
render_path = git_toplevel / key
else:
render_path = Path(key)
render_path.parent.mkdir(exist_ok=True, parents=True)
print(f"Writing to {render_path}")
header = f"""# This file was autogenerated by actions.nix. Do not edit it manually.
Expand All @@ -73,5 +87,14 @@ def main(evaluated_ci_path: Optional[Path]):
if __name__ == "__main__":
argparser = argparse.ArgumentParser()
argparser.add_argument("--evaluated-ci-path", required=False)
argparser.add_argument(
"--no-prepend-git-root",
action="store_true",
help="Do not prepend the git repo root to workflow paths"
)
args = argparser.parse_args()
main(evaluated_ci_path=Path(args.evaluated_ci_path))
main(
evaluated_ci_path=Path(args.evaluated_ci_path) if args.evaluated_ci_path else None,
prepend_git_root=not args.no_prepend_git_root,
)