From 839d7ae7432115e44cd511ba779caba52d9cdca2 Mon Sep 17 00:00:00 2001 From: m3tm3re Date: Fri, 20 Feb 2026 09:01:06 +0100 Subject: [PATCH] feat(ci): support custom update scripts for specific packages Add detection logic to distinguish between: - nix-update-script (standard packages like beads, td, mem0, etc.) - Custom scripts (like n8n's update.sh that strips 'n8n@' prefix) For custom scripts, run them directly with standard env vars: - UPDATE_NIX_NAME, UPDATE_NIX_PNAME - UPDATE_NIX_OLD_VERSION, UPDATE_NIX_ATTR_PATH This ensures n8n only gets stable releases via its custom script. --- .gitea/workflows/nix-update.yml | 131 +++++++++++++++++++++++++++++--- 1 file changed, 120 insertions(+), 11 deletions(-) diff --git a/.gitea/workflows/nix-update.yml b/.gitea/workflows/nix-update.yml index 584234e..59851fd 100644 --- a/.gitea/workflows/nix-update.yml +++ b/.gitea/workflows/nix-update.yml @@ -169,21 +169,130 @@ jobs: [ "$1" != "$(git rev-parse HEAD)" ] && echo "true" || echo "false" } - has_update_script() { - local pkg=$1 - # Check if package has passthru.updateScript attribute - nix eval .#${pkg}.passthru.updateScript --json >/dev/null 2>&1 - } + has_update_script() { + local pkg=$1 + # Check if package has passthru.updateScript attribute + nix eval .#${pkg}.passthru.updateScript --json >/dev/null 2>&1 + } - run_update() { - local pkg=$1 - local before_hash=$(git rev-parse HEAD) + # Check if updateScript is a custom script (path-based) vs nix-update-script + is_custom_update_script() { + local pkg=$1 + local result + # nix-update-script returns a list like [ "/nix/store/...-nix-update/bin/nix-update" ] + # Custom scripts return a path like "/nix/store/.../update.sh" + result=$(nix eval --impure --raw --expr " + let + flake = builtins.getFlake (toString ./.); + pkg = flake.packages.\${builtins.currentSystem}.${pkg}; + script = pkg.passthru.updateScript or []; + in + if builtins.isPath script then + \"custom\" + else if builtins.isList script && builtins.length script > 0 then + let first = builtins.head script; + in if builtins.isString first && builtins.match \".*/nix-update$\" first != null then + \"nix-update-script\" + else if builtins.isPath first then + \"custom\" + else + \"other\" + else if builtins.isAttrs script && script ? command then + if builtins.isPath script.command then \"custom\" + else if builtins.isList script.command && builtins.isPath (builtins.head script.command) then \"custom\" + else \"other\" + else + \"other\" + " 2>/dev/null || echo "other") + [[ "$result" == "custom" ]] + } - echo "::group::Updating $pkg" + # Run a custom update script directly (for packages like n8n) + run_custom_update_script() { + local pkg=$1 + local before_hash=$(git rev-parse HEAD) + + echo " 🔧 Detected custom update script for $pkg" + + # Get package metadata for environment variables + local name pname version + name=$(nix eval --raw .#${pkg}.name 2>/dev/null || echo "$pkg") + pname=$(nix eval --raw .#${pkg}.pname 2>/dev/null || echo "$pkg") + version=$(nix eval --raw .#${pkg}.version 2>/dev/null || echo "unknown") + + # Run the custom script using nix develop + if nix develop --impure --expr " + with builtins; + let + flake = getFlake (toString ./.); + pkgs = flake.inputs.nixpkgs.legacyPackages.\${currentSystem}; + pkg' = flake.packages.\${currentSystem}.${pkg}; + script = pkg'.passthru.updateScript; + cmd = if isAttrs script then script.command else script; + scriptPath = if isList cmd then head cmd else cmd; + in pkgs.mkShell { + inputsFrom = [pkg']; + packages = with pkgs; [ curl jq git ]; + } + " --command bash -c " + export UPDATE_NIX_NAME='${name}' + export UPDATE_NIX_PNAME='${pname}' + export UPDATE_NIX_OLD_VERSION='${version}' + export UPDATE_NIX_ATTR_PATH='${pkg}' + + # Get the script path and execute it + script_path=\$(nix eval --impure --raw --expr ' + let + flake = builtins.getFlake (toString ./.); + pkg = flake.packages.\${builtins.currentSystem}.${pkg}; + script = pkg.passthru.updateScript; + cmd = if builtins.isAttrs script then script.command else script; + in if builtins.isList cmd then toString (builtins.head cmd) + else toString cmd + ' 2>/dev/null) + + if [ -n \"\$script_path\" ]; then + echo \"Running: \$script_path\" + bash \"\$script_path\" + fi + " 2>&1 | tee /tmp/update-${pkg}.log; then + if [ "$(check_commit "$before_hash")" = "true" ]; then + echo "✅ Updated $pkg (via custom script)" + return 0 + fi + fi + + # Clean up on failure + git checkout -- . 2>/dev/null || true + git clean -fd 2>/dev/null || true + + if ! grep -q "already up to date\|No new version found" /tmp/update-${pkg}.log; then + echo "⚠️ Custom update script failed for $pkg" + fi + return 1 + } - local args=("--flake" "--commit" "--use-github-releases") + run_update() { + local pkg=$1 + local before_hash=$(git rev-parse HEAD) - args+=("$pkg") + echo "::group::Updating $pkg" + + # Check if this package has a custom update script + if is_custom_update_script "$pkg"; then + if run_custom_update_script "$pkg"; then + echo "::endgroup::" + return 0 + else + echo "::endgroup::" + return 1 + fi + fi + + # Standard nix-update for packages with nix-update-script + local args=("--flake" "--commit" "--use-github-releases") + + args+=("$pkg") if nix-update "${args[@]}" 2>&1 | tee /tmp/update-${pkg}.log; then if [ "$(check_commit "$before_hash")" = "true" ]; then