Skip to content

Commit 021bdbd

Browse files
authored
Merge pull request #2 from tnull/2026-10-bindings-builds
Add reproducible bindings builds
2 parents 6388e8f + b7d87e4 commit 021bdbd

117 files changed

Lines changed: 25396 additions & 2 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: Pinned Nix
2+
description: Install the shared Nix bootstrap used for checks and candidates
3+
runs:
4+
using: composite
5+
steps:
6+
- uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31
7+
with:
8+
install_url: https://releases.nixos.org/nix/nix-2.35.2/install
9+
extra_nix_config: |
10+
experimental-features = nix-command flakes
11+
accept-flake-config = false
12+
always-allow-substitutes = false
13+
- name: Check Nix bootstrap
14+
shell: bash
15+
run: test "$(nix --version)" = 'nix (Nix) 2.35.2'

‎.github/workflows/candidate.yml‎

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
name: Build candidate
2+
run-name: candidate ${{ inputs.recipe_sha }}
3+
4+
on:
5+
workflow_dispatch:
6+
inputs:
7+
recipe_sha:
8+
description: Full commit of the reviewed bindings build recipe
9+
required: true
10+
type: string
11+
12+
permissions:
13+
contents: read
14+
15+
jobs:
16+
inputs:
17+
runs-on: ubuntu-24.04
18+
timeout-minutes: 5
19+
steps:
20+
- name: Validate dispatch identity and public visibility
21+
env:
22+
RECIPE_SHA: ${{ inputs.recipe_sha }}
23+
shell: bash
24+
run: |
25+
[[ "$RECIPE_SHA" =~ ^[0-9a-f]{40}$ ]]
26+
test "$RECIPE_SHA" = "$GITHUB_SHA"
27+
jq -e '.repository.private == false' "$GITHUB_EVENT_PATH"
28+
29+
build:
30+
needs: inputs
31+
strategy:
32+
fail-fast: false
33+
matrix:
34+
include:
35+
- group: generated
36+
runner: ubuntu-24.04
37+
arch: x86_64
38+
- group: linux-x86_64
39+
runner: ubuntu-24.04
40+
arch: x86_64
41+
- group: linux-aarch64
42+
runner: ubuntu-24.04-arm
43+
arch: aarch64
44+
- group: android
45+
runner: ubuntu-24.04
46+
arch: x86_64
47+
- group: darwin
48+
runner: xcode-27
49+
arch: arm64
50+
runs-on: ${{ matrix.runner }}
51+
timeout-minutes: 180
52+
steps:
53+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
54+
with:
55+
ref: ${{ inputs.recipe_sha }}
56+
persist-credentials: false
57+
- name: Check host architecture
58+
env:
59+
EXPECTED_ARCH: ${{ matrix.arch }}
60+
run: test "$(uname -m)" = "$EXPECTED_ARCH"
61+
- name: Select pinned Apple tools
62+
if: matrix.group == 'darwin'
63+
shell: bash
64+
run: |
65+
sudo xcode-select --switch /Applications/Xcode_27.0.app/Contents/Developer
66+
test "$(xcodebuild -version)" = $'Xcode 27.0\nBuild version 27A266a'
67+
- uses: ./.github/actions/setup-nix
68+
- name: Build and inventory
69+
env:
70+
BUILD_GROUP: ${{ matrix.group }}
71+
shell: bash
72+
run: |
73+
scripts/build.sh --group "$BUILD_GROUP" --output "$RUNNER_TEMP/output"
74+
nix run --no-update-lock-file .#release -- inventory \
75+
--dir "$RUNNER_TEMP/output" --recipe "$GITHUB_SHA" \
76+
--group "$BUILD_GROUP" \
77+
--output "$RUNNER_TEMP/output/$BUILD_GROUP.inventory.json"
78+
git diff --exit-code
79+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
80+
with:
81+
name: build-${{ matrix.group }}
82+
path: ${{ runner.temp }}/output/*
83+
if-no-files-found: error
84+
compression-level: 0
85+
retention-days: 7
86+
overwrite: true
87+
88+
jvm:
89+
needs: build
90+
runs-on: ubuntu-24.04
91+
timeout-minutes: 60
92+
steps:
93+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
94+
with:
95+
ref: ${{ inputs.recipe_sha }}
96+
persist-credentials: false
97+
- uses: ./.github/actions/setup-nix
98+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
99+
with:
100+
pattern: build-*
101+
merge-multiple: true
102+
path: ${{ runner.temp }}/native-inputs
103+
- name: Assemble JVM package with all native payloads
104+
shell: bash
105+
run: |
106+
scripts/build.sh --group jvm --output "$RUNNER_TEMP/output" \
107+
--candidate "$RUNNER_TEMP/native-inputs"
108+
nix run --no-update-lock-file .#release -- inventory \
109+
--dir "$RUNNER_TEMP/output" --recipe "$GITHUB_SHA" --group jvm \
110+
--candidate "$RUNNER_TEMP/native-inputs" \
111+
--output "$RUNNER_TEMP/output/jvm.inventory.json"
112+
git diff --exit-code
113+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
114+
with:
115+
name: build-jvm
116+
path: ${{ runner.temp }}/output/*
117+
if-no-files-found: error
118+
compression-level: 0
119+
retention-days: 7
120+
overwrite: true
121+
122+
jvm-aarch64:
123+
needs: [build, jvm]
124+
runs-on: ubuntu-24.04-arm
125+
timeout-minutes: 60
126+
steps:
127+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
128+
with:
129+
ref: ${{ inputs.recipe_sha }}
130+
persist-credentials: false
131+
- uses: ./.github/actions/setup-nix
132+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
133+
with:
134+
pattern: build-*
135+
merge-multiple: true
136+
path: ${{ runner.temp }}/candidate
137+
- name: Reproduce JVM package and load its native ARM library
138+
shell: bash
139+
run: |
140+
test "$(uname -m)" = aarch64
141+
scripts/build.sh --group jvm --output "$RUNNER_TEMP/output" \
142+
--candidate "$RUNNER_TEMP/candidate"
143+
while IFS= read -r file; do
144+
cmp "$RUNNER_TEMP/output/$file" "$RUNNER_TEMP/candidate/$file"
145+
done < <(jq -r '.groups.jvm[]' release.json)
146+
147+
candidate:
148+
needs: [build, jvm, jvm-aarch64]
149+
runs-on: ubuntu-24.04
150+
timeout-minutes: 30
151+
permissions:
152+
contents: write
153+
steps:
154+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
155+
with:
156+
ref: ${{ inputs.recipe_sha }}
157+
persist-credentials: false
158+
- uses: ./.github/actions/setup-nix
159+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
160+
with:
161+
pattern: build-*
162+
merge-multiple: true
163+
path: ${{ runner.temp }}/candidate
164+
- name: Validate complete candidate
165+
shell: bash
166+
run: |
167+
nix run --no-update-lock-file .#release -- candidate \
168+
--dir "$RUNNER_TEMP/candidate" --recipe "$GITHUB_SHA" \
169+
--run-id "$GITHUB_RUN_ID" --attempt "$GITHUB_RUN_ATTEMPT" \
170+
--output "$RUNNER_TEMP/candidate/candidate.json"
171+
- name: Upload public prerelease for anonymous verification
172+
env:
173+
GH_TOKEN: ${{ github.token }}
174+
shell: bash
175+
run: |
176+
candidate_id="$(jq -er '.id' "$RUNNER_TEMP/candidate/candidate.json")"
177+
manifest_sha256="$(sha256sum "$RUNNER_TEMP/candidate/candidate.json" | cut -d ' ' -f 1)"
178+
cat > "$RUNNER_TEMP/notes.md" <<EOF
179+
Unsigned bindings candidate from recipe $GITHUB_SHA.
180+
181+
Download the assets anonymously and independently rebuild them with
182+
the verification commands in the README at that recipe commit.
183+
SHA-256 of candidate.json: $manifest_sha256
184+
185+
./scripts/verify.sh $candidate_id $manifest_sha256 --repo "$GITHUB_REPOSITORY"
186+
187+
Checksums record transport integrity; independent receipts are
188+
required before a maintainer can publish these bytes locally.
189+
190+
Build: https://github.com/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID
191+
EOF
192+
gh release create "$candidate_id" "$RUNNER_TEMP/candidate/"* \
193+
--repo "$GITHUB_REPOSITORY" --target "$GITHUB_SHA" \
194+
--prerelease --latest=false --title "$candidate_id" \
195+
--notes-file "$RUNNER_TEMP/notes.md"
196+
cat "$RUNNER_TEMP/notes.md" >> "$GITHUB_STEP_SUMMARY"

‎.github/workflows/checks.yml‎

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Checks
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [main]
7+
8+
permissions:
9+
contents: read
10+
11+
concurrency:
12+
group: checks-${{ github.ref }}
13+
cancel-in-progress: true
14+
15+
jobs:
16+
rust-lint:
17+
runs-on: ubuntu-24.04
18+
timeout-minutes: 20
19+
steps:
20+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
21+
with:
22+
persist-credentials: false
23+
- uses: ./.github/actions/setup-nix
24+
- name: Check Rust formatting
25+
run: |
26+
nix develop --no-update-lock-file .#checks --command cargo fmt --all --check
27+
nix develop --no-update-lock-file .#checks --command cargo fmt --manifest-path bindings/uniffi-bindgen/Cargo.toml --all --check
28+
- name: Run Clippy
29+
run: |
30+
CARGO_TARGET_DIR="$(mktemp -d /tmp/cargo-target-bindings-lint-XXXXXX)"
31+
export CARGO_TARGET_DIR
32+
nix develop --no-update-lock-file .#checks --command cargo clippy --locked --workspace --all-targets -- -D warnings
33+
nix develop --no-update-lock-file .#checks --command cargo clippy --locked --manifest-path bindings/uniffi-bindgen/Cargo.toml --all-targets -- -D warnings
34+
checks:
35+
runs-on: ubuntu-24.04
36+
timeout-minutes: 45
37+
steps:
38+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
39+
with:
40+
persist-credentials: false
41+
- uses: ./.github/actions/setup-nix
42+
- name: Lint all tracked shell scripts
43+
run: nix develop --no-update-lock-file .#checks --command bash -euo pipefail -c 'git ls-files -z -- "*.sh" | xargs -0 -r shellcheck'
44+
- name: Verify locked Nix configuration
45+
run: nix flake check --no-update-lock-file
46+
- name: Check release tooling and recipes
47+
shell: bash
48+
run: |
49+
CARGO_TARGET_DIR="$(mktemp -d /tmp/cargo-target-bindings-checks-XXXXXX)"
50+
export CARGO_TARGET_DIR
51+
nix develop --no-update-lock-file .#build --command cargo check --locked --workspace
52+
nix develop --no-update-lock-file .#build --command cargo test --locked --workspace
53+
nix develop --no-update-lock-file .#build --command scripts/build-check.sh
54+
git diff --exit-code

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/target/
2+
/.codex/
23
/result*
34
/.release/
45
/.work/

0 commit comments

Comments
 (0)