Skip to content

Commit 2a57158

Browse files
committed
feat: Ruby on Rails example
1 parent 57400bc commit 2a57158

1,867 files changed

Lines changed: 2989 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# See https://docs.docker.com/engine/reference/builder/#dockerignore-file for more about ignoring files.
2+
3+
# Ignore git directory.
4+
/.git/
5+
/.gitignore
6+
7+
# Ignore bundler config.
8+
/.bundle
9+
10+
# Ignore all environment files.
11+
/.env*
12+
13+
# Ignore all default key files.
14+
/config/master.key
15+
/config/credentials/*.key
16+
17+
# Ignore all logfiles and tempfiles.
18+
/log/*
19+
/tmp/*
20+
!/log/.keep
21+
!/tmp/.keep
22+
23+
# Ignore pidfiles, but keep the directory.
24+
/tmp/pids/*
25+
!/tmp/pids/.keep
26+
27+
# Ignore storage (uploaded files in development and any SQLite databases).
28+
/storage/*
29+
!/storage/.keep
30+
/tmp/storage/*
31+
!/tmp/storage/.keep
32+
33+
# Ignore assets.
34+
/node_modules/
35+
/app/assets/builds/*
36+
!/app/assets/builds/.keep
37+
/public/assets
38+
39+
# Ignore CI service files.
40+
/.github
41+
42+
# Ignore Kamal files.
43+
/config/deploy*.yml
44+
/.kamal
45+
46+
# Ignore development files
47+
/.devcontainer
48+
49+
# Ignore Docker-related files
50+
/.dockerignore
51+
/Dockerfile*
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: bundler
4+
directory: "/"
5+
schedule:
6+
interval: weekly
7+
open-pull-requests-limit: 10
8+
- package-ecosystem: github-actions
9+
directory: "/"
10+
schedule:
11+
interval: weekly
12+
open-pull-requests-limit: 10
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [ main ]
7+
8+
jobs:
9+
scan_ruby:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Checkout code
14+
uses: actions/checkout@v5
15+
16+
- name: Set up Ruby
17+
uses: ruby/setup-ruby@v1
18+
with:
19+
bundler-cache: true
20+
21+
- name: Scan for common Rails security vulnerabilities using static analysis
22+
run: bin/brakeman --no-pager
23+
24+
- name: Scan for known security vulnerabilities in gems used
25+
run: bin/bundler-audit
26+
27+
scan_js:
28+
runs-on: ubuntu-latest
29+
30+
steps:
31+
- name: Checkout code
32+
uses: actions/checkout@v5
33+
34+
- name: Set up Ruby
35+
uses: ruby/setup-ruby@v1
36+
with:
37+
bundler-cache: true
38+
39+
- name: Scan for security vulnerabilities in JavaScript dependencies
40+
run: bin/importmap audit
41+
42+
lint:
43+
runs-on: ubuntu-latest
44+
env:
45+
RUBOCOP_CACHE_ROOT: tmp/rubocop
46+
steps:
47+
- name: Checkout code
48+
uses: actions/checkout@v5
49+
50+
- name: Set up Ruby
51+
uses: ruby/setup-ruby@v1
52+
with:
53+
bundler-cache: true
54+
55+
- name: Prepare RuboCop cache
56+
uses: actions/cache@v4
57+
env:
58+
DEPENDENCIES_HASH: ${{ hashFiles('.ruby-version', '**/.rubocop.yml', '**/.rubocop_todo.yml', 'Gemfile.lock') }}
59+
with:
60+
path: ${{ env.RUBOCOP_CACHE_ROOT }}
61+
key: rubocop-${{ runner.os }}-${{ env.DEPENDENCIES_HASH }}-${{ github.ref_name == github.event.repository.default_branch && github.run_id || 'default' }}
62+
restore-keys: |
63+
rubocop-${{ runner.os }}-${{ env.DEPENDENCIES_HASH }}-
64+
65+
- name: Lint code for consistent style
66+
run: bin/rubocop -f github
67+
68+
test:
69+
runs-on: ubuntu-latest
70+
71+
# services:
72+
# redis:
73+
# image: valkey/valkey:8
74+
# ports:
75+
# - 6379:6379
76+
# options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
77+
steps:
78+
- name: Checkout code
79+
uses: actions/checkout@v5
80+
81+
- name: Set up Ruby
82+
uses: ruby/setup-ruby@v1
83+
with:
84+
bundler-cache: true
85+
86+
- name: Run tests
87+
env:
88+
RAILS_ENV: test
89+
# RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
90+
# REDIS_URL: redis://localhost:6379/0
91+
run: bin/rails db:test:prepare test
92+
93+
system-test:
94+
runs-on: ubuntu-latest
95+
96+
# services:
97+
# redis:
98+
# image: valkey/valkey:8
99+
# ports:
100+
# - 6379:6379
101+
# options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
102+
steps:
103+
- name: Checkout code
104+
uses: actions/checkout@v5
105+
106+
- name: Set up Ruby
107+
uses: ruby/setup-ruby@v1
108+
with:
109+
bundler-cache: true
110+
111+
- name: Run System Tests
112+
env:
113+
RAILS_ENV: test
114+
# RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }}
115+
# REDIS_URL: redis://localhost:6379/0
116+
run: bin/rails db:test:prepare test:system
117+
118+
- name: Keep screenshots from failed system tests
119+
uses: actions/upload-artifact@v4
120+
if: failure()
121+
with:
122+
name: screenshots
123+
path: ${{ github.workspace }}/tmp/screenshots
124+
if-no-files-found: ignore
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
echo "Docker set up on $KAMAL_HOSTS..."
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
echo "Booted app version $KAMAL_VERSION on $KAMAL_HOSTS..."
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/sh
2+
3+
# A sample post-deploy hook
4+
#
5+
# These environment variables are available:
6+
# KAMAL_RECORDED_AT
7+
# KAMAL_PERFORMER
8+
# KAMAL_VERSION
9+
# KAMAL_HOSTS
10+
# KAMAL_ROLES (if set)
11+
# KAMAL_DESTINATION (if set)
12+
# KAMAL_RUNTIME
13+
14+
echo "$KAMAL_PERFORMER deployed $KAMAL_VERSION to $KAMAL_DESTINATION in $KAMAL_RUNTIME seconds"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
echo "Rebooted kamal-proxy on $KAMAL_HOSTS"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
echo "Booting app version $KAMAL_VERSION on $KAMAL_HOSTS..."
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/bin/sh
2+
3+
# A sample pre-build hook
4+
#
5+
# Checks:
6+
# 1. We have a clean checkout
7+
# 2. A remote is configured
8+
# 3. The branch has been pushed to the remote
9+
# 4. The version we are deploying matches the remote
10+
#
11+
# These environment variables are available:
12+
# KAMAL_RECORDED_AT
13+
# KAMAL_PERFORMER
14+
# KAMAL_VERSION
15+
# KAMAL_HOSTS
16+
# KAMAL_ROLES (if set)
17+
# KAMAL_DESTINATION (if set)
18+
19+
if [ -n "$(git status --porcelain)" ]; then
20+
echo "Git checkout is not clean, aborting..." >&2
21+
git status --porcelain >&2
22+
exit 1
23+
fi
24+
25+
first_remote=$(git remote)
26+
27+
if [ -z "$first_remote" ]; then
28+
echo "No git remote set, aborting..." >&2
29+
exit 1
30+
fi
31+
32+
current_branch=$(git branch --show-current)
33+
34+
if [ -z "$current_branch" ]; then
35+
echo "Not on a git branch, aborting..." >&2
36+
exit 1
37+
fi
38+
39+
remote_head=$(git ls-remote $first_remote --tags $current_branch | cut -f1)
40+
41+
if [ -z "$remote_head" ]; then
42+
echo "Branch not pushed to remote, aborting..." >&2
43+
exit 1
44+
fi
45+
46+
if [ "$KAMAL_VERSION" != "$remote_head" ]; then
47+
echo "Version ($KAMAL_VERSION) does not match remote HEAD ($remote_head), aborting..." >&2
48+
exit 1
49+
fi
50+
51+
exit 0
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env ruby
2+
3+
# A sample pre-connect check
4+
#
5+
# Warms DNS before connecting to hosts in parallel
6+
#
7+
# These environment variables are available:
8+
# KAMAL_RECORDED_AT
9+
# KAMAL_PERFORMER
10+
# KAMAL_VERSION
11+
# KAMAL_HOSTS
12+
# KAMAL_ROLES (if set)
13+
# KAMAL_DESTINATION (if set)
14+
# KAMAL_RUNTIME
15+
16+
hosts = ENV["KAMAL_HOSTS"].split(",")
17+
results = nil
18+
max = 3
19+
20+
elapsed = Benchmark.realtime do
21+
results = hosts.map do |host|
22+
Thread.new do
23+
tries = 1
24+
25+
begin
26+
Socket.getaddrinfo(host, 0, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME)
27+
rescue SocketError
28+
if tries < max
29+
puts "Retrying DNS warmup: #{host}"
30+
tries += 1
31+
sleep rand
32+
retry
33+
else
34+
puts "DNS warmup failed: #{host}"
35+
host
36+
end
37+
end
38+
39+
tries
40+
end
41+
end.map(&:value)
42+
end
43+
44+
retries = results.sum - hosts.size
45+
nopes = results.count { |r| r == max }
46+
47+
puts "Prewarmed %d DNS lookups in %.2f sec: %d retries, %d failures" % [ hosts.size, elapsed, retries, nopes ]

0 commit comments

Comments
 (0)