Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .github/release-rules/checks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"target": "branch",
"enforcement": "active",
"conditions": {
"ref_name": {
"include": [
"refs/heads/main"
],
"exclude": []
}
},
"name": "Gem release checks",
"bypass_actors": [
{
"actor_id": 5,
"actor_type": "RepositoryRole",
"bypass_mode": "pull_request"
}
],
"rules": [
{
"type": "required_status_checks",
"parameters": {
"strict_required_status_checks_policy": true,
"do_not_enforce_on_create": false,
"required_status_checks": [
{
"context": "Test Ruby 3.3"
},
{
"context": "Test Ruby 3.4"
},
{
"context": "Test Ruby 4.0"
},
{
"context": "RuboCop"
},
{
"context": "Documentation coverage"
},
{
"context": "Release validation"
}
]
}
}
]
}
22 changes: 22 additions & 0 deletions .github/release-rules/history.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"target": "branch",
"enforcement": "active",
"conditions": {
"ref_name": {
"include": [
"refs/heads/main"
],
"exclude": []
}
},
"name": "Gem release history",
"bypass_actors": [],
"rules": [
{
"type": "deletion"
},
{
"type": "non_fast_forward"
}
]
}
36 changes: 36 additions & 0 deletions .github/release-rules/reviews.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"target": "branch",
"enforcement": "active",
"conditions": {
"ref_name": {
"include": [
"refs/heads/main"
],
"exclude": []
}
},
"name": "Gem release reviews",
"bypass_actors": [
{
"actor_id": 5,
"actor_type": "RepositoryRole",
"bypass_mode": "pull_request"
}
],
"rules": [
{
"type": "pull_request",
"parameters": {
"required_approving_review_count": 2,
"dismiss_stale_reviews_on_push": true,
"require_last_push_approval": true,
"required_review_thread_resolution": true,
"require_code_owner_review": false,
"allowed_merge_methods": [
"merge",
"squash"
]
}
}
]
}
22 changes: 22 additions & 0 deletions .github/release-rules/tags.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "Gem release tags",
"target": "tag",
"enforcement": "active",
"bypass_actors": [],
"conditions": {
"ref_name": {
"include": [
"refs/tags/v*"
],
"exclude": []
}
},
"rules": [
{
"type": "deletion"
},
{
"type": "non_fast_forward"
}
]
}
2 changes: 1 addition & 1 deletion templates/RELEASING.md → .github/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Prepare releases with `bundle exec bake gem:github:release:patch` (or `minor` /

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.

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.
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.

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.

Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/documentation-coverage.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Documentation coverage

on: [push, pull_request]

permissions:
contents: read

env:
BUNDLE_WITH: maintenance

jobs:
validate:
name: Documentation coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- uses: ruby/setup-ruby@a0102e0972be65f351c307e2d64b9314a57c8073 # v1
with:
ruby-version: "3.4"
bundler-cache: true
- name: Check library documentation
timeout-minutes: 5
run: bundle exec bake decode:index:coverage lib
45 changes: 45 additions & 0 deletions .github/workflows/release-prepare.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Prepare release

on:
workflow_dispatch:
inputs:
bump:
description: Version increment
required: true
type: choice
options: [patch, minor, major]

permissions:
contents: write
pull-requests: write

concurrency:
group: release-prepare
cancel-in-progress: false

env:
BUNDLE_WITH: maintenance

jobs:
prepare:
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
ref: main
fetch-depth: 0
persist-credentials: false
- uses: ruby/setup-ruby@a0102e0972be65f351c307e2d64b9314a57c8073 # v1
with:
ruby-version: "3.4"
bundler-cache: true
- name: Create release PR
env:
GH_TOKEN: ${{ github.token }}
BUMP: ${{ inputs.bump }}
run: |
git config user.name 'github-actions[bot]'
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
case "$BUMP" in patch|minor|major) ;; *) exit 1 ;; esac
bundle exec bake "gem:github:release:$BUMP"
101 changes: 101 additions & 0 deletions .github/workflows/release-publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: Publish release

# Only merged source is executed. Validation of unmerged PRs lives in its own
# read-only pull_request workflow. This trigger also supports reviewed fork PRs.
on:
pull_request_target:
types: [closed]
branches: ["main"]

permissions:
contents: read
pull-requests: read

concurrency:
group: release-publish
cancel-in-progress: false

