rails-credentials-conflict 0.1.0 → 0.2.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 +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +27 -1
- data/lib/rails/credentials/conflict/merge_driver.rb +60 -0
- data/lib/rails/credentials/conflict/version.rb +1 -1
- data/lib/rails/credentials/conflict.rb +1 -0
- data/lib/tasks/credentials_conflict.rake +42 -0
- metadata +6 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e3cd17fd0e8851b22e9b7ecf7e539ba99d1080a1aad3fc65c98c1cb72ce536e0
|
|
4
|
+
data.tar.gz: f8f643184cc1eeca3305bd6249bf8fc8da126baaa214c732cfe0e6b0e582669d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3b9f6572939173826d39f0a85051b9ea7ae9cf01544dc975305e836b1b7d50da79ceaea93d78aa909cbf02532a0d34e5db259694957928e9715ee09faf6275f2
|
|
7
|
+
data.tar.gz: f19f66117c4cc206bc11ec23a248f62f231305454bf361162814fa0c7e110a1dd263ecc2d507007b07b50e6f59c4f24debf0383567a7763c61865460ef11905a
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.2.0] - 2026-04-13
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Automatic credentials conflict resolution via a custom git merge driver
|
|
13
|
+
- `base` command to select the base version from git stages
|
|
14
|
+
- Auto-merge of non-conflicting changes in different sections
|
|
15
|
+
- Conflict markers enriched with branch names and commit SHAs
|
|
16
|
+
- Use of `git merge-file` to produce proper conflict markers
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Refactored resolver into focused, single-responsibility classes
|
|
21
|
+
- Enhanced documentation and error handling across conflict resolution
|
|
22
|
+
- Improved gem summary and description
|
|
23
|
+
- Lowered Ruby version requirement
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- Read resolved content from disk after the editor saves
|
|
28
|
+
- Task argument syntax for the environment parameter
|
|
29
|
+
|
|
8
30
|
## [0.1.0] - 2025-01-01
|
|
9
31
|
|
|
10
32
|
### Added
|
data/README.md
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
# Rails Credentials Conflict
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://rubygems.org/gems/rails-credentials-conflict)
|
|
4
|
+
[](LICENSE.txt)
|
|
5
|
+
[](https://www.ruby-lang.org)
|
|
6
|
+
[](https://rubyonrails.org)
|
|
7
|
+
|
|
8
|
+
Resolve git merge conflicts in Rails encrypted credentials by decrypting, merging, and re-encrypting them. Works with merge, rebase, and cherry-pick.
|
|
9
|
+
|
|
10
|
+
- [RubyGems](https://rubygems.org/gems/rails-credentials-conflict)
|
|
11
|
+
- [Source Code](https://github.com/jwo1f/rails-credentials-conflict)
|
|
12
|
+
- [Changelog](CHANGELOG.md)
|
|
4
13
|
|
|
5
14
|
## Problem
|
|
6
15
|
|
|
@@ -28,6 +37,23 @@ And then execute:
|
|
|
28
37
|
bundle install
|
|
29
38
|
```
|
|
30
39
|
|
|
40
|
+
## Automatic merge driver (recommended)
|
|
41
|
+
|
|
42
|
+
Register a custom git merge driver so that git can automatically decrypt, merge, and re-encrypt credentials during merge, rebase, and cherry-pick — resolving conflicts transparently when changes are in different sections.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
rails credentials:conflict:install
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This command:
|
|
49
|
+
|
|
50
|
+
1. Adds a `rails-credentials` merge driver to your local `.git/config`
|
|
51
|
+
2. Appends rules to `.gitattributes` so all `*.yml.enc` credentials files use it
|
|
52
|
+
|
|
53
|
+
**How it works:** When git encounters a conflict in a credentials file it invokes the merge driver instead of producing encrypted gibberish with conflict markers. The driver decrypts all three versions (base, ours, theirs), runs a three-way merge, and re-encrypts the result. If the changes are in different sections the merge succeeds automatically (exit 0). If there is a real conflict the driver exits 1, git marks the file as conflicted, and you can fall back to the manual rake tasks below.
|
|
54
|
+
|
|
55
|
+
> **Note:** `.gitattributes` should be committed so the whole team benefits. The `.git/config` entry is local — each developer runs `rails credentials:conflict:install` once after cloning.
|
|
56
|
+
|
|
31
57
|
## Usage
|
|
32
58
|
|
|
33
59
|
When you encounter a merge conflict in your credentials file, you have four options:
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rails
|
|
4
|
+
module Credentials
|
|
5
|
+
module Conflict
|
|
6
|
+
# Git merge driver entry point for encrypted credentials files.
|
|
7
|
+
#
|
|
8
|
+
# Invoked by git during merge/rebase/cherry-pick when a custom
|
|
9
|
+
# merge driver is configured via +.gitattributes+.
|
|
10
|
+
#
|
|
11
|
+
# Git calls the driver with four paths:
|
|
12
|
+
# - +base_path+ (+%O+) — common ancestor version
|
|
13
|
+
# - +ours_path+ (+%A+) — current branch version (result is written here)
|
|
14
|
+
# - +theirs_path+ (+%B+) — other branch version
|
|
15
|
+
# - +file_path+ (+%P+) — pathname of the file being merged
|
|
16
|
+
module MergeDriver
|
|
17
|
+
# Extracts the environment name from a credentials file path.
|
|
18
|
+
#
|
|
19
|
+
# "config/credentials.yml.enc" → nil
|
|
20
|
+
# "config/credentials/staging.yml.enc" → "staging"
|
|
21
|
+
def self.extract_environment(file_path)
|
|
22
|
+
if file_path =~ %r{config/credentials/([^/]+)\.yml\.enc\z}
|
|
23
|
+
$1
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Runs the merge driver. Decrypts the three versions, performs a
|
|
28
|
+
# three-way merge, and writes the encrypted result back to +ours_path+.
|
|
29
|
+
#
|
|
30
|
+
# Returns +0+ on successful auto-merge, +1+ when conflicts remain.
|
|
31
|
+
def self.call(base_path, ours_path, theirs_path, file_path)
|
|
32
|
+
environment = extract_environment(file_path)
|
|
33
|
+
path_resolver = PathResolver.new(environment)
|
|
34
|
+
encryption_service = EncryptionService.new(path_resolver.key_path)
|
|
35
|
+
merge_strategy = MergeStrategy.new(encryption_service)
|
|
36
|
+
|
|
37
|
+
base_content = encryption_service.decrypt(File.binread(base_path))
|
|
38
|
+
ours_content = encryption_service.decrypt(File.binread(ours_path))
|
|
39
|
+
theirs_content = encryption_service.decrypt(File.binread(theirs_path))
|
|
40
|
+
|
|
41
|
+
return 0 if ours_content == theirs_content
|
|
42
|
+
|
|
43
|
+
result = merge_strategy.create_conflict_markers(
|
|
44
|
+
ours_content,
|
|
45
|
+
base_content,
|
|
46
|
+
theirs_content,
|
|
47
|
+
labels: { ours: "ours", base: "base", theirs: "theirs" }
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
return 1 if result[:has_conflicts]
|
|
51
|
+
|
|
52
|
+
encryption_service.save_encrypted(result[:content], ours_path)
|
|
53
|
+
0
|
|
54
|
+
rescue StandardError
|
|
55
|
+
1
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -6,6 +6,7 @@ require_relative "conflict/encryption_service"
|
|
|
6
6
|
require_relative "conflict/git_conflict_handler"
|
|
7
7
|
require_relative "conflict/merge_strategy"
|
|
8
8
|
require_relative "conflict/resolver"
|
|
9
|
+
require_relative "conflict/merge_driver"
|
|
9
10
|
require_relative "conflict/railtie" if defined?(Rails::Railtie)
|
|
10
11
|
|
|
11
12
|
module Rails
|
|
@@ -31,5 +31,47 @@ namespace :credentials do
|
|
|
31
31
|
rescue Rails::Credentials::Conflict::Error => e
|
|
32
32
|
abort e.message
|
|
33
33
|
end
|
|
34
|
+
|
|
35
|
+
desc "Install git merge driver for automatic credentials conflict resolution"
|
|
36
|
+
task install: :environment do
|
|
37
|
+
require "open3"
|
|
38
|
+
|
|
39
|
+
# Configure git merge driver
|
|
40
|
+
commands = [
|
|
41
|
+
["git", "config", "merge.rails-credentials.name", "Rails encrypted credentials merge driver"],
|
|
42
|
+
["git", "config", "merge.rails-credentials.driver",
|
|
43
|
+
"bundle exec rails runner \"Rails::Credentials::Conflict::MergeDriver.call('%O', '%A', '%B', '%P')\""]
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
commands.each do |cmd|
|
|
47
|
+
_, status = Open3.capture2(*cmd)
|
|
48
|
+
abort "Failed to run: #{cmd.join(" ")}" unless status.success?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
puts "Configured git merge driver 'rails-credentials' in .git/config"
|
|
52
|
+
|
|
53
|
+
# Update .gitattributes
|
|
54
|
+
gitattributes_path = Rails.root.join(".gitattributes")
|
|
55
|
+
existing_content = File.exist?(gitattributes_path) ? File.read(gitattributes_path) : ""
|
|
56
|
+
|
|
57
|
+
lines_to_add = [
|
|
58
|
+
"config/credentials.yml.enc merge=rails-credentials",
|
|
59
|
+
"config/credentials/*.yml.enc merge=rails-credentials"
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
new_lines = lines_to_add.reject { |line| existing_content.include?(line) }
|
|
63
|
+
|
|
64
|
+
if new_lines.any?
|
|
65
|
+
File.open(gitattributes_path, "a") do |f|
|
|
66
|
+
f.puts unless existing_content.empty? && !existing_content.end_with?("\n")
|
|
67
|
+
new_lines.each { |line| f.puts(line) }
|
|
68
|
+
end
|
|
69
|
+
puts "Added merge driver entries to .gitattributes"
|
|
70
|
+
else
|
|
71
|
+
puts ".gitattributes already configured"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
puts "Done! Credentials conflicts will now be auto-merged when possible."
|
|
75
|
+
end
|
|
34
76
|
end
|
|
35
77
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails-credentials-conflict
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- jwo1f
|
|
@@ -37,8 +37,8 @@ dependencies:
|
|
|
37
37
|
- - ">="
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '6.0'
|
|
40
|
-
description:
|
|
41
|
-
|
|
40
|
+
description: Resolve git merge conflicts in Rails encrypted credentials by decrypting,
|
|
41
|
+
merging, and re-encrypting them. Works with merge, rebase, and cherry-pick.
|
|
42
42
|
email:
|
|
43
43
|
- ''
|
|
44
44
|
executables: []
|
|
@@ -52,6 +52,7 @@ files:
|
|
|
52
52
|
- lib/rails/credentials/conflict.rb
|
|
53
53
|
- lib/rails/credentials/conflict/encryption_service.rb
|
|
54
54
|
- lib/rails/credentials/conflict/git_conflict_handler.rb
|
|
55
|
+
- lib/rails/credentials/conflict/merge_driver.rb
|
|
55
56
|
- lib/rails/credentials/conflict/merge_strategy.rb
|
|
56
57
|
- lib/rails/credentials/conflict/path_resolver.rb
|
|
57
58
|
- lib/rails/credentials/conflict/railtie.rb
|
|
@@ -89,7 +90,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
89
90
|
- !ruby/object:Gem::Version
|
|
90
91
|
version: '0'
|
|
91
92
|
requirements: []
|
|
92
|
-
rubygems_version: 4.0.
|
|
93
|
+
rubygems_version: 4.0.3
|
|
93
94
|
specification_version: 4
|
|
94
|
-
summary: Resolve
|
|
95
|
+
summary: Resolve git merge conflicts in Rails encrypted credentials
|
|
95
96
|
test_files: []
|