diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b5ed8d4..e59bd64 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,15 +5,24 @@ on: branches: ["main"] pull_request: branches: ["main"] + workflow_call: + workflow_dispatch: jobs: build: strategy: matrix: - runner: - - ubuntu-latest - - macos-latest - - windows-latest + target: + - aarch64-apple-darwin + - x86_64-apple-darwin + - x86_64-pc-windows-msvc + include: + - target: aarch64-apple-darwin + runner: macos-14 + - target: x86_64-apple-darwin + runner: macos-latest + - target: x86_64-pc-windows-msvc + runner: windows-latest runs-on: ${{ matrix.runner }} @@ -25,9 +34,48 @@ jobs: uses: dtolnay/rust-toolchain@stable with: toolchain: stable + target: ${{ matrix.target }} - name: Setup Rust cache uses: Swatinem/rust-cache@v2 - name: Build - run: cargo build --release --locked + run: cargo build --release --locked --target ${{ matrix.target }} + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + if-no-files-found: "error" + name: nrr-${{ matrix.target }} + path: | + ./target/${{ matrix.target }}/release/nrr + ./target/${{ matrix.target }}/release/nrr.exe + + linux-static: + strategy: + matrix: + arch: + - x86_64 + - aarch64 + + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@v10 + + - name: Setup Nix cache + uses: DeterminateSystems/magic-nix-cache-action@v4 + + - name: Build + run: nix build --fallback --print-build-logs '.#nrr-static-${{ matrix.arch }}' + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + if-no-files-found: "error" + name: nrr-${{ matrix.arch }}-unknown-linux-musl + path: ./result/bin/nrr diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c30aeb6..5cc5b00 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,9 +5,18 @@ on: tags: ["v*.*.*"] jobs: - publish: + build: + uses: ./.github/workflows/build.yml + + crates-io: + name: Publish to crates.io + needs: build + runs-on: ubuntu-latest + permissions: + contents: read + steps: - name: Checkout repository uses: actions/checkout@v4 @@ -24,3 +33,48 @@ jobs: run: cargo publish env: CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_API_TOKEN }} + + github: + name: Make GitHub release + needs: build + + runs-on: ubuntu-latest + + permissions: + contents: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Download artifacts + id: download + uses: actions/download-artifact@v4 + with: + path: /tmp/artifacts + + - name: Prepare assets + env: + ARTIFACTS: ${{ steps.download.outputs.download-path }} + id: prepare + run: | + asset_path="/tmp/assets" + mkdir -p "$asset_path" + for artifact in "$ARTIFACTS"/*/; do + basename "$artifact" | \ + xargs -I {} zip -jr "$asset_path"/{}.zip "$artifact" + done + echo "asset-path=$asset_path" >> "$GITHUB_OUTPUT" + + - name: Create release + env: + ASSETS: ${{ steps.prepare.outputs.asset-path }} + GH_TOKEN: ${{ github.token }} + TAG: ${{ github.ref_name }} + run: | + gh release create \ + --draft \ + --notes-from-tag \ + --verify-tag \ + "$TAG" \ + "$ASSETS"/*.zip diff --git a/default.nix b/default.nix deleted file mode 100644 index 5bb7fd2..0000000 --- a/default.nix +++ /dev/null @@ -1,63 +0,0 @@ -{ - lib, - stdenv, - pkg-config, - rustPlatform, - CoreFoundation, - Security, - IOKit, - libiconv, - version, - self, - lto ? true, - optimizeSize ? true, - nrxAlias ? true, -}: let - filter = path: type: let - path' = toString path; - base = baseNameOf path'; - - matches = lib.any (suffix: lib.hasSuffix suffix base) [".rs" ".toml"]; - isLock = base == "Cargo.lock"; - in - type == "directory" || matches || isLock; - - filterSource = src: - lib.cleanSourceWith { - src = lib.cleanSource src; - inherit filter; - }; -in - rustPlatform.buildRustPackage { - pname = "nrr"; - inherit version; - - src = filterSource self; - cargoLock.lockFile = ./Cargo.lock; - - RUSTFLAGS = - lib.optionalString lto " -C lto=fat -C embed-bitcode=yes" - + lib.optionalString optimizeSize " -C codegen-units=1 -C strip=symbols -C opt-level=z"; - - buildInputs = lib.optionals stdenv.isDarwin [ - CoreFoundation - Security - IOKit - libiconv - ]; - - nativeBuildInputs = [ - pkg-config - ]; - - postInstall = '' - ${lib.optionalString nrxAlias "ln -s $out/bin/nrr $out/bin/nrx"} - ''; - - meta = with lib; { - description = "Minimal, blazing fast npm scripts runner"; - maintainers = with maintainers; [ryanccn]; - license = licenses.gpl3Only; - mainProgram = "nrr"; - }; - } diff --git a/flake.lock b/flake.lock index 10dfe75..a8bac6c 100644 --- a/flake.lock +++ b/flake.lock @@ -1,12 +1,30 @@ { "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1709780214, - "narHash": "sha256-p4iDKdveHMhfGAlpxmkCtfQO3WRzmlD11aIcThwPqhk=", + "lastModified": 1710765496, + "narHash": "sha256-p7ryWEeQfMwTB6E0wIUd5V2cFTgq+DRRBz2hYGnJZyA=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "f945939fd679284d736112d3d5410eb867f3b31c", + "rev": "e367f7a1fb93137af22a3908f00b9a35e2d286a7", "type": "github" }, "original": { @@ -18,7 +36,47 @@ }, "root": { "inputs": { - "nixpkgs": "nixpkgs" + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1710900660, + "narHash": "sha256-PcHmHQvKIOdvAxlqxZ/DPmUMhUUvfp16pRtyW148u/0=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "549f4db17b5c0c143b1308fcfe9620129c387472", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" } } }, diff --git a/flake.nix b/flake.nix index d514996..771aaa5 100644 --- a/flake.nix +++ b/flake.nix @@ -8,39 +8,43 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs = { + nixpkgs.follows = "nixpkgs"; + flake-utils.follows = "flake-utils"; + }; + }; }; outputs = { self, nixpkgs, + flake-utils, ... - }: let - version = builtins.substring 0 8 self.lastModifiedDate or "dirty"; - - inherit (nixpkgs) lib; - - systems = [ - "x86_64-linux" - "aarch64-linux" - "x86_64-darwin" - "aarch64-darwin" - ]; + } @ inputs: + flake-utils.lib.eachDefaultSystem (system: let + pkgs = import nixpkgs { + inherit system; + config = {}; + overlays = [ + inputs.rust-overlay.overlays.default + self.overlays.default + ]; + }; - forAllSystems = fn: lib.genAttrs systems (s: fn nixpkgs.legacyPackages.${s}); - in { - checks = forAllSystems (pkgs: let - formatter = self.formatter.${pkgs.system}; - in { - fmt = - pkgs.runCommand "check-fmt" {} - '' - ${pkgs.lib.getExe formatter} --check ${self} + inherit (pkgs) lib; + in rec { + checks = { + fmt = pkgs.runCommand "check-fmt" {} '' + ${lib.getExe formatter} --check ${./.} touch $out ''; - }); + }; - devShells = forAllSystems (pkgs: { - default = pkgs.mkShell { + devShells.default = pkgs.mkShell { packages = with pkgs; [ rust-analyzer rustc @@ -51,25 +55,21 @@ RUST_BACKTRACE = 1; RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}"; }; - }); - packages = forAllSystems ( - pkgs: let - scope = lib.makeScope pkgs.newScope; - fn = final: {p = self.overlays.default final pkgs;}; - inherit (scope fn) p; - in - p // {default = p.nrr;} - ); + packages = { + inherit (pkgs) nrr; + default = pkgs.nrr; + }; - formatter = forAllSystems (p: p.alejandra); + legacyPackages = let + staticPkgs = import ./nix/static.nix pkgs; + in (lib.optionalAttrs pkgs.stdenv.isLinux staticPkgs); - overlays.default = _: prev: { - nrr = prev.callPackage ./default.nix { - inherit self version; - inherit (prev.darwin.apple_sdk_11_0.frameworks) CoreFoundation Security; - inherit (prev.darwin) IOKit; + formatter = pkgs.alejandra; + }) + // { + overlays.default = _: prev: { + nrr = prev.callPackage ./nix/package.nix {}; }; }; - }; } diff --git a/garnix.yaml b/garnix.yaml index 8e94189..f9946da 100644 --- a/garnix.yaml +++ b/garnix.yaml @@ -1,6 +1,5 @@ builds: - exclude: [] + exclude: + - "packages.x86_64-darwin.*" include: - - "packages.x86_64-linux.*" - - "packages.aarch64-linux.*" - - "packages.aarch64-darwin.*" + - "packages.*.nrr" diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 0000000..9956750 --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,65 @@ +{ + lib, + stdenv, + rustPlatform, + darwin, + pkg-config, + # this doesn't work with a default toolchain + lto ? false, + optimizeSize ? false, + nrxAlias ? true, +}: +rustPlatform.buildRustPackage rec { + pname = passthru.cargoToml.package.name; + inherit (passthru.cargoToml.package) version; + + __structuredAttrs = true; + + src = lib.fileset.toSource { + root = ../.; + fileset = lib.fileset.unions [ + ../src + ../Cargo.lock + ../Cargo.toml + ]; + }; + + cargoLock = { + lockFile = ../Cargo.lock; + }; + + buildInputs = lib.optionals stdenv.isDarwin (with darwin.apple_sdk.frameworks; [ + CoreFoundation + Security + IOKit + darwin.libiconv + ]); + + nativeBuildInputs = lib.optionals stdenv.isDarwin [ + pkg-config + ]; + + env = + lib.optionalAttrs lto { + CARGO_PROFILE_RELEASE_LTO = "fat"; + } + // lib.optionalAttrs optimizeSize { + CARGO_PROFILE_RELEASE_OPT_LEVEL = "z"; + CARGO_PROFILE_RELEASE_PANIC = "abort"; + CARGO_PROFILE_RELEASE_CODEGEN_UNITS = "1"; + CARGO_PROFILE_RELEASE_STRIP = "symbols"; + }; + + postInstall = lib.optionalString nrxAlias "ln -s $out/bin/nr{r,x}"; + + passthru = { + cargoToml = lib.importTOML ../Cargo.toml; + }; + + meta = with lib; { + description = "Minimal, blazing fast npm scripts runner"; + maintainers = with maintainers; [ryanccn]; + license = licenses.gpl3Only; + mainProgram = "nrr"; + }; +} diff --git a/nix/static.nix b/nix/static.nix new file mode 100644 index 0000000..6ea0164 --- /dev/null +++ b/nix/static.nix @@ -0,0 +1,37 @@ +{ + lib, + pkgsCross, + rust-bin, + nrr, + ... +}: let + targets = { + x86_64 = pkgsCross.musl64.pkgsStatic; + aarch64 = pkgsCross.aarch64-multiplatform.pkgsStatic; + }; + + toolchain = rust-bin.stable.latest.minimal.override { + extensions = ["rust-std"]; + targets = map (pkgs: pkgs.stdenv.hostPlatform.config) (lib.attrValues targets); + }; + + rustPlatforms = + lib.mapAttrs ( + lib.const (pkgs: + pkgs.makeRustPlatform ( + lib.genAttrs ["cargo" "rustc"] (lib.const toolchain) + )) + ) + targets; + + mkPackageWith = rustPlatform: + nrr.override { + inherit rustPlatform; + lto = true; + }; +in + lib.mapAttrs' ( + target: rustPlatform: + lib.nameValuePair "nrr-static-${target}" (mkPackageWith rustPlatform) + ) + rustPlatforms