orfeas_lyra 0.6.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/CHANGELOG.md +222 -0
- data/LICENSE +21 -0
- data/README.md +1165 -0
- data/Rakefile +728 -0
- data/app/controllers/lyra/application_controller.rb +23 -0
- data/app/controllers/lyra/dashboard_controller.rb +624 -0
- data/app/controllers/lyra/flow_controller.rb +224 -0
- data/app/controllers/lyra/privacy_controller.rb +182 -0
- data/app/views/lyra/dashboard/audit_trail.html.erb +324 -0
- data/app/views/lyra/dashboard/discrepancies.html.erb +125 -0
- data/app/views/lyra/dashboard/event_graph_view.html.erb +525 -0
- data/app/views/lyra/dashboard/heatmap_view.html.erb +155 -0
- data/app/views/lyra/dashboard/index.html.erb +119 -0
- data/app/views/lyra/dashboard/model_overview.html.erb +115 -0
- data/app/views/lyra/dashboard/projections.html.erb +302 -0
- data/app/views/lyra/dashboard/schema.html.erb +283 -0
- data/app/views/lyra/dashboard/schema_history.html.erb +78 -0
- data/app/views/lyra/dashboard/schema_version.html.erb +340 -0
- data/app/views/lyra/dashboard/verification.html.erb +370 -0
- data/app/views/lyra/flow/crud_mapping.html.erb +125 -0
- data/app/views/lyra/flow/timeline.html.erb +260 -0
- data/app/views/lyra/privacy/pii_detection.html.erb +148 -0
- data/app/views/lyra/privacy/policy.html.erb +188 -0
- data/app/workflows/es_async_mode_workflow.rb +80 -0
- data/app/workflows/es_sync_mode_workflow.rb +64 -0
- data/app/workflows/hijack_mode_workflow.rb +54 -0
- data/app/workflows/lifecycle_workflow.rb +43 -0
- data/app/workflows/monitor_mode_workflow.rb +39 -0
- data/config/privacy_policies.rb +273 -0
- data/config/routes.rb +48 -0
- data/lib/lyra/aggregate.rb +131 -0
- data/lib/lyra/associations/event_aware.rb +225 -0
- data/lib/lyra/command.rb +81 -0
- data/lib/lyra/command_handler.rb +155 -0
- data/lib/lyra/configuration.rb +124 -0
- data/lib/lyra/consistency/read_your_writes.rb +91 -0
- data/lib/lyra/correlation.rb +144 -0
- data/lib/lyra/dual_view.rb +231 -0
- data/lib/lyra/engine.rb +67 -0
- data/lib/lyra/event.rb +71 -0
- data/lib/lyra/event_analyzer.rb +135 -0
- data/lib/lyra/event_flow.rb +449 -0
- data/lib/lyra/event_mapper.rb +106 -0
- data/lib/lyra/event_store_adapter.rb +72 -0
- data/lib/lyra/id_generator.rb +137 -0
- data/lib/lyra/interceptors/association_interceptor.rb +169 -0
- data/lib/lyra/interceptors/crud_interceptor.rb +543 -0
- data/lib/lyra/privacy/gdpr_compliance.rb +161 -0
- data/lib/lyra/privacy/pii_detector.rb +85 -0
- data/lib/lyra/privacy/pii_masker.rb +66 -0
- data/lib/lyra/privacy/policy_integration.rb +253 -0
- data/lib/lyra/projection.rb +94 -0
- data/lib/lyra/projections/async_projection_job.rb +63 -0
- data/lib/lyra/projections/cached_projection.rb +322 -0
- data/lib/lyra/projections/cached_relation.rb +757 -0
- data/lib/lyra/projections/event_store_reader.rb +127 -0
- data/lib/lyra/projections/model_projection.rb +143 -0
- data/lib/lyra/schema/diff.rb +331 -0
- data/lib/lyra/schema/event_class_registrar.rb +63 -0
- data/lib/lyra/schema/generator.rb +190 -0
- data/lib/lyra/schema/reporter.rb +188 -0
- data/lib/lyra/schema/store.rb +156 -0
- data/lib/lyra/schema/validator.rb +100 -0
- data/lib/lyra/strict_data_access.rb +363 -0
- data/lib/lyra/verification/crud_lifecycle_workflow.rb +456 -0
- data/lib/lyra/verification/workflow_generator.rb +540 -0
- data/lib/lyra/version.rb +3 -0
- data/lib/lyra/visualization/activity_heatmap.rb +215 -0
- data/lib/lyra/visualization/event_graph.rb +310 -0
- data/lib/lyra/visualization/timeline.rb +398 -0
- data/lib/lyra.rb +150 -0
- data/lib/tasks/dist.rake +391 -0
- data/lib/tasks/gems.rake +185 -0
- data/lib/tasks/lyra_schema.rake +231 -0
- data/lib/tasks/lyra_workflows.rake +452 -0
- data/lib/tasks/public_release.rake +351 -0
- data/lib/tasks/stats.rake +175 -0
- data/lib/tasks/testbed.rake +479 -0
- data/lib/tasks/version.rake +159 -0
- metadata +221 -0
data/lib/tasks/dist.rake
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :lyra do
|
|
4
|
+
desc "Create distribution zip for open science evaluation"
|
|
5
|
+
task :dist do
|
|
6
|
+
require "fileutils"
|
|
7
|
+
require "date"
|
|
8
|
+
|
|
9
|
+
# Read version from Lyra version file
|
|
10
|
+
version = extract_lyra_version
|
|
11
|
+
date_stamp = Date.today.strftime("%Y%m%d")
|
|
12
|
+
dist_name = "lyra-orfeas-v#{version}-#{date_stamp}"
|
|
13
|
+
dist_dir = "dist/#{dist_name}"
|
|
14
|
+
zip_file = "dist/#{dist_name}.zip"
|
|
15
|
+
|
|
16
|
+
puts "\n" + "=" * 70
|
|
17
|
+
puts "Creating Lyra/ORFEAS Distribution Package"
|
|
18
|
+
puts "=" * 70
|
|
19
|
+
puts "Version: #{version}"
|
|
20
|
+
puts "Output: #{zip_file}"
|
|
21
|
+
puts "=" * 70
|
|
22
|
+
|
|
23
|
+
# Clean previous builds
|
|
24
|
+
FileUtils.rm_rf("dist")
|
|
25
|
+
FileUtils.mkdir_p(dist_dir)
|
|
26
|
+
|
|
27
|
+
# Define what to include
|
|
28
|
+
includes = [
|
|
29
|
+
# Core framework
|
|
30
|
+
"lib",
|
|
31
|
+
"app",
|
|
32
|
+
"config",
|
|
33
|
+
"db",
|
|
34
|
+
|
|
35
|
+
# Gems
|
|
36
|
+
"gems/petri_flow",
|
|
37
|
+
"gems/pam_dsl",
|
|
38
|
+
|
|
39
|
+
# Tests
|
|
40
|
+
"test",
|
|
41
|
+
|
|
42
|
+
# Examples (excluding aegean_epay_testbed which is large and has sensitive config)
|
|
43
|
+
"examples/blog_app",
|
|
44
|
+
"examples/privacy_examples.rb",
|
|
45
|
+
|
|
46
|
+
# Documentation (markdown files only, not Jekyll site)
|
|
47
|
+
"docs",
|
|
48
|
+
|
|
49
|
+
# Root files
|
|
50
|
+
"Gemfile",
|
|
51
|
+
"Gemfile.lock",
|
|
52
|
+
"lyra.gemspec",
|
|
53
|
+
"Rakefile",
|
|
54
|
+
"docker-compose.yml",
|
|
55
|
+
"README.md",
|
|
56
|
+
"LICENSE",
|
|
57
|
+
"docs/ARCHITECTURE.md",
|
|
58
|
+
"docs/GETTING_STARTED.md",
|
|
59
|
+
"docs/MONOREPO.md",
|
|
60
|
+
"CHANGELOG.md"
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
# Define exclusions (patterns)
|
|
64
|
+
exclusions = [
|
|
65
|
+
# Dependency directories
|
|
66
|
+
"**/vendor/**",
|
|
67
|
+
"**/.bundle/**",
|
|
68
|
+
"**/node_modules/**",
|
|
69
|
+
|
|
70
|
+
# Git
|
|
71
|
+
"**/.git/**",
|
|
72
|
+
|
|
73
|
+
# Generated/temp files
|
|
74
|
+
"**/tmp/**",
|
|
75
|
+
"**/log/**",
|
|
76
|
+
"**/coverage/**",
|
|
77
|
+
"**/_site/**",
|
|
78
|
+
"**/.jekyll-cache/**",
|
|
79
|
+
"**/.sass-cache/**",
|
|
80
|
+
|
|
81
|
+
# Database files
|
|
82
|
+
"**/*.sqlite3",
|
|
83
|
+
"**/*.sqlite3-*",
|
|
84
|
+
|
|
85
|
+
# Log files
|
|
86
|
+
"**/*.log",
|
|
87
|
+
|
|
88
|
+
# OS files
|
|
89
|
+
"**/.DS_Store",
|
|
90
|
+
|
|
91
|
+
# Editor/debug files
|
|
92
|
+
"**/.byebug_history",
|
|
93
|
+
"**/.ruby-version",
|
|
94
|
+
|
|
95
|
+
# Test outputs
|
|
96
|
+
"**/test/dummy/tmp/**",
|
|
97
|
+
"**/test/dummy/log/**",
|
|
98
|
+
"**/test/reports/**",
|
|
99
|
+
"**/test_results/**",
|
|
100
|
+
"**/examples/**/tmp/**",
|
|
101
|
+
"**/examples/**/log/**",
|
|
102
|
+
"**/examples/**/reports/**",
|
|
103
|
+
|
|
104
|
+
# Sensitive/internal directories
|
|
105
|
+
"**/webbank_guide/**",
|
|
106
|
+
"**/research/papers/**",
|
|
107
|
+
"**/images/programs/**",
|
|
108
|
+
"proposal/**",
|
|
109
|
+
"thesis/**",
|
|
110
|
+
"paper/**",
|
|
111
|
+
"papertse/**"
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
puts "\nCopying files..."
|
|
115
|
+
|
|
116
|
+
includes.each do |item|
|
|
117
|
+
next unless File.exist?(item)
|
|
118
|
+
|
|
119
|
+
dest = "#{dist_dir}/#{item}"
|
|
120
|
+
|
|
121
|
+
if File.directory?(item)
|
|
122
|
+
copy_directory(item, dest, exclusions)
|
|
123
|
+
else
|
|
124
|
+
FileUtils.mkdir_p(File.dirname(dest))
|
|
125
|
+
FileUtils.cp(item, dest)
|
|
126
|
+
puts " + #{item}"
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Generate MANIFEST.txt
|
|
131
|
+
puts "\nGenerating MANIFEST.txt..."
|
|
132
|
+
generate_manifest(dist_dir)
|
|
133
|
+
|
|
134
|
+
# Generate INSTALL.md
|
|
135
|
+
File.write("#{dist_dir}/INSTALL.md", <<~INSTALL)
|
|
136
|
+
# Lyra/ORFEAS Installation Guide
|
|
137
|
+
|
|
138
|
+
## Prerequisites
|
|
139
|
+
|
|
140
|
+
- Ruby 4.0+
|
|
141
|
+
- Rails 8.0+
|
|
142
|
+
- Bundler
|
|
143
|
+
- PostgreSQL 14+ (required for event sourcing features)
|
|
144
|
+
|
|
145
|
+
## Quick Start
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# Install dependencies
|
|
149
|
+
bundle install
|
|
150
|
+
|
|
151
|
+
# Start PostgreSQL (via Docker)
|
|
152
|
+
rake docker:start
|
|
153
|
+
|
|
154
|
+
# Run Lyra core tests
|
|
155
|
+
bundle exec rake test
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Running Tests
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Lyra core tests only
|
|
162
|
+
bundle exec rake test
|
|
163
|
+
|
|
164
|
+
# All component tests (Lyra + PetriFlow + PAM DSL)
|
|
165
|
+
bundle exec rake test:all
|
|
166
|
+
|
|
167
|
+
# Unit tests only (excludes controller tests)
|
|
168
|
+
bundle exec rake test:unit
|
|
169
|
+
|
|
170
|
+
# Controller tests only (requires Rails dummy app)
|
|
171
|
+
bundle exec rake test:controllers
|
|
172
|
+
|
|
173
|
+
# Individual gem tests
|
|
174
|
+
cd gems/petri_flow && bundle exec rake test
|
|
175
|
+
cd gems/pam_dsl && bundle exec rake test
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Running Example Application
|
|
179
|
+
|
|
180
|
+
### Blog App (Simple Example)
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
cd examples/blog_app
|
|
184
|
+
bundle install
|
|
185
|
+
rails db:create db:migrate db:seed
|
|
186
|
+
rails console
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Documentation
|
|
190
|
+
|
|
191
|
+
Documentation is available in the `docs/` directory as Markdown files:
|
|
192
|
+
|
|
193
|
+
- `docs/API_REFERENCE.md` - API documentation
|
|
194
|
+
- `gems/petri_flow/docs/PETRIFLOW_EXPORT.md` - PetriFlow export formats
|
|
195
|
+
- `docs/PRIVACY_COMPLIANCE_VALIDATION.md` - Privacy compliance
|
|
196
|
+
|
|
197
|
+
## Gem Dependencies
|
|
198
|
+
|
|
199
|
+
If you need to rebuild gem dependencies:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
# Main project
|
|
203
|
+
bundle install
|
|
204
|
+
|
|
205
|
+
# PetriFlow gem
|
|
206
|
+
cd gems/petri_flow && bundle install
|
|
207
|
+
|
|
208
|
+
# PAM DSL gem
|
|
209
|
+
cd gems/pam_dsl && bundle install
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## PostgreSQL Setup
|
|
213
|
+
|
|
214
|
+
The project includes a Docker Compose file for PostgreSQL:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
# Start PostgreSQL container (port 5433)
|
|
218
|
+
rake docker:start
|
|
219
|
+
|
|
220
|
+
# Check status
|
|
221
|
+
rake docker:status
|
|
222
|
+
|
|
223
|
+
# Stop container
|
|
224
|
+
rake docker:stop
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Or install PostgreSQL natively and configure `config/database.yml`.
|
|
228
|
+
|
|
229
|
+
## Troubleshooting
|
|
230
|
+
|
|
231
|
+
### Native extension errors
|
|
232
|
+
Some gems require native extensions. On macOS:
|
|
233
|
+
```bash
|
|
234
|
+
xcode-select --install
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### PostgreSQL connection errors
|
|
238
|
+
Ensure PostgreSQL is running on port 5433 (Docker) or 5432 (native).
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
MIT License - see LICENSE file.
|
|
243
|
+
INSTALL
|
|
244
|
+
puts " + INSTALL.md"
|
|
245
|
+
|
|
246
|
+
# Generate VERSION.txt
|
|
247
|
+
File.write("#{dist_dir}/VERSION.txt", <<~VERSION)
|
|
248
|
+
Lyra/ORFEAS Framework
|
|
249
|
+
Version: #{version}
|
|
250
|
+
Date: #{Date.today}
|
|
251
|
+
|
|
252
|
+
CRUD to Event Sourcing Transformation Engine
|
|
253
|
+
Part of the ORFEAS (Object-Relational to Event-Sourcing Architecture) Framework
|
|
254
|
+
|
|
255
|
+
Author: Michail Pantelelis (mpantel@aegean.gr)
|
|
256
|
+
Institution: University of the Aegean
|
|
257
|
+
|
|
258
|
+
License: MIT
|
|
259
|
+
VERSION
|
|
260
|
+
puts " + VERSION.txt"
|
|
261
|
+
|
|
262
|
+
# Create zip
|
|
263
|
+
puts "\nCreating zip archive..."
|
|
264
|
+
Dir.chdir("dist") do
|
|
265
|
+
system("zip -rq #{dist_name}.zip #{dist_name}")
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Calculate size
|
|
269
|
+
zip_size = File.size(zip_file)
|
|
270
|
+
zip_size_mb = (zip_size / 1024.0 / 1024.0).round(2)
|
|
271
|
+
|
|
272
|
+
# Count files
|
|
273
|
+
file_count = Dir.glob("#{dist_dir}/**/*", File::FNM_DOTMATCH).count { |f| File.file?(f) }
|
|
274
|
+
|
|
275
|
+
puts "\n" + "=" * 70
|
|
276
|
+
puts "Distribution Package Created Successfully"
|
|
277
|
+
puts "=" * 70
|
|
278
|
+
puts "Output: #{zip_file}"
|
|
279
|
+
puts "Size: #{zip_size_mb} MB"
|
|
280
|
+
puts "Files: #{file_count}"
|
|
281
|
+
puts "=" * 70
|
|
282
|
+
puts "\nTo extract: unzip #{zip_file}"
|
|
283
|
+
puts "=" * 70 + "\n\n"
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
desc "List contents of distribution (dry run)"
|
|
287
|
+
task :dist_list do
|
|
288
|
+
includes = %w[lib app config db gems/petri_flow gems/pam_dsl test examples/blog_app docs]
|
|
289
|
+
|
|
290
|
+
exclusions = %w[vendor .bundle .git node_modules tmp log coverage _site .jekyll-cache reports]
|
|
291
|
+
|
|
292
|
+
puts "\n" + "=" * 70
|
|
293
|
+
puts "Distribution Contents (Dry Run)"
|
|
294
|
+
puts "=" * 70
|
|
295
|
+
|
|
296
|
+
total_files = 0
|
|
297
|
+
total_size = 0
|
|
298
|
+
|
|
299
|
+
includes.each do |dir|
|
|
300
|
+
next unless Dir.exist?(dir)
|
|
301
|
+
|
|
302
|
+
files = Dir.glob("#{dir}/**/*").select do |f|
|
|
303
|
+
File.file?(f) && exclusions.none? { |ex| f.include?("/#{ex}/") }
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
size = files.sum { |f| File.size(f) }
|
|
307
|
+
total_files += files.count
|
|
308
|
+
total_size += size
|
|
309
|
+
|
|
310
|
+
puts "%-30s %6d files %8.2f MB" % [dir, files.count, size / 1024.0 / 1024.0]
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
puts "-" * 70
|
|
314
|
+
puts "%-30s %6d files %8.2f MB" % ["TOTAL", total_files, total_size / 1024.0 / 1024.0]
|
|
315
|
+
puts "=" * 70 + "\n\n"
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
private
|
|
319
|
+
|
|
320
|
+
def extract_lyra_version
|
|
321
|
+
version_file = "lib/lyra/version.rb"
|
|
322
|
+
return "0.0.0" unless File.exist?(version_file)
|
|
323
|
+
|
|
324
|
+
content = File.read(version_file)
|
|
325
|
+
match = content.match(/VERSION\s*=\s*["']([^"']+)["']/)
|
|
326
|
+
match ? match[1] : "0.0.0"
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def copy_directory(src, dest, exclusions)
|
|
330
|
+
Dir.glob("#{src}/**/*", File::FNM_DOTMATCH).each do |file|
|
|
331
|
+
next if File.directory?(file)
|
|
332
|
+
next if file.end_with?("/.", "/..")
|
|
333
|
+
|
|
334
|
+
# Check exclusions - match against full path and path segments
|
|
335
|
+
excluded = exclusions.any? do |pattern|
|
|
336
|
+
File.fnmatch?(pattern, file, File::FNM_PATHNAME | File::FNM_DOTMATCH) ||
|
|
337
|
+
file.include?("/_site/") ||
|
|
338
|
+
file.include?("/vendor/") ||
|
|
339
|
+
file.include?("/.bundle/") ||
|
|
340
|
+
file.include?("/node_modules/") ||
|
|
341
|
+
file.include?("/tmp/") ||
|
|
342
|
+
file.include?("/log/") ||
|
|
343
|
+
file.include?("/coverage/") ||
|
|
344
|
+
file.include?("/.git/") ||
|
|
345
|
+
file.include?("/.jekyll-cache/") ||
|
|
346
|
+
file.include?("/.sass-cache/") ||
|
|
347
|
+
file.include?("/test/reports/") ||
|
|
348
|
+
file.include?("/test_results/") ||
|
|
349
|
+
file.include?("/reports/") ||
|
|
350
|
+
file.include?("/webbank_guide/") ||
|
|
351
|
+
file.include?("/research/papers/") ||
|
|
352
|
+
file.include?("/images/programs/") ||
|
|
353
|
+
file.start_with?("proposal/") ||
|
|
354
|
+
file.start_with?("thesis/") ||
|
|
355
|
+
file.start_with?("paper/") ||
|
|
356
|
+
file.start_with?("papertse/") ||
|
|
357
|
+
file.end_with?(".sqlite3") ||
|
|
358
|
+
file.end_with?(".log")
|
|
359
|
+
end
|
|
360
|
+
next if excluded
|
|
361
|
+
|
|
362
|
+
relative = file.sub("#{src}/", "")
|
|
363
|
+
dest_file = "#{dest}/#{relative}"
|
|
364
|
+
|
|
365
|
+
FileUtils.mkdir_p(File.dirname(dest_file))
|
|
366
|
+
FileUtils.cp(file, dest_file)
|
|
367
|
+
end
|
|
368
|
+
puts " + #{src}/"
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def generate_manifest(dist_dir)
|
|
372
|
+
files = Dir.glob("#{dist_dir}/**/*", File::FNM_DOTMATCH)
|
|
373
|
+
.select { |f| File.file?(f) }
|
|
374
|
+
.map { |f| f.sub("#{dist_dir}/", "") }
|
|
375
|
+
.sort
|
|
376
|
+
|
|
377
|
+
manifest_content = <<~HEADER
|
|
378
|
+
LYRA/ORFEAS DISTRIBUTION MANIFEST
|
|
379
|
+
==================================
|
|
380
|
+
Generated: #{Time.now}
|
|
381
|
+
Total Files: #{files.count}
|
|
382
|
+
|
|
383
|
+
FILES:
|
|
384
|
+
------
|
|
385
|
+
HEADER
|
|
386
|
+
|
|
387
|
+
manifest_content += files.join("\n")
|
|
388
|
+
|
|
389
|
+
File.write("#{dist_dir}/MANIFEST.txt", manifest_content)
|
|
390
|
+
end
|
|
391
|
+
end
|
data/lib/tasks/gems.rake
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Rake tasks for publishing gems to RubyGems
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# rake gems:build # Build all gems
|
|
7
|
+
# rake gems:build:petri_flow # Build petri_flow gem
|
|
8
|
+
# rake gems:build:pam_dsl # Build pam_dsl gem
|
|
9
|
+
# rake gems:push # Push all gems to RubyGems
|
|
10
|
+
# rake gems:push:petri_flow # Push petri_flow to RubyGems
|
|
11
|
+
# rake gems:push:pam_dsl # Push pam_dsl to RubyGems
|
|
12
|
+
# rake gems:release # Build and push all gems
|
|
13
|
+
# rake gems:version # Show gem versions
|
|
14
|
+
|
|
15
|
+
require "fileutils"
|
|
16
|
+
|
|
17
|
+
namespace :gems do
|
|
18
|
+
GEMS = {
|
|
19
|
+
orfeas_lyra: {
|
|
20
|
+
path: ".",
|
|
21
|
+
gemspec: "lyra.gemspec"
|
|
22
|
+
},
|
|
23
|
+
orfeas_petri_flow: {
|
|
24
|
+
path: "gems/petri_flow",
|
|
25
|
+
gemspec: "petri_flow.gemspec"
|
|
26
|
+
},
|
|
27
|
+
orfeas_pam_dsl: {
|
|
28
|
+
path: "gems/pam_dsl",
|
|
29
|
+
gemspec: "pam_dsl.gemspec"
|
|
30
|
+
}
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
33
|
+
desc "Show gem versions"
|
|
34
|
+
task :version do
|
|
35
|
+
puts "Gem versions:"
|
|
36
|
+
puts "-" * 40
|
|
37
|
+
GEMS.each do |name, config|
|
|
38
|
+
version = gem_version(config[:path])
|
|
39
|
+
puts " #{name}: #{version}"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
desc "Build all gems"
|
|
44
|
+
task :build do
|
|
45
|
+
GEMS.each_key { |name| Rake::Task["gems:build:#{name}"].invoke }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
desc "Push all gems to RubyGems"
|
|
49
|
+
task :push do
|
|
50
|
+
GEMS.each_key { |name| Rake::Task["gems:push:#{name}"].invoke }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
desc "Release all gems (build + push)"
|
|
54
|
+
task :release => [:build, :push]
|
|
55
|
+
|
|
56
|
+
desc "Clean built gems"
|
|
57
|
+
task :clean do
|
|
58
|
+
GEMS.each do |name, config|
|
|
59
|
+
Dir.glob("#{config[:path]}/*.gem").each do |gem_file|
|
|
60
|
+
FileUtils.rm(gem_file)
|
|
61
|
+
puts "Removed #{gem_file}"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
namespace :build do
|
|
67
|
+
GEMS.each do |name, config|
|
|
68
|
+
desc "Build #{name} gem"
|
|
69
|
+
task name do
|
|
70
|
+
puts "Building #{name}..."
|
|
71
|
+
Dir.chdir(config[:path]) do
|
|
72
|
+
# Clean old gem files
|
|
73
|
+
Dir.glob("*.gem").each { |f| FileUtils.rm(f) }
|
|
74
|
+
|
|
75
|
+
# Build gem
|
|
76
|
+
result = system("gem build #{config[:gemspec]}")
|
|
77
|
+
raise "Failed to build #{name}" unless result
|
|
78
|
+
|
|
79
|
+
gem_file = Dir.glob("*.gem").first
|
|
80
|
+
puts " Built: #{gem_file}"
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
namespace :push do
|
|
87
|
+
GEMS.each do |name, config|
|
|
88
|
+
desc "Push #{name} to RubyGems"
|
|
89
|
+
task name do
|
|
90
|
+
Dir.chdir(config[:path]) do
|
|
91
|
+
gem_file = Dir.glob("*.gem").first
|
|
92
|
+
|
|
93
|
+
unless gem_file
|
|
94
|
+
puts "No gem file found for #{name}. Run 'rake gems:build:#{name}' first."
|
|
95
|
+
next
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
puts "Pushing #{gem_file} to RubyGems..."
|
|
99
|
+
result = system("gem push #{gem_file}")
|
|
100
|
+
raise "Failed to push #{name}" unless result
|
|
101
|
+
|
|
102
|
+
puts " Published #{name} to RubyGems"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
namespace :install do
|
|
109
|
+
GEMS.each do |name, config|
|
|
110
|
+
desc "Install #{name} gem locally"
|
|
111
|
+
task name => "gems:build:#{name}" do
|
|
112
|
+
Dir.chdir(config[:path]) do
|
|
113
|
+
gem_file = Dir.glob("*.gem").first
|
|
114
|
+
system("gem install #{gem_file}")
|
|
115
|
+
puts " Installed #{name} locally"
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
namespace :bump do
|
|
122
|
+
%w[major minor patch].each do |level|
|
|
123
|
+
desc "Bump #{level} version for all gems"
|
|
124
|
+
task level do
|
|
125
|
+
GEMS.each do |name, config|
|
|
126
|
+
bump_version(config[:path], level)
|
|
127
|
+
puts "Bumped #{name} #{level} version"
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
GEMS.each do |name, config|
|
|
133
|
+
namespace name do
|
|
134
|
+
%w[major minor patch].each do |level|
|
|
135
|
+
desc "Bump #{name} #{level} version"
|
|
136
|
+
task level do
|
|
137
|
+
bump_version(config[:path], level)
|
|
138
|
+
new_version = gem_version(config[:path])
|
|
139
|
+
puts "Bumped #{name} to #{new_version}"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Helper methods
|
|
147
|
+
|
|
148
|
+
def gem_version(path)
|
|
149
|
+
version_file = Dir.glob("#{path}/lib/**/version.rb").first
|
|
150
|
+
return "unknown" unless version_file && File.exist?(version_file)
|
|
151
|
+
|
|
152
|
+
content = File.read(version_file)
|
|
153
|
+
if content =~ /VERSION\s*=\s*["']([^"']+)["']/
|
|
154
|
+
$1
|
|
155
|
+
else
|
|
156
|
+
"unknown"
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def bump_version(path, level)
|
|
161
|
+
version_file = Dir.glob("#{path}/lib/**/version.rb").first
|
|
162
|
+
return unless version_file && File.exist?(version_file)
|
|
163
|
+
|
|
164
|
+
content = File.read(version_file)
|
|
165
|
+
if content =~ /VERSION\s*=\s*["'](\d+)\.(\d+)\.(\d+)["']/
|
|
166
|
+
major, minor, patch = $1.to_i, $2.to_i, $3.to_i
|
|
167
|
+
|
|
168
|
+
case level
|
|
169
|
+
when "major"
|
|
170
|
+
major += 1
|
|
171
|
+
minor = 0
|
|
172
|
+
patch = 0
|
|
173
|
+
when "minor"
|
|
174
|
+
minor += 1
|
|
175
|
+
patch = 0
|
|
176
|
+
when "patch"
|
|
177
|
+
patch += 1
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
new_version = "#{major}.#{minor}.#{patch}"
|
|
181
|
+
new_content = content.gsub(/VERSION\s*=\s*["'][^"']+["']/, "VERSION = \"#{new_version}\"")
|
|
182
|
+
File.write(version_file, new_content)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|