Repository navigation
196 lines (179 loc) · 8 KB
/
Copy pathc-api-binaries.yml
File metadata and controls
196 lines (179 loc) · 8 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
# THREAT[TM-INF-027]: build only the immutable SHA exported by tag validation.
# Native C ABI archives, dispatched from the verified release workflow.
# Windows must initialize the Visual Studio environment before using lib.exe/cl.exe.
# Existing tags may be rebuilt only with the tagged or current main workflow definition.
name: Publish C API Binaries
on:
workflow_dispatch:
inputs:
tag:
description: 'Release tag (for example, v0.14.5)'
required: true
type: string
permissions:
contents: read
jobs:
validate-tag:
name: Validate release tag
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.validate.outputs.tag }}
sha: ${{ steps.source.outputs.sha }}
steps:
- name: Validate workflow input
id: validate
env:
INPUT_TAG: ${{ inputs.tag }}
run: |
if [[ ! "$INPUT_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: tag must match vMAJOR.MINOR.PATCH." >&2
exit 1
fi
echo "tag=$INPUT_TAG" >> "$GITHUB_OUTPUT"
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ steps.validate.outputs.tag }}
fetch-depth: 0
- name: Verify tag source
id: source
env:
RELEASE_TAG: ${{ steps.validate.outputs.tag }}
run: |
git fetch --force origin main:refs/remotes/origin/main \
"refs/tags/$RELEASE_TAG:refs/tags/$RELEASE_TAG"
TAG_SHA=$(git rev-list -n 1 "$RELEASE_TAG")
# Validate and build this exact commit even if the tag later moves.
git checkout --detach "$TAG_SHA"
VERSION="${RELEASE_TAG#v}"
CARGO_VERSION=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
if [ "$VERSION" != "$CARGO_VERSION" ]; then
echo "Error: tag $RELEASE_TAG does not match Cargo.toml $CARGO_VERSION" >&2
exit 1
fi
MAIN_SHA=$(git rev-parse origin/main)
if [ "$GITHUB_SHA" != "$TAG_SHA" ] && [ "$GITHUB_SHA" != "$MAIN_SHA" ]; then
echo "Error: workflow ref must be $RELEASE_TAG or current main" >&2
exit 1
fi
if ! git merge-base --is-ancestor "$TAG_SHA" origin/main; then
echo "Error: $RELEASE_TAG is not reachable from origin/main" >&2
exit 1
fi
echo "sha=$TAG_SHA" >> "$GITHUB_OUTPUT"
build:
name: Build C API (${{ matrix.target }})
needs: validate-tag
runs-on: ${{ matrix.runner }}
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- target: aarch64-apple-darwin
runner: macos-latest
library: libbashkit.dylib
archive: bashkit-capi-aarch64-apple-darwin.tar.gz
- target: x86_64-apple-darwin
runner: macos-latest
library: libbashkit.dylib
archive: bashkit-capi-x86_64-apple-darwin.tar.gz
- target: x86_64-unknown-linux-gnu
runner: ubuntu-latest
library: libbashkit.so
archive: bashkit-capi-x86_64-unknown-linux-gnu.tar.gz
- target: aarch64-unknown-linux-gnu
runner: ubuntu-24.04-arm
library: libbashkit.so
archive: bashkit-capi-aarch64-unknown-linux-gnu.tar.gz
- target: x86_64-pc-windows-msvc
runner: windows-latest
library: bashkit.dll
archive: bashkit-capi-x86_64-pc-windows-msvc.zip
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ needs.validate-tag.outputs.sha }}
persist-credentials: false
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@e081816240890017053eacbb1bdf337761dc5582 # 1.95.0
with:
targets: ${{ matrix.target }}
- name: Initialize MSVC tools
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
- name: Cache Rust
uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2
with:
shared-key: "c-api-${{ matrix.target }}"
- name: Build shared library
if: runner.os != 'Windows'
run: ./scripts/build-c-api.sh --release --target ${{ matrix.target }}
- name: Build Windows shared library
if: runner.os == 'Windows'
shell: cmd
run: |
cargo build --release --target ${{ matrix.target }} -p bashkit-capi
copy target\${{ matrix.target }}\release\bashkit_capi.dll target\${{ matrix.target }}\release\bashkit.dll
lib /nologo /def:crates\bashkit-capi\include\bashkit.def /machine:x64 /out:target\${{ matrix.target }}\release\bashkit.lib
- name: Smoke test C consumer
if: matrix.target == 'x86_64-unknown-linux-gnu'
shell: bash
run: |
cc -std=c11 -Wall -Wextra -Werror \
-I crates/bashkit-capi/include \
crates/bashkit-capi/examples/hello.c \
-L target/c-api/release -lbashkit \
-o target/c-api-smoke
OUTPUT=$(LD_LIBRARY_PATH="target/c-api/release" target/c-api-smoke)
[[ "$OUTPUT" =~ ^Hello\ from\ Bashkit!\ User:\ sandbox\ Time:\ [0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$ ]]
- name: Smoke test C consumer on Windows
if: matrix.target == 'x86_64-pc-windows-msvc'
shell: cmd
run: |
cl /nologo /W4 /WX /I crates\bashkit-capi\include crates\bashkit-capi\examples\hello.c target\${{ matrix.target }}\release\bashkit.lib /Fe:target\c-api-smoke.exe
copy target\${{ matrix.target }}\release\bashkit.dll target\bashkit.dll
for /f "delims=" %%i in ('target\c-api-smoke.exe') do set OUTPUT=%%i
echo %OUTPUT% | findstr /b /c:"Hello from Bashkit! User: sandbox Time:" >nul
if errorlevel 1 exit /b 1
- name: Package Unix library
if: runner.os != 'Windows'
shell: bash
run: |
PACKAGE="bashkit-capi-${{ matrix.target }}"
mkdir -p "$PACKAGE/include" "$PACKAGE/examples" "$PACKAGE/lib"
cp crates/bashkit-capi/include/bashkit.h "$PACKAGE/include/"
cp crates/bashkit-capi/examples/*.c "$PACKAGE/examples/"
cp crates/bashkit-capi/README.md "$PACKAGE/"
cp LICENSE NOTICE "$PACKAGE/"
cp -R THIRD_PARTY_LICENSES "$PACKAGE/"
cp "target/c-api/release/${{ matrix.library }}" "$PACKAGE/lib/"
tar czf "${{ matrix.archive }}" "$PACKAGE"
shasum -a 256 "${{ matrix.archive }}" > "${{ matrix.archive }}.sha256"
- name: Package Windows library
if: runner.os == 'Windows'
shell: pwsh
run: |
$package = "bashkit-capi-${{ matrix.target }}"
New-Item -ItemType Directory -Force "$package/include", "$package/examples", "$package/lib"
Copy-Item crates/bashkit-capi/include/bashkit.h "$package/include/"
Copy-Item crates/bashkit-capi/include/bashkit.def "$package/include/"
Copy-Item crates/bashkit-capi/examples/*.c "$package/examples/"
Copy-Item crates/bashkit-capi/README.md "$package/"
Copy-Item LICENSE, NOTICE "$package/"
Copy-Item -Recurse THIRD_PARTY_LICENSES "$package/"
Copy-Item "target/${{ matrix.target }}/release/bashkit.dll" "$package/lib/"
Copy-Item "target/${{ matrix.target }}/release/bashkit.lib" "$package/lib/"
Compress-Archive -Path $package -DestinationPath "${{ matrix.archive }}"
$hash = (Get-FileHash "${{ matrix.archive }}" -Algorithm SHA256).Hash.ToLower()
"$hash ${{ matrix.archive }}" | Out-File -Encoding ascii "${{ matrix.archive }}.sha256"
- name: Upload to release
shell: bash
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ needs.validate-tag.outputs.tag }}
run: |
gh release upload "$RELEASE_TAG" \
"${{ matrix.archive }}" \
"${{ matrix.archive }}.sha256" \
--clobber