Fork of daniellemaywood.uk/gleam — Wasm codegen work
11 kB
299 lines
1# SPDX-License-Identifier: Apache-2.0
2# SPDX-FileCopyrightText: 2025 The Gleam contributors
3
4name: "Build Gleam"
5description: "Build Gleam Release"
6inputs:
7 version:
8 description: "Build Version"
9 required: true
10 toolchain:
11 description: "Cargo Toolchain"
12 required: true
13 target:
14 description: "Cargo Installation Target"
15 required: true
16 cargo-tool:
17 description: "Cargo Tool used for Build (for example, `cross`)"
18 required: true
19 expected-binary-architecture:
20 description: "Expected Binary Architecture"
21 required: false
22 default: ""
23 generate-gleam-licences-html:
24 description: "Generate gleam-licences.html"
25 required: false
26 default: "false"
27 azure-tenant-id:
28 description: "Azure Tenant ID for Windows Code Signing"
29 required: false
30 azure-subscription-id:
31 description: "Azure Subscription ID for Windows Code Signing"
32 required: false
33 azure-client-id:
34 description: "Azure Client ID for Windows Code Signing"
35 required: false
36 azure-trusted-signing-account-name:
37 description: "Azure Trusted Signing Account Name for Windows Code Signing"
38 required: false
39 azure-certificate-profile-name:
40 description: "Azure Certificate Profile Name for Windows Code Signing"
41 required: false
42
43outputs:
44 files:
45 description: "Path to all files"
46 value: |
47 ${{ steps.build.outputs.archive }}
48 ${{ steps.build.outputs.archive }}.sha256
49 ${{ steps.build.outputs.archive }}.sha512
50 ${{ steps.build.outputs.archive }}.sigstore
51 ${{ steps.build.outputs.archive }}.sbom.spdx.json
52 ${{ steps.build.outputs.archive }}.sbom.cyclonedx.json
53 ${{ inputs.generate-gleam-licences-html == 'true' && 'gleam-licences.html' || '' }}
54
55runs:
56 using: "composite"
57 steps:
58 - name: Install Rust toolchain
59 uses: actions-rust-lang/setup-rust-toolchain@150fca883cd4034361b621bd4e6a9d34e5143606 # v1.15.4
60 with:
61 toolchain: ${{ inputs.toolchain }}
62 target: ${{ inputs.target }}
63 cache-key: v1-${{ inputs.target }}
64
65 - name: Install Cargo SBoM
66 shell: bash
67 # The `cargo-sbom` version is specified in the next line. Change it to
68 # keep it up-to-date.
69 run: cargo install cargo-sbom@~0.9.1
70
71 - name: Build WASM release binary
72 if: ${{ inputs.target != 'wasm32-unknown-unknown' }}
73 uses: clechasseur/rs-cargo@319e211e9459c5e531afb6d157296765b441572e # v3.0.3
74 with:
75 command: build
76 args: --release --target ${{ inputs.target }}
77 tool: ${{ inputs.cargo-tool }}
78
79 - name: Install wasm-pack
80 if: ${{ inputs.target == 'wasm32-unknown-unknown' }}
81 shell: bash
82 run: curl -sSL https://rustwasm.github.io/wasm-pack/installer/init.sh | sh
83
84 - name: Build WASM release binary
85 if: ${{ inputs.target == 'wasm32-unknown-unknown' }}
86 shell: bash
87 run: wasm-pack build --release --target web compiler-wasm
88
89 - name: Verify binary architecture
90 if: ${{ inputs.expected-binary-architecture }}
91 shell: bash
92 run: |
93 BINARY_PATH="target/${INPUTS_TARGET}/release/gleam"
94 if [[ "${INPUTS_TARGET}" == *"windows"* ]]; then
95 BINARY_PATH="${BINARY_PATH}.exe"
96 fi
97
98 if ! file -b "$BINARY_PATH" | grep -iq "${INPUTS_EXPECTED_BINARY_ARCHITECTURE}"; then
99 echo "error: Architecture mismatch"
100 echo "Expected architecture: '${INPUTS_EXPECTED_BINARY_ARCHITECTURE}'"
101 echo "Found binary type: '$(file -b "$BINARY_PATH")'"
102 exit 1
103 fi
104 echo "ok: Architecture match"
105 env:
106 INPUTS_TARGET: ${{ inputs.target }}
107 INPUTS_EXPECTED_BINARY_ARCHITECTURE: ${{ inputs.expected-binary-architecture }}
108
109 # We use Azure Trusted Signing to sign the Windows binaries.
110 # This is done to ensure that the binaries are trusted and can be
111 # verified by users and systems that require signed code.
112 #
113 # Why is this helpful?
114 # * It provides a way to verify the authenticity and integrity of the
115 # binaries distributed by Gleam.
116 # * It helps prevent tampering with the binaries, ensuring that users
117 # can trust the code they are running.
118 #
119 # For more information, see:
120 # * https://github.com/Azure/trusted-signing-action
121 # * https://azure.microsoft.com/en-us/products/trusted-signing
122 - name: Log in to Azure
123 if: ${{ contains(inputs.target, '-windows-') && inputs.azure-tenant-id && inputs.azure-subscription-id && inputs.azure-client-id && inputs.azure-trusted-signing-account-name && inputs.azure-certificate-profile-name }}
124 uses: azure/login@532459ea530d8321f2fb9bb10d1e0bcf23869a43 # v3.0.0
125 with:
126 client-id: ${{ inputs.azure-client-id }}
127 tenant-id: ${{ inputs.azure-tenant-id }}
128 subscription-id: ${{ inputs.azure-subscription-id }}
129 - name: Windows Code Signing
130 if: ${{ contains(inputs.target, '-windows-') && inputs.azure-tenant-id && inputs.azure-subscription-id && inputs.azure-client-id && inputs.azure-trusted-signing-account-name && inputs.azure-certificate-profile-name }}
131 uses: azure/artifact-signing-action@c7ab2a863ab5f9a846ddb8265964877ef296ee82 # v2.0.0
132 with:
133 endpoint: https://eus.codesigning.azure.net/
134 signing-account-name: ${{ inputs.azure-trusted-signing-account-name }}
135 certificate-profile-name: ${{ inputs.azure-certificate-profile-name }}
136 files: ${{ github.workspace }}\target\${{ inputs.target }}\release\gleam.exe
137 file-digest: SHA256
138 timestamp-rfc3161: http://timestamp.acs.microsoft.com
139 timestamp-digest: SHA256
140 # https://github.com/Azure/artifact-signing-action/issues/146
141 cache-dependencies: false
142
143 - name: Build archive
144 id: build
145 shell: bash
146 run: |
147 case "$TARGET" in
148 *windows*)
149 ARCHIVE="gleam-$VERSION-$TARGET.zip"
150 cp "target/$TARGET/release/gleam.exe" "gleam.exe"
151 7z a "$ARCHIVE" "gleam.exe"
152 rm gleam.exe
153 ;;
154 wasm*)
155 ARCHIVE="gleam-$VERSION-browser.tar.gz"
156 tar -C compiler-wasm/pkg/ -czvf $ARCHIVE .
157 rm -rf compiler-wasm/pkg/
158 ;;
159 *)
160 ARCHIVE="gleam-$VERSION-$TARGET.tar.gz"
161 cp "target/$TARGET/release/gleam" "gleam"
162 tar -czvf "$ARCHIVE" "gleam"
163 rm gleam
164 ;;
165 esac
166
167 echo "archive=$ARCHIVE" >> $GITHUB_OUTPUT
168 env:
169 TARGET: "${{ inputs.target }}"
170 VERSION: "${{ inputs.version }}"
171
172 - name: Ensure binary successfully boots
173 if: ${{ inputs.expected-binary-architecture }}
174 shell: bash
175 run: |
176 case "$TARGET" in
177 *windows*)
178 7z x "$ARCHIVE"
179 ./gleam.exe --version
180 ;;
181 aarch64*)
182 echo "We cannot test an ARM binary on a AMD64 runner"
183 ;;
184 *)
185 tar -xvzf "$ARCHIVE"
186 ./gleam --version
187 ;;
188 esac
189 env:
190 TARGET: "${{ inputs.target }}"
191 ARCHIVE: "${{ steps.build.outputs.archive }}"
192
193 - name: Install Erlang
194 if: ${{ inputs.generate-gleam-licences-html == 'true' }}
195 uses: erlef/setup-beam@fc68ffb90438ef2936bbb3251622353b3dcb2f93 # v1.24.0
196 with:
197 otp-version: "29"
198 rebar3-version: "3"
199
200 - name: Generate licences HTML
201 if: ${{ inputs.generate-gleam-licences-html == 'true' }}
202 shell: bash
203 working-directory: licence-bundler
204 run: |
205 case "$TARGET" in
206 wasm*)
207 echo "error: cannot generate gleam-licences.html from a wasm build"
208 exit 1
209 ;;
210 *windows*)
211 ../target/"$TARGET"/release/gleam.exe run
212 ;;
213 *)
214 ../target/"$TARGET"/release/gleam run
215 ;;
216 esac
217 env:
218 TARGET: "${{ inputs.target }}"
219
220 # By using `cargo-sbom``, we create two formats of Build SBoMs
221 # (SPDX and CycloneDX) for the gleam build.
222 # We store those files alongside the build artifacts on the GitHub Release
223 # page and also use them to create Container SBoMs for Docker images.
224 #
225 # Why is this helpful?
226 # * It gives us and our users complete visibility into which dependencies
227 # and which versions are present in the build / container image.
228 # * The SBoM can be fed into vulnerability scanners so that anyone can check
229 # if any dependencies have known security issues.
230 - name: Generate Build SBoM
231 shell: bash
232 run: |
233 cargo-sbom \
234 --output-format spdx_json_2_3 \
235 > "$ARCHIVE.sbom.spdx.json"
236
237 cargo-sbom \
238 --output-format cyclone_dx_json_1_4 \
239 > "$ARCHIVE.sbom.cyclonedx.json"
240 env:
241 ARCHIVE: "${{ steps.build.outputs.archive }}"
242
243 - name: Hash Build Archive
244 shell: bash
245 run: |
246 openssl dgst -r -sha256 -out "$ARCHIVE".sha256 "$ARCHIVE"
247 openssl dgst -r -sha512 -out "$ARCHIVE".sha512 "$ARCHIVE"
248 env:
249 ARCHIVE: "${{ steps.build.outputs.archive }}"
250
251 # We provide SLSA Provenance for the distribution build. This attests to
252 # where, when, and how the asset or image was built.
253 #
254 # Why is this helpful?
255 # * It provides a record of the exact Git commit (git sha) and GitHub
256 # Actions workflow used to produce a release.
257 # * Users or automated systems can verify that the artifact you’re
258 # downloading was indeed built from the official Gleam repo, on a
259 # particular date, using the correct pipeline and not tampered with later.
260 # * The attestation is published to a transparency log for extra
261 # verification: https://github.com/gleam-lang/gleam/attestations/
262 #
263 # For more information, see:
264 # * https://github.com/actions/attest
265 # * https://github.com/actions/attest-sbom
266 - name: Attest Distribution Assets with SBoM
267 id: attest-sbom
268 uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
269 with:
270 subject-path: |
271 ${{ steps.build.outputs.archive }}
272 ${{ steps.build.outputs.archive }}.sbom.spdx.json
273 ${{ steps.build.outputs.archive }}.sbom.cyclonedx.json
274 sbom-path: "${{ steps.build.outputs.archive }}.sbom.spdx.json"
275
276 # The provenanve information is stored alongside the built artifact with
277 # the `.sigstore` file extension.
278 - name: "Copy SBoM provenance"
279 id: sbom-provenance
280 shell: bash
281 run: |
282 cp "$ATTESTATION" "$ARCHIVE.sigstore"
283 env:
284 ARCHIVE: "${{ steps.build.outputs.archive }}"
285 ATTESTATION: "${{ steps.attest-sbom.outputs.bundle-path }}"
286
287 - name: Upload artifact
288 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
289 with:
290 name: release-${{ matrix.target }}
291 path: |
292 ${{ steps.build.outputs.archive }}
293 ${{ steps.build.outputs.archive }}.sha256
294 ${{ steps.build.outputs.archive }}.sha512
295 ${{ steps.build.outputs.archive }}.sigstore
296 ${{ steps.build.outputs.archive }}.sbom.spdx.json
297 ${{ steps.build.outputs.archive }}.sbom.cyclonedx.json
298 ${{ inputs.generate-gleam-licences-html == 'true' && 'gleam-licences.html' || '' }}
299 overwrite: true