Skip to content

Commit

Permalink
Add github action
Browse files Browse the repository at this point in the history
  • Loading branch information
arnarg committed Dec 22, 2023
1 parent f3645b5 commit a7ef10e
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 117 deletions.
41 changes: 41 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: nixidy action
description: Generate manifest for a nixidy environment

inputs:
environment:
description: Name of the environment to build
required: true
cwd:
description: Path to directory containing the checked out repository
default: '.'

runs:
using: composite
steps:
- shell: bash
env:
FLAKE: github:${{github.action_repository}}/${{github.action_ref}}
DEST_DIR: ${{runner.temp}}/${{inputs.environment}}
run: |
TARGET_BRANCH=$(nix run '${{env.FLAKE}}#' -- info '${{inputs.cwd}}#${{inputs.environment}}' --json | jq -r .branch)
if git -C "${{inputs.cwd}}" fetch origin "$TARGET_BRANCH"; then
git -C "${{inputs.cwd}}" worktree add --checkout "${{env.DEST_DIR}}" "$TARGET_BRANCH"
else
git -C "${{inputs.cwd}}" worktree add --orphan -b "$TARGET_BRANCH" "${{env.DEST_DIR}}"
fi
RESULT=$(nix run '${{env.FLAKE}}#' -- build '${{inputs.cwd}}#${{inputs.environment}}' --print-out-paths --no-link)
rsync --recursive --delete --exclude=.git -L "$RESULT/" "${{env.DEST_DIR}}"
echo "BRANCH=$TARGET_BRANCH" >> "$GITHUB_ENV"
echo "DEST_DIR=$(realpath --relative-to "$PWD" "$DEST_DIR")" >> "$GITHUB_ENV"
- uses: EndBug/add-and-commit@v9
with:
cwd: ${{env.DEST_DIR}}
default_author: github_actions
message: "chore(${{inputs.environment}}): promote to ${{inputs.environment}} ${{github.sha}}"
fetch: false
push: --set-upstream origin ${{env.BRANCH}}
41 changes: 39 additions & 2 deletions docs/user_guide/github_actions.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,42 @@
# GitHub Actions

A GitHub Action is coming soon...
Nixidy offers a GitHub Action to build and push an environment to its target branch.

In the meantime take a look at the custom workflow in [nixidy-demo](https://github.com/arnarg/nixidy-demo/blob/main/.github/workflows/generate-manifests.yaml).
## Usage

In this example it will build environments dev, test and prod on every push to main. Realistically the different environments should be built in different workflows.

```yaml
name: Generate Kubernetes manifests

on:
push:
branches:
- main

jobs:
generate:
runs-on: ubuntu-latest
strategy:
matrix:
env: ["dev", "test", "prod"]
steps:
- uses: actions/checkout@v4

- uses: cachix/install-nix-action@v20
with:
# This config is required in order to support a nixidy
# flake repository
extra_nix_config: |
extra-experimental-features = nix-command flakes
# This is optional but speeds up consecutive runs
# by caching nix derivations between github workflows
# runs
- uses: DeterminateSystems/magic-nix-cache-action@v2

# Build and push nixidy environment
- uses: arnarg/nixidy@main
with:
environment: ${{matrix.env}}
```
104 changes: 1 addition & 103 deletions modules/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -18,112 +18,10 @@
}
// extraSpecialArgs;
};

extras = pkgs.stdenv.mkDerivation {
name = "nixidy-extras";

phases = ["installPhase"];

installPhase =
''
mkdir -p $out
''
+ (
lib.concatStringsSep "\n" (lib.mapAttrsToList (n: f: ''
mkdir -p $out/$(dirname ${f.path})
cat <<EOF > $out/${f.path}
${f.text}
EOF
'')
module.config.nixidy.extraFiles)
);
};

apps =
lib.mapAttrs (
n: v: {
name = n;
path = v.output.path;
resources = lib.flatten (
lib.mapAttrsToList (
group: groupData:
lib.mapAttrsToList (
kind: kindData:
lib.mapAttrsToList (
res: resData:
resData
// {
apiVersion = group;
kind = kind;
metadata = {name = res;} // (resData.metadata or {});
}
)
kindData
)
groupData
)
v.resources
);
}
)
module.config.applications;

mkApp = app: let
resources =
map (
res: rec {
filename = "${res.kind}-${builtins.replaceStrings ["."] ["-"] res.metadata.name}.yaml";
manifest = let
resource = builtins.toJSON res;
in
pkgs.stdenv.mkDerivation {
inherit resource;

name = "nixidy-app-${app.name}-${filename}";

passAsFile = ["resource"];

phases = ["installPhase"];

installPhase = ''
cat $resourcePath | ${pkgs.yq-go}/bin/yq -P > $out
'';
};
}
)
app.resources;
in
pkgs.stdenv.mkDerivation {
name = "nixidy-app-${app.name}";

phases = ["installPhase"];

installPhase =
''
mkdir -p $out
''
+ (lib.concatStringsSep "\n" (map (res: ''
ln -s ${res.manifest} $out/${res.filename}
'')
resources));
};

