diff --git a/.github/file-filters.yml b/.github/file-filters.yml index fe71faf..5759249 100644 --- a/.github/file-filters.yml +++ b/.github/file-filters.yml @@ -32,3 +32,12 @@ documentation: &documentation documentation_all: - *documentation + +nix: &nix + - "flake.nix" + - "flake.lock" + - "go.mod" + - "go.sum" + +nix_all: + - *nix diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 58fe789..7d6d811 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,6 +22,7 @@ jobs: outputs: documentation: ${{ steps.changes.outputs.documentation_all }} go: ${{ steps.changes.outputs.go_all }} + nix: ${{ steps.changes.outputs.nix_all }} yaml: ${{ steps.changes.outputs.yaml_all }} markdown: ${{ steps.changes.outputs.markdown_all }} steps: @@ -74,6 +75,18 @@ jobs: - name: Run tests run: make test + nix-build: + if: needs.files-changed.outputs.nix == 'true' + needs: ["files-changed"] + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v6 + - uses: DeterminateSystems/nix-installer-action@v21 + - uses: DeterminateSystems/magic-nix-cache-action@v13 + - name: Verify if nix build succeeds + run: nix build --no-link + yaml-lint: if: needs.files-changed.outputs.yaml == 'true' needs: ["files-changed"] diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..de0df29 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1770537093, + "narHash": "sha256-pF1quXG5wsgtyuPOHcLfYg/ft/QMr8NnX0i6tW2187s=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "fef9403a3e4d31b0a23f0bacebbec52c248fbb51", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..03b4a8b --- /dev/null +++ b/flake.nix @@ -0,0 +1,96 @@ +{ + description = "infrahub-backup - Backup/restore and task management tools for Infrahub"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + + version = + if self ? shortRev then self.shortRev + else if self ? dirtyShortRev then self.dirtyShortRev + else "dev"; + + # Shared build configuration for both binaries. + # The neo4j watchdog must be pre-built because both packages + # import src/internal/app which has //go:embed directives + # referencing the watchdog binaries. + commonAttrs = { + inherit version; + src = ./.; + + vendorHash = "sha256-Vo/PzB5MVPhrVyZPyF1WUHJn1Kn/J6cjSlnDKzp+sTQ="; + + # Don't run preBuild (watchdog compilation) in the go-modules + # derivation — it only needs to fetch/vendor dependencies. + overrideModAttrs = finalAttrs: prevAttrs: { + preBuild = ""; + }; + + env.CGO_ENABLED = 0; + + ldflags = [ + "-s" "-w" + "-X main.version=${version}" + ]; + + preBuild = '' + # Build embedded neo4j watchdog binaries required by //go:embed + GOOS=linux GOARCH=arm64 go build -ldflags "-s -w" \ + -o src/internal/app/embedded/neo4jwatchdog/neo4j_watchdog_linux_arm64 \ + ./tools/neo4jwatchdog + GOOS=linux GOARCH=amd64 go build -ldflags "-s -w" \ + -o src/internal/app/embedded/neo4jwatchdog/neo4j_watchdog_linux_amd64 \ + ./tools/neo4jwatchdog + ''; + + meta = with pkgs.lib; { + homepage = "https://github.com/opsmill/infrahub-backup"; + license = licenses.asl20; + maintainers = [ ]; + }; + }; + in + { + packages = { + infrahub-backup = pkgs.buildGoModule (commonAttrs // { + pname = "infrahub-backup"; + subPackages = [ "src/cmd/infrahub-backup" ]; + meta = commonAttrs.meta // { + description = "Backup and restore tool for Infrahub instances"; + mainProgram = "infrahub-backup"; + }; + }); + + infrahub-taskmanager = pkgs.buildGoModule (commonAttrs // { + pname = "infrahub-taskmanager"; + subPackages = [ "src/cmd/infrahub-taskmanager" ]; + meta = commonAttrs.meta // { + description = "Task manager maintenance tool for Infrahub instances"; + mainProgram = "infrahub-taskmanager"; + }; + }); + + default = pkgs.symlinkJoin { + name = "infrahub-ops-cli-${version}"; + paths = [ + self.packages.${system}.infrahub-backup + self.packages.${system}.infrahub-taskmanager + ]; + }; + }; + + devShells.default = pkgs.mkShell { + buildInputs = with pkgs; [ + go + golangci-lint + gopls + ]; + }; + }); +} diff --git a/scripts/update-vendor-hash.sh b/scripts/update-vendor-hash.sh new file mode 100755 index 0000000..8c37231 --- /dev/null +++ b/scripts/update-vendor-hash.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +set -euo pipefail + +FLAKE_FILE="$(git rev-parse --show-toplevel)/flake.nix" +FAKE_HASH="sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" + +if [[ ! -f "$FLAKE_FILE" ]]; then + echo "error: flake.nix not found" >&2 + exit 1 +fi + +# Extract current hash +current_hash=$(grep -oP 'vendorHash = "\K[^"]+' "$FLAKE_FILE") +echo "Current vendorHash: $current_hash" + +# Temporarily set a fake hash +sed -i "s|vendorHash = \"${current_hash}\"|vendorHash = \"${FAKE_HASH}\"|" "$FLAKE_FILE" + +# Build and capture the correct hash from the error output +# Use --no-link to avoid creating a result symlink inside the repo +echo "Computing correct vendorHash..." +correct_hash="" +if build_output=$(nix build --no-link 2>&1); then + echo "nix build succeeded — restoring original hash" + sed -i "s|vendorHash = \"${FAKE_HASH}\"|vendorHash = \"${current_hash}\"|" "$FLAKE_FILE" + exit 0 +else + correct_hash=$(echo "$build_output" | grep -oP 'got:\s+\K\S+' | head -1) +fi + +if [[ -z "$correct_hash" ]]; then + echo "error: could not extract hash from nix build output" >&2 + echo "$build_output" >&2 + # Restore original hash + sed -i "s|vendorHash = \"${FAKE_HASH}\"|vendorHash = \"${current_hash}\"|" "$FLAKE_FILE" + exit 1 +fi + +# Update flake.nix with the correct hash +sed -i "s|vendorHash = \"${FAKE_HASH}\"|vendorHash = \"${correct_hash}\"|" "$FLAKE_FILE" + +if [[ "$current_hash" == "$correct_hash" ]]; then + echo "vendorHash is already up to date: $correct_hash" +else + echo "Updated vendorHash: $current_hash -> $correct_hash" +fi