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 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,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'rails_rebase_migrations'
5
+
6
+ RebaseMigrations.new.main
@@ -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: []