mkStage = apps: let
appsJoined = pkgs.linkFarm "nixidy-stage-apps-joined" (lib.mapAttrsToList (_: app: {
name = app.path;
path = mkApp app;
})
apps);
in
pkgs.symlinkJoin {
name = "nixidy-stage";
paths = [appsJoined extras];
};
in {
targetBranch = module.config.nixidy.target.branch;
meta = {
repository = module.config.nixidy.target.repository;
branch = module.config.nixidy.target.branch;
};
result = mkStage apps;
environmentPackage = module.config.nixidy.environmentPackage;
}
128 changes: 128 additions & 0 deletions modules/environment.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
{
lib,
config,
pkgs,
...
}: let
envName = lib.replaceStrings ["/"] ["-"] config.nixidy.target.branch;

apps =
lib.mapAttrs (
n: v: {
name = n;
path = v.output.path;
resources = lib.flatten (
lib.mapAttrsToList (
group: groupData:
lib.mapAttrsToList (
kind: kindData:
lib.mapAttrsToList (
res: resData:
resData
// {
apiVersion = group;
kind = kind;
metadata = {name = res;} // (resData.metadata or {});
}
)
kindData
)
groupData
)
v.resources
);
}
)
config.applications;

mkApp = app: let
resources =
map (
res: rec {
filename = "${res.kind}-${builtins.replaceStrings ["."] ["-"] res.metadata.name}.yaml";
manifest = let
resource = builtins.toJSON res;
in
pkgs.stdenv.mkDerivation {
inherit resource;

name = "nixidy-app-${app.name}-${filename}";

passAsFile = ["resource"];

phases = ["installPhase"];

installPhase = ''
cat $resourcePath | ${pkgs.yq-go}/bin/yq -P > $out
'';
};
}
)
app.resources;
in
pkgs.stdenv.mkDerivation {
name = "nixidy-app-${app.name}";

phases = ["installPhase"];

installPhase =
''
mkdir -p $out
''
+ (lib.concatStringsSep "\n" (map (res: ''
ln -s ${res.manifest} $out/${res.filename}
'')
resources));
};
in {
options = with lib; {
nixidy.extrasPackage = mkOption {
type = types.package;
internal = true;
description = "The package containing all the extra files for an environment.";
};

nixidy.environmentPackage = mkOption {
type = types.package;
internal = true;
description = "The package containing all the applications for an environment.";
};
};

config = {
# Build all extra files into its own package
nixidy.extrasPackage = pkgs.stdenv.mkDerivation {
name = "nixidy-extras-${envName}";

phases = ["installPhase"];

installPhase =
''
mkdir -p $out
''
+ (lib.concatStringsSep "\n" (lib.mapAttrsToList (_: file: ''
mkdir -p $out/$(dirname ${file.path})
cat <<EOF > "$out/${file.path}"
${file.text}
EOF
'')
config.nixidy.extraFiles));
};

# Build final environment into a package
nixidy.environmentPackage = let
joined = pkgs.linkFarm "nixidy-apps-joined-${envName}" (lib.mapAttrsToList (_: app: {
name = app.path;
path = mkApp app;
})
apps);
in
pkgs.symlinkJoin {
name = "nixidy-environment-${envName}";
paths = [
joined
config.nixidy.extrasPackage
];
};
};
}
1 change: 1 addition & 0 deletions modules/modules.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[
./applications.nix
./nixidy.nix
./environment.nix
]
26 changes: 14 additions & 12 deletions nixidy/nixidy
Original file line number Diff line number Diff line change
Expand Up @@ -47,30 +47,29 @@ function doBuild() {
exit 1
fi

nix build "${FLAKE_ROOT}#nixidyEnvs.${NIX_SYSTEM}.${FLAKE_ENV}.result" "${BUILD_PARAMS[@]}"
nix build "${FLAKE_ROOT}#nixidyEnvs.${NIX_SYSTEM}.${FLAKE_ENV}.environmentPackage" "${BUILD_PARAMS[@]}"
}

function doHelp() {
echo "Usage: $0 [OPTION] COMMAND"
echo
echo "Options"
echo
echo " --no-link Don't create a result symlink (only used in build)."
echo " --out-link PATH Create a custom result symlink (only used in build)."
echo " --json Output info in JSON format (only used in info)."
echo " -h Print this help"
echo " --no-link Don't create a result symlink (only used in build)."
echo " --out-link PATH Create a custom result symlink (only used in build)."
echo " --print-out-paths Print the resulting output paths (only used in build)."
echo " --json Output info in JSON format (only used in info)."
echo " -h Print this help"
echo
echo "Commands"
echo
echo " help Print this help."
echo " help Print this help."
echo
echo " info FLAKE_URI"
echo " Get info about environment."
echo " Example: .#prod"
echo " info FLAKE_URI Get info about environment."
echo " Example: .#prod"
echo
echo " build FLAKE_URI"
echo " Build nixidy environment from flake URI."
echo " Example: .#prod"
echo " build FLAKE_URI Build nixidy environment from flake URI."
echo " Example: .#prod"
}

COMMAND=""
Expand All @@ -89,6 +88,9 @@ while [[ $# -gt 0 ]]; do
--no-link)
BUILD_PARAMS+=("--no-link")
;;
--print-out-paths)
BUILD_PARAMS+=("--print-out-paths")
;;
--out-link)
BUILD_PARAMS+=("--out-link" "$1")
shift
Expand Down

0 comments on commit a7ef10e

Please sign in to comment.