Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 48 additions & 24 deletions .github/workflows/continuous-delivery.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ jobs:
name: Branch Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1

- name: Validate branch
env:
TARGET_ENV: ${{ github.event.inputs.target_env }}
Expand All @@ -41,11 +44,19 @@ jobs:
echo 'This workflow can only be run on branches staging and master.'
exit 1
fi
if [ "$TARGET_ENV" == 'luxadmosam' ] || [ "$TARGET_ENV" == 'euros' ]; then
if [ "$GITHUB_REF_NAME" != 'master' ]; then
echo 'Only the master branch can be deployed to external parties.'
exit 1
fi
# Check branch restriction from deploy_targets.yml
BRANCH_RESTRICTION=$(python3 << 'PYTHON_EOF'
import yaml
with open('config/deploy_targets.yml', 'r') as f:
config = yaml.safe_load(f)
target = config['targets']['${{ github.event.inputs.target_env }}']
restriction = target.get('branch_restriction')
print(restriction if restriction else '')
PYTHON_EOF
)
if [ -n "$BRANCH_RESTRICTION" ] && [ "$GITHUB_REF_NAME" != "$BRANCH_RESTRICTION" ]; then
echo "Target $TARGET_ENV can only be deployed from branch $BRANCH_RESTRICTION, but current branch is $GITHUB_REF_NAME."
exit 1
fi

metadata:
Expand Down Expand Up @@ -74,18 +85,25 @@ jobs:
echo 'has_diff=false' >> "$GITHUB_OUTPUT"
fi
fi

if [ "$TARGET_ENV" == 'luxadmosam' ]; then
echo 'stage=luxproduction' >> "$GITHUB_OUTPUT"
elif [ "$TARGET_ENV" == 'euros' ]; then
echo 'stage=euros' >> "$GITHUB_OUTPUT"
else
echo 'stage=production' >> "$GITHUB_OUTPUT"
fi
else
echo 'stage=staging' >> "$GITHUB_OUTPUT"
fi

# Get stage from deploy_targets.yml
STAGE=$(python3 << 'PYTHON_EOF'
import yaml
with open('config/deploy_targets.yml', 'r') as f:
config = yaml.safe_load(f)
target_env = '${{ github.event.inputs.target_env }}'
current_branch = '${{ github.ref_name }}'
# If on staging branch, always use staging stage unless targeting external party
if current_branch == 'staging':
print('staging')
else:
# On master: use the stage from the target environment
print(config['targets'][target_env]['stage'])
PYTHON_EOF
)
echo "stage=$STAGE" >> "$GITHUB_OUTPUT"

merge:
name: Merge
runs-on: ubuntu-latest
Expand Down Expand Up @@ -162,15 +180,21 @@ jobs:
env:
TARGET_ENV: ${{ github.event.inputs.target_env }}
run: |
if [ "$TARGET_ENV" == 'luxadmosam' ] && [ "$GITHUB_REF_NAME" = 'master' ]; then
echo 'environment_url=https://luxstreep.csvalpha.nl' >> "$GITHUB_OUTPUT"
elif [ "$TARGET_ENV" == 'euros' ] && [ "$GITHUB_REF_NAME" = 'master' ]; then
echo 'environment_url=https://euros.csvalpha.nl' >> "$GITHUB_OUTPUT"
elif [ "$GITHUB_REF_NAME" = 'master' ]; then
echo 'environment_url=https://streep.csvalpha.nl' >> "$GITHUB_OUTPUT"
else
echo 'environment_url=https://stagingstreep.csvalpha.nl' >> "$GITHUB_OUTPUT"
fi
# Get URL from deploy_targets.yml based on current branch and target
URL=$(python3 << 'PYTHON_EOF'
import yaml
with open('config/deploy_targets.yml', 'r') as f:
config = yaml.safe_load(f)
current_branch = '${{ github.ref_name }}'
target_env = '${{ github.event.inputs.target_env }}'
# If on staging, use stagingstreep URL; otherwise use the target's URL
if current_branch == 'staging':
print(config['targets']['stagingstreep']['url'])
else:
print(config['targets'][target_env]['url'])
PYTHON_EOF
)
echo "environment_url=$URL" >> "$GITHUB_OUTPUT"

- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ WORKDIR /app

# Pre-install gems, so that they can be cached.
COPY Gemfile* /app/
RUN if [ "$RAILS_ENV" = 'production' ] || [ "$RAILS_ENV" = 'staging' ] || [ "$RAILS_ENV" = 'luxproduction' ] || [ "$RAILS_ENV" = 'euros' ]; then \
RUN if [ "$RAILS_ENV" != 'development' ] && [ "$RAILS_ENV" != 'test' ]; then \
bundle config set --local without 'development test'; \
else \
bundle config set --local without 'development'; \
Expand All @@ -43,7 +43,7 @@ RUN yarn install --immutable
COPY . /app/

# Precompile assets after copying app because whole Rails pipeline is needed.
RUN if [ "$RAILS_ENV" = 'production' ] || [ "$RAILS_ENV" = 'staging' ] || [ "$RAILS_ENV" = 'luxproduction' ] || [ "$RAILS_ENV" = 'euros' ]; then \
RUN if [ "$RAILS_ENV" != 'development' ] && [ "$RAILS_ENV" != 'test' ]; then \
SECRET_KEY_BASE_DUMMY=1 bundle exec rails assets:precompile; \
else \
echo "Skipping assets:precompile"; \
Expand Down
4 changes: 1 addition & 3 deletions app/controllers/credit_mutations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ def create # rubocop:disable Metrics/MethodLength, Metrics/AbcSize

