+78
-21
.github/workflows/cli.yml
+78
-21
.github/workflows/cli.yml
···
11
11
required: true
12
12
type: string
13
13
14
+
permissions:
15
+
contents: write
16
+
14
17
jobs:
15
18
build:
16
19
name: Build CLI Binaries
17
-
runs-on: ubuntu-latest
20
+
strategy:
21
+
matrix:
22
+
include:
23
+
# - target: x86_64-unknown-linux-gnu
24
+
# os: ubuntu-latest
25
+
# package: grain-linux-x86_64
26
+
# artifact: grain-linux-x86_64
27
+
# - target: aarch64-unknown-linux-gnu
28
+
# os: ubuntu-latest
29
+
# package: grain-linux-aarch64
30
+
# artifact: grain-linux-aarch64
31
+
# - target: x86_64-apple-darwin
32
+
# os: macos-13 # Intel Mac
33
+
# package: grain-macos-x86_64
34
+
# artifact: grain-darwin-x86_64
35
+
- target: aarch64-apple-darwin
36
+
os: macos-latest # Apple Silicon Mac
37
+
package: grain-macos-aarch64
38
+
artifact: grain-darwin-aarch64
39
+
# - target: x86_64-pc-windows-gnu
40
+
# os: ubuntu-latest
41
+
# package: grain-windows-x86_64
42
+
# artifact: grain-windows-x86_64.exe
43
+
44
+
runs-on: ${{ matrix.os }}
18
45
defaults:
19
46
run:
20
47
working-directory: cli
48
+
21
49
steps:
22
50
- name: Checkout
23
51
uses: actions/checkout@v4
···
33
61
- name: Check flake
34
62
run: nix flake check
35
63
36
-
- name: Build Darwin aarch64 only (for testing)
64
+
- name: Build ${{ matrix.target }}
65
+
run: nix build .#${{ matrix.package }}
66
+
67
+
- name: Copy binary
37
68
run: |
38
-
echo "Building for macOS aarch64 only..."
39
69
mkdir -p releases
40
-
nix build .#grain-macos-aarch64 -o result-macos-aarch64
41
-
cp result-macos-aarch64/bin/grain releases/grain-darwin-aarch64
70
+
if [ "${{ matrix.target }}" == "x86_64-pc-windows-gnu" ]; then
71
+
cp result/bin/grain.exe releases/${{ matrix.artifact }}
72
+
else
73
+
cp result/bin/grain releases/${{ matrix.artifact }}
74
+
fi
75
+
76
+
- name: Upload artifact
77
+
uses: actions/upload-artifact@v4
78
+
with:
79
+
name: ${{ matrix.artifact }}
80
+
path: cli/releases/${{ matrix.artifact }}
81
+
retention-days: 7
82
+
83
+
release:
84
+
name: Create Release
85
+
needs: build
86
+
runs-on: ubuntu-latest
87
+
steps:
88
+
- name: Checkout
89
+
uses: actions/checkout@v4
90
+
91
+
- name: Download all artifacts
92
+
uses: actions/download-artifact@v4
93
+
with:
94
+
path: artifacts
42
95
43
96
- name: Prepare release assets
44
97
run: |
45
98
mkdir -p release-assets
46
-
cp releases/grain-darwin-aarch64 release-assets/
47
-
cp install.sh release-assets/
99
+
100
+
# Copy all binaries
101
+
for dir in artifacts/*/; do
102
+
for file in "$dir"*; do
103
+
if [ -f "$file" ]; then
104
+
cp "$file" release-assets/
105
+
fi
106
+
done
107
+
done
108
+
109
+
# Copy install script
110
+
cp cli/install.sh release-assets/
48
111
49
112
# Create checksums
50
113
cd release-assets
51
-
sha256sum grain-darwin-aarch64 > checksums.txt
114
+
sha256sum * > checksums.txt
52
115
53
116
# List files for verification
54
117
ls -la
···
70
133
draft: false
71
134
prerelease: false
72
135
files: |
73
-
cli/release-assets/*
136
+
release-assets/*
74
137
body: |
75
-
## Grain CLI ${{ steps.tag.outputs.tag }} (Test Build)
76
-
77
-
**Note: This is a test build with only macOS Apple Silicon support.**
138
+
## Grain CLI ${{ steps.tag.outputs.tag }}
78
139
79
140
### Installation
80
141
···
85
146
86
147
Or download manually:
87
148
149
+
- **Linux x86_64**: `grain-linux-x86_64`
150
+
- **Linux aarch64**: `grain-linux-aarch64`
151
+
- **macOS Intel**: `grain-darwin-x86_64`
88
152
- **macOS Apple Silicon**: `grain-darwin-aarch64`
153
+
- **Windows x86_64**: `grain-windows-x86_64.exe`
89
154
90
155
### Usage
91
156
···
127
192
sleep 30
128
193
129
194
# Test the install script
130
-
curl -L https://github.com/grainsocial/grain/releases/download/${{ steps.tag.outputs.tag }}/grain-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m) -o grain-test || exit 0
131
-
132
-
if [ -f grain-test ]; then
133
-
chmod +x grain-test
134
-
./grain-test --help
135
-
echo "โ
Binary works correctly"
136
-
else
137
-
echo "โ ๏ธ Binary not available yet for this platform"
138
-
fi
195
+
curl -L https://github.com/grainsocial/grain/releases/download/${{ steps.tag.outputs.tag }}/install.sh | bash
+98
cli/flake.lock
+98
cli/flake.lock
···
1
+
{
2
+
"nodes": {
3
+
"crane": {
4
+
"locked": {
5
+
"lastModified": 1754269165,
6
+
"narHash": "sha256-0tcS8FHd4QjbCVoxN9jI+PjHgA4vc/IjkUSp+N3zy0U=",
7
+
"owner": "ipetkov",
8
+
"repo": "crane",
9
+
"rev": "444e81206df3f7d92780680e45858e31d2f07a08",
10
+
"type": "github"
11
+
},
12
+
"original": {
13
+
"owner": "ipetkov",
14
+
"repo": "crane",
15
+
"type": "github"
16
+
}
17
+
},
18
+
"flake-utils": {
19
+
"inputs": {
20
+
"systems": "systems"
21
+
},
22
+
"locked": {
23
+
"lastModified": 1731533236,
24
+
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
25
+
"owner": "numtide",
26
+
"repo": "flake-utils",
27
+
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
28
+
"type": "github"
29
+
},
30
+
"original": {
31
+
"owner": "numtide",
32
+
"repo": "flake-utils",
33
+
"type": "github"
34
+
}
35
+
},
36
+
"nixpkgs": {
37
+
"locked": {
38
+
"lastModified": 1754214453,
39
+
"narHash": "sha256-Q/I2xJn/j1wpkGhWkQnm20nShYnG7TI99foDBpXm1SY=",
40
+
"owner": "NixOS",
41
+
"repo": "nixpkgs",
42
+
"rev": "5b09dc45f24cf32316283e62aec81ffee3c3e376",
43
+
"type": "github"
44
+
},
45
+
"original": {
46
+
"owner": "NixOS",
47
+
"ref": "nixos-unstable",
48
+
"repo": "nixpkgs",
49
+
"type": "github"
50
+
}
51
+
},
52
+
"root": {
53
+
"inputs": {
54
+
"crane": "crane",
55
+
"flake-utils": "flake-utils",
56
+
"nixpkgs": "nixpkgs",
57
+
"rust-overlay": "rust-overlay"
58
+
}
59
+
},
60
+
"rust-overlay": {
61
+
"inputs": {
62
+
"nixpkgs": [
63
+
"nixpkgs"
64
+
]
65
+
},
66
+
"locked": {
67
+
"lastModified": 1754534980,
68
+
"narHash": "sha256-8cAquqasyPRvgJfKVKxz+gQ+SRoRxiHhX91Avtl9Rn8=",
69
+
"owner": "oxalica",
70
+
"repo": "rust-overlay",
71
+
"rev": "89e92794124b93bddb5f8f92485ed924bd179287",
72
+
"type": "github"
73
+
},
74
+
"original": {
75
+
"owner": "oxalica",
76
+
"repo": "rust-overlay",
77
+
"type": "github"
78
+
}
79
+
},
80
+
"systems": {
81
+
"locked": {
82
+
"lastModified": 1681028828,
83
+
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
84
+
"owner": "nix-systems",
85
+
"repo": "default",
86
+
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
87
+
"type": "github"
88
+
},
89
+
"original": {
90
+
"owner": "nix-systems",
91
+
"repo": "default",
92
+
"type": "github"
93
+
}
94
+
}
95
+
},
96
+
"root": "root",
97
+
"version": 7
98
+
}
+45
-32
cli/flake.nix
+45
-32
cli/flake.nix
···
4
4
inputs = {
5
5
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
6
6
flake-utils.url = "github:numtide/flake-utils";
7
+
crane = {
8
+
url = "github:ipetkov/crane";
9
+
inputs.nixpkgs.follows = "nixpkgs";
10
+
};
7
11
rust-overlay = {
8
12
url = "github:oxalica/rust-overlay";
9
13
inputs.nixpkgs.follows = "nixpkgs";
10
14
};
11
15
};
12
16
13
-
outputs = { self, nixpkgs, flake-utils, rust-overlay }:
17
+
outputs = { self, nixpkgs, flake-utils, crane, rust-overlay }:
14
18
flake-utils.lib.eachDefaultSystem (system:
15
19
let
16
20
overlays = [ (import rust-overlay) ];
···
27
31
];
28
32
};
29
33
30
-
# Build function for different targets
31
-
buildGrainCLI = target: pkgs.stdenv.mkDerivation rec {
32
-
pname = "grain-cli-${target}";
33
-
version = "0.1.0";
34
-
35
-
src = ./.;
36
-
37
-
nativeBuildInputs = with pkgs; [
38
-
rustToolchain
39
-
pkg-config
40
-
] ++ pkgs.lib.optionals (target == "x86_64-pc-windows-gnu") [
41
-
pkgs.pkgsCross.mingwW64.stdenv.cc
42
-
];
34
+
craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain;
35
+
36
+
src = craneLib.cleanCargoSource (craneLib.path ./.);
37
+
38
+
commonArgs = {
39
+
inherit src;
40
+
strictDeps = true;
43
41
44
42
buildInputs = with pkgs; [
45
43
openssl
···
48
46
pkgs.darwin.apple_sdk.frameworks.SystemConfiguration
49
47
];
50
48
51
-
buildPhase = ''
52
-
export CARGO_HOME=$TMPDIR/cargo
53
-
export OPENSSL_NO_VENDOR=1
54
-
export PKG_CONFIG_PATH="${pkgs.openssl.dev}/lib/pkgconfig:$PKG_CONFIG_PATH"
55
-
56
-
${if target == "x86_64-pc-windows-gnu" then ''
57
-
export CC_x86_64_pc_windows_gnu="${pkgs.pkgsCross.mingwW64.stdenv.cc}/bin/x86_64-w64-mingw32-gcc"
58
-
export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER="${pkgs.pkgsCross.mingwW64.stdenv.cc}/bin/x86_64-w64-mingw32-gcc"
59
-
export PKG_CONFIG_ALLOW_CROSS=1
60
-
'' else ""}
61
-
62
-
cargo build --release --target ${target}
63
-
'';
64
-
65
-
installPhase = ''
66
-
mkdir -p $out/bin
67
-
cp target/${target}/release/grain${if target == "x86_64-pc-windows-gnu" then ".exe" else ""} $out/bin/
68
-
'';
49
+
nativeBuildInputs = with pkgs; [
50
+
pkg-config
51
+
];
69
52
};
53
+
54
+
# Build dependencies first for caching
55
+
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
56
+
57
+
# Build function for different targets
58
+
buildGrainCLI = target:
59
+
let
60
+
# Only cross-compile if target is different from current system
61
+
isCrossCompiling = target != system;
62
+
in
63
+
if isCrossCompiling then
64
+
# For cross-compilation, use the native build but with target specified
65
+
craneLib.buildPackage (commonArgs // {
66
+
inherit cargoArtifacts;
67
+
CARGO_BUILD_TARGET = target;
68
+
} // pkgs.lib.optionalAttrs (target == "x86_64-pc-windows-gnu") {
69
+
depsBuildBuild = with pkgs; [
70
+
pkgsCross.mingwW64.stdenv.cc
71
+
pkgsCross.mingwW64.windows.pthreads
72
+
];
73
+
nativeBuildInputs = commonArgs.nativeBuildInputs ++ [
74
+
pkgs.pkgsCross.mingwW64.windows.pthreads
75
+
];
76
+
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = "${pkgs.pkgsCross.mingwW64.stdenv.cc}/bin/x86_64-w64-mingw32-gcc";
77
+
})
78
+
else
79
+
# For native builds, don't specify target
80
+
craneLib.buildPackage (commonArgs // {
81
+
inherit cargoArtifacts;
82
+
});
70
83
71
84
in {
72
85
packages = {