Skip to content

Commit 38db351

Browse files
author
Alex J Lennon
committed
feat: add comprehensive CI/CD pipeline with GitHub Actions
- Add main CI pipeline (.github/workflows/ci.yml) with multi-target builds - Add maintenance workflow for dependency updates and security monitoring - Add Docker development environment with cross-compilation support - Add development helper script (dev.sh) for common tasks - Add Docker Compose setup for development services - Update README with comprehensive CI/CD documentation - Support x86_64, ARM64 glibc, and ARM64 musl targets - Include automated releases, artifact archiving, and checksums
1 parent 15f35fa commit 38db351

7 files changed

Lines changed: 1395 additions & 0 deletions

File tree

.dockerignore

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Docker ignore file for E-ink Power CLI
2+
# Excludes unnecessary files from Docker build context
3+
4+
# Build artifacts
5+
target/
6+
Cargo.lock
7+
8+
# Git
9+
.git/
10+
.gitignore
11+
12+
# IDE and editor files
13+
.vscode/
14+
.idea/
15+
*.swp
16+
*.swo
17+
*~
18+
.DS_Store
19+
20+
# Documentation build
21+
doc/
22+
*.html
23+
24+
# Temporary files
25+
*.tmp
26+
*.temp
27+
.cache/
28+
29+
# Archives and binaries
30+
*.bin
31+
*.exe
32+
*.tar.gz
33+
*.zip
34+
archive/
35+
36+
# Logs
37+
*.log
38+
logs/
39+
reports/
40+
41+
# Development artifacts
42+
release-*/
43+
artifacts/
44+
45+
# OS specific
46+
Thumbs.db
47+
.DS_Store
48+
49+
# Docker
50+
.dockerignore
51+
Dockerfile
52+
docker-compose.yml
53+
54+
# CI/CD
55+
.github/
56+
57+
# Local configuration
58+
.env
59+
.env.local
60+
config.local.*
61+
62+
# Coverage reports
63+
coverage/
64+
*.profraw
65+
66+
# Backup files
67+
*.bak
68+
*.backup

.github/workflows/ci.yml

