wordmove-ng 6.0.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.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +40 -0
  3. data/.github/ISSUE_TEMPLATE/config.yml +11 -0
  4. data/.github/stale.yml +18 -0
  5. data/.github/workflows/release.yml +100 -0
  6. data/.github/workflows/ruby.yml +41 -0
  7. data/.gitignore +21 -0
  8. data/.release-please-manifest.json +3 -0
  9. data/.rspec +2 -0
  10. data/.rubocop.yml +50 -0
  11. data/.rubocop_todo.yml +89 -0
  12. data/.ruby-gemset +1 -0
  13. data/.ruby-version +1 -0
  14. data/.vscode/launch.json +73 -0
  15. data/CHANGELOG.md +78 -0
  16. data/CLAUDE.md +114 -0
  17. data/CONTRIBUTING.md +114 -0
  18. data/Gemfile +14 -0
  19. data/LICENSE +22 -0
  20. data/README.md +340 -0
  21. data/Rakefile +7 -0
  22. data/assets/images/wordmove-ng.png +0 -0
  23. data/bin/bundle +105 -0
  24. data/bin/bundler +17 -0
  25. data/bin/byebug +29 -0
  26. data/bin/coderay +29 -0
  27. data/bin/console +16 -0
  28. data/bin/htmldiff +29 -0
  29. data/bin/kwalify +29 -0
  30. data/bin/ldiff +29 -0
  31. data/bin/pry +29 -0
  32. data/bin/rake +29 -0
  33. data/bin/rspec +29 -0
  34. data/bin/rubocop +29 -0
  35. data/bin/ruby-parse +29 -0
  36. data/bin/ruby-rewrite +29 -0
  37. data/bin/rumoji +29 -0
  38. data/bin/setup +7 -0
  39. data/bin/thor +29 -0
  40. data/bin/wordmove-ng +10 -0
  41. data/deploy/deploy.sh +3 -0
  42. data/exe/wordmove-ng +6 -0
  43. data/lib/wordmove/assets/wordmove_schema_global.yml +16 -0
  44. data/lib/wordmove/assets/wordmove_schema_local.yml +31 -0
  45. data/lib/wordmove/assets/wordmove_schema_remote.yml +167 -0
  46. data/lib/wordmove/cli.rb +134 -0
  47. data/lib/wordmove/deployer/base.rb +356 -0
  48. data/lib/wordmove/deployer/ssh.rb +339 -0
  49. data/lib/wordmove/doctor/movefile.rb +112 -0
  50. data/lib/wordmove/doctor/mysql.rb +136 -0
  51. data/lib/wordmove/doctor/rsync.rb +27 -0
  52. data/lib/wordmove/doctor/ssh.rb +90 -0
  53. data/lib/wordmove/doctor/wpcli.rb +43 -0
  54. data/lib/wordmove/doctor.rb +67 -0
  55. data/lib/wordmove/environments_list.rb +68 -0
  56. data/lib/wordmove/exceptions.rb +10 -0
  57. data/lib/wordmove/generators/movefile.rb +50 -0
  58. data/lib/wordmove/generators/movefile.yml +104 -0
  59. data/lib/wordmove/generators/movefile_adapter.rb +188 -0
  60. data/lib/wordmove/guardian.rb +37 -0
  61. data/lib/wordmove/hook.rb +128 -0
  62. data/lib/wordmove/logger.rb +165 -0
  63. data/lib/wordmove/movefile.rb +129 -0
  64. data/lib/wordmove/prerequisites.rb +57 -0
  65. data/lib/wordmove/sql_adapter/wpcli.rb +72 -0
  66. data/lib/wordmove/ssh_runner.rb +110 -0
  67. data/lib/wordmove/version.rb +3 -0
  68. data/lib/wordmove/wordpress_directory/path.rb +11 -0
  69. data/lib/wordmove/wordpress_directory.rb +41 -0
  70. data/lib/wordmove-ng.rb +4 -0
  71. data/lib/wordmove.rb +51 -0
  72. data/release-please-config.json +25 -0
  73. data/wordmove-ng.gemspec +62 -0
  74. metadata +318 -0
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,114 @@
1
+ Welcome to the contributor guide. If you can't find important information you're welcome
2
+ to edit this page or [open a discussion](https://github.com/tekgnosis-net/wordmove-ng/discussions/new?category=general) to talk with maintainers.
3
+
4
+ In this guide you'll find informations about:
5
+ * [Bug reporting](#bug-reporting)
6
+ * [Development](#development)
7
+ * [Maintainer tasks](#maintainer-tasks)
8
+
9
+ ### Bug reporting
10
+
11
+ wordmove-ng is an hard piece of software to debug and it is used by many users with many
12
+ different environments - Windows also, even if it isn't officially supported by the dev team.
13
+
14
+ So *please*, follow the issue template when reporting a bug.
15
+
16
+ If you're not sure if you're standing in front of a bug, please [open a discussion](https://github.com/tekgnosis-net/wordmove-ng/discussions/new?category=general)
17
+ labeling it as "Triage", possibly using this template to report your problem (note: GH's discussions does not support templates ATM):
18
+
19
+ ```markdown
20
+ **Describe the bug**
21
+
22
+ > A clear and concise description of what the bug is.
23
+
24
+ **Wordmove command**
25
+
26
+ > Command used on the CLI: (e.g.: `wordmove-ng pull --all --no-db`)
27
+
28
+ **Expected behavior**
29
+
30
+ > A clear and concise description of what you expected to happen.
31
+
32
+ **movefile.yml**
33
+
34
+ > Paste (removing personal data) the interesting part, if any, of your `movefile.yml` formatting it inside a code block with `yml` syntax and double checking the indentation.
35
+
36
+ **Exception/trace**
37
+
38
+ > Paste (removing personal data) the entire trace of error/exception you encountered, if any
39
+
40
+ **Environment (please complete the following information):**
41
+
42
+ - OS:
43
+ - Ruby: (`ruby --version`)
44
+ - wordmove-ng: (`wordmove-ng --version`)
45
+
46
+ **Doctor**
47
+
48
+ * [x] running the `wordmove-ng doctor` command returns all green
49
+
50
+ > (If it is not, report the error you got.)
51
+ ```
52
+
53
+ As a general advise: only the latest stable wordmove-ng release is supported. Bugs in the legacy `wordmove` 5.x gem belong to its own tracker.
54
+ We'd appreciate your help opening an in depth report if you'd find that an older version is working
55
+ better for you.
56
+
57
+ Thank you all for your support and for the love <3
58
+
59
+ ### Development
60
+
61
+ #### Get Wordmove
62
+
63
+ * fork wordmove-ng
64
+ * clone your own repo
65
+ * be sure to check-out the right branch, usually `master`
66
+
67
+ ##### Installing Ruby
68
+
69
+ To install ruby, please, use [rbenv](https://github.com/rbenv/rbenv) or [RVM](https://rvm.io).
70
+
71
+ ##### Contribute
72
+
73
+ * run `bundle install` to install gem dependencies
74
+ * `git checkout -b my_feature_or_fix_name`
75
+ * code, commit, push and send a pull request on GitHub
76
+
77
+ > Never bump the version or edit CHANGELOG.md by hand: both are generated by
78
+ > release-please from the commit messages. Write [Conventional Commits](https://www.conventionalcommits.org):
79
+ > `fix: ...` (patch), `feat: ...` (minor), `feat!: ...` or a `BREAKING CHANGE:` footer (major),
80
+ > plus `docs:`, `chore:`, `ci:`, `test:`, `refactor:` for everything that does not ship a change.
81
+
82
+
83
+ ##### Test Wordmove
84
+
85
+ Wordmove has a decent test coverage. We _require_ that pull requests does not break tests launched by the CI.
86
+ In order to launch tests on you dev machine
87
+
88
+ ```fish
89
+ bundle exec rake
90
+ ```
91
+
92
+ The command will launch the test suite - written with RSpec - and rubocop. Ruby 3.0 or
93
+ newer is required; the CI matrix covers 3.0 through 4.0.
94
+
95
+ In order to use the gem locally you can install it
96
+
97
+ ```fish
98
+ bundle exec rake install
99
+ wordmove-ng --version
100
+ ```
101
+
102
+ or run the executable directly
103
+
104
+ ```fish
105
+ bin/wordmove-ng --version
106
+ ```
107
+
108
+ ### Maintainer tasks
109
+
110
+ ToDo:
111
+
112
+ * [ ] versioning and version dumping
113
+ * [ ] changelog/release
114
+ * [ ] publishing the gem
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Runtime dependencies live in wordmove-ng.gemspec
4
+ gemspec
5
+
6
+ group :development, :test do
7
+ gem "bundler", ">= 2.0", "< 5"
8
+ gem "priscilla", "~> 1.0"
9
+ gem "pry-byebug", "~> 3.1"
10
+ gem "rake", "~> 13.0"
11
+ gem "rspec", "~> 3.13"
12
+ gem "rubocop", "~> 1.90"
13
+ gem "simplecov", ">= 0.22", "< 2"
14
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2013-2019 weLaika Soc. Coop. (Wordmove)
4
+ Copyright (c) 2026 Kumar, tekgnosis.net (wordmove-ng changes)
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,340 @@
1
+ # wordmove-ng
2
+
3
+ ![logo](assets/images/wordmove-ng.png)
4
+
5
+ wordmove-ng moves WordPress sites between environments. One command pushes or pulls
6
+ the core, uploads, themes, plugins, mu-plugins, languages and the database between a
7
+ local install and any number of remote hosts over SSH, rewriting URLs and paths on the
8
+ target with wp-cli.
9
+
10
+ It is the maintained, independent successor of [Wordmove](https://github.com/welaika/wordmove)
11
+ by weLaika, continued through the [kokiddp fork](https://github.com/kokiddp/wordmove).
12
+ The movefile format, commands and flags are unchanged. What changed is under the hood, and
13
+ in a few places where the old behaviour was unsafe. See [Upgrading from wordmove 5.x](#upgrading-from-wordmove-5x).
14
+
15
+ [![Tests](https://github.com/tekgnosis-net/wordmove-ng/actions/workflows/ruby.yml/badge.svg)](https://github.com/tekgnosis-net/wordmove-ng/actions/workflows/ruby.yml)
16
+
17
+ ## Highlights
18
+
19
+ - **No Ruby-side SSH.** Every remote operation goes through the system `ssh`, `scp` and
20
+ `rsync`, so your agent, `~/.ssh/config`, jump hosts and modern key types all just work,
21
+ and nothing breaks on a new OpenSSL or Ruby.
22
+ - **The source database is never written.** Push and pull both dump the source, import on
23
+ the target and run `wp search-replace` on the target.
24
+ - **Fails before it breaks anything.** Prerequisites on both sides are probed before any
25
+ backup, dump or import. `wordmove-ng doctor` checks SSH authentication and remote programs
26
+ per environment.
27
+ - **Optional maintenance mode** around the target's database replacement.
28
+ - MariaDB first (`mariadb`, `mariadb-dump`) with MySQL fallback, sandbox-header handling,
29
+ collation and charset normalisation, socket and port support.
30
+ - Runs on Ruby 3.0 through 4.0.
31
+
32
+ ## Installation
33
+
34
+ Ruby 3.0 or newer is required.
35
+
36
+ ```bash
37
+ gem install wordmove-ng
38
+ ```
39
+
40
+ Until the gem is on rubygems.org, or to run the latest master:
41
+
42
+ ```bash
43
+ gem install specific_install
44
+ gem specific_install https://github.com/tekgnosis-net/wordmove-ng.git
45
+ ```
46
+
47
+ From a checkout:
48
+
49
+ ```bash
50
+ bundle install
51
+ bin/wordmove-ng --help
52
+ ```
53
+
54
+ ## Quick start
55
+
56
+ ```bash
57
+ cd /path/to/your/wordpress # where wp-config.php lives
58
+ wordmove-ng init # writes movefile.yml, pre-filled from wp-config.php
59
+ wordmove-ng doctor # validates movefile.yml, local tools, SSH auth, remote tools
60
+ wordmove-ng pull -e staging --all
61
+ wordmove-ng push -e production -t -p # themes and plugins only
62
+ wordmove-ng push -e production -d -s # simulate a database push
63
+ ```
64
+
65
+ Run `wordmove-ng help` for all commands and `wordmove-ng help push` for the flags.
66
+ Component flags: `-w` core, `-u` uploads, `-t` themes, `-p` plugins, `-m` mu-plugins,
67
+ `-l` languages, `-d` database, `--all` everything (`--all --no-uploads` to exclude one).
68
+ `-s` simulates, `-e` picks the environment, `-c` points at another movefile.
69
+
70
+ ## Peer dependencies
71
+
72
+ wordmove-ng is orchestration glue around standard tools.
73
+
74
+ **Locally**
75
+
76
+ | Program | Needed for |
77
+ | --- | --- |
78
+ | `ssh`, `scp`, `rsync` | every remote operation |
79
+ | `sshpass` | only when `ssh.password` is set in the movefile |
80
+ | `gzip` | database sync |
81
+ | `mysqldump` or `mariadb-dump` | `push -d` (dumping the local database) |
82
+ | `mysql` or `mariadb` | `pull -d` (importing into the local database) and `doctor` |
83
+ | `wp` ([WP-CLI](https://wp-cli.org)) | `pull -d` (adapting the local database) |
84
+
85
+ **On each remote**, in the `$PATH` of a non interactive login
86
+
87
+ | Program | Needed for |
88
+ | --- | --- |
89
+ | `rsync`, `gzip` | file and database sync |
90
+ | `mysqldump` or `mariadb-dump` | `pull -d` |
91
+ | `mysql` or `mariadb`, `wp` | `push -d` |
92
+
93
+ `wordmove-ng doctor` reports exactly what is missing where, and every database operation
94
+ re-checks before doing anything.
95
+
96
+ ## SSH authentication
97
+
98
+ Everything uses the system `ssh` client. When no `ssh.password` is configured, connections run
99
+ with `BatchMode=yes`: a failing key authentication is reported as an error with the exact
100
+ command that failed, never an interactive password prompt.
101
+
102
+ - `ssh.host`, `ssh.user`, `ssh.port` map to the obvious ssh options. A host configured in
103
+ `~/.ssh/config` works with only `ssh.host` set.
104
+ - `ssh.password` is passed through `sshpass` to `ssh`, `scp` and `rsync`. Keys are strongly
105
+ preferred.
106
+ - `ssh.gateway` becomes `ssh -J`. The jump host must accept your key or agent; a
107
+ `gateway.password` cannot be honoured and is ignored (doctor warns).
108
+ - `ssh.rsync_options` are appended to the rsync command.
109
+
110
+ Remote commands always run through `sh -c`, so the remote login shell may be bash, zsh,
111
+ fish or csh.
112
+
113
+ ## Database sync
114
+
115
+ Both directions have the same shape: dump the source, import the dump on the target, run
116
+ `wp search-replace` on the target for `vhost` and `wordpress_path`. The source database is
117
+ only ever read.
118
+
119
+ - `wordmove-ng pull -d`: back up the local database, dump the remote, import locally,
120
+ search-replace locally.
121
+ - `wordmove-ng push -d`: back up the remote database, dump locally, import on the remote,
122
+ search-replace on the remote over SSH.
123
+
124
+ Backups are written to the local `wp-content/` directory as timestamped `.sql.gz` files
125
+ before any import. If the remote adaptation fails after the import, the log names the
126
+ backup to restore from.
127
+
128
+ `wp search-replace` runs with `--all-tables --skip-columns=guid`, so every table in the
129
+ target database is adapted, including non WordPress tables sharing it, and post GUIDs are
130
+ left alone as WordPress recommends. `--no-adapt` skips the search-replace entirely.
131
+
132
+ If one of the four search terms is a prefix of another (for example a local vhost of
133
+ `https://site.test` and a remote of `https://site.test.example.com`) the shorter replacement
134
+ also rewrites the longer value. Doctor reports this as an error and the DB step warns.
135
+
136
+ ### Maintenance mode
137
+
138
+ ```yaml
139
+ global:
140
+ maintenance_mode: true
141
+ ```
142
+
143
+ wraps the target's import and search-replace in `wp maintenance-mode activate` and
144
+ `deactivate`, so visitors see the WordPress maintenance page rather than a site pointing at
145
+ the other environment's URLs for a few seconds. Deactivation runs even when the adaptation
146
+ fails. `WORDMOVE_MAINTENANCE_MODE=1` forces it on for a single run. Default: off.
147
+
148
+ ### MariaDB and MySQL compatibility
149
+
150
+ - `mariadb` and `mariadb-dump` are preferred when present, falling back to `mysql` and
151
+ `mysqldump`.
152
+ - Dumps starting with the MariaDB sandbox header (`/*!999999- enable the sandbox mode */`)
153
+ import cleanly on older servers.
154
+ - Imports run with `--binary-mode`, `SET FOREIGN_KEY_CHECKS=0` and a trailing `COMMIT;`,
155
+ unless `mysql_options` already sets binary mode.
156
+ - `database.socket` and `database.port` are first-class; `--socket` inside
157
+ `mysql_options` or `mysqldump_options` still works.
158
+ - Newer `utf8mb3` collations are rewritten to `utf8mb4_unicode_ci` and `utf8mb3` to
159
+ `utf8mb4` before import. Override or extend the mappings:
160
+
161
+ ```yaml
162
+ global:
163
+ collation_fallbacks:
164
+ utf8mb3_uca1400_ai_ci: utf8mb4_unicode_ci
165
+ charset_fallbacks:
166
+ utf8mb3: utf8mb4
167
+ ```
168
+
169
+ - `wp` is always called with `--allow-root`, so root-owned Docker installs work.
170
+
171
+ ## `movefile.yml`
172
+
173
+ ```yaml
174
+ global:
175
+ maintenance_mode: false
176
+
177
+ local:
178
+ vhost: http://vhost.local
179
+ wordpress_path: /home/john/sites/your_site
180
+
181
+ database:
182
+ name: database_name
183
+ user: user
184
+ password: password
185
+ host: localhost
186
+ # port: 3306
187
+ # socket: /path/to/mysql.sock
188
+
189
+ production:
190
+ vhost: https://example.com
191
+ wordpress_path: /var/www/your_site
192
+
193
+ database:
194
+ name: database_name
195
+ user: user
196
+ password: password
197
+ host: host
198
+ # mysqldump_options: --max_allowed_packet=50MB
199
+ # mysql_options: --protocol=TCP
200
+
201
+ exclude:
202
+ - ".git/"
203
+ - ".env"
204
+ - "node_modules/"
205
+ - "wp-config.php"
206
+ - "wp-content/*.sql.gz"
207
+
208
+ ssh:
209
+ host: host
210
+ user: user
211
+ # port: 22
212
+ # password: only with sshpass installed; prefer keys
213
+ # rsync_options: --verbose
214
+ # gateway:
215
+ # host: bastion.example.com
216
+ # user: jump
217
+
218
+ # forbid:
219
+ # push:
220
+ # db: true # never push the database to production
221
+ # hooks:
222
+ # push:
223
+ # before:
224
+ # - command: echo "about to push"
225
+ # where: local
226
+ # after:
227
+ # - command: wp cache flush
228
+ # where: remote
229
+ # raise: false
230
+ ```
231
+
232
+ Every first-level key other than `global` and `local` is a remote environment; pick one with
233
+ `-e`. `movefile.yml` is evaluated as ERB, so secrets can come from the environment or from
234
+ a `.env` / `.env.<environment>` file next to it:
235
+
236
+ ```yaml
237
+ production:
238
+ database:
239
+ password: "<%= ENV['PROD_DB_PASS'] %>"
240
+ ```
241
+
242
+ File sync mirrors the source: files missing on the source are deleted on the destination.
243
+ Put anything you need to keep in `exclude`, which is always relative to `wordpress_path`.
244
+
245
+ The wiki has the full reference:
246
+ [movefile.yml configurations explained](https://github.com/tekgnosis-net/wordmove-ng/wiki/movefile.yml-configurations-explained),
247
+ [Usage and flags explained](https://github.com/tekgnosis-net/wordmove-ng/wiki/Usage-and-flags-explained),
248
+ [Multiple environments explained](https://github.com/tekgnosis-net/wordmove-ng/wiki/Multiple-environments-explained),
249
+ [Hooks](https://github.com/tekgnosis-net/wordmove-ng/wiki/Hooks).
250
+ Where a wiki page still describes wordmove 5.x behaviour, this README wins.
251
+
252
+ ## Logging
253
+
254
+ Long generated shell scripts are summarised into intent lines such as
255
+ `dump database my_db to ./wp-content/dump.sql`, `compress ./wp-content/dump.sql`,
256
+ `wp search-replace old.test -> new.test in /var/www/site` and
257
+ `import SQL dump ... (strip sandbox header, append COMMIT)`. Passwords, hosts, vhosts and
258
+ paths from the movefile are masked as `[secret]` in all output, including hook output.
259
+
260
+ ## Upgrading from wordmove 5.x
261
+
262
+ This applies to both the original `wordmove` gem and the kokiddp fork. Your `movefile.yml`
263
+ keeps working with the exceptions below.
264
+
265
+ 1. **Install the new gem and use the new command.** `gem install wordmove-ng`, then call
266
+ `wordmove-ng` instead of `wordmove`. Both gems can stay installed side by side.
267
+ 2. **Ruby 3.0 or newer.** Ruby 2.6 and 2.7 are no longer supported.
268
+ 3. **Put `wp` on your remotes.** `push -d` now adapts the database on the remote, so WP-CLI
269
+ must be installed there and be in the `$PATH` of a non interactive login. It is a single
270
+ PHAR file: [installing WP-CLI](https://wp-cli.org/#installing). Run `wordmove-ng doctor`
271
+ to confirm.
272
+ 4. **FTP and SFTP are gone.** A movefile with an `ftp` block fails with a clear error. FTP
273
+ only ever existed for shell-less shared hosts, where the database had to be handled by
274
+ uploading temporary PHP scripts and URLs were rewritten in the dump with a regex. Keep the
275
+ legacy `wordmove` 5.x gem for such hosts, or move them to SSH.
276
+ 5. **`global.sql_adapter` is ignored.** URL and path adaptation always uses wp-cli on the
277
+ target. The key is still accepted, with a warning, so old movefiles validate; remove it
278
+ when convenient. `database.charset` (removed in 3.0) is no longer accepted by the schema.
279
+ 6. **Push no longer touches your local database.** Old versions ran `wp search-replace`
280
+ on the live local database during a push and restored it afterwards, which left the local
281
+ site pointing at production if anything failed in between. That is gone.
282
+ 7. **SSH behaves like rsync did.** If rsync worked but the database step asked for a
283
+ password, the cause was the old Net::SSH library, which could not sign RSA keys with
284
+ SHA-2. That path no longer exists. If key authentication fails now, you get an error with
285
+ the failing `ssh` command instead of a prompt. `ssh.gateway.password` is ignored.
286
+ 8. **Remote programs are checked up front.** Missing `gzip`, `mysql`, `mysqldump` or `wp`
287
+ on either side aborts before any backup or dump, listing what is missing.
288
+ 9. **New, optional:** `global.maintenance_mode` (see above).
289
+
290
+ ## Contributing
291
+
292
+ ```bash
293
+ bundle install
294
+ bundle exec rake # specs + rubocop, what CI runs
295
+ bundle exec rspec spec/deployer/ssh_db_spec.rb # one file
296
+ ```
297
+
298
+ CI runs on Ruby 3.0, 3.1, 3.2, 3.3, 3.4 and 4.0. Please keep this README updated when
299
+ changing user-facing behaviour, and write [Conventional Commits](https://www.conventionalcommits.org)
300
+ (`feat:`, `fix:`, `feat!:` for breaking changes): the changelog and version number are
301
+ generated from them. See [CONTRIBUTING.md](CONTRIBUTING.md).
302
+
303
+ ### Releasing
304
+
305
+ Releases are automated by [release-please](https://github.com/googleapis/release-please)
306
+ and published to [rubygems.org](https://rubygems.org/gems/wordmove-ng) with
307
+ [trusted publishing](https://guides.rubygems.org/trusted-publishing/), so no API key is
308
+ stored anywhere.
309
+
310
+ 1. Every push to `master` updates a "release PR" that bumps `lib/wordmove/version.rb` and
311
+ `CHANGELOG.md` according to the commits since the last release.
312
+ 2. Merging that PR creates the `vX.Y.Z` tag and the GitHub release.
313
+ 3. The `publish` job in `.github/workflows/release.yml` then runs the test suite on the
314
+ tagged commit, builds the gem, pushes it to rubygems.org and attaches the `.gem` file to
315
+ the GitHub release.
316
+
317
+ Pushing a `v*` tag by hand at the head of `master` triggers the same publish job; that is
318
+ how 6.0.0 is cut.
319
+
320
+ One-time setup for a new maintainer or a fork:
321
+
322
+ - On rubygems.org, under your profile's *Trusted publishers*, add a **pending** publisher
323
+ for gem `wordmove-ng`, repository owner `tekgnosis-net`, repository `wordmove-ng`,
324
+ workflow `release.yml`, environment `release`. It becomes a regular publisher, and you
325
+ the gem owner, after the first push.
326
+ - In the GitHub repository settings create an environment named `release`, and under
327
+ *Actions → General* enable "Allow GitHub Actions to create and approve pull requests"
328
+ so release-please can open its PR.
329
+
330
+ ## Credits and licence
331
+
332
+ - Wordmove was created and maintained for a decade by [weLaika](https://dev.welaika.com):
333
+ Stefano Verna, Ju Liu, Fabrizio Monti, Alessandro Fazzi, Filippo Gangi Dino and
334
+ [many contributors](https://github.com/welaika/wordmove/graphs/contributors). The
335
+ workflow, movefile format and most of the code are theirs.
336
+ - [kokiddp](https://github.com/kokiddp/wordmove) kept it running on modern Ruby, OpenSSL 3
337
+ and MariaDB and added socket, collation and Docker support.
338
+ - wordmove-ng is maintained by [tekgnosis.net](https://github.com/tekgnosis-net).
339
+
340
+ MIT licence, see [LICENSE](LICENSE).
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+ require 'rubocop/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ RuboCop::RakeTask.new(:rubocop)
7
+ task default: %i[spec rubocop]
Binary file
data/bin/bundle ADDED
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'bundle' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "rubygems"
12
+
13
+ m = Module.new do
14
+ module_function
15
+
16
+ def invoked_as_script?
17
+ File.expand_path($0) == File.expand_path(__FILE__)
18
+ end
19
+
20
+ def env_var_version
21
+ ENV["BUNDLER_VERSION"]
22
+ end
23
+
24
+ def cli_arg_version
25
+ return unless invoked_as_script? # don't want to hijack other binstubs
26
+ return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
27
+ bundler_version = nil
28
+ update_index = nil
29
+ ARGV.each_with_index do |a, i|
30
+ if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
31
+ bundler_version = a
32
+ end
33
+ next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34
+ bundler_version = $1 || ">= 0.a"
35
+ update_index = i
36
+ end
37
+ bundler_version
38
+ end
39
+
40
+ def gemfile
41
+ gemfile = ENV["BUNDLE_GEMFILE"]
42
+ return gemfile if gemfile && !gemfile.empty?
43
+
44
+ File.expand_path("../../Gemfile", __FILE__)
45
+ end
46
+
47
+ def lockfile
48
+ lockfile =
49
+ case File.basename(gemfile)
50
+ when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
51
+ else "#{gemfile}.lock"
52
+ end
53
+ File.expand_path(lockfile)
54
+ end
55
+
56
+ def lockfile_version
57
+ return unless File.file?(lockfile)
58
+ lockfile_contents = File.read(lockfile)
59
+ return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
60
+ Regexp.last_match(1)
61
+ end
62
+
63
+ def bundler_version
64
+ @bundler_version ||= begin
65
+ env_var_version || cli_arg_version ||
66
+ lockfile_version || "#{Gem::Requirement.default}.a"
67
+ end
68
+ end
69
+
70
+ def load_bundler!
71
+ ENV["BUNDLE_GEMFILE"] ||= gemfile
72
+
73
+ # must dup string for RG < 1.8 compatibility
74
+ activate_bundler(bundler_version.dup)
75
+ end
76
+
77
+ def activate_bundler(bundler_version)
78
+ if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
79
+ bundler_version = "< 2"
80
+ end
81
+ gem_error = activation_error_handling do
82
+ gem "bundler", bundler_version
83
+ end
84
+ return if gem_error.nil?
85
+ require_error = activation_error_handling do
86
+ require "bundler/version"
87
+ end
88
+ return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
89
+ warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
90
+ exit 42
91
+ end
92
+
93
+ def activation_error_handling
94
+ yield
95
+ nil
96
+ rescue StandardError, LoadError => e
97
+ e
98
+ end
99
+ end
100
+
101
+ m.load_bundler!
102
+
103
+ if m.invoked_as_script?
104
+ load Gem.bin_path("bundler", "bundle")
105
+ end
data/bin/bundler ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'bundler' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("bundler", "bundler")
data/bin/byebug ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'byebug' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("byebug", "byebug")
data/bin/coderay ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'coderay' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 150) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("coderay", "coderay")