Implement comprehensive CI/CD pipeline with best practices

Major improvements:
- Matrix testing across Linux (stable/beta/nightly), Windows, and macOS
- Test with multiple feature combinations (default, yara-scanning, no-default)
- Code coverage reporting with codecov integration
- Security auditing with cargo-audit and dependency review
- Automated release builds for multiple targets
- Performance benchmarking with trend tracking
- Concurrency control to cancel outdated runs
- Rust cache optimization for faster builds
- Documentation generation checks
- Weekly scheduled runs for proactive monitoring

Additional workflows:
- Automated dependency updates via Dependabot
- Weekly Cargo dependency update PRs
- Stale issue and PR management

Project templates:
- Pull request template with checklist
- Bug report issue template
- Feature request issue template
- Codecov configuration with 70% coverage target
This commit is contained in:
pandaadir05
2025-11-21 12:58:06 +02:00
parent fb8d9971d2
commit 226918d9d8
8 changed files with 525 additions and 115 deletions

44
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,44 @@
---
name: Bug Report
about: Create a report to help us improve
title: '[BUG] '
labels: bug
assignees: ''
---
## Bug Description
A clear and concise description of what the bug is.
## To Reproduce
Steps to reproduce the behavior:
1. Run '...'
2. Execute '...'
3. See error
## Expected Behavior
A clear and concise description of what you expected to happen.
## Actual Behavior
What actually happened.
## Environment
- OS: [e.g., Windows 11, Ubuntu 22.04, macOS 14]
- Ghost Version: [e.g., 0.1.0]
- Rust Version: [e.g., 1.75.0]
## Additional Context
Add any other context about the problem here, including:
- Log output
- Stack traces
- Configuration files
- Screenshots (if applicable)
## Possible Solution
If you have ideas on how to fix the bug, please share them here.

View File

@@ -0,0 +1,36 @@
---
name: Feature Request
about: Suggest an idea for this project
title: '[FEATURE] '
labels: enhancement
assignees: ''
---
## Feature Description
A clear and concise description of what feature you'd like to see.
## Problem Statement
Is your feature request related to a problem? Please describe.
Example: I'm always frustrated when [...]
## Proposed Solution
A clear and concise description of what you want to happen.
## Alternatives Considered
A clear and concise description of any alternative solutions or features you've considered.
## Use Case
Describe the use case or scenario where this feature would be useful.
## Implementation Ideas
If you have thoughts on how this could be implemented, please share them here.
## Additional Context
Add any other context, screenshots, or examples about the feature request here.

37
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,37 @@
## Description
Please provide a clear and concise description of what this PR does.
## Type of Change
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring
- [ ] Test improvements
## How Has This Been Tested?
Please describe the tests that you ran to verify your changes.
- [ ] Unit tests
- [ ] Integration tests
- [ ] Manual testing
- [ ] Platform-specific testing (Windows/Linux/macOS)
## Checklist
- [ ] My code follows the project's style guidelines
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published
## Additional Context
Add any other context about the pull request here.

34
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
version: 2
updates:
- package-ecosystem: "cargo"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 10
reviewers:
- "pandaadir05"
labels:
- "dependencies"
- "rust"
commit-message:
prefix: "chore"
include: "scope"
groups:
dev-dependencies:
dependency-type: "development"
update-types:
- "minor"
- "patch"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 5
labels:
- "dependencies"
- "github-actions"
commit-message:
prefix: "ci"

View File

