Skip to content

Commit 9be8317

Browse files
Set up reviewed releases for bake-gem-github. (#1)
1 parent cf5b033 commit 9be8317

25 files changed

Lines changed: 886 additions & 9 deletions

‎.github/release-rules/checks.json‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"target": "branch",
3+
"enforcement": "active",
4+
"conditions": {
5+
"ref_name": {
6+
"include": [
7+
"refs/heads/main"
8+
],
9+
"exclude": []
10+
}
11+
},
12+
"name": "Gem release checks",
13+
"bypass_actors": [
14+
{
15+
"actor_id": 5,
16+
"actor_type": "RepositoryRole",
17+
"bypass_mode": "pull_request"
18+
}
19+
],
20+
"rules": [
21+
{
22+
"type": "required_status_checks",
23+
"parameters": {
24+
"strict_required_status_checks_policy": true,
25+
"do_not_enforce_on_create": false,
26+
"required_status_checks": [
27+
{
28+
"context": "Test Ruby 3.3"
29+
},
30+
{
31+
"context": "Test Ruby 3.4"
32+
},
33+
{
34+
"context": "Test Ruby 4.0"
35+
},
36+
{
37+
"context": "RuboCop"
38+
},
39+
{
40+
"context": "Documentation coverage"
41+
},
42+
{
43+
"context": "Release validation"
44+
}
45+
]
46+
}
47+
}
48+
]
49+
}

‎.github/release-rules/history.json‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"target": "branch",
3+
"enforcement": "active",
4+
"conditions": {
5+
"ref_name": {
6+
"include": [
7+
"refs/heads/main"
8+
],
9+
"exclude": []
10+
}
11+
},
12+
"name": "Gem release history",
13+
"bypass_actors": [],
14+
"rules": [
15+
{
16+
"type": "deletion"
17+
},
18+
{
19+
"type": "non_fast_forward"
20+
}
21+
]
22+
}

‎.github/release-rules/reviews.json‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"target": "branch",
3+
"enforcement": "active",
4+
"conditions": {
5+
"ref_name": {
6+
"include": [
7+
"refs/heads/main"
8+
],
9+
"exclude": []
10+
}
11+
},
12+
"name": "Gem release reviews",
13+
"bypass_actors": [
14+
{
15+
"actor_id": 5,
16+
"actor_type": "RepositoryRole",
17+
"bypass_mode": "pull_request"
18+
}
19+
],
20+
"rules": [
21+
{
22+
"type": "pull_request",
23+
"parameters": {
24+
"required_approving_review_count": 2,
25+
"dismiss_stale_reviews_on_push": true,
26+
"require_last_push_approval": true,
27+
"required_review_thread_resolution": true,
28+
"require_code_owner_review": false,
29+
"allowed_merge_methods": [
30+
"merge",
31+
"squash"
32+
]
33+
}
34+
}
35+
]
36+
}

