Add Windows support and improve CI coverage handling #7
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: CI | |
| on: | |
| push: | |
| branches: [main, develop, release/**] | |
| pull_request: | |
| branches: [main, develop] | |
| permissions: | |
| actions: write | |
| contents: read | |
| id-token: write | |
| packages: write | |
| jobs: | |
| test: | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| ruby-version: ["2.7", "3.0", "3.1", "3.2", "3.3"] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - name: Set up Ruby ${{ matrix.ruby-version }} | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: ${{ matrix.ruby-version }} | |
| bundler-cache: true | |
| - name: Install system dependencies (Ubuntu) | |
| if: matrix.os == 'ubuntu-latest' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libssl-dev | |
| - name: Install system dependencies (macOS) | |
| if: matrix.os == 'macos-latest' | |
| run: | | |
| brew install openssl | |
| - name: Install system dependencies (Windows) | |
| if: matrix.os == 'windows-latest' | |
| run: | | |
| # OpenSSL comes pre-installed on GitHub Windows runners | |
| # But we may need to set some paths | |
| echo "OPENSSL_ROOT_DIR=C:\Program Files\OpenSSL-Win64" >> $GITHUB_ENV | |
| shell: bash | |
| - name: Compile extension | |
| run: bundle exec rake compile | |
| - name: Run tests with coverage | |
| run: bundle exec rspec | |
| - name: Upload coverage artifact (Ruby 3.3, Ubuntu only) | |
| if: matrix.ruby-version == '3.3' && matrix.os == 'ubuntu-latest' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-report | |
| path: coverage/ | |
| retention-days: 1 | |
| - name: Run RuboCop (Ruby 3.3, Ubuntu only) | |
| if: matrix.ruby-version == '3.3' && matrix.os == 'ubuntu-latest' | |
| run: bundle exec rubocop || true | |
| continue-on-error: true | |
| coverage: | |
| runs-on: ubuntu-latest | |
| needs: test | |
| if: always() # Run even if some test jobs fail | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Download coverage artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: coverage-report | |
| path: coverage/ | |
| continue-on-error: true # In case no coverage artifact was uploaded | |
| - name: Upload coverage to Qlty | |
| uses: qltysh/qlty-action/coverage@v1 | |
| continue-on-error: true | |
| env: | |
| QLTY_COVERAGE_TOKEN: ${{ secrets.QLTY_COVERAGE_TOKEN }} | |
| with: | |
| oidc: true | |
| files: coverage/coverage.json | |
| - name: Run Qlty code quality checks | |
| run: | | |
| curl -sSfL https://qlty.sh | sh | |
| echo "$HOME/.qlty/bin" >> $GITHUB_PATH | |
| ~/.qlty/bin/qlty check || true | |
| continue-on-error: true | |
| security: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: "3.3" | |
| bundler-cache: true | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libssl-dev | |
| - name: Run bundle audit | |
| run: | | |
| gem install bundler-audit | |
| bundle audit --update || true | |
| continue-on-error: true | |
| build: | |
| runs-on: ubuntu-latest | |
| needs: [test, coverage, security] | |
| if: false # Disabled to prevent accidental gem building | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: "3.3" | |
| bundler-cache: true | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libssl-dev | |
| - name: Modify version for develop branch | |
| if: github.ref == 'refs/heads/develop' | |
| run: | | |
| SHORT_SHA=$(git rev-parse --short HEAD) | |
| sed -i "s/VERSION = '\([^']*\)'/VERSION = '\1.dev.${SHORT_SHA}'/" lib/fastpbkdf2/version.rb | |
| echo "VERSION_SUFFIX=.dev.${SHORT_SHA}" >> $GITHUB_ENV | |
| - name: Modify version for release branch | |
| if: startsWith(github.ref, 'refs/heads/release/') | |
| run: | | |
| SHORT_SHA=$(git rev-parse --short HEAD) | |
| sed -i "s/VERSION = '\([^']*\)'/VERSION = '\1.rc.${SHORT_SHA}'/" lib/fastpbkdf2/version.rb | |
| echo "VERSION_SUFFIX=.rc.${SHORT_SHA}" >> $GITHUB_ENV | |
| - name: Set version suffix for main | |
| if: github.ref == 'refs/heads/main' | |
| run: echo "VERSION_SUFFIX=" >> $GITHUB_ENV | |
| - name: Build gem | |
| run: gem build fastpbkdf2.gemspec | |
| - name: Get gem info | |
| id: gem_info | |
| run: | | |
| GEM_FILE=$(ls *.gem) | |
| GEM_VERSION=$(echo $GEM_FILE | sed 's/fastpbkdf2-\(.*\)\.gem/\1/') | |
| echo "gem_file=$GEM_FILE" >> $GITHUB_OUTPUT | |
| echo "gem_version=$GEM_VERSION" >> $GITHUB_OUTPUT | |
| - name: Store gem artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: gem-${{ steps.gem_info.outputs.gem_version }} | |
| path: "*.gem" | |
| retention-days: 30 | |
| - name: Create build summary | |
| run: | | |
| echo "## Gem Built Successfully 💎" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Version**: ${{ steps.gem_info.outputs.gem_version }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **File**: ${{ steps.gem_info.outputs.gem_file }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Branch**: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- **Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "🚀 **Ready to publish!** Use the 'Manual Release' workflow to publish this gem." >> $GITHUB_STEP_SUMMARY | |
| deploy: | |
| runs-on: ubuntu-latest | |
| needs: build | |
| if: false # Disabled to prevent accidental gem publishing | |
| environment: | |
| name: production | |
| url: https://github.com/TwilightCoders/fastpbkdf2-ruby/packages | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: "3.3" | |
| bundler-cache: true | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libssl-dev | |
| - name: Download gem artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: gem-* | |
| merge-multiple: true | |
| - name: Show deployment details | |
| run: | | |
| echo "## 🚀 Ready to Deploy" >> $GITHUB_STEP_SUMMARY | |
| echo "**Gem**: $(ls *.gem)" >> $GITHUB_STEP_SUMMARY | |
| echo "**Branch**: ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY | |
| echo "**Size**: $(ls -lh *.gem | awk '{print $5}')" >> $GITHUB_STEP_SUMMARY | |
| - name: Publish to GitHub Packages | |
| id: publish | |
| continue-on-error: true | |
| run: | | |
| mkdir -p ~/.gem | |
| cat << EOF > ~/.gem/credentials | |
| --- | |
| :github: Bearer ${{ secrets.GITHUB_TOKEN }} | |
| EOF | |
| chmod 600 ~/.gem/credentials | |
| # Try to publish, capturing output | |
| if gem push --key github --host https://rubygems.pkg.github.com/TwilightCoders *.gem 2>&1 | tee publish_output.log; then | |
| echo "success=true" >> $GITHUB_OUTPUT | |
| echo "message=Successfully published $(ls *.gem)" >> $GITHUB_OUTPUT | |
| else | |
| # Check if it's a version conflict (common scenario) | |
| if grep -q "already exists" publish_output.log || grep -q "Repushing of gem versions is not allowed" publish_output.log; then | |
| echo "success=false" >> $GITHUB_OUTPUT | |
| echo "message=Version $(ls *.gem) already exists in GitHub Packages - no action needed" >> $GITHUB_OUTPUT | |
| else | |
| echo "success=false" >> $GITHUB_OUTPUT | |
| echo "message=Failed to publish: $(cat publish_output.log)" >> $GITHUB_OUTPUT | |
| fi | |
| fi | |
| - name: Deployment summary | |
| run: | | |
| if [ "${{ steps.publish.outputs.success }}" == "true" ]; then | |
| echo "## ✅ Deployment Complete" >> $GITHUB_STEP_SUMMARY | |
| echo "${{ steps.publish.outputs.message }}" >> $GITHUB_STEP_SUMMARY | |
| else | |
| echo "## ⚠️ Deployment Skipped" >> $GITHUB_STEP_SUMMARY | |
| echo "${{ steps.publish.outputs.message }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "This is typically expected when the version already exists." >> $GITHUB_STEP_SUMMARY | |
| fi |