Skip to content

Commit 7a7c503

Browse files
committed
merged devlopement into enh/dx-7330
2 parents 02a6aa3 + 89d32f9 commit 7a7c503

22 files changed

Lines changed: 651 additions & 113 deletions

.github/workflows/issues-jira.yml

Lines changed: 0 additions & 31 deletions
This file was deleted.

.github/workflows/release-gem.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ jobs:
1414

1515
steps:
1616
- uses: actions/checkout@v3
17-
- name: Set up Ruby 2.7
17+
- name: Set up Ruby
1818
uses: ruby/setup-ruby@v1
1919
with:
20-
ruby-version: '2.7'
20+
ruby-version: '3.3'
2121

2222
- name: Publish to RubyGems
2323
run: |

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ test
44
doc
55
spec-integration
66
coverage
7+
spec/.env.test
78
\.yardoc
89
.DS_Store
910
.bundle/
1011
**/rspec_results.html
1112
vendor/
12-
.dccache
13+
.dccache
14+
lib/data/regions.json

CHANGELOG.md

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,43 @@
11
## CHANGELOG
22

3-
## Version 0.9.0
4-
### Date: 19th-May-2026
3+
## Version 0.10.0
4+
### Date: 27th-July-2026
55
### Features
66
- Added `variants(variant_uids, branch_name)` on `Contentstack::Entry` and `Contentstack::Query` to fetch entry variants with optional per-request branch scoping. Requests send the `x-cs-variant-uid` header (comma-separated UIDs) and respect stack-level or per-call branch.
77

8+
------------------------------------------------
9+
10+
## Version 0.9.2
11+
### Date: 6th-July-2026
12+
### Fix
13+
- - Snyk fixes `json >= 2.19.9`.
14+
15+
------------------------------------------------
16+
17+
## Version 0.9.1
18+
### Date: 29th-June-2026
19+
### Fix
20+
- Snyk fixes
21+
22+
------------------------------------------------
23+
24+
## Version 0.9.0
25+
### Date: 15th-June-2026
26+
### Enhancement
27+
- Introduced centralized endpoint resolution via `Contentstack::Endpoint.get_contentstack_endpoint(region, service)`, eliminating all hardcoded Contentstack hostnames from the SDK.
28+
- Added `Contentstack.get_contentstack_endpoint` as a backward-compatible module-level proxy, aligned with the `ContentstackUtils` endpoint resolution API.
29+
- Added `Contentstack::Service` class with `CDA`, `CMA`, and `PREVIEW` constants.
30+
- Added `Contentstack::Region::GCP_EU` region constant.
31+
- Endpoint URLs are driven by a local `lib/data/regions.json` file with automatic runtime fallback to the Contentstack registry when the file is absent.
32+
- Added `bundle exec rake refresh_regions` task to manually update region metadata from the registry.
33+
34+
------------------------------------------------
35+
36+
## Version 0.8.5
37+
### Date: 5th-June-2026
38+
### Deprecated
39+
- `Query#include_draft` is deprecated. The Content Delivery API returns published content only; the `include_draft` query parameter has no effect. Use Live Preview with the Preview Service to preview unpublished entries, or the Content Management API to work with draft content.
40+
841
## Version 0.8.4
942
### Date: 15th-April-2026
1043
### Security and Compatibility

Gemfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ source "https://rubygems.org"
44
# Transitive via contentstack_utils; pin until upstream requires >= 1.19.1 (SNYK-RUBY-NOKOGIRI-15315717).
55
gem "nokogiri", ">= 1.19.1"
66

7+
# Transitive via activesupport; pin until upstream requires >= 2.19.9 (SNYK-RUBY-JSON-17739957).
8+
gem "json", ">= 2.19.9"
9+
710
# Ruby 4.0.x on recent macOS often segfaults in OpenSSL during `bundle` (not fixable in-app). Use Ruby 3.3+ (see .ruby-version).
811

912
gemspec

Gemfile.lock

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
contentstack (0.8.5)
4+
contentstack (0.10.0)
55
activesupport (>= 3.2)
66
contentstack_utils (~> 1.2)
77

