ruact 0.0.11 → 0.0.13
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 +4 -4
- data/CHANGELOG.md +147 -48
- data/CONTRIBUTING.md +233 -0
- data/README.md +18 -8
- data/RELEASING.md +125 -139
- data/lib/generators/ruact/install/install_generator.rb +305 -126
- data/lib/generators/ruact/install/templates/AGENTS.md.tt +14 -13
- data/lib/generators/ruact/install/templates/initializer.rb.tt +29 -7
- data/lib/generators/ruact/install/templates/tsconfig.json.tt +3 -0
- data/lib/generators/ruact/layout/layout_generator.rb +52 -0
- data/lib/generators/ruact/scaffold/templates/controller.rb.tt +5 -3
- data/lib/ruact/configuration.rb +65 -13
- data/lib/ruact/controller/document_rendering.rb +72 -16
- data/lib/ruact/controller/page_rendering.rb +134 -0
- data/lib/ruact/controller/pages.rb +116 -0
- data/lib/ruact/controller.rb +78 -11
- data/lib/ruact/doctor.rb +233 -25
- data/lib/ruact/layout_source.rb +29 -7
- data/lib/ruact/navigation_boundary.rb +240 -0
- data/lib/ruact/packaging.rb +68 -0
- data/lib/ruact/railtie.rb +30 -0
- data/lib/ruact/server.rb +10 -1
- data/lib/ruact/version.rb +1 -1
- data/lib/ruact/view_helper.rb +158 -1
- data/lib/ruact/views/layouts/ruact.html.erb +32 -0
- data/lib/ruact.rb +29 -0
- data/vendor/javascript/vite-plugin-ruact/flight-client.test.mjs +321 -0
- data/vendor/javascript/vite-plugin-ruact/package-lock.json +11 -0
- data/vendor/javascript/vite-plugin-ruact/package.json +1 -0
- data/vendor/javascript/vite-plugin-ruact/ruact-router.test.mjs +433 -0
- data/vendor/javascript/vite-plugin-ruact/runtime/flight-client.js +14 -3
- data/vendor/javascript/vite-plugin-ruact/runtime/ruact-router.js +170 -7
- metadata +12 -107
- data/.codecov.yml +0 -31
- data/.github/workflows/ci.yml +0 -284
- data/.github/workflows/server-functions-bench.yml +0 -54
- data/.rubocop.yml +0 -107
- data/.rubocop_todo.yml +0 -63
- data/Rakefile +0 -10
- data/bench/server_functions_dispatch_bench.rb +0 -276
- data/bench/server_functions_dispatch_bench.results.md +0 -150
- data/docs/internal/README.md +0 -9
- data/docs/internal/decisions/server-functions-api.md +0 -2236
- data/spec/benchmarks/baseline.json +0 -12
- data/spec/benchmarks/render_pipeline_benchmark_spec.rb +0 -109
- data/spec/fixtures/flight/README.md +0 -136
- data/spec/fixtures/flight/array.txt +0 -1
- data/spec/fixtures/flight/as_json_object.txt +0 -2
- data/spec/fixtures/flight/bigint.txt +0 -1
- data/spec/fixtures/flight/boolean_false.txt +0 -1
- data/spec/fixtures/flight/boolean_true.txt +0 -1
- data/spec/fixtures/flight/client_component_with_props.txt +0 -2
- data/spec/fixtures/flight/client_reference.txt +0 -2
- data/spec/fixtures/flight/hash.txt +0 -1
- data/spec/fixtures/flight/infinity.txt +0 -1
- data/spec/fixtures/flight/nan.txt +0 -1
- data/spec/fixtures/flight/negative_infinity.txt +0 -1
- data/spec/fixtures/flight/nil.txt +0 -1
- data/spec/fixtures/flight/number_float.txt +0 -1
- data/spec/fixtures/flight/number_integer.txt +0 -1
- data/spec/fixtures/flight/react_element_no_props.txt +0 -1
- data/spec/fixtures/flight/redirect_row.txt +0 -1
- data/spec/fixtures/flight/serializable_object.txt +0 -2
- data/spec/fixtures/flight/string_basic.txt +0 -1
- data/spec/fixtures/flight/string_dollar_escape.txt +0 -1
- data/spec/fixtures/flight/undefined.txt +0 -1
- data/spec/fixtures/readme/children-error.html.erb +0 -3
- data/spec/fixtures/readme/children-error.txt +0 -1
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/demo/show.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/errors_demo/new.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/exploding_layout_demo/show.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/ghost_layout_demo/show.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/layout_demo/show.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/rootless_layout_demo/show.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/controller_request_spec_support/unwired_layout_demo/show.html.erb +0 -3
- data/spec/fixtures/story_7_9_views/layouts/bare_host.html.erb +0 -16
- data/spec/fixtures/story_7_9_views/layouts/exploding_host.html.erb +0 -24
- data/spec/fixtures/story_7_9_views/layouts/rootless_host.html.erb +0 -15
- data/spec/fixtures/story_7_9_views/layouts/ruact_host.html.erb +0 -17
- data/spec/readme_demo_message_spec.rb +0 -67
- data/spec/readme_spec.rb +0 -282
- data/spec/ruact/client_manifest_spec.rb +0 -270
- data/spec/ruact/component_contract_spec.rb +0 -119
- data/spec/ruact/configuration_spec.rb +0 -518
- data/spec/ruact/controller_request_spec.rb +0 -671
- data/spec/ruact/controller_spec.rb +0 -343
- data/spec/ruact/doctor_spec.rb +0 -769
- data/spec/ruact/erb_preprocessor_hook_spec.rb +0 -55
- data/spec/ruact/erb_preprocessor_spec.rb +0 -361
- data/spec/ruact/errors_spec.rb +0 -93
- data/spec/ruact/flight/renderer_spec.rb +0 -133
- data/spec/ruact/flight/serializer_spec.rb +0 -494
- data/spec/ruact/html_converter_spec.rb +0 -375
- data/spec/ruact/install_generator_spec.rb +0 -1549
- data/spec/ruact/layout_source_spec.rb +0 -108
- data/spec/ruact/manifest_resolver_spec.rb +0 -174
- data/spec/ruact/query_request_spec.rb +0 -706
- data/spec/ruact/query_spec.rb +0 -105
- data/spec/ruact/railtie_spec.rb +0 -155
- data/spec/ruact/render_context_spec.rb +0 -58
- data/spec/ruact/render_pipeline_concurrency_spec.rb +0 -78
- data/spec/ruact/render_pipeline_spec.rb +0 -928
- data/spec/ruact/scaffold_generator_spec.rb +0 -1849
- data/spec/ruact/serializable_spec.rb +0 -179
- data/spec/ruact/server_bucket_request_spec.rb +0 -785
- data/spec/ruact/server_function_name_spec.rb +0 -53
- data/spec/ruact/server_functions/backtrace_cleaner_spec.rb +0 -63
- data/spec/ruact/server_functions/bucket_two_payload_spec.rb +0 -200
- data/spec/ruact/server_functions/codegen_spec.rb +0 -397
- data/spec/ruact/server_functions/error_payload_spec.rb +0 -222
- data/spec/ruact/server_functions/error_suggestion_spec.rb +0 -79
- data/spec/ruact/server_functions/introspection_spec.rb +0 -135
- data/spec/ruact/server_functions/name_bridge_spec.rb +0 -212
- data/spec/ruact/server_functions/query_context_spec.rb +0 -72
- data/spec/ruact/server_functions/query_source_spec.rb +0 -193
- data/spec/ruact/server_functions/railtie_integration_spec.rb +0 -215
- data/spec/ruact/server_functions/rake_spec.rb +0 -86
- data/spec/ruact/server_functions/route_source_spec.rb +0 -202
- data/spec/ruact/server_functions/snapshot_spec.rb +0 -96
- data/spec/ruact/server_functions/snapshot_writer_spec.rb +0 -71
- data/spec/ruact/server_rescue_request_spec.rb +0 -416
- data/spec/ruact/server_spec.rb +0 -179
- data/spec/ruact/server_upload_request_spec.rb +0 -311
- data/spec/ruact/signed_references_spec.rb +0 -164
- data/spec/ruact/string_distance_spec.rb +0 -38
- data/spec/ruact/tasks_json_introspection_spec.rb +0 -141
- data/spec/ruact/testing/have_ruact_component_spec.rb +0 -170
- data/spec/ruact/testing/no_production_load_spec.rb +0 -41
- data/spec/ruact/validation_errors_spec.rb +0 -116
- data/spec/ruact/view_helper_spec.rb +0 -131
- data/spec/spec_helper.rb +0 -77
- data/spec/support/fixtures/pixel.png +0 -0
- data/spec/support/flight_wire_parser.rb +0 -21
- data/spec/support/flight_wire_parser_spec.rb +0 -93
- data/spec/support/matchers/flight_fixture_matcher.rb +0 -130
- data/spec/support/matchers/flight_fixture_matcher_spec.rb +0 -250
- data/spec/support/rails_stub.rb +0 -115
data/RELEASING.md
CHANGED
|
@@ -1,209 +1,195 @@
|
|
|
1
1
|
# Releasing ruact
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A release publishes exactly one artifact: the `ruact` gem, to RubyGems.
|
|
4
4
|
|
|
5
|
-
The
|
|
5
|
+
The Vite plugin is not a second artifact. It ships **inside** the gem, under `vendor/javascript/`, together with
|
|
6
|
+
the browser runtime; a generated app imports the plugin by filesystem path off the installed gem. Neither
|
|
7
|
+
bundled package is published, so neither is co-versioned with anything — whatever version number their
|
|
8
|
+
`package.json` files carry is internal to the gem and is not a release. The standalone `vite-plugin-ruact`
|
|
9
|
+
package on npm is a superseded artifact from before the plugin was vendored; no ruact release touches it, and
|
|
10
|
+
nothing this document describes puts anything there.
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
**The pull request is the release.** You write the version into `lib/ruact/version.rb` and stamp the CHANGELOG
|
|
13
|
+
in the same pull request; merging it is what publishes. There is no switch to turn on beforehand and none to
|
|
14
|
+
remember afterwards, and a merge that carries no new version publishes nothing — its content accumulates under
|
|
15
|
+
`[Unreleased]` until somebody decides to cut a release.
|
|
16
|
+
|
|
17
|
+
That is the whole of this document, and it is why almost every hand step this file used to prescribe has been
|
|
18
|
+
deleted rather than corrected: the workflow builds, uploads and tags, and it writes nothing you would otherwise
|
|
19
|
+
write yourself.
|
|
8
20
|
|
|
9
|
-
|
|
21
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for the checks that run on every push and pull request and how to run
|
|
22
|
+
them locally — this document deliberately describes none of them, so the two cannot drift apart.
|
|
23
|
+
|
|
24
|
+
---
|
|
10
25
|
|
|
11
|
-
|
|
26
|
+
## Who owns what
|
|
12
27
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
28
|
+
| | Owner |
|
|
29
|
+
|---|---|
|
|
30
|
+
| Whether this merge publishes | you — by putting a new version in the pull request, or not |
|
|
31
|
+
| The version number | you — typed, in `lib/ruact/version.rb` |
|
|
32
|
+
| What the CHANGELOG entry says | you, in the same pull request |
|
|
33
|
+
| The build, the upload to RubyGems, the tag | the `release` job, on the push to `main` |
|
|
34
|
+
| Anything committed to `main` | nobody but a merge — the job pushes a tag and nothing else |
|
|
19
35
|
|
|
20
36
|
---
|
|
21
37
|
|
|
22
|
-
##
|
|
38
|
+
## 1. Decide the version
|
|
23
39
|
|
|
24
|
-
|
|
40
|
+
SemVer, against the public API: a breaking change to what consumers call (a renamed public method, a changed
|
|
41
|
+
signature, a removed configuration option, an incompatible change to the Flight wire format) is a major; a
|
|
42
|
+
backwards-compatible feature is a minor; everything else is a patch.
|
|
25
43
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
| Bug fix, patch | Patch: `X.Y.Z+1` | `0.1.0` → `0.1.1` |
|
|
44
|
+
Nothing computes this for you and nothing defaults. That is deliberate: the number used to be derived from a
|
|
45
|
+
default plus a marker in a commit message, which meant a minor could arrive as a side effect of how a merge was
|
|
46
|
+
worded — and the first one would have landed on the version this project has reserved for a milestone it has
|
|
47
|
+
not reached.
|
|
31
48
|
|
|
32
|
-
|
|
49
|
+
A minor or a major also moves the supported-versions table in [SECURITY.md](SECURITY.md). Do it in the same
|
|
50
|
+
pull request; nothing checks it.
|
|
33
51
|
|
|
34
52
|
---
|
|
35
53
|
|
|
36
|
-
##
|
|
37
|
-
|
|
38
|
-
### 1. Create a release branch
|
|
54
|
+
## 2. Prepare the release
|
|
39
55
|
|
|
40
56
|
```bash
|
|
41
|
-
|
|
57
|
+
bin/release X.Y.Z
|
|
42
58
|
```
|
|
43
59
|
|
|
44
|
-
|
|
60
|
+
It refuses a dirty checkout, and one that is not `main` exactly as the remote has it — a branch is never
|
|
61
|
+
*behind* `main` either, and cutting a release from one would put whatever it carries into the release. It
|
|
62
|
+
refuses a version that is not one step from the current one, and one that is already tagged. Then it writes `lib/ruact/version.rb`, re-resolves `Gemfile.lock` against
|
|
63
|
+
it, moves the accumulated `[Unreleased]` content in [CHANGELOG.md](CHANGELOG.md) under a dated heading, opens a
|
|
64
|
+
fresh empty `[Unreleased]`, rewrites both link references, proves the result against the changelog checks and
|
|
65
|
+
the release gate, commits, pushes, and opens the pull request.
|
|
45
66
|
|
|
46
|
-
|
|
67
|
+
**The pull-request body it writes is the checklist**, with the version already substituted. There is no
|
|
68
|
+
checklist document in this repository on purpose: a checklist is a second copy of the process in the
|
|
69
|
+
imperative, and it rots the way every other second copy does. This one is generated by the thing that performs
|
|
70
|
+
the process, on every release.
|
|
47
71
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
VERSION = "{X.Y.Z}"
|
|
51
|
-
end
|
|
52
|
-
```
|
|
72
|
+
You can do all of it by hand — the script performs no step you could not — but then you own the parts it
|
|
73
|
+
proves, and the gate on the pull request is where you find out.
|
|
53
74
|
|
|
54
|
-
|
|
75
|
+
CHANGELOG.md deserves one warning of its own, because it has three readers who share no directory: this
|
|
76
|
+
repository, a `.gem` unpacked on somebody's disk, and the generated changelog page on the documentation site.
|
|
77
|
+
An entry may name a file but must not **link** one relatively, because a target that resolves here 404s in the
|
|
78
|
+
other two. Absolute URLs only, or no link at all.
|
|
55
79
|
|
|
56
|
-
|
|
80
|
+
---
|
|
57
81
|
|
|
58
|
-
|
|
59
|
-
{
|
|
60
|
-
"version": "{X.Y.Z}"
|
|
61
|
-
}
|
|
62
|
-
```
|
|
82
|
+
## 3. Merge
|
|
63
83
|
|
|
64
|
-
|
|
84
|
+
On the resulting push to `main`, the `release` job — which waits on every other job in the workflow — asks one
|
|
85
|
+
question: **does `lib/ruact/version.rb` name a version that has no tag?**
|
|
65
86
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
3. Add or update the link footer at the bottom:
|
|
69
|
-
```
|
|
70
|
-
[Unreleased]: https://github.com/luizcg/ruact/compare/v{X.Y.Z}...HEAD
|
|
71
|
-
[{X.Y.Z}]: https://github.com/luizcg/ruact/compare/v{PREV}...v{X.Y.Z}
|
|
72
|
-
```
|
|
73
|
-
4. If this release contains breaking changes, ensure the section includes a `[BREAKING]` subsection with a **Migration Guide** (see "Breaking Changes" section below).
|
|
87
|
+
If it does not, the job reports that there is nothing to publish and ends green. That is the ordinary case;
|
|
88
|
+
most merges are not releases.
|
|
74
89
|
|
|
75
|
-
|
|
90
|
+
If it does, the job authenticates to RubyGems through Trusted Publishing (OIDC) — a short-lived credential
|
|
91
|
+
minted for that run, no stored secret, nothing interactive — then builds the gem, uploads it, and **tags last**.
|
|
76
92
|
|
|
77
|
-
|
|
93
|
+
**Why the tag comes last.** The tag is the record of a publish that finished. An upload that fails leaves no
|
|
94
|
+
tag, so the version is still untagged, so the next green push to `main` tries again — automatically, with
|
|
95
|
+
nothing to unwind and nobody to remember. The cost of that order is a re-run that meets a version already on
|
|
96
|
+
RubyGems, which is why a duplicate-version rejection is treated as *already done* rather than as a failure.
|
|
78
97
|
|
|
79
|
-
|
|
98
|
+
**Why a question about state rather than about this push.** A trigger that fired on "the version changed in
|
|
99
|
+
this push" would be lost forever whenever no run is created for a push — which happens, merge commits
|
|
100
|
+
included. The version would then say one thing, RubyGems another, and the next release would skip the number
|
|
101
|
+
entirely. Asking about state instead makes the job idempotent and self-healing: run it twice and the second
|
|
102
|
+
does nothing; miss it once and the next green push repairs it.
|
|
80
103
|
|
|
81
|
-
|
|
82
|
-
git add gem/lib/ruact/version.rb \
|
|
83
|
-
packages/vite-plugin-ruact/package.json \
|
|
84
|
-
gem/CHANGELOG.md \
|
|
85
|
-
packages/vite-plugin-ruact/CHANGELOG.md
|
|
86
|
-
git commit -m "Release v{X.Y.Z}"
|
|
87
|
-
```
|
|
104
|
+
---
|
|
88
105
|
|
|
89
|
-
|
|
106
|
+
## 4. Verify
|
|
90
107
|
|
|
91
108
|
```bash
|
|
92
|
-
|
|
109
|
+
curl -s https://rubygems.org/api/v1/versions/ruact/latest.json
|
|
93
110
|
```
|
|
94
111
|
|
|
95
|
-
|
|
112
|
+
Use that endpoint. The other one — `/gems/ruact.json` — is CDN-cached and keeps serving the previous version
|
|
113
|
+
for minutes after a successful publish, which reads exactly like a release that did not happen.
|
|
96
114
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
Merge the PR. Confirm all CI jobs pass on the merge commit, then tag the verified merge commit:
|
|
115
|
+
---
|
|
100
116
|
|
|
101
|
-
|
|
102
|
-
git checkout main
|
|
103
|
-
git pull origin main
|
|
104
|
-
git tag v{X.Y.Z}
|
|
105
|
-
git push origin v{X.Y.Z}
|
|
106
|
-
```
|
|
117
|
+
## 5. When nothing was published and nothing said so
|
|
107
118
|
|
|
108
|
-
|
|
119
|
+
From the outside, a release that did not happen and one that did look identical until you check RubyGems. Every
|
|
120
|
+
case below shares one recovery, and it is the reason the trigger has the shape it has: **the version is still
|
|
121
|
+
untagged, so the next green push to `main` publishes it.** Nothing has to be unwound and nothing has to be
|
|
122
|
+
remembered.
|
|
109
123
|
|
|
110
|
-
|
|
124
|
+
**A job the `release` job waits on went red on the push to `main`.** The release job never ran, the merge has
|
|
125
|
+
landed, and no error anywhere says "no release happened". The run that matters is the one on `main`, not the
|
|
126
|
+
one on the pull request:
|
|
111
127
|
|
|
112
128
|
```bash
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
gem push ruact-{X.Y.Z}.gem
|
|
116
|
-
# Enter OTP when prompted (MFA is required)
|
|
117
|
-
rm ruact-{X.Y.Z}.gem
|
|
129
|
+
gh run list --branch main -L 3
|
|
130
|
+
gh run rerun <run-id> --failed
|
|
118
131
|
```
|
|
119
132
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
> gem contents ruact-{X.Y.Z} | grep -E 'CHANGELOG|RELEASING|SECURITY'
|
|
123
|
-
> ```
|
|
133
|
+
**No run was created for the push at all.** Same state, same repair; there is simply no run to re-run. Push
|
|
134
|
+
something green to `main` — the next merge does it on its own.
|
|
124
135
|
|
|
125
|
-
|
|
136
|
+
**The upload failed, or Trusted Publishing rejected the run.** Nothing was tagged, because the tag is written
|
|
137
|
+
after the upload. Fix the cause and let the next green push reconcile it.
|
|
126
138
|
|
|
127
|
-
|
|
128
|
-
cd packages/vite-plugin-ruact
|
|
129
|
-
npm publish
|
|
130
|
-
```
|
|
139
|
+
**The version is on RubyGems but the API still shows the old one.** CDN cache; see §4.
|
|
131
140
|
|
|
132
|
-
|
|
141
|
+
**A release was prepared and should not go out.** If it has not merged, close the pull request — nothing was
|
|
142
|
+
released and nothing has to be undone. If it has, see §6.
|
|
133
143
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
4. Body: paste the `## [{X.Y.Z}]` section from `gem/CHANGELOG.md`
|
|
138
|
-
5. Publish
|
|
144
|
+
**The suite is red on `main` because the record and the code disagree.** The changelog checks run in a job the
|
|
145
|
+
release job waits on, so once `lib/ruact/version.rb` and `CHANGELOG.md` stop naming the same version, **every**
|
|
146
|
+
later release waits too. The failure names which of the two moved.
|
|
139
147
|
|
|
140
148
|
---
|
|
141
149
|
|
|
142
|
-
##
|
|
143
|
-
|
|
144
|
-
When a release contains a breaking change:
|
|
150
|
+
## 6. Stopping a release that has already merged
|
|
145
151
|
|
|
146
|
-
|
|
147
|
-
2. Mark the CHANGELOG entry with `[BREAKING]` and include a **Migration Guide** sub-section:
|
|
152
|
+
Publication is irreversible, so there is a stop — a repository variable, read by the job itself:
|
|
148
153
|
|
|
149
|
-
|
|
150
|
-
|
|
154
|
+
```bash
|
|
155
|
+
gh variable set RUACT_RELEASE_HALT -b stop -R luizcg/ruact
|
|
156
|
+
```
|
|
151
157
|
|
|
152
|
-
|
|
153
|
-
- [BREAKING] `Ruact::Serializable.ruact_props` now rejects non-Symbol arguments at class-load time
|
|
158
|
+
Any non-empty value stops it. Unset — the normal, permanent state — publishes.
|
|
154
159
|
|
|
155
|
-
|
|
160
|
+
**A halted run fails red, naming the version it refused.** That is the point of it: the stop is a state
|
|
161
|
+
somebody has to undo, and a stop that produced a quiet, successful-looking run would suppress every later
|
|
162
|
+
release invisibly. This one reddens `main` on the next merge instead, which is a thing you find out about.
|
|
156
163
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
include Ruact::Serializable
|
|
161
|
-
ruact_props "id", "title" # strings silently coerced
|
|
162
|
-
end
|
|
163
|
-
```
|
|
164
|
-
**After:**
|
|
165
|
-
```ruby
|
|
166
|
-
class Post
|
|
167
|
-
include Ruact::Serializable
|
|
168
|
-
ruact_props :id, :title # must be Symbols
|
|
169
|
-
end
|
|
170
|
-
```
|
|
171
|
-
```
|
|
164
|
+
```bash
|
|
165
|
+
gh variable delete RUACT_RELEASE_HALT -R luizcg/ruact
|
|
166
|
+
```
|
|
172
167
|
|
|
173
|
-
|
|
168
|
+
The version is still untagged while the halt is in place, so clearing it does not require another bump: the
|
|
169
|
+
next green push publishes what was held.
|
|
174
170
|
|
|
175
171
|
---
|
|
176
172
|
|
|
177
|
-
## Rollback
|
|
173
|
+
## 7. Rollback
|
|
178
174
|
|
|
179
|
-
If a
|
|
175
|
+
If a published version has a critical defect:
|
|
180
176
|
|
|
181
|
-
**RubyGems** (within 30 days):
|
|
182
177
|
```bash
|
|
183
|
-
gem yank ruact -v
|
|
178
|
+
gem yank ruact -v X.Y.Z
|
|
184
179
|
```
|
|
185
180
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
181
|
+
This is the one RubyGems command still run by a person rather than by the workflow, and it is the one place the
|
|
182
|
+
"nothing interactive" of §3 does not apply: the gem declares `rubygems_mfa_required`, so yanking needs your own
|
|
183
|
+
RubyGems credential and a one-time code. The workflow's OIDC credential is minted for its own run and is no
|
|
184
|
+
help here.
|
|
190
185
|
|
|
191
|
-
|
|
186
|
+
Then cut a patch release with the fix immediately. A yanked version with no replacement leaves anyone who
|
|
187
|
+
pinned it with nothing to move to. There is nothing to unpublish anywhere else — this process publishes to
|
|
188
|
+
RubyGems only.
|
|
192
189
|
|
|
193
190
|
---
|
|
194
191
|
|
|
195
|
-
##
|
|
196
|
-
|
|
197
|
-
**`gem push` fails with "MFA required"**: Run `gem signin` first and ensure your OTP authenticator is set up at https://rubygems.org/settings/edit.
|
|
192
|
+
## Where this ends
|
|
198
193
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
**CI fails on release branch**: Fix the issue on the release branch and push the fix. Wait for CI to pass before tagging. If you already pushed a tag pointing to a broken commit, delete it and recreate after the fix:
|
|
202
|
-
```bash
|
|
203
|
-
git tag -d v{X.Y.Z} # delete local tag
|
|
204
|
-
git push origin :refs/tags/v{X.Y.Z} # delete remote tag
|
|
205
|
-
# fix the issue, merge, then re-tag from the correct commit
|
|
206
|
-
git checkout main && git pull origin main
|
|
207
|
-
git tag v{X.Y.Z} && git push origin v{X.Y.Z}
|
|
208
|
-
```
|
|
209
|
-
Do not use `git push --force` on tags — force-pushing a tag rewrite history for anyone who has already fetched it.
|
|
194
|
+
The gem is published and verified. The rest of a release — the private planning side — is outside this
|
|
195
|
+
repository and outside this document.
|