Skip to content

Commit 394f3a7

Browse files
authored
Merge pull request #435 from 1Password/mrj/nix-flake-overlay
feat: Add a Nix Flake with a devShell, NixOS module, and home-manager module to configure Shell Plugins
2 parents acb6582 + e751aa5 commit 394f3a7

File tree

8 files changed

+239
-0
lines changed

8 files changed

+239
-0
lines changed

.github/workflows/check-flake.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: Check Nix flake
2+
on:
3+
pull_request:
4+
push:
5+
branches:
6+
- main
7+
jobs:
8+
check-flake:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
- uses: DeterminateSystems/nix-installer-action@main
13+
- uses: DeterminateSystems/magic-nix-cache-action@main
14+
- name: Check Nix flake inputs
15+
uses: DeterminateSystems/flake-checker-action@v5
16+
with:
17+
fail-mode: true
18+
send-statistics: false
19+
- name: Run nix flake check
20+
run: nix flake check
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# CI job to periodically (once a week) update flake.lock
2+
name: Update flake dependencies
3+
4+
on:
5+
schedule:
6+
- cron: '0 16 * * 5'
7+
workflow_dispatch: # for allowing manual triggers of the workflow
8+
9+
jobs:
10+
update-dependencies:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: DeterminateSystems/nix-installer-action@main
15+
- uses: DeterminateSystems/magic-nix-cache-action@main
16+
- name: update flake.lock
17+
run: nix flake update
18+
- name: Create signed commit with flake.lock changes
19+
env:
20+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
21+
FILE_TO_COMMIT: flake.lock
22+
COMMIT_BRANCH: automation/update-flake-dependencies
23+
COMMIT_MESSAGE: "chore(nix): Update Flake dependencies"
24+
run: |
25+
# make sure something actually changed first, if not, no updates required
26+
if [[ `git status --porcelain` ]]; then
27+
# create the branch on the remote
28+
git branch "$COMMIT_BRANCH"
29+
git push -u origin "$COMMIT_BRANCH"
30+
# commit via the GitHub API so we get automatic commit signing
31+
gh api --method PUT /repos/1Password/shell-plugins/contents/$FILE_TO_COMMIT \
32+
--field message="$COMMIT_MESSAGE" \
33+
--field content=@<(base64 -i $FILE_TO_COMMIT) \
34+
--field branch="$COMMIT_BRANCH" \
35+
--field sha="$(git rev-parse $COMMIT_BRANCH:$FILE_TO_COMMIT)"
36+
gh pr create --title "[automation]: Update Flake dependencies" --body "This is an automated PR to update \`flake.lock\`" --reviewer mrjones2014 --base main --head $COMMIT_BRANCH
37+
fi

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@ plugins/registry.json
1919

2020
# 1Password
2121
.op
22+
23+
# direnv
24+
.direnv
25+
.envrc

flake.lock

Lines changed: 61 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

flake.nix

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
inputs = {
3+
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
4+
flake-utils = { url = "github:numtide/flake-utils"; };
5+
};
6+
outputs = { nixpkgs, flake-utils, ... }:
7+
(flake-utils.lib.eachDefaultSystem (system:
8+
let pkgs = nixpkgs.legacyPackages.${system};
9+
in {
10+
devShells.default = pkgs.mkShell {
11+
name = "Shell with Go toolchain";
12+
packages = with pkgs; [ go gopls ];
13+
};
14+
})) // {
15+
nixosModules.default = import ./nix/nixos.nix;
16+
hmModules.default = import ./nix/home-manager.nix;
17+
};
18+
}

nix/home-manager.nix

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{ pkgs, lib, config, ... }:
2+
import ./shell-plugins.nix {
3+
inherit pkgs;
4+
inherit lib;
5+
inherit config;
6+
is-home-manager = true;
7+
}

nix/nixos.nix

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{ pkgs, lib, config, ... }:
2+
import ./shell-plugins.nix {
3+
inherit pkgs;
4+
inherit lib;
5+
inherit config;
6+
is-home-manager = false;
7+
}