@@ -3,162 +3,322 @@ name: CI/CD Pipeline
on:
push:
branches: [main, develop]
tags:
- 'v*'
pull_request:
branches: [ main ]
branches: [main, develop]
schedule:
- cron: '0 0 * * 0'
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
RUSTFLAGS: -D warnings
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
format:
name: Format Check
check:
name: Code Quality Checks
runs-on: ubuntu-latest
steps:
- name: Checkout
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
components: rustfmt, clippy
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
with:
shared-key: "check"
- name: Check formatting
run: cargo fmt --all -- --check
clippy:
name: Clippy Lints
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run clippy (without YARA)
run: cargo clippy --workspace --all-targets --no-default-features -- -D warnings
- name: Install YARA
run: sudo apt-get update && sudo apt-get install -y libyara-dev
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Run clippy
run: cargo clippy --all-targets -- -A clippy::too_many_arguments -A clippy::type_complexity -A dead_code
- name: Check documentation
run: cargo doc --workspace --no-deps --no-default-features
env:
RUSTDOCFLAGS: -D warnings
test-linux:
name: Test on Linux
name: Test - Linux
runs-on: ubuntu-latest
needs: [format, clippy]
needs: check
strategy:
matrix:
rust: [stable, beta, nightly]
features: ['', '--features yara-scanning', '--no-default-features']
continue-on-error: ${{ matrix.rust == 'nightly' }}
steps:
- name: Checkout
- name: Checkout repository
uses: actions/checkout@v4
- name: Install YARA
run: sudo apt-get update && sudo apt-get install -y libyara-dev
if: contains(matrix.features, 'yara-scanning')
run: |
sudo apt-get update
sudo apt-get install -y libyara-dev pkg-config
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo
uses: actions/cache@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-test-
${{ runner.os }}-cargo-
toolchain: ${{ matrix.rust }}
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
with:
shared-key: "test-linux-${{ matrix.rust }}-${{ matrix.features }}"
- name: Build
run: cargo build --verbose
run: cargo build --workspace --verbose ${{ matrix.features }}
- name: Run tests
run: cargo test --verbose
run: cargo test --workspace --verbose ${{ matrix.features }}
- name: Run doc tests
run: cargo test --workspace --doc ${{ matrix.features }}
test-windows:
name: Test on Windows
name: Test - Windows
runs-on: windows-latest
needs: [format, clippy]
needs: check
strategy:
matrix:
rust: [stable]
features: ['', '--no-default-features']
steps:
- name: Checkout
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo
uses: actions/cache@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
path: |
~\.cargo\registry
~\.cargo\git
target
key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-test-
${{ runner.os }}-cargo-
toolchain: ${{ matrix.rust }}
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
with:
shared-key: "test-windows-${{ matrix.rust }}"
- name: Build
run: cargo build --verbose
continue-on-error: true
run: cargo build --workspace --verbose ${{ matrix.features }}
- name: Run tests
run: cargo test --verbose
continue-on-error: true
run: cargo test --workspace --verbose ${{ matrix.features }}
test-macos:
name: Test on macOS
name: Test - macOS
runs-on: macos-latest
needs: [format, clippy]
needs: check
strategy:
matrix:
rust: [stable]
features: ['', '--no-default-features']
steps:
- name: Checkout
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo
uses: actions/cache@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@master
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-test-
${{ runner.os }}-cargo-
toolchain: ${{ matrix.rust }}
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
with:
shared-key: "test-macos-${{ matrix.rust }}"
- name: Build
run: cargo build --verbose
run: cargo build --workspace --verbose ${{ matrix.features }}
- name: Run tests
run: cargo test --verbose
run: cargo test --workspace --verbose ${{ matrix.features }}
security:
coverage:
name: Code Coverage
runs-on: ubuntu-latest
needs: check
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
- name: Generate coverage
run: cargo llvm-cov --workspace --no-default-features --lcov --output-path lcov.info
- name: Upload to codecov.io
uses: codecov/codecov-action@v4
with:
files: lcov.info
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
security-audit:
name: Security Audit
runs-on: ubuntu-latest
steps:
- name: Checkout
- name: Checkout repository
uses: actions/checkout@v4
- name: Install YARA
run: sudo apt-get update && sudo apt-get install -y libyara-dev
- name: Run cargo-deny
uses: EmbarkStudios/cargo-deny-action@v1
- name: Run cargo-audit
uses: rustsec/audit-check@v1
with:
log-level: warn
command: check
token: ${{ secrets.GITHUB_TOKEN }}
dependency-review:
name: Dependency Review
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Dependency Review
uses: actions/dependency-review-action@v4
build-release:
name: Build Release - ${{ matrix.target }}
runs-on: ${{ matrix.os }}
needs: [test-linux, test-windows, test-macos]
if: startsWith(github.ref, 'refs/tags/v')
strategy:
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-latest
- target: x86_64-unknown-linux-musl
os: ubuntu-latest
- target: x86_64-pc-windows-msvc
os: windows-latest
- target: x86_64-apple-darwin
os: macos-latest
- target: aarch64-apple-darwin
os: macos-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
with:
shared-key: "release-${{ matrix.target }}"
- name: Install musl tools
if: matrix.target == 'x86_64-unknown-linux-musl'
run: sudo apt-get install -y musl-tools
- name: Build release
run: cargo build --release --target ${{ matrix.target }} --no-default-features
- name: Create archive
shell: bash
run: |
VERSION="${GITHUB_REF#refs/tags/v}"
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
ARCHIVE="ghost-${VERSION}-${{ matrix.target }}.zip"
7z a "${ARCHIVE}" ./target/${{ matrix.target }}/release/ghost.exe
else
ARCHIVE="ghost-${VERSION}-${{ matrix.target }}.tar.gz"
tar czf "${ARCHIVE}" -C ./target/${{ matrix.target }}/release ghost
fi
echo "ARCHIVE=${ARCHIVE}" >> $GITHUB_ENV
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: ghost-${{ matrix.target }}
path: ${{ env.ARCHIVE }}
release:
name: Create Release
runs-on: ubuntu-latest
needs: build-release
if: startsWith(github.ref, 'refs/tags/v')
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Create GitHub Release
uses: softprops/action-gh-release@v1
with:
draft: false
prerelease: ${{ contains(github.ref, 'alpha') || contains(github.ref, 'beta') || contains(github.ref, 'rc') }}
generate_release_notes: true
files: artifacts/**/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
benchmark:
name: Performance Benchmarks
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
- name: Run benchmarks
run: cargo bench --no-default-features --no-fail-fast
- name: Store benchmark result
uses: benchmark-action/github-action-benchmark@v1
with:
tool: 'cargo'
output-file-path: target/criterion/output.json
github-token: ${{ secrets.GITHUB_TOKEN }}
auto-push: true
alert-threshold: '200%'
comment-on-alert: true
fail-on-alert: false
all-checks-pass:
name: All Checks Pass
runs-on: ubuntu-latest
needs: [check, test-linux, test-windows, test-macos, coverage, security-audit]
if: always()
steps:
- name: Check job results
run: |
if [[ "${{ needs.check.result }}" != "success" ]] || \
[[ "${{ needs.test-linux.result }}" != "success" ]] || \
[[ "${{ needs.test-windows.result }}" != "success" ]] || \
[[ "${{ needs.test-macos.result }}" != "success" ]] || \
[[ "${{ needs.coverage.result }}" != "success" ]] || \
[[ "${{ needs.security-audit.result }}" != "success" ]]; then
echo "One or more required checks failed"
exit 1
fi
echo "All required checks passed"

