Skip to content

Commit d578ea4

Browse files
lodewigesCopilot
andauthored
make it easier to deploy a new env (#1176)
* make it easier to deploy a new env * simplify logic * remove EnvironmentAware * remove more random stuff * made sentry.rb more readable * use only 2 enviroments * make logic more readable * i could not simplfy it 2 env * fix lint * Fix branch restriction condition in CI workflow * Update config/initializers/sentry.rb Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update config/deploy.rb Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update config/initializers/sentry.rb Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Fix a lot of suggestions * fix lint * fix lint * fix lint 2/2 --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 1cc364c commit d578ea4

10 files changed

Lines changed: 125 additions & 55 deletions

File tree

.github/workflows/continuous-delivery.yml

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ jobs:
3333
name: Branch Check
3434
runs-on: ubuntu-latest
3535
steps:
36+
- name: Checkout code
37+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
38+
3639
- name: Validate branch
3740
env:
3841
TARGET_ENV: ${{ github.event.inputs.target_env }}
@@ -41,11 +44,19 @@ jobs:
4144
echo 'This workflow can only be run on branches staging and master.'
4245
exit 1
4346
fi
44-
if [ "$TARGET_ENV" == 'luxadmosam' ] || [ "$TARGET_ENV" == 'euros' ]; then
45-
if [ "$GITHUB_REF_NAME" != 'master' ]; then
46-
echo 'Only the master branch can be deployed to external parties.'
47-
exit 1
48-
fi
47+
# Check branch restriction from deploy_targets.yml
48+
BRANCH_RESTRICTION=$(python3 << 'PYTHON_EOF'
49+
import yaml
50+
with open('config/deploy_targets.yml', 'r') as f:
51+
config = yaml.safe_load(f)
52+
target = config['targets']['${{ github.event.inputs.target_env }}']
53+
restriction = target.get('branch_restriction')
54+
print(restriction if restriction else '')
55+
PYTHON_EOF
56+
)
57+
if [ -n "$BRANCH_RESTRICTION" ] && [ "$GITHUB_REF_NAME" != "$BRANCH_RESTRICTION" ]; then
58+
echo "Target $TARGET_ENV can only be deployed from branch $BRANCH_RESTRICTION, but current branch is $GITHUB_REF_NAME."
59+
exit 1
4960
fi
5061
5162
metadata:
@@ -74,18 +85,25 @@ jobs:
7485
echo 'has_diff=false' >> "$GITHUB_OUTPUT"
7586
fi
7687
fi
77-
78-
if [ "$TARGET_ENV" == 'luxadmosam' ]; then
79-
echo 'stage=luxproduction' >> "$GITHUB_OUTPUT"
80-
elif [ "$TARGET_ENV" == 'euros' ]; then
81-
echo 'stage=euros' >> "$GITHUB_OUTPUT"
82-
else
83-
echo 'stage=production' >> "$GITHUB_OUTPUT"
84-
fi
85-
else
86-
echo 'stage=staging' >> "$GITHUB_OUTPUT"
8788
fi
8889
90+
# Get stage from deploy_targets.yml
91+
STAGE=$(python3 << 'PYTHON_EOF'
92+
import yaml
93+
with open('config/deploy_targets.yml', 'r') as f:
94+
config = yaml.safe_load(f)
95+
target_env = '${{ github.event.inputs.target_env }}'
96+
current_branch = '${{ github.ref_name }}'
97+
# If on staging branch, always use staging stage unless targeting external party
98+
if current_branch == 'staging':
99+
print('staging')
100+
else:
101+
# On master: use the stage from the target environment
102+
print(config['targets'][target_env]['stage'])
103+
PYTHON_EOF
104+
)
105+
echo "stage=$STAGE" >> "$GITHUB_OUTPUT"
106+
89107
merge:
90108
name: Merge
91109
runs-on: ubuntu-latest
@@ -157,25 +175,31 @@ jobs:
157175
inputs.merge && fromJSON(needs.metadata.outputs.has_diff) || github.event.inputs.ignore_metadata_diff && success()) ||
158176
((!inputs.merge|| !fromJSON(needs.metadata.outputs.has_diff)) || github.event.inputs.ignore_metadata_diff && !cancelled()))
159177
steps:
178+
- name: Checkout code
179+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
180+
with:
181+
ref: ${{ needs.merge.outputs.sha }}
182+
160183
- name: Get environment URL
161184
id: get_url
162185
env:
163186
TARGET_ENV: ${{ github.event.inputs.target_env }}
164187
run: |
165-
if [ "$TARGET_ENV" == 'luxadmosam' ] && [ "$GITHUB_REF_NAME" = 'master' ]; then
166-
echo 'environment_url=https://luxstreep.csvalpha.nl' >> "$GITHUB_OUTPUT"
167-
elif [ "$TARGET_ENV" == 'euros' ] && [ "$GITHUB_REF_NAME" = 'master' ]; then
168-
echo 'environment_url=https://euros.csvalpha.nl' >> "$GITHUB_OUTPUT"
169-
elif [ "$GITHUB_REF_NAME" = 'master' ]; then
170-
echo 'environment_url=https://streep.csvalpha.nl' >> "$GITHUB_OUTPUT"
171-
else
172-
echo 'environment_url=https://stagingstreep.csvalpha.nl' >> "$GITHUB_OUTPUT"
173-
fi
174-
175-
- name: Checkout code
176-
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
177-
with:
178-
ref: ${{ needs.merge.outputs.sha }}
188+
# Get URL from deploy_targets.yml based on current branch and target
189+
URL=$(python3 << 'PYTHON_EOF'
190+
import yaml
191+
with open('config/deploy_targets.yml', 'r') as f:
192+
config = yaml.safe_load(f)
193+
current_branch = '${{ github.ref_name }}'
194+
target_env = '${{ github.event.inputs.target_env }}'
195+
# If on staging, use stagingstreep URL; otherwise use the target's URL
196+
if current_branch == 'staging':
197+
print(config['targets']['stagingstreep']['url'])
198+
else:
199+
print(config['targets'][target_env]['url'])
200+
PYTHON_EOF
201+
)
202+
echo "environment_url=$URL" >> "$GITHUB_OUTPUT"
179203
180204
- name: Start deployment
181205
uses: bobheadxi/deployments@648679e8e4915b27893bd7dbc35cb504dc915bc8 # v1.5.0

Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ WORKDIR /app
2828

