Skip to content

Commit 31822eb

Browse files
committed
Rework for ruby 3.2+
Signed-off-by: David Kirwan <[email protected]>
1 parent 04db00d commit 31822eb

23 files changed

Lines changed: 1618 additions & 180 deletions

.env.example

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Application Configuration
2+
RACK_ENV=development
3+
LOG_LEVEL=DEBUG
4+
APP_VERSION=1.0.0
5+
PORT=8080
6+
7+
# BullionVault API Configuration
8+
BULLIONVAULT_URL=https://www.bullionvault.com/view_market_xml.do
9+
BULLIONVAULT_TIMEOUT=30
10+
BULLIONVAULT_RETRIES=3
11+
12+
# Coinbase API Configuration
13+
COINBASE_URL=https://api.coinbase.com/v2/prices
14+
COINBASE_TIMEOUT=30
15+
COINBASE_RETRIES=3
16+
17+
# Monitoring Configuration
18+
METRICS_PATH=/metrics
19+
HEALTH_PATH=/health
20+
READY_PATH=/ready

.github/workflows/ci.yml

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
name: CI/CD Pipeline
2+
3+
on:
4+
push:
5+
branches: [ main, master, develop ]
6+
pull_request:
7+
branches: [ main, master ]
8+
9+
env:
10+
RUBY_VERSION: '3.2.0'
11+
BUNDLE_PATH: vendor/bundle
12+
13+
jobs:
14+
test:
15+
name: Test Suite
16+
runs-on: ubuntu-latest
17+
18+
services:
19+
prometheus:
20+
image: prom/prometheus:latest
21+
ports:
22+
- 9090:9090
23+
24+
steps:
25+
- name: Checkout code
26+
uses: actions/checkout@v4
27+
28+
- name: Set up Ruby
29+
uses: ruby/setup-ruby@v1
30+
with:
31+
ruby-version: ${{ env.RUBY_VERSION }}
32+
bundler-cache: true
33+
34+
- name: Install dependencies
35+
run: |
36+
bundle config path vendor/bundle
37+
bundle install --jobs 4 --retry 3
38+
39+
- name: Run RuboCop
40+
run: bundle exec rubocop
41+
42+
- name: Run RSpec tests
43+
run: bundle exec rspec --format documentation
44+
45+
- name: Upload coverage reports
46+
uses: codecov/codecov-action@v3
47+
if: success()
48+
with:
49+
file: ./coverage/lcov.info
50+
flags: unittests
51+
name: codecov-umbrella
52+
53+
security:
54+
name: Security Scan
55+
runs-on: ubuntu-latest
56+
57+
steps:
58+
- name: Checkout code
59+
uses: actions/checkout@v4
60+
61+
- name: Set up Ruby
62+
uses: ruby/setup-ruby@v1
63+
with:
64+
ruby-version: ${{ env.RUBY_VERSION }}
65+
bundler-cache: true
66+
67+
- name: Run security audit
68+
run: |
69+
bundle audit --update
70+
bundle exec brakeman --no-pager
71+
72+
build:
73+
name: Build Docker Image
74+
runs-on: ubuntu-latest
75+
needs: [test, security]
76+
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')
77+
78+
steps:
79+
- name: Checkout code
80+
uses: actions/checkout@v4
81+
82+
- name: Set up Docker Buildx
83+
uses: docker/setup-buildx-action@v3
84+
85+
- name: Login to Container Registry
86+
uses: docker/login-action@v3
87+
with:
88+
registry: quay.io
89+
username: ${{ secrets.QUAY_USERNAME }}
90+
password: ${{ secrets.QUAY_TOKEN }}
91+
92+
- name: Extract metadata
93+
id: meta
94+
uses: docker/metadata-action@v5
95+
with:
96+
images: quay.io/dkirwan/asset_monitoring
97+
tags: |
98+
type=ref,event=branch
99+
type=ref,event=pr
100+
type=sha,prefix={{branch}}-
101+
type=raw,value=latest,enable={{is_default_branch}}
102+
103+
- name: Build and push Docker image
104+
uses: docker/build-push-action@v5
105+
with:
106+
context: .
107+
platforms: linux/amd64,linux/arm64
108+
push: true
109+
tags: ${{ steps.meta.outputs.tags }}
110+
labels: ${{ steps.meta.outputs.labels }}
111+
cache-from: type=gha
112+
cache-to: type=gha,mode=max
113+
114+
deploy:
115+
name: Deploy to Kubernetes
116+
runs-on: ubuntu-latest
117+
needs: [build]
118+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
119+
environment: production
120+
121+
steps:
122+
- name: Checkout code
123+
uses: actions/checkout@v4
124+
125+
- name: Configure kubectl
126+
uses: azure/k8s-set-context@v3
127+
with:
128+
method: kubeconfig
129+
kubeconfig: ${{ secrets.KUBE_CONFIG }}
130+
131+
- name: Deploy to Kubernetes
132+
run: |
133+
# Update image tag in deployment
134+
sed -i "s|quay.io/dkirwan/asset_monitoring:.*|quay.io/dkirwan/asset_monitoring:${GITHUB_SHA}|g" kubernetes/deployment.yaml
135+
136+
# Apply Kubernetes manifests
137+
kubectl apply -f kubernetes/
138+
139+
# Wait for deployment to be ready
140+
kubectl rollout status deployment/crypto -n monitoring-example --timeout=300s

