Skip to content

Commit fbf77e0

Browse files
Merge pull request #2 from fac/devp/v1.1.0
Devp/v1.1.0 See: fac/dev-platform#62
2 parents 81dca54 + 659a9b3 commit fbf77e0

File tree

5 files changed

+192
-15
lines changed

5 files changed

+192
-15
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22

33
## [Unreleased]
44

5+
## [1.1.0] - 2021-04-15
6+
7+
- Add: input release: Whether to push release versions
8+
- Add: input pre-release: Whether to push pre-release versions
9+
- Add: input tag-release: After pushing a new gem version, git tag with the version string
10+
- Add: output pushed-version: the version of the gem pushed to the repository
11+
512
## [1.0.0] - 2021-04-15
613

714
- Add basic action that pushes gems to the repository

README.md

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,15 @@ If the gem version already exists in the repo the action will no-op and still se
88

99
## Usage
1010

11+
The action expects that you have already checked out your gem and setup your ruby environment (bundle installed), such that gem and ruby commands are availiable. The easiest way to do this is using `actions/checkout` and `ruby/setup-ruby` actions with a `.ruby-version` file. See example below.
12+
13+
### Basic Setup
14+
15+
Build and push all new version of the gem:
16+
1117
```yaml
1218
steps:
19+
# Setup ruby environment
1320
- uses: actions/checkout@v2
1421
- uses: ruby/setup-ruby@v1 # .ruby-version
1522

@@ -36,6 +43,62 @@ If you want to use a different gem host or key:
3643
gem_host_api_key: ${{ secrets.EXAMPLE_APYI_KEY }}
3744
```
3845
46+
### Separate release and pre-release workflow
47+
48+
You probably don't want to push all versions from any branch. More likely you would want to push release versions from your default branch (e.g. main) and pre-release from PR builds. To help with this the release and pre-release inputs can be used:
49+
50+
```yaml
51+
name: Gem Build and Release
52+
on:
53+
push:
54+
branches:
55+
- main
56+
pull_request:
57+
58+
jobs:
59+
test:
60+
name: Gem / Test
61+
runs-on: ubuntu-latest
62+
steps:
63+
- uses: actions/checkout@v2
64+
- uses: ruby/setup-ruby@v1
65+
- name: Test
66+
run: bundle exec rake
67+
68+
release:
69+
name: Gem / Release
70+
needs: test
71+
runs-on: ubuntu-latest
72+
73+
steps:
74+
- uses: actions/checkout@v2
75+
- uses: ruby/setup-ruby@v1
76+
77+
- name: Build Gem
78+
run: bundle exec rake build
79+
80+
- name: Setup GPR
81+
uses: fac/rubygems-setup-gpr-action@v1
82+
with:
83+
token: ${{ secrets.github_token }}
84+
85+
# Release production gem version from default branch
86+
- name: Push Release Gem
87+
if: github.ref == 'refs/heads/main'
88+
uses: fac/rubygems-push-action@v1
89+
90+
# PR branch builds will release pre-release gems
91+
- name: Push Pre-Release Gem
92+
if: github.ref != 'refs/heads/main'
93+
uses: fac/rubygems-push-action@v1
94+
with:
95+
release: false
96+
pre-release: true
97+
```
98+
99+
Here we run the test on its own job, so that it gets it's own status on the PR, that you can require separately from the release job in your branch protection.
100+
The release job runs if the tests pass, we always package the gem to test that works. For release we use a conditional along with the actions inputs to push release versions for the main branch only and push pre-releases for PR.
101+
39102
## Inputs
40103
41104
### package-glob
@@ -49,9 +112,28 @@ File glob to match the gem file to push. The default `pkg/*.gem` picks up gems b
49112
package-glob: build/special.gem
50113
```
51114

115+
### release
116+
117+
Whether to push new release versions of the gem. Defaults to true.
118+
119+
### pre-release
120+
121+
Whether to push new pre-release versions of the gem. Defaults to true.
122+
123+
### tag-release
124+
125+
When true (the default), after pushing a new gem version tag the repo with
126+
the version number prefixed with `v`. e.g. after pushing version `0.1.0`, the
127+
tag will be `v0.1.0`. This is the same behavior as `gem tag`, but internally
128+
implemented to work with older gem versions.
129+
130+
The tag commit and push will be made as the author of the commit being tagged.
131+
52132
## Outputs
53133

54-
None.
134+
### pushed-version
135+
136+
If we pushed a gem to the repository, this will be set to the version pushed.
55137

56138
## Environment Variables
57139

action.yml

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,37 @@
11
# See: https://docs.github.com/en/actions/creating-actions
22
name: Gem Push
33
author: FreeAgent
4-
description: Push gem packages to a rubygems compatible repo
4+
description: Push gem packages to a rubygems compatible repository
55
inputs:
66
package-glob:
7-
description: "File glob to match the .gem files to push"
7+
description: File glob to match the .gem files to push
88
default: "pkg/*.gem"
9+
release:
10+
description: Whether to push release versions
11+
default: true
12+
pre-release:
13+
description: Whether to push pre-release versions
14+
default: true
15+
tag-release:
16+
description: After pushing a new gem version, git tag with the version string
17+
default: true
18+
outputs:
19+
pushed-version:
20+
description: "The version of the gem pushed to the repository"
21+
value: ${{ steps.push-gem.outputs.pushed-version }}
922

1023
runs:
1124
using: "composite"
1225
steps:
1326
- name: Push Gem
27+
id: push-gem
1428
shell: bash
1529
env:
1630
# Expects GEM_HOST and GEM_HOST_API_KEY to be set
17-
GEM_GLOB: ${{ inputs.package-glob }}
31+
INPUT_PACKAGE_GLOB: ${{ inputs.package-glob }}
32+
INPUT_RELEASE: ${{ inputs.release }}
33+
INPUT_PRE_RELEASE: ${{ inputs.pre-release }}
34+
INPUT_TAG_RELEASE: ${{ inputs.tag-release }}
1835
run: |
19-
if ! gem push --host "$GEM_HOST" $GEM_GLOB | tee push.out; then
20-
gemerr=$?
21-
if grep "has already been pushed" push.out; then
22-
echo Gem Already Pushed
23-
exit 0
24-
fi
25-
echo ::error::Gem Push Failed
26-
cat push.out | sed 's/^/::error::/'
27-
exit $gemerr
28-
fi
29-
exit 0
36+
PATH="${{ github.action_path }}:$PATH"
37+
gem-push-action

gem-push-action

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/bash
2+
set -e -o pipefail
3+
4+
if parse-gemspec --is-pre-release; then
5+
if [[ $INPUT_PRE_RELEASE != true ]]; then
6+
echo "Ignoring pre-release. To release, pass pre-release: true as an input"
7+
exit 0
8+
fi
9+
elif [[ $INPUT_RELEASE != true ]]; then
10+
echo "Ignoring release. To release, pass release: true as an input"
11+
exit 0
12+
fi
13+
14+
# tee the output to get it in the logs but capture as we can't tell why gem
15+
# push failed from the exit code, so need to grep the output. Gem existing is
16+
# ok, other errors not. Avoids playing games setting up auth differently for
17+
# gem query.
18+
# Note: the glob is intentially unquoted, we want a glob!
19+
if ! gem push --host "$GEM_HOST" $INPUT_PACKAGE_GLOB | tee push.out; then
20+
gemerr=$?
21+
if grep -q "has already been pushed" push.out; then
22+
echo Gem Already Pushed
23+
exit 0
24+
fi
25+
echo ::error::Gem Push Failed
26+
sed 's/^/::error::/' push.out
27+
exit $gemerr
28+
fi
29+
30+
echo "::set-output name=pushed-version::$( parse-gemspec --version )"
31+
32+
if [[ $INPUT_TAG_RELEASE == true ]]; then
33+
tagname="v$( parse-gemspec --version )"
34+
git config user.name "$(git log -1 --pretty=format:%an)"
35+
git config user.email "$(git log -1 --pretty=format:%ae)"
36+
git tag -a -m "Gem release $tagname" "$tagname"
37+
git push origin "$tagname"
38+
fi
39+
40+
exit 0

parse-gemspec

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/usr/bin/env ruby
2+
3+
require 'optparse'
4+
5+
gemspecs = Dir["*.gemspec"]
6+
7+
if gemspecs.empty?
8+
warn "No gemspec found"
9+
exit 10
10+
end
11+
12+
if gemspecs.count > 1
13+
warn "More than one gemspec found"
14+
exit 10
15+
end
16+
17+
spec = Gem::Specification.load(gemspecs.first)
18+
exit 10 unless spec
19+
20+
def puts!(msg)
21+
puts msg
22+
exit
23+
end
24+
25+
OptionParser.new do |opts|
26+
opts.banner = "Usage: #{File.basename($0)} [options]"
27+
opts.on("-h", "--help", "Prints this help") do
28+
puts! opts
29+
end
30+
opts.on("--name", "Output gemspec name") do |v|
31+
puts! spec.name
32+
end
33+
opts.on("--version", "Output gemspec gem version") do |v|
34+
puts! spec.version
35+
end
36+
opts.on("--is-pre-release", "Exit 0 if pre-release, 1 otherwise") do |v|
37+
exit 0 if spec.version.prerelease?
38+
exit 1
39+
end
40+
end.parse!

0 commit comments

Comments
 (0)