feat: comprehensive NixOS support improvements (#1024)
* feat: comprehensive NixOS support improvements This commit adds full NixOS support and automates Nix package maintenance: ## Static Linux Binaries for NixOS Changes .goreleaser.yml to create static Linux binaries: - Set CGO_ENABLED=0 for Linux amd64 and arm64 builds - Remove cross-compiler dependencies (aarch64-linux-gnu-gcc) - Simplifies build process while fixing NixOS compatibility Static binaries work on all Linux distributions including NixOS, Alpine, and musl-based distros without dynamic linker dependencies. ## Automated default.nix Version Management Adds default.nix to the version bump workflow: - Updates default.nix version field in bump-version.sh (new step 9) - Adds default.nix to version verification checks - Prevents version drift (was 5 releases behind: 0.42.0 vs 0.47.0) - Updates README.md to remove glibc 2.32+ requirement ## Automated vendorHash Management Creates scripts/update-nix-vendorhash.sh to automate vendorHash updates: - Automatically detects correct hash by triggering Nix build error - Extracts hash from error message and updates default.nix - Verifies update with clean build - Eliminates error-prone manual copy-paste workflow - Works with local Nix OR Docker (uses nixos/nix image automatically) Integrates vendorHash check into bump-version.sh: - Detects when go.mod or go.sum have changed - Prompts to run vendorHash update script interactively - Catches synchronization issues at release time ## Documentation Updates AGENTS.md with Nix package maintenance guide: - Documents when and how to update vendorHash - Recommends automated script as primary method - Provides manual and alternative methods as fallback - Notes Docker fallback for maintainers without Nix ## Impact - NixOS users can now install via standard methods - Nix package version stays synchronized automatically - vendorHash updates work without Nix installed (via Docker) - vendorHash updates are caught during release workflow - All Linux users benefit from more portable binaries Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> * fix: address PR review feedback for NixOS support Fixes three issues identified in PR review: 1. Replace undefined log_* functions in bump-version.sh with existing echo pattern (log_warning, log_info, log_success, log_error were called but not defined) 2. Update default.nix version from 0.42.0 to 0.47.0 to fix version drift with cmd/bd/version.go 3. Remove Nix Package Maintenance section from AGENTS.md per beads architecture (use bd prime for dynamic context, keep AGENTS.md minimal) * fix: update versions to 0.47.1 after merge with main - Update claude-plugin plugin.json to 0.47.1 - Update default.nix to 0.47.1 - Fixes version check failures after merging latest main branch --------- Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,7 @@ builds:
|
||||
main: ./cmd/bd
|
||||
binary: bd
|
||||
env:
|
||||
- CGO_ENABLED=1
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
goarch:
|
||||
@@ -29,9 +29,7 @@ builds:
|
||||
main: ./cmd/bd
|
||||
binary: bd
|
||||
env:
|
||||
- CGO_ENABLED=1
|
||||
- CC=aarch64-linux-gnu-gcc
|
||||
- CXX=aarch64-linux-gnu-g++
|
||||
- CGO_ENABLED=0
|
||||
goos:
|
||||
- linux
|
||||
goarch:
|
||||
|
||||
@@ -57,7 +57,7 @@ Beads supports hierarchical IDs for epics:
|
||||
* **Homebrew:** `brew install steveyegge/beads/bd`
|
||||
* **Go:** `go install github.com/steveyegge/beads/cmd/bd@latest`
|
||||
|
||||
**Requirements:** Linux (glibc 2.32+), FreeBSD, macOS, or Windows.
|
||||
**Requirements:** Linux, FreeBSD, macOS, or Windows.
|
||||
|
||||
## 🌐 Community Tools
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{ pkgs, self }:
|
||||
pkgs.buildGoModule {
|
||||
pname = "beads";
|
||||
version = "0.42.0";
|
||||
version = "0.47.1";
|
||||
|
||||
src = self;
|
||||
|
||||
|
||||
@@ -305,6 +305,60 @@ main() {
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if go.mod or go.sum changed since last commit
|
||||
if git diff HEAD go.mod go.sum 2>/dev/null | grep -q .; then
|
||||
echo ""
|
||||
echo -e "${YELLOW}Warning: go.mod or go.sum has uncommitted changes${NC}"
|
||||
echo "You may need to update vendorHash in default.nix"
|
||||
echo ""
|
||||
read -p "Run ./scripts/update-nix-vendorhash.sh now? [y/N] " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
if [ -f "./scripts/update-nix-vendorhash.sh" ]; then
|
||||
echo "Running vendorHash update script..."
|
||||
if ./scripts/update-nix-vendorhash.sh; then
|
||||
echo -e "${GREEN}✓ vendorHash updated successfully${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠ vendorHash update failed or was skipped${NC}"
|
||||
fi
|
||||
echo ""
|
||||
else
|
||||
echo -e "${RED}Error: scripts/update-nix-vendorhash.sh not found${NC}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Skipping vendorHash update"
|
||||
echo "Run ./scripts/update-nix-vendorhash.sh manually if needed"
|
||||
echo ""
|
||||
fi
|
||||
elif git diff HEAD~1..HEAD go.mod go.sum 2>/dev/null | grep -q .; then
|
||||
# Check if go.mod/go.sum changed in the last commit
|
||||
echo ""
|
||||
echo -e "${YELLOW}Warning: go.mod or go.sum changed in the last commit${NC}"
|
||||
echo "You may need to update vendorHash in default.nix"
|
||||
echo ""
|
||||
read -p "Run ./scripts/update-nix-vendorhash.sh now? [y/N] " -n 1 -r
|
||||
echo ""
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
if [ -f "./scripts/update-nix-vendorhash.sh" ]; then
|
||||
echo "Running vendorHash update script..."
|
||||
if ./scripts/update-nix-vendorhash.sh; then
|
||||
echo -e "${GREEN}✓ vendorHash updated successfully${NC}"
|
||||
else
|
||||
echo -e "${YELLOW}⚠ vendorHash update failed or was skipped${NC}"
|
||||
fi
|
||||
echo ""
|
||||
else
|
||||
echo -e "${RED}Error: scripts/update-nix-vendorhash.sh not found${NC}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "Skipping vendorHash update"
|
||||
echo "Run ./scripts/update-nix-vendorhash.sh manually if needed"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Updating version files..."
|
||||
|
||||
# 1. Update cmd/bd/version.go
|
||||
@@ -357,7 +411,13 @@ main() {
|
||||
"\"version\": \"$CURRENT_VERSION\"" \
|
||||
"\"version\": \"$NEW_VERSION\""
|
||||
|
||||
# 9. Update hook templates
|
||||
# 9. Update default.nix (Nix package definition)
|
||||
echo " • default.nix"
|
||||
update_file "default.nix" \
|
||||
"version = \"$CURRENT_VERSION\";" \
|
||||
"version = \"$NEW_VERSION\";"
|
||||
|
||||
# 10. Update hook templates
|
||||
echo " • cmd/bd/templates/hooks/*"
|
||||
HOOK_FILES=("pre-commit" "post-merge" "pre-push" "post-checkout")
|
||||
for hook in "${HOOK_FILES[@]}"; do
|
||||
@@ -366,7 +426,7 @@ main() {
|
||||
"# bd-hooks-version: $NEW_VERSION"
|
||||
done
|
||||
|
||||
# 10. Update CHANGELOG.md
|
||||
# 11. Update CHANGELOG.md
|
||||
echo " • CHANGELOG.md"
|
||||
update_changelog "$NEW_VERSION"
|
||||
|
||||
@@ -389,6 +449,7 @@ main() {
|
||||
"$(grep '__version__ = ' integrations/beads-mcp/src/beads_mcp/__init__.py | sed 's/.*"\(.*\)".*/\1/')"
|
||||
"$(jq -r '.version' npm-package/package.json)"
|
||||
"$(grep '# bd-hooks-version: ' cmd/bd/templates/hooks/pre-commit | sed 's/.*: \(.*\)/\1/')"
|
||||
"$(grep 'version = ' default.nix | sed 's/.*"\(.*\)".*/\1/')"
|
||||
)
|
||||
|
||||
ALL_MATCH=true
|
||||
|
||||
197
scripts/update-nix-vendorhash.sh
Executable file
197
scripts/update-nix-vendorhash.sh
Executable file
@@ -0,0 +1,197 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# =============================================================================
|
||||
# UPDATE NIX VENDORHASH SCRIPT
|
||||
# =============================================================================
|
||||
#
|
||||
# Automatically updates the vendorHash in default.nix after go.mod changes.
|
||||
# This script:
|
||||
# 1. Sets vendorHash to a known-bad hash to trigger an error
|
||||
# 2. Runs nix build to get the actual hash from the error message
|
||||
# 3. Extracts the correct hash from the error
|
||||
# 4. Updates default.nix with the correct hash
|
||||
# 5. Verifies the update by rebuilding
|
||||
#
|
||||
# Requirements:
|
||||
# - Either nix installed locally, OR
|
||||
# - Docker (will automatically use nixos/nix Docker image)
|
||||
#
|
||||
# Usage:
|
||||
# ./scripts/update-nix-vendorhash.sh
|
||||
#
|
||||
# =============================================================================
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
log_info() {
|
||||
echo -e "${BLUE}==>${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}✓${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}⚠${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}✗${NC} $1" >&2
|
||||
}
|
||||
|
||||
# Check if we're in the repo root
|
||||
if [ ! -f "default.nix" ]; then
|
||||
log_error "Must run from repository root (default.nix not found)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Determine if we should use Docker for Nix
|
||||
USE_DOCKER=false
|
||||
NIX_CMD="nix"
|
||||
|
||||
if ! command -v nix &> /dev/null; then
|
||||
log_warning "nix command not found locally"
|
||||
|
||||
# Check if Docker is available
|
||||
if command -v docker &> /dev/null; then
|
||||
log_info "Docker detected - will use nixos/nix Docker image"
|
||||
USE_DOCKER=true
|
||||
|
||||
# Pull the Nix Docker image if not present
|
||||
if ! docker image inspect nixos/nix:latest &> /dev/null; then
|
||||
log_info "Pulling nixos/nix:latest Docker image..."
|
||||
docker pull nixos/nix:latest
|
||||
fi
|
||||
else
|
||||
log_error "Neither nix nor docker found."
|
||||
log_error "Please install one of:"
|
||||
log_error " - Nix: https://nixos.org/download.html"
|
||||
log_error " - Docker: https://docs.docker.com/get-docker/"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Function to run nix commands (either locally or via Docker)
|
||||
run_nix() {
|
||||
if [ "$USE_DOCKER" = true ]; then
|
||||
# Get absolute path of current directory
|
||||
ABS_PWD=$(cd "$(pwd)" && pwd)
|
||||
|
||||
# Run nix in Docker container with current directory mounted
|
||||
# Mount at both /workspace and the original path (for git worktree compatibility)
|
||||
DOCKER_VOLUMES="-v $ABS_PWD:/workspace -v $ABS_PWD:$ABS_PWD"
|
||||
|
||||
# If this is a git worktree, mount the main git directory too
|
||||
if [ -f .git ] && grep -q "^gitdir: " .git; then
|
||||
GIT_COMMON_DIR=$(git rev-parse --git-common-dir 2>/dev/null || echo "")
|
||||
if [ -n "$GIT_COMMON_DIR" ] && [ -d "$GIT_COMMON_DIR" ]; then
|
||||
# Mount the main git directory at the same path
|
||||
DOCKER_VOLUMES="$DOCKER_VOLUMES -v $GIT_COMMON_DIR:$GIT_COMMON_DIR"
|
||||
fi
|
||||
fi
|
||||
|
||||
docker run --rm \
|
||||
$DOCKER_VOLUMES \
|
||||
-w /workspace \
|
||||
nixos/nix:latest \
|
||||
nix "$@" --extra-experimental-features "nix-command flakes"
|
||||
else
|
||||
nix "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
log_info "Updating vendorHash in default.nix..."
|
||||
echo ""
|
||||
|
||||
# Get current vendorHash
|
||||
CURRENT_HASH=$(grep 'vendorHash = ' default.nix | sed 's/.*"\(.*\)".*/\1/')
|
||||
log_info "Current vendorHash: $CURRENT_HASH"
|
||||
|
||||
# Step 1: Set to a known-bad hash to trigger an error
|
||||
log_info "Setting temporary bad hash to trigger error..."
|
||||
FAKE_HASH="sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
|
||||
|
||||
# Backup the file
|
||||
cp default.nix default.nix.backup
|
||||
|
||||
# Detect sed version (GNU vs BSD)
|
||||
if sed --version 2>/dev/null | grep -q "GNU sed"; then
|
||||
SED_INPLACE="sed -i"
|
||||
else
|
||||
SED_INPLACE="sed -i ''"
|
||||
fi
|
||||
|
||||
# Update to fake hash
|
||||
$SED_INPLACE "s|vendorHash = \".*\";|vendorHash = \"$FAKE_HASH\";|" default.nix
|
||||
|
||||
# Step 2: Run nix build and capture the error
|
||||
log_info "Building to get actual hash (this will fail intentionally)..."
|
||||
BUILD_LOG="/tmp/nix-vendorhash-build-$$.log"
|
||||
run_nix build > "$BUILD_LOG" 2>&1 || true
|
||||
|
||||
# Step 3: Extract the actual hash from the error message
|
||||
# Error format: "error: hash mismatch ... got: sha256-ACTUAL_HASH" (note: multiple spaces)
|
||||
# Use portable grep + sed instead of grep -P (which requires GNU grep)
|
||||
ACTUAL_HASH=$(grep -o 'got:[[:space:]]*sha256-[A-Za-z0-9+/=]*' "$BUILD_LOG" | head -1 | sed 's/got:[[:space:]]*//')
|
||||
|
||||
if [ -z "$ACTUAL_HASH" ]; then
|
||||
log_error "Failed to extract hash from nix build output"
|
||||
log_error "This might mean:"
|
||||
log_error " - Go dependencies haven't changed (no update needed)"
|
||||
log_error " - There's a different build error"
|
||||
echo ""
|
||||
log_info "Build output (last 30 lines):"
|
||||
tail -30 "$BUILD_LOG"
|
||||
echo ""
|
||||
log_info "Full build log saved to: $BUILD_LOG"
|
||||
|
||||
# Restore backup
|
||||
mv default.nix.backup default.nix
|
||||
log_info "Restored original default.nix"
|
||||
|
||||
# Check if hash is actually the same
|
||||
if grep -q "hash mismatch" "$BUILD_LOG"; then
|
||||
log_error "Hash mismatch detected but couldn't extract hash"
|
||||
log_error "Check the full log: $BUILD_LOG"
|
||||
exit 1
|
||||
else
|
||||
log_success "No hash mismatch - vendorHash is already correct!"
|
||||
rm -f "$BUILD_LOG"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
log_success "Extracted actual hash: $ACTUAL_HASH"
|
||||
|
||||
# Step 4: Update default.nix with the correct hash
|
||||
log_info "Updating default.nix with correct hash..."
|
||||
$SED_INPLACE "s|vendorHash = \".*\";|vendorHash = \"$ACTUAL_HASH\";|" default.nix
|
||||
|
||||
# Remove backup
|
||||
rm default.nix.backup
|
||||
|
||||
# Step 5: Verify the update by rebuilding
|
||||
log_info "Verifying update with a clean build..."
|
||||
if run_nix build 2>&1 | tee /tmp/nix-build-verify.log; then
|
||||
log_success "Build successful! vendorHash updated correctly."
|
||||
echo ""
|
||||
log_info "Summary:"
|
||||
echo " Old hash: $CURRENT_HASH"
|
||||
echo " New hash: $ACTUAL_HASH"
|
||||
echo ""
|
||||
log_success "default.nix has been updated"
|
||||
|
||||
# Clean up build logs
|
||||
rm -f "$BUILD_LOG" /tmp/nix-build-verify.log
|
||||
else
|
||||
log_error "Build failed after updating hash"
|
||||
log_error "See /tmp/nix-build-verify.log for details"
|
||||
log_error "Initial build log: $BUILD_LOG"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user