2929
# Pre-install gems, so that they can be cached.
3030
COPY Gemfile* /app/
31-
RUN if [ "$RAILS_ENV" = 'production' ] || [ "$RAILS_ENV" = 'staging' ] || [ "$RAILS_ENV" = 'luxproduction' ] || [ "$RAILS_ENV" = 'euros' ]; then \
31+
RUN if [ "$RAILS_ENV" != 'development' ] && [ "$RAILS_ENV" != 'test' ]; then \
3232
bundle config set --local without 'development test'; \
33-
else \
33+
elif [ "$RAILS_ENV" != 'test' ]; then \
3434
bundle config set --local without 'development'; \
3535
fi
3636
RUN bundle install
@@ -43,7 +43,7 @@ RUN yarn install --immutable
4343
COPY . /app/
4444

4545
# Precompile assets after copying app because whole Rails pipeline is needed.
46-
RUN if [ "$RAILS_ENV" = 'production' ] || [ "$RAILS_ENV" = 'staging' ] || [ "$RAILS_ENV" = 'luxproduction' ] || [ "$RAILS_ENV" = 'euros' ]; then \
46+
RUN if [ "$RAILS_ENV" != 'development' ] && [ "$RAILS_ENV" != 'test' ]; then \
4747
SECRET_KEY_BASE_DUMMY=1 bundle exec rails assets:precompile; \
4848
else \
4949
echo "Skipping assets:precompile"; \

app/controllers/credit_mutations_controller.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ def create # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
1919

2020
respond_to do |format|
2121
if @mutation.save
22-
if Rails.env.production? || Rails.env.staging? || Rails.env.luxproduction? || Rails.env.euros?
23-
NewCreditMutationNotificationJob.perform_later(@mutation)
24-
end
22+
NewCreditMutationNotificationJob.perform_later(@mutation) unless Rails.env.local?
2523
format.html { redirect_to which_redirect?, flash: { success: 'Inleg of mutatie aangemaakt' } }
2624
format.json do
2725
render json: @mutation, include: { user: { methods: User.orderscreen_json_includes } }

app/jobs/credit_insufficient_notification_job.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def send_notification_delivery_reports(success_count, unnotifyable_users)
3030
).deliver_later
3131
end
3232

33-
return unless Rails.env.production? || Rails.env.staging? || Rails.env.luxproduction? || Rails.env.euros?
33+
return if Rails.env.local?
3434

3535
HealthCheckJob.perform_later('credit_insufficient')
3636
end

app/jobs/payment_poll_job.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def perform
99
# it will be checked again the next time this poll job runs
1010
end
1111

12-
return unless Rails.env.production? || Rails.env.staging? || Rails.env.luxproduction? || Rails.env.euros?
12+
return if Rails.env.local?
1313

1414
HealthCheckJob.perform_later('payment_poll')
1515
end

app/views/partials/_footer.html.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<footer class="footer d-flex justify-content-between">
22
<span class="text-danger text-uppercase fw-bold mx-2">
3-
<% if Rails.application.config.x.sofia_host == 'stagingstreep.csvalpha.nl' %>
3+
<% if Rails.env.staging? %>
44
For demo and testing purposes only
5-
<% elsif Rails.application.config.x.sofia_host != 'streep.csvalpha.nl' && Rails.application.config.x.sofia_host != 'luxstreep.csvalpha.nl' && Rails.application.config.x.sofia_host != 'euros.csvalpha.nl' %>
5+
<% elsif Rails.env.development? %>
66
Development mode
77
<% end %>
88
</span>

