From ddd5ef7329ec421332a2aaf68f80d59a6fccef8a Mon Sep 17 00:00:00 2001 From: Sridhar Ratnakumar Date: Thu, 28 Aug 2025 05:31:50 +0530 Subject: [PATCH] Add hackage-publish.nix, to be tested --- CLAUDE.md | 5 ++- modules/home/all/tmux.nix | 2 +- modules/home/claude-code/commands/ci.md | 22 ++++++++++ modules/home/claude-code/default.nix | 25 ++++++----- packages/cat-agenix-secret.nix | 20 +++++++++ packages/hackage-publish.nix | 58 +++++++++++++++++++++++++ secrets/hackage-password.age | 11 +++++ secrets/secrets.nix | 1 + 8 files changed, 131 insertions(+), 13 deletions(-) create mode 100644 modules/home/claude-code/commands/ci.md create mode 100644 packages/cat-agenix-secret.nix create mode 100644 packages/hackage-publish.nix create mode 100644 secrets/hackage-password.age diff --git a/CLAUDE.md b/CLAUDE.md index 687a5ed..110f9c1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,4 +1,5 @@ -## Local CI +## Workflows -- You can test your changes by running `nix build` on the relevant configuration. \ No newline at end of file +- You can test your changes by running `nix build` on the relevant configuration. +- To deploy configuration to current system, we run `just activate` in Nix devShell. diff --git a/modules/home/all/tmux.nix b/modules/home/all/tmux.nix index 26a8d60..c540023 100644 --- a/modules/home/all/tmux.nix +++ b/modules/home/all/tmux.nix @@ -1,4 +1,4 @@ -{ pkgs, config, ... }: +{ pkgs, ... }: { programs.tmux = { enable = true; diff --git a/modules/home/claude-code/commands/ci.md b/modules/home/claude-code/commands/ci.md new file mode 100644 index 0000000..35442c8 --- /dev/null +++ b/modules/home/claude-code/commands/ci.md @@ -0,0 +1,22 @@ +--- +name: ci +description: Run local CI using omnix +--- + +This command runs local continuous integration checks using omnix. + +**IMPORTANT**: `om ci` will run full CI, thus takes a lot of time. Use only when necessary. + +Steps: +1. Run `om ci` to execute all CI checks locally + +This will: +- Build all flake outputs, which includes: + - Run tests + - Check formatting + - Validate flake structure + - Perform other CI validations + +Prerequisites: +- Must be in a flake-enabled project directory +- omnix (`om`) must be available in the environment \ No newline at end of file diff --git a/modules/home/claude-code/default.nix b/modules/home/claude-code/default.nix index 5674e8d..3ed754e 100644 --- a/modules/home/claude-code/default.nix +++ b/modules/home/claude-code/default.nix @@ -8,8 +8,21 @@ let (builtins.readFile (subagentsDir + "/${fileName}")) ) (builtins.readDir subagentsDir); + + commandsDir = ./commands; + commands = lib.mapAttrs' + (fileName: _: + lib.nameValuePair + (lib.removeSuffix ".md" fileName) + (builtins.readFile (commandsDir + "/${fileName}")) + ) + (builtins.readDir commandsDir); in { + home.packages = [ + pkgs.cat-agenix-secret # Used by hackage-publish script + pkgs.hackage-publish # Haskell package publishing script + ]; programs.claude-code = { enable = true; @@ -20,21 +33,13 @@ in # Basic settings for Claude Code settings = { theme = "dark"; - # enableAllProjectMcpServers = true; permissions = { defaultMode = "plan"; - additionalDirectories = [ ]; }; }; - # Custom commands can be added here - commands = { - "om-ci" = '' - #!/bin/bash - # Run local CI (Nix) - om ci - ''; - }; + # Automatically discovered commands from commands/ directory + commands = commands; # Automatically discovered agents from subagents/ directory agents = agents; diff --git a/packages/cat-agenix-secret.nix b/packages/cat-agenix-secret.nix new file mode 100644 index 0000000..23c4d99 --- /dev/null +++ b/packages/cat-agenix-secret.nix @@ -0,0 +1,20 @@ +{ pkgs, ... }: +pkgs.writeShellApplication { + name = "cat-agenix-secret"; + runtimeInputs = [ pkgs.ragenix ]; + meta.description = "Decrypt agenix secrets from nixos-config repo and output only the secret content"; + text = '' + if [ $# -ne 1 ]; then + echo "Usage: cat-agenix-secret " + echo "Example: cat-agenix-secret hackage-password.age" + exit 1 + fi + + secret_file="$1" + + cd "${./..}"/secrets + # Use ragenix with EDITOR=cat to decrypt the secret (ragenix doesn't have -d option) + set -x + env EDITOR=cat ragenix -e "$secret_file" -i ~/.ssh/id_ed25519 + ''; +} diff --git a/packages/hackage-publish.nix b/packages/hackage-publish.nix new file mode 100644 index 0000000..1e0a564 --- /dev/null +++ b/packages/hackage-publish.nix @@ -0,0 +1,58 @@ +{ pkgs, ... }: +pkgs.writeShellApplication { + name = "hackage-publish"; + runtimeInputs = [ pkgs.cat-agenix-secret ]; + meta.description = "Publish Haskell library to Hackage with encrypted password"; + text = '' + set -e + + # Check if we're in a Haskell project + if [ ! -f "*.cabal" ] && [ ! -f "cabal.project" ]; then + echo "Error: Not in a Haskell project directory (no .cabal file found)" >&2 + exit 1 + fi + + # Parse command line arguments + dry_run=false + if [ "$#" -gt 0 ] && [ "$1" = "--dry-run" ]; then + dry_run=true + echo "Running in dry-run mode (will print commands instead of executing)" + fi + + # Set cabal command based on dry-run mode + if [ "$dry_run" = true ]; then + cabal_cmd="echo cabal" + else + cabal_cmd="cabal" + fi + + echo "Step 2: Generating distribution tarball..." + $cabal_cmd sdist + + echo "Step 3: Getting Hackage password..." + if [ "$dry_run" = true ]; then + password="" + else + password=$(cat-agenix-secret hackage-password.age) + if [ -z "$password" ]; then + echo "Error: Failed to get Hackage password" >&2 + exit 1 + fi + fi + + echo "Step 4: Uploading to Hackage..." + read -p "Upload package to Hackage? (y/N): " -n 1 -r + echo + if [[ $REPLY =~ ^[Yy]$ ]]; then + $cabal_cmd upload -u sridca -P "$password" --publish + else + echo "Upload cancelled" + exit 0 + fi + + echo "Step 5: Uploading documentation..." + $cabal_cmd upload -d -u sridca -P "$password" --publish + + echo "Hackage publish completed successfully!" + ''; +} diff --git a/secrets/hackage-password.age b/secrets/hackage-password.age new file mode 100644 index 0000000..099c8bf --- /dev/null +++ b/secrets/hackage-password.age @@ -0,0 +1,11 @@ +age-encryption.org/v1 +-> ssh-ed25519 96IXNQ fkw73hLDykfEcq/OvTGwfQKO8adwA1ojBuPCKO5hZyw +YNN1Vcg+30il/ccbcWMgR4uucLBMGSdFLk+6PwjKiKc +-> ssh-ed25519 Ysxvmg RATkz1A0SNVm6Ynu2FhoTgc8yi6TwnK+I3LRpp32jAM +lUFyoIQSu1DCjkdAgWtDTDuM89GtqFSdbBsBzSZr4yg +-> ssh-ed25519 HQ+y9w OZSJZi0YRfkpmc5d6cMALj+Uo/WFoPy9+ME5tScunn4 ++4W1K5A+p2IPtPzcIiO+z4sVhNotX4T9wqs0E1BRlSc +-> ssh-ed25519 p0qplg Z2P1LtaIrYJujIQy9pIfgjc/tjvy5lWCKPDRUrr5LGs +Ve5d3aOfB9/GI45gapzVEtnTr0u6N4krZ+DoWj2lbN8 +--- CBkheL3TQ/W/4aVzTxuTUPh1UQMGT5AeWTXKCcVTVq8 +‡:wé[-CþÖ7Ÿ#ì«õØu<¥ÑG:l¹Pâ{‚gÐã¹ÙþR¥ç\Î@./ \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index a18dbd2..720b3d4 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -13,4 +13,5 @@ in "github-nix-ci/emaletter.token.age".publicKeys = users ++ systems; "pureintent-basic-auth.age".publicKeys = users ++ systems; "gmail-app-password.age".publicKeys = users ++ systems; + "hackage-password.age".publicKeys = users ++ systems; }