Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6964076
Default to live edition in dataloader specs
yndajas Feb 26, 2026
b544f9c
Use custom matcher in reverse dataloader spec
yndajas Feb 26, 2026
a7186c1
Rename have_links matcher have_reverse_links
mike3985 Jan 29, 2026
32ceaab
Test #live_content when only drafts are available
mike3985 Jan 2, 2026
914bea8
Bump draft factory's default user_facing_version
mike3985 Dec 31, 2025
a9bd65c
Support with_drafts flag in LinkedToEditionsSource
mike3985 Jan 2, 2026
082d71a
Support with_drafts flag in Reverse... dataloader
mike3985 Jan 2, 2026
fab1bf7
Make timestamps nullable to support drafts
mike3985 Jan 6, 2026
e2564c9
Remove some `content_store: "live"`s
mike3985 Jan 2, 2026
bed1e96
Replace QueryType content_store with with_drafts
mike3985 Dec 19, 2025
c7c2a03
Pass query's with_drafts setting to dataloaders
mike3985 Jan 2, 2026
733b5d7
Add with_drafts variable when generating queries
mike3985 Jan 6, 2026
388789d
Add with_drafts variable to all GraphQL queries
Dec 18, 2025
2399481
Default EditionFinderService to live content_store
mike3985 Jan 2, 2026
014d670
Find editions by base_path and with_drafts flag
mike3985 Jan 2, 2026
02b9372
Use shared examples in GraphQL controller spec
yndajas Mar 5, 2026
1d4d6bb
Introduce /graphql/draft draft content endpoint
mike3985 Dec 18, 2025
3e8b3ea
Check drafts in link expansion precedence tests
yndajas Feb 17, 2026
8862626
Check drafts in reverse link exp. precedence tests
yndajas Feb 25, 2026
4577adf
Speed up GraphQL link expansion integration tests
yndajas Feb 26, 2026
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
48 changes: 40 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ jobs:
- name: Setup Postgres
id: setup-postgres-graphql-direct-link-precedence-same-content-id
uses: alphagov/govuk-infrastructure/.github/actions/setup-postgres@main
with:
POSTGRES_DB: postgres-graphql-link-precedence

- name: Setup Redis
uses: alphagov/govuk-infrastructure/.github/actions/setup-redis@main
Expand All @@ -115,11 +117,17 @@ jobs:
TEST_DATABASE_URL: ${{ steps.setup-postgres-graphql-direct-link-precedence-same-content-id.outputs.db-url }}
run: bundle exec rails db:setup

- name: Run RSpec
- name: Prepare for parallel testing
env:
RAILS_ENV: test
TEST_DATABASE_URL: ${{ steps.setup-postgres-graphql-direct-link-precedence-same-content-id.outputs.db-url }}
run: bundle exec rake db:parallel:create db:parallel:prepare

- name: Run RSpec in parallel
env:
RAILS_ENV: test
TEST_DATABASE_URL: ${{ steps.setup-postgres-graphql-direct-link-precedence-same-content-id.outputs.db-url }}
run: bundle exec rspec spec/integration/graphql/link_expansion/direct_link_precedence_with_same_content_ids_spec.rb
run: bundle exec prspec spec/integration/graphql/link_expansion/direct_link_precedence_with_same_content_ids_spec.rb

test-graphql-direct-link-precedence-different-content-id:
name: "Test GraphQL direct link expansion precedence with different content IDs"
Expand All @@ -128,6 +136,8 @@ jobs:
- name: Setup Postgres
id: setup-postgres-graphql-direct-link-precedence-different-content-id
uses: alphagov/govuk-infrastructure/.github/actions/setup-postgres@main
with:
POSTGRES_DB: postgres-graphql-link-precedence

- name: Setup Redis
uses: alphagov/govuk-infrastructure/.github/actions/setup-redis@main
Expand All @@ -146,11 +156,17 @@ jobs:
TEST_DATABASE_URL: ${{ steps.setup-postgres-graphql-direct-link-precedence-different-content-id.outputs.db-url }}
run: bundle exec rails db:setup

- name: Run RSpec
- name: Prepare for parallel testing
env:
RAILS_ENV: test
TEST_DATABASE_URL: ${{ steps.setup-postgres-graphql-direct-link-precedence-different-content-id.outputs.db-url }}
run: bundle exec rake db:parallel:create db:parallel:prepare

