-
Notifications
You must be signed in to change notification settings - Fork 422
Expand file tree
/
Copy pathbuild-cli-release.reusable.yaml
More file actions
424 lines (373 loc) · 16.3 KB
/
build-cli-release.reusable.yaml
File metadata and controls
424 lines (373 loc) · 16.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
name: BAML Release - Build BAML CLI
on:
workflow_call:
inputs:
version:
description: "Release version"
required: false
type: string
package_for_release:
description: "Create archives for release instead of raw binaries"
type: boolean
default: true
required: false
push:
branches:
- sam/mise-protoc-gen-go
- aaron/fix-windows
- aaron/fix-windows-cli-build
env:
MACOSX_DEPLOYMENT_TARGET: "10.13"
# Turbo remote caching
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: gloo
concurrency:
# suffix is important to prevent a concurrency deadlock with the calling workflow
group: ${{ github.workflow }}-${{ github.ref }}-build-cli
cancel-in-progress: true
jobs:
build:
strategy:
fail-fast: false
matrix:
_:
# Always include these targets
- os: ubuntu-22.04
target: x86_64-unknown-linux-gnu
- os: ubuntu-22.04
target: x86_64-unknown-linux-musl
static: true
- os: macos-14
target: x86_64-apple-darwin
- os: macos-14
target: aarch64-apple-darwin
# If you change the windows version, change the rest of the script to match
- os: windows-2022
target: x86_64-pc-windows-msvc
- os: windows-2022
target: aarch64-pc-windows-msvc
# ARM targets (will be conditionally skipped if not needed)
- os: ubuntu-22.04
target: aarch64-unknown-linux-gnu
- os: ubuntu-22.04
target: aarch64-unknown-linux-musl
# Run Linux builds inside a more modern manylinux container (AlmaLinux 8 based)
# with a newer GLIBC version compatible with Node24 used by actions/checkout@v6
# container: ${{ contains(matrix._.os, 'ubuntu') && (contains(matrix._.target, 'x86_64') && 'quay.io/pypa/manylinux_2_28_x86_64' || 'ghcr.io/rust-cross/manylinux_2_28-cross:aarch64') || '' }}
runs-on: ${{ matrix._.os }}
env:
CROSS_VERSION: v0.2.5
CARGO: cargo
TARGET_FLAGS: ${{ matrix._.target != '' && format('--target {0}', matrix._.target) || '' }}
RUST_BACKTRACE: 1
# When CARGO is set to CROSS, TARGET_DIR includes matrix.target.
TARGET_DIR: ./engine/target
steps:
- name: Checkout
uses: actions/checkout@v6
# This sets up protoc-gen-go for non-Windows builds
# and on windows this seems to hang forever since 0.217.0
- name: Setup Tools
if: matrix._.os != 'windows-2022'
uses: ./.github/actions/setup-tools
- name: Setup Rust
uses: ./.github/actions/setup-rust
with:
targets: ${{ matrix._.target }}
enable-cache: false
- name: Setup Go
uses: ./.github/actions/setup-go
- uses: jdx/mise-action@v2
if: matrix._.os != 'windows-2022'
with:
install_args: "protoc-gen-go"
- name: Setup Protoc (Windows)
if: matrix._.os == 'windows-2022'
shell: bash
run: |
# Download protoc directly to avoid rate limiting
PROTOC_VERSION="27.1"
curl -LO "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VERSION}/protoc-${PROTOC_VERSION}-win64.zip"
unzip -q protoc-${PROTOC_VERSION}-win64.zip -d $HOME/.local
echo "$HOME/.local/bin" >> $GITHUB_PATH
rm protoc-${PROTOC_VERSION}-win64.zip
- name: Install protoc-gen-go (Windows)
if: matrix._.os == 'windows-2022'
run: |
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.34.1
echo "$HOME/go/bin" >> $GITHUB_PATH
shell: bash
- name: Test protoc-gen-go availability
id: protoc_gen_go_setup
shell: bash
run: |
echo "Current PATH: $PATH"
echo "Go bin directory contents:"
ls -la $HOME/go/bin/
echo "Which protoc-gen-go:"
PROTOC_GEN_GO_PATH=$(which protoc-gen-go)
echo "Found protoc-gen-go at: $PROTOC_GEN_GO_PATH"
echo "protoc_gen_go_path=$PROTOC_GEN_GO_PATH" >> $GITHUB_OUTPUT
echo "Testing protoc can find protoc-gen-go plugin..."
# Test that protoc can find the go plugin (this will show an error about missing .proto file, but that's expected)
protoc --go_out=/tmp --help | grep -q "go_out" && echo "✅ protoc recognizes --go_out flag" || echo "❌ protoc does not recognize --go_out flag"
- name: Use Cross
if: contains(matrix._.os, 'ubuntu')
run: |
cargo install cross
echo 'CARGO=cross' >> "$GITHUB_ENV"
- name: Set target variables
shell: bash
run: |
echo "TARGET_FLAGS=--target ${{ matrix._.target }}" >> $GITHUB_ENV
echo "TARGET_DIR=./engine/target/${{ matrix._.target }}" >> $GITHUB_ENV
- name: Check GLIBC version
if: contains(matrix._.target, 'linux')
run: |
ldd --version
- name: Show command used for Cargo
shell: bash
run: |
echo "cargo command is: ${{ env.CARGO }}"
echo "target flag is: ${{ env.TARGET_FLAGS }}"
echo "target dir is: ${{ env.TARGET_DIR }}"
# Build the CLI - Always use static-ssl features
- name: Build CLI Binary
# This single step now handles all builds
run: >
${{ env.CARGO }} build --release --bin baml-cli ${{ env.TARGET_FLAGS }}
--features static-ssl
--no-default-features
working-directory: engine
- name: Build CFFI Library (Unix)
if: ${{ !contains(matrix._.os, 'windows') }}
shell: bash
run: |
# Set the correct protoc-gen-go path based on whether we're using cross (Linux) or native build
if [[ "${{ env.CARGO }}" == "cross" ]]; then
# For cross builds (Linux), protoc-gen-go will be installed in the container at /usr/local/bin
export PROTOC_GEN_GO_PATH="/usr/local/bin/protoc-gen-go"
else
# For native builds (macOS), use the host path
export PROTOC_GEN_GO_PATH="${{ steps.protoc_gen_go_setup.outputs.protoc_gen_go_path }}"
fi
echo "Using PROTOC_GEN_GO_PATH: $PROTOC_GEN_GO_PATH"
# We must use PROTOC_GEN_GO_PATH to explicitly tell the build script
# where to find the plugin, as the cross-compile environment is isolated.
export GOPATH=$HOME/go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOROOT:$GOPATH:$GOBIN
${{ env.CARGO }} build --release -p baml_cffi ${{ env.TARGET_FLAGS }}
working-directory: engine
- name: Build CFFI Library (Windows)
if: ${{ contains(matrix._.os, 'windows') }}
shell: bash
run: |
cargo build --release -p baml_cffi ${{ env.TARGET_FLAGS }}
working-directory: engine
# Determine CFFI library name and artifact suffix based on OS
- name: Set CFFI Lib Info
id: cffi_info
shell: bash
run: |
target="${{ matrix._.target }}"
if [[ "${{ matrix._.os }}" == *"windows"* ]]; then
base_name="baml_cffi.dll" # Note: no "lib" prefix on Windows
suffix="windows"
extension="dll"
elif [[ "${{ matrix._.os }}" == *"macos"* ]]; then
base_name="libbaml_cffi.dylib"
suffix="darwin"
extension="dylib"
else # Linux
base_name="libbaml_cffi.so"
suffix="linux"
extension="so"
fi
# Windows DLLs don't use lib prefix
if [[ "${{ matrix._.os }}" == *"windows"* ]]; then
new_name="baml_cffi-${target}.${extension}"
else
new_name="libbaml_cffi-${target}.${extension}"
fi
echo "lib_name=${base_name}" >> $GITHUB_OUTPUT
echo "new_lib_name=${new_name}" >> $GITHUB_OUTPUT
echo "artifact_suffix=${suffix}" >> $GITHUB_OUTPUT
echo "Original Filename: ${base_name}"
echo "New Filename: ${new_name}"
# List target directories to debug build outputs
- name: List target directories
shell: bash
run: |
echo "Listing target/ directory:"
ls -la engine/target/
echo "Listing target/${{ matrix._.target }} directory:"
ls -la engine/target/${{ matrix._.target }}/
echo "Listing target/${{ matrix._.target }}/release directory:"
ls -la engine/target/${{ matrix._.target }}/release/
# Rename the CFFI library file
- name: Rename CFFI Library
shell: bash
run: |
set -x # enable debug printing
release_dir="engine/target/${{ matrix._.target }}/release"
original_file="${release_dir}/${{ steps.cffi_info.outputs.lib_name }}"
new_file="${release_dir}/${{ steps.cffi_info.outputs.new_lib_name }}"
echo "Checking if original file exists: ${original_file}"
if [ ! -f "$original_file" ]; then
echo "Error: CFFI library file not found at ${original_file}"
# List directory contents again for debugging
ls -la "$release_dir"
exit 1
fi
echo "Renaming ${original_file} to ${new_file}"
mv "$original_file" "$new_file"
echo "Checking if new file exists: ${new_file}"
if [ ! -f "$new_file" ]; then
echo "Error: Failed to rename CFFI library file. New file not found at ${new_file}"
ls -la "$release_dir"
exit 1
fi
echo "Rename successful. New listing:"
ls -la "$release_dir"
# Upload the CFFI library for this specific target
- name: Upload CFFI Library Artifact
uses: actions/upload-artifact@v7
with:
# Artifact name uses the target name for uniqueness (as decided previously)
name: libbaml-cffi-${{ matrix._.target }}
# Path now points to the *renamed* library file
path: engine/target/${{ matrix._.target }}/release/${{ steps.cffi_info.outputs.new_lib_name }}
if-no-files-found: error # Fail if the library file doesn't exist
# Determine binary path and archive name
- name: Set binary and archive paths
id: paths
if: inputs.package_for_release
shell: bash
run: |
echo "version: ${{ inputs.version }}"
if [[ "${{ matrix._.os }}" == *"windows"* ]]; then
bin="engine/target/${{ matrix._.target }}/release/baml-cli.exe"
else
bin="engine/target/${{ matrix._.target }}/release/baml-cli"
fi
# Ensure the binary exists before proceeding
if [ ! -f "$bin" ]; then
echo "Binary not found at $bin"
exit 1
fi
echo "bin=$bin" >> $GITHUB_OUTPUT
# Use inputs.version if provided, otherwise default to 'dev' or similar
version_name="${{ inputs.version || 'dev' }}"
archive_base="baml-cli-${version_name}-${{ matrix._.target }}"
echo "archive_base=$archive_base" >> $GITHUB_OUTPUT
# Directory to create for staging files
echo "archive_dir=./${archive_base}" >> $GITHUB_OUTPUT
# Print determined paths for debugging
- name: Print artifact details
if: inputs.package_for_release
shell: bash
run: |
echo "Binary Path: ${{ steps.paths.outputs.bin }}"
echo "Archive Base Name: ${{ steps.paths.outputs.archive_base }}"
echo "Staging Directory: ${{ steps.paths.outputs.archive_dir }}"
# Create archives with proper format
- name: Create archive (Windows)
if: matrix._.os == 'windows-2022'
shell: bash
run: |
set -euo pipefail # Exit immediately if a command exits with a non-zero status, treat unset variables as an error, and catch errors in pipelines.
staging_dir="${{ steps.paths.outputs.archive_dir }}"
archive_base="${{ steps.paths.outputs.archive_base }}"
archive_file="${archive_base}.zip"
checksum_file="${archive_file}.sha256"
echo "Creating staging directory: $staging_dir"
mkdir -p "$staging_dir"
echo "Copying files to staging directory"
cp "${{ steps.paths.outputs.bin }}" "$staging_dir/"
# Use find for robust copy
find . -maxdepth 1 -name 'README.md' -exec cp {} "$staging_dir/" \; || echo "README.md not found"
find . -maxdepth 1 -name 'LICENSE*' -exec cp {} "$staging_dir/" \; || echo "LICENSE* files not found"
echo "Creating archive: $archive_file"
# Use original cd logic for 7z stability, but run in subshell
(
cd "$staging_dir"
7z a "../${archive_file}" .
)
# Check if 7z command succeeded and file exists
if [ ! -f "${archive_file}" ]; then
echo "Archive creation failed or file not found: ${archive_file}"
exit 1
fi
echo "Creating checksum file: $checksum_file"
certutil -hashfile "${archive_file}" SHA256 > "${checksum_file}"
# Check if certutil command succeeded and file exists
if [ ! -f "${checksum_file}" ]; then
echo "Checksum creation failed or file not found: ${checksum_file}"
exit 1
fi
# Add check for empty checksum file
if [ ! -s "${checksum_file}" ]; then
echo "Checksum file is empty: ${checksum_file}"
exit 1
fi
echo "Archive and checksum created successfully:"
ls -l "${archive_base}".*
- name: Create archive (Unix)
if: matrix._.os != 'windows-2022'
shell: bash
run: |
set -euo pipefail # Exit immediately if a command exits with a non-zero status, treat unset variables as an error, and catch errors in pipelines.
staging_dir="${{ steps.paths.outputs.archive_dir }}"
archive_base="${{ steps.paths.outputs.archive_base }}"
archive_file="${archive_base}.tar.gz"
checksum_file="${archive_file}.sha256"
echo "Creating staging directory: $staging_dir"
mkdir -p "$staging_dir"
echo "Copying files to staging directory"
cp "${{ steps.paths.outputs.bin }}" "$staging_dir/"
# Use find for robust copy
find . -maxdepth 1 -name 'README.md' -exec cp {} "$staging_dir/" \; || echo "README.md not found"
find . -maxdepth 1 -name 'LICENSE*' -exec cp {} "$staging_dir/" \; || echo "LICENSE* files not found"
echo "Creating archive: $archive_file"
# Create the archive in the parent directory directly using -C
tar czf "${archive_file}" -C "$staging_dir" .
# Check if tar command succeeded and file exists
if [ ! -f "${archive_file}" ]; then
echo "Archive creation failed or file not found: ${archive_file}"
exit 1
fi
echo "Creating checksum file: $checksum_file"
shasum -a 256 "${archive_file}" > "${checksum_file}"
# Check if shasum command succeeded and file exists
if [ ! -f "${checksum_file}" ]; then
echo "Checksum creation failed or file not found: ${checksum_file}"
exit 1
fi
echo "Archive and checksum created successfully:"
ls -l "${archive_base}".*
# Debug: List root directory contents
- name: List root directory contents
shell: bash
run: |
echo "Listing root directory contents:"
ls -la
echo "Looking for specific archive files:"
find . -name "${{ steps.paths.outputs.archive_base }}.*" -type f
# Upload different artifacts based on mode
- name: Upload CLI artifacts (Release)
if: inputs.package_for_release
uses: actions/upload-artifact@v7
with:
# Artifact name in GitHub Actions UI remains the same
name: baml-cli-${{ matrix._.target }}
path: |
${{ steps.paths.outputs.archive_base }}.*
if-no-files-found: error
- name: Upload CLI artifacts (CI)
if: inputs.package_for_release == false
uses: actions/upload-artifact@v7
with:
name: baml-cli-${{ matrix._.target }}
path: |
${{ matrix._.os == 'windows-2022' && format('engine/target/{0}/release/baml-cli.exe', matrix._.target) || format('engine/target/{0}/release/baml-cli', matrix._.target) }}