|
1 | | -defmodule RustlerPrecompiled.ChecksumGenerator do |
2 | | - @moduledoc """ |
3 | | - Generates checksums for precompiled NIFs downloaded from GitHub releases. |
4 | | -
|
5 | | - This script is used during the release process to generate SHA256 checksums |
6 | | - for all platform-specific binaries. The checksums are used by rustler_precompiled |
7 | | - to verify the integrity of downloaded binaries. |
8 | | -
|
9 | | - Usage: |
10 | | - mix run checksum-Elixir.exs |
11 | | - """ |
12 | | - |
13 | | - def generate do |
14 | | - version = Mix.Project.config()[:version] |
15 | | - base_url = "https://github.com/kreuzberg-dev/kreuzberg/releases/download/v#{version}" |
16 | | - |
17 | | - targets = [ |
18 | | - "aarch64-apple-darwin", |
19 | | - "x86_64-apple-darwin", |
20 | | - "x86_64-unknown-linux-gnu", |
21 | | - "x86_64-unknown-linux-musl", |
22 | | - "aarch64-unknown-linux-gnu", |
23 | | - "aarch64-unknown-linux-musl", |
24 | | - "x86_64-pc-windows-msvc", |
25 | | - "x86_64-pc-windows-gnu" |
26 | | - ] |
27 | | - |
28 | | - nif_versions = ["2.16", "2.17"] |
29 | | - |
30 | | - IO.puts("Generating checksums for Kreuzberg v#{version}\n") |
31 | | - IO.puts("Base URL: #{base_url}\n") |
32 | | - |
33 | | - checksums = |
34 | | - for target <- targets, |
35 | | - nif_version <- nif_versions do |
36 | | - ext = if String.contains?(target, "windows"), do: "dll", else: "so" |
37 | | - filename = "libkreuzberg_rustler-v#{version}-nif-#{nif_version}-#{target}.#{ext}.tar.gz" |
38 | | - url = "#{base_url}/#{filename}" |
39 | | - |
40 | | - case download_and_checksum(url, filename) do |
41 | | - {:ok, checksum} -> |
42 | | - IO.puts("✓ #{filename}: #{checksum}") |
43 | | - {filename, checksum} |
44 | | - |
45 | | - {:error, reason} -> |
46 | | - IO.puts("✗ #{filename}: #{reason}") |
47 | | - nil |
48 | | - end |
49 | | - end |
50 | | - |> Enum.reject(&is_nil/1) |
51 | | - |> Map.new() |
52 | | - |
53 | | - if Enum.empty?(checksums) do |
54 | | - IO.puts("\n⚠ Warning: No checksums generated!") |
55 | | - IO.puts("Make sure binaries are published to GitHub releases first.") |
56 | | - else |
57 | | - write_checksum_file(checksums) |
58 | | - IO.puts("\n✓ Checksums written to checksum-Elixir.exs") |
59 | | - IO.puts("Total files: #{map_size(checksums)}") |
60 | | - end |
61 | | - end |
62 | | - |
63 | | - defp download_and_checksum(url, filename) do |
64 | | - cache_dir = Path.join([System.tmp_dir!(), "kreuzberg-checksums"]) |
65 | | - File.mkdir_p!(cache_dir) |
66 | | - local_path = Path.join(cache_dir, filename) |
67 | | - |
68 | | - # Try to download the file |
69 | | - case System.cmd("curl", ["-fsSL", "-o", local_path, url], stderr_to_stdout: true) do |
70 | | - {_, 0} -> |
71 | | - # Calculate SHA256 |
72 | | - case System.cmd("shasum", ["-a", "256", local_path]) do |
73 | | - {output, 0} -> |
74 | | - [checksum | _] = String.split(output) |
75 | | - {:ok, String.trim(checksum)} |
76 | | - |
77 | | - {error, _} -> |
78 | | - {:error, "Failed to calculate checksum: #{error}"} |
79 | | - end |
80 | | - |
81 | | - {error, _} -> |
82 | | - {:error, "Download failed: #{String.slice(error, 0..100)}"} |
83 | | - end |
84 | | - end |
85 | | - |
86 | | - defp write_checksum_file(checksums) do |
87 | | - content = """ |
88 | | - %{ |
89 | | - #{Enum.map_join(checksums, ",\n", fn {filename, hash} -> |
90 | | - " \"#{filename}\" => \"sha256:#{hash}\"" |
91 | | - end)} |
92 | | - } |
93 | | - """ |
94 | | - |
95 | | - File.write!("checksum-Elixir.exs", content) |
96 | | - end |
97 | | -end |
98 | | - |
99 | | -# Run the generator |
100 | | -RustlerPrecompiled.ChecksumGenerator.generate() |
| 1 | +%{ |
| 2 | + # This file is populated by CI during the release process. |
| 3 | + # It contains SHA256 checksums for precompiled NIF binaries. |
| 4 | + # Run `mix rustler_precompiled.download Kreuzberg.Native --all --print` to regenerate. |
| 5 | +} |
0 commit comments