- name: Run RSpec in parallel
env:
RAILS_ENV: test
TEST_DATABASE_URL: ${{ steps.setup-postgres-graphql-direct-link-precedence-different-content-id.outputs.db-url }}
run: bundle exec rspec spec/integration/graphql/link_expansion/direct_link_precedence_with_different_content_ids_spec.rb
run: bundle exec prspec spec/integration/graphql/link_expansion/direct_link_precedence_with_different_content_ids_spec.rb

test-graphql-reverse-link-precedence-same-content-id:
name: "Test GraphQL reverse link expansion precedence with same content ID"
Expand All @@ -159,6 +175,8 @@ jobs:
- name: Setup Postgres
id: setup-postgres-graphql-reverse-link-precedence-same-content-id
uses: alphagov/govuk-infrastructure/.github/actions/setup-postgres@main
with:
POSTGRES_DB: postgres-graphql-link-precedence

- name: Setup Redis
uses: alphagov/govuk-infrastructure/.github/actions/setup-redis@main
Expand All @@ -177,11 +195,17 @@ jobs:
TEST_DATABASE_URL: ${{ steps.setup-postgres-graphql-reverse-link-precedence-same-content-id.outputs.db-url }}
run: bundle exec rails db:setup

- name: Run RSpec
- name: Prepare for parallel testing
env:
RAILS_ENV: test
TEST_DATABASE_URL: ${{ steps.setup-postgres-graphql-reverse-link-precedence-same-content-id.outputs.db-url }}
run: bundle exec rake db:parallel:create db:parallel:prepare

- name: Run RSpec in parallel
env:
RAILS_ENV: test
TEST_DATABASE_URL: ${{ steps.setup-postgres-graphql-reverse-link-precedence-same-content-id.outputs.db-url }}
run: bundle exec rspec spec/integration/graphql/link_expansion/reverse_link_precedence_with_same_content_ids_spec.rb
run: bundle exec prspec spec/integration/graphql/link_expansion/reverse_link_precedence_with_same_content_ids_spec.rb

test-graphql-reverse-link-precedence-different-content-id:
name: "Test GraphQL reverse link expansion precedence with different content IDs"
Expand All @@ -190,6 +214,8 @@ jobs:
- name: Setup Postgres
id: setup-postgres-graphql-reverse-link-precedence-different-content-id
uses: alphagov/govuk-infrastructure/.github/actions/setup-postgres@main
with:
POSTGRES_DB: postgres-graphql-link-precedence

- name: Setup Redis
uses: alphagov/govuk-infrastructure/.github/actions/setup-redis@main
Expand All @@ -208,11 +234,17 @@ jobs:
TEST_DATABASE_URL: ${{ steps.setup-postgres-graphql-reverse-link-precedence-different-content-id.outputs.db-url }}
run: bundle exec rails db:setup

- name: Run RSpec
- name: Prepare for parallel testing
env:
RAILS_ENV: test
TEST_DATABASE_URL: ${{ steps.setup-postgres-graphql-reverse-link-precedence-different-content-id.outputs.db-url }}
run: bundle exec rake db:parallel:create db:parallel:prepare

- name: Run RSpec in parallel
env:
RAILS_ENV: test
TEST_DATABASE_URL: ${{ steps.setup-postgres-graphql-reverse-link-precedence-different-content-id.outputs.db-url }}
run: bundle exec rspec spec/integration/graphql/link_expansion/reverse_link_precedence_with_different_content_ids_spec.rb
run: bundle exec prspec spec/integration/graphql/link_expansion/reverse_link_precedence_with_different_content_ids_spec.rb

check-schemas-build:
name: Check content schemas are built
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ group :development, :test do
gem "govuk_test"
gem "pact", require: false
gem "pact_broker-client", require: false
gem "parallel_rspec"
gem "rspec-rails"
gem "rubocop-govuk", require: false
gem "simplecov", require: false
Expand Down
4 changes: 4 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,9 @@ GEM
term-ansicolor (~> 1.7)
thor (>= 0.20, < 2.0)
parallel (1.27.0)
parallel_rspec (3.0.0)
rake (> 10.0)
rspec
parser (3.3.10.1)
ast (~> 2.4.1)
racc
Expand Down Expand Up @@ -935,6 +938,7 @@ DEPENDENCIES
oj
pact
pact_broker-client
parallel_rspec
pg
plek
prometheus-client
Expand Down
43 changes: 42 additions & 1 deletion app/controllers/graphql_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,52 @@ class GraphqlController < ApplicationController
DEFAULT_TTL = ENV.fetch("DEFAULT_TTL", 5.minutes).to_i.seconds
MINIMUM_TTL = [DEFAULT_TTL, 5.seconds].min

