Skip to content

Commit 9d70b7c

Browse files
committed
chore: add ci/cd
Signed-off-by: azjezz <[email protected]>
1 parent cd4530c commit 9d70b7c

File tree

38 files changed

+504
-74
lines changed

38 files changed

+504
-74
lines changed

.github/workflows/cd.yml

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
name: Continuous Deployment
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
push:
7+
branches:
8+
- main
9+
tags:
10+
- "*"
11+
12+
env:
13+
CICD_INTERMEDIATES_DIR: "_cd-intermediates"
14+
15+
jobs:
16+
crate_metadata:
17+
name: extract crate metadata
18+
runs-on: ubuntu-latest
19+
steps:
20+
- uses: actions/checkout@v4
21+
- name: extract crate information
22+
id: crate_metadata
23+
run: |
24+
cargo metadata --no-deps --format-version 1 | jq -r '
25+
.packages[0] |
26+
[
27+
"version=" + .version,
28+
"maintainer=" + (.authors[0] // ""),
29+
"homepage=" + (.homepage // ""),
30+
"msrv=" + (.rust_version // "")
31+
] |
32+
join("\n")
33+
' | tee -a $GITHUB_OUTPUT
34+
outputs:
35+
name: "mago"
36+
bin-name: "mago"
37+
version: ${{ steps.crate_metadata.outputs.version }}
38+
maintainer: ${{ steps.crate_metadata.outputs.maintainer }}
39+
homepage: ${{ steps.crate_metadata.outputs.homepage }}
40+
msrv: ${{ steps.crate_metadata.outputs.msrv }}
41+
42+
ensure_cargo_fmt:
43+
name: Ensure 'cargo fmt' has been run
44+
runs-on: ubuntu-20.04
45+
steps:
46+
- uses: dtolnay/rust-toolchain@stable
47+
with:
48+
components: rustfmt
49+
- uses: actions/checkout@v4
50+
- run: cargo fmt -- --check
51+
52+
min_version:
53+
name: Minimum supported rust version
54+
runs-on: ubuntu-20.04
55+
needs: crate_metadata
56+
steps:
57+
- name: Checkout source code
58+
uses: actions/checkout@v4
59+
60+
- name: Install rust toolchain (v${{ needs.crate_metadata.outputs.msrv }})
61+
uses: dtolnay/rust-toolchain@master
62+
with:
63+
toolchain: ${{ needs.crate_metadata.outputs.msrv }}
64+
- name: Run tests
65+
run: cargo test --workspace --locked --all-targets
66+
67+
build:
68+
name: ${{ matrix.job.target }} (${{ matrix.job.os }})
69+
runs-on: ${{ matrix.job.os }}
70+
needs: crate_metadata
71+
strategy:
72+
fail-fast: false
73+
matrix:
74+
job:
75+
# Windows
76+
- { target: i686-pc-windows-msvc, os: windows-2019 }
77+
- { target: x86_64-pc-windows-msvc, os: windows-2019 }
78+
# macOS
79+
- { target: aarch64-apple-darwin, os: macos-15 }
80+
- { target: x86_64-apple-darwin, os: macos-13 }
81+
# Linux with cross
82+
- {
83+
target: aarch64-unknown-linux-gnu,
84+
os: ubuntu-20.04,
85+
use-cross: true,
86+
}
87+
- {
88+
target: arm-unknown-linux-gnueabihf,
89+
os: ubuntu-20.04,
90+
use-cross: true,
91+
}
92+
- {
93+
target: arm-unknown-linux-musleabihf,
94+
os: ubuntu-20.04,
95+
use-cross: true,
96+
}
97+
- {
98+
target: i686-unknown-linux-gnu,
99+
os: ubuntu-20.04,
100+
use-cross: true,
101+
}
102+
- {
103+
target: i686-unknown-linux-musl,
104+
os: ubuntu-20.04,
105+
use-cross: true,
106+
}
107+
- {
108+
target: x86_64-unknown-linux-gnu,
109+
os: ubuntu-20.04,
110+
use-cross: true,
111+
}
112+
- {
113+
target: x86_64-unknown-linux-musl,
114+
os: ubuntu-20.04,
115+
use-cross: true,
116+
}
117+
118+
env:
119+
BUILD_CMD: cargo
120+
121+
steps:
122+
- name: checkout source code
123+
uses: actions/checkout@v4
124+
125+
- name: Determine tag version
126+
id: version
127+
run: |
128+
CLEAN_TAG=${GITHUB_REF_NAME#v}
129+
echo "CLEAN_TAG=$CLEAN_TAG" >> $GITHUB_OUTPUT
130+
131+
- name: install prerequisites
132+
shell: bash
133+
run: |
134+
case ${{ matrix.job.target }} in
135+
arm-unknown-linux-*) sudo apt-get -y update && sudo apt-get -y install gcc-arm-linux-gnueabihf ;;
136+
aarch64-unknown-linux-gnu) sudo apt-get -y update && sudo apt-get -y install gcc-aarch64-linux-gnu ;;
137+
esac
138+
139+
- name: install Rust toolchain
140+
uses: dtolnay/rust-toolchain@stable
141+
with:
142+
targets: ${{ matrix.job.target }}
143+
144+
- name: install cross
145+
if: matrix.job.use-cross
146+
uses: taiki-e/install-action@v2
147+
with:
148+
tool: cross
149+
150+
- name: overwrite build command env variable (for cross)
151+
if: matrix.job.use-cross
152+
shell: bash
153+
run: echo "BUILD_CMD=cross" >> $GITHUB_ENV
154+
155+
- name: show version information (Rust, cargo, GCC)
156+
shell: bash
157+
run: |
158+
set -x
159+
gcc --version || true
160+
rustup -V
161+
rustup toolchain list
162+
rustup default
163+
cargo -V
164+
rustc -V
165+
166+
- name: build
167+
shell: bash
168+
run: $BUILD_CMD build --locked --release --target=${{ matrix.job.target }}
169+
170+
- name: set binary name
171+
id: bin
172+
shell: bash
173+
run: |
174+
EXE_suffix=""
175+
case ${{ matrix.job.target }} in
176+
*-pc-windows-*) EXE_suffix=".exe" ;;
177+
esac;
178+
179+
BIN_NAME="${{ needs.crate_metadata.outputs.bin-name }}${EXE_suffix}"
180+
BIN_PATH="target/${{ matrix.job.target }}/release/${BIN_NAME}"
181+
182+
echo "BIN_PATH=${BIN_PATH}" >> $GITHUB_OUTPUT
183+
echo "BIN_NAME=${BIN_NAME}" >> $GITHUB_OUTPUT
184+
185+
- name: set testing options
186+
id: test-options
187+
shell: bash
188+
run: |
189+
unset CARGO_TEST_OPTIONS
190+
case ${{ matrix.job.target }} in
191+
arm-* | aarch64-*)
192+
CARGO_TEST_OPTIONS="--bin ${{ steps.bin.outputs.BIN_NAME }}"
193+
;;
194+
esac;
195+
echo "CARGO_TEST_OPTIONS=${CARGO_TEST_OPTIONS}" >> $GITHUB_OUTPUT
196+
197+
- name: run tests
198+
shell: bash
199+
run: $BUILD_CMD test --locked --target=${{ matrix.job.target }} ${{ steps.test-options.outputs.CARGO_TEST_OPTIONS}}
200+
201+
# Build the WASM artifacts only for x86_64-unknown-linux-gnu
202+
- name: Install wasm-pack and build WASM
203+
if: matrix.job.target == 'x86_64-unknown-linux-gnu'
204+
run: |
205+
cargo install wasm-pack --version 0.10.3 --locked
206+
cd crates/wasm
207+
wasm-pack build --target web --no-typescript -d pkg --no-pack --release
208+
cd ../..
209+
WASM_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/wasm"
210+
mkdir -p "${WASM_STAGING}"
211+
cp crates/wasm/pkg/mago_wasm_bg.wasm crates/wasm/pkg/mago_wasm.js "${WASM_STAGING}/"
212+
213+
- name: create tarball (main binary)
214+
id: package
215+
shell: bash
216+
run: |
217+
CLEAN_TAG="${{ steps.version.outputs.CLEAN_TAG }}"
218+
TARGET="${{ matrix.job.target }}"
219+
PKG_SUFFIX=".tar.gz"
220+
case "$TARGET" in
221+
*-pc-windows-msvc) PKG_SUFFIX=".zip" ;;
222+
esac
223+
224+
# Transform target naming:
225+
# 1) remove "unknown-" substrings
226+
# 2) replace "pc-windows-msvc" with "windows"
227+
# 3) replace "x86_64" with "x86-64"
228+
SHORT_TARGET=$(echo "$TARGET" | sed 's/unknown-//g; s/pc-windows-msvc/windows/; s/x86_64/x86-64/')
229+
230+
PKG_NAME="mago-${CLEAN_TAG}-${SHORT_TARGET}${PKG_SUFFIX}"
231+
echo "PKG_NAME=${PKG_NAME}" >> $GITHUB_OUTPUT
232+
233+
PKG_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/package"
234+
ARCHIVE_DIR="${PKG_STAGING}/mago-${CLEAN_TAG}-${SHORT_TARGET}/"
235+
mkdir -p "${ARCHIVE_DIR}"
236+
237+
# Binary
238+
cp "${{ steps.bin.outputs.BIN_PATH }}" "$ARCHIVE_DIR"
239+
240+
# Docs and licenses
241+
cp "README.md" "LICENSE-MIT" "LICENSE-APACHE" "$ARCHIVE_DIR" || true
242+
243+
pushd "${PKG_STAGING}/" >/dev/null
244+
case "$PKG_SUFFIX" in
245+
.zip)
246+
7z -y a "${PKG_NAME}" "mago-${CLEAN_TAG}-${SHORT_TARGET}/*"
247+
;;
248+
.tar.gz)
249+
tar czf "${PKG_NAME}" "mago-${CLEAN_TAG}-${SHORT_TARGET}"/*
250+
;;
251+
esac
252+
popd >/dev/null
253+
254+
echo "PKG_PATH=${PKG_STAGING}/${PKG_NAME}" >> $GITHUB_OUTPUT
255+
256+
- name: create WASM tarball
257+
id: wasm_package
258+
if: matrix.job.target == 'x86_64-unknown-linux-gnu'
259+
shell: bash
260+
run: |
261+
CLEAN_TAG="${{ steps.version.outputs.CLEAN_TAG }}"
262+
# Since WASM is universal, just name it 'mago-{CLEAN_TAG}-wasm.tar.gz'
263+
WASM_PKG_NAME="mago-${CLEAN_TAG}-wasm.tar.gz"
264+
echo "WASM_PKG_NAME=${WASM_PKG_NAME}" >> $GITHUB_OUTPUT
265+
266+
WASM_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/wasm"
267+
pushd "${WASM_STAGING}" >/dev/null
268+
tar czf "${WASM_PKG_NAME}" mago_wasm_bg.wasm mago_wasm.js
269+
popd >/dev/null
270+
271+
echo "WASM_PKG_PATH=${WASM_STAGING}/${WASM_PKG_NAME}" >> $GITHUB_OUTPUT
272+
273+
- name: create Debian package
274+
id: debian-package
275+
shell: bash
276+
if: startsWith(matrix.job.os, 'ubuntu')
277+
run: |
278+
CLEAN_TAG="${{ steps.version.outputs.CLEAN_TAG }}"
279+
TARGET="${{ matrix.job.target }}"
280+
281+
# Derive arch from target:
282+
case "$TARGET" in
283+
*x86_64*) DPKG_ARCH="amd64" ;;
284+
*i686*) DPKG_ARCH="i686" ;;
285+
*aarch64*|*arm64*) DPKG_ARCH="arm64" ;;
286+
*arm*hf*) DPKG_ARCH="armhf" ;;
287+
esac
288+
289+
# Check if musl in target
290+
if [[ "$TARGET" == *"musl"* ]]; then
291+
DPKG_NAME="mago-${CLEAN_TAG}-musl-${DPKG_ARCH}.deb"
292+
else
293+
DPKG_NAME="mago-${CLEAN_TAG}-${DPKG_ARCH}.deb"
294+
fi
295+
296+
echo "DPKG_NAME=${DPKG_NAME}" >> $GITHUB_OUTPUT
297+
298+
DPKG_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/debian-package"
299+
DPKG_DIR="${DPKG_STAGING}/dpkg"
300+
mkdir -p "${DPKG_DIR}"
301+
302+
install -Dm755 "${{ steps.bin.outputs.BIN_PATH }}" "${DPKG_DIR}/usr/bin/${{ steps.bin.outputs.BIN_NAME }}"
303+
304+
install -Dm644 "README.md" "${DPKG_DIR}/usr/share/doc/mago/README.md" || true
305+
install -Dm644 "LICENSE-MIT" "${DPKG_DIR}/usr/share/doc/mago/LICENSE-MIT" || true
306+
install -Dm644 "LICENSE-APACHE" "${DPKG_DIR}/usr/share/doc/mago/LICENSE-APACHE" || true
307+
308+
mkdir -p "${DPKG_DIR}/DEBIAN"
309+
cat > "${DPKG_DIR}/DEBIAN/control" <<EOF
310+
Package: mago
311+
Version: ${CLEAN_TAG}
312+
Section: utils
313+
Priority: optional
314+
Maintainer: ${{ needs.crate_metadata.outputs.maintainer }}
315+
Homepage: ${{ needs.crate_metadata.outputs.homepage }}
316+
Architecture: ${DPKG_ARCH}
317+
Description: A command-line benchmarking tool
318+
EOF
319+
320+
DPKG_PATH="${DPKG_STAGING}/${DPKG_NAME}"
321+
echo "DPKG_PATH=${DPKG_PATH}" >> $GITHUB_OUTPUT
322+
323+
fakeroot dpkg-deb --build "${DPKG_DIR}" "${DPKG_PATH}"
324+
325+
- name: "Artifact upload: tarball"
326+
uses: actions/upload-artifact@v3
327+
with:
328+
name: ${{ steps.package.outputs.PKG_NAME }}
329+
path: ${{ steps.package.outputs.PKG_PATH }}
330+
331+
- name: "Artifact upload: WASM"
332+
if: matrix.job.target == 'x86_64-unknown-linux-gnu' && steps.wasm_package.outputs.WASM_PKG_NAME
333+
uses: actions/upload-artifact@v3
334+
with:
335+
name: ${{ steps.wasm_package.outputs.WASM_PKG_NAME }}
336+
path: ${{ steps.wasm_package.outputs.WASM_PKG_PATH }}
337+
338+
- name: "Artifact upload: Debian package"
339+
uses: actions/upload-artifact@v3
340+
if: steps.debian-package.outputs.DPKG_NAME
341+
with:
342+
name: ${{ steps.debian-package.outputs.DPKG_NAME }}
343+
path: ${{ steps.debian-package.outputs.DPKG_PATH }}
344+
345+
- name: check for release
346+
id: is-release
347+
shell: bash
348+
run: |
349+
unset IS_RELEASE ; if [[ $GITHUB_REF =~ ^refs/tags/[0-9].* ]]; then IS_RELEASE='true' ; fi
350+
echo "IS_RELEASE=${IS_RELEASE}" >> $GITHUB_OUTPUT
351+
352+
- name: publish archives and packages
353+
uses: softprops/action-gh-release@v2
354+
if: steps.is-release.outputs.IS_RELEASE
355+
with:
356+
files: |
357+
${{ steps.package.outputs.PKG_PATH }}
358+
${{ steps.debian-package.outputs.DPKG_PATH }}
359+
${{ steps.wasm_package.outputs.WASM_PKG_PATH }}
360+
env:
361+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)