From a1455d88d8b03f2f442e5c2a465fa4a58eeb4374 Mon Sep 17 00:00:00 2001 From: Michael Lyon Date: Fri, 3 Apr 2026 10:56:39 -0600 Subject: [PATCH 1/3] Add Nix flake for declarative installation Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release.yml | 26 +++++++++++++ flake.lock | 27 +++++++++++++ flake.nix | 71 +++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c465e48..9a422d6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -63,3 +63,29 @@ jobs: dist/*.AppImage dist/*.deb dist/*.rpm + + - name: Update flake.nix hashes + env: + VERSION: ${{ steps.bump.outputs.version }} + run: | + X86_HASH=$(sha256sum dist/linear-linux-${VERSION}-x86_64.AppImage | awk '{print $1}') + ARM_HASH=$(sha256sum dist/linear-linux-${VERSION}-arm64.AppImage | awk '{print $1}') + + X86_SRI="sha256-$(echo -n "$X86_HASH" | python3 -c "import sys,base64,binascii; print(base64.b64encode(binascii.unhexlify(sys.stdin.read())).decode())")" + ARM_SRI="sha256-$(echo -n "$ARM_HASH" | python3 -c "import sys,base64,binascii; print(base64.b64encode(binascii.unhexlify(sys.stdin.read())).decode())")" + + sed -i "s|version = \".*\";|version = \"${VERSION}\";|" flake.nix + sed -i "s|hash = \"sha256-.*\"; # x86_64|hash = \"${X86_SRI}\"; # x86_64|" flake.nix + sed -i "s|hash = \"sha256-.*\"; # aarch64|hash = \"${ARM_SRI}\"; # aarch64|" flake.nix + + - name: Commit flake.nix update + env: + VERSION: ${{ steps.bump.outputs.version }} + run: | + git add flake.nix + if git diff --cached --quiet; then + echo "No changes to flake.nix" + else + git commit -m "chore: update flake.nix hashes for v${VERSION}" + git push + fi diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..4b75299 --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1775036866, + "narHash": "sha256-ZojAnPuCdy657PbTq5V0Y+AHKhZAIwSIT2cb8UgAz/U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6201e203d09599479a3b3450ed24fa81537ebc4e", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..21a977f --- /dev/null +++ b/flake.nix @@ -0,0 +1,71 @@ +{ + description = "Unofficial Linux desktop client for Linear (linear.app)"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + }; + + outputs = { self, nixpkgs }: + let + version = "0.2.5"; + + sources = { + x86_64-linux = { + url = "https://github.com/kleo-dev/linear-linux/releases/download/v${version}/linear-linux-${version}-x86_64.AppImage"; + hash = "sha256-NBmfXyrmtBccOLLzBiwbkCyA8IGxtY+AQIgAVxfrank="; # x86_64 + }; + aarch64-linux = { + url = "https://github.com/kleo-dev/linear-linux/releases/download/v${version}/linear-linux-${version}-arm64.AppImage"; + hash = "sha256-nNDo7cq05as0qoEbd1UkOG+s8PzFZxnovcqLsg11RlU="; # aarch64 + }; + }; + + forAllSystems = nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" ]; + in + { + packages = forAllSystems (system: + let + pkgs = nixpkgs.legacyPackages.${system}; + src = pkgs.fetchurl { + url = sources.${system}.url; + hash = sources.${system}.hash; + }; + in + { + linear-linux = pkgs.appimageTools.wrapType2 { + pname = "linear-linux"; + inherit version src; + + extraInstallCommands = + let + appimageContents = pkgs.appimageTools.extractType2 { + pname = "linear-linux"; + inherit version src; + }; + in + '' + # Install desktop file + install -Dm644 ${appimageContents}/linear-linux.desktop \ + $out/share/applications/linear-linux.desktop + substituteInPlace $out/share/applications/linear-linux.desktop \ + --replace-warn 'Exec=AppRun' 'Exec=linear-linux' + + # Install icons + install -Dm644 ${appimageContents}/usr/share/icons/hicolor/1024x1024/apps/linear-linux.png \ + $out/share/icons/hicolor/1024x1024/apps/linear-linux.png + ''; + + meta = with pkgs.lib; { + description = "Unofficial Linux desktop client for Linear (linear.app)"; + homepage = "https://github.com/kleo-dev/linear-linux"; + license = licenses.isc; + platforms = [ "x86_64-linux" "aarch64-linux" ]; + mainProgram = "linear-linux"; + }; + }; + + default = self.packages.${system}.linear-linux; + } + ); + }; +} From 8b0b1e25b337e93bd6b6daa50b6be7cdc630f180 Mon Sep 17 00:00:00 2001 From: Michael Lyon Date: Fri, 3 Apr 2026 11:15:21 -0600 Subject: [PATCH 2/3] Use nix-hash for SRI conversion and add install-nix-action Replace the fragile Python one-liner with nix-hash --sri for computing flake hashes in CI. Add cachix/install-nix-action@v31 to ensure Nix is available on the runner. Add grep verification to fail loudly if sed replacements don't take effect. Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/workflows/release.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9a422d6..a9f8abc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -64,20 +64,23 @@ jobs: dist/*.deb dist/*.rpm + - name: Install Nix + uses: cachix/install-nix-action@v31 + - name: Update flake.nix hashes env: VERSION: ${{ steps.bump.outputs.version }} run: | - X86_HASH=$(sha256sum dist/linear-linux-${VERSION}-x86_64.AppImage | awk '{print $1}') - ARM_HASH=$(sha256sum dist/linear-linux-${VERSION}-arm64.AppImage | awk '{print $1}') - - X86_SRI="sha256-$(echo -n "$X86_HASH" | python3 -c "import sys,base64,binascii; print(base64.b64encode(binascii.unhexlify(sys.stdin.read())).decode())")" - ARM_SRI="sha256-$(echo -n "$ARM_HASH" | python3 -c "import sys,base64,binascii; print(base64.b64encode(binascii.unhexlify(sys.stdin.read())).decode())")" + X86_SRI=$(nix-hash --type sha256 --flat --sri dist/linear-linux-${VERSION}-x86_64.AppImage) + ARM_SRI=$(nix-hash --type sha256 --flat --sri dist/linear-linux-${VERSION}-arm64.AppImage) sed -i "s|version = \".*\";|version = \"${VERSION}\";|" flake.nix sed -i "s|hash = \"sha256-.*\"; # x86_64|hash = \"${X86_SRI}\"; # x86_64|" flake.nix sed -i "s|hash = \"sha256-.*\"; # aarch64|hash = \"${ARM_SRI}\"; # aarch64|" flake.nix + grep -q "${X86_SRI}" flake.nix || { echo "::error::Failed to update x86_64 hash"; exit 1; } + grep -q "${ARM_SRI}" flake.nix || { echo "::error::Failed to update aarch64 hash"; exit 1; } + - name: Commit flake.nix update env: VERSION: ${{ steps.bump.outputs.version }} From a9f402048731cc45bb83c99f4c98be308557a786 Mon Sep 17 00:00:00 2001 From: Michael Lyon Date: Fri, 3 Apr 2026 11:15:25 -0600 Subject: [PATCH 3/3] Add Nix result symlink to .gitignore Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index c6bba59..37d4252 100644 --- a/.gitignore +++ b/.gitignore @@ -128,3 +128,6 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +# Nix build output +result