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