Skip to content

Commit f582734

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

File tree

38 files changed

+461
-74
lines changed

38 files changed

+461
-74
lines changed

.github/workflows/cd.yml

Lines changed: 319 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,319 @@
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+
# Adjust these if your crate name or binary differ
36+
name: "mago"
37+
bin-name: "mago"
38+
version: ${{ steps.crate_metadata.outputs.version }}
39+
maintainer: ${{ steps.crate_metadata.outputs.maintainer }}
40+
homepage: ${{ steps.crate_metadata.outputs.homepage }}
41+
msrv: ${{ steps.crate_metadata.outputs.msrv }}
42+
43+
ensure_cargo_fmt:
44+
name: Ensure 'cargo fmt' has been run
45+
runs-on: ubuntu-20.04
46+
steps:
47+
- uses: dtolnay/rust-toolchain@stable
48+
with:
49+
components: rustfmt
50+
- uses: actions/checkout@v4
51+
- run: cargo fmt -- --check
52+
53+
min_version:
54+
name: Minimum supported rust version
55+
runs-on: ubuntu-20.04
56+
needs: crate_metadata
57+
steps:
58+
- name: Checkout source code
59+
uses: actions/checkout@v4
60+
61+
- name: Install rust toolchain (v${{ needs.crate_metadata.outputs.msrv }})
62+
uses: dtolnay/rust-toolchain@master
63+
with:
64+
toolchain: ${{ needs.crate_metadata.outputs.msrv }}
65+
- name: Run tests
66+
run: cargo test --workspace --locked --all-targets
67+
68+
build:
69+
name: ${{ matrix.job.target }} (${{ matrix.job.os }})
70+
runs-on: ${{ matrix.job.os }}
71+
needs: crate_metadata
72+
strategy:
73+
fail-fast: false
74+
matrix:
75+
job:
76+
# Windows
77+
- { target: i686-pc-windows-msvc, os: windows-2019 }
78+
- { target: x86_64-pc-windows-msvc, os: windows-2019 }
79+
# macOS
80+
- { target: aarch64-apple-darwin, os: macos-15 }
81+
- { target: x86_64-apple-darwin, os: macos-13 }
82+
# Linux with cross
83+
- {
84+
target: aarch64-unknown-linux-gnu,
85+
os: ubuntu-20.04,
86+
use-cross: true,
87+
}
88+
- {
89+
target: arm-unknown-linux-gnueabihf,
90+
os: ubuntu-20.04,
91+
use-cross: true,
92+
}
93+
- {
94+
target: arm-unknown-linux-musleabihf,
95+
os: ubuntu-20.04,
96+
use-cross: true,
97+
}
98+
- {
99+
target: i686-unknown-linux-gnu,
100+
os: ubuntu-20.04,
101+
use-cross: true,
102+
}
103+
- {
104+
target: i686-unknown-linux-musl,
105+
os: ubuntu-20.04,
106+
use-cross: true,
107+
}
108+
- {
109+
target: x86_64-unknown-linux-gnu,
110+
os: ubuntu-20.04,
111+
use-cross: true,
112+
}
113+
- {
114+
target: x86_64-unknown-linux-musl,
115+
os: ubuntu-20.04,
116+
use-cross: true,
117+
}
118+
119+
env:
120+
BUILD_CMD: cargo
121+
122+
steps:
123+
- name: checkout source code
124+
uses: actions/checkout@v4
125+
126+
- name: install prerequisites
127+
shell: bash
128+
run: |
129+
case ${{ matrix.job.target }} in
130+
arm-unknown-linux-*) sudo apt-get -y update && sudo apt-get -y install gcc-arm-linux-gnueabihf ;;
131+
aarch64-unknown-linux-gnu) sudo apt-get -y update && sudo apt-get -y install gcc-aarch64-linux-gnu ;;
132+
esac
133+
134+
- name: install Rust toolchain
135+
uses: dtolnay/rust-toolchain@stable
136+
with:
137+
targets: ${{ matrix.job.target }}
138+
139+
- name: install cross
140+
if: matrix.job.use-cross
141+
uses: taiki-e/install-action@v2
142+
with:
143+
tool: cross
144+
145+
- name: overwrite build command env variable (for cross)
146+
if: matrix.job.use-cross
147+
shell: bash
148+
run: echo "BUILD_CMD=cross" >> $GITHUB_ENV
149+
150+
- name: show version information (Rust, cargo, GCC)
151+
shell: bash
152+
run: |
153+
set -x
154+
gcc --version || true
155+
rustup -V
156+
rustup toolchain list
157+
rustup default
158+
cargo -V
159+
rustc -V
160+
161+
- name: build
162+
shell: bash
163+
run: $BUILD_CMD build --locked --release --target=${{ matrix.job.target }}
164+
165+
- name: set binary name
166+
id: bin
167+
shell: bash
168+
run: |
169+
EXE_suffix=""
170+
case ${{ matrix.job.target }} in
171+
*-pc-windows-*) EXE_suffix=".exe" ;;
172+
esac;
173+
174+
BIN_NAME="${{ needs.crate_metadata.outputs.bin-name }}${EXE_suffix}"
175+
BIN_PATH="target/${{ matrix.job.target }}/release/${BIN_NAME}"
176+
177+
echo "BIN_PATH=${BIN_PATH}" >> $GITHUB_OUTPUT
178+
echo "BIN_NAME=${BIN_NAME}" >> $GITHUB_OUTPUT
179+
180+
- name: set testing options
181+
id: test-options
182+
shell: bash
183+
run: |
184+
unset CARGO_TEST_OPTIONS
185+
case ${{ matrix.job.target }} in
186+
arm-* | aarch64-*)
187+
CARGO_TEST_OPTIONS="--bin ${{ steps.bin.outputs.BIN_NAME }}"
188+
;;
189+
esac;
190+
echo "CARGO_TEST_OPTIONS=${CARGO_TEST_OPTIONS}" >> $GITHUB_OUTPUT
191+
192+
- name: run tests
193+
shell: bash
194+
run: $BUILD_CMD test --locked --target=${{ matrix.job.target }} ${{ steps.test-options.outputs.CARGO_TEST_OPTIONS}}
195+
196+
- name: create tarball
197+
id: package
198+
shell: bash
199+
run: |
200+
PKG_suffix=".tar.gz"
201+
case ${{ matrix.job.target }} in
202+
*-pc-windows-*) PKG_suffix=".zip" ;;
203+
esac;
204+
205+
PKG_BASENAME=${{ needs.crate_metadata.outputs.name }}-v${{ needs.crate_metadata.outputs.version }}-${{ matrix.job.target }}
206+
PKG_NAME=${PKG_BASENAME}${PKG_suffix}
207+
echo "PKG_NAME=${PKG_NAME}" >> $GITHUB_OUTPUT
208+
209+
PKG_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/package"
210+
ARCHIVE_DIR="${PKG_STAGING}/${PKG_BASENAME}/"
211+
mkdir -p "${ARCHIVE_DIR}"
212+
213+
# Binary
214+
cp "${{ steps.bin.outputs.BIN_PATH }}" "$ARCHIVE_DIR"
215+
216+
# Docs and licenses (adjust if not present)
217+
cp "README.md" "LICENSE-MIT" "LICENSE-APACHE" "$ARCHIVE_DIR" || true
218+
219+
pushd "${PKG_STAGING}/" >/dev/null
220+
case ${{ matrix.job.target }} in
221+
*-pc-windows-*)
222+
7z -y a "${PKG_NAME}" "${PKG_BASENAME}/*"
223+
;;
224+
*)
225+
tar czf "${PKG_NAME}" "${PKG_BASENAME}"/*
226+
;;
227+
esac
228+
popd >/dev/null
229+
230+
echo "PKG_PATH=${PKG_STAGING}/${PKG_NAME}" >> $GITHUB_OUTPUT
231+
232+
- name: create Debian package
233+
id: debian-package
234+
shell: bash
235+
if: startsWith(matrix.job.os, 'ubuntu')
236+
run: |
237+
COPYRIGHT_YEARS="2024 - "$(date "+%Y")
238+
DPKG_STAGING="${{ env.CICD_INTERMEDIATES_DIR }}/debian-package"
239+
DPKG_DIR="${DPKG_STAGING}/dpkg"
240+
mkdir -p "${DPKG_DIR}"
241+
242+
DPKG_BASENAME=${{ needs.crate_metadata.outputs.name }}
243+
DPKG_CONFLICTS=${{ needs.crate_metadata.outputs.name }}-musl
244+
case ${{ matrix.job.target }} in *-musl*)
245+
DPKG_BASENAME=${{ needs.crate_metadata.outputs.name }}-musl
246+
DPKG_CONFLICTS=${{ needs.crate_metadata.outputs.name }}
247+
;;
248+
esac;
249+
DPKG_VERSION=${{ needs.crate_metadata.outputs.version }}
250+
251+
unset DPKG_ARCH
252+
case ${{ matrix.job.target }} in
253+
aarch64-*-linux-*) DPKG_ARCH=arm64 ;;
254+
arm-*-linux-*hf) DPKG_ARCH=armhf ;;
255+
i686-*-linux-*) DPKG_ARCH=i686 ;;
256+
x86_64-*-linux-*) DPKG_ARCH=amd64 ;;
257+
*) DPKG_ARCH=notset ;;
258+
esac;
259+
260+
DPKG_NAME="${DPKG_BASENAME}_${DPKG_VERSION}_${DPKG_ARCH}.deb"
261+
echo "DPKG_NAME=${DPKG_NAME}" >> $GITHUB_OUTPUT
262+
263+
# Binary
264+
install -Dm755 "${{ steps.bin.outputs.BIN_PATH }}" "${DPKG_DIR}/usr/bin/${{ steps.bin.outputs.BIN_NAME }}"
265+
266+
# Docs
267+
install -Dm644 "README.md" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/README.md" || true
268+
install -Dm644 "LICENSE-MIT" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/LICENSE-MIT" || true
269+
install -Dm644 "LICENSE-APACHE" "${DPKG_DIR}/usr/share/doc/${DPKG_BASENAME}/LICENSE-APACHE" || true
270+
271+
mkdir -p "${DPKG_DIR}/DEBIAN"
272+
cat > "${DPKG_DIR}/DEBIAN/control" <<EOF
273+
Package: ${DPKG_BASENAME}
274+
Version: ${DPKG_VERSION}
275+
Section: utils
276+
Priority: optional
277+
Maintainer: ${{ needs.crate_metadata.outputs.maintainer }}
278+
Homepage: ${{ needs.crate_metadata.outputs.homepage }}
279+
Architecture: ${DPKG_ARCH}
280+
Provides: ${{ needs.crate_metadata.outputs.name }}
281+
Conflicts: ${DPKG_CONFLICTS}
282+
Description: A command-line benchmarking tool
283+
EOF
284+
285+
DPKG_PATH="${DPKG_STAGING}/${DPKG_NAME}"
286+
echo "DPKG_PATH=${DPKG_PATH}" >> $GITHUB_OUTPUT
287+
288+
# Build dpkg
289+
fakeroot dpkg-deb --build "${DPKG_DIR}" "${DPKG_PATH}"
290+
291+
- name: "Artifact upload: tarball"
292+
uses: actions/upload-artifact@v3
293+
with:
294+
name: ${{ steps.package.outputs.PKG_NAME }}
295+
path: ${{ steps.package.outputs.PKG_PATH }}
296+
297+
- name: "Artifact upload: Debian package"
298+
if: steps.debian-package.outputs.DPKG_NAME
299+
uses: actions/upload-artifact@v3
300+
with:
301+
name: ${{ steps.debian-package.outputs.DPKG_NAME }}
302+
path: ${{ steps.debian-package.outputs.DPKG_PATH }}
303+
304+
- name: check for release
305+
id: is-release
306+
shell: bash
307+
run: |
308+
unset IS_RELEASE ; if [[ $GITHUB_REF =~ ^refs/tags/[0-9].* ]]; then IS_RELEASE='true' ; fi
309+
echo "IS_RELEASE=${IS_RELEASE}" >> $GITHUB_OUTPUT
310+
311+
- name: publish archives and packages
312+
uses: softprops/action-gh-release@v2
313+
if: steps.is-release.outputs.IS_RELEASE
314+
with:
315+
files: |
316+
${{ steps.package.outputs.PKG_PATH }}
317+
${{ steps.debian-package.outputs.DPKG_PATH }}
318+
env:
319+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/snapshot.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# A temporary workflow to create a snapshot tag for the current commit
2+
#
3+
# This workflow is triggered by a cron job that runs once every hour.
4+
#
5+
# TODO(azjezz): Remove this workflow once the snapshot tag is no longer needed,
6+
# i.e. when we have a release tag > 0.0.0.
7+
name: snapshot
8+
9+
on:
10+
schedule:
11+
- cron: "0 * * * *" # runs once every hour, at the top of the hour
12+
13+
jobs:
14+
create_snapshot:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: checkout main
18+
uses: actions/checkout@v4
19+
with:
20+
ref: main
21+
fetch-depth: 0
22+
23+
- name: get latest commit short hash
24+
id: commit
25+
run: |
26+
SHORT_HASH=$(git rev-parse --short HEAD)
27+
echo "SHORT_HASH=${SHORT_HASH}" >> $GITHUB_OUTPUT
28+
29+
- name: check if tag exists
30+
id: check_tag
31+
run: |
32+
TAG_NAME="0.0.0-${{ steps.commit.outputs.SHORT_HASH }}"
33+
# Check if this tag already exists
34+
if git rev-parse -q --verify "refs/tags/$TAG_NAME" >/dev/null; then
35+
echo "exists=true" >> $GITHUB_OUTPUT
36+
else
37+
echo "exists=false" >> $GITHUB_OUTPUT
38+
fi
39+
40+
- name: create and push tag
41+
if: steps.check_tag.outputs.exists == 'false'
42+
run: |
43+
TAG_NAME="0.0.0-${{ steps.commit.outputs.SHORT_HASH }}"
44+
git config user.name "github-actions"
45+
git config user.email "[email protected]"
46+
git tag $TAG_NAME
47+
git push origin $TAG_NAME

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ license = "MIT OR Apache-2.0"
77
description = "A comprehensive suite of PHP tooling inspired by Rust’s approach, providing parsing, linting, formatting, and more through a unified CLI and library interface."
88
homepage = "https://github.com/carthage-software/mago"
99
repository = "https://github.com/carthage-software/mago"
10+
rust-version = "1.82.0"
1011

1112
[workspace]
1213
package.edition = "2021"
@@ -15,6 +16,7 @@ package.license = "MIT OR Apache-2.0"
1516
package.version = "0.0.0"
1617
package.homepage = "https://github.com/carthage-software/mago"
1718
package.repository = "https://github.com/carthage-software/mago"
19+
package.rust-version = "1.82.0"
1820
members = ["crates/*"]
1921

2022
[workspace.lints.clippy]

0 commit comments

Comments
 (0)