55 branches : [ main ]
66 workflow_dispatch :
77
8+ env :
9+ RUBY_VERSION : ' 3.3.6'
10+ NODE_VERSION : ' 20'
11+ POSTGRES_VERSION : ' 17'
12+ REDIS_VERSION : ' 7'
13+
814jobs :
915 test :
1016 runs-on : ubuntu-latest
17+ timeout-minutes : 30
1118
1219 services :
1320 postgres :
1421 image : postgres:17
1522 env :
1623 POSTGRES_PASSWORD : postgres
24+ POSTGRES_DB : streamsource_test
1725 options : >-
1826 --health-cmd pg_isready
1927 --health-interval 10s
@@ -33,23 +41,46 @@ jobs:
3341 - 6379:6379
3442
3543 steps :
36- - uses : actions/checkout@v4
44+ - name : Checkout code
45+ uses : actions/checkout@v4
46+ with :
47+ fetch-depth : 0 # Full history for better caching
3748
49+ - name : Cache Ruby dependencies
50+ uses : actions/cache@v4
51+ with :
52+ path : |
53+ ~/.bundle
54+ vendor/bundle
55+ key : ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
56+ restore-keys : |
57+ ${{ runner.os }}-gems-
58+
3859 - name : Set up Ruby
3960 uses : ruby/setup-ruby@v1
4061 with :
41- ruby-version : ' 3.3.6 '
62+ ruby-version : ${{ env.RUBY_VERSION }}
4263 bundler-cache : true
4364
65+ - name : Cache Node dependencies
66+ uses : actions/cache@v4
67+ with :
68+ path : |
69+ ~/.cache/yarn
70+ node_modules
71+ key : ${{ runner.os }}-node-${{ hashFiles('**/yarn.lock') }}
72+ restore-keys : |
73+ ${{ runner.os }}-node-
74+
4475 - name : Setup Node
4576 uses : actions/setup-node@v4
4677 with :
47- node-version : ' 20 '
78+ node-version : ${{ env.NODE_VERSION }}
4879 cache : ' yarn'
4980
5081 - name : Install dependencies
5182 run : |
52- yarn install --frozen-lockfile
83+ yarn install --frozen-lockfile --prefer-offline
5384
5485 - name : Setup test database
5586 env :
@@ -69,37 +100,148 @@ jobs:
69100
70101 - name : Run security checks
71102 run : |
72- bundle exec brakeman -q -w2
73- bundle exec bundler-audit --update
103+ echo "π Running security analysis..."
104+
105+ # Static Application Security Testing (SAST)
106+ bundle exec brakeman -q -w2 --format json --output brakeman-report.json
107+
108+ # Dependency vulnerability scanning
109+ bundle exec bundler-audit check --update --format json --output bundler-audit-report.json
110+
111+ # Display results
112+ echo "Brakeman security scan completed"
113+ if [ -f brakeman-report.json ]; then
114+ echo "Brakeman found $(jq '.warnings | length' brakeman-report.json) potential issues"
115+ fi
116+
117+ echo "Bundler audit completed"
118+ if [ -f bundler-audit-report.json ]; then
119+ echo "Bundler audit found $(jq '.vulnerabilities | length' bundler-audit-report.json) vulnerabilities"
120+ fi
121+
122+ - name : Upload security reports
123+ uses : actions/upload-artifact@v4
124+ if : always()
125+ with :
126+ name : security-reports
127+ path : |
128+ brakeman-report.json
129+ bundler-audit-report.json
130+ retention-days : 30
74131
75132 deploy :
76133 needs : test
77134 runs-on : ubuntu-latest
78135 if : github.ref == 'refs/heads/main'
136+ timeout-minutes : 20
137+ environment :
138+ name : production
139+ url : https://${{ secrets.DROPLET_HOST }}
79140
80141 steps :
81- - uses : actions/checkout@v4
142+ - name : Checkout code
143+ uses : actions/checkout@v4
82144
83145 - name : Deploy to DigitalOcean
146+ id : deploy
8414785148 with :
86149 host : ${{ secrets.DROPLET_HOST }}
87150 username : deploy
88151 key : ${{ secrets.DEPLOY_SSH_KEY }}
152+ timeout : 900s
89153 script : |
154+ set -e
90155 cd /var/www/streamsource
156+
157+ # Set environment variables for deployment
158+ export GITHUB_REPOSITORY="${{ github.repository }}"
159+ export GITHUB_SHA="${{ github.sha }}"
160+ export GITHUB_REF="${{ github.ref }}"
161+
162+ # Run deployment with error handling
163+ echo "π Starting deployment..."
91164 ./deploy/github-deploy.sh
165+
166+ echo "β
Deployment completed successfully"
92167
93- - name : Health check
168+ - name : Comprehensive health check
94169 run : |
170+ echo "π₯ Running comprehensive health checks..."
171+
172+ # Wait for application to stabilize
95173 sleep 30
96- curl -f https://${{ secrets.DROPLET_HOST }}/health || exit 1
174+
175+ # Test multiple endpoints
176+ echo "Testing basic health endpoint..."
177+ curl -f -s https://${{ secrets.DROPLET_HOST }}/health || exit 1
178+
179+ echo "Testing database connectivity..."
180+ curl -f -s https://${{ secrets.DROPLET_HOST }}/health/db || exit 1
181+
182+ echo "Testing Redis connectivity..."
183+ curl -f -s https://${{ secrets.DROPLET_HOST }}/health/redis || exit 1
184+
185+ echo "Testing application responsiveness..."
186+ RESPONSE_TIME=$(curl -w "%{time_total}" -s -o /dev/null https://${{ secrets.DROPLET_HOST }}/health)
187+ echo "Response time: ${RESPONSE_TIME}s"
188+
189+ # Fail if response time is too slow (> 5 seconds)
190+ if (( $(echo "$RESPONSE_TIME > 5.0" | bc -l) )); then
191+ echo "β Application is responding too slowly ($RESPONSE_TIME seconds)"
192+ exit 1
193+ fi
194+
195+ echo "β
All health checks passed"
97196
197+ - name : Rollback on failure
198+ if : failure() && steps.deploy.conclusion == 'failure'
199+ 200+ with :
201+ host : ${{ secrets.DROPLET_HOST }}
202+ username : deploy
203+ key : ${{ secrets.DEPLOY_SSH_KEY }}
204+ script : |
205+ cd /var/www/streamsource
206+ echo "π Initiating automatic rollback..."
207+ ./deploy/rollback.sh
208+ echo "β
Rollback completed"
209+ continue-on-error : true
210+
98211 - name : Notify deployment status
99212 if : always()
100213 uses : 8398a7/action-slack@v3
101214 with :
102215 status : ${{ job.status }}
103- text : ' StreamSource deployment ${{ job.status }}'
104216 webhook_url : ${{ secrets.SLACK_WEBHOOK }}
105- continue-on-error : true
217+ text : |
218+ StreamSource deployment ${{ job.status }}
219+
220+ π *Deployment Details:*
221+ β’ Commit: `${{ github.sha }}`
222+ β’ Branch: `${{ github.ref_name }}`
223+ β’ Author: ${{ github.actor }}
224+ β’ Workflow: ${{ github.workflow }}
225+
226+ ${{ job.status == 'success' && 'β
Deployment successful!' || 'β Deployment failed - automatic rollback initiated' }}
227+
228+ π [View Workflow Run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
229+ continue-on-error : true
230+
231+ - name : Record deployment metrics
232+ if : always()
233+ run : |
234+ echo "π Recording deployment metrics..."
235+
236+ # Create deployment record
237+ curl -X POST "https://api.github.com/repos/${{ github.repository }}/deployments" \
238+ -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
239+ -H "Content-Type: application/json" \
240+ -d '{
241+ "ref": "${{ github.sha }}",
242+ "environment": "production",
243+ "description": "Deployment via GitHub Actions",
244+ "auto_merge": false
245+ }' || echo "Failed to record deployment"
246+
247+ echo "β
Deployment metrics recorded"
0 commit comments