infinum_app_revision 0.1.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: f2b11c408e68ff49ba458642cfee2ad19ffc03743ae4dcd7f5105e782ab6cf1c
4
+ data.tar.gz: 4c380bc2f1c3a6c57bd846ec32abb9be0b2a98c8b441926a3d48204970e1a48b
5
+ SHA512:
6
+ metadata.gz: 90ae1352930a043874f6d79547e2b1fec9c74c3c2a4c8b8576a54911c74ae0ed8fb266bd0d2e51eaa5e2639c6ffb59f1096a53f6d12053481b60bbe89f35a555
7
+ data.tar.gz: d8dcbfbe903ac1507ad135dc16cd0b142451febf76449fd0e17c7d98e3161853b3bc7adfab1f7a340f5939fbcd74ab31c8d42ad8905ba0e8d5b6036adfd7f2de
@@ -0,0 +1,21 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+
6
+ jobs:
7
+ build:
8
+ runs-on: ubuntu-latest
9
+
10
+ steps:
11
+ - uses: actions/checkout@v3
12
+ - name: Set up Ruby
13
+ uses: ruby/setup-ruby@v1
14
+ with:
15
+ bundler-cache: true
16
+ - name: Install dependencies
17
+ run: bundle install
18
+ - name: Run rubocop
19
+ run: bundle exec rubocop
20
+ - name: Run tests
21
+ run: bundle exec rspec
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/tmp/
9
+ /tmp/
10
+ /private/ # only in case specs don't cleanup
11
+
12
+ !.keep
13
+ # rspec failure tracking
14
+ .rspec_status
data/.overcommit.yml ADDED
@@ -0,0 +1,26 @@
1
+ gemfile: Gemfile
2
+
3
+ CommitMsg:
4
+ HardTabs:
5
+ enabled: true
6
+
7
+ PreCommit:
8
+ BundleAudit:
9
+ enabled: true
10
+ flags: ['--update']
11
+ on_warn: fail
12
+ command: ['bundle', 'exec', 'bundle-audit']
13
+
14
+ BundleCheck:
15
+ enabled: true
16
+
17
+ RuboCop:
18
+ enabled: true
19
+ on_warn: fail
20
+ command: ['bundle', 'exec', 'rubocop']
21
+
22
+ TrailingWhitespace:
23
+ enabled: true
24
+
25
+ HardTabs:
26
+ enabled: true
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,23 @@
1
+ plugins:
2
+ - rubocop-infinum
3
+ - rubocop-rake
4
+
5
+ Metrics/BlockLength:
6
+ Exclude:
7
+ - 'spec/**/*_spec.rb'
8
+
9
+ RSpec/ExampleLength:
10
+ Max: 10
11
+
12
+ RSpec/MultipleExpectations:
13
+ Max: 5
14
+
15
+ Style/AccessorGrouping:
16
+ EnforcedStyle: separated
17
+
18
+ Style/FrozenStringLiteralComment:
19
+ Enabled: false
20
+
21
+ AllCops:
22
+ TargetRubyVersion: 3.2
23
+ NewCops: enable
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.4.5
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2025-10-01
4
+
5
+ - Initial release
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ # Specify your gem's dependencies in infinum-app-revision.gemspec
6
+ gemspec
7
+
8
+ gem 'bundler-audit', require: false
9
+ gem 'overcommit', '~> 0.58', require: false
10
+ gem 'rake', require: false
11
+ gem 'rspec', require: false
12
+ gem 'rubocop', '~> 1.0', require: false
13
+ gem 'rubocop-infinum', require: false
14
+ gem 'rubocop-rake', require: false
15
+ gem 'simplecov', require: false
data/Gemfile.lock ADDED
@@ -0,0 +1,150 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ infinum_app_revision (0.1.0)
5
+ json
6
+ rack (>= 2.0)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ activesupport (8.1.1)
12
+ base64
13
+ bigdecimal
14
+ concurrent-ruby (~> 1.0, >= 1.3.1)
15
+ connection_pool (>= 2.2.5)
16
+ drb
17
+ i18n (>= 1.6, < 2)
18
+ json
19
+ logger (>= 1.4.2)
20
+ minitest (>= 5.1)
21
+ securerandom (>= 0.3)
22
+ tzinfo (~> 2.0, >= 2.0.5)
23
+ uri (>= 0.13.1)
24
+ ast (2.4.3)
25
+ base64 (0.3.0)
26
+ bigdecimal (3.3.1)
27
+ bundler-audit (0.9.2)
28
+ bundler (>= 1.2.0, < 3)
29
+ thor (~> 1.0)
30
+ childprocess (5.1.0)
31
+ logger (~> 1.5)
32
+ concurrent-ruby (1.3.5)
33
+ connection_pool (2.5.4)
34
+ diff-lcs (1.6.2)
35
+ docile (1.4.1)
36
+ drb (2.2.3)
37
+ i18n (1.14.7)
38
+ concurrent-ruby (~> 1.0)
39
+ iniparse (1.5.0)
40
+ json (2.16.0)
41
+ language_server-protocol (3.17.0.5)
42
+ lint_roller (1.1.0)
43
+ logger (1.7.0)
44
+ minitest (5.26.1)
45
+ overcommit (0.68.0)
46
+ childprocess (>= 0.6.3, < 6)
47
+ iniparse (~> 1.4)
48
+ rexml (>= 3.3.9)
49
+ parallel (1.27.0)
50
+ parser (3.3.10.0)
51
+ ast (~> 2.4.1)
52
+ racc
53
+ prism (1.6.0)
54
+ racc (1.8.1)
55
+ rack (3.2.4)
56
+ rainbow (3.1.1)
57
+ rake (13.3.1)
58
+ regexp_parser (2.11.3)
59
+ rexml (3.4.4)
60
+ rspec (3.13.2)
61
+ rspec-core (~> 3.13.0)
62
+ rspec-expectations (~> 3.13.0)
63
+ rspec-mocks (~> 3.13.0)
64
+ rspec-core (3.13.6)
65
+ rspec-support (~> 3.13.0)
66
+ rspec-expectations (3.13.5)
67
+ diff-lcs (>= 1.2.0, < 2.0)
68
+ rspec-support (~> 3.13.0)
69
+ rspec-mocks (3.13.7)
70
+ diff-lcs (>= 1.2.0, < 2.0)
71
+ rspec-support (~> 3.13.0)
72
+ rspec-support (3.13.6)
73
+ rubocop (1.81.7)
74
+ json (~> 2.3)
75
+ language_server-protocol (~> 3.17.0.2)
76
+ lint_roller (~> 1.1.0)
77
+ parallel (~> 1.10)
78
+ parser (>= 3.3.0.2)
79
+ rainbow (>= 2.2.2, < 4.0)
80
+ regexp_parser (>= 2.9.3, < 3.0)
81
+ rubocop-ast (>= 1.47.1, < 2.0)
82
+ ruby-progressbar (~> 1.7)
83
+ unicode-display_width (>= 2.4.0, < 4.0)
84
+ rubocop-ast (1.48.0)
85
+ parser (>= 3.3.7.2)
86
+ prism (~> 1.4)
87
+ rubocop-factory_bot (2.27.1)
88
+ lint_roller (~> 1.1)
89
+ rubocop (~> 1.72, >= 1.72.1)
90
+ rubocop-infinum (1.0.0)
91
+ lint_roller
92
+ rubocop (>= 1.72.1)
93
+ rubocop-factory_bot (>= 2.27.1)
94
+ rubocop-performance (>= 1.24.0)
95
+ rubocop-rails (>= 2.30.0)
96
+ rubocop-rspec (>= 3.5.0)
97
+ rubocop-rspec_rails (>= 2.31.0)
98
+ rubocop-performance (1.26.1)
99
+ lint_roller (~> 1.1)
100
+ rubocop (>= 1.75.0, < 2.0)
101
+ rubocop-ast (>= 1.47.1, < 2.0)
102
+ rubocop-rails (2.33.4)
103
+ activesupport (>= 4.2.0)
104
+ lint_roller (~> 1.1)
105
+ rack (>= 1.1)
106
+ rubocop (>= 1.75.0, < 2.0)
107
+ rubocop-ast (>= 1.44.0, < 2.0)
108
+ rubocop-rake (0.7.1)
109
+ lint_roller (~> 1.1)
110
+ rubocop (>= 1.72.1)
111
+ rubocop-rspec (3.7.0)
112
+ lint_roller (~> 1.1)
113
+ rubocop (~> 1.72, >= 1.72.1)
114
+ rubocop-rspec_rails (2.31.0)
115
+ lint_roller (~> 1.1)
116
+ rubocop (~> 1.72, >= 1.72.1)
117
+ rubocop-rspec (~> 3.5)
118
+ ruby-progressbar (1.13.0)
119
+ securerandom (0.4.1)
120
+ simplecov (0.22.0)
121
+ docile (~> 1.1)
122
+ simplecov-html (~> 0.11)
123
+ simplecov_json_formatter (~> 0.1)
124
+ simplecov-html (0.13.2)
125
+ simplecov_json_formatter (0.1.4)
126
+ thor (1.4.0)
127
+ tzinfo (2.0.6)
128
+ concurrent-ruby (~> 1.0)
129
+ unicode-display_width (3.2.0)
130
+ unicode-emoji (~> 4.1)
131
+ unicode-emoji (4.1.0)
132
+ uri (1.1.1)
133
+
134
+ PLATFORMS
135
+ arm64-darwin-24
136
+ ruby
137
+
138
+ DEPENDENCIES
139
+ bundler-audit
140
+ infinum_app_revision!
141
+ overcommit (~> 0.58)
142
+ rake
143
+ rspec
144
+ rubocop (~> 1.0)
145
+ rubocop-infinum
146
+ rubocop-rake
147
+ simplecov
148
+
149
+ BUNDLED WITH
150
+ 2.5.16
data/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # InfinumAppRevision
2
+
3
+ Simple Rack middleware to expose the app revision via an HTTP header.
4
+
5
+ ## Installation
6
+
7
+ Add `infinum_app_revision` to your gemfile:
8
+
9
+ ```ruby
10
+ gem 'infinum_app_revision'
11
+ ```
12
+
13
+ or run
14
+
15
+ ```bash
16
+ bundle add infinum_app_revision
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ By default the middleware sets the `X-App-Revision` header on every HTTP response. You can plug it into any Rack app (including Rails) and choose how the revision is determined via a version provider.
22
+
23
+ ### Rack (config.ru)
24
+
25
+ ```ruby
26
+ require 'rack'
27
+ require 'infinum_app_revision'
28
+
29
+ # Choose a version provider (see options below)
30
+ version_provider = InfinumAppRevision::VersionProvider::Docker.new
31
+
32
+ use InfinumAppRevision::Middleware, version_provider: version_provider
33
+ run ->(_env) { [200, { 'Content-Type' => 'text/plain' }, ['OK']] }
34
+ ```
35
+
36
+ ### Rails
37
+
38
+ Add to your middleware stack (e.g., in `config/application.rb` or an environment file):
39
+
40
+ ```ruby
41
+ # config/application.rb
42
+ require 'infinum_app_revision'
43
+
44
+ module YourApp
45
+ class Application < Rails::Application
46
+ # ...
47
+ config.middleware.use InfinumAppRevision::Middleware,
48
+ version_provider: InfinumAppRevision::VersionProvider::Docker.new
49
+ end
50
+ end
51
+ ```
52
+
53
+ ### Version providers
54
+
55
+ - Docker (default example): reads a JSON file (defaults to `private/version.json`) containing the revision and optional metadata.
56
+
57
+ Default path can be overridden:
58
+ ```ruby
59
+ InfinumAppRevision::VersionProvider::Docker.new(
60
+ version_file_path: 'path/to/version.json'
61
+ )
62
+ ```
63
+
64
+ Expected file format:
65
+ ```json
66
+ {
67
+ "revision": "abc1234",
68
+ "build_time": "2025-11-09T12:34:56Z",
69
+ "branch": "main"
70
+ }
71
+ ```
72
+
73
+ Write this file during the container image build.
74
+
75
+ - Mina: reads the revision from a `.mina_git_revision` file at the project root.
76
+
77
+ ```ruby
78
+ InfinumAppRevision::VersionProvider::Mina.new
79
+ ```
80
+
81
+ Write the file during deploy, for example:
82
+ ```bash
83
+ git rev-parse --short HEAD > .mina_git_revision
84
+ ```
85
+
86
+ If you're using [mina](https://mina-deploy.github.io/mina/) to deploy your app then it should already create this file automatically.
87
+
88
+ - Base (fallback): if you don’t pass a provider, the base provider will yield `"undefined"` as the revision.
89
+
90
+ ### Custom header name
91
+
92
+ Change the response header name if needed:
93
+
94
+ ```ruby
95
+ use InfinumAppRevision::Middleware,
96
+ header: 'X-Revision',
97
+ version_provider: InfinumAppRevision::VersionProvider::Docker.new
98
+ ```
99
+
100
+ ## Development
101
+
102
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
103
+
104
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
105
+
106
+ ## License
107
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
data/bin/console ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'bundler/setup'
5
+ require 'infinum_app_revision'
6
+
7
+ require 'irb'
8
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ overcommit --install
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/infinum_app_revision/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'infinum_app_revision'
7
+ spec.version = InfinumAppRevision::VERSION
8
+ spec.summary = 'Infinum App Revision'
9
+ spec.description = 'Simple middleware for reporting back deployed app revisions.'
10
+ spec.authors = ['Team Backend @ Infinum']
11
+ spec.email = ['team.backend@infinum.com']
12
+ spec.files = `git ls-files`.split("\n")
13
+ spec.require_paths = ['lib']
14
+ spec.homepage = 'https://github.com/infinum/rails-infinum-app-revision'
15
+ spec.license = 'MIT'
16
+ spec.required_ruby_version = '>= 3.2'
17
+ spec.metadata = { 'rubygems_mfa_required' => 'true', 'homepage_uri' => spec.homepage }
18
+
19
+ spec.add_dependency 'json'
20
+ spec.add_dependency 'rack', '>= 2.0'
21
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InfinumAppRevision
4
+ class Middleware
5
+ def initialize(app, header: DEFAULT_HEADER, version_provider: VersionProvider::Base.new)
6
+ @app = app
7
+ @header = header
8
+ @version_provider = version_provider
9
+ end
10
+
11
+ def call(env)
12
+ @app.call(env).tap do |_status, headers, _body|
13
+ headers[@header] = @version_provider.version.id
14
+ end
15
+ end
16
+
17
+ DEFAULT_HEADER = 'X-App-Revision'
18
+ private_constant :DEFAULT_HEADER
19
+ end
20
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InfinumAppRevision
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InfinumAppRevision
4
+ module VersionProvider
5
+ class Base
6
+ def version = @version ||= Version.new(id:, metadata:)
7
+
8
+ protected
9
+
10
+ def id = 'undefined'
11
+
12
+ def metadata = {}
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'pathname'
5
+
6
+ module InfinumAppRevision
7
+ module VersionProvider
8
+ class Docker < Base
9
+ def initialize(version_file_path: DEFAULT_VERSION_FILE_PATH)
10
+ @version_file_path = Pathname.getwd.join(version_file_path)
11
+ super()
12
+ end
13
+
14
+ protected
15
+
16
+ def id
17
+ version_file_contents[:revision]
18
+ end
19
+
20
+ def metadata
21
+ version_file_contents.except(:revision)
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :version_file_path
27
+
28
+ def version_file_contents
29
+ return {} unless version_file_path.file?
30
+
31
+ JSON.parse(version_file_path.read, symbolize_names: true)
32
+ end
33
+
34
+ DEFAULT_VERSION_FILE_PATH = 'private/version.json'
35
+ private_constant :DEFAULT_VERSION_FILE_PATH
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pathname'
4
+
5
+ module InfinumAppRevision
6
+ module VersionProvider
7
+ class Mina < Base
8
+ protected
9
+
10
+ def id
11
+ mina_git_revision
12
+ end
13
+
14
+ private
15
+
16
+ def mina_git_revision
17
+ return unless mina_git_revision_path.file?
18
+
19
+ mina_git_revision_path.read.strip
20
+ end
21
+
22
+ def mina_git_revision_path
23
+ Pathname.getwd.join('.mina_git_revision')
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InfinumAppRevision
4
+ module VersionProvider
5
+ Version = Data.define(:id, :metadata) do
6
+ def initialize(id:, metadata: {}) = super(id: id.freeze, metadata: metadata.freeze)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'infinum_app_revision/version'
4
+ require_relative 'infinum_app_revision/version_provider/version'
5
+ require_relative 'infinum_app_revision/version_provider/base'
6
+ require_relative 'infinum_app_revision/version_provider/mina'
7
+ require_relative 'infinum_app_revision/version_provider/docker'
8
+ require_relative 'infinum_app_revision/middleware'
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe InfinumAppRevision::Middleware do
4
+ subject(:call) { described_class.new(app, version_provider: version_provider).call({}) }
5
+
6
+ let(:app) { ->(_env) { [200, { 'Content-Type' => 'application/json' }, ['Hello World']] } }
7
+ let(:version_provider) { InfinumAppRevision::VersionProvider::Base.new }
8
+
9
+ it 'adds the revision header to the response' do
10
+ _status, headers, _body = call
11
+ expect(headers['X-App-Revision']).to eq('undefined')
12
+ end
13
+
14
+ context 'with a custom header name' do
15
+ subject(:call) do
16
+ described_class.new(app, header: 'X-Custom-Revision-Header', version_provider: version_provider).call({})
17
+ end
18
+
19
+ it 'assigns the custom header name' do
20
+ _status, headers, _body = call
21
+ expect(headers['X-Custom-Revision-Header']).to eq('undefined')
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe InfinumAppRevision::VersionProvider::Base do
4
+ subject(:provider) { described_class.new }
5
+
6
+ describe '#version' do
7
+ it 'returns a Version instance' do
8
+ expect(provider.version).to be_a(InfinumAppRevision::VersionProvider::Version)
9
+ end
10
+
11
+ it 'returns a version with id "undefined"' do
12
+ expect(provider.version.id).to eq('undefined')
13
+ end
14
+
15
+ it 'memoizes the version' do
16
+ first_call = provider.version
17
+ second_call = provider.version
18
+ expect(first_call).to be(second_call)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe InfinumAppRevision::VersionProvider::Docker do
4
+ describe '#version' do
5
+ context 'with the default version file path' do
6
+ subject(:provider) { described_class.new }
7
+
8
+ let(:version_data) do
9
+ {
10
+ revision: 'abc123',
11
+ branch: 'main',
12
+ build_date: '2025-09-30'
13
+ }
14
+ end
15
+
16
+ before do
17
+ FileUtils.mkdir_p(Pathname.getwd.join('private'))
18
+ File.write(Pathname.getwd.join('private/version.json'), version_data.to_json)
19
+ end
20
+
21
+ after do
22
+ FileUtils.rm_rf(Pathname.getwd.join('private'))
23
+ end
24
+
25
+ it 'returns a Version instance' do
26
+ expect(provider.version).to be_a(InfinumAppRevision::VersionProvider::Version)
27
+ end
28
+
29
+ it 'extracts the revision as the version id' do
30
+ expect(provider.version.id).to eq('abc123')
31
+ end
32
+ end
33
+
34
+ context 'with custom version file path' do
35
+ subject(:provider) { described_class.new(version_file_path: version_file_path) }
36
+
37
+ let(:version_file_path) { 'spec/tmp/test_version.json' }
38
+ let(:version_data) do
39
+ {
40
+ revision: 'abc123',
41
+ branch: 'main',
42
+ build_date: '2025-09-30'
43
+ }
44
+ end
45
+
46
+ before do
47
+ File.write(Pathname.getwd.join(version_file_path), version_data.to_json)
48
+ end
49
+
50
+ after do
51
+ FileUtils.rm_f(Pathname.getwd.join(version_file_path))
52
+ end
53
+
54
+ it 'returns a Version instance' do
55
+ expect(provider.version).to be_a(InfinumAppRevision::VersionProvider::Version)
56
+ end
57
+
58
+ it 'extracts the revision as the version id' do
59
+ expect(provider.version.id).to eq('abc123')
60
+ end
61
+
62
+ it 'stores additional fields in metadata' do
63
+ expect(provider.version.metadata).to eq(branch: 'main', build_date: '2025-09-30')
64
+ end
65
+
66
+ it 'memoizes the version' do
67
+ first_call = provider.version
68
+ second_call = provider.version
69
+ expect(first_call).to be(second_call)
70
+ end
71
+ end
72
+
73
+ context 'when version file does not exist' do
74
+ subject(:provider) { described_class.new(version_file_path: version_file_path) }
75
+
76
+ let(:version_file_path) { 'spec/tmp/nonexistent_version.json' }
77
+
78
+ it 'returns a Version instance' do
79
+ expect(provider.version).to be_a(InfinumAppRevision::VersionProvider::Version)
80
+ end
81
+
82
+ it 'returns nil as the version id' do
83
+ expect(provider.version.id).to be_nil
84
+ end
85
+
86
+ it 'has empty metadata' do
87
+ expect(provider.version.metadata).to eq({})
88
+ end
89
+ end
90
+
91
+ context 'when version file only contains revision' do
92
+ subject(:provider) { described_class.new(version_file_path: version_file_path) }
93
+
94
+ let(:version_file_path) { 'spec/tmp/test_version.json' }
95
+ let(:version_data) { { revision: 'xyz789' } }
96
+
97
+ before do
98
+ File.write(Pathname.getwd.join(version_file_path), version_data.to_json)
99
+ end
100
+
101
+ after do
102
+ FileUtils.rm_f(Pathname.getwd.join(version_file_path))
103
+ end
104
+
105
+ it 'extracts the revision as the version id' do
106
+ expect(provider.version.id).to eq('xyz789')
107
+ end
108
+
109
+ it 'has empty metadata' do
110
+ expect(provider.version.metadata).to eq({})
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe InfinumAppRevision::VersionProvider::Mina do
4
+ subject(:provider) { described_class.new }
5
+
6
+ let(:mina_file_path) { Pathname.getwd.join('.mina_git_revision') }
7
+
8
+ describe '#version' do
9
+ context 'when .mina_git_revision file exists' do
10
+ before do
11
+ File.write(mina_file_path, "abc123def456\n")
12
+ end
13
+
14
+ after do
15
+ FileUtils.rm_f(mina_file_path)
16
+ end
17
+
18
+ it 'returns a Version instance' do
19
+ expect(provider.version).to be_a(InfinumAppRevision::VersionProvider::Version)
20
+ end
21
+
22
+ it 'extracts the git revision as the version id' do
23
+ expect(provider.version.id).to eq('abc123def456')
24
+ end
25
+
26
+ it 'memoizes the version' do
27
+ first_call = provider.version
28
+ second_call = provider.version
29
+ expect(first_call).to be(second_call)
30
+ end
31
+ end
32
+
33
+ context 'when .mina_git_revision file does not exist' do
34
+ before do
35
+ FileUtils.rm_f(mina_file_path)
36
+ end
37
+
38
+ it 'returns a Version instance' do
39
+ expect(provider.version).to be_a(InfinumAppRevision::VersionProvider::Version)
40
+ end
41
+
42
+ it 'returns nil as the version id' do
43
+ expect(provider.version.id).to be_nil
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe InfinumAppRevision::VersionProvider::Version do
4
+ describe '#initialize' do
5
+ it 'sets the id' do
6
+ version = described_class.new(id: 'abc123')
7
+ expect(version.id).to eq('abc123')
8
+ end
9
+
10
+ it 'sets the metadata' do
11
+ metadata = { branch: 'main', build_date: '2025-09-30' }
12
+ version = described_class.new(id: 'abc123', metadata: metadata)
13
+ expect(version.metadata).to eq(metadata)
14
+ end
15
+
16
+ it 'defaults metadata to an empty hash' do
17
+ version = described_class.new(id: 'abc123')
18
+ expect(version.metadata).to eq({})
19
+ end
20
+
21
+ it 'freezes the id' do
22
+ version = described_class.new(id: 'abc123')
23
+ expect(version.id).to be_frozen
24
+ end
25
+
26
+ it 'freezes the metadata' do
27
+ metadata = { branch: 'main' }
28
+ version = described_class.new(id: 'abc123', metadata: metadata)
29
+ expect(version.metadata).to be_frozen
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'simplecov'
4
+ require 'infinum_app_revision'
5
+
6
+ RSpec.configure do |config|
7
+ # Enable flags like --only-failures and --next-failure
8
+ config.example_status_persistence_file_path = '.rspec_status'
9
+
10
+ # Disable RSpec exposing methods globally on `Module` and `main`
11
+ config.disable_monkey_patching!
12
+
13
+ config.expect_with :rspec do |c|
14
+ c.syntax = :expect
15
+ end
16
+ end
data/spec/tmp/.keep ADDED
File without changes
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: infinum_app_revision
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Team Backend @ Infinum
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: json
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: rack
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '2.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '2.0'
40
+ description: Simple middleware for reporting back deployed app revisions.
41
+ email:
42
+ - team.backend@infinum.com
43
+ executables: []
44
+ extensions: []
45
+ extra_rdoc_files: []
46
+ files:
47
+ - ".github/workflows/test.yml"
48
+ - ".gitignore"
49
+ - ".overcommit.yml"
50
+ - ".rspec"
51
+ - ".rubocop.yml"
52
+ - ".ruby-version"
53
+ - CHANGELOG.md
54
+ - Gemfile
55
+ - Gemfile.lock
56
+ - README.md
57
+ - Rakefile
58
+ - bin/console
59
+ - bin/setup
60
+ - infinum_app_revision.gemspec
61
+ - lib/infinum_app_revision.rb
62
+ - lib/infinum_app_revision/middleware.rb
63
+ - lib/infinum_app_revision/version.rb
64
+ - lib/infinum_app_revision/version_provider/base.rb
65
+ - lib/infinum_app_revision/version_provider/docker.rb
66
+ - lib/infinum_app_revision/version_provider/mina.rb
67
+ - lib/infinum_app_revision/version_provider/version.rb
68
+ - spec/infinum_app_revision/middleware_spec.rb
69
+ - spec/infinum_app_revision/version_provider/base_spec.rb
70
+ - spec/infinum_app_revision/version_provider/docker_spec.rb
71
+ - spec/infinum_app_revision/version_provider/mina_spec.rb
72
+ - spec/infinum_app_revision/version_provider/version_spec.rb
73
+ - spec/spec_helper.rb
74
+ - spec/tmp/.keep
75
+ homepage: https://github.com/infinum/rails-infinum-app-revision
76
+ licenses:
77
+ - MIT
78
+ metadata:
79
+ rubygems_mfa_required: 'true'
80
+ homepage_uri: https://github.com/infinum/rails-infinum-app-revision
81
+ rdoc_options: []
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '3.2'
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubygems_version: 3.6.9
96
+ specification_version: 4
97
+ summary: Infinum App Revision
98
+ test_files: []