veragem 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +53 -0
- data/LICENSE-APACHE +201 -0
- data/LICENSE-MIT +7 -0
- data/README.md +151 -0
- data/lib/veragem/generator.rb +109 -0
- data/lib/veragem/name.rb +111 -0
- data/lib/veragem/options.rb +53 -0
- data/lib/veragem/project.rb +77 -0
- data/lib/veragem/version.rb +5 -0
- data/lib/veragem.rb +23 -0
- data/plugins.rb +15 -0
- data/sig/bundler.rbs +10 -0
- data/sig/veragem.rbs +79 -0
- data/template/%name%.gemspec.erb +30 -0
- data/template/.editorconfig +15 -0
- data/template/.githooks/commit-msg +12 -0
- data/template/.githooks/pre-commit +6 -0
- data/template/.githooks/pre-push +17 -0
- data/template/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
- data/template/.github/ISSUE_TEMPLATE/config.yml.erb +5 -0
- data/template/.github/ISSUE_TEMPLATE/documentation.md +19 -0
- data/template/.github/ISSUE_TEMPLATE/feature_request.md +15 -0
- data/template/.github/PULL_REQUEST_TEMPLATE.md +14 -0
- data/template/.github/dependabot.yml +85 -0
- data/template/.github/image-registries.sh +31 -0
- data/template/.github/release-notes.sh +13 -0
- data/template/.github/workflows/dependabot-automerge.yml +70 -0
- data/template/.github/workflows/dependency-review.yml +50 -0
- data/template/.github/workflows/image.yml +140 -0
- data/template/.github/workflows/nix.yml +46 -0
- data/template/.github/workflows/release.yml +117 -0
- data/template/.github/workflows/rubocop-autocorrect.yml +114 -0
- data/template/.github/workflows/ruby-ci.yml +62 -0
- data/template/.github/workflows/security.yml +43 -0
- data/template/.github/workflows/style-check-cocogitto.yml +56 -0
- data/template/.github/workflows/style-check-dprint.yml +44 -0
- data/template/.gitignore +12 -0
- data/template/.rubocop.yml +27 -0
- data/template/AGENTS.md.erb +75 -0
- data/template/CODE_OF_CONDUCT.md.erb +18 -0
- data/template/CONTRIBUTING.md.erb +183 -0
- data/template/Gemfile +24 -0
- data/template/LICENSE-APACHE.erb +201 -0
- data/template/LICENSE-MIT.erb +7 -0
- data/template/README.md.erb +82 -0
- data/template/Rakefile +136 -0
- data/template/SECURITY.md.erb +21 -0
- data/template/Steepfile.erb +11 -0
- data/template/bin/console.erb +8 -0
- data/template/bin/setup +5 -0
- data/template/cliff.toml +70 -0
- data/template/cog.toml +8 -0
- data/template/dprint.json +23 -0
- data/template/exe/%name%.erb +6 -0
- data/template/flake.lock +27 -0
- data/template/flake.nix +213 -0
- data/template/lib/%path%/cli.rb.erb +45 -0
- data/template/lib/%path%/version.rb.erb +3 -0
- data/template/lib/%path%.rb.erb +13 -0
- data/template/sig/%path%.rbs.erb +16 -0
- data/template/test/test_%underscored%.rb.erb +27 -0
- data/template/test/test_cli.rb.erb +40 -0
- data/template/test/test_helper.rb.erb +15 -0
- data/template/typeprof.conf.jsonc +7 -0
- metadata +111 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: Dependency Review
|
|
2
|
+
|
|
3
|
+
# The licences and advisories of what a pull request adds to Gemfile.lock and the workflows, as the
|
|
4
|
+
# templates' Python and Rust ones review theirs. Advisory: it reports only when those files change,
|
|
5
|
+
# so no required check can be it, and dependabot-automerge.yml merges a bump it flags (security.yml's
|
|
6
|
+
# bundler-audit holds the lock daily).
|
|
7
|
+
on:
|
|
8
|
+
pull_request:
|
|
9
|
+
paths:
|
|
10
|
+
- "Gemfile"
|
|
11
|
+
- "Gemfile.lock"
|
|
12
|
+
- "*.gemspec"
|
|
13
|
+
- ".github/workflows/**"
|
|
14
|
+
|
|
15
|
+
permissions: {}
|
|
16
|
+
|
|
17
|
+
# NOTE: it needs the repository's dependency graph (Settings → Advanced
|
|
18
|
+
# Security), and on a private repository GitHub Code Security too (an
|
|
19
|
+
# organization's): without them, this job fails rather than skipping --
|
|
20
|
+
# enable them, or delete the workflow.
|
|
21
|
+
#
|
|
22
|
+
# What it reads: Gemfile.lock has no scopes, so each of its gems counts as
|
|
23
|
+
# runtime -- the gemspec's dependencies and the Gemfile's tools alike --;
|
|
24
|
+
# the actions for licences in effect: advisories match actions by semantic
|
|
25
|
+
# version alone, not the commits these are pinned to ("Dependency graph
|
|
26
|
+
# supported package ecosystems").
|
|
27
|
+
jobs:
|
|
28
|
+
dependency-review:
|
|
29
|
+
name: License & Security Check
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
permissions:
|
|
32
|
+
contents: read
|
|
33
|
+
# no checkout: the action compares the pull request's base and head through GitHub's API
|
|
34
|
+
steps:
|
|
35
|
+
- name: Dependency Review
|
|
36
|
+
uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
|
|
37
|
+
with:
|
|
38
|
+
fail-on-severity: moderate
|
|
39
|
+
# The licences are ClearlyDefined's, not the gemspecs'; a gem's:
|
|
40
|
+
# curl -s https://api.clearlydefined.io/definitions/gem/rubygems/-/NAME/VERSION
|
|
41
|
+
# (.licensed.declared). Add anything legitimate that is missing rather
|
|
42
|
+
# than deleting this list -- an empty allow-list allows everything.
|
|
43
|
+
# Ruby: Ruby's own licence, with MIT or BSD's (concurrent-ruby, reline)
|
|
44
|
+
allow-licenses: >
|
|
45
|
+
0BSD, Apache-2.0, BlueOak-1.0.0, BSD-2-Clause, BSD-3-Clause,
|
|
46
|
+
BSL-1.0, CC0-1.0, CC-BY-4.0, ISC, MIT, MIT-0, MPL-2.0,
|
|
47
|
+
Ruby, Unlicense, Zlib
|
|
48
|
+
# bundler-audit: GPL-3.0-or-later, a tool run here, never shipped. rake: MIT,
|
|
49
|
+
# to which ClearlyDefined adds a warranty disclaimer it takes for a licence
|
|
50
|
+
allow-dependencies-licenses: pkg:gem/bundler-audit, pkg:gem/rake
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# A release tag (`rake release`'s v<version>) publishes the command's OCI image to GHCR, as
|
|
2
|
+
# ghcr.io/<owner>/<repository>: the flake's `image` built on each Linux architecture, run once
|
|
3
|
+
# (`--version`), pushed per architecture, then joined under one multi-architecture tag, <version>
|
|
4
|
+
# (and `latest` while it is the highest release). The per-architecture tags (<version>-amd64,
|
|
5
|
+
# <version>-arm64) stay, the multi-architecture tag's parts. It runs beside release.yml, not after
|
|
6
|
+
# it: the image does not wait for the gem's push to RubyGems.
|
|
7
|
+
#
|
|
8
|
+
# The job's token pushes: no secret stored. A first push is private (GHCR's default): make the
|
|
9
|
+
# package public in its settings once.
|
|
10
|
+
#
|
|
11
|
+
# Docker Hub too, the same tags, once vars.DOCKERHUB_USERNAME and secrets.DOCKERHUB_TOKEN (an
|
|
12
|
+
# access token that writes) are set: as vars.DOCKERHUB_REPOSITORY, else <username>/<repository>. A
|
|
13
|
+
# Docker Hub failure in the build (its login, its name, a push) holds GHCR's multi-architecture tag
|
|
14
|
+
# back too; a re-run, once fixed, completes both.
|
|
15
|
+
#
|
|
16
|
+
# Run by hand (workflow_dispatch) on a branch, it builds and runs the image on both architectures,
|
|
17
|
+
# pushing nothing: a rehearsal before the first release; on a tag, it publishes that release again.
|
|
18
|
+
name: Image
|
|
19
|
+
|
|
20
|
+
on:
|
|
21
|
+
push:
|
|
22
|
+
tags: ["v[0-9]*"]
|
|
23
|
+
workflow_dispatch:
|
|
24
|
+
|
|
25
|
+
permissions: {}
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
build:
|
|
29
|
+
name: Build and run (${{ matrix.arch }})
|
|
30
|
+
runs-on: ${{ matrix.runner }}
|
|
31
|
+
strategy:
|
|
32
|
+
matrix:
|
|
33
|
+
include:
|
|
34
|
+
- runner: ubuntu-latest
|
|
35
|
+
arch: amd64
|
|
36
|
+
- runner: ubuntu-24.04-arm
|
|
37
|
+
arch: arm64
|
|
38
|
+
permissions:
|
|
39
|
+
contents: read
|
|
40
|
+
packages: write
|
|
41
|
+
outputs:
|
|
42
|
+
description: ${{ steps.build.outputs.description }}
|
|
43
|
+
steps:
|
|
44
|
+
- name: Checkout
|
|
45
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
46
|
+
with:
|
|
47
|
+
persist-credentials: false
|
|
48
|
+
|
|
49
|
+
- name: Install Nix
|
|
50
|
+
uses: cachix/install-nix-action@448cde739abec1eaf0646249e3d25bb8d9bc7702 # v31.11.2
|
|
51
|
+
|
|
52
|
+
- name: Build and run
|
|
53
|
+
id: build
|
|
54
|
+
run: |
|
|
55
|
+
set -euo pipefail
|
|
56
|
+
version="$(nix eval --raw .#image.imageTag)"
|
|
57
|
+
# a tag's version is the one version.rb declares at its commit, the image's tag
|
|
58
|
+
if [[ $GITHUB_REF_TYPE == tag && $GITHUB_REF_NAME != "v$version" ]]; then
|
|
59
|
+
echo "::error::$GITHUB_REF_NAME, but version.rb declares $version" >&2
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
# streamed into docker: no compressed copy of the closure in the store
|
|
63
|
+
stream="$(nix build --no-link --print-out-paths .#image.stream)"
|
|
64
|
+
"$stream" | docker load
|
|
65
|
+
loaded="$(nix eval --raw .#image.imageName):$version"
|
|
66
|
+
# the image as a user runs it: its entrypoint, as its user
|
|
67
|
+
expected="$(nix eval --raw .#image.imageName) $version"
|
|
68
|
+
actual="$(docker run --rm --pull never "$loaded" --version)"
|
|
69
|
+
if [[ $actual != "$expected" ]]; then
|
|
70
|
+
echo "::error::--version gave '$actual', expected '$expected'" >&2
|
|
71
|
+
exit 1
|
|
72
|
+
fi
|
|
73
|
+
# assigned first: a failing command substitution inside echo's arguments would not stop
|
|
74
|
+
# the step
|
|
75
|
+
description="$(nix eval --raw .#default.meta.description)"
|
|
76
|
+
echo "description=$description" >> "$GITHUB_OUTPUT"
|
|
77
|
+
|
|
78
|
+
- name: Push
|
|
79
|
+
if: github.ref_type == 'tag'
|
|
80
|
+
env:
|
|
81
|
+
GH_TOKEN: ${{ github.token }}
|
|
82
|
+
# Docker Hub too, when both are set (.github/image-registries.sh): an unset variable or
|
|
83
|
+
# secret is empty, and no `if:` can read a secret. The username is a variable, as in
|
|
84
|
+
# Docker's guide: a secret would be masked wherever it appears, GHCR's paths included
|
|
85
|
+
DOCKERHUB_USERNAME: ${{ vars.DOCKERHUB_USERNAME }}
|
|
86
|
+
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
87
|
+
DOCKERHUB_REPOSITORY: ${{ vars.DOCKERHUB_REPOSITORY }}
|
|
88
|
+
ARCH: ${{ matrix.arch }}
|
|
89
|
+
run: |
|
|
90
|
+
set -euo pipefail
|
|
91
|
+
repositories="$(.github/image-registries.sh)"
|
|
92
|
+
version="${GITHUB_REF_NAME#v}"
|
|
93
|
+
loaded="$(nix eval --raw .#image.imageName):$version"
|
|
94
|
+
# the list on its own descriptor: no command in the loop can read it away
|
|
95
|
+
while read -r repository <&3; do
|
|
96
|
+
docker tag "$loaded" "$repository:$version-$ARCH"
|
|
97
|
+
docker push "$repository:$version-$ARCH"
|
|
98
|
+
done 3<<< "$repositories"
|
|
99
|
+
|
|
100
|
+
publish:
|
|
101
|
+
name: Multi-architecture tag
|
|
102
|
+
needs: build
|
|
103
|
+
if: github.ref_type == 'tag'
|
|
104
|
+
runs-on: ubuntu-latest
|
|
105
|
+
permissions:
|
|
106
|
+
contents: read
|
|
107
|
+
packages: write
|
|
108
|
+
steps:
|
|
109
|
+
- name: Checkout
|
|
110
|
+
# every tag, to tell whether this one is the highest
|
|
111
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
112
|
+
with:
|
|
113
|
+
persist-credentials: false
|
|
114
|
+
fetch-depth: 0
|
|
115
|
+
|
|
116
|
+
- name: Join the architectures
|
|
117
|
+
env:
|
|
118
|
+
GH_TOKEN: ${{ github.token }}
|
|
119
|
+
DOCKERHUB_USERNAME: ${{ vars.DOCKERHUB_USERNAME }}
|
|
120
|
+
DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
121
|
+
DOCKERHUB_REPOSITORY: ${{ vars.DOCKERHUB_REPOSITORY }}
|
|
122
|
+
DESCRIPTION: ${{ needs.build.outputs.description }}
|
|
123
|
+
run: |
|
|
124
|
+
set -euo pipefail
|
|
125
|
+
repositories="$(.github/image-registries.sh)"
|
|
126
|
+
version="${GITHUB_REF_NAME#v}"
|
|
127
|
+
# `latest`: the highest final release (SemVer: no pre-release, no build metadata), so a
|
|
128
|
+
# patch to an older line leaves it where it is
|
|
129
|
+
highest="$(git tag --list 'v[0-9]*' | sed 's/^v//' \
|
|
130
|
+
| { grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' || true; } | sort -V | tail -n 1)"
|
|
131
|
+
# each repository's index from its own pushes: imagetools create's sources must be in
|
|
132
|
+
# the registry it writes to (its docs). The description is the index's annotation, as
|
|
133
|
+
# GHCR reads it for a multi-architecture image
|
|
134
|
+
while read -r repository <&3; do
|
|
135
|
+
tags=(--tag "$repository:$version")
|
|
136
|
+
if [[ $version == "$highest" ]]; then tags+=(--tag "$repository:latest"); fi
|
|
137
|
+
docker buildx imagetools create "${tags[@]}" \
|
|
138
|
+
--annotation "index:org.opencontainers.image.description=$DESCRIPTION" \
|
|
139
|
+
"$repository:$version-amd64" "$repository:$version-arm64"
|
|
140
|
+
done 3<<< "$repositories"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# The flake's checks (flake.nix): the Nix format, the shell scripts, the workflows, the gem built
|
|
2
|
+
# as a package (and a command's run, and its OCI image on Linux) -- built on each system the flake
|
|
3
|
+
# declares: x86_64 and aarch64 Linux, Apple silicon (macos-latest). The dev shell is built too, so
|
|
4
|
+
# each system's tools are known to install.
|
|
5
|
+
name: Nix
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
branches: [main]
|
|
10
|
+
# every pull request, whatever it touches: a path-filtered workflow never reports, and a
|
|
11
|
+
# required check that never reports blocks the merge
|
|
12
|
+
pull_request:
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
# a pull request's newest run cancels its older ones; any other run, a group of its own: every
|
|
16
|
+
# commit on main checked (in a shared group, a pending run gives way to the newest: the default)
|
|
17
|
+
concurrency:
|
|
18
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
|
19
|
+
cancel-in-progress: true
|
|
20
|
+
|
|
21
|
+
permissions:
|
|
22
|
+
contents: read
|
|
23
|
+
|
|
24
|
+
jobs:
|
|
25
|
+
flake-check:
|
|
26
|
+
name: nix flake check (${{ matrix.os }})
|
|
27
|
+
runs-on: ${{ matrix.os }}
|
|
28
|
+
strategy:
|
|
29
|
+
fail-fast: false
|
|
30
|
+
matrix:
|
|
31
|
+
os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest]
|
|
32
|
+
steps:
|
|
33
|
+
- name: Checkout
|
|
34
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
35
|
+
with:
|
|
36
|
+
persist-credentials: false
|
|
37
|
+
|
|
38
|
+
- name: Install Nix
|
|
39
|
+
# flakes on, and the job's token for GitHub fetches
|
|
40
|
+
uses: cachix/install-nix-action@448cde739abec1eaf0646249e3d25bb8d9bc7702 # v31.11.2
|
|
41
|
+
|
|
42
|
+
- name: nix flake check
|
|
43
|
+
run: nix flake check --print-build-logs
|
|
44
|
+
|
|
45
|
+
- name: The dev shell
|
|
46
|
+
run: nix develop --command ruby --version
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# A release tag, v<version> (`rake bump`, then `rake release`), publishes the gem: checked and built
|
|
2
|
+
# once, pushed to RubyGems through Trusted Publishing (no API key stored), then its GitHub release
|
|
3
|
+
# of the same file, its notes the release's section of CHANGELOG.md (release-notes.sh). Trusted
|
|
4
|
+
# Publishing needs, once, a (pending) trusted publisher on rubygems.org naming this repository,
|
|
5
|
+
# this workflow (release.yml) and the `release` environment.
|
|
6
|
+
#
|
|
7
|
+
# Least privilege, as RubyGems' Trusted Publishing advises, after PyPI's security model: the
|
|
8
|
+
# build, which runs the checks and the gemspec, writes nothing but its artifacts and mints no key;
|
|
9
|
+
# only the RubyGems job can mint one, with nothing checked out and no Gemfile or Rakefile loaded;
|
|
10
|
+
# only the release job can write the repository.
|
|
11
|
+
name: Release
|
|
12
|
+
|
|
13
|
+
on:
|
|
14
|
+
push:
|
|
15
|
+
tags: ["v[0-9]*"]
|
|
16
|
+
|
|
17
|
+
permissions: {}
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
build:
|
|
21
|
+
name: Check and build
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
permissions:
|
|
24
|
+
contents: read
|
|
25
|
+
steps:
|
|
26
|
+
- name: Checkout
|
|
27
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
28
|
+
with:
|
|
29
|
+
persist-credentials: false
|
|
30
|
+
|
|
31
|
+
- name: Set up Ruby
|
|
32
|
+
uses: ruby/setup-ruby@7f797815d8adceb1c412e7abefdd1ab4abc47a5f # v1.335.0
|
|
33
|
+
with:
|
|
34
|
+
ruby-version: "4.0"
|
|
35
|
+
|
|
36
|
+
- name: The gems, from Gemfile.lock
|
|
37
|
+
# installed afresh, not restored from bundler-cache: a cache any run on main can write is
|
|
38
|
+
# never an input to the gem published
|
|
39
|
+
env:
|
|
40
|
+
BUNDLE_FROZEN: "true"
|
|
41
|
+
run: bundle install
|
|
42
|
+
|
|
43
|
+
- name: RuboCop, Steep, the tests
|
|
44
|
+
run: bundle exec rake
|
|
45
|
+
|
|
46
|
+
- name: Build the gem, and its notes
|
|
47
|
+
run: |
|
|
48
|
+
set -euo pipefail
|
|
49
|
+
version="$(ruby -e 'puts Gem::Specification.load(Dir["*.gemspec"].first).version')"
|
|
50
|
+
if [[ $GITHUB_REF_NAME != "v$version" ]]; then
|
|
51
|
+
echo "::error::$GITHUB_REF_NAME, but the gemspec's version is $version" >&2
|
|
52
|
+
exit 1
|
|
53
|
+
fi
|
|
54
|
+
# into pkg/, as Bundler's gem tasks build it
|
|
55
|
+
bundle exec rake build
|
|
56
|
+
.github/release-notes.sh CHANGELOG.md "$version" > notes.md
|
|
57
|
+
|
|
58
|
+
- name: Keep the gem
|
|
59
|
+
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
60
|
+
with:
|
|
61
|
+
name: gem
|
|
62
|
+
path: pkg/
|
|
63
|
+
if-no-files-found: error
|
|
64
|
+
|
|
65
|
+
- name: Keep the notes
|
|
66
|
+
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
67
|
+
with:
|
|
68
|
+
name: notes
|
|
69
|
+
path: notes.md
|
|
70
|
+
if-no-files-found: error
|
|
71
|
+
|
|
72
|
+
rubygems:
|
|
73
|
+
name: RubyGems
|
|
74
|
+
needs: build
|
|
75
|
+
runs-on: ubuntu-latest
|
|
76
|
+
environment:
|
|
77
|
+
name: release
|
|
78
|
+
permissions:
|
|
79
|
+
id-token: write # the short-lived token Trusted Publishing exchanges for an API key
|
|
80
|
+
steps:
|
|
81
|
+
- name: The build's gem
|
|
82
|
+
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
83
|
+
with:
|
|
84
|
+
name: gem
|
|
85
|
+
path: pkg/
|
|
86
|
+
|
|
87
|
+
- name: Trusted Publishing's API key
|
|
88
|
+
uses: rubygems/configure-rubygems-credentials@dc5a8d8553e6ee01fc26761a49e99e733d17954a # v2.1.0
|
|
89
|
+
|
|
90
|
+
- name: Push
|
|
91
|
+
# the runner image's RubyGems: no other action in the one job that can mint a key
|
|
92
|
+
run: gem push pkg/*.gem
|
|
93
|
+
|
|
94
|
+
release:
|
|
95
|
+
name: GitHub release
|
|
96
|
+
needs: rubygems
|
|
97
|
+
runs-on: ubuntu-latest
|
|
98
|
+
permissions:
|
|
99
|
+
contents: write
|
|
100
|
+
steps:
|
|
101
|
+
- name: The build's gem
|
|
102
|
+
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
103
|
+
with:
|
|
104
|
+
name: gem
|
|
105
|
+
path: pkg/
|
|
106
|
+
|
|
107
|
+
- name: Its notes
|
|
108
|
+
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
109
|
+
with:
|
|
110
|
+
name: notes
|
|
111
|
+
|
|
112
|
+
- name: Release
|
|
113
|
+
env:
|
|
114
|
+
GH_TOKEN: ${{ github.token }}
|
|
115
|
+
run: |
|
|
116
|
+
gh release create "$GITHUB_REF_NAME" pkg/*.gem --repo "$GITHUB_REPOSITORY" --verify-tag \
|
|
117
|
+
--title "$GITHUB_REF_NAME" --notes-file notes.md
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# A Dependabot pull request that moves Gemfile.lock gets RuboCop's safe corrections
|
|
2
|
+
# (`rake rubocop:autocorrect`), when the bumped RuboCop finds any, as a commit of their own on its
|
|
3
|
+
# branch, then merges as any bump once its checks pass. No token is stored: the job's GITHUB_TOKEN
|
|
4
|
+
# pushes, and GitHub may hold the checks of that token's commit until a maintainer approves them
|
|
5
|
+
# (the pull request's "Approve workflows to run"); no workflow can start them sooner -- dispatched,
|
|
6
|
+
# theirs are not the pull request's required checks. `[dependabot skip]`: Dependabot rebases the
|
|
7
|
+
# bump still, over the commit, and this workflow corrects the new one.
|
|
8
|
+
name: RuboCop Autocorrect
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
pull_request:
|
|
12
|
+
paths:
|
|
13
|
+
- "Gemfile.lock"
|
|
14
|
+
|
|
15
|
+
permissions: {}
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
correct:
|
|
19
|
+
name: Safe corrections
|
|
20
|
+
# Dependabot's own branches alone: never a fork's, never a person's pull request
|
|
21
|
+
if: >-
|
|
22
|
+
github.event.pull_request.user.login == 'dependabot[bot]' &&
|
|
23
|
+
github.event.pull_request.head.repo.full_name == github.repository
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
# the bumped gems run here, so this job's token writes nothing: the next job, which pushes,
|
|
26
|
+
# runs no gem
|
|
27
|
+
permissions:
|
|
28
|
+
contents: read
|
|
29
|
+
outputs:
|
|
30
|
+
changed: ${{ steps.correct.outputs.changed }}
|
|
31
|
+
steps:
|
|
32
|
+
- name: Checkout
|
|
33
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
34
|
+
with:
|
|
35
|
+
ref: ${{ github.event.pull_request.head.sha }}
|
|
36
|
+
persist-credentials: false
|
|
37
|
+
|
|
38
|
+
- name: Set up Ruby
|
|
39
|
+
uses: ruby/setup-ruby@7f797815d8adceb1c412e7abefdd1ab4abc47a5f # v1.335.0
|
|
40
|
+
with:
|
|
41
|
+
ruby-version: "4.0"
|
|
42
|
+
bundler-cache: true
|
|
43
|
+
|
|
44
|
+
- name: RuboCop's safe corrections
|
|
45
|
+
id: correct
|
|
46
|
+
run: |
|
|
47
|
+
set -euo pipefail
|
|
48
|
+
# what is left once corrected fails CI's own RuboCop, for a person to fix
|
|
49
|
+
bundle exec rake rubocop:autocorrect || true
|
|
50
|
+
git diff --binary > "$RUNNER_TEMP/corrections.patch"
|
|
51
|
+
if [[ -s $RUNNER_TEMP/corrections.patch ]]; then
|
|
52
|
+
echo "changed=true" >> "$GITHUB_OUTPUT"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
- name: Keep the corrections
|
|
56
|
+
if: steps.correct.outputs.changed == 'true'
|
|
57
|
+
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
58
|
+
with:
|
|
59
|
+
name: corrections
|
|
60
|
+
path: ${{ runner.temp }}/corrections.patch
|
|
61
|
+
if-no-files-found: error
|
|
62
|
+
|
|
63
|
+
push:
|
|
64
|
+
name: Commit them
|
|
65
|
+
needs: correct
|
|
66
|
+
if: needs.correct.outputs.changed == 'true'
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
permissions:
|
|
69
|
+
contents: write
|
|
70
|
+
steps:
|
|
71
|
+
- name: Checkout
|
|
72
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
73
|
+
with:
|
|
74
|
+
ref: ${{ github.event.pull_request.head.ref }}
|
|
75
|
+
# the push below uses it
|
|
76
|
+
persist-credentials: true
|
|
77
|
+
|
|
78
|
+
- name: The corrections
|
|
79
|
+
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
80
|
+
with:
|
|
81
|
+
name: corrections
|
|
82
|
+
path: ${{ runner.temp }}
|
|
83
|
+
|
|
84
|
+
- name: Commit and push
|
|
85
|
+
env:
|
|
86
|
+
BRANCH: ${{ github.event.pull_request.head.ref }}
|
|
87
|
+
CORRECTED: ${{ github.event.pull_request.head.sha }}
|
|
88
|
+
PATCH: ${{ runner.temp }}/corrections.patch
|
|
89
|
+
run: |
|
|
90
|
+
set -euo pipefail
|
|
91
|
+
# corrections of the commit they were made on: on a newer one, Dependabot's or these
|
|
92
|
+
# corrections', a re-run has nothing to do
|
|
93
|
+
if [[ $(git rev-parse HEAD) != "$CORRECTED" ]]; then
|
|
94
|
+
echo "$BRANCH is past $CORRECTED: corrected already, or a newer commit its own run corrects"
|
|
95
|
+
exit 0
|
|
96
|
+
fi
|
|
97
|
+
# RuboCop's files alone, edited in place: nothing else the bumped gems could write
|
|
98
|
+
ruby_files='^([^/]+/)*([^/]+\.(rb|gemspec)|Gemfile|Rakefile|Steepfile|(bin|exe)/[^/]+)$'
|
|
99
|
+
if [[ -n $(git apply --summary "$PATCH") ]] ||
|
|
100
|
+
git apply --numstat "$PATCH" | cut -f 3 | grep -Ev "$ruby_files"; then
|
|
101
|
+
echo "::error::the corrections change more than RuboCop's files, in place: not committed"
|
|
102
|
+
exit 1
|
|
103
|
+
fi
|
|
104
|
+
git apply "$PATCH"
|
|
105
|
+
git -c user.name="github-actions[bot]" \
|
|
106
|
+
-c user.email="41898282+github-actions[bot]@users.noreply.github.com" \
|
|
107
|
+
commit --all --quiet --message "style: apply RuboCop's safe corrections [dependabot skip]"
|
|
108
|
+
if ! git push origin "HEAD:$BRANCH"; then
|
|
109
|
+
# refused because Dependabot pushed meanwhile, whose own run corrects its commit;
|
|
110
|
+
# refused otherwise, a failure
|
|
111
|
+
remote=$(git ls-remote origin "refs/heads/$BRANCH" | cut -f 1)
|
|
112
|
+
if [[ $remote == "$CORRECTED" ]]; then exit 1; fi
|
|
113
|
+
echo "$BRANCH moved on: its own run corrects it"
|
|
114
|
+
fi
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# The Ruby checks, `bundle exec rake` (RuboCop, Steep, the tests with their coverage gate), on each
|
|
2
|
+
# Ruby the matrix lists, the gems installed from Gemfile.lock; then TypeProf's verdict, advisory.
|
|
3
|
+
# nix.yml runs the flake's checks: the Nix format, the shell, the workflows, the package.
|
|
4
|
+
name: Ruby CI
|
|
5
|
+
|
|
6
|
+
on:
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
# every pull request, whatever it touches: a path-filtered workflow never reports, and a
|
|
10
|
+
# required check that never reports blocks the merge
|
|
11
|
+
pull_request:
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
# a pull request's newest run cancels its older ones; any other run, a group of its own: every
|
|
15
|
+
# commit on main checked (in a shared group, a pending run gives way to the newest: the default)
|
|
16
|
+
concurrency:
|
|
17
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
|
18
|
+
cancel-in-progress: true
|
|
19
|
+
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
checks:
|
|
25
|
+
name: Checks (Ruby ${{ matrix.ruby }})
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
strategy:
|
|
28
|
+
fail-fast: false
|
|
29
|
+
matrix:
|
|
30
|
+
# the gemspec's required_ruby_version, and each newer Ruby once released
|
|
31
|
+
ruby: ["4.0"]
|
|
32
|
+
steps:
|
|
33
|
+
- name: Checkout
|
|
34
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
35
|
+
with:
|
|
36
|
+
persist-credentials: false
|
|
37
|
+
|
|
38
|
+
- name: Set up Ruby
|
|
39
|
+
# bundler-cache: `bundle install`, frozen to Gemfile.lock, cached
|
|
40
|
+
uses: ruby/setup-ruby@7f797815d8adceb1c412e7abefdd1ab4abc47a5f # v1.335.0
|
|
41
|
+
with:
|
|
42
|
+
ruby-version: ${{ matrix.ruby }}
|
|
43
|
+
bundler-cache: true
|
|
44
|
+
|
|
45
|
+
- name: RuboCop, Steep, the tests
|
|
46
|
+
# RuboCop's offences as annotations too, on a pull request's lines (its github formatter)
|
|
47
|
+
env:
|
|
48
|
+
RUBOCOP_OPTS: --format progress --format github
|
|
49
|
+
run: bundle exec rake
|
|
50
|
+
|
|
51
|
+
- name: RuboCop's safe corrections, as a patch
|
|
52
|
+
# a failed run's: what `rake rubocop:autocorrect` changes, in the run's summary, to
|
|
53
|
+
# `git apply` (a Dependabot bump's, rubocop-autocorrect.yml commits)
|
|
54
|
+
if: failure()
|
|
55
|
+
run: |
|
|
56
|
+
bundle exec rake rubocop:autocorrect || true
|
|
57
|
+
if ! git diff --quiet; then
|
|
58
|
+
{ echo '```diff'; git diff; echo '```'; } >> "$GITHUB_STEP_SUMMARY"
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
- name: TypeProf (advisory)
|
|
62
|
+
run: bundle exec rake typeprof
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# bundler-audit: Gemfile.lock against the Ruby Advisory Database -- daily, on demand, and when the
|
|
2
|
+
# lock changes (`rake audit`). A finding fails the run, notified to the workflow's creator (or
|
|
3
|
+
# whoever last changed its cron: docs.github.com, "Notifications for workflow runs"). GitHub
|
|
4
|
+
# disables a public repository's schedule after 60 days without activity ("Events that trigger
|
|
5
|
+
# workflows"): Dependabot alerts, the repository's setting, watch the lock without one.
|
|
6
|
+
name: Security
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
schedule:
|
|
10
|
+
- cron: "0 0 * * *" # daily, midnight UTC
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
push:
|
|
13
|
+
branches: [main]
|
|
14
|
+
paths:
|
|
15
|
+
- "Gemfile.lock"
|
|
16
|
+
- ".github/workflows/security.yml"
|
|
17
|
+
pull_request:
|
|
18
|
+
paths:
|
|
19
|
+
- "Gemfile.lock"
|
|
20
|
+
- ".github/workflows/security.yml"
|
|
21
|
+
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
bundler-audit:
|
|
27
|
+
name: bundler-audit
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
steps:
|
|
30
|
+
- name: Checkout
|
|
31
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
32
|
+
with:
|
|
33
|
+
persist-credentials: false
|
|
34
|
+
|
|
35
|
+
- name: Set up Ruby
|
|
36
|
+
uses: ruby/setup-ruby@7f797815d8adceb1c412e7abefdd1ab4abc47a5f # v1.335.0
|
|
37
|
+
with:
|
|
38
|
+
ruby-version: "4.0"
|
|
39
|
+
bundler-cache: true
|
|
40
|
+
|
|
41
|
+
- name: bundler-audit
|
|
42
|
+
# the advisory database updated first, then the lock checked
|
|
43
|
+
run: bundle exec rake audit
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
name: Conventional Commits Check
|
|
2
|
+
|
|
3
|
+
# On a push, the whole history rather than `--from-latest-tag`: with no tag
|
|
4
|
+
# yet, cog stops "unable to get any tag" -- every new project's first push.
|
|
5
|
+
# A pull request's title too: a squash merge of two or more commits makes the
|
|
6
|
+
# title the commit, and so a changelog entry -- checked again when edited.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
branches: [main]
|
|
11
|
+
pull_request:
|
|
12
|
+
types: [opened, synchronize, reopened, edited]
|
|
13
|
+
|
|
14
|
+
# a pull request's newest run cancels its older ones; any other run, a group of its own: every
|
|
15
|
+
# commit on main checked (in a shared group, a pending run gives way to the newest: the default)
|
|
16
|
+
concurrency:
|
|
17
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
|
18
|
+
cancel-in-progress: true
|
|
19
|
+
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
check_commits:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
name: Check Conventional Commits
|
|
27
|
+
steps:
|
|
28
|
+
- name: Checkout
|
|
29
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
30
|
+
with:
|
|
31
|
+
fetch-depth: 0
|
|
32
|
+
persist-credentials: false
|
|
33
|
+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
|
34
|
+
|
|
35
|
+
- name: Check PR Commits
|
|
36
|
+
if: github.event_name == 'pull_request'
|
|
37
|
+
uses: cocogitto/cocogitto-action@52d0023b4396897f1815648e553db2ab8d782f3a # v4.2.0
|
|
38
|
+
with:
|
|
39
|
+
command: check
|
|
40
|
+
args: --ignore-merge-commits ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}
|
|
41
|
+
|
|
42
|
+
# after the action: `cog verify` panics without git's user.name and user.email, which
|
|
43
|
+
# the action sets globally (its git-user inputs) on every run
|
|
44
|
+
- name: Check PR Title
|
|
45
|
+
if: github.event_name == 'pull_request'
|
|
46
|
+
env:
|
|
47
|
+
TITLE: ${{ github.event.pull_request.title }} # through the environment, never the script
|
|
48
|
+
# after `--`: a title is the message, never an option (`--file=...`)
|
|
49
|
+
run: cog verify -- "$TITLE"
|
|
50
|
+
|
|
51
|
+
- name: Check Push Commits
|
|
52
|
+
if: github.event_name == 'push'
|
|
53
|
+
uses: cocogitto/cocogitto-action@52d0023b4396897f1815648e553db2ab8d782f3a # v4.2.0
|
|
54
|
+
with:
|
|
55
|
+
command: check
|
|
56
|
+
args: --ignore-merge-commits
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# The action installs dprint's latest release, attested; the formatting is
|
|
2
|
+
# the plugins', pinned in dprint.json.
|
|
3
|
+
name: Dprint Formatting Checks
|
|
4
|
+
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
paths:
|
|
9
|
+
# dprint.json's plugins' extensions, markdown and toml, no more: one
|
|
10
|
+
# no plugin handles (yaml, json, Dockerfile) only schedules runs that
|
|
11
|
+
# check nothing. Add a plugin there and its extensions here together,
|
|
12
|
+
# each its own entry: path filters have no brace expansion {a,b}.
|
|
13
|
+
- "**/*.md"
|
|
14
|
+
- "**/*.markdown"
|
|
15
|
+
- "**/*.toml"
|
|
16
|
+
- ".github/workflows/style-check-dprint.yml"
|
|
17
|
+
- "dprint.json"
|
|
18
|
+
# every pull request, whatever it touches: a path-filtered workflow never
|
|
19
|
+
# reports, and a required check that never reports blocks the merge
|
|
20
|
+
pull_request:
|
|
21
|
+
|
|
22
|
+
# a pull request's newest run cancels its older ones; any other run, a group of its own: every
|
|
23
|
+
# commit on main checked (in a shared group, a pending run gives way to the newest: the default)
|
|
24
|
+
concurrency:
|
|
25
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
|
|
26
|
+
cancel-in-progress: true
|
|
27
|
+
|
|
28
|
+
permissions:
|
|
29
|
+
contents: read
|
|
30
|
+
|
|
31
|
+
jobs:
|
|
32
|
+
dprint:
|
|
33
|
+
name: dprint check
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
steps:
|
|
36
|
+
- name: Checkout
|
|
37
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
38
|
+
with:
|
|
39
|
+
persist-credentials: false
|
|
40
|
+
|
|
41
|
+
- name: Dprint format check
|
|
42
|
+
uses: dprint/check@7dc032d8874778fc024f6f9b4a7e6d896782c330 # v2.5
|
|
43
|
+
with:
|
|
44
|
+
config-path: dprint.json
|