5 Commits
Author SHA1 Message Date
awkawb 8f831f21c5 package.nix: updated invoiceninja to v5.13.53 2026-11-03 13:58:30 -05:00
awkawbandClaude Sonnet 5 badcdd2566 justfile: add update target to automate version bumps; push ui to cachix
push-cache was only printing the main invoiceninja package's out path, so
the ui derivation (exposed via passthru.ui) never actually reached the
cachix cache even though it gets built as a dependency.

The new update target (scripts/update-versions.sh) checks GitHub for the
latest invoiceninja release and the latest invoiceninja/ui tag, bumps
whichever changed in package.nix, and iteratively rebuilds -- parsing
each hash-mismatch error Nix reports for a fixed-output derivation -- to
fill in the correct src/npmDeps/vendor hashes automatically.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-22 17:35:06 -04:00
awkawbandClaude Sonnet 5 37abda5f39 package: update invoiceninja to v5.13.50, ui to 18.10.2026.1
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-22 17:35:00 -04:00
awkawbandClaude Sonnet 5 4e544f6e46 flake: add cachix binary cache
Adds nixConfig substituter/key for the invoiceninja-nixos cachix cache,
a `just push-cache` target to build and push the package and automated
test to it, and exposes the UI frontend build as a passthru output
(`invoiceninja.ui`) so it can be built and pushed independently.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-22 15:59:29 -04:00
awkawbandClaude Sonnet 5 0f1f3f6675 package: update invoiceninja to v5.13.48, ui to 06.10.2026.1
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-15 19:20:39 -04:00
4 changed files with 204 additions and 7 deletions
+7
View File
@@ -1,6 +1,13 @@
{
description = "An Invoice Ninja package and module.";
nixConfig = {
extra-substituters = [ "https://invoiceninja-nixos.cachix.org" ];
extra-trusted-public-keys = [
"invoiceninja-nixos.cachix.org-1:TmRZaji8FFVjjIw9KZmvLrxMxfP+JDThOyOX04z526A="
];
};
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
outputs =
+14
View File
@@ -36,3 +36,17 @@ boot-vm:
test:
nix flake check -L
[doc('Update invoiceninja and ui to their latest upstream versions, recomputing hashes')]
[group('maintenance')]
update:
./scripts/update-versions.sh
[doc('Build the package and automated test, then push results to the invoiceninja-nixos cachix cache')]
[group('maintenance')]
push-cache:
nix build --print-out-paths --no-link \
".#invoiceninja" \
".#invoiceninja.ui" \
".#checks.x86_64-linux.invoiceninja" \
| cachix push invoiceninja-nixos
+9 -7
View File
@@ -14,13 +14,13 @@
let
pname = "invoiceninja";
version = "5.13.43";
version = "5.13.53";
src = fetchFromGitHub {
name = "${pname}";
owner = pname;
repo = pname;
rev = "v${version}";
hash = "sha256-F8lEyVi2EFRnkxWSDRIqsqrKmtCEUEee8lDDUZXoo0c=";
hash = "sha256-KQMb1W2S1YrRZOgjV3NPDpQaz5BbF/xtziNFd34wvxo=";
postFetch = ''
# add missing integrity fields to lockfile
@@ -28,13 +28,13 @@ let
'';
};
uiVersion = "28.09.2026.1";
uiVersion = "18.10.2026.1";
uiSrc = fetchFromGitHub {
name = "${pname}-ui";
owner = pname;
repo = "ui";
tag = uiVersion;
hash = "sha256-RLirh0Q5lhH2O7AEwoR4MdlELAgB00f9w6FfiBNhoho=";
hash = "sha256-56szHmIWU9De04Orykp2RxrW0RV87JxB7Y1yvdrSJm4=";
postFetch = ''
# add missing integrity fields to lockfile
@@ -50,7 +50,7 @@ let
nodejs = nodejs_22;
npmDepsHash = "sha256-7Boz+o4pQkPNMJREWgUMeKQa7avChqd+GpZoaXO0LqE=";
npmDepsHash = "sha256-j5XocHvBfMvzNrkaVkTsck2+yPraYWrXQxAbf3EYfIk=";
preConfigure = ''
sed -i 's/VITE_IS_TEST=true/VITE_IS_TEST=false/' .env.example
@@ -74,6 +74,8 @@ php82.buildComposerProject (finalAttrs: {
inherit src version;
pname = "${pname}-composer";
passthru.ui = ui;
nativeBuildInputs = [
jq
nodejs_22
@@ -81,7 +83,7 @@ php82.buildComposerProject (finalAttrs: {
npmHooks.npmBuildHook
];
vendorHash = "sha256-zTo+unMIsv2XObjwiFpxTdUxVfZoXbMNviDrLMVMJI0=";
vendorHash = "sha256-sFpfnCt8jv8z9cLoFE8utPQiGz7q/KkqUXabEhcJP3M=";
# Upstream composer.json has invalid license, webpatser/laravel-countries package is pointing
# to commit-ref, and php required in require and require-dev
@@ -92,7 +94,7 @@ php82.buildComposerProject (finalAttrs: {
npmDeps = fetchNpmDeps {
name = "${pname}-${version}-npm-deps";
inherit src;
hash = "sha256-uHbvhf8EWOBiyPQ9ieA4ynIUkIXWJEXZ7ZVsr4NXWtU=";
hash = "sha256-ditAbluBzs5OV/fCMV5Q4w1amao6ofOlee4YXMpZ37I=";
};
preConfigure = ''
+174
View File
@@ -0,0 +1,174 @@
#!/usr/bin/env bash
# Bumps invoiceninja/package.nix to the latest upstream invoiceninja and
# invoiceninja/ui versions, then rebuilds repeatedly -- using the
# "specified vs. got" hash mismatch that Nix reports for each
# fixed-output derivation -- to fill in the correct src/npmDeps/vendor
# hashes. Invoked via `just update`.
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")/.."
pkg=package.nix
# Replaces the RHS (between the first "=" and the last ";") of the line
# immediately following the first line containing $anchor.
set_after() {
local file="$1" anchor="$2" newrhs="$3"
awk -v anchor="$anchor" -v newrhs="$newrhs" '
{
if (found) {
sub(/=.*;/, "= " newrhs ";")
found = 0
}
if (index($0, anchor) > 0) found = 1
print
}
' "$file" > "${file}.tmp"
mv "${file}.tmp" "$file"
}
# Replaces the RHS of the first line assigning to $field. Only the first
# match is touched -- "version" is assigned twice in package.nix (the
# top-level invoiceninja version, and buildNpmPackage's own "version"
# attribute for the ui derivation, which must stay "= uiVersion;") and the
# top-level one always comes first.
set_field() {
local file="$1" field="$2" newrhs="$3"
awk -v field="$field" -v newrhs="$newrhs" '
{
if (!done && $0 ~ "^[[:space:]]*" field "[[:space:]]*=") {
sub(/=.*;/, "= " newrhs ";")
done = 1
}
print
}
' "$file" > "${file}.tmp"
mv "${file}.tmp" "$file"
}
current_main_version=$(grep -m1 -E '^\s*version = "' "$pkg" | sed -E 's/.*"([^"]+)".*/\1/')
current_ui_version=$(grep -m1 -E '^\s*uiVersion = "' "$pkg" | sed -E 's/.*"([^"]+)".*/\1/')
echo "Current: invoiceninja=$current_main_version ui=$current_ui_version"
latest_main_version=$(curl -sf https://api.github.com/repos/invoiceninja/invoiceninja/releases/latest | jq -r '.tag_name' | sed 's/^v//')
# invoiceninja/ui has no GitHub Releases, just date-stamped tags
# (DD.MM.YYYY.N) -- paginate through all tags and pick the newest by
# calendar date, ignoring "-release" hotfix tags and other one-off tag
# names that don't fit that scheme.
ui_tags=""
page=1
while :; do
batch=$(curl -sf "https://api.github.com/repos/invoiceninja/ui/tags?per_page=100&page=${page}" | jq -r '.[].name')
[ -z "$batch" ] && break
ui_tags="${ui_tags}
${batch}"
page=$((page + 1))
done
latest_ui_version=$(printf '%s\n' "$ui_tags" \
| grep -E '^[0-9]{2}\.[0-9]{2}\.[0-9]{4}\.[0-9]+$' \
| awk -F. '{printf "%s%02d%02d%s %s\n", $3, $2, $1, $4, $0}' \
| sort \
| tail -1 \
| awk '{print $2}')
if [ -z "$latest_main_version" ] || [ -z "$latest_ui_version" ]; then
echo "error: failed to determine latest versions (main=$latest_main_version ui=$latest_ui_version)" >&2
exit 1
fi
echo "Latest: invoiceninja=$latest_main_version ui=$latest_ui_version"
main_changed=0
ui_changed=0
if [ "$latest_main_version" != "$current_main_version" ]; then
main_changed=1
set_field "$pkg" version "\"$latest_main_version\""
fi
if [ "$latest_ui_version" != "$current_ui_version" ]; then
ui_changed=1
set_field "$pkg" uiVersion "\"$latest_ui_version\""
fi
if [ "$main_changed" = 0 ] && [ "$ui_changed" = 0 ]; then
echo "Already up to date."
exit 0
fi
# Invalidate every hash that could have changed as a result of the version
# bump(s) above, so the rebuild loop below reports the real ones.
if [ "$main_changed" = 1 ]; then
set_after "$pkg" 'rev = "v${version}";' 'lib.fakeHash'
set_after "$pkg" 'inherit src;' 'lib.fakeHash'
set_field "$pkg" vendorHash 'lib.fakeHash'
fi
if [ "$ui_changed" = 1 ]; then
set_after "$pkg" 'tag = uiVersion;' 'lib.fakeHash'
set_field "$pkg" npmDepsHash 'lib.fakeHash'
fi
echo "Rebuilding to discover the correct hashes (this takes a few iterations)..."
max_iterations=10
for ((i = 1; i <= max_iterations; i++)); do
echo "--- build attempt $i/$max_iterations ---"
set +e
build_output=$(nix build ".#invoiceninja" ".#invoiceninja.ui" --no-link -L 2>&1)
status=$?
set -e
if [ "$status" -eq 0 ]; then
echo "Build succeeded."
exit 0
fi
mismatch_line=$(printf '%s\n' "$build_output" | grep -m1 "hash mismatch in fixed-output derivation" || true)
if [ -z "$mismatch_line" ]; then
echo "$build_output" | tail -80
echo "error: build failed for a reason other than a hash mismatch; see output above" >&2
exit 1
fi
drv_path=$(printf '%s\n' "$mismatch_line" | sed -E "s/.*'([^']+)'.*/\1/")
# Store paths are "<32-char hash>-<name>"; strip the hash to get the name.
name=$(basename "$drv_path" .drv | sed -E 's/^[0-9a-z]{32}-//')
got_hash=$(printf '%s\n' "$build_output" | grep -m1 -E '^\s+got: ' | awk '{print $2}')
if [ -z "$got_hash" ]; then
echo "$build_output" | tail -80
echo "error: could not parse the correct hash out of the build output above" >&2
exit 1
fi
echo "Fixing hash for '$name': $got_hash"
case "$name" in
invoiceninja)
set_after "$pkg" 'rev = "v${version}";' "\"$got_hash\""
;;
invoiceninja-ui)
set_after "$pkg" 'tag = uiVersion;' "\"$got_hash\""
;;
invoiceninja-ui-*-npm-deps)
set_field "$pkg" npmDepsHash "\"$got_hash\""
;;
invoiceninja-composer-composer-repository-*)
set_field "$pkg" vendorHash "\"$got_hash\""
;;
invoiceninja-*-npm-deps)
set_after "$pkg" 'inherit src;' "\"$got_hash\""
;;
*)
echo "error: unrecognized derivation '$name' in hash mismatch; don't know which field to update" >&2
exit 1
;;
esac
done
echo "error: exceeded $max_iterations build attempts without resolving all hash mismatches" >&2
exit 1