@@ -25,7 +25,7 @@ GEM
2525
public_suffix (>= 2.0.2, < 8.0)
2626
base64 (0.3.0)
2727
bigdecimal (4.1.2)
28-
concurrent-ruby (1.3.6)
28+
concurrent-ruby (1.3.7)
2929
connection_pool (3.0.2)
3030
contentstack_utils (1.2.3)
3131
activesupport (>= 8.0)
@@ -39,13 +39,27 @@ GEM
3939
hashdiff (1.2.1)
4040
i18n (1.14.8)
4141
concurrent-ruby (~> 1.0)
42-
json (2.19.5)
42+
json (2.20.0)
4343
logger (1.7.0)
4444
minitest (6.0.6)
4545
drb (~> 2.0)
4646
prism (~> 1.5)
47+
nokogiri (1.19.3-aarch64-linux-gnu)
48+
racc (~> 1.4)
49+
nokogiri (1.19.3-aarch64-linux-musl)
50+
racc (~> 1.4)
51+
nokogiri (1.19.3-arm-linux-gnu)
52+
racc (~> 1.4)
53+
nokogiri (1.19.3-arm-linux-musl)
54+
racc (~> 1.4)
4755
nokogiri (1.19.3-arm64-darwin)
4856
racc (~> 1.4)
57+
nokogiri (1.19.3-x86_64-darwin)
58+
racc (~> 1.4)
59+
nokogiri (1.19.3-x86_64-linux-gnu)
60+
racc (~> 1.4)
61+
nokogiri (1.19.3-x86_64-linux-musl)
62+
racc (~> 1.4)
4963
prism (1.9.0)
5064
public_suffix (7.0.5)
5165
racc (1.8.1)
@@ -77,20 +91,70 @@ GEM
7791
addressable (>= 2.8.0)
7892
crack (>= 0.3.2)
7993
hashdiff (>= 0.4.0, < 2.0.0)
80-
yard (0.9.43)
94+
yard (0.9.44)
8195

8296
PLATFORMS
83-
arm64-darwin-22
84-
arm64-darwin-24
85-
arm64-darwin-25
97+
aarch64-linux-gnu
98+
aarch64-linux-musl
99+
arm-linux-gnu
100+
arm-linux-musl
101+
arm64-darwin
102+
x86_64-darwin
103+
x86_64-linux-gnu
104+
x86_64-linux-musl
86105

87106
DEPENDENCIES
88107
contentstack!
108+
json (>= 2.19.9)
89109
nokogiri (>= 1.19.1)
90110
rspec (~> 3.13.0)
91111
simplecov (~> 0.22.0)
92112
webmock (~> 3.26.0)
93113
yard (~> 0.9.38)
94114