env:
BUNDLE_WITH: maintenance
RELEASE_PR: ${{ github.event.pull_request.number }}

jobs:
inspect:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
outputs:
release: ${{ steps.inspect.outputs.release }}
commit: ${{ steps.inspect.outputs.commit }}
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
fetch-depth: 0
persist-credentials: false
- uses: ruby/setup-ruby@a0102e0972be65f351c307e2d64b9314a57c8073 # v1
with:
ruby-version: "3.4"
bundler-cache: true
- id: inspect
env:
GH_TOKEN: ${{ github.token }}
run: bundle exec bake gem:github:release:resolve

publish:
needs: inspect
if: needs.inspect.outputs.release == 'true'
runs-on: ubuntu-latest
environment: rubygems
permissions:
contents: write
pull-requests: read
actions: read
id-token: write
attestations: write
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
ref: ${{ needs.inspect.outputs.commit }}
fetch-depth: 0
persist-credentials: false
- uses: ruby/setup-ruby@a0102e0972be65f351c307e2d64b9314a57c8073 # v1
with:
ruby-version: "3.4"
rubygems: '4.0.21'
bundler-cache: true
- name: Build or restore artifact
id: build
env:
GH_TOKEN: ${{ github.token }}
GEM_SIGNING_KEY: ${{ secrets.GEM_SIGNING_KEY }}
run: bundle exec bake gem:github:release:build
- name: Sign RubyGems attestation
if: steps.build.outputs.restored != 'true'
env:
PACKAGE: ${{ steps.build.outputs.package }}
run: gem exec sigstore-cli:0.2.3 sign "$PACKAGE" --bundle "$PACKAGE.sigstore.json"
- name: Attest exact source and artifact
if: steps.build.outputs.restored != 'true'
id: attest
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4
with:
subject-path: ${{ steps.build.outputs.package }}
predicate-type: https://slsa.dev/provenance/v1
predicate-path: pkg/provenance.json
- name: Retain provenance bundle
if: steps.build.outputs.restored != 'true'
env:
ATTESTATION_BUNDLE: ${{ steps.attest.outputs.bundle-path }}
run: cp "$ATTESTATION_BUNDLE" pkg/provenance.sigstore.json
- name: Preserve release before upload
if: steps.build.outputs.restored != 'true'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: ${{ steps.build.outputs.artifact }}
path: pkg/
if-no-files-found: error
retention-days: 90
- uses: rubygems/configure-rubygems-credentials@2a7221c7c44c30ebc68eda38fa25c60b918245c7
- name: Verify, publish, and finalize
env:
GH_TOKEN: ${{ github.token }}
run: bundle exec bake gem:github:release:publish
32 changes: 32 additions & 0 deletions .github/workflows/release-validate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Validate release

on:
pull_request:
branches: ["main"]

permissions:
contents: read

env:
BUNDLE_WITH: maintenance

jobs:
validate:
name: Release validation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
persist-credentials: false
- uses: ruby/setup-ruby@a0102e0972be65f351c307e2d64b9314a57c8073 # v1
with:
ruby-version: "3.4"
bundler-cache: true
- name: Regenerate release content
env:
RELEASE_BASE: ${{ github.event.pull_request.base.sha }}
run: bundle exec bake gem:release:validate "base=$RELEASE_BASE" optional=true
- name: Build unsigned package
run: bundle exec bake gem:build signing_key=false
20 changes: 20 additions & 0 deletions .github/workflows/rubocop.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: RuboCop

on: [push, pull_request]

permissions:
contents: read

jobs:
check:
name: RuboCop
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- uses: ruby/setup-ruby@a0102e0972be65f351c307e2d64b9314a57c8073 # v1
with:
ruby-version: "3.4"
bundler-cache: true
- name: Check Ruby and documentation style
timeout-minutes: 10
run: bundle exec rubocop
24 changes: 24 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Test

on: [push, pull_request]

permissions:
contents: read

jobs:
test:
name: Test Ruby ${{ matrix.ruby }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ruby: ["3.3", "3.4", "4.0"]
steps:
- uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
- uses: ruby/setup-ruby@a0102e0972be65f351c307e2d64b9314a57c8073 # v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run tests
timeout-minutes: 10
run: bundle exec sus-parallel
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
/coverage/
/gems.locked
/pkg/
/vendor/bundle/
Loading
Loading