config/deploy.rb

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,20 @@
22
# This file is for mina to be able to connect to the rails console on the server
33

44
require 'mina/rails'
5+
require 'yaml'
56
import 'lib/mina/tasks/rails.rake'
67

78
set :domain, 'ssh.csvalpha.nl'
89

9-
task :staging do
10-
set :deploy_to, '/opt/docker/sofia/staging'
11-
end
12-
13-
task :production do
14-
set :deploy_to, '/opt/docker/sofia/production'
15-
end
10+
# Load deployment targets from config/deploy_targets.yml
11+
deploy_targets_path = File.expand_path('deploy_targets.yml', __dir__)
12+
deploy_config = YAML.safe_load_file(deploy_targets_path, permitted_classes: [], permitted_symbols: [], aliases: false)
1613

17-
task :luxproduction do
18-
set :deploy_to, '/opt/docker/sofia/luxproduction'
19-
end
14+
deploy_targets = deploy_config['targets']
2015

21-
task :euros do
22-
set :deploy_to, '/opt/docker/sofia/euros'
16+
# Dynamically create mina tasks for each deployment target
17+
deploy_targets.each do |target_name, config|
18+
task target_name.to_sym do
19+
set :deploy_to, config['deploy_path']
20+
end
2321
end

config/deploy_targets.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Deployment Targets Configuration
2+
#
3+
# This file defines all deployment targets for the Sofia application.
4+
# Each target specifies the deployment location, stage, hostname, and URL.
5+
#
6+
# To add a new deployment target:
7+
# 1. Add a new entry below with the target name as the key (deployment identifier)
8+
# 2. Set deploy_path to the docker directory path on the server
9+
# 3. Set stage to the Rails environment (production or staging)
10+
# 4. Set hostname to the application's domain
11+
# 5. Set url to the HTTPS URL for GitHub Actions deployment tracking
12+
# 6. Set branch_restriction to limit deployments to specific branches
13+
# 7. Set allow_targets to restrict which deployment systems can use this target
14+
#
15+
# After adding a deployment target:
16+
# - Copy the .env and docker-compose files to the deploy_path on the server
17+
# - Setup TransIP DNS records to point to the server's IP
18+
targets:
19+
csvalpha:
20+
deploy_path: /opt/docker/sofia/production
21+
stage: production
22+
hostname: streep.csvalpha.nl
23+
url: https://streep.csvalpha.nl
24+
branch_restriction: master
25+
26+
stagingstreep:
27+
deploy_path: /opt/docker/sofia/staging
28+
stage: staging
29+
hostname: stagingstreep.csvalpha.nl
30+
url: https://stagingstreep.csvalpha.nl
31+
branch_restriction: staging
32+
33+
luxadmosam:
34+
deploy_path: /opt/docker/sofia/luxproduction
35+
stage: luxproduction
36+
hostname: luxstreep.csvalpha.nl
37+
url: https://luxstreep.csvalpha.nl
38+
branch_restriction: master
39+
40+
euros:
41+
deploy_path: /opt/docker/sofia/euros
42+
stage: euros
43+
hostname: euros.csvalpha.nl
44+
url: https://euros.csvalpha.nl
45+
branch_restriction: master

config/initializers/sentry.rb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
1+
# Load enabled environments from deploy_targets.yml
2+
deploy_targets_path = Rails.root.join('config', 'deploy_targets.yml')
3+
deploy_targets = {}
4+
5+
raw_config = YAML.load_file(deploy_targets_path)
6+
deploy_targets = raw_config['targets'] if raw_config.is_a?(Hash) && raw_config['targets'].is_a?(Hash)
7+
18
Sentry.init do |config|
29
config.dsn = Rails.application.config.x.sentry_dsn
3-
config.enabled_environments = %w[production staging luxproduction euros]
10+
config.enabled_environments = deploy_targets.values.filter_map { |target| target['stage'] }.uniq.map(&:to_sym)
411
config.environment = Rails.env
512
config.release = ENV.fetch('BUILD_HASH', nil)
613
end

spec/rails_helper.rb

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
require File.expand_path('../config/environment', __dir__)
77
# Prevent database truncation if the environment is production
88
# rubocop:disable Rails/Exit
9-
if Rails.env.production? || Rails.env.staging? || Rails.env.luxproduction? || Rails.env.euros?
10-
abort('The Rails environment is running in production mode!')
11-
end
9+
abort('The Rails environment is running in production mode!') unless Rails.env.local?
1210
# rubocop:enable Rails/Exit
1311
require 'rspec/rails'
1412
# Add additional requires below this line. Rails is not loaded until this point!

0 commit comments

Comments
 (0)