‎.github/release-rules/tags.json‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "Gem release tags",
3+
"target": "tag",
4+
"enforcement": "active",
5+
"bypass_actors": [],
6+
"conditions": {
7+
"ref_name": {
8+
"include": [
9+
"refs/tags/v*"
10+
],
11+
"exclude": []
12+
}
13+
},
14+
"rules": [
15+
{
16+
"type": "deletion"
17+
},
18+
{
19+
"type": "non_fast_forward"
20+
}
21+
]
22+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Prepare releases with `bundle exec bake gem:github:release:patch` (or `minor` /
44

55
Review the entire release diff. Native GitHub rules require the configured reviews and CI, including an up-to-date branch and **Release validation**. Administrators can explicitly bypass the review/check rules. A rebase is sufficient only if regenerated content still matches. If notes are stale, prepare again from the current default branch and preserve any manual edits separately for review.
66

7-
Merging a version increase publishes the actual merged commit through `release-publish.yaml`. There is no second release approval. The public `release.cert` stays in Git; the optional private key belongs in the `rubygems` environment secret `GEM_SIGNING_KEY`. RubyGems authentication uses Trusted Publishing.
7+
Merging a version increase publishes the actual merged commit through `release-publish.yaml`. There is no second release approval. The public `release.cert` stays in Git; the optional private key belongs in the Actions secret `GEM_SIGNING_KEY`, supplied by the `rubygems` environment or an organization secret. RubyGems authentication uses Trusted Publishing.
88

99
If a publishing job fails, use **Re-run all jobs** on that same workflow run, or `bundle exec bake gem:github:release:resume run=RUN_ID`. The original artifact is downloaded before another upload is attempted. Do not create a replacement version bump or rebuild an already-published version. Conflicting bytes or tags require investigation; never automatically yank a version or move a tag.
1010

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Documentation coverage
2+
3+
on: [push, pull_request]
4+
5+
permissions:
6+
contents: read
7+
8+
env:
9+
BUNDLE_WITH: maintenance
10+
11+
jobs:
12+
validate:
13+
name: Documentation coverage
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
17+
- uses: ruby/setup-ruby@a0102e0972be65f351c307e2d64b9314a57c8073 # v1
18+
with:
19+
ruby-version: "3.4"
20+
bundler-cache: true
21+
- name: Check library documentation
22+
timeout-minutes: 5
23+
run: bundle exec bake decode:index:coverage lib
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Prepare release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
bump:
7+
description: Version increment
8+
required: true
9+
type: choice
10+
options: [patch, minor, major]
11+
12+
permissions:
13+
contents: write
14+
pull-requests: write
15+
16+
concurrency:
17+
group: release-prepare
18+
cancel-in-progress: false
19+
20+
env:
21+
BUNDLE_WITH: maintenance
22+
23+
jobs:
24+
prepare:
25+
if: github.ref == 'refs/heads/main'
26+
runs-on: ubuntu-latest
27+
steps:
28+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
29+
with:
30+
ref: main
31+
fetch-depth: 0
32+
persist-credentials: false
33+
- uses: ruby/setup-ruby@a0102e0972be65f351c307e2d64b9314a57c8073 # v1
34+
with:
35+
ruby-version: "3.4"
36+
bundler-cache: true
37+
- name: Create release PR
38+
env:
39+
GH_TOKEN: ${{ github.token }}
40+
BUMP: ${{ inputs.bump }}
41+
run: |
42+
git config user.name 'github-actions[bot]'
43+
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
44+
case "$BUMP" in patch|minor|major) ;; *) exit 1 ;; esac
45+
bundle exec bake "gem:github:release:$BUMP"
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: Publish release
2+
3+
# Only merged source is executed. Validation of unmerged PRs lives in its own
4+
# read-only pull_request workflow. This trigger also supports reviewed fork PRs.
5+
on:
6+
pull_request_target:
7+
types: [closed]
8+
branches: ["main"]
9+
10+
permissions:
11+
contents: read
12+
pull-requests: read
13+
14+
concurrency:
15+
group: release-publish
16+
cancel-in-progress: false
17+
18+
env:
19+
BUNDLE_WITH: maintenance
20+
RELEASE_PR: ${{ github.event.pull_request.number }}
21+
22+
jobs:
23+
inspect:
24+
if: github.event.pull_request.merged == true
25+
runs-on: ubuntu-latest
26+
outputs:
27+
release: ${{ steps.inspect.outputs.release }}
28+
commit: ${{ steps.inspect.outputs.commit }}
29+
steps:
30+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
31+
with:
32+
fetch-depth: 0
33+
persist-credentials: false
34+
- uses: ruby/setup-ruby@a0102e0972be65f351c307e2d64b9314a57c8073 # v1
35+
with:
36+
ruby-version: "3.4"
37+
bundler-cache: true
38+
- id: inspect
39+
env:
40+
GH_TOKEN: ${{ github.token }}
41+
run: bundle exec bake gem:github:release:resolve
42+
43+
publish:
44+
needs: inspect
45+
if: needs.inspect.outputs.release == 'true'
46+
runs-on: ubuntu-latest
47+
environment: rubygems
48+
permissions:
49+
contents: write
50+
pull-requests: read
51+
actions: read
52+
id-token: write
53+
attestations: write
54+
steps:
55+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
56+
with:
57+
ref: ${{ needs.inspect.outputs.commit }}
58+
fetch-depth: 0
59+
persist-credentials: false
60+
- uses: ruby/setup-ruby@a0102e0972be65f351c307e2d64b9314a57c8073 # v1
61+
with:
62+
ruby-version: "3.4"
63+
rubygems: '4.0.21'
64+
bundler-cache: true
65+
- name: Build or restore artifact
66+
id: build
67+
env:
68+
GH_TOKEN: ${{ github.token }}
69+
GEM_SIGNING_KEY: ${{ secrets.GEM_SIGNING_KEY }}
70+
run: bundle exec bake gem:github:release:build
71+
- name: Sign RubyGems attestation
72+
if: steps.build.outputs.restored != 'true'
73+
env:
74+
PACKAGE: ${{ steps.build.outputs.package }}
75+
run: gem exec sigstore-cli:0.2.3 sign "$PACKAGE" --bundle "$PACKAGE.sigstore.json"
76+
- name: Attest exact source and artifact
77+
if: steps.build.outputs.restored != 'true'
78+
id: attest
79+
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4
80+
with:
81+
subject-path: ${{ steps.build.outputs.package }}
82+
predicate-type: https://slsa.dev/provenance/v1
83+
predicate-path: pkg/provenance.json
84+
- name: Retain provenance bundle
85+
if: steps.build.outputs.restored != 'true'
86+
env:
87+
ATTESTATION_BUNDLE: ${{ steps.attest.outputs.bundle-path }}
88+
run: cp "$ATTESTATION_BUNDLE" pkg/provenance.sigstore.json
89+
- name: Preserve release before upload
90+
if: steps.build.outputs.restored != 'true'
91+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
92+
with:
93+
name: ${{ steps.build.outputs.artifact }}
94+
path: pkg/
95+
if-no-files-found: error
96+
retention-days: 90
97+
- uses: rubygems/configure-rubygems-credentials@2a7221c7c44c30ebc68eda38fa25c60b918245c7
98+
- name: Verify, publish, and finalize
99+
env:
100+
GH_TOKEN: ${{ github.token }}
101+
run: bundle exec bake gem:github:release:publish
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Validate release
2+
3+
on:
4+
pull_request:
5+
branches: ["main"]
6+
7+
permissions:
8+
contents: read
9+
10+
env:
11+
BUNDLE_WITH: maintenance
12+
13+
jobs:
14+
validate:
15+
name: Release validation
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
19+
with:
20+
ref: ${{ github.event.pull_request.head.sha }}
21+
fetch-depth: 0
22+
persist-credentials: false
23+
- uses: ruby/setup-ruby@a0102e0972be65f351c307e2d64b9314a57c8073 # v1
24+
with:
25+
ruby-version: "3.4"
26+
bundler-cache: true
27+
- name: Regenerate release content
28+
env:
29+
RELEASE_BASE: ${{ github.event.pull_request.base.sha }}
30+
run: bundle exec bake gem:release:validate "base=$RELEASE_BASE" optional=true
31+
- name: Build unsigned package
32+
run: bundle exec bake gem:build signing_key=false

‎.github/workflows/rubocop.yaml‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: RuboCop
2+
3+
on: [push, pull_request]
4+
5+
permissions:
6+
contents: read
7+
8+
jobs:
9+
check:
10+
name: RuboCop
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
14+
- uses: ruby/setup-ruby@a0102e0972be65f351c307e2d64b9314a57c8073 # v1
15+
with:
16+
ruby-version: "3.4"
17+
bundler-cache: true
18+
- name: Check Ruby and documentation style
19+
timeout-minutes: 10
20+
run: bundle exec rubocop

0 commit comments

Comments
 (0)