-
-
Notifications
You must be signed in to change notification settings - Fork 20
Add automated release pipeline with prerelease support #47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
233cad3
a1e89e1
4ea43c4
0c0c935
eba52c8
fd75af4
96a34a4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| # Release Process | ||
|
|
||
| This repository uses an automated release pipeline via GitHub Actions. | ||
|
|
||
| ## How It Works | ||
|
|
||
| The release workflow (`.github/workflows/release.yml`) is triggered when a version tag is pushed to the repository. The workflow: | ||
|
|
||
| 1. **Runs tests** - Ensures all tests pass before releasing | ||
| 2. **Builds the gem** - Creates the `.gem` package using `bundle exec rake build` | ||
| 3. **Generates checksums** - Creates SHA-512 checksums for the gem package | ||
| 4. **Creates GitHub Release** - Publishes a release on GitHub with the gem and checksums as artifacts | ||
| 5. **Publishes to RubyGems** - Automatically pushes the gem to [rubygems.org](https://rubygems.org) | ||
|
|
||
| ## Triggering a Release | ||
|
|
||
| ### For Stable Releases | ||
|
|
||
| 1. Update the version in `lib/cyclonedx/ruby/version.rb` | ||
| 2. Update `CHANGELOG.md` with the changes | ||
| 3. Commit the changes: `git commit -am "🔖 Prepare release v1.2.0"` | ||
| 4. Create and push a tag: `git tag v1.2.0 && git push origin v1.2.0` | ||
|
|
||
| ### For Prereleases | ||
|
|
||
| Prereleases follow the same process but use a tag with a prerelease identifier: | ||
|
|
||
| - Alpha: `git tag v1.3.0-alpha.1 && git push origin v1.3.0-alpha.1` | ||
| - Beta: `git tag v1.3.0-beta.1 && git push origin v1.3.0-beta.1` | ||
| - Release Candidate: `git tag v1.3.0-rc.1 && git push origin v1.3.0-rc.1` | ||
|
|
||
| Prereleases are automatically detected by the workflow and marked as "prerelease" on GitHub. | ||
|
|
||
| ## Version Tag Format | ||
|
|
||
| - **Stable releases**: `v<MAJOR>.<MINOR>.<PATCH>` (e.g., `v1.2.0`) | ||
| - **Prereleases**: `v<MAJOR>.<MINOR>.<PATCH>-<PRERELEASE>` (e.g., `v1.3.0-alpha.1`) | ||
|
|
||
| The version in the tag must match the version in `lib/cyclonedx/ruby/version.rb`. | ||
|
|
||
| ## Required Secrets | ||
|
|
||
| The workflow requires the following GitHub repository secret to be configured: | ||
|
|
||
| ### `RUBYGEMS_API_KEY` | ||
|
|
||
| This is your RubyGems API key for publishing gems. To set it up: | ||
|
|
||
| 1. Generate an API key on [rubygems.org](https://rubygems.org/profile/edit): | ||
| - Go to your profile → Edit Profile → API Keys | ||
| - Create a new API key with "Push rubygem" scope | ||
|
|
||
| 2. Add it to GitHub repository secrets: | ||
| - Go to repository Settings → Secrets and variables → Actions | ||
| - Click "New repository secret" | ||
| - Name: `RUBYGEMS_API_KEY` | ||
| - Value: Your RubyGems API key | ||
| - Click "Add secret" | ||
|
|
||
| **Note**: The `publish` job only runs on the official repository (`CycloneDX/cyclonedx-ruby-gem`) to prevent accidental publishes from forks. | ||
|
|
||
| ## Release Artifacts | ||
|
|
||
| Each release includes the following artifacts: | ||
|
|
||
| 1. **Gem Package** (`cyclonedx-ruby-<version>.gem`) - The built Ruby gem | ||
| 2. **SHA-512 Checksum** (`cyclonedx-ruby-<version>.gem.sha512`) - Checksum for verification | ||
|
|
||
| These artifacts are attached to the GitHub Release and can be downloaded for verification. | ||
|
|
||
| ## Monitoring Releases | ||
|
|
||
| - **GitHub Actions**: Check the [Actions tab](https://github.com/CycloneDX/cyclonedx-ruby-gem/actions) for workflow runs | ||
| - **GitHub Releases**: View all releases in the [Releases section](https://github.com/CycloneDX/cyclonedx-ruby-gem/releases) | ||
| - **RubyGems**: Check [rubygems.org/gems/cyclonedx-ruby](https://rubygems.org/gems/cyclonedx-ruby) for published versions | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### Release workflow fails on tests | ||
|
|
||
| The workflow will not create a release if tests fail. Fix the failing tests and push a new commit, then create the tag again. | ||
|
|
||
| ### Gem fails to publish to RubyGems | ||
|
|
||
| Check that: | ||
| - The `RUBYGEMS_API_KEY` secret is set correctly | ||
| - The API key has the "Push rubygem" permission | ||
| - The gem version doesn't already exist on RubyGems (versions cannot be overwritten) | ||
|
|
||
| ### Prerelease not detected correctly | ||
|
|
||
| The workflow detects prereleases by checking if the version matches the exact pattern `MAJOR.MINOR.PATCH` (e.g., `1.2.3`). Any version that includes additional characters after the patch version (e.g., `1.2.3-alpha.1`, `1.2.3.rc1`, `1.2.3-beta`) is automatically marked as a prerelease. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,168 @@ | ||
| name: Release | ||
|
|
||
| run-name: Release ${{ github.ref_name }} | ||
|
|
||
| on: | ||
| push: | ||
| tags: | ||
| - 'v*' | ||
|
|
||
| permissions: {} | ||
|
|
||
| jobs: | ||
| validate: | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| version: ${{ steps.version.outputs.VERSION }} | ||
| prerelease: ${{ steps.prerelease.outputs.PRERELEASE }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Ruby | ||
| uses: ruby/setup-ruby@v1 | ||
| with: | ||
| ruby-version: '3.3' | ||
| bundler-cache: false | ||
|
|
||
| - name: Install dependencies | ||
| run: bundle install --jobs 4 --retry 3 | ||
|
|
||
| - name: Extract version from tag | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @copilot move the version and determination prerelease detection to an own job
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved version extraction and prerelease detection to dedicated |
||
| id: version | ||
| run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT | ||
|
|
||
| - name: Verify version matches code | ||
| run: | | ||
| TAG_VERSION="${{ steps.version.outputs.VERSION }}" | ||
| CODE_VERSION=$(bundle exec ruby -r ./lib/cyclonedx/ruby/version.rb -e 'puts Cyclonedx::Ruby::VERSION') | ||
| echo "Tag version: $TAG_VERSION" | ||
| echo "Code version: $CODE_VERSION" | ||
| if [ "$TAG_VERSION" != "$CODE_VERSION" ]; then | ||
| echo "::error::Version mismatch! Tag is v$TAG_VERSION but code version is $CODE_VERSION" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Determine if prerelease | ||
| id: prerelease | ||
| run: | | ||
| VERSION="${{ steps.version.outputs.VERSION }}" | ||
| # A version is a prerelease if it contains anything after the patch version | ||
| # e.g., 1.2.3-alpha.1, 1.2.3.rc1, 1.2.3-beta are all prereleases | ||
| # but 1.2.3 is a stable release | ||
| if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | ||
| echo "PRERELEASE=false" >> $GITHUB_OUTPUT | ||
| echo "Detected stable release: $VERSION" | ||
| else | ||
| echo "PRERELEASE=true" >> $GITHUB_OUTPUT | ||
| echo "Detected prerelease: $VERSION" | ||
| fi | ||
|
|
||
| test: | ||
| needs: validate | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Ruby | ||
| uses: ruby/setup-ruby@v1 | ||
| with: | ||
| ruby-version: '3.3' | ||
| bundler-cache: false | ||
|
|
||
| - name: Install dependencies | ||
| run: bundle install --jobs 4 --retry 3 | ||
|
|
||
| - name: Run tests | ||
jkowalleck marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| run: bundle exec rake test | ||
|
|
||
| build: | ||
| needs: test | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Ruby | ||
| uses: ruby/setup-ruby@v1 | ||
| with: | ||
| ruby-version: '3.3' | ||
| bundler-cache: false | ||
|
|
||
| - name: Install dependencies | ||
| run: bundle install --jobs 4 --retry 3 | ||
|
|
||
| - name: Build gem | ||
| run: bundle exec rake build | ||
|
|
||
| - name: Generate checksum | ||
| run: bundle exec rake build:checksum | ||
|
|
||
| - name: List build artifacts | ||
| run: ls -lh pkg/ checksums/ | ||
|
|
||
| - name: Upload build artifacts | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: gem-package | ||
| path: | | ||
| pkg/*.gem | ||
| checksums/*.sha512 | ||
|
|
||
| release-github: | ||
| needs: [validate, build] | ||
| runs-on: ubuntu-latest | ||
| # GitHub release creation requires contents:write to create releases | ||
| permissions: | ||
| contents: write | ||
| steps: | ||
| - name: Download build artifacts | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: gem-package | ||
|
|
||
| - name: Create GitHub Release | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. move the "generate github release" to an own job...
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved GitHub release to dedicated |
||
| uses: softprops/action-gh-release@v1 | ||
| with: | ||
| files: | | ||
| *.gem | ||
| *.sha512 | ||
| prerelease: ${{ needs.validate.outputs.prerelease }} | ||
| generate_release_notes: true | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| release-rubygems: | ||
| needs: [validate, build] | ||
| runs-on: ubuntu-latest | ||
| if: github.repository == 'CycloneDX/cyclonedx-ruby-gem' | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
|
|
||
| - name: Set up Ruby | ||
| uses: ruby/setup-ruby@v1 | ||
| with: | ||
| ruby-version: '3.3' | ||
| bundler-cache: false | ||
|
|
||
| - name: Check for RubyGems API key | ||
| run: | | ||
| if [ -z "${{ secrets.RUBYGEMS_API_KEY }}" ]; then | ||
| echo "::error::RUBYGEMS_API_KEY secret is not set" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Download build artifacts | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: gem-package | ||
|
|
||
| - name: Publish to RubyGems | ||
| run: | | ||
| mkdir -p ~/.gem | ||
| cat << EOF > ~/.gem/credentials | ||
| --- | ||
| :rubygems_api_key: ${RUBYGEMS_API_KEY} | ||
| EOF | ||
| chmod 0600 ~/.gem/credentials | ||
| gem push *.gem | ||
| env: | ||
| RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| # Build Artifacts | ||
| /pkg/ | ||
| /tmp/ | ||
| /checksums/ | ||
| *.gem | ||
|
|
||
| # Bundler | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.