respond_to do |format|
if @mutation.save
if Rails.env.production? || Rails.env.staging? || Rails.env.luxproduction? || Rails.env.euros?
NewCreditMutationNotificationJob.perform_later(@mutation)
end
NewCreditMutationNotificationJob.perform_later(@mutation) unless Rails.env.local?
format.html { redirect_to which_redirect?, flash: { success: 'Inleg of mutatie aangemaakt' } }
format.json do
render json: @mutation, include: { user: { methods: User.orderscreen_json_includes } }
Expand Down
2 changes: 1 addition & 1 deletion app/jobs/credit_insufficient_notification_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def send_notification_delivery_reports(success_count, unnotifyable_users)
).deliver_later
end

return unless Rails.env.production? || Rails.env.staging? || Rails.env.luxproduction? || Rails.env.euros?
return if Rails.env.local?

HealthCheckJob.perform_later('credit_insufficient')
end
Expand Down
2 changes: 1 addition & 1 deletion app/jobs/payment_poll_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def perform
# it will be checked again the next time this poll job runs
end

return unless Rails.env.production? || Rails.env.staging? || Rails.env.luxproduction? || Rails.env.euros?
return if Rails.env.local?

HealthCheckJob.perform_later('payment_poll')
end
Expand Down
4 changes: 2 additions & 2 deletions app/views/partials/_footer.html.erb
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<footer class="footer d-flex justify-content-between">
<span class="text-danger text-uppercase fw-bold mx-2">
<% if Rails.application.config.x.sofia_host == 'stagingstreep.csvalpha.nl' %>
<% if Rails.env.staging? %>
For demo and testing purposes only
<% 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' %>
<% elsif Rails.env.development? %>
Development mode
<% end %>
</span>
Expand Down
21 changes: 8 additions & 13 deletions config/deploy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,17 @@
# This file is for mina to be able to connect to the rails console on the server

require 'mina/rails'
require 'yaml'
import 'lib/mina/tasks/rails.rake'

set :domain, 'ssh.csvalpha.nl'

task :staging do
set :deploy_to, '/opt/docker/sofia/staging'
end

task :production do
set :deploy_to, '/opt/docker/sofia/production'
end

task :luxproduction do
set :deploy_to, '/opt/docker/sofia/luxproduction'
end
# Load deployment targets from config/deploy_targets.yml
deploy_targets = YAML.load_file(File.expand_path('deploy_targets.yml', __dir__))['targets']

task :euros do
set :deploy_to, '/opt/docker/sofia/euros'
# Dynamically create mina tasks for each deployment target
deploy_targets.each do |target_name, config|
task target_name.to_sym do
set :deploy_to, config['deploy_path']
end
end
49 changes: 49 additions & 0 deletions config/deploy_targets.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Deployment Targets Configuration
#
# This file defines all deployment targets for the Sofia application.
# Each target specifies the deployment location, stage, hostname, and URL.
#
# To add a new deployment target:
# 1. Add a new entry below with the target name as the key (deployment identifier)
# 2. Set deploy_path to the docker directory path on the server
# 3. Set stage to the Rails environment (production or staging)
# 4. Set hostname to the application's domain
# 5. Set url to the HTTPS URL for GitHub Actions deployment tracking
# 6. Set branch_restriction to limit deployments to specific branches
# 7. Set allow_targets to restrict which deployment systems can use this target
#
# After adding a deployment target:
# - Copy the .env and docker-compose files to the deploy_path on the server
# - Setup TransIP DNS records to point to the server's IP
targets:
csvalpha:
deploy_path: /opt/docker/sofia/production
stage: production
hostname: streep.csvalpha.nl
url: https://streep.csvalpha.nl
branch_restriction: master # Only from master branch
allow_targets: csvalpha

stagingstreep:
deploy_path: /opt/docker/sofia/staging
stage: staging
hostname: stagingstreep.csvalpha.nl
url: https://stagingstreep.csvalpha.nl
branch_restriction: staging # Only from staging branch
allow_targets: csvalpha

luxadmosam:
deploy_path: /opt/docker/sofia/luxproduction
stage: luxproduction
hostname: luxstreep.csvalpha.nl
url: https://luxstreep.csvalpha.nl
branch_restriction: master # Only from master branch
allow_targets: luxadmosam

euros:
deploy_path: /opt/docker/sofia/euros
stage: euros
hostname: euros.csvalpha.nl
url: https://euros.csvalpha.nl
branch_restriction: master # Only from master branch
allow_targets: euros
5 changes: 4 additions & 1 deletion config/initializers/sentry.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Load enabled environments from deploy_targets.yml
deploy_targets = YAML.load_file(Rails.root.join('config', 'deploy_targets.yml'))['targets']

Sentry.init do |config|
config.dsn = Rails.application.config.x.sentry_dsn
config.enabled_environments = %w[production staging luxproduction euros]
config.enabled_environments = deploy_targets.keys.map(&:to_sym)
config.environment = Rails.env
config.release = ENV.fetch('BUILD_HASH', nil)
end
4 changes: 1 addition & 3 deletions spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
require File.expand_path('../config/environment', __dir__)
# Prevent database truncation if the environment is production
# rubocop:disable Rails/Exit
if Rails.env.production? || Rails.env.staging? || Rails.env.luxproduction? || Rails.env.euros?
abort('The Rails environment is running in production mode!')
end
abort('The Rails environment is running in production mode!') unless Rails.env.local?
# rubocop:enable Rails/Exit
require 'rspec/rails'
# Add additional requires below this line. Rails is not loaded until this point!
Expand Down