Release #11
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| push: | |
| tags: | |
| - 'v*.*.*' | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: 'Tag to release' | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| env: | |
| CARGO_TERM_COLOR: always | |
| RUST_BACKTRACE: 1 | |
| CARGO_NET_RETRY: 10 | |
| CARGO_HTTP_TIMEOUT: 120 | |
| RUSTUP_USE_CURL: 1 | |
| jobs: | |
| create-release: | |
| name: Create Release | |
| runs-on: ubuntu-latest | |
| outputs: | |
| upload_url: ${{ steps.create_release.outputs.upload_url }} | |
| release_id: ${{ steps.create_release.outputs.id }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get version from tag | |
| id: get_version | |
| run: | | |
| if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then | |
| VERSION="${{ github.event.inputs.tag }}" | |
| else | |
| VERSION=${GITHUB_REF#refs/tags/} | |
| fi | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "version_number=${VERSION#v}" >> $GITHUB_OUTPUT | |
| - name: Generate changelog | |
| id: changelog | |
| run: | | |
| if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then | |
| TAG="${{ github.event.inputs.tag }}" | |
| else | |
| TAG=${GITHUB_REF#refs/tags/} | |
| fi | |
| # Get previous tag | |
| PREV_TAG=$(git describe --tags --abbrev=0 $TAG^ 2>/dev/null || echo "") | |
| if [ -n "$PREV_TAG" ]; then | |
| echo "## Changes since $PREV_TAG" > changelog.md | |
| echo "" >> changelog.md | |
| git log --pretty=format:"- %s (%h)" $PREV_TAG..$TAG >> changelog.md | |
| else | |
| echo "## Initial Release" > changelog.md | |
| echo "" >> changelog.md | |
| echo "First release of ClamReef Agent" >> changelog.md | |
| fi | |
| echo "" >> changelog.md | |
| echo "## Features" >> changelog.md | |
| echo "- 🔒 Comprehensive endpoint protection monitoring" >> changelog.md | |
| echo "- 📊 Rich host metrics with system information" >> changelog.md | |
| echo "- ⏱️ Performance analytics and scan duration tracking" >> changelog.md | |
| echo "- 🗓️ Automated ClamAV scanning with cron schedules" >> changelog.md | |
| echo "- 📡 OpenTelemetry integration for observability" >> changelog.md | |
| echo "- 🌐 Cross-platform support (Linux ARM64, macOS ARM64)" >> changelog.md | |
| echo "" >> changelog.md | |
| echo "## Installation" >> changelog.md | |
| echo '```bash' >> changelog.md | |
| echo "# Download and install" >> changelog.md | |
| echo "curl -LO https://github.com/${{ github.repository }}/releases/download/$TAG/clamreef-agent-\$(uname -s)-\$(uname -m)" >> changelog.md | |
| echo "chmod +x clamreef-agent-*" >> changelog.md | |
| echo "sudo mv clamreef-agent-* /usr/local/bin/clamreef-agent" >> changelog.md | |
| echo '```' >> changelog.md | |
| - name: Create Release | |
| id: create_release | |
| uses: actions/create-release@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| tag_name: ${{ steps.get_version.outputs.version }} | |
| release_name: ClamReef Agent ${{ steps.get_version.outputs.version }} | |
| body_path: changelog.md | |
| draft: false | |
| prerelease: ${{ contains(steps.get_version.outputs.version, 'alpha') || contains(steps.get_version.outputs.version, 'beta') || contains(steps.get_version.outputs.version, 'rc') }} | |
| build: | |
| name: Build Release Binaries | |
| needs: create-release | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| matrix: | |
| include: | |
| # Linux aarch64/arm64 target | |
| - os: ubuntu-latest | |
| target: aarch64-unknown-linux-gnu | |
| artifact_name: clamreef-agent | |
| asset_name: clamreef-agent-Linux-aarch64 | |
| cross: true | |
| # macOS aarch64/arm64 target (Apple Silicon) | |
| - os: macos-latest | |
| target: aarch64-apple-darwin | |
| artifact_name: clamreef-agent | |
| asset_name: clamreef-agent-Darwin-aarch64 | |
| cross: false | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Install Rust toolchain with retry | |
| env: | |
| RUSTUP_USE_CURL: 1 | |
| RUSTUP_DIST_SERVER: https://static.rust-lang.org | |
| CARGO_NET_RETRY: 10 | |
| CARGO_HTTP_TIMEOUT: 120 | |
| run: | | |
| set -e | |
| echo "Installing Rust toolchain for target: ${{ matrix.target }}" | |
| max_retries=5 | |
| retry_count=0 | |
| retry_delay=10 | |
| while [ $retry_count -lt $max_retries ]; do | |
| retry_count=$((retry_count + 1)) | |
| echo "Attempt $retry_count of $max_retries..." | |
| # Clean up any partial downloads | |
| rm -rf ~/.rustup/tmp ~/.rustup/downloads 2>/dev/null || true | |
| # Try to install rustup with increased timeout and retries | |
| if curl --proto '=https' --tlsv1.2 --retry 5 --retry-delay 5 \ | |
| --retry-connrefused --max-time 300 -sSf https://sh.rustup.rs | \ | |
| sh -s -- -y --default-toolchain stable --profile minimal \ | |
| --target ${{ matrix.target }} --no-modify-path; then | |
| # Export PATH for subsequent steps | |
| echo "$HOME/.cargo/bin" >> $GITHUB_PATH | |
| export PATH="$HOME/.cargo/bin:$PATH" | |
| # Verify installation | |
| rustc --version | |
| cargo --version | |
| rustup target list --installed | |
| echo "Rust toolchain installed successfully!" | |
| break | |
| else | |
| echo "Attempt $retry_count failed" | |
| if [ $retry_count -eq $max_retries ]; then | |
| echo "Failed to install Rust after $max_retries attempts" | |
| echo "Trying alternative installation method..." | |
| # Alternative: Use GitHub's pre-installed Rust and add target | |
| if command -v rustup >/dev/null 2>&1; then | |
| echo "Using pre-installed rustup" | |
| rustup default stable | |
| rustup target add ${{ matrix.target }} || true | |
| rustc --version | |
| cargo --version | |
| exit 0 | |
| else | |
| exit 1 | |
| fi | |
| fi | |
| # Exponential backoff | |
| sleep $((retry_delay * retry_count)) | |
| fi | |
| done | |
| - name: Setup Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| key: ${{ matrix.os }}-${{ matrix.target }} | |
| continue-on-error: true | |
| - name: Install cross-compilation dependencies (Linux) | |
| if: matrix.cross && matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y gcc-multilib | |
| cargo install cross --git https://github.com/cross-rs/cross | |
| - name: Install additional dependencies (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' && !matrix.cross | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libssl-dev pkg-config | |
| - name: Install additional dependencies (macOS) | |
| if: matrix.os == 'macos-latest' | |
| run: | | |
| # No additional dependencies needed for macOS | |
| - name: Build binary (native) | |
| if: "!matrix.cross" | |
| run: | | |
| cargo build --release --target ${{ matrix.target }} --all-features | |
| - name: Build binary (cross-compiled) | |
| if: matrix.cross | |
| run: | | |
| cross build --release --target ${{ matrix.target }} --all-features | |
| - name: Strip binary | |
| if: "!matrix.cross" | |
| run: | | |
| strip target/${{ matrix.target }}/release/${{ matrix.artifact_name }} | |
| - name: Strip binary (cross-compiled) | |
| if: matrix.cross | |
| run: | | |
| # For cross-compiled binaries, we need the appropriate strip tool | |
| # or we can skip stripping since release profile already optimizes size | |
| echo "Skipping strip for cross-compiled target: ${{ matrix.target }}" | |
| ls -lh target/${{ matrix.target }}/release/${{ matrix.artifact_name }} | |
| - name: Create archive | |
| run: | | |
| cd target/${{ matrix.target }}/release | |
| tar czf ../../../${{ matrix.asset_name }}.tar.gz ${{ matrix.artifact_name }} | |
| cd ../../.. | |
| - name: Upload binary to release | |
| uses: actions/upload-release-asset@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| upload_url: ${{ needs.create-release.outputs.upload_url }} | |
| asset_path: ${{ matrix.asset_name }}.tar.gz | |
| asset_name: ${{ matrix.asset_name }}.tar.gz | |
| asset_content_type: application/gzip | |
| - name: Upload standalone binary | |
| uses: actions/upload-release-asset@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| upload_url: ${{ needs.create-release.outputs.upload_url }} | |
| asset_path: target/${{ matrix.target }}/release/${{ matrix.artifact_name }} | |
| asset_name: ${{ matrix.asset_name }} | |
| asset_content_type: application/octet-stream | |
| checksums: | |
| name: Generate Checksums | |
| needs: [create-release, build] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Get release info | |
| id: get_release | |
| run: | | |
| echo "Getting release info for tag: ${{ github.ref }}" | |
| # Release assets will be available after build jobs complete | |
| - name: Download release assets and generate checksums | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # Get the release ID | |
| RELEASE_ID="${{ needs.create-release.outputs.release_id }}" | |
| # Get release assets | |
| ASSETS=$(gh api repos/${{ github.repository }}/releases/$RELEASE_ID/assets --jq '.[].browser_download_url') | |
| # Download each asset and generate checksums | |
| for asset_url in $ASSETS; do | |
| echo "Downloading: $asset_url" | |
| asset_name=$(basename "$asset_url") | |
| curl -L -H "Authorization: token $GITHUB_TOKEN" -o "$asset_name" "$asset_url" | |
| if [[ "$asset_name" == *.tar.gz ]] || [[ "$asset_name" != *.* ]]; then | |
| sha256sum "$asset_name" >> checksums.txt | |
| sha512sum "$asset_name" >> checksums.txt | |
| fi | |
| done | |
| - name: Upload checksums | |
| uses: actions/upload-release-asset@v1 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| with: | |
| upload_url: ${{ needs.create-release.outputs.upload_url }} | |
| asset_path: checksums.txt | |
| asset_name: checksums.txt | |
| asset_content_type: text/plain |