Lines changed: 312 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
name: CI/CD Pipeline
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
tags: [ 'v*' ]
7+
pull_request:
8+
branches: [ main, develop ]
9+
10+
env:
11+
CARGO_TERM_COLOR: always
12+
RUST_BACKTRACE: 1
13+
14+
jobs:
15+
# ============================================================================
16+
# Code Quality and Testing
17+
# ============================================================================
18+
test:
19+
name: Test and Quality Checks
20+
runs-on: ubuntu-latest
21+
container:
22+
image: rust:1.75-bullseye
23+
options: --user root
24+
25+
steps:
26+
- name: Checkout code
27+
uses: actions/checkout@v4
28+
with:
29+
fetch-depth: 0
30+
31+
- name: Install system dependencies
32+
run: |
33+
apt-get update && apt-get install -y \
34+
build-essential \
35+
pkg-config \
36+
libudev-dev \
37+
libssl-dev \
38+
ca-certificates \
39+
curl
40+
41+
- name: Cache Rust dependencies
42+
uses: actions/cache@v4
43+
with:
44+
path: |
45+
~/.cargo/bin/
46+
~/.cargo/registry/index/
47+
~/.cargo/registry/cache/
48+
~/.cargo/git/db/
49+
target/
50+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
51+
restore-keys: |
52+
${{ runner.os }}-cargo-
53+
54+
- name: Install Rust toolchain
55+
run: |
56+
rustup component add clippy rustfmt
57+
rustup show
58+
59+
- name: Check code formatting
60+
run: cargo fmt --all -- --check
61+
62+
- name: Run Clippy lints
63+
run: cargo clippy --all-targets --all-features -- -D warnings
64+
65+
- name: Run tests
66+
run: cargo test --verbose --all-features
67+
68+
- name: Run integration tests
69+
run: cargo test --test integration_tests --verbose
70+
71+
- name: Check documentation
72+
run: cargo doc --no-deps --document-private-items
73+
74+
# ============================================================================
75+
# Security Audit
76+
# ============================================================================
77+
security:
78+
name: Security Audit
79+
runs-on: ubuntu-latest
80+
container:
81+
image: rust:1.75-bullseye
82+
83+
steps:
84+
- name: Checkout code
85+
uses: actions/checkout@v4
86+
87+
- name: Install cargo-audit
88+
run: cargo install cargo-audit
89+
90+
- name: Run security audit
91+
run: cargo audit
92+
93+
# ============================================================================
94+
# Build Matrix - Multiple Targets
95+
# ============================================================================
96+
build:
97+
name: Build (${{ matrix.target }})
98+
runs-on: ubuntu-latest
99+
needs: [test, security]
100+
container:
101+
image: rust:1.75-bullseye
102+
options: --user root
103+
104+
strategy:
105+
fail-fast: false
106+
matrix:
107+
target:
108+
- x86_64-unknown-linux-gnu
109+
- aarch64-unknown-linux-gnu
110+
- aarch64-unknown-linux-musl
111+
include:
112+
- target: x86_64-unknown-linux-gnu
113+
artifact_name: eink-power-cli-linux-x64
114+
- target: aarch64-unknown-linux-gnu
115+
artifact_name: eink-power-cli-linux-arm64
116+
- target: aarch64-unknown-linux-musl
117+
artifact_name: eink-power-cli-linux-arm64-musl
118+
119+
steps:
120+
- name: Checkout code
121+
uses: actions/checkout@v4
122+
123+
- name: Install system dependencies
124+
run: |
125+
apt-get update && apt-get install -y \
126+
build-essential \
127+
pkg-config \
128+
libudev-dev \
129+
libssl-dev \
130+
gcc-aarch64-linux-gnu \
131+
libc6-dev-arm64-cross
132+
133+
- name: Cache Rust dependencies
134+
uses: actions/cache@v4
135+
with:
136+
path: |
137+
~/.cargo/bin/
138+
~/.cargo/registry/index/
139+
~/.cargo/registry/cache/
140+
~/.cargo/git/db/
141+
target/
142+
key: ${{ runner.os }}-cargo-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}
143+
restore-keys: |
144+
${{ runner.os }}-cargo-${{ matrix.target }}-
145+
${{ runner.os }}-cargo-
146+
147+
- name: Install Rust target
148+
run: |
149+
rustup target add ${{ matrix.target }}
150+
rustup show
151+
152+
- name: Configure cross-compilation environment
153+
if: matrix.target == 'aarch64-unknown-linux-gnu'
154+
run: |
155+
echo "CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
156+
echo "CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++" >> $GITHUB_ENV
157+
echo "AR_aarch64_unknown_linux_gnu=aarch64-linux-gnu-ar" >> $GITHUB_ENV
158+
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
159+
160+
- name: Build release binary
161+
run: |
162+
cargo build --release --target ${{ matrix.target }} --verbose
163+
164+
- name: Strip binary (if not musl)
165+
if: "!contains(matrix.target, 'musl')"
166+
run: |
167+
if [ "${{ matrix.target }}" = "aarch64-unknown-linux-gnu" ]; then
168+
aarch64-linux-gnu-strip target/${{ matrix.target }}/release/eink-power-cli
169+
else
170+
strip target/${{ matrix.target }}/release/eink-power-cli
171+
fi
172+
173+
- name: Create artifact directory
174+
run: |
175+
mkdir -p artifacts
176+
cp target/${{ matrix.target }}/release/eink-power-cli artifacts/${{ matrix.artifact_name }}
177+
178+
# Create build info
179+
cat > artifacts/build-info-${{ matrix.target }}.txt << EOF
180+
Build Information
181+
=================
182+
Target: ${{ matrix.target }}
183+
Commit: ${{ github.sha }}
184+
Branch: ${{ github.ref_name }}
185+
Build Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC')
186+
Rust Version: $(rustc --version)
187+
Cargo Version: $(cargo --version)
188+
EOF
189+
190+
- name: Upload build artifacts
191+
uses: actions/upload-artifact@v4
192+
with:
193+
name: ${{ matrix.artifact_name }}
194+
path: |
195+
artifacts/${{ matrix.artifact_name }}
196+
artifacts/build-info-${{ matrix.target }}.txt
197+
retention-days: 30
198+
199+
- name: Generate checksums
200+
run: |
201+
cd artifacts
202+
sha256sum ${{ matrix.artifact_name }} > ${{ matrix.artifact_name }}.sha256
203+
md5sum ${{ matrix.artifact_name }} > ${{ matrix.artifact_name }}.md5
204+
205+
- name: Upload checksums
206+
uses: actions/upload-artifact@v4
207+
with:
208+
name: ${{ matrix.artifact_name }}-checksums
209+
path: |
210+
artifacts/${{ matrix.artifact_name }}.sha256
211+
artifacts/${{ matrix.artifact_name }}.md5
212+
retention-days: 30
213+
214+
# ============================================================================
215+
# Create Release (on tags)
216+
# ============================================================================
217+
release:
218+
name: Create Release
219+
runs-on: ubuntu-latest
220+
needs: [build]
221+
if: startsWith(github.ref, 'refs/tags/v')
222+
223+
steps:
224+
- name: Checkout code
225+
uses: actions/checkout@v4
226+
227+
- name: Download all artifacts
228+
uses: actions/download-artifact@v4
229+
with:
230+
path: artifacts
231+
232+
- name: Prepare release assets
233+
run: |
234+
mkdir -p release-assets
235+
236+
# Copy all binaries and checksums
237+
find artifacts -name "eink-power-cli-*" -type f | while read file; do
238+
cp "$file" release-assets/
239+
done
240+
241+
# Create combined checksums file
242+
cat artifacts/*/*.sha256 > release-assets/SHA256SUMS
243+
cat artifacts/*/*.md5 > release-assets/MD5SUMS
244+
245+
# Create release notes
246+
cat > release-assets/RELEASE_NOTES.md << EOF
247+
# E-ink Power CLI ${{ github.ref_name }}
248+
249+
## Build Information
250+
- **Commit**: ${{ github.sha }}
251+
- **Build Date**: $(date -u '+%Y-%m-%d %H:%M:%S UTC')
252+
- **Rust Version**: 1.75
253+
254+
## Supported Platforms
255+
- **Linux x86_64**: \`eink-power-cli-linux-x64\`
256+
- **Linux ARM64 (glibc)**: \`eink-power-cli-linux-arm64\`
257+
- **Linux ARM64 (musl)**: \`eink-power-cli-linux-arm64-musl\`
258+
259+
## Installation
260+
1. Download the appropriate binary for your platform
261+
2. Make it executable: \`chmod +x eink-power-cli-*\`
262+
3. Move to your PATH: \`sudo mv eink-power-cli-* /usr/local/bin/eink-power-cli\`
263+
264+
## Verification
265+
Verify the download integrity using the provided checksums:
266+
\`\`\`bash
267+
sha256sum -c SHA256SUMS
268+
\`\`\`
269+
270+
## Target Hardware
271+
- **Board**: i.MX93 Jaguar E-ink
272+
- **Controller**: MCXC143VFM power management controller
273+
- **Interface**: Serial UART (/dev/ttyUSB0 at 115200 baud)
274+
EOF
275+
276+
- name: Create GitHub Release
277+
uses: softprops/action-gh-release@v1
278+
with:
279+
files: release-assets/*
280+
body_path: release-assets/RELEASE_NOTES.md
281+
draft: false
282+
prerelease: ${{ contains(github.ref_name, '-') }}
283+
generate_release_notes: true
284+
env:
285+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
286+
287+
# ============================================================================
288+
# Build Status Summary
289+
# ============================================================================
290+
build-summary:
291+
name: Build Summary
292+
runs-on: ubuntu-latest
293+
needs: [test, security, build]
294+
if: always()
295+
296+
steps:
297+
- name: Build Summary
298+
run: |
299+
echo "## Build Summary" >> $GITHUB_STEP_SUMMARY
300+
echo "" >> $GITHUB_STEP_SUMMARY
301+
echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY
302+
echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY
303+
echo "| Tests & Quality | ${{ needs.test.result }} |" >> $GITHUB_STEP_SUMMARY
304+
echo "| Security Audit | ${{ needs.security.result }} |" >> $GITHUB_STEP_SUMMARY
305+
echo "| Build Matrix | ${{ needs.build.result }} |" >> $GITHUB_STEP_SUMMARY
306+
echo "" >> $GITHUB_STEP_SUMMARY
307+
308+
if [ "${{ needs.test.result }}" = "success" ] && [ "${{ needs.security.result }}" = "success" ] && [ "${{ needs.build.result }}" = "success" ]; then
309+
echo "✅ All builds completed successfully!" >> $GITHUB_STEP_SUMMARY
310+
else
311+
echo "❌ Some builds failed. Check the individual job logs for details." >> $GITHUB_STEP_SUMMARY
312+
fi

0 commit comments

Comments
 (0)