rails-rebase-migrations 1.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.
- checksums.yaml +7 -0
- data/bin/rebase-migrations +6 -0
- data/lib/rebase_migrations.rb +112 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 308418a394a967adb56ba7e5a4826f1e23b139e9250a219ced47ea195e65e9e8
|
4
|
+
data.tar.gz: 04f7d242120998f9632ba540fd3b2ffaa06b8cc5a6537275ed37c33f808c478f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f547e60c2d6b62b5173b9b1ab136b6d4951a4c8e91202d61b3d6c871587a43a2884bfb6c1f19d260c9831cbdc9dbb1e220760497ad9c0d6fdc9e2cecf4fd2108
|
7
|
+
data.tar.gz: dc692ba49d38af2f21ae9ab6b88fc3f91e0c0865ea30816206deb475fbf8544beafbbce206cfb509f4c11ecd3b3565529c460b916b6ee481a4afd69a52f6b074
|
@@ -0,0 +1,112 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'open3'
|
5
|
+
require 'optparse'
|
6
|
+
require 'shellwords'
|
7
|
+
|
8
|
+
class RebaseMigrations
|
9
|
+
SKIP_REBASE = '_skip_rebase_'
|
10
|
+
|
11
|
+
MIGRATIONS_DIR = 'db/migrate/'
|
12
|
+
MIGRATION_NAME_RE = /^(\d+)(.*)$/
|
13
|
+
|
14
|
+
def main
|
15
|
+
ref, options = parse_args
|
16
|
+
|
17
|
+
out = subprocess('git', 'ls-files', '--', MIGRATIONS_DIR)
|
18
|
+
all_migrations = out.split("\n").to_a.sort
|
19
|
+
|
20
|
+
out = subprocess('git', 'diff', '--diff-filter=A', '--name-only', ref, '--', MIGRATIONS_DIR)
|
21
|
+
new_migrations = out.split("\n").to_a.sort
|
22
|
+
|
23
|
+
starting_index = all_migrations.length - new_migrations.length
|
24
|
+
|
25
|
+
now = Time.now.to_i
|
26
|
+
|
27
|
+
return if new_migrations.empty?
|
28
|
+
|
29
|
+
new_migrations.each do |path|
|
30
|
+
basename = File.basename(path)
|
31
|
+
match = MIGRATION_NAME_RE.match(File.basename(path))
|
32
|
+
migration_timestamp = match[1]
|
33
|
+
migration_name_base = match[2]
|
34
|
+
next if migration_name_base.start_with?(SKIP_REBASE)
|
35
|
+
|
36
|
+
if options[:check]
|
37
|
+
index = all_migrations.index(path)
|
38
|
+
if index < starting_index
|
39
|
+
skip_migration_name = "#{migration_timestamp}#{SKIP_REBASE}#{migration_name_base[1..]}"
|
40
|
+
|
41
|
+
warn <<~MSG
|
42
|
+
Migration #{basename} is out of order. It should come after
|
43
|
+
pre-existing migrations. To fix, run the command:
|
44
|
+
|
45
|
+
$ ./tools/rebase-migrations
|
46
|
+
|
47
|
+
If the migration is intentionally out of order, add the magic
|
48
|
+
string "#{SKIP_REBASE}" to the beginning of the migration name:
|
49
|
+
|
50
|
+
$ git mv #{path} #{MIGRATIONS_DIR}#{skip_migration_name}
|
51
|
+
|
52
|
+
If this pull request is merging across branches prod, staging, or
|
53
|
+
main, then add the "review-merge" label.
|
54
|
+
MSG
|
55
|
+
|
56
|
+
exit 1
|
57
|
+
end
|
58
|
+
else
|
59
|
+
new_timestamp = Time.at(now).utc.strftime('%Y%m%d%H%M%S')
|
60
|
+
new_migration_name = "#{new_timestamp}#{migration_name_base}"
|
61
|
+
subprocess('git', 'mv', path, "#{MIGRATIONS_DIR}#{new_migration_name}")
|
62
|
+
# Add 120s so the new migrations maintain the same order and provides
|
63
|
+
# room between the migrations to inject new ones.
|
64
|
+
now += 120
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
return if options[:check]
|
69
|
+
|
70
|
+
# Regenerate db/schema.rb
|
71
|
+
system('rails', 'db:drop', 'db:create', 'db:migrate', exception: true)
|
72
|
+
subprocess('git', 'add', 'db/schema.rb')
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def parse_args
|
78
|
+
options = {}
|
79
|
+
|
80
|
+
parser = OptionParser.new do |opts|
|
81
|
+
opts.banner = "Usage: #{opts.program_name} [--check] [REF]"
|
82
|
+
|
83
|
+
opts.on('--check', 'Check new migrations are ordered last. Exit with status code 1 if they are not.')
|
84
|
+
|
85
|
+
opts.on('--help', '-h', 'Print this help') do
|
86
|
+
puts opts
|
87
|
+
exit
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
args = parser.parse(ARGV, into: options)
|
92
|
+
if args.length > 1
|
93
|
+
warn "Expected 0 or 1 positional arguments but found #{args.length}."
|
94
|
+
exit 2
|
95
|
+
end
|
96
|
+
ref = args.first || 'main'
|
97
|
+
|
98
|
+
[ref, options]
|
99
|
+
end
|
100
|
+
|
101
|
+
def subprocess(*args)
|
102
|
+
stdin, stdout, wait_thr = Open3.popen2(*args)
|
103
|
+
stdin.close
|
104
|
+
out = stdout.read
|
105
|
+
stdout.close
|
106
|
+
status = wait_thr.value
|
107
|
+
|
108
|
+
raise "Command failed: #{status}\n\n #{Shellwords.join(args)}\n" if status != 0
|
109
|
+
|
110
|
+
out
|
111
|
+
end
|
112
|
+
end
|
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rails-rebase-migrations
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pioneer Valley Books
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-10-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.1'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '8'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '6.1'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '8'
|
33
|
+
description: |
|
34
|
+
# Rebase Migrations
|
35
|
+
|
36
|
+
Rebase Migrations is a library and command line tool to rebase Rails migrations
|
37
|
+
to have the latest timestamp.
|
38
|
+
|
39
|
+
## Installation
|
40
|
+
|
41
|
+
```console
|
42
|
+
$ bundle add rebase-migrations --group=development,test
|
43
|
+
```
|
44
|
+
|
45
|
+
## Scenario
|
46
|
+
|
47
|
+
Two team members, Alice and Bob, are working on the same Rails project and both
|
48
|
+
are adding new database migrations. Alice realizes her migration depends on
|
49
|
+
Bob's, but the migration timestamps are out of order. The `rebase-migration`
|
50
|
+
command line tool can be used to reorder Alice's new migrations to have the
|
51
|
+
latest timestamp in the sequence.
|
52
|
+
|
53
|
+
## Usage
|
54
|
+
|
55
|
+
To rebase all new migrations with respect to the `main` git branch:
|
56
|
+
|
57
|
+
```console
|
58
|
+
$ bundle exec rebase-migrations
|
59
|
+
```
|
60
|
+
|
61
|
+
To rebase all new migrations with respect to a different branch:
|
62
|
+
|
63
|
+
```console
|
64
|
+
$ bundle exec rebase-migrations my-branch
|
65
|
+
```
|
66
|
+
|
67
|
+
The command has a `--check` argument that is useful for CI. To check that all
|
68
|
+
new migrations are the latest in the sequence:
|
69
|
+
|
70
|
+
```console
|
71
|
+
$ bundle exec rebase-migrations --check
|
72
|
+
```
|
73
|
+
|
74
|
+
It will exit with status code 1 if the check fails. The `--check` form also
|
75
|
+
accepts a branch argument.
|
76
|
+
|
77
|
+
### Skipping Migrations
|
78
|
+
|
79
|
+
To skip a specific migration files from the `--check` include `_skip_rebase` in
|
80
|
+
its filename.
|
81
|
+
email:
|
82
|
+
executables:
|
83
|
+
- rebase-migrations
|
84
|
+
extensions: []
|
85
|
+
extra_rdoc_files: []
|
86
|
+
files:
|
87
|
+
- bin/rebase-migrations
|
88
|
+
- lib/rebase_migrations.rb
|
89
|
+
homepage: https://github.com/Pioneer-Valley-Books/rebase-migrations
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata:
|
93
|
+
rubygems_mfa_required: 'true'
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '3.0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubygems_version: 3.3.7
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: Rebase Rails migrations to be the latest
|
113
|
+
test_files: []
|