dagger_ruby 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/CHANGELOG.md +43 -0
- data/LICENSE.txt +21 -0
- data/README.md +319 -0
- data/dagger_ruby.gemspec +43 -0
- data/lib/dagger_ruby/cache_volume.rb +27 -0
- data/lib/dagger_ruby/client.rb +165 -0
- data/lib/dagger_ruby/config.rb +13 -0
- data/lib/dagger_ruby/container.rb +392 -0
- data/lib/dagger_ruby/dagger_object.rb +93 -0
- data/lib/dagger_ruby/directory.rb +166 -0
- data/lib/dagger_ruby/errors.rb +9 -0
- data/lib/dagger_ruby/file.rb +89 -0
- data/lib/dagger_ruby/git_repository.rb +88 -0
- data/lib/dagger_ruby/host.rb +60 -0
- data/lib/dagger_ruby/query_builder.rb +124 -0
- data/lib/dagger_ruby/secret.rb +38 -0
- data/lib/dagger_ruby/service.rb +113 -0
- data/lib/dagger_ruby/version.rb +5 -0
- data/lib/dagger_ruby.rb +42 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: dfc23973d2dde6e9c8843fc21857992abacd569144f24cc12f5242ce45535c58
|
4
|
+
data.tar.gz: d3bee65d4fea6d9c273a8b35d2b0522184498db206a42c60f1da550fd8f74770
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: '0854808f4c8af428eefd82c5fabcf6ac882e88bedd74103c3e34b653dd0c4b8f8f7282f82aadd012c8e0fa60f35a41a2d588ecdf23c3a877323964ae1592c505'
|
7
|
+
data.tar.gz: 9b8220aa64717475766209d52eff04fb9c5ee134cb343d8f5869e4654d1d41165884768593aa22a827aef958a085e422f2818557b59a8a6a670de5b9a84e1e22
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [0.1.0] - 2024-12-19
|
9
|
+
|
10
|
+
### Added
|
11
|
+
- Complete Dagger Ruby SDK with full API coverage
|
12
|
+
- Smart connection handling that auto-detects Dagger sessions
|
13
|
+
- Container operations (from, with_exec, with_directory, with_mounted_cache, etc.)
|
14
|
+
- Directory and file operations with proper GraphQL query generation
|
15
|
+
- Cache volume management for build optimization
|
16
|
+
- Secret management and mounting
|
17
|
+
- HTTP GraphQL client with session token authentication
|
18
|
+
- Lazy execution with method chaining
|
19
|
+
- Comprehensive test suite (72 tests, 119 assertions, 0 failures)
|
20
|
+
- Working examples with dummy applications
|
21
|
+
- Integration with BoringBuildRuby for Rails application builds
|
22
|
+
|
23
|
+
### Features
|
24
|
+
- **Client**: GraphQL client with automatic session detection
|
25
|
+
- **Container**: Full container lifecycle management and operations
|
26
|
+
- **Directory**: File system operations and directory manipulation
|
27
|
+
- **File**: File reading, writing, and export operations
|
28
|
+
- **Cache Volume**: Build caching for faster rebuilds
|
29
|
+
- **Secret**: Secure secret injection and mounting
|
30
|
+
- **Query Builder**: Optimized GraphQL query generation
|
31
|
+
- **Error Handling**: Comprehensive error types and messages
|
32
|
+
|
33
|
+
### Examples
|
34
|
+
- Simple Ruby application build with caching
|
35
|
+
- Rails CI/CD pipeline with multi-environment support
|
36
|
+
- BoringBuildRuby integration for optimized Rails builds
|
37
|
+
- Cowsay demonstration of basic operations
|
38
|
+
|
39
|
+
### Performance
|
40
|
+
- Lazy evaluation prevents unnecessary API calls
|
41
|
+
- Cache volumes provide 50-80% faster rebuilds
|
42
|
+
- Optimized GraphQL query generation
|
43
|
+
- HTTP connection reuse and pooling
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2025 Gaurav Tiwari
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,319 @@
|
|
1
|
+
# DaggerRuby
|
2
|
+
|
3
|
+
A Ruby SDK for [Dagger](https://dagger.io) - build powerful CI/CD pipelines using Ruby code instead of YAML configurations.
|
4
|
+
|
5
|
+
DaggerRuby provides a fluent, idiomatic Ruby interface to Dagger's container-based CI/CD engine, enabling you to define build pipelines programmatically with the full power of Ruby.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'dagger_ruby'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
```bash
|
18
|
+
bundle install
|
19
|
+
```
|
20
|
+
|
21
|
+
Or install it yourself with:
|
22
|
+
|
23
|
+
```bash
|
24
|
+
gem install dagger_ruby
|
25
|
+
```
|
26
|
+
|
27
|
+
### Prerequisites
|
28
|
+
|
29
|
+
- Ruby 3.1 or higher
|
30
|
+
- [Dagger CLI](https://docs.dagger.io/install) installed
|
31
|
+
- Docker or compatible container runtime (Docker Desktop, Podman, etc.)
|
32
|
+
|
33
|
+
## Quick Start
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require 'dagger_ruby'
|
37
|
+
|
38
|
+
DaggerRuby.connection do |client|
|
39
|
+
result = client.container
|
40
|
+
.from("alpine:latest")
|
41
|
+
.with_exec(["echo", "hello world"])
|
42
|
+
.stdout
|
43
|
+
|
44
|
+
puts result
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
Run your script with Dagger:
|
49
|
+
|
50
|
+
```bash
|
51
|
+
dagger run ruby your_script.rb
|
52
|
+
```
|
53
|
+
|
54
|
+
## Key Features
|
55
|
+
|
56
|
+
- **Smart Connection**: Auto-detects Dagger sessions
|
57
|
+
- **Lazy Execution**: Queries built but not executed until needed
|
58
|
+
- **Cache Volumes**: Fast builds with persistent caching
|
59
|
+
- **Secrets Management**: Secure handling of sensitive data
|
60
|
+
- **Git Integration**: Clone and build from repositories
|
61
|
+
- **Registry Auth**: Push to private registries
|
62
|
+
- **Multi-platform**: Build for multiple architectures
|
63
|
+
|
64
|
+
## Examples
|
65
|
+
|
66
|
+
### Basic Container
|
67
|
+
```ruby
|
68
|
+
DaggerRuby.connection do |client|
|
69
|
+
client.container
|
70
|
+
.from("python:alpine")
|
71
|
+
.with_exec(["pip", "install", "cowsay"])
|
72
|
+
.with_exec(["cowsay", "Hello from Dagger!"])
|
73
|
+
.stdout
|
74
|
+
end
|
75
|
+
```
|
76
|
+
|
77
|
+
### With Caching
|
78
|
+
```ruby
|
79
|
+
DaggerRuby.connection do |client|
|
80
|
+
cache = client.cache_volume("bundle-cache")
|
81
|
+
|
82
|
+
client.container
|
83
|
+
.from("ruby:3.2")
|
84
|
+
.with_mounted_cache("/usr/local/bundle", cache)
|
85
|
+
.with_exec(["bundle", "install"])
|
86
|
+
.with_exec(["ruby", "app.rb"])
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
### Git Repository
|
91
|
+
```ruby
|
92
|
+
DaggerRuby.connection do |client|
|
93
|
+
source = client.git("https://github.com/user/repo.git")
|
94
|
+
.branch("main")
|
95
|
+
.tree
|
96
|
+
|
97
|
+
client.container
|
98
|
+
.from("node:18")
|
99
|
+
.with_directory("/src", source)
|
100
|
+
.with_exec(["npm", "install"])
|
101
|
+
.with_exec(["npm", "run", "build"])
|
102
|
+
end
|
103
|
+
```
|
104
|
+
|
105
|
+
### Secret Management
|
106
|
+
```ruby
|
107
|
+
DaggerRuby.connection do |client|
|
108
|
+
# Set a secret
|
109
|
+
db_password = client.set_secret("db_password", "super_secret")
|
110
|
+
|
111
|
+
client.container
|
112
|
+
.from("postgres:15")
|
113
|
+
.with_secret_variable("POSTGRES_PASSWORD", db_password)
|
114
|
+
.with_exec(["postgres"])
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
### Multi-stage Builds
|
119
|
+
```ruby
|
120
|
+
DaggerRuby.connection do |client|
|
121
|
+
# Build stage
|
122
|
+
builder = client.container
|
123
|
+
.from("golang:1.21")
|
124
|
+
.with_directory("/src", client.host.directory("."))
|
125
|
+
.with_workdir("/src")
|
126
|
+
.with_exec(["go", "build", "-o", "app"])
|
127
|
+
|
128
|
+
# Runtime stage
|
129
|
+
client.container
|
130
|
+
.from("alpine:latest")
|
131
|
+
.with_file("/bin/app", builder.file("/src/app"))
|
132
|
+
.with_entrypoint(["/bin/app"])
|
133
|
+
end
|
134
|
+
```
|
135
|
+
|
136
|
+
### Building and Pushing Images
|
137
|
+
```ruby
|
138
|
+
DaggerRuby.connection do |client|
|
139
|
+
ref = client.container
|
140
|
+
.from("node:18")
|
141
|
+
.with_directory("/app", client.host.directory("."))
|
142
|
+
.with_workdir("/app")
|
143
|
+
.with_exec(["npm", "ci"])
|
144
|
+
.with_exec(["npm", "run", "build"])
|
145
|
+
.publish("registry.example.com/my-app:latest")
|
146
|
+
|
147
|
+
puts "Published image: #{ref}"
|
148
|
+
end
|
149
|
+
```
|
150
|
+
|
151
|
+
## Advanced Usage
|
152
|
+
|
153
|
+
### Working with Services
|
154
|
+
```ruby
|
155
|
+
DaggerRuby.connection do |client|
|
156
|
+
# Start a database service
|
157
|
+
postgres = client.container
|
158
|
+
.from("postgres:15")
|
159
|
+
.with_env_variable("POSTGRES_PASSWORD", "password")
|
160
|
+
.with_exposed_port(5432)
|
161
|
+
.as_service
|
162
|
+
|
163
|
+
# Run tests against the database
|
164
|
+
client.container
|
165
|
+
.from("ruby:3.2")
|
166
|
+
.with_service_binding("db", postgres)
|
167
|
+
.with_env_variable("DATABASE_URL", "postgres://postgres:password@db:5432/test")
|
168
|
+
.with_exec(["bundle", "exec", "rspec"])
|
169
|
+
end
|
170
|
+
```
|
171
|
+
|
172
|
+
### Cross-platform Builds
|
173
|
+
```ruby
|
174
|
+
DaggerRuby.connection do |client|
|
175
|
+
platforms = ["linux/amd64", "linux/arm64"]
|
176
|
+
|
177
|
+
platforms.each do |platform|
|
178
|
+
ref = client.container(platform: platform)
|
179
|
+
.from("golang:1.21")
|
180
|
+
.with_directory("/src", client.host.directory("."))
|
181
|
+
.with_workdir("/src")
|
182
|
+
.with_exec(["go", "build", "-o", "app"])
|
183
|
+
.publish("my-registry.com/app:latest-#{platform.gsub('/', '-')}")
|
184
|
+
|
185
|
+
puts "Built for #{platform}: #{ref}"
|
186
|
+
end
|
187
|
+
end
|
188
|
+
```
|
189
|
+
|
190
|
+
## Configuration
|
191
|
+
|
192
|
+
DaggerRuby can be configured using a configuration object:
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
config = DaggerRuby::Config.new
|
196
|
+
config.timeout = 300 # Set timeout to 5 minutes
|
197
|
+
config.log_output = STDOUT # Enable logging
|
198
|
+
|
199
|
+
DaggerRuby.connection(config) do |client|
|
200
|
+
# Your pipeline code
|
201
|
+
end
|
202
|
+
```
|
203
|
+
|
204
|
+
## Error Handling
|
205
|
+
|
206
|
+
DaggerRuby provides specific error classes for different failure scenarios:
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
begin
|
210
|
+
DaggerRuby.connection do |client|
|
211
|
+
client.container
|
212
|
+
.from("nonexistent:image")
|
213
|
+
.stdout
|
214
|
+
end
|
215
|
+
rescue DaggerRuby::ConnectionError => e
|
216
|
+
puts "Failed to connect to Dagger: #{e.message}"
|
217
|
+
rescue DaggerRuby::GraphQLError => e
|
218
|
+
puts "GraphQL error: #{e.message}"
|
219
|
+
rescue DaggerRuby::InvalidQueryError => e
|
220
|
+
puts "Invalid query: #{e.message}"
|
221
|
+
end
|
222
|
+
```
|
223
|
+
|
224
|
+
## Best Practices
|
225
|
+
|
226
|
+
### 1. Use Cache Volumes for Dependencies
|
227
|
+
```ruby
|
228
|
+
# Good: Use cache volumes for package managers
|
229
|
+
cache = client.cache_volume("npm-cache")
|
230
|
+
container.with_mounted_cache("/root/.npm", cache)
|
231
|
+
|
232
|
+
# Bad: No caching, slower builds
|
233
|
+
container.with_exec(["npm", "install"])
|
234
|
+
```
|
235
|
+
|
236
|
+
### 2. Leverage Multi-stage Builds
|
237
|
+
```ruby
|
238
|
+
# Separate build and runtime environments for smaller images
|
239
|
+
builder = client.container.from("node:18").with_exec(["npm", "run", "build"])
|
240
|
+
runtime = client.container.from("nginx:alpine").with_directory("/usr/share/nginx/html", builder.directory("/app/dist"))
|
241
|
+
```
|
242
|
+
|
243
|
+
### 3. Use Secrets for Sensitive Data
|
244
|
+
```ruby
|
245
|
+
# Good: Use Dagger secrets
|
246
|
+
api_key = client.set_secret("api_key", ENV["API_KEY"])
|
247
|
+
container.with_secret_variable("API_KEY", api_key)
|
248
|
+
|
249
|
+
# Bad: Expose secrets in environment variables
|
250
|
+
container.with_env_variable("API_KEY", ENV["API_KEY"]) # This gets cached!
|
251
|
+
```
|
252
|
+
|
253
|
+
## Examples
|
254
|
+
|
255
|
+
See the `examples/` directory for complete working examples:
|
256
|
+
|
257
|
+
- `examples/cowsay.rb` - Simple container execution
|
258
|
+
- `examples/ruby_app_build.rb` - Ruby web application build and validation
|
259
|
+
- `examples/service_test.rb` - App testing and validation
|
260
|
+
- `examples/simple_service.rb` - Quick service binding demo with Redis
|
261
|
+
|
262
|
+
### Running Examples
|
263
|
+
|
264
|
+
```bash
|
265
|
+
# Simple container example
|
266
|
+
dagger run ruby examples/cowsay.rb "Hello Dagger!"
|
267
|
+
|
268
|
+
# Build and validate a Ruby web application
|
269
|
+
dagger run ruby examples/ruby_app_build.rb
|
270
|
+
|
271
|
+
# Test and validate app without services
|
272
|
+
dagger run ruby examples/service_test.rb
|
273
|
+
|
274
|
+
# Quick service binding example
|
275
|
+
dagger run ruby examples/simple_service.rb
|
276
|
+
```
|
277
|
+
|
278
|
+
## Development
|
279
|
+
|
280
|
+
After checking out the repo, run:
|
281
|
+
|
282
|
+
```bash
|
283
|
+
bin/setup # Install dependencies
|
284
|
+
bin/console # Start an interactive prompt
|
285
|
+
```
|
286
|
+
|
287
|
+
To run tests:
|
288
|
+
|
289
|
+
```bash
|
290
|
+
bundle exec rake test
|
291
|
+
```
|
292
|
+
|
293
|
+
## Contributing
|
294
|
+
|
295
|
+
1. Fork the repository
|
296
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
297
|
+
3. Commit your changes (`git commit -am 'Add amazing feature'`)
|
298
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
299
|
+
5. Open a Pull Request
|
300
|
+
|
301
|
+
## Requirements
|
302
|
+
|
303
|
+
- Ruby 3.1+
|
304
|
+
- Dagger CLI
|
305
|
+
- Docker or compatible container runtime
|
306
|
+
|
307
|
+
## Support
|
308
|
+
|
309
|
+
- [GitHub Issues](https://github.com/boring-build/dagger-ruby/issues) - Bug reports and feature requests
|
310
|
+
- [Dagger Documentation](https://docs.dagger.io) - Official Dagger documentation
|
311
|
+
- [Ruby Documentation](https://docs.ruby-lang.org) - Ruby language documentation
|
312
|
+
|
313
|
+
## Acknowledgments
|
314
|
+
|
315
|
+
Built with ❤️ using **Claude Sonnet 3.5/4** + **GPT-4** AI assistance.
|
316
|
+
|
317
|
+
## License
|
318
|
+
|
319
|
+
MIT
|
data/dagger_ruby.gemspec
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/dagger_ruby/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "dagger_ruby"
|
7
|
+
spec.version = DaggerRuby::VERSION
|
8
|
+
spec.authors = [ "Gaurav Tiwari" ]
|
9
|
+
spec.email = [ "gaurav@gauravtiwari.co.uk" ]
|
10
|
+
|
11
|
+
spec.summary = "A Ruby SDK for Dagger"
|
12
|
+
spec.description = "A Ruby SDK for Dagger that provides a simple interface to build and deploy applications"
|
13
|
+
spec.homepage = "https://github.com/boring-build/dagger-ruby"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = ">= 3.1.0"
|
16
|
+
|
17
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
18
|
+
|
19
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
20
|
+
spec.metadata["source_code_uri"] = "https://github.com/boring-build/dagger-ruby"
|
21
|
+
spec.metadata["changelog_uri"] = "https://github.com/boring-build/dagger-ruby/blob/main/CHANGELOG.md"
|
22
|
+
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
24
|
+
spec.files = Dir.glob(%w[
|
25
|
+
lib/**/*
|
26
|
+
*.gemspec
|
27
|
+
LICENSE*
|
28
|
+
CHANGELOG*
|
29
|
+
README*
|
30
|
+
.yardopts
|
31
|
+
]).reject { |f| File.directory?(f) }
|
32
|
+
|
33
|
+
spec.bindir = "exe"
|
34
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
35
|
+
spec.require_paths = [ "lib" ]
|
36
|
+
|
37
|
+
# Core dependencies - using only Ruby stdlib
|
38
|
+
spec.add_dependency "json", "~> 2.6"
|
39
|
+
spec.add_dependency "base64", "~> 0.1"
|
40
|
+
|
41
|
+
# Development dependencies are managed in Gemfile
|
42
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
43
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "dagger_object"
|
4
|
+
|
5
|
+
module DaggerRuby
|
6
|
+
class CacheVolume < DaggerObject
|
7
|
+
def self.from_id(id, client)
|
8
|
+
query = QueryBuilder.new("cacheVolume")
|
9
|
+
query.load_from_id(id)
|
10
|
+
new(query, client)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.root_field_name
|
14
|
+
"cacheVolume"
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def key
|
19
|
+
get_scalar("key")
|
20
|
+
end
|
21
|
+
|
22
|
+
def sync
|
23
|
+
get_scalar("id") # Force execution by getting ID
|
24
|
+
self
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "logger"
|
4
|
+
require "net/http"
|
5
|
+
require "uri"
|
6
|
+
require "json"
|
7
|
+
require "base64"
|
8
|
+
require_relative "container"
|
9
|
+
require_relative "directory"
|
10
|
+
require_relative "file"
|
11
|
+
require_relative "secret"
|
12
|
+
require_relative "cache_volume"
|
13
|
+
require_relative "host"
|
14
|
+
require_relative "git_repository"
|
15
|
+
require_relative "service"
|
16
|
+
require_relative "query_builder"
|
17
|
+
|
18
|
+
module DaggerRuby
|
19
|
+
class Client
|
20
|
+
attr_reader :config
|
21
|
+
|
22
|
+
def initialize(config: nil)
|
23
|
+
@config = config || Config.new
|
24
|
+
|
25
|
+
port = ENV["DAGGER_SESSION_PORT"]
|
26
|
+
@session_token = ENV["DAGGER_SESSION_TOKEN"]
|
27
|
+
|
28
|
+
unless port && @session_token
|
29
|
+
raise ConnectionError, "This script must be run within a Dagger session.\nRun with: dagger run ruby script.rb [args...]"
|
30
|
+
end
|
31
|
+
|
32
|
+
@endpoint = "http://127.0.0.1:#{port}/query"
|
33
|
+
@uri = URI(@endpoint)
|
34
|
+
@auth_header = "Basic #{Base64.strict_encode64("#{@session_token}:")}"
|
35
|
+
|
36
|
+
if @config.log_output
|
37
|
+
logger = Logger.new(@config.log_output)
|
38
|
+
logger.level = Logger::INFO
|
39
|
+
@logger = logger
|
40
|
+
end
|
41
|
+
|
42
|
+
begin
|
43
|
+
execute_query("query { container { id } }")
|
44
|
+
rescue => e
|
45
|
+
raise ConnectionError, "Failed to connect to Dagger engine: #{e.message}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def container(opts = {})
|
50
|
+
query = QueryBuilder.new
|
51
|
+
if opts[:platform]
|
52
|
+
query = query.chain_operation("container", { "platform" => opts[:platform] })
|
53
|
+
else
|
54
|
+
query = query.chain_operation("container")
|
55
|
+
end
|
56
|
+
Container.new(query, self)
|
57
|
+
end
|
58
|
+
|
59
|
+
def directory
|
60
|
+
Directory.new(QueryBuilder.new("directory"), self)
|
61
|
+
end
|
62
|
+
|
63
|
+
def file
|
64
|
+
File.new(QueryBuilder.new("file"), self)
|
65
|
+
end
|
66
|
+
|
67
|
+
def secret
|
68
|
+
Secret.new(QueryBuilder.new("secret"), self)
|
69
|
+
end
|
70
|
+
|
71
|
+
def cache_volume(name)
|
72
|
+
query = QueryBuilder.new
|
73
|
+
query = query.chain_operation("cacheVolume", { "key" => name })
|
74
|
+
CacheVolume.new(query, self)
|
75
|
+
end
|
76
|
+
|
77
|
+
def host
|
78
|
+
Host.new(QueryBuilder.new("host"), self)
|
79
|
+
end
|
80
|
+
|
81
|
+
def git(url, opts = {})
|
82
|
+
args = { "url" => url }
|
83
|
+
args["keepGitDir"] = opts[:keep_git_dir] if opts.key?(:keep_git_dir)
|
84
|
+
args["sshKnownHosts"] = opts[:ssh_known_hosts] if opts[:ssh_known_hosts]
|
85
|
+
args["sshAuthSocket"] = opts[:ssh_auth_socket].is_a?(DaggerObject) ? opts[:ssh_auth_socket].id : opts[:ssh_auth_socket] if opts[:ssh_auth_socket]
|
86
|
+
args["httpAuthUsername"] = opts[:http_auth_username] if opts[:http_auth_username]
|
87
|
+
args["httpAuthToken"] = opts[:http_auth_token].is_a?(DaggerObject) ? opts[:http_auth_token].id : opts[:http_auth_token] if opts[:http_auth_token]
|
88
|
+
args["httpAuthHeader"] = opts[:http_auth_header].is_a?(DaggerObject) ? opts[:http_auth_header].id : opts[:http_auth_header] if opts[:http_auth_header]
|
89
|
+
|
90
|
+
query = QueryBuilder.new
|
91
|
+
query = query.chain_operation("git", args)
|
92
|
+
GitRepository.new(query, self)
|
93
|
+
end
|
94
|
+
|
95
|
+
def http(url, opts = {})
|
96
|
+
args = { "url" => url }
|
97
|
+
args["name"] = opts[:name] if opts[:name]
|
98
|
+
args["permissions"] = opts[:permissions] if opts[:permissions]
|
99
|
+
args["authHeader"] = opts[:auth_header].is_a?(DaggerObject) ? opts[:auth_header].id : opts[:auth_header] if opts[:auth_header]
|
100
|
+
|
101
|
+
query = QueryBuilder.new
|
102
|
+
query = query.chain_operation("http", args)
|
103
|
+
File.new(query, self)
|
104
|
+
end
|
105
|
+
|
106
|
+
def set_secret(name, value)
|
107
|
+
query = QueryBuilder.new
|
108
|
+
query = query.chain_operation("setSecret", { "name" => name, "plaintext" => value })
|
109
|
+
Secret.new(query, self)
|
110
|
+
end
|
111
|
+
|
112
|
+
def close
|
113
|
+
end
|
114
|
+
|
115
|
+
def execute_query(query)
|
116
|
+
http = Net::HTTP.new(@uri.host, @uri.port)
|
117
|
+
http.read_timeout = @config.timeout
|
118
|
+
http.open_timeout = 10
|
119
|
+
|
120
|
+
request = Net::HTTP::Post.new(@uri.path)
|
121
|
+
request["Content-Type"] = "application/json"
|
122
|
+
request["Authorization"] = @auth_header
|
123
|
+
request["User-Agent"] = "Dagger Ruby"
|
124
|
+
request.body = { query: query }.to_json
|
125
|
+
|
126
|
+
response = http.request(request)
|
127
|
+
handle_response(response)
|
128
|
+
end
|
129
|
+
|
130
|
+
alias execute execute_query
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def handle_response(response)
|
135
|
+
case response.code.to_i
|
136
|
+
when 200
|
137
|
+
begin
|
138
|
+
parsed_body = JSON.parse(response.body)
|
139
|
+
rescue JSON::ParserError
|
140
|
+
raise GraphQLError, "Invalid JSON response from server"
|
141
|
+
end
|
142
|
+
|
143
|
+
if parsed_body.nil?
|
144
|
+
raise GraphQLError, "Empty response from server"
|
145
|
+
end
|
146
|
+
|
147
|
+
if parsed_body["errors"]
|
148
|
+
raise GraphQLError, parsed_body["errors"].map { |e| e["message"] }.join(", ")
|
149
|
+
end
|
150
|
+
|
151
|
+
if parsed_body["data"].nil?
|
152
|
+
raise GraphQLError, "No data in response"
|
153
|
+
end
|
154
|
+
|
155
|
+
parsed_body["data"]
|
156
|
+
when 400
|
157
|
+
raise InvalidQueryError, "Invalid GraphQL query: #{response.body}"
|
158
|
+
when 401
|
159
|
+
raise ConnectionError, "Authentication failed"
|
160
|
+
else
|
161
|
+
raise HTTPError, "HTTP #{response.code}: #{response.body}"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require "logger"
|
2
|
+
|
3
|
+
module DaggerRuby
|
4
|
+
class Config
|
5
|
+
attr_reader :log_output, :workdir, :timeout
|
6
|
+
|
7
|
+
def initialize(log_output: nil, workdir: nil, timeout: nil)
|
8
|
+
@log_output = log_output
|
9
|
+
@workdir = workdir
|
10
|
+
@timeout = timeout || 600
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|