{"id":13499446,"url":"https://github.com/svenfuchs/gem-release","last_synced_at":"2025-05-13T20:22:53.975Z","repository":{"id":39897845,"uuid":"592533","full_name":"svenfuchs/gem-release","owner":"svenfuchs","description":"Release your ruby gems with ease. ","archived":false,"fork":false,"pushed_at":"2024-12-28T02:54:26.000Z","size":389,"stargazers_count":513,"open_issues_count":6,"forks_count":59,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-05-06T13:12:13.891Z","etag":null,"topics":["cli","extension","gem-bootstrap","gem-gemspec","gemspec","release","ruby","ruby-gem","rubygems"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/svenfuchs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"MIT-LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2010-04-03T00:04:17.000Z","updated_at":"2025-04-26T15:55:20.000Z","dependencies_parsed_at":"2023-02-16T14:16:00.836Z","dependency_job_id":"1eb5e030-bfc0-404d-a7bb-7829f3956a0d","html_url":"https://github.com/svenfuchs/gem-release","commit_stats":{"total_commits":286,"total_committers":39,"mean_commits":7.333333333333333,"dds":0.6818181818181819,"last_synced_commit":"7d665ba5baa91e17f2cf9bb62fd18691549179ef"},"previous_names":[],"tags_count":60,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svenfuchs%2Fgem-release","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svenfuchs%2Fgem-release/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svenfuchs%2Fgem-release/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/svenfuchs%2Fgem-release/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/svenfuchs","download_url":"https://codeload.github.com/svenfuchs/gem-release/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253381459,"owners_count":21899711,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","extension","gem-bootstrap","gem-gemspec","gemspec","release","ruby","ruby-gem","rubygems"],"created_at":"2024-07-31T22:00:33.206Z","updated_at":"2025-05-13T20:22:48.965Z","avatar_url":"https://github.com/svenfuchs.png","language":"Ruby","readme":"# gem release\n\nThis gem plugin aims at making gem development easier by automating repetitive work based on conventions, configuration, and templates.\n\nIt adds the commands `bootstrap`, `gemspec`, `bump`, `tag` and a `release` to the rubygems `gem` command.\n\n| Project                |  Gem Release |\n| ---------------------- | ------------ |\n| Gem name               |  gem-release |\n| License                |  [MIT](https://github.com/svenfuchs/gem-release/blob/master/LICENSE.md) |\n| Version                |  [![Gem Version](https://img.shields.io/gem/v/gem-release.svg?style=flat-square)](https://badge.fury.io/rb/gem-release) |\n| Continuous integration |  [![GitHub Build Status](https://img.shields.io/github/actions/workflow/status/svenfuchs/gem-release/tests.yaml?branch=master\u0026style=flat-square)](https://github.com/svenfuchs/gem-release/actions/workflows/tests.yaml) |\n| Test coverage          |  [![Coverage Status](https://img.shields.io/coveralls/svenfuchs/gem-release.svg?style=flat-square)](https://coveralls.io/r/svenfuchs/gem-release) |\n| Documentation          |  [Documentation](https://www.rubydoc.info/gems/gem-release) |\n| Credits                |  [Contributors](https://github.com/svenfuchs/gem-release/graphs/contributors) |\n\n# Table of contents\n\n* [Demo](#demo)\n* [Installation](#installation)\n* [Configuration](#configuration)\n* [Conventions](#conventions)\n* [Piping](#piping)\n* [Reference](#reference)\n* [Scenarios](#scenarios)\n* [Development](#development)\n\n# Demo\n\nThis gif demos some of the things you can do with this plugin:\n\n![gem-release-demo](https://cloud.githubusercontent.com/assets/2208/25634571/68b78080-2f7b-11e7-9eb2-c7d1df13c727.gif)\n\n## Installation\n\nThe gem provides a rubygems plugin, so it's just:\n\n```\ngem install gem-release\n```\n\n\n# Configuration\n\nDefaults for all options can be specified in a config file at either one of\nthese locations:\n\n* `~/.gem_release/config.yml`\n* `~/.gem_release.yml`\n* `./.gem_release/config.yml`\n* `./.gem_release.yml`\n\nConfig files must be in the [YAML](http://www.yaml.org/) format, and list\noptions per command. Common options can be set on the root.\n\nFor instance, the following entries will set the `quiet` flag for all commands,\nand a custom host name with `gem release`:\n\n```yaml\nquiet: true\n\nrelease:\n  host: https://example.com\n```\n\nDefaults for all options also can be specified as environment variables, for\nexample `GEM_RELEASE_PRETEND=true`.\n\nDefaults specified in config files and environment variables can be overridden\nas command line options when issuing the respective `gem` command.\n\nOnly the first config file found in the locations given above will be used, if\nany, and defaults from this config file will be merged with both environment\nvariables and given command line options.\n\n\n# Conventions\n\nWhen bootstrapping a new gem:\n\n* A gem name `gem_name` is left untouched when mapped to the path `lib/gem_name`, and the Ruby constant name `GemName`.\n* A gem name `gem-name` is mapped to the path `lib/gem/name`, and the Ruby constant name `Gem::Name`\n\nWhen bumping the version of an existing gem `gem-name` the following locations are checked:\n\n* `lib/gem/name/version.rb`\n* `lib/gem-name/version.rb`\n\n# Piping\n\nOutput depends on a `tty` being available or not. I.e. when run as an\nindividual command colorized human readable output will be printed (see the\nDemo screencast above). When attached to a pipe then output is kept simple and\nparsable.\n\nE.g.:\n\n```\n$ gem bump --pretend | cat\nbump gem-release 1.0.0 1.0.1\ngit_add lib/gem/release/version.rb\ngit_commit \"Bump gem-release to 1.0.1\"\n```\n\nThis is useful, for example, for grabbing the next version number:\n\n```\n$ gem bump --pretend --no-commit | awk '{ print $4 }'\n1.0.1\n```\n\n\n# Reference\n\nThe gem `gem-release` adds the following commands to the rubygems `gem` command:\n\n  * [gem bootstrap](#gem-bootstrap) - Scaffolds a new gem from template files.\n  * [gem bump](#gem-bump) - Bumps one, several, or all gems in this directory.\n  * [gem gemspec](#gem-gemspec) - Generates a gemspec.\n  * [gem release](#gem-release) - Releases one or all gems in this directory.\n  * [gem tag](#gem-tag) - Tags the HEAD commit with the gem's current version.\n\n## gem bootstrap\n\nScaffolds a new gem from template files.\n\n### Arguments\n\n```\ngem_name - name of the gem (optional, will default to the current directory name if not specified)\n```\n\n### Options\n\n```\n    --[no-]scaffold              Scaffold gem files (default: true)\n    --dir DIR                    Directory to place the gem in (defaults to the given name, or the current working dir)\n    --bin                        Create an executable ./bin/[name], add executables directive to .gemspec\n-t, --template NAME              Template groups to use for scaffolding\n    --rspec                      Use the rspec group (by default adds .rspec and spec/spec_helper.rb)\n    --travis                     Use the travis group (by default adds .travis.yml)\n-l, --[no-]license NAME          License(s) to add (default: mit)\n-s, --strategy NAME              Strategy for collecting files [glob|git] in .gemspec (default: glob)\n    --[no-]git                   Initialize a git repo (default: true)\n    --github                     Initialize a git repo, create on github\n    --remote                     Git remote repository\n    --push                       Push the git repo to github\n    --[no-]color\n    --pretend\n```\n\n### Description\n\nScaffolds a new gem from template files. Optionally initialize a git\nrepository, set a git remote, and push to the remote repository.\n\nIf no argument is given the current directory name is used as the gem\nname. If one or many arguments are given then these will be used as\ngem names, and new directories will be created accordingly.\n\nBy default the following files will be created:\n\n* `.gitignore`\n* `Gemspec`\n* `[gem-name].gemspec`\n* `LICENSE.md`\n* `lib/[gem]/[name].rb`\n* `lib/[gem]/[name]/version.rb`\n\nTemplates in the first existing one of these directories will always\nbe used to create additional files:\n\n* `./.gem-release/default` (local)\n* `~/.gem-release/default` (global)\n\nIf `--template [group]` is given additional files will be created from\nthe first existing one of these directories:\n\n* `./.gem-release/[group]` (local)\n* `~/.gem-release/[group]` (global)\n\nIt is possible to specify several template groups in order to add\nfiles from several custom template directories.\n\nIf `--template rspec` is given then additionally the files `.rspec`\nand `spec/spec_helper.rb` will be created, or whatever files exist in\na local or global directory `.gem-release/templates/rspec`.\n\nIf `--template travis` is given then additionally the file\n`.travis.yml` will be created, or whatever files exist in a local or\nglobal directory `.gem-release/templates/travis`.\n\nThe license added by default is the MIT License. If `--license [name]`\nis given then this license will be added. The only other license file\nshipped is the Mozilla Public License v2.0. Other licenses must be\npresent in the local or global directory `.gem-release/licenses`. If\n`--no-license` is given then no license will be added.\n\n## gem bump\n\nBumps one, several, or all gems in this directory.\n\n### Arguments\n\n```\ngem_name - name of the gem (optional, will use the directory name, or all gemspecs if --recurse is given)\n```\n\n### Options\n\n```\n-v, --version VERSION            Target version: next [major|minor|patch|pre|release] or a given version number [x.x.x]\n-c, --[no-]commit                Create a commit after incrementing gem version (default: true)\n-m, --message MESSAGE            Commit message template (default: Bump %{name} to %{version} %{skip_ci})\n    --skip-ci                    Add the [skip ci] tag to the commit message\n-p, --push                       Push the new commit to the git remote repository\n    --remote REMOTE              Git remote to push to (defaults to origin) (default: origin)\n-s, --sign                       GPG sign the commit message\n    --branch [BRANCH]            Check out a new branch for the target version (e.g. `v1.0.0`)\n-t, --tag                        Shortcut for running the `gem tag` command\n-r, --release                    Shortcut for the `gem release` command\n    --recurse                    Recurse into directories that contain gemspec files\n    --file FILE                  Full path to the version file\n    --[no-]color\n    --pretend\n```\n\n### Description\n\nBumps the version number defined in lib/[gem_name]/version.rb to a\ngiven, specific version number, or to the next major, minor, patch, or\npre-release level.\n\nOptionally it pushes to the origin repository. Also, optionally it\ninvokes the `gem tag` and/or `gem release` command.\n\nIf no argument is given the first gemspec's name is assumed as the gem\nname. If one or many arguments are given then these will be used as\ngem names. If `--recurse` is given then all gem names from all\ngemspecs in this directory or any of its subdirectories will be used.\n\nThe version can be bumped to either one of these targets:\n\n```\nmajor\n1.1.1       # Bump to the given, specific version number\nmajor       # Bump to the next major level (e.g. 0.0.1 to 1.0.0)\nminor       # Bump to the next minor level (e.g. 0.0.1 to 0.1.0)\npatch       # Bump to the next patch level (e.g. 0.0.1 to 0.0.2)\npre|rc|etc  # Bump to the next pre-release level (e.g. 0.0.1 to\n#   0.1.0.pre.1, 1.0.0.pre.1 to 1.0.0.pre.2)\n```\n\nWhen searching for the version file for a gem named `gem-name`: the\nfollowing paths will be searched relative to the gemspec's directory.\n\n* `lib/gem-name/version.rb`\n* `lib/gem/name/version.rb`\n\n## gem gemspec\n\nGenerates a gemspec.\n\n### Arguments\n\n```\ngem_name - name of the gem (optional, will default to the current directory name if not specified)\n```\n\n### Options\n\n```\n    --[no]-bin                   Add bin files directive to the gemspec (defaults to true if a ./bin directory exists)\n    --dir DIR                    Directory to place the gem in (defaults to the given name, or the current working dir)\n-l, --[no-]license NAMES         License(s) to list in the gemspec\n-s, --strategy                   Strategy for collecting files [glob|git] in gemspec (default: glob)\n    --[no-]color\n    --pretend\n```\n\n### Description\n\nGenerates a gemspec.\n\nIf no argument is given the current directory name is used as the gem\nname. If one or many arguments are given then these will be used as\ngem names, and new directories will be created accordingly.\n\nThe generated `gemspec` file will use the `glob` strategy for finding\nfiles by default. Known strategies are:\n\n* `glob` - uses the glob pattern `{bin/*,lib/**/*,[A-Z]*}`\n* `git`  - uses the git command `git ls-files app lib`\n\n## gem release\n\nReleases one or all gems in this directory.\n\n### Arguments\n\n```\ngem_name - name of the gem (optional, will use the first gemspec, or all gemspecs if --recurse is given)\n```\n\n### Options\n\n```\n    --host HOST                  Push to a compatible host other than rubygems.org\n-k, --key KEY                    Use the API key from ~/.gem/credentials\n-t, --tag                        Shortcut for running the `gem tag` command\n-p, --push                       Push tag to the remote git repository\n    --recurse                    Recurse into directories that contain gemspec files\n-g, --github                     Create a GitHub release\n-d, --description DESCRIPTION    Description of the release\n    --repo REPO                  Full name of the repository on GitHub, e.g. svenfuchs/gem-release (defaults to the repo name from the gemspec's homepage if this is a GitHub URL)\n    --token TOKEN                GitHub OAuth token\n    --[no-]color\n    --pretend\n```\n\n### Description\n\nBuilds one or many gems from the given gemspec(s), pushes them to\nrubygems.org (or another, compatible host), and removes the left over\ngem file.\n\nOptionally invoke `gem tag`.\n\nIf no argument is given the first gemspec's name is assumed as the gem\nname. If one or many arguments are given then these will be used. If\n`--recurse` is given then all gem names from all gemspecs in this\ndirectory or any of its subdirectories will be used.\n\n## gem tag\n\nTags the HEAD commit with the gem's current version.\n\n### Options\n\n```\n-p, --[no-]push                  Push tag to the remote git repository\n    --remote REMOTE              Git remote to push to (default: origin)\n-s, --sign                       GPG sign the tag\n    --[no-]color\n    --pretend\n```\n\n### Description\n\nCreates an annotated tag for the current HEAD commit, using the gem's\ncurrent version.\n\nOptionally pushes the tag to the origin repository.\n\nIf one or many arguments are given then gemspecs with the same names\nwill be searched, and the working directory changed to their\nrespective directories. If `--recurse` is given then the directories\nall gem names from all gemspecs in this directory or any of its\nsubdirectories will be used. This assumes that these directories are\nseparate git repositories.\n\nThe tag name will be `v[version]`.  For example, if the current\nversion is `1.0.0`, then The tag is created using the command `git tag\n-am \"tag v1.0.0\" v1.0.0`.\n\n\n# Scenarios\n\n* [Single gem in root](#scenario-1-single-gem-in-root)\n* [Multiple gems in root](#scenario-2-multiple-gems-in-root)\n* [Multiple gems in sub directories](#scenario-3-multiple-gems-in-sub-directories)\n* [Nested gem with a conventional sub directory name](#scenario-4-nested-gem-with-a-conventional-sub-directory-name)\n* [Nested gem with an irregular sub directory name](#scenario-5-nested-gem-with-an-irregular-sub-directory-name)\n\n## Scenario 1: Single gem in root\n\n### Setup\n\n```\ncd /tmp\nrm -rf foo\ngem bootstrap foo\ncd foo\ntree -a -I .git\n```\n\n### Directory structure\n\n```\n.\n├── Gemfile\n├── LICENSE.md\n├── foo.gemspec\n└── lib\n    ├── foo\n    │   └── version.rb\n    └── foo.rb\n```\n\n### Behaviour\n\n```\n# this bumps foo\ncd /tmp/foo; gem bump\n\n# this also bumps foo\ncd /tmp/foo; gem bump foo\n```\n\n### Demo\n\n![gem-release-scenario-1](https://cloud.githubusercontent.com/assets/2208/25634572/68d1fd20-2f7b-11e7-83bc-9e11f60438f3.gif)\n\n\n## Scenario 2: Multiple gems in root\n\n### Setup\n\n```\ncd /tmp\nrm -rf foo bar\ngem bootstrap foo\ncd foo\ngem bootstrap bar --dir .\ntree -a -I .git\n```\n\n### Directory structure\n\n```\n.\n├── Gemfile\n├── LICENSE.md\n├── bar.gemspec\n├── foo.gemspec\n└── lib\n    ├── bar\n    │   └── version.rb\n    ├── bar.rb\n    ├── foo\n    │   └── version.rb\n    └── foo.rb\n```\n\n### Behaviour\n\n```\n# this bumps both foo and bar\ncd /tmp/foo; gem bump --recurse\n\n# this also bumps both foo and bar\ncd /tmp/foo; gem bump foo bar\n\n# this bumps foo (because it's the first gemspec found)\ncd /tmp/foo; gem bump\n\n# this bumps foo\ncd /tmp/foo; gem bump foo\n\n# this bumps bar\ncd /tmp/foo; gem bump bar\n```\n\n### Demo\n\n![gem-release-scenario-2](https://cloud.githubusercontent.com/assets/2208/25634575/68dcb670-2f7b-11e7-991e-901283164d21.gif)\n\n## Scenario 3: Multiple gems in sub directories\n\n### Setup\n\n```\ncd /tmp\nrm -rf root\nmkdir root\ncd root\ngem bootstrap foo\ngem bootstrap bar\ntree -a -I .git\n```\n\n### Directory structure\n\n```\n.\n├── bar\n│   ├── Gemfile\n│   ├── LICENSE.md\n│   ├── bar.gemspec\n│   └── lib\n│       ├── bar\n│       │   └── version.rb\n│       └── bar.rb\n└── foo\n    ├── Gemfile\n    ├── LICENSE.md\n    ├── foo.gemspec\n    └── lib\n        ├── foo\n        │   └── version.rb\n        └── foo.rb\n```\n\n### Behaviour\n\n```\n# this bumps both foo and bar\ncd /tmp/root; gem bump --recurse\n\n# this also bumps both foo and bar\ncd /tmp/root; gem bump foo bar\n\n# this does bumps both foo and bar\ncd /tmp/root; gem bump\n\n# this bumps foo\ncd /tmp/root; gem bump foo\n\n# this bumps bar\ncd /tmp/root; gem bump bar\n```\n\n### Demo\n\n![gem-release-scenario-3](https://cloud.githubusercontent.com/assets/2208/25634573/68d51c3a-2f7b-11e7-8ec8-629bc8019d16.gif)\n\n\n## Scenario 4: Nested gem with a conventional sub directory name\n\n### Setup\n\n```\ncd /tmp\nrm -rf sinja\ngem bootstrap sinja\ncd sinja\nmkdir extensions\ncd extensions\ngem bootstrap sinja-sequel\ncd /tmp/sinja\ntree -a -I .git\n```\n\n### Directory structure\n\n```\n.\n├── Gemfile\n├── LICENSE.md\n├── extensions\n│   └── sinja-sequel\n│       ├── Gemfile\n│       ├── LICENSE.md\n│       ├── lib\n│       │   └── sinja\n│       │       ├── sequel\n│       │       │   └── version.rb\n│       │       └── sequel.rb\n│       └── sinja-sequel.gemspec\n├── lib\n│   ├── sinja\n│   │   └── version.rb\n│   └── sinja.rb\n└── sinja.gemspec\n```\n\n### Behaviour\n\n```\n# this bumps both sinja and sinja-sequel\ncd /tmp/sinja; gem bump --recurse\n\n# this bumps sinja\ncd /tmp/sinja; gem bump\n\n# this also bumps sinja\ncd /tmp/sinja; gem bump sinja\n\n# this bumps sinja-sequel\ncd /tmp/sinja; gem bump sinja-sequel\n\n# this also bumps sinja-sequel\ncd /tmp/sinja/extensions/sinja-sequel; gem bump\n\n# this also bumps sinja-sequel\ncd /tmp/sinja/extensions/sinja-sequel; gem bump sinja-sequel\n```\n\n### Demo\n\n![gem-release-scenario-4](https://cloud.githubusercontent.com/assets/2208/25634576/68dce4a6-2f7b-11e7-9d6b-571d672e4998.gif)\n\n## Scenario 5: Nested gem with an irregular sub directory name\n\n### Setup\n\n```\ncd /tmp\nrm -rf sinja\ngem bootstrap sinja\ncd sinja\nmkdir -p extensions\ncd extensions\ngem bootstrap sinja-sequel\nmv sinja-sequel sequel\ncd /tmp/sinja\ntree -a -I .git\n```\n\n### Directory structure\n\n```\n.\n├── Gemfile\n├── LICENSE.md\n├── extensions\n│   └── sequel\n│       ├── Gemfile\n│       ├── LICENSE.md\n│       ├── lib\n│       │   └── sinja\n│       │       ├── sequel\n│       │       │   └── version.rb\n│       │       └── sequel.rb\n│       └── sinja-sequel.gemspec\n├── lib\n│   ├── sinja\n│   │   └── version.rb\n│   └── sinja.rb\n└── sinja.gemspec\n```\n\n### Behaviour\n\n```\n# this bumps both sinja and sinja-sequel\ncd /tmp/sinja; gem bump --recurse\n\n# this bumps sinja\ncd /tmp/sinja; gem bump\n\n# this also bumps sinja\ncd /tmp/sinja; gem bump sinja\n\n# this bumps sinja-sequel only\ncd /tmp/sinja; gem bump sinja-sequel\n\n# this also bumps sinja-sequel only\ncd /tmp/sinja/extensions/sequel; gem bump\n\n# this also bumps sinja-sequel only\ncd /tmp/sinja/extensions/sequel; gem bump sinja-sequel\n```\n\n### Demo\n\n![gem-release-scenario-5](https://cloud.githubusercontent.com/assets/2208/25634574/68d6d138-2f7b-11e7-9e64-e4c86cb85b9a.gif)\n\n\n# Development\n\nRunning tests:\n\n```\nbundle install\nbundle exec rspec\n```\n\nTesting commands against a [Geminabox](https://github.com/geminabox/geminabox) instance:\n\n```\n# start geminabox\nbundle install\nbundle exec rackup\n\n# workaround rubygems issue with a missing key\n# see https://github.com/geminabox/geminabox/issues/153\necho ':localhost: none' \u003e\u003e ~/.gem/credentials\n\n# test release\nbundle exec gem release --host=http://localhost:9292 --key localhost\n```\n","funding_links":[],"categories":["Releasing","Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsvenfuchs%2Fgem-release","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsvenfuchs%2Fgem-release","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsvenfuchs%2Fgem-release/lists"}