def draft_content
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the argument in the commit message for having the duplication here, but I do wonder if there's potential for deviation from each other in the future?

Given there's only (as far as I can see) two lines difference between live and draft, would DRY-ing up these methods (with some conditional logic for the two lines that are different) be a better approach?

execute_in_read_replica do
begin
encoded_base_path = Addressable::URI.encode("/#{params[:base_path]}")
edition = EditionFinderService.new(encoded_base_path, with_drafts: true).find
set_cache_headers(edition)
return head :not_found unless edition

if edition.base_path != encoded_base_path
return redirect_to graphql_draft_content_path(base_path: edition.base_path.gsub(/^\//, "")), status: :see_other
end

begin
query = File.read(Rails.root.join("app/graphql/queries/#{edition.schema_name}.graphql"))
rescue Errno::ENOENT
return head :not_found
end

result = PublishingApiSchema.execute(query, variables: { base_path: encoded_base_path, with_drafts: true }).to_hash
report_result(result)

content_item = GraphqlContentItemService.for_edition(edition).process(result)

http_status = if content_item["schema_name"] == "gone" && (content_item["details"].nil? || content_item["details"].values.reject(&:blank?).empty?)
410
else
200
end

render json: content_item, status: http_status
end
rescue Addressable::URI::InvalidURIError
Rails.logger.warn "Can't encode request_path '#{params[:base_path]}'"
return head :bad_request
rescue StandardError => e
raise e unless Rails.env.development?

handle_error_in_development(e)
end
end

def live_content
execute_in_read_replica do
begin
encoded_base_path = Addressable::URI.encode("/#{params[:base_path]}")
edition = EditionFinderService.new(encoded_base_path, "live").find
edition = EditionFinderService.new(encoded_base_path).find
set_cache_headers(edition)
return head :not_found unless edition

Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/answer.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query answer($base_path: String!) {
edition(base_path: $base_path) {
query answer($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/calendar.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query calendar($base_path: String!) {
edition(base_path: $base_path) {
query calendar($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/call_for_evidence.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query call_for_evidence($base_path: String!) {
edition(base_path: $base_path) {
query call_for_evidence($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/case_study.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query case_study($base_path: String!) {
edition(base_path: $base_path) {
query case_study($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/completed_transaction.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query completed_transaction($base_path: String!) {
edition(base_path: $base_path) {
query completed_transaction($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/consultation.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query consultation($base_path: String!) {
edition(base_path: $base_path) {
query consultation($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/coronavirus_landing_page.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query coronavirus_landing_page($base_path: String!) {
edition(base_path: $base_path) {
query coronavirus_landing_page($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/corporate_information_page.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query corporate_information_page($base_path: String!) {
edition(base_path: $base_path) {
query corporate_information_page($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/detailed_guide.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query detailed_guide($base_path: String!) {
edition(base_path: $base_path) {
query detailed_guide($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/document_collection.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query document_collection($base_path: String!) {
edition(base_path: $base_path) {
query document_collection($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/email_alert_signup.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query email_alert_signup($base_path: String!) {
edition(base_path: $base_path) {
query email_alert_signup($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/embassies_index.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query embassies_index($base_path: String!) {
edition(base_path: $base_path) {
query embassies_index($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/fatality_notice.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query fatality_notice($base_path: String!) {
edition(base_path: $base_path) {
query fatality_notice($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/field_of_operation.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query field_of_operation($base_path: String!) {
edition(base_path: $base_path) {
query field_of_operation($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/fields_of_operation.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query fields_of_operation($base_path: String!) {
edition(base_path: $base_path) {
query fields_of_operation($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/finder.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query finder($base_path: String!) {
edition(base_path: $base_path) {
query finder($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/finder_email_signup.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query finder_email_signup($base_path: String!) {
edition(base_path: $base_path) {
query finder_email_signup($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
4 changes: 2 additions & 2 deletions app/graphql/queries/generic.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ fragment defaultFields on Edition {
web_url
}

query generic($base_path: String!) {
edition(base_path: $base_path) {
query generic($base_path: String!, $with_drafts: Boolean) {
edition(base_path: $base_path, with_drafts: $with_drafts) {
... on Edition {
analytics_identifier
base_path
Expand Down
Loading
Loading