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 +7 -0
- data/.github/workflows/test.yml +21 -0
- data/.gitignore +14 -0
- data/.overcommit.yml +26 -0
- data/.rspec +3 -0
- data/.rubocop.yml +23 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +150 -0
- data/README.md +107 -0
- data/Rakefile +3 -0
- data/bin/console +8 -0
- data/bin/setup +8 -0
- data/infinum_app_revision.gemspec +21 -0
- data/lib/infinum_app_revision/middleware.rb +20 -0
- data/lib/infinum_app_revision/version.rb +5 -0
- data/lib/infinum_app_revision/version_provider/base.rb +15 -0
- data/lib/infinum_app_revision/version_provider/docker.rb +38 -0
- data/lib/infinum_app_revision/version_provider/mina.rb +27 -0
- data/lib/infinum_app_revision/version_provider/version.rb +9 -0
- data/lib/infinum_app_revision.rb +8 -0
- data/spec/infinum_app_revision/middleware_spec.rb +24 -0
- data/spec/infinum_app_revision/version_provider/base_spec.rb +21 -0
- data/spec/infinum_app_revision/version_provider/docker_spec.rb +114 -0
- data/spec/infinum_app_revision/version_provider/mina_spec.rb +47 -0
- data/spec/infinum_app_revision/version_provider/version_spec.rb +32 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/tmp/.keep +0 -0
- metadata +98 -0
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
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
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
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
data/bin/console
ADDED
data/bin/setup
ADDED
|
@@ -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,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,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
|
data/spec/spec_helper.rb
ADDED
|
@@ -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: []
|