115+
CHECKSUMS
116+
activesupport (8.1.3) sha256=21a5e0dfbd4c3ddd9e1317ec6a4d782fa226e7867dc70b0743acda81a1dca20e
117+
addressable (2.9.0) sha256=7fdf6ac3660f7f4e867a0838be3f6cf722ace541dd97767fa42bc6cfa980c7af
118+
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
119+
bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd
120+
concurrent-ruby (1.3.7) sha256=4412caec3a5ea2e5fdc52076724c071a81f2c0593d83b2ac8cbb8ca63b3151b0
121+
connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
122+
contentstack (0.9.2)
123+
contentstack_utils (1.2.3) sha256=cf2f5f996eb487559fd2d7d48a99262710f53dec62c84c6e325b9a598cd31ba7
124+
crack (1.0.1) sha256=ff4a10390cd31d66440b7524eb1841874db86201d5b70032028553130b6d4c7e
125+
diff-lcs (1.6.2) sha256=9ae0d2cba7d4df3075fe8cd8602a8604993efc0dfa934cff568969efb1909962
126+
docile (1.4.1) sha256=96159be799bfa73cdb721b840e9802126e4e03dfc26863db73647204c727f21e
127+
drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373
128+
hashdiff (1.2.1) sha256=9c079dbc513dfc8833ab59c0c2d8f230fa28499cc5efb4b8dd276cf931457cd1
129+
i18n (1.14.8) sha256=285778639134865c5e0f6269e0b818256017e8cde89993fdfcbfb64d088824a5
130+
json (2.20.0) sha256=9362bc6e55a952b056abf9167cf053358181c904cb70cd6eee0808ea830fc32b
131+
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
132+
minitest (6.0.6) sha256=153ea36d1d987a62942382b61075745042a2b3123b1cd48f4c3675af9cc7d6f1
133+
nokogiri (1.19.3-aarch64-linux-gnu) sha256=46b89e5d7b9e844c2ee360794240c6ea2a4e6fa0c5892a4ed487db621224b639
134+
nokogiri (1.19.3-aarch64-linux-musl) sha256=8392dfdcd21be7a94dbbe9ccc138dea01b97b24cb2dc02a114ca98bfb1d9a0b7
135+
nokogiri (1.19.3-arm-linux-gnu) sha256=3919d5ffc334ad778a4a9eb88fda7dcb8b1fb58c8a52ac640c6dcd2f038e774f
136+
nokogiri (1.19.3-arm-linux-musl) sha256=9ce1cb6346bb9c67b1550eb537aa183ead91e4b6eadb2f36ade02d8dd2a79fb6
137+
nokogiri (1.19.3-arm64-darwin) sha256=71b9bd424b1b7abc18b05052a1a3cfd3627abdca62be280854cc411791357e42
138+
nokogiri (1.19.3-x86_64-darwin) sha256=77f3fba57d46c53ab31e62fc6c28f705109d1bf6264356c76f132b2be5728d4d
139+
nokogiri (1.19.3-x86_64-linux-gnu) sha256=2f5078620fe12e83669b5b17311b32532a8153d02eee7ad06948b926d6080976
140+
nokogiri (1.19.3-x86_64-linux-musl) sha256=248c906d2166eca5efb56d52fdee5f9a1f51d69a72e2b64fdac647b4ce39ea3f
141+
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
142+
public_suffix (7.0.5) sha256=1a8bb08f1bbea19228d3bed6e5ed908d1cb4f7c2726d18bd9cadf60bc676f623
143+
racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
144+
rexml (3.4.4) sha256=19e0a2c3425dfbf2d4fc1189747bdb2f849b6c5e74180401b15734bc97b5d142
145+
rspec (3.13.2) sha256=206284a08ad798e61f86d7ca3e376718d52c0bc944626b2349266f239f820587
146+
rspec-core (3.13.6) sha256=a8823c6411667b60a8bca135364351dda34cd55e44ff94c4be4633b37d828b2d
147+
rspec-expectations (3.13.5) sha256=33a4d3a1d95060aea4c94e9f237030a8f9eae5615e9bd85718fe3a09e4b58836
148+
rspec-mocks (3.13.8) sha256=086ad3d3d17533f4237643de0b5c42f04b66348c28bf6b9c2d3f4a3b01af1d47
149+
rspec-support (3.13.7) sha256=0640e5570872aafefd79867901deeeeb40b0c9875a36b983d85f54fb7381c47c
150+
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
151+
simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5
152+
simplecov-html (0.13.2) sha256=bd0b8e54e7c2d7685927e8d6286466359b6f16b18cb0df47b508e8d73c777246
153+
simplecov_json_formatter (0.1.4) sha256=529418fbe8de1713ac2b2d612aa3daa56d316975d307244399fa4838c601b428
154+
tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
155+
uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
156+
webmock (3.26.2) sha256=774556f2ea6371846cca68c01769b2eac0d134492d21f6d0ab5dd643965a4c90
157+
yard (0.9.44) sha256=eb087e9b631ccd887b049f303d489963945452d5e2a7eb49a5a74a7cf6887f28
158+
95159
BUNDLED WITH
96-
2.3.13
160+
2.6.3

contentstack.gemspec

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ Gem::Specification.new do |s|
1818
s.summary = %q{Contentstack Ruby client for the Content Delivery API}
1919
s.description = %q{Contentstack Ruby client for the Content Delivery API}
2020

21-
s.files = `git ls-files`.split("\n")
21+
s.files = `git ls-files`.split("\n") +
22+
Dir['ext/**/*'].select { |f| File.file?(f) }
23+
s.extensions = ['ext/download_regions/extconf.rb']
2224
s.require_paths = ["lib"]
2325

2426
s.add_dependency 'activesupport', '>= 3.2'

ext/download_regions/extconf.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
require 'net/http'
2+
require 'uri'
3+
require 'json'
4+
require 'fileutils'
5+
6+
REGISTRY_URL = 'https://artifacts.contentstack.com/regions.json'
7+
8+
gem_root = File.expand_path('../..', __dir__)
9+
data_dir = File.join(gem_root, 'lib', 'data')
10+
dest_file = File.join(data_dir, 'regions.json')
11+
12+
FileUtils.mkdir_p(data_dir)
13+
14+
begin
15+
uri = URI.parse(REGISTRY_URL)
16+
response = Net::HTTP.get_response(uri)
17+
if response.is_a?(Net::HTTPSuccess)
18+
File.write(dest_file, JSON.pretty_generate(JSON.parse(response.body)))
19+
$stdout.puts "[Contentstack] regions.json downloaded successfully."
20+
else
21+
$stdout.puts "[Contentstack] Warning: Could not download regions.json (HTTP #{response.code}). Runtime fallback will be used."
22+
end
23+
rescue => e
24+
$stdout.puts "[Contentstack] Warning: Could not download regions.json — #{e.message}. Runtime fallback will be used."
25+
end
26+
27+
# RubyGems requires a Makefile to exist after extconf.rb runs.
28+
# We create a no-op one since this extension has no C code to compile.
29+
File.write('Makefile', "all:\n\ninstall:\n\nclean:\n\n")

