Skip to content

Commit 02fe6a9

Browse files
authored
CI/CD Pipeline for Rails 8 test app
1 parent 065b640 commit 02fe6a9

File tree

1 file changed

+371
-0
lines changed

1 file changed

+371
-0
lines changed

ci-cd-workflow.md

Lines changed: 371 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,371 @@
1+
# Spec-Driven Rails App Development and Deployment (End-to-End Guide)
2+
3+
## Overview
4+
This document provides a complete end-to-end guide for building, testing, and deploying a spec-driven Ruby on Rails 8 application using Docker, Kamal, and Amazon Lightsail, with automated CI/CD via GitHub Actions.
5+
6+
Workflow:
7+
```
8+
Edit business spec → Commit → GitHub Actions (validate + test) → Deploy via Kamal → App updates
9+
```
10+
11+
---
12+
13+
## 1. Project Setup
14+
15+
[Placeholder: Complete step-by-step project initialization including Rails 8 setup, initial configuration, database setup, and basic application structure. This section will cover creating the Rails app, configuring essential files, setting up the business spec system, and preparing the project for spec-driven development.]
16+
17+
### Create Rails App
18+
19+
```bash
20+
rails new spec_driven_app --database=sqlite3
21+
cd spec_driven_app
22+
```
23+
24+
### Run App Locally
25+
26+
```bash
27+
bin/dev
28+
```
29+
30+
---
31+
32+
## 2. Version Control (Git + GitHub)
33+
34+
### Initialize Git
35+
36+
```bash
37+
git init
38+
git add .
39+
git commit -m "Initial commit - spec driven Rails app"
40+
```
41+
42+
### Connect to GitHub
43+
44+
```bash
45+
git remote add origin git@github.com:apperph/github-actions-test.git
46+
git branch -M main
47+
git push -u origin main
48+
```
49+
50+
---
51+
52+
## 3. Deployment Setup (Lightsail)
53+
54+
### SSH into Server
55+
56+
```bash
57+
ssh -i ~/Downloads/rails-test-key.pem ubuntu@<LIGHTSAIL_IP>
58+
```
59+
60+
### Notes
61+
- Default user: `ubuntu`
62+
- Ensure Docker is installed
63+
- Open port 80
64+
65+
---
66+
67+
## 4. Kamal Deployment Setup
68+
69+
### Install Kamal
70+
71+
```bash
72+
bundle add kamal
73+
```
74+
75+
### Deploy Config (`config/deploy.yml`)
76+
77+
```yaml
78+
service: spec_driven_app
79+
image: ghcr.io/apperph/github-actions-test
80+
servers:
81+
web:
82+
- 13.213.250.166
83+
proxy:
84+
ssl: false
85+
host: 13.213.250.166
86+
registry:
87+
server: ghcr.io
88+
username: apperph
89+
password:
90+
- KAMAL_REGISTRY_PASSWORD
91+
builder:
92+
arch: amd64
93+
env:
94+
clear:
95+
PORT: 80
96+
RAILS_ENV: production
97+
secret:
98+
- RAILS_MASTER_KEY
99+
ssh:
100+
user: ubuntu
101+
keys_only: true
102+
config: true
103+
```
104+
105+
---
106+
107+
## 5. Spec-Driven Logic
108+
109+
### Business Spec File
110+
111+
```bash
112+
config/specs/business.yml
113+
```
114+
115+
---
116+
117+
## 6. Rake Tasks
118+
119+
### Validate + Sync
120+
121+
```ruby
122+
namespace :specs do
123+
task validate: :environment do
124+
# validations
125+
end
126+
task sync: :environment do
127+
# apply logic
128+
end
129+
end
130+
```
131+
132+
---
133+
134+
## 7. GitHub Actions CI/CD
135+
136+
### Workflow File
137+
`.github/workflows/deploy.yml`
138+
139+
### Pipeline Flow
140+
1. Validate spec
141+
2. Run tests
142+
3. Deploy via Kamal
143+
144+
### Key Commands Used in Workflow
145+
146+
#### SSH Setup
147+
148+
```bash
149+
mkdir -p ~/.ssh
150+
echo "${{ secrets.LIGHTSAIL_SSH_KEY }}" > ~/.ssh/lightsail_key
151+
chmod 600 ~/.ssh/lightsail_key
152+
ssh-keygen -R "${{ vars.LIGHTSAIL_HOST }}" || true
153+
ssh-keyscan "${{ vars.LIGHTSAIL_HOST }}" >> ~/.ssh/known_hosts
154+
```
155+
156+
**Important:**
157+
- Do NOT use `-H` in `ssh-keyscan`
158+
- Avoid hashed known_hosts (causes HostKeyMismatch)
159+
160+
---
161+
162+
## 8. Git Workflow (VERY IMPORTANT)
163+
164+
### Always Sync Before Push
165+
166+
```bash
167+
git pull --rebase origin main
168+
```
169+
170+
### Push Changes
171+
172+
```bash
173+
git add .
174+
git commit -m "Your message"
175+
git push origin main
176+
```
177+
178+
### If Push Rejected
179+
180+
```bash
181+
git pull --rebase origin main
182+
git push origin main
183+
```
184+
185+
### Resolve Conflicts
186+
187+
```bash
188+
git status
189+
# edit files
190+
git add <file>
191+
git rebase --continue
192+
```
193+
194+
---
195+
196+
## 9. GitHub Secrets & Variables Configuration
197+
198+
This section explains how to securely configure credentials required for deployment.
199+
200+
### Where to Configure
201+
Go to your GitHub repository:
202+
Settings → Secrets and variables → Actions
203+
204+
You will see two sections:
205+
- Secrets
206+
- Variables
207+
208+
### A. GitHub Secrets (Sensitive Data)
209+
210+
#### 1. LIGHTSAIL_SSH_KEY
211+
**What this is**
212+
Your private SSH key (.pem) used to access the Lightsail instance.
213+
214+
**How to get it (from your local machine)**
215+
If you already SSH like this:
216+
217+
```bash
218+
ssh -i ~/Downloads/rails-test-key.pem ubuntu@13.213.250.166
219+
```
220+
221+
Then open the key:
222+
223+
```bash
224+
cat ~/Downloads/rails-test-key.pem
225+
```
226+
227+
**What to copy**
228+
Copy everything, including:
229+
230+
```
231+
-----BEGIN RSA PRIVATE KEY-----
232+
...
233+
-----END RSA PRIVATE KEY-----
234+
```
235+
236+
**Add to GitHub**
237+
1. Go to Secrets → New repository secret
238+
2. Name: `LIGHTSAIL_SSH_KEY`
239+
3. Paste the entire key
240+
4. Click Add secret
241+
242+
#### 2. RAILS_MASTER_KEY
243+
**What this is**
244+
Rails uses this to decrypt credentials.
245+
246+
**Get it locally**
247+
248+
```bash
249+
cat config/master.key
250+
```
251+
252+
**Add to GitHub**
253+
- Name: `RAILS_MASTER_KEY`
254+
- Value = contents of master.key
255+
256+
#### 3. GHCR_TOKEN
257+
**What this is**
258+
Token for pushing/pulling Docker images from GitHub Container Registry.
259+
260+
**Create token**
261+
1. Go to GitHub → Settings → Developer Settings → Personal Access Tokens
262+
2. Create new token with scopes:
263+
- `write:packages`
264+
- `read:packages`
265+
266+
**Add to GitHub**
267+
- Name: `GHCR_TOKEN`
268+
- Value = your token
269+
270+
### B. GitHub Variables (Non-sensitive)
271+
272+
#### 1. LIGHTSAIL_HOST
273+
**What this is**
274+
Your Lightsail public IP
275+
276+
Example: `13.213.250.166`
277+
278+
**Add to GitHub**
279+
1. Go to Variables → New repository variable
280+
2. Name: `LIGHTSAIL_HOST`
281+
3. Value: `13.213.250.166`
282+
283+
---
284+
285+
## 10. Important Notes
286+
287+
### Spec Updates
288+
Whenever editing `config/specs/business.yml`, you must:
289+
1. Validate
290+
2. Commit
291+
3. Push
292+
293+
### Validate Locally
294+
295+
```bash
296+
bundle exec rake specs:validate
297+
```
298+
299+
### Run Tests
300+
301+
```bash
302+
bundle exec rails test
303+
```
304+
305+
### Deploy Trigger
306+
307+
#### Automatic (preferred)
308+
309+
```bash
310+
git commit -m "Update spec"
311+
git push origin main
312+
```
313+
314+
#### Manual Trigger
315+
GitHub UI:
316+
1. Go to **Actions**
317+
2. Select **Rails CI/CD Deploy**
318+
3. Click **Run workflow**
319+
320+
#### Force Trigger
321+
322+
```bash
323+
git commit --allow-empty -m "Trigger deploy"
324+
git push origin main
325+
```
326+
327+
---
328+
329+
## 11. Manual Updates in GitHub (No Terminal)
330+
331+
### Editing Business Spec
332+
1. Go to repository
333+
2. Navigate to `config/specs/business.yml`
334+
3. Click **Edit**
335+
4. Modify values
336+
5. Scroll down → Commit changes
337+
338+
### Result
339+
- Triggers GitHub Actions
340+
- Runs validation + tests
341+
- Deploys automatically
342+
343+
---
344+
345+
## 12. Final Architecture
346+
347+
```
348+
PM edits YAML (GitHub UI or local)
349+
350+
GitHub Actions
351+
- validate
352+
- test
353+
354+
Kamal deploy
355+
356+
Lightsail server
357+
358+
Updated Rails app
359+
```
360+
361+
---
362+
363+
## 13. Best Practices / Lessons Learned
364+
- Always `git pull --rebase` before push
365+
- Avoid secrets in repo
366+
- Never re-run old workflows
367+
- Use fresh commits to trigger deploy
368+
- Keep tests aligned with specs
369+
- Avoid hashed SSH known_hosts
370+
- Validate specs before pushing
371+

0 commit comments

Comments
 (0)