.gitignore

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,46 @@
1-
bundle
1+
# Ruby
2+
*.gem
3+
*.rbc
4+
/.config
5+
/coverage/
6+
/InstalledFiles
7+
/pkg/
8+
/spec/reports/
9+
/spec/examples.txt
10+
/test/tmp/
11+
/test/version_tmp/
12+
/tmp/
13+
14+
# RSpec
15+
/spec/examples.txt
16+
17+
# SimpleCov
18+
/coverage/
19+
20+
# VCR
21+
/spec/fixtures/vcr_cassettes/
22+
23+
# Logs
24+
*.log
25+
26+
# Environment variables
27+
.env
28+
.env.local
29+
.env.*.local
30+
31+
# IDE
32+
.vscode/
33+
.idea/
234
*.swp
35+
*.swo
36+
37+
# OS
38+
.DS_Store
39+
Thumbs.db
40+
41+
# Bundler
42+
/.bundle/
43+
/vendor/bundle/
44+
45+
# Docker
46+
.dockerignore

.rubocop.yml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
AllCops:
2+
NewCops: enable
3+
TargetRubyVersion: 3.2
4+
Exclude:
5+
- 'vendor/**/*'
6+
- 'spec/fixtures/**/*'
7+
- 'coverage/**/*'
8+
9+
Layout/LineLength:
10+
Max: 120
11+
Exclude:
12+
- 'spec/**/*'
13+
14+
Style/Documentation:
15+
Enabled: false
16+
17+
Style/StringLiterals:
18+
EnforcedStyle: single_quotes
19+
20+
Style/FrozenStringLiteralComment:
21+
Enabled: true
22+
23+
Style/ClassAndModuleChildren:
24+
Enabled: false
25+
26+
Style/GuardClause:
27+
Enabled: false
28+
29+
Metrics/AbcSize:
30+
Max: 20
31+
32+
Metrics/MethodLength:
33+
Max: 20
34+
35+
Metrics/BlockLength:
36+
Exclude:
37+
- 'spec/**/*'
38+
39+
RSpec/ExampleLength:
40+
Max: 10
41+
42+
RSpec/MultipleExpectations:
43+
Max: 5
44+
45+
RSpec/NestedGroups:
46+
Max: 4

Dockerfile

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,57 @@
1-
FROM ruby:2.6.5
2-
MAINTAINER David Kirwan <[email protected]>
1+
# Multi-stage build for smaller production image
2+
FROM ruby:3.2.0-alpine AS builder
33

4+
# Install build dependencies
5+
RUN apk add --no-cache \
6+
build-base \
7+
git \
8+
&& gem install bundler:2.4.22
49

5-
RUN mkdir /app
610
WORKDIR /app
711

8-
ADD . /app
9-
RUN bundle install --path /app/bundle/
12+
# Copy dependency files
13+
COPY Gemfile Gemfile.lock ./
1014

11-
RUN chmod 755 /app/asset_monitoring.rb
15+
# Install gems
16+
RUN bundle config set --local deployment 'true' \
17+
&& bundle config set --local without 'development test' \
18+
&& bundle install --jobs=4 --retry=3
1219

13-
ENTRYPOINT ["bundle", "exec", "rackup", "--host", "0.0.0.0", "-p", "8080"]
20+
# Production stage
21+
FROM ruby:3.2.0-alpine AS production
22+
23+
# Install runtime dependencies
24+
RUN apk add --no-cache \
25+
tzdata \
26+
ca-certificates \
27+
&& addgroup -g 1001 -S appgroup \
28+
&& adduser -u 1001 -S appuser -G appgroup
29+
30+
# Set timezone
31+
ENV TZ=UTC
32+
33+
# Create app directory
34+
WORKDIR /app
35+
36+
# Copy gems from builder stage
37+
COPY --from=builder /usr/local/bundle /usr/local/bundle
38+
39+
# Copy application code
40+
COPY --chown=appuser:appgroup . .
41+
42+
# Create non-root user and set permissions
43+
USER appuser
44+
45+
# Health check
46+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
47+
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
48+
49+
# Expose port
50+
EXPOSE 8080
51+
52+
# Set environment variables
53+
ENV RACK_ENV=production
54+
ENV PORT=8080
55+
56+
# Start the application
57+
CMD ["bundle", "exec", "rackup", "--host", "0.0.0.0", "-p", "8080"]

Gemfile

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,25 @@
11
source 'https://rubygems.org'
22

3-
gem 'curb'
4-
gem 'sinatra'
5-
gem 'json'
6-
gem 'puma'
7-
gem 'open-uri'
8-
gem "nokogiri", ">= 1.12.5"
3+
ruby '3.2.0'
4+
5+
# Application gems
6+
gem 'sinatra', '~> 3.0'
7+
gem 'puma', '~> 6.0'
8+
gem 'nokogiri', '~> 1.15'
9+
gem 'faraday', '~> 2.7' # Modern HTTP client instead of curb
10+
gem 'json', '~> 2.6'
11+
12+
# Development and test gems
13+
group :development, :test do
14+
gem 'rspec', '~> 3.12'
15+
gem 'rubocop', '~> 1.50'
16+
gem 'rubocop-rspec', '~> 2.20'
17+
gem 'simplecov', '~> 0.22'
18+
gem 'webmock', '~> 3.18'
19+
gem 'vcr', '~> 6.1'
20+
gem 'pry', '~> 0.14'
21+
end
22+
23+
group :development do
24+
gem 'rerun', '~> 0.14' # Auto-reload during development
25+
end

0 commit comments

Comments
 (0)