diff --git a/.changelog.yml b/.changelog.yml new file mode 100644 index 0000000..852fec7 --- /dev/null +++ b/.changelog.yml @@ -0,0 +1,50 @@ +# Configuration for gh-changelog +# Labels added here will be omitted from the changelog +excluded_labels: + - maintenance + - dependencies + - wontfix + - duplicate + - invalid + +# This is the filename of the generated changelog +file_name: CHANGELOG.md + +# This is where labels are mapped to the sections in a changelog entry +# The possible sections are restricted to: Added, Changed, Deprecated, +# Removed, Fixed, Security. +sections: + added: + - enhancement + - feature + - new + changed: + - backwards-incompatible + - breaking-change + - change + deprecated: + - deprecation + removed: + - removal + fixed: + - bug + - bugfix + - fix + security: + - security + - vulnerability + +# When set to true, unlabelled entries will not be included in the changelog. +# By default they will be grouped in a section named "Other". +skip_entries_without_label: false + +# Adds an unreleased section to the changelog. This will contain any qualifying entries +# that have been added since the last tag. +# Note: The unreleased section is not created when the --next-version flag is used. +show_unreleased: true + +# If set to false, the tool will not check remotely for updates +check_for_updates: true + +# Determines the logging mode. The default is spinner. The other option is console. +logger: console diff --git a/.github/workflows/release_prep.yml b/.github/workflows/release_prep.yml new file mode 100644 index 0000000..24aa51d --- /dev/null +++ b/.github/workflows/release_prep.yml @@ -0,0 +1,92 @@ +name: "Release Prep" + +on: + workflow_dispatch: + inputs: + target: + description: "The target for the release. This can be a commit sha or a branch." + required: false + default: "main" + type: "string" + version: + description: "Version of gem to be released." + required: true + type: "string" + +jobs: + release_prep: + name: "Release Prep" + runs-on: "ubuntu-latest" + + steps: + - name: "Checkout" + uses: "actions/checkout@v4" + with: + ref: ${{ github.event.inputs.target }} + clean: true + fetch-depth: 0 + + - name: "Setup Ruby" + uses: "ruby/setup-ruby@v1" + with: + ruby-version: "3.2" + bundler-cache: true + + - name: "Bundle environment" + run: | + echo ::group::bundler environment + bundle env + echo ::endgroup:: + + - name: "Update Version" + run: | + current_version=$(ruby -e "require 'rubygems'; puts Gem::Specification::load(Dir.glob('*.gemspec').first).version.to_s") + normalized_version=$(echo ${{ github.event.inputs.version }} | sed "s/-/./g") + sed -i "s/$current_version/$normalized_version/g" $(find . -path './lib/**' -name 'version.rb' -not -path "vendor/*") + + - name: "Generate changelog" + run: | + export GH_HOST=github.com + gh extension install chelnak/gh-changelog || gh extension upgrade chelnak/gh-changelog + gh changelog new --next-version v${{ github.event.inputs.version }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: "Run tests to ensure everything works" + run: | + bundle exec rake spec + + - name: "Run RuboCop to ensure code quality" + run: | + bundle exec rubocop + + - name: "Build gem to verify it can be built" + run: | + bundle exec rake build + + - name: "Commit changes" + run: | + git config --local user.email "${{ github.repository_owner }}@users.noreply.github.com" + git config --local user.name "GitHub Actions" + git add . + git commit -m "Release prep v${{ github.event.inputs.version }}" + + - name: "Create pull request" + uses: "peter-evans/create-pull-request@v7" + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: "Release prep v${{ github.event.inputs.version }}" + branch: "release-prep-v${{ github.event.inputs.version }}" + delete-branch: true + title: "Release prep v${{ github.event.inputs.version }}" + base: "main" + body: | + Automated release-prep for version v${{ github.event.inputs.version }} from commit ${{ github.sha }}. + + This PR includes: + - Version bump to v${{ github.event.inputs.version }} + - Updated CHANGELOG.md + - Verified tests pass + - Verified RuboCop passes + - Verified gem can be built + labels: "maintenance" diff --git a/docs/how-to/publishing_automation.md b/docs/how-to/publishing_automation.md new file mode 100644 index 0000000..3034c4b --- /dev/null +++ b/docs/how-to/publishing_automation.md @@ -0,0 +1,143 @@ +# Publishing Your Gem with GitHub Automation + +This repository includes GitHub Actions workflows to automate the gem publishing process, inspired by the puppetlabs/cat-github-actions workflows but adapted for personal use. + +## Prerequisites + +Before you can use these workflows, you need to set up a few things: + +### 1. RubyGems API Key + +To publish to RubyGems.org, you need to set up an API key: + +1. Go to https://rubygems.org/settings/edit +2. Create an API key with the scope you need (usually "Push rubygems") +3. In your GitHub repository, go to Settings → Secrets and variables → Actions +4. Add a new repository secret named `GEM_HOST_API_KEY` with your RubyGems API key + +### 2. Optional: Codecov Integration + +For enhanced coverage reporting: + +1. Go to https://codecov.io and sign up/login with your GitHub account +2. Add your repository to Codecov +3. Get your repository's Codecov token +4. Add it as a repository secret named `CODECOV_TOKEN` + +## Available Workflows + +### 1. CI Workflow (`.github/workflows/ci.yml`) + +**Triggers:** Push to main/master/development branches, pull requests to main/master + +**What it does:** +- Runs tests on Ruby 3.1 and 3.2 +- Runs RuboCop linting +- Generates coverage reports +- Uploads coverage to Codecov (if configured) +- Deploys coverage reports to GitHub Pages + +### 2. Release Prep Workflow (`.github/workflows/release_prep.yml`) + +**Triggers:** Manual trigger via GitHub Actions tab + +**What it does:** +- Updates the version in your `lib/gempath/version.rb` file +- Generates/updates the CHANGELOG.md using PR/issue labels +- Runs tests and linting to ensure everything works +- Builds the gem to verify it can be built +- Creates a release preparation pull request + +**How to use:** +1. Go to your repository's Actions tab +2. Select "Release Prep" workflow +3. Click "Run workflow" +4. Enter the version you want to release (e.g., "1.0.0") +5. Review and merge the generated pull request + +### 3. Release Workflow (`.github/workflows/release.yml`) + +**Triggers:** Manual trigger via GitHub Actions tab + +**What it does:** +- Runs final tests and linting +- Builds the gem +- Creates a GitHub release with generated release notes +- Publishes the gem to RubyGems.org +- Publishes the gem to GitHub Packages + +**How to use:** +1. Ensure your release prep PR has been merged +2. Go to your repository's Actions tab +3. Select "Release" workflow +4. Click "Run workflow" +5. The workflow will automatically detect the version from your gemspec + +## Changelog Generation + +The workflows use the `gh-changelog` extension to automatically generate changelog entries based on: + +- Pull request titles and descriptions +- Issue labels +- Git commit messages + +### Label Mapping + +The changelog generator maps GitHub labels to changelog sections: + +- **Added:** enhancement, feature, new +- **Changed:** backwards-incompatible, breaking-change, change +- **Fixed:** bug, bugfix, fix +- **Security:** security, vulnerability +- **Deprecated:** deprecation +- **Removed:** removal + +### Excluded Labels + +These labels won't appear in the changelog: +- maintenance +- dependencies +- wontfix +- duplicate +- invalid + +## Release Process + +Here's the recommended process for releasing a new version: + +1. **Develop and test your changes** on feature branches +2. **Create and merge pull requests** to main with appropriate labels +3. **Run the Release Prep workflow** with your desired version number +4. **Review the generated pull request** to ensure the changelog and version bump look correct +5. **Merge the release prep pull request** +6. **Run the Release workflow** to publish the gem + +## Differences from puppetlabs/cat-github-actions + +While inspired by the puppetlabs workflows, these have been adapted for personal use: + +1. **Repository ownership check:** Changed from `puppetlabs` to `gavindidrichsen` +2. **Ruby version:** Updated to use Ruby 3.2 as primary version +3. **Additional verification:** Added gem building verification in release prep +4. **Enhanced CI:** Added matrix testing across Ruby 3.1 and 3.2 +5. **Development branch:** Added support for development branch in CI +6. **Better error handling:** Made Codecov upload optional to prevent failures + +## Troubleshooting + +### Release Prep Fails + +- Check that your repository has proper PR/issue history for changelog generation +- Ensure your version.rb file is in the expected location (`lib/gempath/version.rb`) +- Verify tests pass locally before running the workflow + +### Release Fails + +- Ensure `GEM_HOST_API_KEY` secret is set correctly +- Check that the gem builds successfully locally with `bundle exec rake build` +- Verify your gemspec is valid + +### Coverage Issues + +- Codecov upload is optional; the workflow will continue if it fails +- Check that your test suite generates coverage data in the expected format diff --git a/docs/how-to/release_checklist.md b/docs/how-to/release_checklist.md new file mode 100644 index 0000000..f2d19e8 --- /dev/null +++ b/docs/how-to/release_checklist.md @@ -0,0 +1,69 @@ +# Release Checklist + +Use this checklist to ensure a smooth release process: + +## Pre-Release + +- [ ] All desired features and fixes are merged to `main` +- [ ] Tests are passing locally: `bundle exec rake spec` +- [ ] RuboCop passes locally: `bundle exec rubocop` +- [ ] Gem builds successfully: `bundle exec rake build` +- [ ] Documentation is up to date +- [ ] Version number follows [Semantic Versioning](https://semver.org/) + +## Release Prep + +- [ ] Run the "Release Prep" workflow from GitHub Actions + - [ ] Go to Actions tab → Release Prep → Run workflow + - [ ] Enter the new version number (e.g., "1.0.0") +- [ ] Review the generated pull request: + - [ ] Version bump is correct in `lib/gempath/version.rb` + - [ ] CHANGELOG.md has been updated appropriately + - [ ] All automated checks pass +- [ ] Merge the release prep pull request + +## Release + +- [ ] Ensure the release prep PR has been merged +- [ ] Run the "Release" workflow from GitHub Actions + - [ ] Go to Actions tab → Release → Run workflow +- [ ] Verify the release completed successfully: + - [ ] GitHub release was created with release notes + - [ ] Gem was published to RubyGems.org + - [ ] Gem was published to GitHub Packages (optional) + +## Post-Release + +- [ ] Verify the gem can be installed: `gem install gempath` +- [ ] Test the installed gem works as expected +- [ ] Announce the release (optional): + - [ ] Update project README if needed + - [ ] Share on social media, blog, etc. + +## Secrets Required + +Ensure these GitHub repository secrets are configured: + +- [ ] `GEM_HOST_API_KEY` - Your RubyGems.org API key (required) +- [ ] `CODECOV_TOKEN` - Your Codecov token (optional, for coverage reporting) + +## Troubleshooting + +If something goes wrong: + +1. **Release Prep fails**: Check the workflow logs and ensure your repo has sufficient history for changelog generation +2. **Release fails**: Verify your `GEM_HOST_API_KEY` is correct and has push permissions +3. **Gem push fails**: Check if the version already exists on RubyGems.org + +## Version Numbering Guide + +Follow [Semantic Versioning](https://semver.org/): + +- **Major (X.0.0)**: Breaking changes +- **Minor (0.X.0)**: New features, backwards compatible +- **Patch (0.0.X)**: Bug fixes, backwards compatible + +Examples: +- `0.1.0` → `0.1.1` (bug fix) +- `0.1.1` → `0.2.0` (new feature) +- `0.2.0` → `1.0.0` (breaking change or first stable release)