36
.github/workflows/dependencies.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: Dependency Management
on:
schedule:
- cron: '0 0 * * 1'
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
update-dependencies:
name: Update Dependencies
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Update dependencies
run: cargo update
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
commit-message: Update Cargo dependencies
title: 'chore: update Cargo dependencies'
body: |
Automated dependency update generated by GitHub Actions.
Please review the changes and ensure all tests pass before merging.
branch: deps/cargo-update
delete-branch: true

36
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name: Issue and PR Cleanup
on:
schedule:
- cron: '0 0 * * *'
workflow_dispatch:
permissions:
issues: write
pull-requests: write
jobs:
stale:
name: Mark Stale Issues and PRs
runs-on: ubuntu-latest
steps:
- name: Mark stale issues and PRs
uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: |
This issue has been automatically marked as stale because it has not had recent activity.
It will be closed in 7 days if no further activity occurs.
If this is still relevant, please add a comment to keep it open.
stale-pr-message: |
This pull request has been automatically marked as stale because it has not had recent activity.
It will be closed in 7 days if no further activity occurs.
If you're still working on this, please add a comment or update the PR.
close-issue-message: 'This issue was closed because it has been stale for 7 days with no activity.'
close-pr-message: 'This PR was closed because it has been stale for 7 days with no activity.'
days-before-stale: 30
days-before-close: 7
stale-issue-label: 'stale'
stale-pr-label: 'stale'
exempt-issue-labels: 'pinned,security,enhancement'
exempt-pr-labels: 'pinned,security'

27
codecov.yml Normal file
View File

@@ -0,0 +1,27 @@
coverage:
precision: 2
round: down
range: 70..100
status:
project:
default:
target: 70%
threshold: 5%
if_ci_failed: error
patch:
default:
target: 80%
threshold: 10%
comment:
layout: "header, diff, flags, components, files, footer"
behavior: default
require_changes: false
require_base: false
require_head: true
ignore:
- "tests/**"
- "benches/**"
- "examples/**"
- "**/*_test.rs"