diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..d6254e9 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,99 @@ +name: Release + +on: + push: + tags: ["v*.*.*"] + +# see https://docs.github.com/en/actions/tutorials/authenticate-with-github_token#modifying-the-permissions-for-the-github_token +permissions: {} + +jobs: + test: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout Code + # see https://github.com/actions/checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Set up Ruby + # see https://github.com/ruby/setup-ruby + uses: ruby/setup-ruby@9eb537ca036ebaed86729dcb9309076e4c5c3b74 # v1.314.0 + with: + ruby-version: '3.3.9' + bundler-cache: false + - name: Install Dependencies + run: bundle install + - name: Run the default task + run: bundle exec rake + + rubygems_release: + name: RubyGems Release + if: github.repository == 'CycloneDX/cyclonedx-ruby-gem' + runs-on: ubuntu-latest + timeout-minutes: 10 + needs: test + permissions: + contents: write # Required for `rake release` to perform git synchronization. + id-token: write # Required for Trusted Publishing authentication. + environment: release + steps: + - name: Checkout Code + # see https://github.com/actions/checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Set up Ruby + # see https://github.com/ruby/setup-ruby + uses: ruby/setup-ruby@9eb537ca036ebaed86729dcb9309076e4c5c3b74 # v1.314.0 + with: + ruby-version: '3.4' # Stable environment to package the gem for the supported ruby versions + bundler-cache: false + - name: Push gem to RubyGems + # see https://github.com/rubygems/release-gem + uses: rubygems/release-gem@6317d8d1f7e28c24d28f6eff169ea854948bd9f7 # v1.2.0 + - name: Upload gem artifact + # see https://github.com/actions/upload-artifact + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a #v7.0.1 + with: + name: gem + path: pkg/*.gem + retention-days: 1 + + github_release: + name: GitHub Release + if: github.repository == 'CycloneDX/cyclonedx-ruby-gem' + runs-on: ubuntu-latest + timeout-minutes: 10 + needs: rubygems_release + environment: release + # Needed for `gh release create` because GitHub Releases require write access + # to repository contents, which is not granted by default with GITHUB_TOKEN. + permissions: + contents: write + steps: + - name: Checkout Code + # see https://github.com/actions/checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + - name: Download gem artifact + # see https://github.com/actions/download-artifact + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: gem + path: pkg + - name: Create GitHub Release + run: | + declare -a FLAGS=("--verify-tag" "--generate-notes") + + # Determine release type from tag suffix + if [[ "$GITHUB_REF_NAME" =~ -(alpha|beta|rc|pre)[0-9.]*$ ]]; then + FLAGS+=("--prerelease") + fi + + # Publish the release on GitHub with auto-generated release notes + gh release create "${FLAGS[@]}" -- "$GITHUB_REF_NAME" pkg/*.gem + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index e50ee65..1981ada 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,9 @@ Please file a bug if you notice a violation of semantic versioning. ### Added +- Semi-automated CI release workflow triggered by version tags (`vMAJOR.MINOR.PATCH` with optional pre-release suffixes) (#46) +- RubyGems publishing via `rubygems_release` using trusted publishing +- Automated GitHub Releases with generated release notes, including support for pre-releases - `CONTRIBUTING.md` file to help people find their way to contributing - `CHANGELOG.md` file to document notable changes in keep-a-changelog format - `Cyclonedx::BomHelpers` module to house helper methods, replacing global methods diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7157a53..18eb0bc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -88,36 +88,20 @@ Made with [contributors-img][🖐contrib-rocks]. ### To release a new version: -#### Automated process - -Coming Soon! - -#### Manual process - -1. Run `bin/setup && bin/rake` as a "test, coverage, & linting" sanity check -2. Update the version number in `version.rb`, and ensure `CHANGELOG.md` reflects changes -3. Run `bin/setup && bin/rake` again as a secondary check, and to update `Gemfile.lock` -4. Run `git commit -am "🔖 Prepare release v"` to commit the changes -5. Run `git push` to trigger the final CI pipeline before release, and merge PRs +#### Semi-automated process + +1. Update the version number in `version.rb`, and ensure `CHANGELOG.md` reflects the changes. +2. Commit the changes: + ```sh + git commit -am "🔖 Prepare release v" + ``` +3. Push the changes to trigger the final CI pipeline before the release. - NOTE: Remember to [check the build][🧪build]. -6. Run `export GIT_TRUNK_BRANCH_NAME="$(git remote show origin | grep 'HEAD branch' | cut -d ' ' -f5)" && echo $GIT_TRUNK_BRANCH_NAME` -7. Run `git checkout $GIT_TRUNK_BRANCH_NAME` -8. Run `git pull origin $GIT_TRUNK_BRANCH_NAME` to ensure latest trunk code -9. Optional for older Bundler (< 2.7.0): Set `SOURCE_DATE_EPOCH` so `rake build` and `rake release` use the same timestamp and generate the same checksums - - If your Bundler is >= 2.7.0, you can skip this; builds are reproducible by default. - - Run `export SOURCE_DATE_EPOCH=$EPOCHSECONDS && echo $SOURCE_DATE_EPOCH` - - If the echo above has no output, then it didn't work. - - Note: `zsh/datetime` module is needed, if running `zsh`. - - In older versions of `bash` you can use `date +%s` instead, i.e. `export SOURCE_DATE_EPOCH=$(date +%s) && echo $SOURCE_DATE_EPOCH` -10. Run `bundle exec rake build` -11. Run `bundle exec rake release` which will create a git tag for the version, - push git commits and tags, and push the `.gem` file to the gem host configured in the gemspec. -12. Run `bin/gem_checksums` (more context [1][🔒️rubygems-checksums-pr], [2][🔒️rubygems-guides-pr]) - to create SHA-256 and SHA-512 checksums. This functionality is provided by the `stone_checksums` - [gem][💎stone_checksums]. - - The script automatically commits but does not push the checksums -13. Sanity check the SHA256, comparing with the output from the `bin/gem_checksums` command: - - `sha256sum pkg/-.gem` +4. Create a git tag for the gem version. Prefix the tag with 'v'. For example, if the current [gem version](https://github.com/CycloneDX/cyclonedx-ruby-gem/blob/master/lib/cyclonedx/ruby/version.rb) is 1.2.0, the tag should be 'v1.2.0'. Pre-releases are supported. See the [release workflow](https://github.com/CycloneDX/cyclonedx-ruby-gem/blob/master/.github/workflows/release.yml) for more details. Push the tag to the repository to trigger the release workflow. + +> [!WARNING] +> The gem version and git tag MUST match. A mismatch may cause `rake release` (invoked by `rubygems/release-gem`) to create and push a tag for the gem version, which could produce unexpected results. +5. Monitor the release workflow and verify that the release completes succesfully. [📜src-gh]: https://github.com/CycloneDX/cyclonedx-ruby-gem [🧪build]: https://github.com/CycloneDX/cyclonedx-ruby-gem/actions