lib/contentstack.rb

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require "contentstack/version"
44
require "contentstack/client"
55
require "contentstack/region"
6+
require "contentstack/endpoint"
67
require "contentstack_utils"
78

89
# == Contentstack - Ruby SDK
@@ -23,10 +24,24 @@
2324
# ==== Query entries
2425
# @stack.content_type('blog').query.regex('title', '.*hello.*').fetch
2526
module Contentstack
26-
def self.render_content(content, options)
27-
ContentstackUtils.render_content(content, options)
28-
end
29-
def self.json_to_html(content, options)
30-
ContentstackUtils.json_to_html(content, options)
31-
end
27+
def self.render_content(content, options)
28+
ContentstackUtils.render_content(content, options)
29+
end
30+
31+
def self.json_to_html(content, options)
32+
ContentstackUtils.json_to_html(content, options)
33+
end
34+
35+
# Backward-compatible proxy for endpoint resolution.
36+
# Delegates to ContentstackUtils.get_contentstack_endpoint when available,
37+
# otherwise resolves via Contentstack::Endpoint.
38+
#
39+
# Contentstack.get_contentstack_endpoint('eu')
40+
# # => "https://eu-cdn.contentstack.com"
41+
#
42+
# Contentstack.get_contentstack_endpoint('us', 'cma')
43+
# # => "https://api.contentstack.io"
44+
def self.get_contentstack_endpoint(region, service = Contentstack::Service::CDA)
45+
Contentstack::Endpoint.get_contentstack_endpoint(region, service)
46+
end
3247
end

lib/contentstack/client.rb

Lines changed: 7 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
require 'contentstack/content_type'
33
require 'contentstack/asset_collection'
44
require 'contentstack/sync_result'
5+
require 'contentstack/endpoint'
56
require 'util'
67
require 'contentstack/error'
78
module Contentstack
@@ -80,47 +81,14 @@ def sync(params)
8081
end
8182

8283
private
83-
def get_default_region_hosts(region='us')
84-
host = "#{Contentstack::Host::PROTOCOL}#{Contentstack::Host::DEFAULT_HOST}" #set default host if region is nil
85-
case region
86-
when "us"
87-
host = "#{Contentstack::Host::PROTOCOL}#{Contentstack::Host::DEFAULT_HOST}"
88-
when "eu"
89-
host = "#{Contentstack::Host::PROTOCOL}eu-cdn.#{Contentstack::Host::HOST}"
90-
when "azure-na"
91-
host = "#{Contentstack::Host::PROTOCOL}azure-na-cdn.#{Contentstack::Host::HOST}"
92-
when "azure-eu"
93-
host = "#{Contentstack::Host::PROTOCOL}azure-eu-cdn.#{Contentstack::Host::HOST}"
94-
when "gcp-na"
95-
host = "#{Contentstack::Host::PROTOCOL}gcp-na-cdn.#{Contentstack::Host::HOST}"
96-
end
97-
host
98-
end
9984

10085
def get_host_by_region(region, options)
101-
if options[:host].nil? && region.present?
102-
host = get_default_region_hosts(region)
103-
elsif options[:host].present? && region.present?
104-
custom_host = options[:host]
105-
case region
106-
when "us"
107-
host = "#{Contentstack::Host::PROTOCOL}cdn.#{custom_host}"
108-
when "eu"
109-
host = "#{Contentstack::Host::PROTOCOL}eu-cdn.#{custom_host}"
110-
when "azure-na"
111-
host = "#{Contentstack::Host::PROTOCOL}azure-na-cdn.#{custom_host}"
112-
when "azure-eu"
113-
host = "#{Contentstack::Host::PROTOCOL}azure-eu-cdn.#{custom_host}"
114-
when "gcp-na"
115-
host = "#{Contentstack::Host::PROTOCOL}gcp-na-cdn.#{custom_host}"
116-
end
117-
elsif options[:host].present? && region.empty?
118-
custom_host = options[:host]
119-
host = "#{Contentstack::Host::PROTOCOL}cdn.#{custom_host}"
120-
else
121-
host = "#{Contentstack::Host::PROTOCOL}#{Contentstack::Host::DEFAULT_HOST}" #set default host if region and host is empty
122-
end
123-
host
86+
custom_host = options[:host]
87+
Contentstack::Endpoint.get_contentstack_endpoint(
88+
region.present? ? region : Contentstack::Region::US,
89+
Contentstack::Service::CDA,
90+
custom_host.present? ? custom_host : nil
91+
)
12492
end
12593

12694
end

0 commit comments

Comments
 (0)