-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2149 from DFE-Digital/sync-configuration
Sync country, region and english language provider configuration
- Loading branch information
Showing
6 changed files
with
405 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
name: Synchronise configuration | ||
|
||
on: workflow_dispatch | ||
|
||
jobs: | ||
export: | ||
name: Export from production | ||
runs-on: ubuntu-latest | ||
|
||
environment: production | ||
|
||
outputs: | ||
output1: ${{ steps.step1.outputs.test }} | ||
output2: ${{ steps.step2.outputs.test }} | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- uses: Azure/login@v2 | ||
with: | ||
creds: ${{ secrets.AZURE_CREDENTIALS }} | ||
|
||
- uses: ./.github/actions/set-kubernetes-credentials | ||
with: | ||
environment: production | ||
azure-credentials: ${{ secrets.AZURE_CREDENTIALS }} | ||
|
||
- name: Get pod name | ||
id: pod-name | ||
run: | | ||
echo "value=$(kubectl get pod \ | ||
-n tra-production \ | ||
-l app=apply-for-qts-production-web \ | ||
-o jsonpath="{.items[0].metadata.name}")" >> $GITHUB_OUTPUT | ||
- name: Export configuration data | ||
run: | | ||
kubectl exec \ | ||
-n tra-production \ | ||
${{ steps.pod-name.outputs.value }} \ | ||
-- sh -c "cd /app && /usr/local/bin/bundle exec rails configuration_sync:export[data.json]" | ||
- name: Copy configuration data | ||
run: | | ||
kubectl cp \ | ||
-n tra-production \ | ||
${{ steps.pod-name.outputs.value }}:data.json \ | ||
data.json | ||
- name: Upload configuration data | ||
uses: actions/upload-artifact@v4 | ||
with: | ||
name: data | ||
path: data.json | ||
retention-days: 3 | ||
|
||
import: | ||
name: Export from production | ||
runs-on: ubuntu-latest | ||
|
||
strategy: | ||
matrix: | ||
environment: [development, test] | ||
|
||
environment: ${{ matrix.environment }} | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- uses: Azure/login@v2 | ||
with: | ||
creds: ${{ secrets.AZURE_CREDENTIALS }} | ||
|
||
- uses: ./.github/actions/set-kubernetes-credentials | ||
with: | ||
environment: ${{ matrix.environment }} | ||
azure-credentials: ${{ secrets.AZURE_CREDENTIALS }} | ||
|
||
- name: Download configuration data | ||
uses: actions/download-artifact@v4 | ||
with: | ||
name: data | ||
|
||
- name: Get pod name | ||
id: pod-name | ||
run: | | ||
echo "value=$(kubectl get pod \ | ||
-n tra-${{ matrix.environment }} \ | ||
-l app=apply-for-qts-${{ matrix.environment }}-web \ | ||
-o jsonpath="{.items[0].metadata.name}")" >> $GITHUB_OUTPUT | ||
- name: Copy configuration data | ||
run: | | ||
kubectl cp \ | ||
-n tra-${{ matrix.environment }} \ | ||
data.json \ | ||
${{ steps.pod-name.outputs.value }}:data.json | ||
- name: Import configuration data | ||
run: | | ||
kubectl exec \ | ||
-n tra-${{ matrix.environment }} \ | ||
${{ steps.pod-name.outputs.value }} \ | ||
-- sh -c "cd /app && /usr/local/bin/bundle exec rails configuration_sync:import[data.json]" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# frozen_string_literal: true | ||
|
||
class ConfigurationSync::Exporter | ||
include ServicePattern | ||
|
||
def initialize(file:) | ||
@file = file | ||
end | ||
|
||
def call | ||
file.write(serialise.to_json) | ||
end | ||
|
||
private | ||
|
||
attr_reader :file | ||
|
||
def serialise | ||
{ | ||
countries: Country.all.map { |country| serialise_country(country) }, | ||
english_language_providers: | ||
EnglishLanguageProvider.all.map do |english_language_provider| | ||
serialise_english_language_provider(english_language_provider) | ||
end, | ||
regions: | ||
Region.includes(:country).map { |region| serialise_region(region) }, | ||
} | ||
end | ||
|
||
def serialise_country(country) | ||
{ | ||
code: country.code, | ||
eligibility_enabled: country.eligibility_enabled, | ||
eligibility_skip_questions: country.eligibility_skip_questions, | ||
other_information: country.other_information, | ||
qualifications_information: country.qualifications_information, | ||
sanction_information: country.sanction_information, | ||
status_information: country.status_information, | ||
subject_limited: country.subject_limited, | ||
} | ||
end | ||
|
||
def serialise_english_language_provider(english_language_provider) | ||
{ | ||
accepted_tests: english_language_provider.accepted_tests, | ||
b2_level_requirement: english_language_provider.b2_level_requirement, | ||
b2_level_requirement_prefix: | ||
english_language_provider.b2_level_requirement_prefix, | ||
check_url: english_language_provider.check_url, | ||
name: english_language_provider.name, | ||
reference_hint: english_language_provider.reference_hint, | ||
reference_name: english_language_provider.reference_name, | ||
url: english_language_provider.url, | ||
} | ||
end | ||
|
||
def serialise_region(region) | ||
{ | ||
application_form_skip_work_history: | ||
region.application_form_skip_work_history, | ||
country_code: region.country.code, | ||
name: region.name, | ||
other_information: region.other_information, | ||
qualifications_information: region.qualifications_information, | ||
reduced_evidence_accepted: region.reduced_evidence_accepted, | ||
sanction_check: region.sanction_check, | ||
sanction_information: region.sanction_information, | ||
status_check: region.status_check, | ||
status_information: region.status_information, | ||
teaching_authority_address: region.teaching_authority_address, | ||
teaching_authority_certificate: region.teaching_authority_certificate, | ||
teaching_authority_emails: region.teaching_authority_emails, | ||
teaching_authority_name: region.teaching_authority_name, | ||
teaching_authority_online_checker_url: | ||
region.teaching_authority_online_checker_url, | ||
teaching_authority_provides_written_statement: | ||
region.teaching_authority_provides_written_statement, | ||
teaching_authority_requires_submission_email: | ||
region.teaching_authority_requires_submission_email, | ||
teaching_authority_websites: region.teaching_authority_websites, | ||
written_statement_optional: region.written_statement_optional, | ||
} | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# frozen_string_literal: true | ||
|
||
class ConfigurationSync::Importer | ||
include ServicePattern | ||
|
||
def initialize(file:) | ||
@data = JSON.parse(file.read).deep_symbolize_keys | ||
end | ||
|
||
def call | ||
data[:countries].each { |record| deserialise_country(record) } | ||
|
||
data[:english_language_providers].each do |record| | ||
deserialise_english_language_provider(record) | ||
end | ||
|
||
data[:regions].each { |record| deserialise_region(record) } | ||
end | ||
|
||
private | ||
|
||
attr_reader :data | ||
|
||
def deserialise_country(record) | ||
Country.find_or_initialize_by(code: record[:code]).update!( | ||
record.except(:code), | ||
) | ||
end | ||
|
||
def deserialise_english_language_provider(record) | ||
EnglishLanguageProvider.find_or_initialize_by(name: record[:name]).update!( | ||
record.except(:name), | ||
) | ||
end | ||
|
||
def deserialise_region(record) | ||
country = Country.find_by!(code: record[:country_code]) | ||
Region.find_or_initialize_by(country:, name: record[:name]).update!( | ||
record.except(:country_code, :name), | ||
) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# frozen_string_literal: true | ||
|
||
namespace :configuration_sync do | ||
desc "Export countries, regions and english language providers." | ||
task :export, %i[filename] => :environment do |_task, args| | ||
File.open(args[:filename], "w") do |file| | ||
ConfigurationSync::Exporter.call(file:) | ||
end | ||
end | ||
|
||
desc "Import countries, regions and english language providers." | ||
task :import, %i[filename] => :environment do |_task, args| | ||
if HostingEnvironment.production? | ||
raise "This task cannot be run in production." | ||
end | ||
|
||
File.open(args[:filename], "r") do |file| | ||
ConfigurationSync::Importer.call(file:) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# frozen_string_literal: true | ||
|
||
require "rails_helper" | ||
|
||
RSpec.describe ConfigurationSync::Exporter do | ||
subject(:call) { described_class.call(file:) } | ||
|
||
let(:file) { StringIO.new } | ||
|
||
let(:parsed_file) do | ||
file.rewind | ||
JSON.parse(file.read) | ||
end | ||
|
||
before do | ||
country = create(:country, code: "FR") | ||
create(:region, country:, name: "Region") | ||
create(:english_language_provider, name: "Provider") | ||
end | ||
|
||
before { expect { call }.to_not raise_error } | ||
|
||
it "exports the countries" do | ||
expect(parsed_file).to include("countries") | ||
expect(parsed_file["countries"].first).to eq( | ||
{ | ||
"code" => "FR", | ||
"eligibility_enabled" => true, | ||
"eligibility_skip_questions" => false, | ||
"other_information" => "", | ||
"qualifications_information" => "", | ||
"sanction_information" => "", | ||
"status_information" => "", | ||
"subject_limited" => false, | ||
}, | ||
) | ||
end | ||
|
||
it "exports the english language providers" do | ||
expect(parsed_file).to include("english_language_providers") | ||
expect(parsed_file["english_language_providers"].first).to match( | ||
{ | ||
"accepted_tests" => a_kind_of(String), | ||
"b2_level_requirement" => a_kind_of(String), | ||
"b2_level_requirement_prefix" => a_kind_of(String), | ||
"check_url" => a_kind_of(String), | ||
"name" => "Provider", | ||
"reference_hint" => a_kind_of(String), | ||
"reference_name" => a_kind_of(String), | ||
"url" => a_kind_of(String), | ||
}, | ||
) | ||
end | ||
|
||
it "exports the regions" do | ||
expect(parsed_file).to include("regions") | ||
expect(parsed_file["regions"].first).to eq( | ||
{ | ||
"application_form_skip_work_history" => false, | ||
"country_code" => "FR", | ||
"name" => "Region", | ||
"other_information" => "", | ||
"qualifications_information" => "", | ||
"reduced_evidence_accepted" => false, | ||
"sanction_check" => "none", | ||
"sanction_information" => "", | ||
"status_check" => "none", | ||
"status_information" => "", | ||
"teaching_authority_address" => "", | ||
"teaching_authority_certificate" => "", | ||
"teaching_authority_emails" => [], | ||
"teaching_authority_name" => "", | ||
"teaching_authority_online_checker_url" => "", | ||
"teaching_authority_provides_written_statement" => false, | ||
"teaching_authority_requires_submission_email" => false, | ||
"teaching_authority_websites" => [], | ||
"written_statement_optional" => false, | ||
}, | ||
) | ||
end | ||
end |
Oops, something went wrong.