nix/shell-plugins.nix

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
{ pkgs, lib, config, is-home-manager, ... }:
2+
with lib;
3+
let
4+
cfg = config.programs._1password-shell-plugins;
5+
6+
supported_plugins = splitString "\n" (lib.readFile "${
7+
# get the list of supported plugin executable names
8+
pkgs.runCommand "op-plugin-list" { }
9+
# 1Password CLI tries to create the config directory automatically, so set a temp XDG_CONFIG_HOME
10+
# since we don't actually need it for this
11+
"mkdir $out && XDG_CONFIG_HOME=$out ${pkgs._1password}/bin/op plugin list | cut -d ' ' -f1 | tail -n +2 > $out/plugins.txt"
12+
}/plugins.txt");
13+
getExeName = package:
14+
# NOTE: SAFETY: This is okay because the `packages` list is also referred
15+
# to below as `home.packages = packages;` or `environment.systemPackages = packages;`
16+
# depending on if it's using `home-manager` or not; this means that Nix can still
17+
# compute the dependency tree, even though we're discarding string context here,
18+
# since the packages are still referred to below without discarding string context.
19+
strings.unsafeDiscardStringContext (baseNameOf (getExe package));
20+
in {
21+
options = {
22+
programs._1password-shell-plugins = {
23+
enable = mkEnableOption "1Password Shell Plugins";
24+
plugins = mkOption {
25+
type = types.listOf types.package;
26+
default = [ ];
27+
example = literalExpression ''
28+
with pkgs; [
29+
gh
30+
awscli2
31+
cachix
32+
]
33+
'';
34+
description =
35+
"CLI Packages to enable 1Password Shell Plugins for; ensure that a Shell Plugin exists by checking the docs: https://developer.1password.com/docs/cli/shell-plugins/";
36+
# this is a bit of a hack to do option validation;
37+
# ensure that the list of packages include only packages
38+
# for which the executable has a supported 1Password Shell Plugin
39+
apply = package_list:
40+
map (package:
41+
if (elem (getExeName package) supported_plugins) then
42+
package
43+
else
44+
abort "${
45+
getExeName package
46+
} is not a valid 1Password Shell Plugin. A list of supported plugins can be found by running `op plugin list` or at: https://developer.1password.com/docs/cli/shell-plugins/")
47+
package_list;
48+
};
49+
};
50+
};
51+
52+
config = let
53+
# executable names as strings, e.g. `pkgs.gh` => `"gh"`, `pkgs.awscli2` => `"aws"`
54+
pkg-exe-names = map getExeName cfg.plugins;
55+
# Explanation:
56+
# Map over `cfg.plugins` (the value of the `plugins` option provided by the user)
57+
# and for each package specified, get the executable name, then create a shell alias
58+
# of the form:
59+
# `alias {pkg}="op plugin run -- {pkg}"`
60+
# where `{pkg}` is the executable name of the package
61+
aliases = listToAttrs (map (package: {
62+
name = package;
63+
value = "op plugin run -- ${package}";
64+
}) pkg-exe-names);
65+
packages = [ pkgs._1password ] ++ cfg.plugins;
66+
in mkIf cfg.enable (mkMerge [
67+
({
68+
programs = {
69+
bash.shellAliases = aliases;
70+
zsh.shellAliases = aliases;
71+
fish.shellAliases = aliases;
72+
};
73+
} // optionalAttrs is-home-manager {
74+
home = {
75+
inherit packages;
76+
sessionVariables = { OP_PLUGINS_SOURCED = "1"; };
77+
};
78+
} // optionalAttrs (!is-home-manager) {
79+
environment = {
80+
systemPackages = packages;
81+
variables = { OP_PLUGINS_SOURCED = "1"; };
82+
};
83+
})
84+
]);
85+
}

0 commit comments

Comments
 (0)