Skip to content
Merged
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
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,5 @@ PARDOT_SUBSCRIPTION_URL=
# https://developers.cloudflare.com/turnstile/troubleshooting/testing/.
CLOUDFLARE_TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA

HOSTNAME=localhost
HOSTNAME=localhost
LEARNER_EXPERIENCE_TESTS_DISPATCH_TOKEN=changeme
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
web: bundle exec puma -C config/puma.rb
release: bundle exec rails db:migrate && bundle exec rake projects:create_experience_cs_examples
release: bundle exec rails db:migrate && bundle exec rake projects:create_experience_cs_examples integration_tests:dispatch
worker: bundle exec good_job start --max-threads=8
47 changes: 47 additions & 0 deletions lib/tasks/integration_tests.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

namespace :integration_tests do
desc 'Trigger the learner-experience-integration-tests GitHub Actions workflow against the deployed test environment'
task dispatch: :environment do
next unless on_test_app?

response = connection.post(dispatch_url, dispatch_payload)
raise "GitHub dispatch API returned status #{response.status}" unless response.status == 204
rescue StandardError => e
Sentry.capture_exception(e)
end

def dispatch_url
'https://api.github.com/repos/RaspberryPiFoundation/learner-experience-integration-tests/dispatches'
end

def on_test_app?
ENV.fetch('HEROKU_APP_NAME') == 'editor-api-test'
end
Comment thread
zetter-rpf marked this conversation as resolved.

def connection
Faraday.new do |faraday|
faraday.request :json
faraday.headers = {
'Accept' => 'application/vnd.github+json',
'Authorization' => "Bearer #{ENV.fetch('LEARNER_EXPERIENCE_TESTS_DISPATCH_TOKEN')}"
}
end
end
Comment thread
zetter-rpf marked this conversation as resolved.

def dispatch_payload
sha = ENV.fetch('HEROKU_SLUG_COMMIT')

{
event_type: 'learner-experience-test',
client_payload: {
repo: 'editor-api',
sha:,
ref: 'main',
commit_message: "https://github.com/RaspberryPiFoundation/editor-api/commit/#{sha}",
deploy_url: ENV.fetch('HOST_URL'),
triggered_at: Time.now.utc.iso8601
}
}
end
end
116 changes: 116 additions & 0 deletions spec/lib/tasks/integration_tests_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# frozen_string_literal: true

require 'rails_helper'
require 'rake'

RSpec.describe 'integration_tests', type: :task do
describe ':dispatch' do
let(:task) { Rake::Task['integration_tests:dispatch'] }
let(:dispatch_url) { 'https://api.github.com/repos/RaspberryPiFoundation/learner-experience-integration-tests/dispatches' }
let(:heroku_app_name) { 'editor-api-test' }
let(:host_url) { 'https://test-editor-api.raspberrypi.org' }
let(:sha) { SecureRandom.hex(20) }
let(:token) { 'dispatch-token' }
let(:env) do
{
'HEROKU_APP_NAME' => heroku_app_name,
'HEROKU_SLUG_COMMIT' => sha,
'HOST_URL' => host_url,
'LEARNER_EXPERIENCE_TESTS_DISPATCH_TOKEN' => token
}
end

around { |example| ClimateControl.modify(env) { example.run } }

before do
stub_request(:post, dispatch_url).to_return(status: 204)
end

context 'when HEROKU_APP_NAME is editor-api-test' do
it 'dispatches the workflow with the expected payload and auth header' do
task.invoke

expect(WebMock).to have_requested(:post, dispatch_url)
.with(
headers: {
'Authorization' => "Bearer #{token}",
'Accept' => 'application/vnd.github+json'
},
body: {
event_type: 'learner-experience-test',
client_payload: {
repo: 'editor-api',
sha:,
ref: 'main',
commit_message: "https://github.com/RaspberryPiFoundation/editor-api/commit/#{sha}",
deploy_url: host_url,
triggered_at: /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z\z/
}
}
)
end
end

context 'when HEROKU_APP_NAME is not editor-api-test' do
let(:heroku_app_name) { 'editor-api-staging' }

it 'does not dispatch the workflow' do
task.invoke

expect(WebMock).not_to have_requested(:post, dispatch_url)
end
end
Comment thread
zetter-rpf marked this conversation as resolved.

context 'when a required env var is missing' do
let(:env) { super().merge('HEROKU_SLUG_COMMIT' => nil) }

it 'does not raise' do
expect { task.invoke }.not_to raise_error
end

it 'reports the error to Sentry' do
allow(Sentry).to receive(:capture_exception)

task.invoke

expect(Sentry).to have_received(:capture_exception).with(an_instance_of(KeyError))
end
end

context 'when the request fails' do
before do
stub_request(:post, dispatch_url).to_return(status: 500)
end

it 'does not raise' do
expect { task.invoke }.not_to raise_error
end

it 'reports the error to Sentry' do
allow(Sentry).to receive(:capture_exception)

task.invoke

expect(Sentry).to have_received(:capture_exception).with(an_instance_of(RuntimeError))
end
end

context 'when an unexpected error is raised' do
before do
allow_any_instance_of(Faraday::Connection).to receive(:post).and_raise(Faraday::ConnectionFailed, 'boom') # rubocop:disable RSpec/AnyInstance
end

it 'does not raise' do
expect { task.invoke }.not_to raise_error
end

it 'reports the error to Sentry' do
allow(Sentry).to receive(:capture_exception)

task.invoke

expect(Sentry).to have_received(:capture_exception).with(an_instance_of(Faraday::ConnectionFailed))
end
end
end
end
2 changes: 1 addition & 1 deletion spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
end

config.before(:suite) do
Rails.application.load_tasks
Rails.application.load_tasks if Rake::Task.tasks.empty?

db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).first
Rails.logger.debug { "Running tests in environment: #{Rails.env}" }
Expand Down
Loading